diff --git a/## Changes.md b/## Changes.md new file mode 100644 index 000000000..b6e11f765 --- /dev/null +++ b/## Changes.md @@ -0,0 +1,138 @@ +## Additions + +- Netherite Backtank +- Netherite Diving Helmet and Boots +- Contraption Controls +- Elevator Pulley +- Copycat Panels and Copycat Steps +- Block of Andesite Alloy +- Block of Industrial Iron +- Large Water Wheel +- Mechanical Roller +- Andesite, Brass and Copper Doors +- Andesite, Brass and Copper Bars +- Andesite, Brass and Copper Scaffolding +- Clipboard +- Mangrove Windows (1.19) + +## Changes + +- Overhauled models and textures of Andesite & Brass components (Kryppers) +- Reworked textures of colored blocks such as seats and sails (dani) +- New filter sprites (vectorwing) +- Valve handles can now be used to precisely turn mechanical bearings by a set angle +- Pulley ropes are now climbable +- Lowered hitbox of seats for improved traversability inside contraptions +- Improved safety for players standing on vertically moving contraptions +- Pulley contraptions will now make an effort to place remote players at y values sensible to the client +- Fixed seated entities on rotating contraptions not rendering at the correct location +- Deployers no longer fail to activate in chunks claimed or protected by the player that placed them +- Fixed couplings, schematics and in-world overlays not rendering correctly at coordinates far from the origin +- Fixed Bearings, Pistons, Pulleys and Gantries powered by a Sequenced Gearshift not moving precisely to its instructions at high speeds +- Minecart contraptions no longer visually jump to a location when stalled +- Mechanical bearings now snap to a rounded angle when stopped +- Contraption storage now accepts more chests and barrels from other mods +- Players can now open chests and barrels on assembled contraptions +- Mechanical Pumps no longer reverse direction based on kinetic input +- Fixed pipe connections pulling fluids with half the speed compared to a directly attached pump +- Substantially increased speed of visual flow propagation inside pipe networks +- Portable storage interfaces now stall for longer after an exchange has happened, and shorter otherwise +- Single train track blocks with slopes connected on either side will angle themselves to create a smoother ascend across both +- Multiple pulleys can now attach to contraptions in a synchronised group +- Display Boards now update text instantaneously at high input rpm +- Diving helmets now always grant aqua affinity +- Diving helmets can no longer be enchanted with aqua affinity +- Water wheel fins are no longer directional +- Water wheels now only have one speed level +- Water wheels can now take the appearance of any reasonably implemented wood type +- Added sided door control options to elevator contact and train station UI +- Liquid can no longer spread perpendicularly on top of water wheels +- Overhauled UX of scroll values and item filtering +- Filtered item extraction can now be configured to pull "up to x items" per operation +- Connected textures now use and apply the getAppearance() standard by Forge, allowing them to connect across other mods' facades, etc. (1.19) +- Boiler status now highlights information about water flow when insufficient +- The majority of in-world options no longer require a wrench +- Chutes can now be encased in Industrial Iron Blocks +- Chutes are now less prone to resetting shape when moved or rotated +- Moved metal block variants to Building Blocks tab +- Changed stonecutting ingredient of metal block variants from sheet to ingot +- Base stone blocks can now be stonecut back from their cut variants +- Fixed track placement allowing an s-bend between two sloped track pieces in specific arrangements +- Fixed funnels losing filters when changing between types +- New randomised textures for natural palette stone types (Kryppers) +- Readjusted palette stone generation to use taller layers +- World generation now places fewer stone type veins by default +- Fixed lava fans voiding items that have smoking & smelting recipes with different outputs +- Filter items now filter for their own item type if left empty +- Valve handles no longer create stress config entries for each dyed variant +- Place near initial angle mode on bearings now has a smaller interval considered 'near' +- Players can now take items from saws via right-click +- Item Drains now accept dropped items as input +- Train track placement overlay now explicitly mentions the ctrl key +- Fixed Mechanical Saws not rendering as animated when using rubidium +- Fixed a ui element of the Station Screen rendering behind the background +- Belts printed instantly or via cannon now retain the correct type of casing +- Scheduled trains no longer slow down for slight ascends/descents on a straight track +- Fixed saplings and other non-collidables sticking to chassis or super glue +- Encased Fluid Pipes no longer z-fight on open pipe faces +- Valve handles now turn twice as quickly +- Bearings no longer have the angle-indicating nook on their block +- Depot hitbox is now a simple cuboid +- Fixed belts encased with andesite briefly showing brass textures +- Fixed Filters and Attribute Filters not stacking with unmodified, equivalent stacks +- Fixed Attribute Filters saving the name tag preview item in their data +- Filters and Schedules can now be reset via crafting +- Renamed Sails to Windmill Sails +- Crushing gold ore now yields more experience nuggets +- Fixed valve pipes sometimes not rotating their indicator fully +- Horizontal, encased belts now render a support structure when solid blocks are above them +- Added placement assist for mechanical drills, saws and deployers +- Mechanical Belts can now be waterlogged +- Depots and Ejectors can now be Waterlogged +- Chutes and Funnels can now be Waterlogged +- Fixed upright mechanical saws only able to be oriented in two directions +- Deployers now have their filter slot on the side of the block +- Deployers can now be rotated by wrenching them near the edge of the front face +- Deployers now set filters on blocks only by targeting any location on a correct side +- Fixed Schematics loaded for deployer printing not rotating block entity contents +- Added tripwire to #movable_empty_collider +- Renamed Stockpile Switch to Threshold Switch +- Renamed Content Observer to Smart Observer +- Smart observer and threshold switch can now be oriented to face blocks above or below them +- Smart observer will now also emit redstone when the block in front of it matches its filter +- Fixed non-vanilla signs not accepted as valid display targets +- Brass tunnels with no distribution behaviour no longer show the mode switcher +- Used more contrasting colours for diode and tunnel value inputs +- Fixed crash when hose pulley cannot find reference fluid for infinite draining +- Clipboards can now be used to transfer settings between blocks +- Clipboards can now be used to manually write to Display Boards and Nixie Tubes +- Clipboards can now be used as Material Checklists in the Schematicannon +- Fixed and edited existing tooltips and ponder scenes to include behavioural changes in 0.5.1 +- New ponder scenes for Smart Observer, Threshold Switch, Elevator Pulley, Contraption Controls and Mechanical Rollers +- Fixed ponder overlay text rendering with wonky pixels +- Added a ponder category for recently added/changed blocks +- Renamed Filter to List Filter +- Deployers can now apply filters to a Redstone link with less required precision +- Bezier track segments now render with a slight angle to reduce z-fighting +- Fixed offset shaft rotation on encased large cogwheels +- Fixed Smart Fluid Pipe not dropping filter when broken +- Placards and Creative Crates will no longer hold on to special nbt content (except potion data, damage, enchants) of the contained item when imported via Schematicannon +- Schematicannons can no longer print mobs +- Fixed item frames not requiring an exact nbt match for printed contents +- Players can now sneak while using exp nuggets to only consume one item at a time +- Minecart contraption items can no longer be placed in container items like toolboxes or shulkers (configurable) +- Implemented ComputerCraft interaction for Speed Controllers, Display Links, Speedometers, Stressometers, Sequenced Gearshifts and Train Stations (caelwarner) +- Hand crank no longer drains hunger when using the extendo grip (Xstoudi) +- Fixed Encased Chain Drives not reacting to block rotation and mirroring correctly +- Open Ended Pipes now correctly handle Builder's Tea (NerdsOfAFeather) +- Added Config entry for brass tunnel distribution cooldown (Walle123) +- API for custom bogey & track types (Rabbitminers, techno-sam) +- Fixed server crash caused by Gantry Contraptions assembling (Lucasmellof) +- Fix "Lighter than air" fluids displayed incorrectly in spouts (cakeGit) +- Added rotate and mirror methods to Fluid Pipes (xieve) +- Chocolate & Honey fluid fog distance is now configurable (radimous) +- Added a TrackGraph merge event (DaComputerNerd717) +- Fixed players dismounting when trains get assembled (Equinoxxe) +- Added GameTests (TropheusJ) +- Added armor tags (NerdsOfAFeather) +- Major updates now release as patch A \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index efbe37479..32975f259 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -1,6 +1,6 @@ name: Bug Report description: Create a bug report to help us improve Create -labels: [ "bug" ] +labels: [ "type: bug" ] body: - type: textarea attributes: @@ -49,7 +49,8 @@ body: label: Mod Version description: The version of the mod you were using when the bug occured options: - - "0.5.0j" + - "0.5.1b" + - "0.5.1a" - "0.5.0i" - "0.5.0h" - "0.5.0g" diff --git a/.github/ISSUE_TEMPLATE/suggestion.yml b/.github/ISSUE_TEMPLATE/suggestion.yml index 3a460558b..ff5acdb33 100644 --- a/.github/ISSUE_TEMPLATE/suggestion.yml +++ b/.github/ISSUE_TEMPLATE/suggestion.yml @@ -1,6 +1,6 @@ name: Suggestion description: Suggest something that would improve Create -labels: [ "suggestion" ] +labels: [ "type: suggestion" ] body: - type: textarea attributes: diff --git a/.github/config/labels.yml b/.github/config/labels.yml index 724dff12d..29e1fdc47 100644 --- a/.github/config/labels.yml +++ b/.github/config/labels.yml @@ -1,12 +1,12 @@ -1.14: +'version: 1.14': - '1\.14(?:\.\d)?' -1.15: +'version: 1.15': - '1\.15(?:\.\d)?' -1.16: +'version: 1.16': - '1\.16(?:\.\d)?' -1.17: +'version: 1.17': - '1\.17(?:\.\d)?' -1.18: +'version: 1.18': - '1\.18(?:\.\d)?' -1.19: +'version: 1.19': - '1\.19(?:\.\d)?' diff --git a/.github/workflows/gametest.yml b/.github/workflows/gametest.yml new file mode 100644 index 000000000..23bb055a9 --- /dev/null +++ b/.github/workflows/gametest.yml @@ -0,0 +1,23 @@ +name: gametest +on: [ workflow_dispatch ] + +jobs: + build: + runs-on: ubuntu-latest + steps: + + - name: checkout repository + uses: actions/checkout@v3 + + - name: setup Java + uses: actions/setup-java@v3 + with: + distribution: temurin + java-version: 17 + cache: gradle + + - name: make gradle wrapper executable + run: chmod +x ./gradlew + + - name: run gametests + run: ./gradlew prepareRunGameTestServer runGameTestServer --no-daemon diff --git a/.gitignore b/.gitignore index 4afb35865..b9a3321f8 100644 --- a/.gitignore +++ b/.gitignore @@ -42,4 +42,5 @@ local.properties # PDT-specific .buildpath -.DS_Store \ No newline at end of file +.DS_Store +/libs/ diff --git a/build.gradle b/build.gradle index d6dafb7a6..9b00ea06e 100644 --- a/build.gradle +++ b/build.gradle @@ -90,44 +90,58 @@ minecraft { } } } + + gameTestServer { + workingDirectory project.file('run/gametest') + arg '-mixin.config=create.mixins.json' + property 'forge.logging.console.level', 'info' + mods { + create { + source sourceSets.main + } + } + setForceExit false + } } } repositories { maven { - // Location of the maven that hosts JEI files (and TiC) - name 'Progwml6 maven' - url 'https://dvs1.progwml6.com/files/maven' + // location of the maven for Registrate and Flywheel + name = 'tterrag maven' + url = 'https://maven.tterrag.com' + } + maven { + // location of the maven that hosts JEI files since January 2023 + // location of the maven for Vazkii's mods + name = "Jared's maven" + url = "https://maven.blamejared.com/" } /*maven { - // Location of a maven mirror for JEI files, as a fallback - name 'ModMaven' - url 'https://modmaven.k-4u.nl' + // location of a maven mirror for JEI files, as a fallback + name = "ModMaven" + url = "https://modmaven.dev" }*/ maven { - // Location of the maven for vazkii's mods - name 'blamejared' - url 'https://maven.blamejared.com' + // location of the maven for Dynamic Trees + url = 'https://harleyoconnor.com/maven' } maven { - // Location of the maven for mixed mappings, Registrate, and Flywheel - name 'tterrag maven' - url 'https://maven.tterrag.com' + // location of the maven for Curios API + url = "https://maven.theillusivec4.top/" } maven { - url 'https://www.cursemaven.com' + // location of maven for CC: Tweaked + name = "squiddev" + url = "https://squiddev.cc/maven/" + } + + maven { + url = 'https://www.cursemaven.com' content { includeGroup "curse.maven" } } - maven { - //location of the maven for dynamic trees - url 'https://harleyoconnor.com/maven' - } - maven { - //location of the maven for curios api - url = "https://maven.theillusivec4.top/" - } maven { name = "Modrinth" url = "https://api.modrinth.com/maven" @@ -135,6 +149,10 @@ repositories { includeGroup "maven.modrinth" } } + + flatDir { + dirs 'libs' + } } dependencies { @@ -162,6 +180,11 @@ dependencies { compileOnly fg.deobf("top.theillusivec4.curios:curios-forge:${curios_minecraft_version}-${curios_version}:api") runtimeOnly fg.deobf("top.theillusivec4.curios:curios-forge:${curios_minecraft_version}-${curios_version}") + if (cc_tweaked_enable.toBoolean()) { + compileOnly fg.deobf("cc.tweaked:cc-tweaked-${cc_tweaked_minecraft_version}-forge-api:${cc_tweaked_version}:cc-tweaked-${cc_tweaked_minecraft_version}-forge-api-${cc_tweaked_version}") + runtimeOnly fg.deobf("cc.tweaked:cc-tweaked-${cc_tweaked_minecraft_version}-forge:${cc_tweaked_version}:cc-tweaked-${cc_tweaked_minecraft_version}-forge-${cc_tweaked_version}") + } + // implementation fg.deobf("curse.maven:druidcraft-340991:3101903") // implementation fg.deobf("com.ferreusveritas.dynamictrees:DynamicTrees-1.16.5:0.10.0-Beta25") // runtimeOnly fg.deobf("vazkii.arl:AutoRegLib:1.4-35.69") @@ -169,6 +192,7 @@ dependencies { // runtimeOnly fg.deobf("slimeknights.mantle:Mantle:1.16.5-1.6.115") // runtimeOnly fg.deobf("slimeknights.tconstruct:TConstruct:1.16.5-3.1.1.252") // runtimeOnly fg.deobf("maven.modrinth:rubidium:0.5.3") + // implementation fg.deobf("com.railwayteam.railways:railways-1.18.2-1.1.1:all") { transitive = false } // https://discord.com/channels/313125603924639766/725850371834118214/910619168821354497 // Prevent Mixin annotation processor from getting into IntelliJ's annotation processor settings @@ -178,6 +202,12 @@ dependencies { } } +sourceSets.main.java { + if (!cc_tweaked_enable.toBoolean()) { + exclude 'com/simibubi/create/compat/computercraft/implementation/**' + } +} + sourceSets.main.resources { srcDir 'src/generated/resources' exclude '.cache/' diff --git a/crowdin.yml b/crowdin.yml index 39f243b83..7ebdc939f 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -13,12 +13,15 @@ "cs": "cs_cz", "da": "da_dk", "de": "de_de", + "eo": "eo_uy", "es-CL": "es_cl", "es-ES": "es_es", "es-MX": "es_mx", "fa": "fa_ir", + "fi": "fi_fi", "fr": "fr_fr", "hu": "hu_hu", + "id": "id_id", "is": "is_is", "it": "it_it", "ja": "ja_jp", @@ -30,6 +33,7 @@ "pt-BR": "pt_br", "pt-PT": "pt_pt", "ro": "ro_ro", + "rpr": "rpr", "ru": "ru_ru", "sv-SE": "sv_se", "th": "th_th", diff --git a/gradle.properties b/gradle.properties index e75505ee0..aac31591b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,14 +4,14 @@ org.gradle.jvmargs = -Xmx3G org.gradle.daemon = false # mod version info -mod_version = 0.5.0.j +mod_version = 0.5.1.b artifact_minecraft_version = 1.19.3 minecraft_version = 1.19.3 forge_version = 44.1.8 # build dependency versions -forgegradle_version = 5.1.53 +forgegradle_version = 5.1.74 mixingradle_version = 0.7-SNAPSHOT mixin_version = 0.8.5 librarian_version = 1.+ @@ -27,6 +27,10 @@ jei_version = 12.1.1.13 curios_minecraft_version = 1.19.3 curios_version = 5.1.2.0 +cc_tweaked_enable = false +cc_tweaked_minecraft_version = 1.19.3 +cc_tweaked_version = 1.103.1 + # curseforge information projectId = 328085 curse_type = beta diff --git a/src/generated/resources/.cache/12afe0d97856fb2040b8407470e6d13529994eaa b/src/generated/resources/.cache/12afe0d97856fb2040b8407470e6d13529994eaa index a1f924f3d..6d72ea410 100644 --- a/src/generated/resources/.cache/12afe0d97856fb2040b8407470e6d13529994eaa +++ b/src/generated/resources/.cache/12afe0d97856fb2040b8407470e6d13529994eaa @@ -1,4 +1,4 @@ -// 1.19.3 2023-02-06T18:08:23.2283539 Create's Sequenced Assembly Recipes -e6efd0d76dc451a44b663a453cef6e6656ad523f data/create/recipes/sequenced_assembly/precision_mechanism.json +// 1.19.3 2023-06-27T03:14:49.7447744 Create's Sequenced Assembly Recipes +dbaca5a5aa312f3bc7b826e51e665d32e798a5d7 data/create/recipes/sequenced_assembly/precision_mechanism.json 0cdbd4f583aa0a2aa8f3ca2827199bede1732722 data/create/recipes/sequenced_assembly/sturdy_sheet.json 1274315b5c570722d6f5b2ed7f5e53fe01b6288a data/create/recipes/sequenced_assembly/track.json diff --git a/src/generated/resources/.cache/1cb0872ba1a6c752326d93c76b4dff08eb2dcb71 b/src/generated/resources/.cache/1cb0872ba1a6c752326d93c76b4dff08eb2dcb71 index ae41034c9..e33e487cd 100644 --- a/src/generated/resources/.cache/1cb0872ba1a6c752326d93c76b4dff08eb2dcb71 +++ b/src/generated/resources/.cache/1cb0872ba1a6c752326d93c76b4dff08eb2dcb71 @@ -1,10 +1,10 @@ -// 1.19.3 2023-02-06T18:08:23.3300822 Create's Worldgen Data +// 1.19.3 2023-06-27T03:14:49.7872831 Create's Worldgen Data f650826db97d0562230ae0bd965ccbad4c696eff data/create/forge/biome_modifier/striated_ores_nether.json d401f270f1ba0e5d6940aeb8f72ebb3a02dd055e data/create/forge/biome_modifier/striated_ores_overworld.json ed82e4fd3dba36cf2fd81a196cc6670ae0c6da9f data/create/forge/biome_modifier/zinc_ore.json -e1614c8a64a300d8a02553e22812a7e4e157a8f2 data/create/worldgen/configured_feature/striated_ores_nether.json -642faaa439921e0ddb0d0f28d0af0f0fa52d27dd data/create/worldgen/configured_feature/striated_ores_overworld.json +ed83634a4af759ef80cfd1101f5715d38268620f data/create/worldgen/configured_feature/striated_ores_nether.json +39576de9dc1368287a96a8627bbdef34954242e0 data/create/worldgen/configured_feature/striated_ores_overworld.json fbf6999fb922a0770cfbea3a8bddc11ba8b1552b data/create/worldgen/configured_feature/zinc_ore.json -460db1f0c937bdd80be710de8df0a763ad5658a1 data/create/worldgen/placed_feature/striated_ores_nether.json -62ce384c45affdc6c3722d7cbbb862237fcac131 data/create/worldgen/placed_feature/striated_ores_overworld.json +176a1226e308874605a73ab7a627b8d0ef87f3ed data/create/worldgen/placed_feature/striated_ores_nether.json +451e7dab2b989b4c481c1d7c38ab9daab70474f5 data/create/worldgen/placed_feature/striated_ores_overworld.json b3f6cb5cfd9fd10d4841480632474800b34055ad data/create/worldgen/placed_feature/zinc_ore.json diff --git a/src/generated/resources/.cache/455c485c9c8ef171bbc1ce4d435b3110ba1557ba b/src/generated/resources/.cache/455c485c9c8ef171bbc1ce4d435b3110ba1557ba index e4247c16c..8b650516c 100644 --- a/src/generated/resources/.cache/455c485c9c8ef171bbc1ce4d435b3110ba1557ba +++ b/src/generated/resources/.cache/455c485c9c8ef171bbc1ce4d435b3110ba1557ba @@ -1,4 +1,4 @@ -// 1.19.3 2023-02-06T18:08:23.2183804 Create's Advancements +// 1.19.3 2023-06-27T03:14:49.7357976 Create's Advancements 2079ae09cf699108a8035ced7ca712fed4ab1577 data/create/advancements/andesite_alloy.json 082d3987c5e074ed50be4a94a6fdc17120af241b data/create/advancements/andesite_casing.json 4618109cfb4550fd8e19dc9d794ef24398b10a61 data/create/advancements/anvil_plough.json @@ -28,8 +28,8 @@ e564c7aa283e81d5aa4c043b6de97b7328aa877d data/create/advancements/crushing_wheel f175d1f816f32e1c50891321331e475863ce1e89 data/create/advancements/deployer.json 62ffffc6834c54ae1abca584522c577226f7f891 data/create/advancements/display_board_0.json 68749521feb4832c8da666454c70f883129f9335 data/create/advancements/display_link.json -02af5f59f671b59efb1419b67463326984a971fc data/create/advancements/diving_suit.json -df385d36b345e919cca92ba212818bc39032fd02 data/create/advancements/diving_suit_lava.json +dfa5e42ee372df8c810e1ccf8a6928e4f1299f37 data/create/advancements/diving_suit.json +836e914e3139f8cbf4cdd78ae53bd9bdd041a693 data/create/advancements/diving_suit_lava.json 2d19468ffed9345ebe8cecf220acc15651917082 data/create/advancements/drain.json 492d8ebc5d10e7efd100570f1507413d78723782 data/create/advancements/ejector_maxed.json 7e19fd15b675494d2a8d5ac3cef4a50cf58c203f data/create/advancements/encased_fan.json @@ -47,8 +47,7 @@ b68f4baee272682b6f4c9a34089837fec2cd9c58 data/create/advancements/funnel.json c365ee5c1175fa4bf4627d78c7bdce6ca7a2defb data/create/advancements/hose_pulley_lava.json c0f0689a4497affe0feb20bc20d708aa0d8eb90e data/create/advancements/lava_wheel_00000.json 2bef7aa7c863c9b149c67a506725ffa0fee3d977 data/create/advancements/linked_controller.json -29a4c44e4f89cbb0f4d694c6c28a0e2c03dc64f3 data/create/advancements/long_bend.json -74bc9d3d1df777980634861e0ea11b6343e3bbc5 data/create/advancements/long_train.json +8d842135a5111786c0c656dfcac6be9c1d1a459d data/create/advancements/long_train.json 333335c09683319ceaaa2974a9f746c0545bf425 data/create/advancements/long_travel.json 1025b22c5ff39a4d54bb5857e04e35a5d806ceba data/create/advancements/mechanical_arm.json 7703192ff1ccba4cc006bcfae349084756ae62d7 data/create/advancements/mechanical_crafter.json diff --git a/src/generated/resources/.cache/5f8aca9eaba9b8ce3917e7fa81ee22a77c9fb8ed b/src/generated/resources/.cache/5f8aca9eaba9b8ce3917e7fa81ee22a77c9fb8ed index 5dbdc1910..84aa2496b 100644 --- a/src/generated/resources/.cache/5f8aca9eaba9b8ce3917e7fa81ee22a77c9fb8ed +++ b/src/generated/resources/.cache/5f8aca9eaba9b8ce3917e7fa81ee22a77c9fb8ed @@ -1,21 +1,25 @@ -// 1.19.3 2023-02-06T18:13:06.6720228 Registrate Provider for create [Recipes, Advancements, Loot Tables, Tags (blocks), Tags (items), Tags (fluids), Tags (entity_types), Blockstates, Item models, Lang (en_us/en_ud), Create's lang merger] +// 1.19.3 2023-06-27T03:15:21.593699 Registrate Provider for create [Recipes, Advancements, Loot Tables, Tags (blocks), Tags (items), Tags (fluids), Tags (entity_types), Blockstates, Item models, Lang (en_us/en_ud), Create's lang merger] 60bbdf92d2ac9824ea6144955c74043a6005f79d assets/create/blockstates/acacia_window.json 6a67703c2697d81b7dc83e9d72a66f9c9ff08383 assets/create/blockstates/acacia_window_pane.json c3ae87b62e81d8e9476eccd793bb1548d74c66a1 assets/create/blockstates/adjustable_chain_gearshift.json 188fb038919138844cf018d5afeeddd8808c413b assets/create/blockstates/analog_lever.json -e316413e43e67314846a706ba36201b8c4658481 assets/create/blockstates/andesite_belt_funnel.json +6a95eb99f4acf53189f9f578eaa829652b726b2a assets/create/blockstates/andesite_alloy_block.json +96c0b7cf225d51e2df633786c1a8a0a6c61fe261 assets/create/blockstates/andesite_bars.json +db046170dcd57e5fcfe85b475790d6725a0ad8e3 assets/create/blockstates/andesite_belt_funnel.json 6cd5574ad64b212440ae07ab75b732e04ee3aab5 assets/create/blockstates/andesite_casing.json +aff6d09929301e72548f4ce5720af96426171580 assets/create/blockstates/andesite_door.json 84dacd6144568b97ae00a55525290b4f295a72e7 assets/create/blockstates/andesite_encased_cogwheel.json c9aa3f6acdcadfcd6f0c48457ddafcdd9ff37104 assets/create/blockstates/andesite_encased_large_cogwheel.json 4946d26000065d09b51752b6ad34d0050f829a0d assets/create/blockstates/andesite_encased_shaft.json -b42ab84c580d1ff955fb7eee26008003f9f277e1 assets/create/blockstates/andesite_funnel.json +7791ae0b7027e3bb83968c811c3a82f65226dd7c assets/create/blockstates/andesite_funnel.json 1299bde31535b381cc2d9b40f58097702bd12b92 assets/create/blockstates/andesite_ladder.json afff577673aec43b9a596c4663024cb35127e0c3 assets/create/blockstates/andesite_pillar.json -7e6808d9128828ae470ab6bf006ff871e1f0dcd4 assets/create/blockstates/andesite_tunnel.json -86f0d13f99ea4223651e81cb632ba5101896772c assets/create/blockstates/asurine.json +0d47d0816051dd63837c689de8b838dc1639d2fd assets/create/blockstates/andesite_scaffolding.json +67c4f7802f0854d24bb29019682b1d0a2f335a15 assets/create/blockstates/andesite_tunnel.json +542af96eb0c1e34df81f15fae7dbbaf4f81287f3 assets/create/blockstates/asurine.json 7f07775d89e3bea45d7161d289daf15470e7f544 assets/create/blockstates/asurine_pillar.json 9c62e0ce5d85ac4081bc04c85db7676b996b0f12 assets/create/blockstates/basin.json -51e18c0b0d730230b84f4659fe94c81c196bc30e assets/create/blockstates/belt.json +a97910c7516e7cedec9e34eca51f1183f1e3e681 assets/create/blockstates/belt.json 0ea03133af234921a3313f52521d8cfd02bf5d81 assets/create/blockstates/birch_window.json 2003c43151b731bf19cae58290c63bcb3785848a assets/create/blockstates/birch_window_pane.json c8b65faf51122eb411f5895e718869da9b260c2e assets/create/blockstates/black_nixie_tube.json @@ -29,15 +33,18 @@ d540f0f23e0d7c03f8e147cf3eebbaf7caec9f93 assets/create/blockstates/blue_sail.jso d2fdb432bb037de781260c789e905b223fab408c assets/create/blockstates/blue_seat.json f91092da79b69fece9583ccc15350612f439ee1b assets/create/blockstates/blue_toolbox.json e330efa253172b315f73401ed8f2c39270ba90d3 assets/create/blockstates/blue_valve_handle.json -f88ccf59cced46a7c2965077d4c36f7db0a8e7aa assets/create/blockstates/brass_belt_funnel.json +5c7065e56a831e0957b6531d50f720e9efb64309 assets/create/blockstates/brass_bars.json +d49d09f1026f816bb05a5dc13c806b860f2eb07a assets/create/blockstates/brass_belt_funnel.json 5a2551315557447abc579cf9225e3a12d9a46641 assets/create/blockstates/brass_block.json ac2f8f5e1d556e5c697da95729e82f107b115f09 assets/create/blockstates/brass_casing.json +2ae65b2e9018a7445b42609e99b91e64cb2dff45 assets/create/blockstates/brass_door.json bac88b313b63acfc77c25b1463276a714f22f336 assets/create/blockstates/brass_encased_cogwheel.json 8a152aeb42b1e8fc3596886124139c811976bf7b assets/create/blockstates/brass_encased_large_cogwheel.json 64008f70adf8067b5691a8a26f66d6715c73411e assets/create/blockstates/brass_encased_shaft.json -abd422776d9b3273699405c6be0a413f3f2f1a39 assets/create/blockstates/brass_funnel.json +a408005aae4c1caa7aaae5a0ddf9d1ad73cd0254 assets/create/blockstates/brass_funnel.json 1e8eba1ac6a0beb744f8b5feb96bbe5f3a75f214 assets/create/blockstates/brass_ladder.json -277e81dd612b3b08d6bf76616da95c9bb9493a9c assets/create/blockstates/brass_tunnel.json +6d210298b9d80ae69aa03b09aa73b92e14b9ab1b assets/create/blockstates/brass_scaffolding.json +8ee948f9e87b82bb27aaecc522127fa1297b3d9d assets/create/blockstates/brass_tunnel.json debf33346bf410216f21082e1e8d07aa6250b84c assets/create/blockstates/brown_nixie_tube.json 1334fc9e71d9f2a6117f448817263467a9c695de assets/create/blockstates/brown_sail.json 19524b2c0672632e63372f405a87dbea35f1d160 assets/create/blockstates/brown_seat.json @@ -46,16 +53,21 @@ debf33346bf410216f21082e1e8d07aa6250b84c assets/create/blockstates/brown_nixie_t 2064534de4791b339fdcd4ef3a8129a2e233ec50 assets/create/blockstates/calcite_pillar.json 060c957b28afed9f4e0954cbef7e80cbf4b99f58 assets/create/blockstates/cart_assembler.json c7eca70054241944171b1d4ffcba0376b071ec62 assets/create/blockstates/chocolate.json -1dbc25ad2b02467fc322c44d3c816e8194b3d330 assets/create/blockstates/chute.json +9eb989b0a0545af9efd052d1f127b2ec28a972d1 assets/create/blockstates/chute.json +b5170d754ce5f07ea2b4646eb07c099c50bae249 assets/create/blockstates/clipboard.json 6aaece104960d0b586644085c990d051972bf8b2 assets/create/blockstates/clockwork_bearing.json 418f2519202c4159d3309834bb121d5e23a51f29 assets/create/blockstates/clutch.json 6ea849c441a5444e896cbb246c7d10862b3b6b19 assets/create/blockstates/cogwheel.json -3f61e31c5c189eda9b249c3edd519647abb0ea4d assets/create/blockstates/content_observer.json +646b25b6e2d1c4a7e7a2a7f3810ae75797e61392 assets/create/blockstates/content_observer.json +376a488212875b40e8df50f7ea4902fbb174dcb8 assets/create/blockstates/contraption_controls.json 2f1914af1078db737e338359bc8c8ac493cae050 assets/create/blockstates/controller_rail.json 8bb9865ebfa6db9a13a29c9a327c2ccc4151222d assets/create/blockstates/controls.json 134c62bbd8ea43ff54c8edb2da5ea707f0a228fe assets/create/blockstates/copper_backtank.json +1b1e311efecc45ce7a3f69c8a1c2c53c6559b995 assets/create/blockstates/copper_bars.json 33175a9b530554e42e2ac68a9761d55f7f8623cf assets/create/blockstates/copper_casing.json +f7254f20f91e2f1295e36d2e70390d43f3952d07 assets/create/blockstates/copper_door.json 736777de0eb038ff1ef9e8fe9d04c23d80239eda assets/create/blockstates/copper_ladder.json +df3103dfc1c3ba7a9573229d009cb0de4925df16 assets/create/blockstates/copper_scaffolding.json 4d3d29e8a74bf103da39e76a1466b03eb5dcf916 assets/create/blockstates/copper_shingles.json 1ea8fdb990f8cda1762ab69ac38ea3161a835227 assets/create/blockstates/copper_shingle_slab.json 7c35bb802099d6bb5d92eafd8cbb7ea146979a2e assets/create/blockstates/copper_shingle_stairs.json @@ -63,14 +75,18 @@ c7eca70054241944171b1d4ffcba0376b071ec62 assets/create/blockstates/chocolate.jso 7db7a0d81887091ca889f40bb8a508d3098c5164 assets/create/blockstates/copper_tile_slab.json c0b7eca017242913d156e4623147add0d03574f6 assets/create/blockstates/copper_tile_stairs.json ef3ccb2d8b03f5a972b053a15bb037f8db6af17c assets/create/blockstates/copper_valve_handle.json +4758bed22fb6fe18213f463bc055775c1909e858 assets/create/blockstates/copycat_bars.json +4789c857508452aede1cb7389187b99ce2d7bf62 assets/create/blockstates/copycat_base.json +3dff9e1ec59415779195d2abfa9f07bc17b428a1 assets/create/blockstates/copycat_panel.json +3dff9e1ec59415779195d2abfa9f07bc17b428a1 assets/create/blockstates/copycat_step.json 61aff016059d737c970202cfe22e1cf9e111fb01 assets/create/blockstates/creative_crate.json a04c7aa7dc994b76252b0d35d0a90f8ee79c7282 assets/create/blockstates/creative_fluid_tank.json 185cf1232b3db390c24653c17c0522d8320f94a4 assets/create/blockstates/creative_motor.json -95a09387cfc61cdcf3f9eb6961b489cb5633ccb4 assets/create/blockstates/crimsite.json +d0536a75e870eda403f8924d4dd75603f6834a8a assets/create/blockstates/crimsite.json 45d667c79a7c22cc8f636c8c44264ba521fedbdf assets/create/blockstates/crimsite_pillar.json 41926b920da593ed2e529986304f7c4c12333402 assets/create/blockstates/crimson_window.json cffc87d0896e1946b8bf211e282eb4cdd9b1ca5c assets/create/blockstates/crimson_window_pane.json -03dc209ae3a5e680729a98746873d41f7dad6d66 assets/create/blockstates/crushing_wheel.json +c9a2c3a7971c46957d0f07c6d94d76f59da54a0b assets/create/blockstates/crushing_wheel.json 4b0e51a1c10685f7d432467339afc9c2e24793b0 assets/create/blockstates/crushing_wheel_controller.json ba9c3ecfacbd398048440d247decffeaefc714b5 assets/create/blockstates/cuckoo_clock.json 1f6d84cba69062a1989d671c9c97317e2c2455b6 assets/create/blockstates/cut_andesite.json @@ -200,9 +216,12 @@ d0ec99fdd534e1f3a84cc51fa914d3b74fb2c96a assets/create/blockstates/deployer.json d45d92164f81fd42cc1f8c6ba4ac25df0fca79b1 assets/create/blockstates/display_board.json a65771f280051a884725073d14a831539bc0d658 assets/create/blockstates/display_link.json ce43c78368724a2e1a6048c5b4e4fb45297b1593 assets/create/blockstates/dripstone_pillar.json +f7f5df9086c71688cbdb5d05c394dc5acb8fb338 assets/create/blockstates/elevator_contact.json +359a0c4954da65d8f7af554b9b8a11a707a8b68a assets/create/blockstates/elevator_pulley.json 2fa96f480365dcbd867635eaa665d1ad5936ca65 assets/create/blockstates/encased_chain_drive.json d47bc65703e9582cc710e6408fb565e16d3514a6 assets/create/blockstates/encased_fan.json 651f9fdb11f56d887d131be8f936f508d0b2fc1d assets/create/blockstates/encased_fluid_pipe.json +489ad4daeaed702d231a3f175f7b66846f5789a6 assets/create/blockstates/experience_block.json 5f6c60a30889b043709066707e80a21081d98155 assets/create/blockstates/exposed_copper_shingles.json 74c8a72db3dd3fa919e29baaa8c5865f13490461 assets/create/blockstates/exposed_copper_shingle_slab.json 4e0b5a9be15f0c2861f5f6bd71bd9c2a4db2a21d assets/create/blockstates/exposed_copper_shingle_stairs.json @@ -240,12 +259,14 @@ d0b26c085df3ee5189082bc18945e5f74ee529fa assets/create/blockstates/haunted_bell. 44343f14fb6e43a93882b4f9ce0640e54876fdf8 assets/create/blockstates/horizontal_framed_glass.json bffc2169f5fc3a8e22f8952a90767e0bb8d726b5 assets/create/blockstates/horizontal_framed_glass_pane.json 8ae52808eba950c36b75d62113e9cea9441a1a54 assets/create/blockstates/hose_pulley.json +87fa830c5d3541d096fab32d430c54516c197583 assets/create/blockstates/industrial_iron_block.json 2788ad2d29996076f7f18ab8d47e40c1ad10b348 assets/create/blockstates/item_drain.json 3e99569e978c0fe17ec18b97881434a9da1a8421 assets/create/blockstates/item_vault.json 8680e9d2a94231f4bbad87b26ab2efdb714903d3 assets/create/blockstates/jungle_window.json ddcf1010e43c5d4a8c93aad37cc97a94343fd9f5 assets/create/blockstates/jungle_window_pane.json e986248237013eea755bccd300f745e44d0a183f assets/create/blockstates/large_bogey.json bf3ee4416935ba760777e0702eef28ad94332d76 assets/create/blockstates/large_cogwheel.json +ba1ab31dd3ed2fbf9709ef2ba509b7ac210f5ad2 assets/create/blockstates/large_water_wheel.json ecc6a978a44636a43f12728da56268de05e9bfbd assets/create/blockstates/layered_andesite.json 8917eb8a3bb805e79bdc6a837c38f4d7b5ccc4fd assets/create/blockstates/layered_asurine.json 3198434c68e45a274c31f0c95929dd03a80ab034 assets/create/blockstates/layered_calcite.json @@ -285,29 +306,33 @@ f150922cbed1c05fb3892d4ac91eb471234252e2 assets/create/blockstates/magenta_sail. bb1ab5c70647933400b3a99ef9d166ba5e3d4709 assets/create/blockstates/magenta_seat.json fcd226c7863262d98765c701538bf9e44d2b177e assets/create/blockstates/magenta_toolbox.json ecf670d95969a33a738f59e08393299891f78847 assets/create/blockstates/magenta_valve_handle.json +8a30c1ed277ec60963abbcb24cce6efd162d02d3 assets/create/blockstates/mangrove_window.json +ed1afa8eec6824928332aed7f75c07ba6754c760 assets/create/blockstates/mangrove_window_pane.json 9386361f50a60bb14f397821285e64d33ed21fd2 assets/create/blockstates/mechanical_arm.json aafb4c62ae10fd65003f05160f3e1fbddbb01c5e assets/create/blockstates/mechanical_bearing.json be119eeeb8e0d9a9a5515dd2c49eaf91268d49b3 assets/create/blockstates/mechanical_crafter.json d17606a48ba154490c539fb07747ddf1fc15cb89 assets/create/blockstates/mechanical_drill.json -e1defe84b150f07258f4e0629cd8baa9cdfde326 assets/create/blockstates/mechanical_harvester.json +4a329956138fa77de07c183ebe4e5751bdce2560 assets/create/blockstates/mechanical_harvester.json 3238f7a31049bc6a810936366bba417ed7b0e5f2 assets/create/blockstates/mechanical_mixer.json 916a6ebe785f37afbf153dc0e8fe6be264eb5425 assets/create/blockstates/mechanical_piston.json 039686cb1a0f9b3eea44ff39431ebe9c57081fc3 assets/create/blockstates/mechanical_piston_head.json -7719852bceb6e42ed00a07871ce7c7521d468911 assets/create/blockstates/mechanical_plough.json +c9c7d39adc40a2c3f93dd88f412563cd89c8f0ba assets/create/blockstates/mechanical_plough.json 383a36c7aebf2351de9b1f2d41552c743840bc0d assets/create/blockstates/mechanical_press.json ed641766febe7fb28ea284609f1c76ee923faecb assets/create/blockstates/mechanical_pump.json -31d870761dd21aae90e5977df458a5a06c6ce13a assets/create/blockstates/mechanical_saw.json +e10b013ce15bbd4936c791ffb77c7fc3e106c013 assets/create/blockstates/mechanical_roller.json +852dde5b240a61c3dba99e7d69a2a9499e7fc5c2 assets/create/blockstates/mechanical_saw.json 884ea4362ec7ce45666a34da4ae21706a29dd1cc assets/create/blockstates/metal_bracket.json 2ccd64475bf5be5cd6e8e029277293e9f3a604cf assets/create/blockstates/metal_girder.json 2c1c3bb461ffb640fa241c69dc12d9cbdd266ffd assets/create/blockstates/metal_girder_encased_shaft.json 6e3247f54dfbfd4dccab046b2d4507ca41af87ba assets/create/blockstates/millstone.json dc8dcde498e19cf11a81266ba422c21e298b8df5 assets/create/blockstates/minecart_anchor.json ba9c3ecfacbd398048440d247decffeaefc714b5 assets/create/blockstates/mysterious_cuckoo_clock.json +6df63c68be95f7e8073d298559afd2e21fdf4311 assets/create/blockstates/netherite_backtank.json 8875635297883533de5fae78e24f7b08f5638c63 assets/create/blockstates/nixie_tube.json 2aaa022b8ee325faa3dfe6f560f04edffed2bfbf assets/create/blockstates/nozzle.json 22d97edd763e503b99ebe041eceee5f499c770f5 assets/create/blockstates/oak_window.json 7f2c5728e24d60ed2f7a095e3a954d7ca4e410e9 assets/create/blockstates/oak_window_pane.json -7e5f1947ae6886d6dbfcbb92fae69cb8e566c712 assets/create/blockstates/ochrum.json +df91d0ca68934c1afd9858a8d1591dd4cb88df65 assets/create/blockstates/ochrum.json 09c9bee3d26edc4b87cb7a5042f125c439ee5956 assets/create/blockstates/ochrum_pillar.json af4c2c4861d1410e1b7371a5bf3fe09ed3ab0077 assets/create/blockstates/orange_sail.json aab812cecf7d10d4e7587f4dead8a98238a15f41 assets/create/blockstates/orange_seat.json @@ -495,7 +520,7 @@ a60c9c8241e40c2e28f5760c0ca6e80cfe9d59f3 assets/create/blockstates/steam_whistle 636ec6c7e1ef3b737edc716200f138bc63681d78 assets/create/blockstates/steam_whistle_extension.json 8865500bcd2e4d467e74edb3509850fa92a5809f assets/create/blockstates/sticker.json bed0534e618105184bc877b104230403ca85bb58 assets/create/blockstates/sticky_mechanical_piston.json -be2ac84a015296e0717dc63bbfa9130efc0b9276 assets/create/blockstates/stockpile_switch.json +bab242ab794e6d439645c2d5a0242ae7c81942ff assets/create/blockstates/stockpile_switch.json a70c025de5d85180f371ff05bbdc531d8bdfaab1 assets/create/blockstates/stressometer.json 8086f80c532fad42b37fcdc590b890ed7e8c3fe9 assets/create/blockstates/tiled_glass.json 1143ab7223c655764a81ed72ac385ea179664072 assets/create/blockstates/tiled_glass_pane.json @@ -507,13 +532,14 @@ a70c025de5d85180f371ff05bbdc531d8bdfaab1 assets/create/blockstates/stressometer. 635468424f86e159628fb6f8f8e4e81f87486055 assets/create/blockstates/train_trapdoor.json 01e40ddbc83d714b543e319963ddc6b27514bccb assets/create/blockstates/tuff_pillar.json bfb2b7eabba2e7aef4d783328c8a5a1558e7e493 assets/create/blockstates/turntable.json -7ba695698b74d35e10a65b041d00de30dc3c605f assets/create/blockstates/veridium.json +92992bc0bb08c67e32a48957a984e22551a70abd assets/create/blockstates/veridium.json 09ffd28ac9044c7c6597f9bdb75f2bd66e0f591d assets/create/blockstates/veridium_pillar.json 673ca844beebe630ab847fb4d6bf0d3b9a183ba6 assets/create/blockstates/vertical_framed_glass.json 52aa6d08d9b950c2194bf126640f684342d3b0b5 assets/create/blockstates/vertical_framed_glass_pane.json 04b90c8216a1ab87eb2158313796fa687f8c619a assets/create/blockstates/warped_window.json 116d0a8fb72bcc00bd511db7893ea3e96efda297 assets/create/blockstates/warped_window_pane.json -00089f3c08fc3e53bd38ea67caca473f9cc07848 assets/create/blockstates/water_wheel.json +fa3d300520e3bedb926696d9980cbeeb54cfdc68 assets/create/blockstates/water_wheel.json +3dff9e1ec59415779195d2abfa9f07bc17b428a1 assets/create/blockstates/water_wheel_structure.json 2ae175c489b86b78b4646306250ca2dba66b0a5e assets/create/blockstates/waxed_copper_shingles.json 85ed36dcb0a3542e0638601116360202a9670d53 assets/create/blockstates/waxed_copper_shingle_slab.json aaf49f1b6785e2195c5dc2e8792c99c960745f89 assets/create/blockstates/waxed_copper_shingle_stairs.json @@ -544,7 +570,7 @@ c11562afd9a5f85945e521dcea5f911d1b6d13c6 assets/create/blockstates/weathered_cop 236e072d9056c0dbffdf5d7d973a85a56c2c8de1 assets/create/blockstates/weathered_copper_tiles.json fee668eb9a45dca0d287fee5811219d69f9ec3e2 assets/create/blockstates/weathered_copper_tile_slab.json da110f382368257e15431c77164aef82e014e3f8 assets/create/blockstates/weathered_copper_tile_stairs.json -82e1fb7c4df72be25bc5645937ea6dc928411fd5 assets/create/blockstates/weighted_ejector.json +25ce64b7af5d244f194da91ccf964a9bf5762327 assets/create/blockstates/weighted_ejector.json 2974b34a8cfb0d4e8e010f8bd085584ea631d541 assets/create/blockstates/white_nixie_tube.json f079469d186087d23f0d91b384040f777b0088b1 assets/create/blockstates/white_sail.json 317a6463db64b66d215d25b65ab52fe7f26ba9f8 assets/create/blockstates/white_seat.json @@ -559,8 +585,8 @@ b0d8f08968763a5f74e5cd5644377a76a9f39753 assets/create/blockstates/yellow_toolbo fe8c497aacc641c2f01cec90bba9f19e59cc2ed2 assets/create/blockstates/yellow_valve_handle.json e819e93fdcbe9fd9c050a052d2718ff3b3539365 assets/create/blockstates/zinc_block.json 64121dcb216381c83b4fe28aa361ea07c24c9ad0 assets/create/blockstates/zinc_ore.json -af25fce0cd0f61c6f0feaf6cfe00e92fb6d0e6e0 assets/create/lang/en_ud.json -28beca6e221b45c93aa1a370b1f86a4c509ae52e assets/create/lang/en_us.json +3a1e0c68a9f1d6a252f47b3f7311278711f2aae0 assets/create/lang/en_ud.json +12da996b104ab0e5ce956c963fbdae7e59e72f79 assets/create/lang/en_us.json a97e1060e00ae701a02e39cd4ef8054cf345fac4 assets/create/models/block/acacia_window.json 103e032c0b1a0a6a27c67da8c91179a564bd281c assets/create/models/block/acacia_window_pane_noside.json fb00b627abda76ad4fea867ca57dbfadd24fffa3 assets/create/models/block/acacia_window_pane_noside_alt.json @@ -577,40 +603,47 @@ b3395dc098640a77ff226f9c6a5c518a4d2919ff assets/create/models/block/adjustable_c 7aa37fa87c81ae4704871710fe9ce90c70194ed4 assets/create/models/block/adjustable_chain_gearshift_middle_vertical_powered.json b6ff6e0f4e70bd194ffb28d489587ad0c7549e9d assets/create/models/block/adjustable_chain_gearshift_single.json 998e44d53c59dd176945b936c9c0dbf733bd66c4 assets/create/models/block/adjustable_chain_gearshift_single_powered.json -a033ad7c4c73a09335bdeb3ae563facfd901a1c8 assets/create/models/block/andesite_belt_funnel_extended.json -58d2c7133de3a31a2e0719a022022786e00c8a5a assets/create/models/block/andesite_belt_funnel_extended_powered.json -e2e6c946390bf3e40815a3b6bce25c6e702b6b91 assets/create/models/block/andesite_belt_funnel_pulling.json -bb9b09581a6a7535aec03b1f621a94c49afda5e3 assets/create/models/block/andesite_belt_funnel_pulling_powered.json -8a63bee9a9a15fa751c97e7b583b16fb80c2034b assets/create/models/block/andesite_belt_funnel_pushing.json -d88e234d5a0c50049a4b22aae81176de9235982f assets/create/models/block/andesite_belt_funnel_pushing_powered.json -467dcce21b1ef913168e79b027ee54411fceb659 assets/create/models/block/andesite_belt_funnel_retracted.json -6c6d181a50e82139d682bfc9586fe50117056965 assets/create/models/block/andesite_belt_funnel_retracted_powered.json +2b7c4bcc18f4535e73819315a8e776b73fa15bf6 assets/create/models/block/andesite_alloy_block.json +8771ee925d11cbd29cd876621235301f19360ea0 assets/create/models/block/andesite_belt_funnel_extended_powered.json +c1fe0201ed3856ae1ae0d9695f1561a0f443aa8e assets/create/models/block/andesite_belt_funnel_extended_unpowered.json +d4ffa3f167dfa03728ed760db7b72480ac78da71 assets/create/models/block/andesite_belt_funnel_pulling_powered.json +54e60c81510d842c7086441bfff246687504b574 assets/create/models/block/andesite_belt_funnel_pulling_unpowered.json +1779a6141817e462efccf64e7194bb72e7cc2e36 assets/create/models/block/andesite_belt_funnel_pushing_powered.json +6cf7d3d9d8e6a9e92fc4622ca6aaf2e2accdd65f assets/create/models/block/andesite_belt_funnel_pushing_unpowered.json +56ab231c317040a02bf8588096c414c043062e0d assets/create/models/block/andesite_belt_funnel_retracted_powered.json +593b75f5d1ef34fd479e87228cd9b84404966d6e assets/create/models/block/andesite_belt_funnel_retracted_unpowered.json +63dc5d1d36eda5131f6163d1c051ff5b5d60b1f5 assets/create/models/block/andesite_cap.json +088c4433e9199faf6a09032f443d1c5529c1f117 assets/create/models/block/andesite_cap_alt.json b69b845d2a5f93ec3c2339fd5d38fa8e1360a3ee assets/create/models/block/andesite_casing.json -cfb697c3c9935bf484ffeb2f40704d7275b2bc5e assets/create/models/block/andesite_encased_cogwheel.json -e85e4623c550beb3ea88d57debebc611038b8e97 assets/create/models/block/andesite_encased_cogwheel_bottom.json -ea3d5d65aa4b11edba4a837a542be8beffb26f45 assets/create/models/block/andesite_encased_cogwheel_top.json -e963124e598c99340bbdb3ab6b67530236ff2658 assets/create/models/block/andesite_encased_cogwheel_top_bottom.json -90940a7e32e97647cc523877374540da968c0ae4 assets/create/models/block/andesite_encased_large_cogwheel.json -1041a07e89a86ae36b38748c426350c77c093348 assets/create/models/block/andesite_encased_large_cogwheel_bottom.json -31fe80580ff3e56814c675ca74a5c70cea221960 assets/create/models/block/andesite_encased_large_cogwheel_top.json -15f3dff551c508f698fff89eb35f20fc482eb4ae assets/create/models/block/andesite_encased_large_cogwheel_top_bottom.json -9c76184f7f25cbf89d38ca59f12a4c9b7e05c0d8 assets/create/models/block/andesite_funnel_horizontal_pull.json -e819df27d4de2c4b3b3451ccdf626e61a1eebd71 assets/create/models/block/andesite_funnel_horizontal_pull_powered.json -9be27e50953499461b7f463f7f4a792aec91bbd4 assets/create/models/block/andesite_funnel_horizontal_push.json -1454be0431ec6c948eb1e4762c05478baefe5660 assets/create/models/block/andesite_funnel_horizontal_push_powered.json -cb880ca2eb8514af5acb95c58176bae5e4709be3 assets/create/models/block/andesite_funnel_vertical_filterless_pull.json -16b78bd653797b67f1fae5059456ad2c506d05d2 assets/create/models/block/andesite_funnel_vertical_filterless_pull_powered.json -75b7b59f0c9e2c2cf2a89e8a749d71bc329104ca assets/create/models/block/andesite_funnel_vertical_filterless_push.json -45aed296685893b0fa7658f58e204f9cbda74a16 assets/create/models/block/andesite_funnel_vertical_filterless_push_powered.json +7f3e4636d521a67eb621d5d27d6b175d455179f8 assets/create/models/block/andesite_encased_cogwheel.json +5a5a3aac31c44030880774b96cfecc40568abe75 assets/create/models/block/andesite_encased_cogwheel_bottom.json +82ce3bec0d6b5332b4f5007245ca2cdd8e28b9c9 assets/create/models/block/andesite_encased_cogwheel_top.json +81aeb37ffeb6540cf7af0c28165dcc39d69f6578 assets/create/models/block/andesite_encased_cogwheel_top_bottom.json +869f5648e722de9f61d85d7248f737969403df23 assets/create/models/block/andesite_encased_large_cogwheel.json +79df86bc27f8ddf964bc16b2a3c95d15076c7766 assets/create/models/block/andesite_encased_large_cogwheel_bottom.json +827e21caf325dd7c503ba59c8c1be66e49d290ef assets/create/models/block/andesite_encased_large_cogwheel_top.json +a56b436a83a59511b1e9f0a86551f01281a9e268 assets/create/models/block/andesite_encased_large_cogwheel_top_bottom.json +739054687d9cdb15ee9e42195d1789230ffc1514 assets/create/models/block/andesite_funnel_horizontal_pull_powered.json +d002aa323299d1079c4707fabfc518dc0d7255fd assets/create/models/block/andesite_funnel_horizontal_pull_unpowered.json +1d2feb144e9070fd46581c4ae46dc3469aa5f8a9 assets/create/models/block/andesite_funnel_horizontal_push_powered.json +49db82218c6b2734ef839651d17ead455f97a947 assets/create/models/block/andesite_funnel_horizontal_push_unpowered.json +647a2f025e790176fca3021b92cc6a79474c3237 assets/create/models/block/andesite_funnel_vertical_filterless_pull_powered.json +08f58a237d111d614e00b3523680362be688b439 assets/create/models/block/andesite_funnel_vertical_filterless_pull_unpowered.json +7f0c84aa3eaf452d30b71b9646199ca5dda2c3ac assets/create/models/block/andesite_funnel_vertical_filterless_push_powered.json +dcbf18e7c49d8058e6ad9309b2473ef3bc1d5519 assets/create/models/block/andesite_funnel_vertical_filterless_push_unpowered.json b39661fd20e4b3f5ab2b20cbd51af4ca98e2410e assets/create/models/block/andesite_ladder.json 338ecc4d7d7c71fec17c8370a1313049d5179bb3 assets/create/models/block/andesite_pillar.json 46d6434572f5514e9af63c7234f581d6b2a873fb assets/create/models/block/andesite_pillar_horizontal.json -c2d91fcdf2aae1291861f449f96bedbdbb9aef80 assets/create/models/block/andesite_tunnel/cross.json -793427dab4e9046143a65f9bd216c82e2255238c assets/create/models/block/andesite_tunnel/straight.json -95de25b3e0fd0cea938b447ac5d1c372d2c7aef0 assets/create/models/block/andesite_tunnel/t_left.json -11721ac2d9fb8d2e2a84468248b86ac97c8f7bd9 assets/create/models/block/andesite_tunnel/t_right.json -d29ebb7c1840ce434d1ff2797fb1ee20cca39c21 assets/create/models/block/andesite_tunnel/window.json -0a48412af05856e5bc61cafd27f2dbb50dc3bd0b assets/create/models/block/asurine.json +3819c8da4fa1074e05de1e18317530c543ed4504 assets/create/models/block/andesite_post.json +3127d8ac32a3283797cd6f4784c5bbdcbc6d01b7 assets/create/models/block/andesite_post_ends.json +167d94c692f94f49c2f33d59008b0d10c435c570 assets/create/models/block/andesite_scaffolding.json +32551174974fde322de14af09afb160673c4ed23 assets/create/models/block/andesite_scaffolding_horizontal.json +e20105b4d1762fbfe67377e08cdb8c7ff9a62128 assets/create/models/block/andesite_side.json +b58e7204eef795080abf9fffa41ba11ec2e12426 assets/create/models/block/andesite_side_alt.json +378df94de8cbce28cd3c2dc30fd3a30dfc451cdd assets/create/models/block/asurine_natural_0.json +d6eb7105dd9b42adde48bd70e3f2fba70751c1db assets/create/models/block/asurine_natural_1.json +6d77d2591579619aa1ebb7b2f0e2c939e1648e4a assets/create/models/block/asurine_natural_2.json +e80a3d387e8c40bf886735d46a119f9a93c6f5a8 assets/create/models/block/asurine_natural_3.json 1c3ddf07bdd9fc5fcf7c1f35c7a06846cc1add54 assets/create/models/block/asurine_pillar.json 403efa3dcd07e94c351594cc6c5b5becc15e6690 assets/create/models/block/asurine_pillar_horizontal.json 930e154155eaba67acb96109472b6d8c502907dc assets/create/models/block/birch_window.json @@ -641,38 +674,41 @@ b628e6d5cd66a84b7efb5bb7ab5c5a06ab9a81e6 assets/create/models/block/bracket/shaf f766eee9623c2bfa62a35e5637fcdd2a3a54cfaa assets/create/models/block/bracket/shaft/ground_wooden.json c841b4f04c0aaf388d279f2c0f3aed128cfbafc1 assets/create/models/block/bracket/shaft/wall_metal.json 7f39cb914b74a5643567da90160a43959eabee8f assets/create/models/block/bracket/shaft/wall_wooden.json -492f3021447cf13a51e489d2af43b745f221f4f0 assets/create/models/block/brass_belt_funnel_extended.json -6f848d352a6fa91b36b25c59c7f78036aff1821f assets/create/models/block/brass_belt_funnel_extended_powered.json -62bf77afa03c1c96f071e18bd6e7a351262cd7d3 assets/create/models/block/brass_belt_funnel_pulling.json -016a94de2413b412c7e2dfe130c08c4869da1e6b assets/create/models/block/brass_belt_funnel_pulling_powered.json -3b5e7b6d31e3f7cac63ce6164a7bd93affe95690 assets/create/models/block/brass_belt_funnel_pushing.json -01237bdde4727d3ec6a1b667a12c3de2ec9c8195 assets/create/models/block/brass_belt_funnel_pushing_powered.json -295cf9044e18e1dfea4b23e981afdb918fc84311 assets/create/models/block/brass_belt_funnel_retracted.json -fb39a27228862fdb5c34acdcf91828de2ba2012d assets/create/models/block/brass_belt_funnel_retracted_powered.json -4d02b6debedd7da0c0c5082d1da93e736edd33db assets/create/models/block/brass_block.json +b3c0a6837fd8f1796ce953df4ab1ae0e7b9c16e8 assets/create/models/block/brass_belt_funnel_extended_powered.json +1c2fd7977aad00cb78579eef6d26931a35fc02a2 assets/create/models/block/brass_belt_funnel_extended_unpowered.json +5aaf26529f19e21563b2a0f6a810c583346dd356 assets/create/models/block/brass_belt_funnel_pulling_powered.json +baaaaf87b9b883ef028fbf42e4f8b1fe89f79acf assets/create/models/block/brass_belt_funnel_pulling_unpowered.json +274d99974b02a58b7ea620a1d884e315d414df4f assets/create/models/block/brass_belt_funnel_pushing_powered.json +8e01225fb52b7d5184c5d9f2d9649b97fdbb0ce8 assets/create/models/block/brass_belt_funnel_pushing_unpowered.json +052ce8de93d149988688f465efd7381d8e5aa942 assets/create/models/block/brass_belt_funnel_retracted_powered.json +59da0fcd09fda595825c34509aa97b64b539f424 assets/create/models/block/brass_belt_funnel_retracted_unpowered.json +4ef8482fd79248ebae907a60355cc630737a4b69 assets/create/models/block/brass_block.json +f96d0c4880b15e2b85c3d3428e7a5db502d2a668 assets/create/models/block/brass_cap.json +0686785f47d3360012dab59291271a30ad039603 assets/create/models/block/brass_cap_alt.json d2c11a9d736b8cb17b7face08f00202ecb12b4df assets/create/models/block/brass_casing.json -23d4000981b7e5d7ca5626bbd93018972a079729 assets/create/models/block/brass_encased_cogwheel.json -0333996c2e42edd3f9330fb57c58432bfc42ac9d assets/create/models/block/brass_encased_cogwheel_bottom.json -f7a8b95481c4f85c294a8a16dcee298b5d54d5ee assets/create/models/block/brass_encased_cogwheel_top.json -7634a06f5ea5b80e38550a44886acf20fab50a77 assets/create/models/block/brass_encased_cogwheel_top_bottom.json -06a1cdaf43b4b8118acd97435e9a4de7bf623023 assets/create/models/block/brass_encased_large_cogwheel.json -0d83b45a761df448c80cfe98cf4257eae5fdfe99 assets/create/models/block/brass_encased_large_cogwheel_bottom.json -179a4fca6999a775fca520436589b51b68e9bf75 assets/create/models/block/brass_encased_large_cogwheel_top.json -d32b38a238ddb4eeea8d942788f1c7056c548211 assets/create/models/block/brass_encased_large_cogwheel_top_bottom.json -92b97464dfeb4ebf3558c1888a3e3e67644c491e assets/create/models/block/brass_funnel_horizontal_pull.json -8ba56683235a30a9eaaf068894d4ac16b30d9086 assets/create/models/block/brass_funnel_horizontal_pull_powered.json -6754956f052226385403f87c12c03f0f4f3ad6f1 assets/create/models/block/brass_funnel_horizontal_push.json -7b95be3a8103138024151e59c5ba1b383b56b307 assets/create/models/block/brass_funnel_horizontal_push_powered.json -956ce081b9960a94db8f1f41fcb8b77440fec832 assets/create/models/block/brass_funnel_vertical_pull.json -d81454fa4e62248add402cc2736558bc26db8f63 assets/create/models/block/brass_funnel_vertical_pull_powered.json -c2cb02a13923c2de5ccfee53b6c06471d8a6a38a assets/create/models/block/brass_funnel_vertical_push.json -048d963708199a451dcecefcb3bd22a2b1ed7829 assets/create/models/block/brass_funnel_vertical_push_powered.json +bf9a54257daa3e2787c8dcd84d42b9eb72503b5b assets/create/models/block/brass_encased_cogwheel.json +ef13822bd18d37e7cf5d2c37e3fd3207cf2c58c1 assets/create/models/block/brass_encased_cogwheel_bottom.json +c2187c0544513e96b440432f373f60845398af8a assets/create/models/block/brass_encased_cogwheel_top.json +653f7f852234dc2a790f2465120b049aa57c2992 assets/create/models/block/brass_encased_cogwheel_top_bottom.json +5949ef5674dc05a8f3ed03ad35d331e91a67c3aa assets/create/models/block/brass_encased_large_cogwheel.json +48622b2819203c5314857aaddc0d93daa7af4af2 assets/create/models/block/brass_encased_large_cogwheel_bottom.json +36633bb570f5644af88df8cd47991a31c4d5e41a assets/create/models/block/brass_encased_large_cogwheel_top.json +b13b6dd2cf862082027ab4992fd472cadde5e2a3 assets/create/models/block/brass_encased_large_cogwheel_top_bottom.json +f2a6b17faef0cd7f5170e8367b38a8555fcc50a7 assets/create/models/block/brass_funnel_horizontal_pull_powered.json +077a144b01afb7b7c9e7ff07faa02cc07378228a assets/create/models/block/brass_funnel_horizontal_pull_unpowered.json +a54f6d0bc97ba10795581b323ede1cbc2e139f0d assets/create/models/block/brass_funnel_horizontal_push_powered.json +cf63ef853a4f1c4e83c95f7485b9ef7ce02fdf51 assets/create/models/block/brass_funnel_horizontal_push_unpowered.json +717937a1dcfb986e00daeed7f6b58acc9a550305 assets/create/models/block/brass_funnel_vertical_pull_powered.json +49587723182812317f2e5d99232816f20492c256 assets/create/models/block/brass_funnel_vertical_pull_unpowered.json +4b88543d2db333ccad092ac508b20f8c241e976a assets/create/models/block/brass_funnel_vertical_push_powered.json +48e734cd25a835993c6fba210d4ad1889c48aa41 assets/create/models/block/brass_funnel_vertical_push_unpowered.json 4e4ac84ae8d864cc8a7d8e2c4d002be7d5c08304 assets/create/models/block/brass_ladder.json -69a1afc1290d909ed7a49ed845b6a61e31d6e43d assets/create/models/block/brass_tunnel/cross.json -c24b5b79c413639b1ab1e0f21274ac60db16f8c5 assets/create/models/block/brass_tunnel/straight.json -be59010a5fea25305da7a74f6e58851b73debb6e assets/create/models/block/brass_tunnel/t_left.json -9fd9eff3324ad051fabf8ce4f719a997306c0c3f assets/create/models/block/brass_tunnel/t_right.json -3f8bbc1d90909fd6927bdd6e7130c5bedfb0ca52 assets/create/models/block/brass_tunnel/window.json +8725b8d89416b5fcfc02a69038046067e834bf48 assets/create/models/block/brass_post.json +b2a95218042586aae38dff9278f3ee3f159bc73e assets/create/models/block/brass_post_ends.json +0fe59cd0ec75eeb44115bb0e2127acde25be100a assets/create/models/block/brass_scaffolding.json +62d99236e09b11af9a24d3c667fb1167cf8db0b0 assets/create/models/block/brass_scaffolding_horizontal.json +ec81e9c237ec98b30a3de22e12cb9720922478eb assets/create/models/block/brass_side.json +c697cace1f4097468ff34254c4ff6450d9d52f91 assets/create/models/block/brass_side_alt.json 2f040681214af58a97e70d3a6e77a0fc2e02c624 assets/create/models/block/brown_nixie_tube.json 50a054d1e0660d16e86cf7a520b9bf36e38401b6 assets/create/models/block/brown_sail.json 0616de192825246e6036d1f69911170438a83b81 assets/create/models/block/brown_seat.json @@ -681,15 +717,23 @@ be59010a5fea25305da7a74f6e58851b73debb6e assets/create/models/block/brass_tunnel 40a224ce4ea989599f7bd66bd2437ac2b98247d8 assets/create/models/block/calcite_pillar.json 141fc72bb7296c6b5a13499622c0c7384179a7fa assets/create/models/block/calcite_pillar_horizontal.json e9d61ba17fa2619af01ef604c3f65cbe9272f010 assets/create/models/block/chocolate.json -1029bf6dac53e0c7c805ae911221722e54909f4b assets/create/models/block/clockwork_bearing.json +d8339ab47ffa828985c7da27c37794a95aba8b42 assets/create/models/block/clockwork_bearing.json +8afe6afaff33b94c1fcee68fdaf842d525eec212 assets/create/models/block/copper_cap.json +58e6ed1f765ba67ca5d8a446af357f311587e431 assets/create/models/block/copper_cap_alt.json d8053f194ee9331288aadac94bc23fff5a63ae9c assets/create/models/block/copper_casing.json 2606721928394e80b24b5f0ff7011c1c552cfe7c assets/create/models/block/copper_ladder.json +d063df8e9b974c11fc7810ce176b02d7d924e15b assets/create/models/block/copper_post.json +2b5aed4a917694beb33d9b0ecbc800dcbc143ee9 assets/create/models/block/copper_post_ends.json +bac7566a726b0fe6d537c744aec4afb383dc165c assets/create/models/block/copper_scaffolding.json +dbee65c129740f3b99c07e754b3224d3f9f8c242 assets/create/models/block/copper_scaffolding_horizontal.json 32fdb85b5b62d5a0fb41732874c854788cdd2ba1 assets/create/models/block/copper_shingles.json fb7fb6deebd502946ab57f1b8a9f4a6b5dd48da3 assets/create/models/block/copper_shingle_slab.json 660f61112b8e46dec5050cb0ed4ee936965a7c58 assets/create/models/block/copper_shingle_slab_top.json 5d74be967bbe9feba4b630751f13af817a733d1d assets/create/models/block/copper_shingle_stairs.json 35cb89f29ce3f8d8af13602c08ecd7afbb7cf56a assets/create/models/block/copper_shingle_stairs_inner.json fcb9295f4f388e6d439ec9a3906ca326b6d69077 assets/create/models/block/copper_shingle_stairs_outer.json +cb218a725f82db34ffe58a5208266e1c768cfc05 assets/create/models/block/copper_side.json +d9b4652ca8f1e65007f42d946ecfb38acc3f168f assets/create/models/block/copper_side_alt.json 32f06f39d0b34e4431795aa6e64f87e58dc1597b assets/create/models/block/copper_tiles.json 298c6100de02ed9f813397d8ba38c46f35035c69 assets/create/models/block/copper_tile_slab.json d4422c2d96fb329087d1be70d8b983a8cf6c7f01 assets/create/models/block/copper_tile_slab_top.json @@ -726,7 +770,10 @@ bedffd9e30f340c6644e9216ab685d997dd0d2d1 assets/create/models/block/creative_sin 53accbd8241624398b0cca14bbd3261733e3a673 assets/create/models/block/creative_top_window_nw.json 8c8facc1969c416d7a297334f982b8ef123d7563 assets/create/models/block/creative_top_window_se.json 93ca6f95a8613e155e38f8f3c534ca054d037f9d assets/create/models/block/creative_top_window_sw.json -e0c2f1773af6768e26436bb8fe2125b3e9706587 assets/create/models/block/crimsite.json +0cf06ef8844933b64f6cb90b490b2bb098f42f3a assets/create/models/block/crimsite_natural_0.json +612778c4a390c3fc9de7ef40713375dc7be85270 assets/create/models/block/crimsite_natural_1.json +deee56804ca8b6ca8fb5c217bca064f7a13f63d1 assets/create/models/block/crimsite_natural_2.json +c4ce898117c64ad3ae05a109edc6357c3a2b2fe3 assets/create/models/block/crimsite_natural_3.json 2679b3d1594a600afc02c914f2b00cfb900b90e9 assets/create/models/block/crimsite_pillar.json 9234f132f7c179bbf23bbc74f4fddb82d8a2074b assets/create/models/block/crimsite_pillar_horizontal.json e5bf0e7cf732ac1cba943d5d297b2167f5523db4 assets/create/models/block/crimson_window.json @@ -1089,6 +1136,7 @@ f0100e1d44146b256998fbd2af05da80d147e8d9 assets/create/models/block/horizontal_f a1a239714f5feb45a692f5c2873c37d6614e1b8b assets/create/models/block/horizontal_framed_glass_pane_post.json 0f7e518ef02428c55e1683bc9de0d20e2c1e6883 assets/create/models/block/horizontal_framed_glass_pane_side.json db3f9472815fb6acc1ee1d9941b8cc19518ebcbf assets/create/models/block/horizontal_framed_glass_pane_side_alt.json +6868ed1959875efec96a15ca6f32b8c7efefb2d9 assets/create/models/block/industrial_iron_block.json cdc4f1c608f74824fd270521a846823ca4b6ef16 assets/create/models/block/jungle_window.json 8c5ee8e36756fcff3095c564567a35be1db23cee assets/create/models/block/jungle_window_pane_noside.json 2bb34fe17c7cfafc8658cd0b44ab636191f81348 assets/create/models/block/jungle_window_pane_noside_alt.json @@ -1136,7 +1184,13 @@ f885acc0ba705cfa9c65b62626ab4007f3b6e329 assets/create/models/block/linear_chass b5cd13b021400b3c37499ec4ef22e560c721ac54 assets/create/models/block/magenta_seat.json d7b2b16ba2d6a0b2441aeaf7faa76f61fbdc35e7 assets/create/models/block/magenta_toolbox.json c0d29851d48cebd376b3b6e8f0454e0369d0e265 assets/create/models/block/magenta_valve_handle.json -19d9b5215ea3d32da398118274c8bfe112a74a56 assets/create/models/block/mechanical_bearing.json +026384a699d592160624bb7a1606e31fb77751be assets/create/models/block/mangrove_window.json +fefcd6368357f1ad324b07a082fcd059900e0a39 assets/create/models/block/mangrove_window_pane_noside.json +166268a91f073f60e86af3e39a85dc0f4eb23368 assets/create/models/block/mangrove_window_pane_noside_alt.json +cf77590316c06bfea1c11fb39626f49888bf61b6 assets/create/models/block/mangrove_window_pane_post.json +dfd365f73424f4ffd1915822ae0c4d5538922ed1 assets/create/models/block/mangrove_window_pane_side.json +a8fb21f2d2f10b0c46bea41c9dd41eb9c5a9c5fe assets/create/models/block/mangrove_window_pane_side_alt.json +5a6d44dbf914c22065d8f32519defc93ce124c49 assets/create/models/block/mechanical_bearing.json 2f040681214af58a97e70d3a6e77a0fc2e02c624 assets/create/models/block/nixie_tube.json e298cb8398f551c5af5f563f95123b18f39d4753 assets/create/models/block/oak_window.json ed54366f117e121aa887cb6f8df9fa9457910153 assets/create/models/block/oak_window_pane_noside.json @@ -1144,7 +1198,10 @@ ed54366f117e121aa887cb6f8df9fa9457910153 assets/create/models/block/oak_window_p b16726446c5706091984c145751d7f3612ecc1b8 assets/create/models/block/oak_window_pane_post.json 38bc0c1757bbb45d0d3ce961025d8b720dde53ed assets/create/models/block/oak_window_pane_side.json ad522b2cf9193978d6f6bb112e7badeb0f8bedcb assets/create/models/block/oak_window_pane_side_alt.json -3be67dea08c613ded673d91ac5a44cdbb4689147 assets/create/models/block/ochrum.json +f8a67d6e5a9dae05b32b90272d93175489da696b assets/create/models/block/ochrum_natural_0.json +af50363d603d61340b336569d58c1febde253665 assets/create/models/block/ochrum_natural_1.json +611fdd4c21527994c9cae2c2399c3fd7398c3dbc assets/create/models/block/ochrum_natural_2.json +d69effa0a811cb93fead8257bcaad4bbf0094002 assets/create/models/block/ochrum_natural_3.json 24669a4e93925940477fcfc0aca10ab9d87368e0 assets/create/models/block/ochrum_pillar.json c8dd33a0b71dce37712788a61729de89574b117f assets/create/models/block/ochrum_pillar_horizontal.json cb4cd4e4bfb0d105a09c56454abf4795b155d12b assets/create/models/block/orange_sail.json @@ -1502,13 +1559,6 @@ e13aabf77b949a4eaf33c772e8b7112b1a7f1e72 assets/create/models/block/spruce_windo 9bf5008df74b7caea128580021605a6abcae6841 assets/create/models/block/steam_whistle/block_medium_wall_powered.json 92eba6564e2c65e08bc628107fbf89a5ff7ab53e assets/create/models/block/steam_whistle/block_small_floor_powered.json d768a02c31606cc46a4bbd619906e313099cce2d assets/create/models/block/steam_whistle/block_small_wall_powered.json -057c92cc040a48e2c43868d5a62383d3809f4e28 assets/create/models/block/stockpile_switch_0.json -2bf8d40bb1b3d13b41cd2dec72c504c6674e6dfb assets/create/models/block/stockpile_switch_1.json -ad3c2c6a877d403df25a2c103c8d70e111ce11bf assets/create/models/block/stockpile_switch_2.json -b83e834cc3473a10f3042535c1febf52b88b0079 assets/create/models/block/stockpile_switch_3.json -6294701ea01580224c0e6eaf24bba13fa1faefe7 assets/create/models/block/stockpile_switch_4.json -bb12d368350de91367a6989ca291f85bd1b1424e assets/create/models/block/stockpile_switch_5.json -51655f0e5ccd15b13745738d38ea430a0e65daca assets/create/models/block/stockpile_switch_6.json 9e74256a37ee71de978395fb911e6e6db9fcc41e assets/create/models/block/tiled_glass.json 49c76af85635454ba3b6278f7317bb1729c4c58a assets/create/models/block/tiled_glass_pane_noside.json 4319255a3fcb0b9b60cba96273c513329a480a6b assets/create/models/block/tiled_glass_pane_noside_alt.json @@ -1517,7 +1567,20 @@ bb12d368350de91367a6989ca291f85bd1b1424e assets/create/models/block/stockpile_sw 4666d4fa04549c2fc182da43295b15ba6e35e874 assets/create/models/block/tiled_glass_pane_side_alt.json c6772ce52c8e9e763a2ae26bd367deb02d9b7949 assets/create/models/block/tuff_pillar.json 5b62f55f41de41cdc80af2c474a4b2bbdf9cd629 assets/create/models/block/tuff_pillar_horizontal.json -dd0cfb9dbea4064562869ec6b7c8633b881dff41 assets/create/models/block/veridium.json +a576d5644cca47998391ba62ea2b5de73236e7e7 assets/create/models/block/tunnel/andesite_tunnel/cross.json +3dfec1c898324c5e9eb8c46079c372c7b0a87566 assets/create/models/block/tunnel/andesite_tunnel/straight.json +623e1b0da749f8ad397b50eb94e3bd5d745a9b50 assets/create/models/block/tunnel/andesite_tunnel/t_left.json +4f2ba214ef7e7a97c096e1a9dbbfa4ceafa814f5 assets/create/models/block/tunnel/andesite_tunnel/t_right.json +a99c3c8b5f4530ecff8e4a25c2a95d2399781817 assets/create/models/block/tunnel/andesite_tunnel/window.json +14cea60ecb9a49f3e7a216e5c208ba134a610537 assets/create/models/block/tunnel/brass_tunnel/cross.json +1dc41df10c394bea32f34bfd4ff05bab5002b7d7 assets/create/models/block/tunnel/brass_tunnel/straight.json +2b8379727fff55130815826c13285b65b30ce29a assets/create/models/block/tunnel/brass_tunnel/t_left.json +578e09fa338c9f51185d9502e789009bd644b4f3 assets/create/models/block/tunnel/brass_tunnel/t_right.json +df2cb93c8be9c08f4cc312e23d7e35b4e4bed8fd assets/create/models/block/tunnel/brass_tunnel/window.json +f2c50cb2a7899de719552327e0093c26380b5b5d assets/create/models/block/veridium_natural_0.json +63a159b54de6a31ee265750e4af4b1990820eda6 assets/create/models/block/veridium_natural_1.json +d253cb618fd47d1a9dbecbb6ee72639e1da2b8da assets/create/models/block/veridium_natural_2.json +2b6b8969b7a363698aae4f85f7ac39f876fe78e4 assets/create/models/block/veridium_natural_3.json 25cc486b31fca67b84f44ff4b5c220a059bc8589 assets/create/models/block/veridium_pillar.json e0fd360f1fa4324ddd7f190b1d14696463ab7d1c assets/create/models/block/veridium_pillar_horizontal.json 5f70af15ec2569c68a17d31024c7a37cb5c68c7e assets/create/models/block/vertical_framed_glass.json @@ -1596,7 +1659,7 @@ e7ae89577be9d26a071bf96cbd7ed80293902b63 assets/create/models/block/weathered_co 99f0628623a36ac1700a5876cec010ee6353162f assets/create/models/block/white_seat.json f252f8c68702a0c050797a2dc2a51c586408722d assets/create/models/block/white_toolbox.json c9e344a06ee8bca1bfddd70481198135cabafbce assets/create/models/block/white_valve_handle.json -893643a67b4f3ff16cf6523f6f90e3ca0d39139e assets/create/models/block/windmill_bearing.json +68d8eddfb724c73938862fb1a213a99c95814fdb assets/create/models/block/windmill_bearing.json 2f040681214af58a97e70d3a6e77a0fc2e02c624 assets/create/models/block/yellow_nixie_tube.json cf8477d6c7558ceba38416fae755567086a856a6 assets/create/models/block/yellow_sail.json 07b68f0e4c617dfe3e935a1b9e8e020ab3131c0b assets/create/models/block/yellow_seat.json @@ -1609,16 +1672,21 @@ cf8477d6c7558ceba38416fae755567086a856a6 assets/create/models/block/yellow_sail. feb7bd45dc6ec0542c7af648b371e54168641d1e assets/create/models/item/adjustable_chain_gearshift.json be9e4a7937dcb87bce696e6ad234c9eff8cd299e assets/create/models/item/analog_lever.json 626cc26c8a7a2742b991b432c5104981183f1eb6 assets/create/models/item/andesite_alloy.json +158270c9fa3022d1afb56002d0ea1db3366467aa assets/create/models/item/andesite_alloy_block.json +d497fcfe54f9caddf1925cc303f9f9a62015e0ae assets/create/models/item/andesite_bars.json 11c747281cbe2d96324db27fec020100b50977d0 assets/create/models/item/andesite_casing.json -ddb782a38f13bfc7da34c00871b38048a4a08792 assets/create/models/item/andesite_encased_cogwheel.json -6e0bb25ef4ca5b148592c2cddd8c96c9017d999b assets/create/models/item/andesite_encased_large_cogwheel.json +ab09b7886916048add1fa0ea9e87c4644a781031 assets/create/models/item/andesite_door.json +944cbae9f7c4bf7d1734d25645cfa6b0d0f2c33d assets/create/models/item/andesite_encased_cogwheel.json +bb351157b7f6771be05b4cecef17b8610c3810b3 assets/create/models/item/andesite_encased_large_cogwheel.json af792bb7d70029e66cc8aa21ed61322f899fb134 assets/create/models/item/andesite_encased_shaft.json -8ab8027d257d512c369d57a8dcc6fc9077008973 assets/create/models/item/andesite_funnel.json +31c9724ae43519a02f42cebfb0dc1074a66f94ff assets/create/models/item/andesite_funnel.json 113fb6cb131bc3cdf63f558be71b8d77f9ae64c9 assets/create/models/item/andesite_ladder.json f187d676688c728804ab3758eb4b78a431c7ec21 assets/create/models/item/andesite_pillar.json -c541ce58f49adac21bab57114b80e9da8106cf99 assets/create/models/item/andesite_tunnel.json -bd95deec527040a50f28da8855c623b4d8dfc3f2 assets/create/models/item/asurine.json +d0dd86f6c7418c27c0f930cfd20e0867936eca3d assets/create/models/item/andesite_scaffolding.json +d5375c3de6272a00f3e3787fee6b8255f828d686 assets/create/models/item/andesite_tunnel.json +d6eb7105dd9b42adde48bd70e3f2fba70751c1db assets/create/models/item/asurine.json 8b61987c61ae461e4bea0fccf5b1bb3399ac9226 assets/create/models/item/asurine_pillar.json +a8e9fab6ce8dc5da29b451c827663fb553669a23 assets/create/models/item/attribute_filter.json 6913f9acbb272de28387918ce92984fa767b4389 assets/create/models/item/bar_of_chocolate.json def88cd2c79a1f0ed40bbf5a0332187dd1d6006e assets/create/models/item/basin.json 35a1e2cb2645a8386dfee2697b47547b3f9a1dd2 assets/create/models/item/belt_connector.json @@ -1633,18 +1701,21 @@ c31038397821b6abe296d2799aa81edf3c12d095 assets/create/models/item/blaze_burner. de8beb7ef521822eb9b2826806baf1fa3344a45d assets/create/models/item/blue_seat.json a82bc56a503cd15d2354c86a49fc6d1d4ed22767 assets/create/models/item/blue_toolbox.json 2f90f781cd9b5d144a6cfd4748ae3a87c9f12ba8 assets/create/models/item/blue_valve_handle.json +4e711f64e0ab7d16c550cc4aa8b876d604dfb2af assets/create/models/item/brass_bars.json 136f97f26217c51c932d79bf715b2a1a92e6595e assets/create/models/item/brass_block.json c876713c3b8ed6511679d1e3186e6d6031190dd5 assets/create/models/item/brass_casing.json -aeba15ecd6e6f0914b6ce2c0cf5787cb41f856e4 assets/create/models/item/brass_encased_cogwheel.json -fd9b8984bfb2523031c4acc5f8c7f6323dd57568 assets/create/models/item/brass_encased_large_cogwheel.json +378a2f1820c9abdc1080c940e5a01e30c25ea5cb assets/create/models/item/brass_door.json +2bff62a6d695a0affa217569c764e37b584495f9 assets/create/models/item/brass_encased_cogwheel.json +14cae756c604d0ea39f640f7cedc11cd403562f1 assets/create/models/item/brass_encased_large_cogwheel.json 67a6ed2caa2ae35b8a9e81219ab678102c28072d assets/create/models/item/brass_encased_shaft.json -eb6cd761122d76e709362dd6156f9a9351da2d8f assets/create/models/item/brass_funnel.json +185ab66a6338b7b15b30c77470186bde1592b2fe assets/create/models/item/brass_funnel.json 6da5a17e2595ce82fa29dc815250fbdebae7c7ae assets/create/models/item/brass_hand.json dac449cb08713a7c9290ceb0d2669b3fc62a06de assets/create/models/item/brass_ingot.json a51a28424e75dbd11c845f455c778d4c578b9da4 assets/create/models/item/brass_ladder.json 55208677f9135c3ca897c2432caa332bb1b858f2 assets/create/models/item/brass_nugget.json +af97ba84be90381e2cc9434e31e2199c2e7e3aa6 assets/create/models/item/brass_scaffolding.json b78e9274156f5027a9a3b6fb7725c57a7aecc8bb assets/create/models/item/brass_sheet.json -27063d589fe0c14819cac7db34ed29998a8420c1 assets/create/models/item/brass_tunnel.json +28e104d5041c1f4676704c0f6b4e2e80aac43106 assets/create/models/item/brass_tunnel.json fce64539b36fc8a5ffa39d7a3f73765818437cbf assets/create/models/item/brown_seat.json 90c1ec317beed0b5735c8731e3115a695b7060f7 assets/create/models/item/brown_toolbox.json 9477ab491586f1314bebf4d58387425ae56d0bad assets/create/models/item/brown_valve_handle.json @@ -1656,17 +1727,27 @@ a197d08618f4035182c91a6b16031eb681ab8a7c assets/create/models/item/chest_minecar 77654cbd16cdfa95181ea3f85fcfa3cd352b69fd assets/create/models/item/chocolate_glazed_berries.json 6e24ec6cd22448fcf4282563a6612034a4a4a05e assets/create/models/item/chute.json e42f988403c87b0601fa7c5ddc6168d06e91a8a4 assets/create/models/item/cinder_flour.json +f05a7bf70ebc7db3beb4e208269d0ad3c42cc076 assets/create/models/item/clipboard.json +10a5cac35c60dc5ca4ac4eacd311f6779343ebda assets/create/models/item/clipboard_0.json +598b87cd6b411c760c72f63d704944ae7ab8b00d assets/create/models/item/clipboard_1.json +3f00f6dfc3f9e2c601f30649cb6a88a44c330c40 assets/create/models/item/clipboard_2.json 9656ebb104b88231f2582a8a854b3d00383802f9 assets/create/models/item/clockwork_bearing.json 09a557848d21d15a8484b53fda67e9b86ab6b40d assets/create/models/item/clutch.json 83ebd837c4752b23d9dc7e54e54c182b02e0f26d assets/create/models/item/cogwheel.json dcaabf9723d27f154f012fb308edbabf9b3d76dd assets/create/models/item/content_observer.json +de48f4b6fa26928ebc7d5d60e6a0767093430d65 assets/create/models/item/contraption_controls.json 33cfd6dcf11287f5e666c6a4f4af026b9b05f30c assets/create/models/item/controller_rail.json 6a4e8aa37120fa8238be72fb2c732f9ab5670d53 assets/create/models/item/controls.json 68d0bd260e5062448ca9008f7cf44e963d941653 assets/create/models/item/copper_backtank.json 6c53b1a6ed28929b7a0a090edf6101e610f842fc assets/create/models/item/copper_backtank_placeable.json +2a0b31d76ab8a74c458475640d17de15ad314fcd assets/create/models/item/copper_bars.json 688e4dee99126b7507761de618d6788c18f17153 assets/create/models/item/copper_casing.json +68890c027cd6a094b484a237d3ff5daeb09622af assets/create/models/item/copper_diving_boots.json +23499699c6ea6a30673835056f5d0039519413fa assets/create/models/item/copper_diving_helmet.json +0e394c50a977eae45d3d8e6a62e256a5408ac994 assets/create/models/item/copper_door.json 4a849d8ae080dca8bb53c7f53558c76e89e1609e assets/create/models/item/copper_ladder.json ccdf08652511e5737a8489d86ea9422ade4f4ca5 assets/create/models/item/copper_nugget.json +86a770e9b2af1f19bf633f5cfeecd84848f73fbd assets/create/models/item/copper_scaffolding.json a4fd2f4f00e03b2ac5d863e93827d39a984cc2ff assets/create/models/item/copper_sheet.json 13b18ba2938e283d507fbca70518cf52198cdc71 assets/create/models/item/copper_shingles.json 79d9f8667965072f12e51e6601b5c36f8acc125f assets/create/models/item/copper_shingle_slab.json @@ -1675,30 +1756,32 @@ a4fd2f4f00e03b2ac5d863e93827d39a984cc2ff assets/create/models/item/copper_sheet. a7147444fc28a4cce21b6cf38e9528537e27c352 assets/create/models/item/copper_tile_slab.json 7330324d6c64f0340d676ecef83a930515d9130e assets/create/models/item/copper_tile_stairs.json 08c35e85afe4eb2b106133c5d9c7d7c64ca9a915 assets/create/models/item/copper_valve_handle.json +5cec229a3117ea5987aa42288c070427ac48a5dc assets/create/models/item/copycat_panel.json +1b6707005830ca066a7e997c73391ca88c70bdb0 assets/create/models/item/copycat_step.json d042526836aa5261a49557e6c656ee06d6eeb2b0 assets/create/models/item/crafter_slot_cover.json ae5f96175f8b70144a940789aaa3956173906939 assets/create/models/item/crafting_blueprint.json 21ac802aa450b5917f1883e8e3d8b8e2f80bace8 assets/create/models/item/creative_blaze_cake.json 27a8a2681d7a128da49f8c828ffd67a9ec4c9d63 assets/create/models/item/creative_crate.json 01fbc5c7662880fb67a8a38b909b0bd55864a34b assets/create/models/item/creative_fluid_tank.json ad620bd5eb32a41b0a8a130f49ab3dbb398907e5 assets/create/models/item/creative_motor.json -03a39539f5124e0872fc43f1529cb59a8c0edf7e assets/create/models/item/crimsite.json +612778c4a390c3fc9de7ef40713375dc7be85270 assets/create/models/item/crimsite.json e432e359b77e7129e18c1d4daf68d11c4a661110 assets/create/models/item/crimsite_pillar.json 9c77e6d7d56310b34468a6d52080e477e893494d assets/create/models/item/crimson_window.json 43625514f941a61cfbae339419d0de4b22db9662 assets/create/models/item/crimson_window_pane.json -5ca45663ebe86fa950422dbb9b01466b7481fb61 assets/create/models/item/crushed_aluminum_ore.json -2444b785037622848eba0e4c28a4b08e721d092c assets/create/models/item/crushed_copper_ore.json -66ac146278a0f6fbd8786ef54973de43774938e9 assets/create/models/item/crushed_gold_ore.json -1eb56f88fadc6e59ab2a99d4e695f4b6f0b45170 assets/create/models/item/crushed_iron_ore.json -9d5a2184c2cd323ca2b85b7e20f306af4e57d855 assets/create/models/item/crushed_lead_ore.json -9eb46a88b86076c907dadab3e3bfa1bacd721f90 assets/create/models/item/crushed_nickel_ore.json -086bbb62b3d04cba493e6ea79283a6425bdfcd1c assets/create/models/item/crushed_osmium_ore.json -dd716a4af46045021fe5ff8a7a497efc00277dc0 assets/create/models/item/crushed_platinum_ore.json -392262ebebe5f36b14136df479f2a7e111888586 assets/create/models/item/crushed_quicksilver_ore.json -fc1d202bb318061ae8d9f30993bc5aa84d428e66 assets/create/models/item/crushed_silver_ore.json -5b6cb4201eb3af671e415f6b263f80e6d186c9e0 assets/create/models/item/crushed_tin_ore.json -9659c432fdf348c81aaf39b8745eb796eca93c11 assets/create/models/item/crushed_uranium_ore.json -1c5eb12c78687fa35c075845febddff1dadb1d4e assets/create/models/item/crushed_zinc_ore.json -a253eda226cb3bdcd6fb5cd851ea15ea672a1e3b assets/create/models/item/crushing_wheel.json +189ddf2f3c83608ddfe9e8d2fe88d8b4610ade13 assets/create/models/item/crushed_raw_aluminum.json +4e74e066349d0311064e21fd72aa40e249e2e830 assets/create/models/item/crushed_raw_copper.json +513ccb83879e523f8df66a4ad8aee0ecab1ba003 assets/create/models/item/crushed_raw_gold.json +31c4057bbfd7b031f2af98372a18e9e56bbb0d47 assets/create/models/item/crushed_raw_iron.json +f99ca9b4a25aba1ad42f5a704e70a698eb6503e8 assets/create/models/item/crushed_raw_lead.json +22392367f1b654af8551c837b88fbe3e32d20a02 assets/create/models/item/crushed_raw_nickel.json +71127952d026df479327d27c5e4cf8fb521627c2 assets/create/models/item/crushed_raw_osmium.json +0a3e076dd93d08ab874407b542b144c202b75732 assets/create/models/item/crushed_raw_platinum.json +def1684a021949093ab01c638e25cb914f0c085b assets/create/models/item/crushed_raw_quicksilver.json +7af5c88e0218aa446bfb6bfd49fb4d50d79da841 assets/create/models/item/crushed_raw_silver.json +aca5ad87a4e9e3d9518fb89f86c0174b96a7bdca assets/create/models/item/crushed_raw_tin.json +06d5aa86789155cfd00dbd281f2ad281b28822b5 assets/create/models/item/crushed_raw_uranium.json +b6acd86be9e6cac8b9ed2bc6297d27941ca05f46 assets/create/models/item/crushed_raw_zinc.json +b67e95801010eab58de02f2b0160bff3f008bd18 assets/create/models/item/crushing_wheel.json af189b0c04482064520d84546d81af8154824292 assets/create/models/item/cuckoo_clock.json 314fb287c7b16a6478fbefde0da80de8828b684e assets/create/models/item/cut_andesite.json e2840073eac2e6419cd312b3d0177d4c64a5346c assets/create/models/item/cut_andesite_bricks.json @@ -1824,15 +1907,16 @@ aa44d681c3ccffe08aedbda093062b1a5ab3302e assets/create/models/item/depot.json 85a5830ca034be9a0ed534186210aa975278b20b assets/create/models/item/diorite_pillar.json 2a992f0961b8bab5628e075da413c91e903e424c assets/create/models/item/display_board.json 0dd4d33644c9ec7dbf920d7fd7b713e4b413b330 assets/create/models/item/display_link.json -68149ba11c8224bd8c15f52c3d04505d4640d809 assets/create/models/item/diving_boots.json -faa024189d2e552d4224f9941c3f65397e1b0418 assets/create/models/item/diving_helmet.json eb750000addd1c25e79fc9fb277ccdcc3274852c assets/create/models/item/dough.json 5803643723c0aa65d6c531c1f9798556cd36d21a assets/create/models/item/dripstone_pillar.json 97ef1363d4a64103d2ec3b0e8640cf931d0c3f94 assets/create/models/item/electron_tube.json +fa82ee6ea59876a9ea0f02d0fafd102ba26752f8 assets/create/models/item/elevator_contact.json +d6c1c5ff9506a60fbdde4580dad39d97fc1832d3 assets/create/models/item/elevator_pulley.json 890e519d407cab18c04ee439e7d5f67eb4f76ab3 assets/create/models/item/empty_blaze_burner.json badd4326fac0b0a1590a2e9bce7c2cdd4e4562f3 assets/create/models/item/empty_schematic.json 5daa4b49db850923319916aaa9842c33f99e0a00 assets/create/models/item/encased_chain_drive.json 7ec3ed4aaab72d76f6414447bbb3ad7887adf61f assets/create/models/item/encased_fan.json +3e1fdcc80fd68199b1890bcc830f78c48e7c0e43 assets/create/models/item/experience_block.json 9775e83414c0febb5c5b832437b0580e91bcbff3 assets/create/models/item/experience_nugget.json 87add851ae3271d733c9e6888865c288b6716f3b assets/create/models/item/exposed_copper_shingles.json 721c8ac46bf23abec2bbf4cff6dbfdf96cc569a6 assets/create/models/item/exposed_copper_shingle_slab.json @@ -1841,6 +1925,7 @@ fa7ffb172a43774cc07a2bb201e7010a2549001d assets/create/models/item/exposed_coppe a443633d90ef9ac2a866b69b2ecdfad1841dc3e1 assets/create/models/item/exposed_copper_tile_slab.json 9bb425a14635fc8b36a9a95f3d0c54e0b129b7b4 assets/create/models/item/exposed_copper_tile_stairs.json 8b64a93d9b6e33e3caa66adb7a0cc8c5cd473023 assets/create/models/item/extendo_grip.json +dad31483f65baaf187e6553e3cd301c5d69e9db4 assets/create/models/item/filter.json 575047531b8e324df9e58abba79cfe9ee3db8b16 assets/create/models/item/fluid_pipe.json 51d34caaa63685e901b8bfe6ced13ff2e8914ce7 assets/create/models/item/fluid_tank.json 2abb05e5097eab5e4bece05c0e48561ce1b0e59e assets/create/models/item/fluid_valve.json @@ -1873,12 +1958,14 @@ e623c9541adc0fa877c5615e3211f47886383f2d assets/create/models/item/horizontal_fr 58b6f4ec2af3a69ae7145fb25d73451b6e8a2834 assets/create/models/item/hose_pulley.json 14ae1ba5e842715fc4526b19e20c74d10102eb4a assets/create/models/item/incomplete_precision_mechanism.json ae5c5925ecf775a4f5c3dc3c79d9766d7dd34ab6 assets/create/models/item/incomplete_track.json +43173d18384817288a9ba687da77a4fab31b1957 assets/create/models/item/industrial_iron_block.json c6e3e4ca8b3dfdaaa943faa3dc89c0b2e6f2b5c4 assets/create/models/item/iron_sheet.json d1fbf1be53208c3ab5384dfd6be4d980c858941c assets/create/models/item/item_drain.json 908dd0a4eafd868d280e25cfb7721f20b649560f assets/create/models/item/item_vault.json 5fba1fa33e360c2744ec74d7ccb63f9baa295546 assets/create/models/item/jungle_window.json b3a0c9664465f49a2f53e4ded6c29710a357e6ca assets/create/models/item/jungle_window_pane.json 26c3f75074779ec0286e19219bd277147bfb9e96 assets/create/models/item/large_cogwheel.json +23f9028ae83a1723071c67cb6a1742731969e21e assets/create/models/item/large_water_wheel.json 33978f928e1f548a2b53081d6a7517e41d875ec3 assets/create/models/item/layered_andesite.json c4282864fa5dd189b851a2494e55d4cbcb67ad50 assets/create/models/item/layered_asurine.json 1baba6ebcb0d9f9caea736ede395032d91138b7d assets/create/models/item/layered_calcite.json @@ -1899,7 +1986,7 @@ dae914625ff1bc3ebe1463485cad4526a7d7e9f5 assets/create/models/item/light_blue_to 1747bcdea3b1d3f5dfb786102069e07198d36dfe assets/create/models/item/light_gray_seat.json c8513eb1c89652783e26d7dcfcf64afa97619bc8 assets/create/models/item/light_gray_toolbox.json 3774d23e76b5712e7004e333e0a770f2230c2998 assets/create/models/item/light_gray_valve_handle.json -9a124c76d659aced2aaa16f3019d1f1bd58d5cd3 assets/create/models/item/limestone.json +8f53caad3899a30be5087a0ba155080834418cc0 assets/create/models/item/limestone.json fba1e7d1cad39c89976b427db62544d80f47ad5d assets/create/models/item/limestone_pillar.json 32cd55a1c97a31a13ad106a457ec9925aa91f6d3 assets/create/models/item/lime_seat.json 931d187c11cb95a0eeae8f256187ef551b42007e assets/create/models/item/lime_toolbox.json @@ -1909,6 +1996,8 @@ d0f4148bdb0a905e68f54b5dfd829fd47e528fea assets/create/models/item/lime_valve_ha ad6fd371ee989c9c3c21e762273e8a4e903f0af8 assets/create/models/item/magenta_seat.json 7c0e3f91e5ab029473736deffb2b2aab9d4763c7 assets/create/models/item/magenta_toolbox.json 6d82582e5afea919927606b20a74cbda5223956f assets/create/models/item/magenta_valve_handle.json +a4ecba2ee36699401de661b89065bf0738487a87 assets/create/models/item/mangrove_window.json +474c896c4ca4e6547fac225cc204bbc0b287c5ea assets/create/models/item/mangrove_window_pane.json d5b1665cdcf03baef41a8d3fbbdcc747cd6867f8 assets/create/models/item/mechanical_arm.json 95d437fffd455e5a22d288bb7683fbdce211fa8a assets/create/models/item/mechanical_bearing.json 08dcab9d0cdb7fb6426b8dee508eecc3f5d71fb1 assets/create/models/item/mechanical_crafter.json @@ -1919,6 +2008,7 @@ d5b1665cdcf03baef41a8d3fbbdcc747cd6867f8 assets/create/models/item/mechanical_ar a5637c3d0477113ef87311510892256476c30e17 assets/create/models/item/mechanical_plough.json df4da272a430c5af74d7f456278589cf09691eed assets/create/models/item/mechanical_press.json 3a9bdf4c1283a74cb9a70c0089b3b00fb6e0a3c7 assets/create/models/item/mechanical_pump.json +5a69999e11638137b488d4158ab8e659aa9ff32e assets/create/models/item/mechanical_roller.json a897baeb9c43c36ce733991fdb08241ce932d29c assets/create/models/item/mechanical_saw.json 285f49039c8356204d9d19b998da56dd93dbb39d assets/create/models/item/metal_bracket.json 6fea2ff006272a950c229c817ab76c54bdf83837 assets/create/models/item/metal_girder.json @@ -1926,11 +2016,15 @@ e850316869094c83c1479197e1778634a8c5e42b assets/create/models/item/millstone.jso 2735d3a17e7e655736eac0f2799eed954ea0001a assets/create/models/item/minecart_contraption.json fb4dc1f636ffe66b64a8a4179212a1cf798ac58b assets/create/models/item/minecart_coupling.json af189b0c04482064520d84546d81af8154824292 assets/create/models/item/mysterious_cuckoo_clock.json +c11656a940ef54a023634376c742b3fb17201f92 assets/create/models/item/netherite_backtank.json +6c53b1a6ed28929b7a0a090edf6101e610f842fc assets/create/models/item/netherite_backtank_placeable.json +563b6261b042d41f705e41bb2cb3151b1de1feee assets/create/models/item/netherite_diving_boots.json +7d68ea71d2a468260b9eaf72e02f08246ddacb49 assets/create/models/item/netherite_diving_helmet.json f80358eba19bc8d1741e4e25753866799631a118 assets/create/models/item/nixie_tube.json 33c5dfa7ef718fb29cf59bb0c04ebd88cf20eb1c assets/create/models/item/nozzle.json 39626402ba637abced828902d9d657ab09edcadb assets/create/models/item/oak_window.json 061587faf0e53e4fac0c8f2f3bd6b22020b2a3ee assets/create/models/item/oak_window_pane.json -21ef5c891ac03669e3c825bc2e0f946bd7ab31ac assets/create/models/item/ochrum.json +af50363d603d61340b336569d58c1febde253665 assets/create/models/item/ochrum.json 62ec1afee14f9de3f5b02ee930d002a240a3c337 assets/create/models/item/ochrum_pillar.json 56e7d28824d3fc566b5f551babbe423a550ef08c assets/create/models/item/orange_seat.json 96cc543d5afed90a022ece7b8671cd47a9b6fb68 assets/create/models/item/orange_toolbox.json @@ -2044,9 +2138,9 @@ d45005a89e2c0d29944e0112be274365e0e318a5 assets/create/models/item/rose_quartz_t 8b7727844d8c12c3c22828c7f65fc7ac2d273e36 assets/create/models/item/schematicannon.json 2a52f084fa8187dd8da28fe820dde50c47a93b57 assets/create/models/item/schematic_and_quill.json 4c8b34627001e35ee15412a0cd037d0f24ba914e assets/create/models/item/schematic_table.json -e4a68c3e8a6eee3058a119052987f1862f5f0c2d assets/create/models/item/scorchia.json +2955563914c2f84ed06474c135062e91189ddf3a assets/create/models/item/scorchia.json 669041e5ad29d2166cc8895f85aa262040671d3e assets/create/models/item/scorchia_pillar.json -d5675fdeec92ed67cf04621ab47248e4d2f6f58e assets/create/models/item/scoria.json +ff52eb59dadfe675e416440f3115856a501428a6 assets/create/models/item/scoria.json 2b5db844faf2dea0672def113dddbac323ca71e7 assets/create/models/item/scoria_pillar.json ff36a19e124caf2ee8a03767e39601df6866075b assets/create/models/item/secondary_linear_chassis.json 480a7585107ebbfd54f3288eccb68e639790fe3c assets/create/models/item/sequenced_gearshift.json @@ -2120,7 +2214,7 @@ b82ab0c69df330f6f938ed1beee7b4add67d2e50 assets/create/models/item/steam_engine. 24acc593a5e910b6301afcb3f23cba526d23a0ab assets/create/models/item/steam_whistle.json 54f200be903e056e5cf9e2186f0a0a51f8f0f84e assets/create/models/item/sticker.json 0f88de164439640cc175ceef2017f7416b5a7018 assets/create/models/item/sticky_mechanical_piston.json -24daa2871904a5bb24902d0b3d3eea8a5922c59a assets/create/models/item/stockpile_switch.json +4b640b66765b206f8c2884b7c1a1ef860b81d841 assets/create/models/item/stockpile_switch.json 6ee792277b9fd980c40e18e841afa63fc500ed0b assets/create/models/item/stressometer.json 8d4ce1ccf180016506292f63188c10d0dabe0ee3 assets/create/models/item/sturdy_sheet.json a10bb4d6d1a4483a806e3aaa086d48c0e20aaefe assets/create/models/item/super_glue.json @@ -2137,7 +2231,7 @@ ba7a9f542e9f65bdce3d3330a95f1166a0be0673 assets/create/models/item/tree_fertiliz 55aafc103c38057faa3295ccc76da99f4a91de52 assets/create/models/item/tuff_pillar.json 0e199ab3e450156aae2d54c227383af9bb3f7082 assets/create/models/item/turntable.json 3e7f095acd023ec549fe41ceed9fc3997de24a25 assets/create/models/item/unprocessed_obsidian_sheet.json -240bbf789dd5ead15d2584e0d7dac54a56ba99f0 assets/create/models/item/veridium.json +63a159b54de6a31ee265750e4af4b1990820eda6 assets/create/models/item/veridium.json 38970acde350735e00b53e6836ccee428c630fcc assets/create/models/item/veridium_pillar.json 9b2e4da1ab7e20cd744adb469dd3690e33cc905f assets/create/models/item/vertical_framed_glass.json 63d94954704691fccde1b13b320ec62a4e12a13a assets/create/models/item/vertical_framed_glass_pane.json @@ -2145,7 +2239,7 @@ b0f6d37aa695395e28a23d36775092f63ab3f5a5 assets/create/models/item/vertical_gear 011ef16e912638b4095d34c8c711ebd67cb85fba assets/create/models/item/wand_of_symmetry.json 9c5087114e35052c5e56bb752252de5d092408c5 assets/create/models/item/warped_window.json 83502f4b8d0134e793611b36a56cca59af097ed5 assets/create/models/item/warped_window_pane.json -b34e50348a7e80235be32b980f16dfa5262ed5cf assets/create/models/item/water_wheel.json +e5939b47bf7440dc101c667e68ef6bf750a3290f assets/create/models/item/water_wheel.json be2f058a7ecb015599ee052ec27c4360d636999a assets/create/models/item/waxed_copper_shingles.json adc188e4e48bea80607c6e0c7076c9bdd7236cb0 assets/create/models/item/waxed_copper_shingle_slab.json 7e224aceaa94361256e95e4c44d8814aebaf297c assets/create/models/item/waxed_copper_shingle_stairs.json @@ -2183,7 +2277,7 @@ aacced59d21212090d508a9684bb46c9472a8a2f assets/create/models/item/whisk.json 17ed8ac7d745117f622190a46c5e1b42892afc29 assets/create/models/item/white_seat.json 432040f39177ab3df6003df24e818c73e28cf754 assets/create/models/item/white_toolbox.json 8ba8a6d4baf98f0f037f83b4b704f75a8d46a26e assets/create/models/item/white_valve_handle.json -cf1da9216e263f2ea26c58135a01ad70b5ae7be2 assets/create/models/item/windmill_bearing.json +bccccbdfa5d376936e123defa44f2907dc317617 assets/create/models/item/windmill_bearing.json 47c6ad1c146366156a0ec4bc1cbf74282784698f assets/create/models/item/wooden_bracket.json 6c08d2fa59e56e4848063ab6f3e45894b89f1744 assets/create/models/item/wrench.json ac59f141cd3c3f7e57a794e542d6e22bf8ebb8f9 assets/create/models/item/yellow_seat.json @@ -2193,26 +2287,46 @@ bcf63b7198d31d3a94b2566171b7e3e84464601c assets/create/models/item/zinc_block.js d4a3290393c1c659f3d4dd4e267a87d287bd49a6 assets/create/models/item/zinc_ingot.json 1e9656f81ec01a89796b175cf029d1de45b758fe assets/create/models/item/zinc_nugget.json f3719d4d3a8d1e0d9f36db5d1317894ecacf3bf3 assets/create/models/item/zinc_ore.json +63d74987f8461b4e94c00030d380d4891707d2ae assets/create/models/threshold_switch/block_ceiling_0.json +12496e505374e7fff2d1f800218848635d86ec71 assets/create/models/threshold_switch/block_ceiling_1.json +523bc69211b6e90cc381356f103b01b8d7e15771 assets/create/models/threshold_switch/block_ceiling_2.json +c62cbd9fe144326c46702ba4e512c832484ea4e8 assets/create/models/threshold_switch/block_ceiling_3.json +fe1017b4338d3027771d5eb8b4e2444ddb842b36 assets/create/models/threshold_switch/block_ceiling_4.json +d090a659a8df0b86d9892214ac5b06641aaabc9a assets/create/models/threshold_switch/block_ceiling_5.json +dffc869ccce392b1908c833631e3df374c6a3012 assets/create/models/threshold_switch/block_floor_0.json +ab3d51ab5dd8ef6c1cad5d65406180915340dd7e assets/create/models/threshold_switch/block_floor_1.json +7a69fb5a6e77b457c381495c951aa0ba9c7df7f0 assets/create/models/threshold_switch/block_floor_2.json +3a6bbc80eea8d824a981e257f8025997946b3260 assets/create/models/threshold_switch/block_floor_3.json +a76fae0415604615be0e822394e0879ca81bf166 assets/create/models/threshold_switch/block_floor_4.json +28ddae97613f1a06885f06faa20b1b2a5bcaa7db assets/create/models/threshold_switch/block_floor_5.json +ab50d142c25c95b0865dd41176cc07a0c76109ac assets/create/models/threshold_switch/block_wall_0.json +be730f505bf937db4b3658b2bd3763b514d295c2 assets/create/models/threshold_switch/block_wall_1.json +f7f6d92ab5dea5a85ec3d570cdd169329dd4225f assets/create/models/threshold_switch/block_wall_2.json +41009d15d22c946a2ed4c6ba98447c3c7cc26315 assets/create/models/threshold_switch/block_wall_3.json +ad3204842128db2c7bebdbf3c40fccc45c82de44 assets/create/models/threshold_switch/block_wall_4.json +197a6ed7fd9514de13daf58605c24a7156c00bd1 assets/create/models/threshold_switch/block_wall_5.json 59c1c7f291378e9e4ca9978142943aa4bec507db data/create/advancements/recipes/building_blocks/acacia_window.json bfa00dd7eb3d71f2c2649c2ecc17065e877a7bd4 data/create/advancements/recipes/building_blocks/acacia_window_pane.json -2eefefa8b8885786f296bde1451ed5f6245444ed data/create/advancements/recipes/building_blocks/andesite_pillar_from_andesite_stonecutting.json +e9be13270e548bab1efa783297ecd542f1131a64 data/create/advancements/recipes/building_blocks/andesite_from_stone_types_andesite_stonecutting.json fdddf63ddd501b57deba33fae92fc9870b0613e2 data/create/advancements/recipes/building_blocks/andesite_pillar_from_stone_types_andesite_stonecutting.json -9d8a0267e8656efa1982f0c875f347300ce17e79 data/create/advancements/recipes/building_blocks/asurine_pillar_from_asurine_stonecutting.json +8ea872ceefe468103c7e3a2a202f1ff5c36f9c7b data/create/advancements/recipes/building_blocks/asurine_from_stone_types_asurine_stonecutting.json cf3c9bb7ebb89e695b09e89e53e9c956c6ee098e data/create/advancements/recipes/building_blocks/asurine_pillar_from_stone_types_asurine_stonecutting.json 25da416d2c0b1ede72a2acafff9313f8aa06b88a data/create/advancements/recipes/building_blocks/birch_window.json 77ca712c533da5849a44e50ece9b6c973cb255b7 data/create/advancements/recipes/building_blocks/birch_window_pane.json -6e5255d06209867c54bd531f6f1c4b78830d7e29 data/create/advancements/recipes/building_blocks/calcite_pillar_from_calcite_stonecutting.json +e8e507e2981114d79c7cdc6a63cd0cfc5eb588fb data/create/advancements/recipes/building_blocks/calcite_from_stone_types_calcite_stonecutting.json ef61bc5be05186488d225af223348e83af61388b data/create/advancements/recipes/building_blocks/calcite_pillar_from_stone_types_calcite_stonecutting.json -ef7d276010ae99b6c58156d05f9850fb867f0dd1 data/create/advancements/recipes/building_blocks/copper_shingles_from_plates_copper_stonecutting.json +534a957912e3f6e6418765479a2739670f680d6a data/create/advancements/recipes/building_blocks/copper_shingles_from_ingots_copper_stonecutting.json abff4ac821c5a8381450290652d7a5b06b22323d data/create/advancements/recipes/building_blocks/copper_shingle_slab.json 4e75e2ec0c2a38933763a195e9a22b9724cee621 data/create/advancements/recipes/building_blocks/copper_shingle_slab_from_copper_shingles_stonecutting.json 1d6584da36f0ab13a9115f152edb3b8a9f56bba3 data/create/advancements/recipes/building_blocks/copper_shingle_stairs.json d49e06b0ac01376f9181d843f28336fc62db4fbe data/create/advancements/recipes/building_blocks/copper_shingle_stairs_from_copper_shingles_stonecutting.json -4b32adeceabe4e24933872027562851663ab0b63 data/create/advancements/recipes/building_blocks/copper_tiles_from_plates_copper_stonecutting.json +bfb8ef530386edbbb0d5759d9e2b320e0084c2b7 data/create/advancements/recipes/building_blocks/copper_tiles_from_ingots_copper_stonecutting.json 7c679df626dfdc5c4b8d4aedba173f39ceffe96c data/create/advancements/recipes/building_blocks/copper_tile_slab.json 8e7bc4261031c0de44dbc2da7675c8789ec65084 data/create/advancements/recipes/building_blocks/copper_tile_slab_from_copper_tiles_stonecutting.json 96b1f1da1e7e1130f73adc7669d915bc075f966c data/create/advancements/recipes/building_blocks/copper_tile_stairs.json 0976b6dcdbb42277f7547bbeff7f6bd0e7ee6c64 data/create/advancements/recipes/building_blocks/copper_tile_stairs_from_copper_tiles_stonecutting.json +0c72fe88dd96eb446bb1cbcf687c4d6481abc2e8 data/create/advancements/recipes/building_blocks/copycat_panel_from_ingots_zinc_stonecutting.json +f6d1ec97f93b0270da7c3bf5b666ac117ad3076c data/create/advancements/recipes/building_blocks/copycat_step_from_ingots_zinc_stonecutting.json 47f9eede564a3a7db56468ac8c6fd5980a9fa96a data/create/advancements/recipes/building_blocks/crafting/copper/waxed_copper_shingles_from_honeycomb.json 6631f01c66a3358ca3f9fa8c6b7cae35e7c90f6d data/create/advancements/recipes/building_blocks/crafting/copper/waxed_copper_shingle_slab_from_honeycomb.json 612ac623c661376aaa14f4b6785845f6c2d87c9f data/create/advancements/recipes/building_blocks/crafting/copper/waxed_copper_shingle_stairs_from_honeycomb.json @@ -2237,353 +2351,273 @@ b4c198189ee25a6228b58cea27ea6018bef889dc data/create/advancements/recipes/buildi 6cb21b4e9db83313dc0e09c4cf079347639e2de9 data/create/advancements/recipes/building_blocks/crafting/copper/waxed_weathered_copper_tiles_from_honeycomb.json 9b3c2b22d161670b004bd55b92287a0ca9029cdb data/create/advancements/recipes/building_blocks/crafting/copper/waxed_weathered_copper_tile_slab_from_honeycomb.json c7155f56b7d31f5f8f6bb284fb71b39019d967a1 data/create/advancements/recipes/building_blocks/crafting/copper/waxed_weathered_copper_tile_stairs_from_honeycomb.json -ff7608f0da2f5b94c4df8132c6da7bd7d9764801 data/create/advancements/recipes/building_blocks/crimsite_pillar_from_crimsite_stonecutting.json +3f256f95ccf0acdf47d05893ee4e21d3c7df2c0c data/create/advancements/recipes/building_blocks/crafting/kinetics/black_seat.json +6c41c0225fa2fdd6c52405c6d3c38414fd676aa9 data/create/advancements/recipes/building_blocks/crafting/kinetics/black_seat_from_other_seat.json +988d6bb62ca303051a3898632a175cbda12ae289 data/create/advancements/recipes/building_blocks/crafting/kinetics/blue_seat.json +bd1348d231e7c2d306e9cc8a760143bd6cfffb73 data/create/advancements/recipes/building_blocks/crafting/kinetics/blue_seat_from_other_seat.json +5d729ff1a81a3a0118f5949aaa1111489f88e4ec data/create/advancements/recipes/building_blocks/crafting/kinetics/brown_seat.json +722a52c3a8c23fcbbbc08177ab135ca40c58f53a data/create/advancements/recipes/building_blocks/crafting/kinetics/brown_seat_from_other_seat.json +69768ed726ff11680beceb15f34f8a52ba3b6b67 data/create/advancements/recipes/building_blocks/crafting/kinetics/cyan_seat.json +794f03e20084b9fc0d65dfe60b21a34e6e0002ec data/create/advancements/recipes/building_blocks/crafting/kinetics/cyan_seat_from_other_seat.json +2696a3b8645fd09d830cf7d7a76f5aab54dcd02e data/create/advancements/recipes/building_blocks/crafting/kinetics/gray_seat.json +e55d3bca5ac8090d46ab18b5b768bdd135f3e8ed data/create/advancements/recipes/building_blocks/crafting/kinetics/gray_seat_from_other_seat.json +540b652774130e8ad707cb0f79a9397857408563 data/create/advancements/recipes/building_blocks/crafting/kinetics/green_seat.json +717ab89326073d9327767f65c9ef8f0ebca7a02e data/create/advancements/recipes/building_blocks/crafting/kinetics/green_seat_from_other_seat.json +93374c0d142ce125b86a7017308eb3da50415a23 data/create/advancements/recipes/building_blocks/crafting/kinetics/light_blue_seat.json +64193680060042e4069497b1ead22470ce1912f8 data/create/advancements/recipes/building_blocks/crafting/kinetics/light_blue_seat_from_other_seat.json +b2da019020d8feabf57b3d0cedc3e9ecb7331272 data/create/advancements/recipes/building_blocks/crafting/kinetics/light_gray_seat.json +b7e1966db2269995ffa1065a0aeaa6e47e1eda9d data/create/advancements/recipes/building_blocks/crafting/kinetics/light_gray_seat_from_other_seat.json +481daedd0b8fe95ae10efc38fa34e0bc800512d3 data/create/advancements/recipes/building_blocks/crafting/kinetics/lime_seat.json +4b9f96c0171731bee73512314f7c5d18552601ab data/create/advancements/recipes/building_blocks/crafting/kinetics/lime_seat_from_other_seat.json +847bc1e330f0c20b728f2c4b1709a34f4322f169 data/create/advancements/recipes/building_blocks/crafting/kinetics/magenta_seat.json +8f42db87f1767fa6fd2847374be3646d72934e7d data/create/advancements/recipes/building_blocks/crafting/kinetics/magenta_seat_from_other_seat.json +7bde8a042ceeeacf716b6b161bafed6d65bade5d data/create/advancements/recipes/building_blocks/crafting/kinetics/orange_seat.json +3148ec4ccf8eb6894f4457a0aa73c89944016a8d data/create/advancements/recipes/building_blocks/crafting/kinetics/orange_seat_from_other_seat.json +6f9dfb04857f7e442848fa8daab13a28ca35199c data/create/advancements/recipes/building_blocks/crafting/kinetics/pink_seat.json +e8bad3149b616f469e7173e9cd03656f146cdadb data/create/advancements/recipes/building_blocks/crafting/kinetics/pink_seat_from_other_seat.json +6b0f3cbd721e042b6541c1d1eb9fa98afec3c3b7 data/create/advancements/recipes/building_blocks/crafting/kinetics/purple_seat.json +77cc0fed3db9f111dfb453d252a0ea5c2f92f183 data/create/advancements/recipes/building_blocks/crafting/kinetics/purple_seat_from_other_seat.json +db8494bbd886ca1639541e4d85699d3300da274b data/create/advancements/recipes/building_blocks/crafting/kinetics/red_seat.json +98427f485f606219f1d189b34d4af72bf2a2d248 data/create/advancements/recipes/building_blocks/crafting/kinetics/red_seat_from_other_seat.json +4a7001a6af435f49a993af706e0b81074d080147 data/create/advancements/recipes/building_blocks/crafting/kinetics/white_seat.json +3b63ced7008a10c802ea5bb30e9a8e040e4b6e53 data/create/advancements/recipes/building_blocks/crafting/kinetics/white_seat_from_other_seat.json +46f6347035596f6cbb8a19aacfe4c89e8ad82ba8 data/create/advancements/recipes/building_blocks/crafting/kinetics/yellow_seat.json +fe5e4d607d6a26ada2e51fc8481a3ce5aea8d3c1 data/create/advancements/recipes/building_blocks/crafting/kinetics/yellow_seat_from_other_seat.json +e53266c2bd1db17197d0d534c647ca78e9d98019 data/create/advancements/recipes/building_blocks/crimsite_from_stone_types_crimsite_stonecutting.json 16ce341b487f5002196918dabbf302c3da3538c6 data/create/advancements/recipes/building_blocks/crimsite_pillar_from_stone_types_crimsite_stonecutting.json 2652b6913e74ec8a703cabf9c8cfdb6d3ca2d0bf data/create/advancements/recipes/building_blocks/crimson_window.json 5dbb30639d0fe95348b6c322a947b2bc0b896a2f data/create/advancements/recipes/building_blocks/crimson_window_pane.json -56561ed49a403cea4f29e2625c52b846e508ad49 data/create/advancements/recipes/building_blocks/cut_andesite_bricks_from_andesite_stonecutting.json 708ac3126d72b122422bbfa45ac403b9a2214666 data/create/advancements/recipes/building_blocks/cut_andesite_bricks_from_stone_types_andesite_stonecutting.json 0b2e1484b37f4b26ba87df25ca3dc4f38e34cde1 data/create/advancements/recipes/building_blocks/cut_andesite_brick_slab.json -17cec491ecca38cf4a9fa0cd6c23e932c351ed97 data/create/advancements/recipes/building_blocks/cut_andesite_brick_slab_from_andesite_stonecutting.json aa24b9647ca5ff054ddc53ee17d56aa3759e43c9 data/create/advancements/recipes/building_blocks/cut_andesite_brick_slab_from_stone_types_andesite_stonecutting.json 306461ec050c1a8ce6ed13f25c0b9a64927612cb data/create/advancements/recipes/building_blocks/cut_andesite_brick_slab_recycling.json df9ca9fdceb1d078321573f0b6e0a3a635cd9783 data/create/advancements/recipes/building_blocks/cut_andesite_brick_stairs.json -21d87c6ce372424c82452bc0c8409148b00f18b1 data/create/advancements/recipes/building_blocks/cut_andesite_brick_stairs_from_andesite_stonecutting.json 7112575113cd0d665cdd74286f80d941fab9a495 data/create/advancements/recipes/building_blocks/cut_andesite_brick_stairs_from_stone_types_andesite_stonecutting.json e779e799d4a12c6dbed33826844471197189101d data/create/advancements/recipes/building_blocks/cut_andesite_brick_wall.json -5b336b46dce710e45e0459a21440d1d6f004751c data/create/advancements/recipes/building_blocks/cut_andesite_brick_wall_from_andesite_stonecutting.json e5fe278f1d85c4de71c742b561ec3c8ef3f4edcc data/create/advancements/recipes/building_blocks/cut_andesite_brick_wall_from_stone_types_andesite_stonecutting.json -79cefdc7ec2ee5fd1600ce5a4835d7a61c0a5dae data/create/advancements/recipes/building_blocks/cut_andesite_from_andesite_stonecutting.json 15fc1adaf5cd5456e7fd83faee6be0cd87767d72 data/create/advancements/recipes/building_blocks/cut_andesite_from_stone_types_andesite_stonecutting.json 09bb56d4f758e8d8370e43958b63b69aa03d0942 data/create/advancements/recipes/building_blocks/cut_andesite_slab.json -bdcbe940d65b2bb1298a4c100696c1f1f9532af0 data/create/advancements/recipes/building_blocks/cut_andesite_slab_from_andesite_stonecutting.json bddad75d8e87ea1da4ab05750d2c865e59aa002a data/create/advancements/recipes/building_blocks/cut_andesite_slab_from_stone_types_andesite_stonecutting.json 7d5114c22d7f918577994f27b0a2715081206399 data/create/advancements/recipes/building_blocks/cut_andesite_slab_recycling.json 5a589ca3ab88bae2bd39010d419d66e59fab188d data/create/advancements/recipes/building_blocks/cut_andesite_stairs.json -54487c32b2eed979065e0ee8872b7abc495baecd data/create/advancements/recipes/building_blocks/cut_andesite_stairs_from_andesite_stonecutting.json 0f61aa2d78881eb02c90b0f0b95fb60fc2eab4b3 data/create/advancements/recipes/building_blocks/cut_andesite_stairs_from_stone_types_andesite_stonecutting.json b4890d0feacd4957b95ce63d2a0f99650890719d data/create/advancements/recipes/building_blocks/cut_andesite_wall.json -dc162932e5fb89b1a21a5d2c8956537ea5884820 data/create/advancements/recipes/building_blocks/cut_andesite_wall_from_andesite_stonecutting.json 3a8ac226e7a56e528e0f368e3266c109362728dd data/create/advancements/recipes/building_blocks/cut_andesite_wall_from_stone_types_andesite_stonecutting.json -d9c14cdabef2e3163441cfd411b1e865c5166294 data/create/advancements/recipes/building_blocks/cut_asurine_bricks_from_asurine_stonecutting.json 5dadaf62f6ec649663d70b558c3d04a2f7ae7cc7 data/create/advancements/recipes/building_blocks/cut_asurine_bricks_from_stone_types_asurine_stonecutting.json cba88968955e066522f9cc90ddc588628614e074 data/create/advancements/recipes/building_blocks/cut_asurine_brick_slab.json -5344eab09b4c07c66c1e323ec93a896734cd939a data/create/advancements/recipes/building_blocks/cut_asurine_brick_slab_from_asurine_stonecutting.json 0b0d5a1d2e29786960845a113be30c044b528b89 data/create/advancements/recipes/building_blocks/cut_asurine_brick_slab_from_stone_types_asurine_stonecutting.json 0149e2ab1b841ed9389d71163806de06532e90f4 data/create/advancements/recipes/building_blocks/cut_asurine_brick_slab_recycling.json 702ca91d575f411ad5c4cfa4f44a872ea34ea340 data/create/advancements/recipes/building_blocks/cut_asurine_brick_stairs.json -4dcab177c2d604e88812c01339b8f5db3f76f7a7 data/create/advancements/recipes/building_blocks/cut_asurine_brick_stairs_from_asurine_stonecutting.json 492916c176a370ad34ffc3d8d77baae404a8ee93 data/create/advancements/recipes/building_blocks/cut_asurine_brick_stairs_from_stone_types_asurine_stonecutting.json aa2b82480a69ffc8968de09b39fb19ab9be47eac data/create/advancements/recipes/building_blocks/cut_asurine_brick_wall.json -1c8fabcd814dd47b244c8c8bb7eac40d98637f94 data/create/advancements/recipes/building_blocks/cut_asurine_brick_wall_from_asurine_stonecutting.json 39e8e6e1df10792369f1ddb4405cba2eeeb953b2 data/create/advancements/recipes/building_blocks/cut_asurine_brick_wall_from_stone_types_asurine_stonecutting.json -8bb4220979b29c1dcb7bb89ec1ca516a4b583036 data/create/advancements/recipes/building_blocks/cut_asurine_from_asurine_stonecutting.json f23c4e2bd710c96387abfdd0facc0944578d83dc data/create/advancements/recipes/building_blocks/cut_asurine_from_stone_types_asurine_stonecutting.json 5f153a15d33907059ad8a44fb9933d740913d134 data/create/advancements/recipes/building_blocks/cut_asurine_slab.json -123cf0cf1fff979e8977f8972754e27494d37550 data/create/advancements/recipes/building_blocks/cut_asurine_slab_from_asurine_stonecutting.json 66ac215c3a782d258a9c954a4fe85488d31c3301 data/create/advancements/recipes/building_blocks/cut_asurine_slab_from_stone_types_asurine_stonecutting.json c3ea11fc1e0d6e966389bec4a97b46829f5cbc6e data/create/advancements/recipes/building_blocks/cut_asurine_slab_recycling.json 9fe9aa4eb44ffccecb84e493b429053887ec1110 data/create/advancements/recipes/building_blocks/cut_asurine_stairs.json -05f0625d50b4521d59ea6561e5ccae84edea04bf data/create/advancements/recipes/building_blocks/cut_asurine_stairs_from_asurine_stonecutting.json fe1199da4db28e7bcee4565c9fe48f7c7cfef5a4 data/create/advancements/recipes/building_blocks/cut_asurine_stairs_from_stone_types_asurine_stonecutting.json 53a4338d5072996de61bac224d48b0ae8d4c5e95 data/create/advancements/recipes/building_blocks/cut_asurine_wall.json -3b0f12a97c38e555398423beab1ba41b5be75fb6 data/create/advancements/recipes/building_blocks/cut_asurine_wall_from_asurine_stonecutting.json 6fabd216f093e6248fefdf84abbe8cc760dd4444 data/create/advancements/recipes/building_blocks/cut_asurine_wall_from_stone_types_asurine_stonecutting.json -212959de90b53c9087c588e2c9e1725790f23de2 data/create/advancements/recipes/building_blocks/cut_calcite_bricks_from_calcite_stonecutting.json 284b7c402a62eb4b88bced25dd788b4d1d8bb780 data/create/advancements/recipes/building_blocks/cut_calcite_bricks_from_stone_types_calcite_stonecutting.json 7ae1099c47a34f8cef3a9d23382a64a1f2a69247 data/create/advancements/recipes/building_blocks/cut_calcite_brick_slab.json -5d613f80bd68b6550778900868aced1a67038cb6 data/create/advancements/recipes/building_blocks/cut_calcite_brick_slab_from_calcite_stonecutting.json 733924da5125fccd4fe2548d53a722cef5e3c4d0 data/create/advancements/recipes/building_blocks/cut_calcite_brick_slab_from_stone_types_calcite_stonecutting.json a532d6f958dffa4fba38c02edd45ead7be781aae data/create/advancements/recipes/building_blocks/cut_calcite_brick_slab_recycling.json b414d2a3d35a010d2bba7bee0c585400d022ba56 data/create/advancements/recipes/building_blocks/cut_calcite_brick_stairs.json -acab5b98215f04a669c754b54768ddc4fbfe7736 data/create/advancements/recipes/building_blocks/cut_calcite_brick_stairs_from_calcite_stonecutting.json cdc6d74e43c2eb2324b0fd6943dbba68654556c8 data/create/advancements/recipes/building_blocks/cut_calcite_brick_stairs_from_stone_types_calcite_stonecutting.json 11b9f64328e03ebf8f44a15ff57c93057622b3db data/create/advancements/recipes/building_blocks/cut_calcite_brick_wall.json -15a63e60699dc262e5b0a7e5aa62faa6e6fe2b6a data/create/advancements/recipes/building_blocks/cut_calcite_brick_wall_from_calcite_stonecutting.json 90fff2ca15d728192a710901cda78ee94a95b8b6 data/create/advancements/recipes/building_blocks/cut_calcite_brick_wall_from_stone_types_calcite_stonecutting.json -e7814cecbbb59e943443db241ff8af93828620bc data/create/advancements/recipes/building_blocks/cut_calcite_from_calcite_stonecutting.json 6cf01b382487d445ab194f5c3134fc57059b8d2a data/create/advancements/recipes/building_blocks/cut_calcite_from_stone_types_calcite_stonecutting.json 82e6cf4332106c4ce56f06fd8f6e9d891066c600 data/create/advancements/recipes/building_blocks/cut_calcite_slab.json -d2de637abb56a85ad2fcea2239c22a362c1231bd data/create/advancements/recipes/building_blocks/cut_calcite_slab_from_calcite_stonecutting.json fd6a0027a03865ac8c979efcf7e5acd58cec97a7 data/create/advancements/recipes/building_blocks/cut_calcite_slab_from_stone_types_calcite_stonecutting.json 97cc22fc946f7a78d74f4f69e47f472a830efc12 data/create/advancements/recipes/building_blocks/cut_calcite_slab_recycling.json f83c60a9cf5be56108b5fbab1627e8a37ced68bb data/create/advancements/recipes/building_blocks/cut_calcite_stairs.json -d489be901acab2333da4096faa17abf6bdd46bad data/create/advancements/recipes/building_blocks/cut_calcite_stairs_from_calcite_stonecutting.json c5d76d3fe9df6b0b612e14af5e38ef6a52154750 data/create/advancements/recipes/building_blocks/cut_calcite_stairs_from_stone_types_calcite_stonecutting.json 779736acebdb449b52eda5482a0eede6ac3dd87b data/create/advancements/recipes/building_blocks/cut_calcite_wall.json -d991090a8d2aea8e987a3036275c2c3349900823 data/create/advancements/recipes/building_blocks/cut_calcite_wall_from_calcite_stonecutting.json 39030f771cdb9c66eacdb1fd4f614ca4207cd460 data/create/advancements/recipes/building_blocks/cut_calcite_wall_from_stone_types_calcite_stonecutting.json -a2fef7e28a04b1ea385df72f847325e5e65e8005 data/create/advancements/recipes/building_blocks/cut_crimsite_bricks_from_crimsite_stonecutting.json 383acca53bfa1796d92f44a3f463f508cb820b21 data/create/advancements/recipes/building_blocks/cut_crimsite_bricks_from_stone_types_crimsite_stonecutting.json 4581ccfe72f3cc57db03e8a1fa8f6b3331e6fe13 data/create/advancements/recipes/building_blocks/cut_crimsite_brick_slab.json -8f9807664d74ef69bcbd00bdd3d25367af1b34cd data/create/advancements/recipes/building_blocks/cut_crimsite_brick_slab_from_crimsite_stonecutting.json 2410b456788ec8d0be02b9e76a7fca556cabca87 data/create/advancements/recipes/building_blocks/cut_crimsite_brick_slab_from_stone_types_crimsite_stonecutting.json 75d8b6e4d97434d6b558937958ff0be74c55752d data/create/advancements/recipes/building_blocks/cut_crimsite_brick_slab_recycling.json 4498fa30c26edd0d2d71639547b766b1043b717a data/create/advancements/recipes/building_blocks/cut_crimsite_brick_stairs.json -5ebc75ed56cd332e74a27444e0b591258296f67b data/create/advancements/recipes/building_blocks/cut_crimsite_brick_stairs_from_crimsite_stonecutting.json ecaff640603e0587965788c0a5c65b46bda0aa6d data/create/advancements/recipes/building_blocks/cut_crimsite_brick_stairs_from_stone_types_crimsite_stonecutting.json 97d0c94525c04a97577b60dece1ddb2a4aaac7d1 data/create/advancements/recipes/building_blocks/cut_crimsite_brick_wall.json -ca547583c2c6a413b3cfcc0b9ea2d57953efc57b data/create/advancements/recipes/building_blocks/cut_crimsite_brick_wall_from_crimsite_stonecutting.json b35546df16e9d29bc7086a352819074dbbe04761 data/create/advancements/recipes/building_blocks/cut_crimsite_brick_wall_from_stone_types_crimsite_stonecutting.json -cd6a8a3462f6b7e739ba01280848d980ae03cb51 data/create/advancements/recipes/building_blocks/cut_crimsite_from_crimsite_stonecutting.json 310c2feb52093d45bd00103ed0eefb7d72120780 data/create/advancements/recipes/building_blocks/cut_crimsite_from_stone_types_crimsite_stonecutting.json 3365d6bc10fbf2ae6f27459e9836789ce68db222 data/create/advancements/recipes/building_blocks/cut_crimsite_slab.json -13e6f1d70eae8e107b85a773626776f444ae1ad5 data/create/advancements/recipes/building_blocks/cut_crimsite_slab_from_crimsite_stonecutting.json 26293949d6f5dbae7d528a366501257bc4e698dd data/create/advancements/recipes/building_blocks/cut_crimsite_slab_from_stone_types_crimsite_stonecutting.json 30a08e737e68357717e881762ddc47d520c7b629 data/create/advancements/recipes/building_blocks/cut_crimsite_slab_recycling.json 55dfa898f2c1a784f3558ea35cf104ace0c2729e data/create/advancements/recipes/building_blocks/cut_crimsite_stairs.json -a3b51a32f1101e5244030c6eee269c2acb3f51e5 data/create/advancements/recipes/building_blocks/cut_crimsite_stairs_from_crimsite_stonecutting.json b5edac3f3466640c80ae0fcba02da0c3b73df95a data/create/advancements/recipes/building_blocks/cut_crimsite_stairs_from_stone_types_crimsite_stonecutting.json 9c1c4ea38f486b1cbaa9cd85ead6cc43dacf9c45 data/create/advancements/recipes/building_blocks/cut_crimsite_wall.json -e22bc7f9e7d833308b6aae1ba068a86bfbfd6b35 data/create/advancements/recipes/building_blocks/cut_crimsite_wall_from_crimsite_stonecutting.json a1921b19b9457e3641867c2941070c0ae69fc0cb data/create/advancements/recipes/building_blocks/cut_crimsite_wall_from_stone_types_crimsite_stonecutting.json -0093bd41ee9dc1555fd680deda20495344195f27 data/create/advancements/recipes/building_blocks/cut_deepslate_bricks_from_deepslate_stonecutting.json c3fdf1643bfe035da5870df1873a5e2e0883218d data/create/advancements/recipes/building_blocks/cut_deepslate_bricks_from_stone_types_deepslate_stonecutting.json 6e7e83ea1d9f6b379ce7db3c598db9f4cbb98675 data/create/advancements/recipes/building_blocks/cut_deepslate_brick_slab.json -11fdb31286dd90ecb931cad7deef60d7a50b4959 data/create/advancements/recipes/building_blocks/cut_deepslate_brick_slab_from_deepslate_stonecutting.json e2b8b4a7afcd705abfd75b5c9b0861ab01d115c9 data/create/advancements/recipes/building_blocks/cut_deepslate_brick_slab_from_stone_types_deepslate_stonecutting.json b4b8a0eb229abce4a0c9d761e9da37087f66c2ac data/create/advancements/recipes/building_blocks/cut_deepslate_brick_slab_recycling.json c7df63690b9c73c43cf93611fb3a3e22dca95339 data/create/advancements/recipes/building_blocks/cut_deepslate_brick_stairs.json -326e398fc2d05044b8c445f754e728ca59864fa4 data/create/advancements/recipes/building_blocks/cut_deepslate_brick_stairs_from_deepslate_stonecutting.json cdc335c4386681c67d54e5786caae2c5146b78f3 data/create/advancements/recipes/building_blocks/cut_deepslate_brick_stairs_from_stone_types_deepslate_stonecutting.json 88a721cd2e0bdae836a7bbf9e1fe21edd3d9f4ad data/create/advancements/recipes/building_blocks/cut_deepslate_brick_wall.json -48341b4a62da271cfb4150c3e45cd553ac61f090 data/create/advancements/recipes/building_blocks/cut_deepslate_brick_wall_from_deepslate_stonecutting.json a4f9b6946e6d1ecc58917342a16714a217dcf383 data/create/advancements/recipes/building_blocks/cut_deepslate_brick_wall_from_stone_types_deepslate_stonecutting.json -41e169cef8648a4bb2abe52361644194acd43a91 data/create/advancements/recipes/building_blocks/cut_deepslate_from_deepslate_stonecutting.json 1ba32ee6c39d65577d34046893e56e393f9f1d35 data/create/advancements/recipes/building_blocks/cut_deepslate_from_stone_types_deepslate_stonecutting.json 9e55733c80762ae531fba22fa829b30a448b0f25 data/create/advancements/recipes/building_blocks/cut_deepslate_slab.json -8b293d572e4d471c96e578a22df342595cbddb7d data/create/advancements/recipes/building_blocks/cut_deepslate_slab_from_deepslate_stonecutting.json 91fd9447a1956930989c6c27ae085a9e2d02543f data/create/advancements/recipes/building_blocks/cut_deepslate_slab_from_stone_types_deepslate_stonecutting.json 9e89809bc079b1ef37ae8957fa04bb8120aa0b89 data/create/advancements/recipes/building_blocks/cut_deepslate_slab_recycling.json 35db33f42eaf2195284433cc183a35e192933472 data/create/advancements/recipes/building_blocks/cut_deepslate_stairs.json -0a7e9fe5014033ccd8feea9615e9b60b6c05a0e9 data/create/advancements/recipes/building_blocks/cut_deepslate_stairs_from_deepslate_stonecutting.json d1d48964172cc0e9597f96a140c14e216fadd98b data/create/advancements/recipes/building_blocks/cut_deepslate_stairs_from_stone_types_deepslate_stonecutting.json a7aa30e5ebd9ce9cfe3a96a64289ac1cdf452243 data/create/advancements/recipes/building_blocks/cut_deepslate_wall.json -d152fb611d31b1144fed0ba0797c080b3b61482c data/create/advancements/recipes/building_blocks/cut_deepslate_wall_from_deepslate_stonecutting.json f499128e6724523b07b2b2ff892224d11f026e50 data/create/advancements/recipes/building_blocks/cut_deepslate_wall_from_stone_types_deepslate_stonecutting.json -47122a1b3398920f4a1abdff86773c3303818735 data/create/advancements/recipes/building_blocks/cut_diorite_bricks_from_diorite_stonecutting.json 39327fe977fd95b4258b1c97d1c60f6b0684a562 data/create/advancements/recipes/building_blocks/cut_diorite_bricks_from_stone_types_diorite_stonecutting.json a9623d6c71b7b386dba519cddd508266a6f46816 data/create/advancements/recipes/building_blocks/cut_diorite_brick_slab.json -ffa1a61f077ddfbe6981bafbfd8c68c05c87cb7a data/create/advancements/recipes/building_blocks/cut_diorite_brick_slab_from_diorite_stonecutting.json 79999ab8a8ecffbfad1769777cd8611be30fb8df data/create/advancements/recipes/building_blocks/cut_diorite_brick_slab_from_stone_types_diorite_stonecutting.json 07cf9a3a9345c4102916ab4a8c524869f57c082b data/create/advancements/recipes/building_blocks/cut_diorite_brick_slab_recycling.json 6eadd400cee51bc64af1217690fc700a93cb49f1 data/create/advancements/recipes/building_blocks/cut_diorite_brick_stairs.json -2d158c8dd797ef993cffc8db86272b149ace02cf data/create/advancements/recipes/building_blocks/cut_diorite_brick_stairs_from_diorite_stonecutting.json 586e3dd71cab20d8163097dfb6a74e069958d35d data/create/advancements/recipes/building_blocks/cut_diorite_brick_stairs_from_stone_types_diorite_stonecutting.json 0cc127dc6859b1b289344a083cb10313ba4f48f7 data/create/advancements/recipes/building_blocks/cut_diorite_brick_wall.json -0268df0c27906a6f6177ab8ee0e08da0c7a894d8 data/create/advancements/recipes/building_blocks/cut_diorite_brick_wall_from_diorite_stonecutting.json 7574be2a077307389027e2e48ca18090511be1a7 data/create/advancements/recipes/building_blocks/cut_diorite_brick_wall_from_stone_types_diorite_stonecutting.json -d25a7aeb5a183c15aac958d6b4faf47a1bf04a68 data/create/advancements/recipes/building_blocks/cut_diorite_from_diorite_stonecutting.json 837fd66c341b9bb1b39ae959ec9b93962d3d7678 data/create/advancements/recipes/building_blocks/cut_diorite_from_stone_types_diorite_stonecutting.json d1f26286e4b1f86f80095e68749c49c09a0524c2 data/create/advancements/recipes/building_blocks/cut_diorite_slab.json -cfaf281b28870310d30fb0cfc9bc19271353a347 data/create/advancements/recipes/building_blocks/cut_diorite_slab_from_diorite_stonecutting.json 36a47132e7345646c38d196e2484ba85aeef1179 data/create/advancements/recipes/building_blocks/cut_diorite_slab_from_stone_types_diorite_stonecutting.json 4fd0d42f5b12b156e098addd0f37658fd2b6d173 data/create/advancements/recipes/building_blocks/cut_diorite_slab_recycling.json 9789c93d92a97cd220f979fea4760d6a4be54c16 data/create/advancements/recipes/building_blocks/cut_diorite_stairs.json -23b91aa1d94e899f245d5958bf58a2c9cc317131 data/create/advancements/recipes/building_blocks/cut_diorite_stairs_from_diorite_stonecutting.json 2aab681d1c5f0a0bac70386e7a9afa82dc36d834 data/create/advancements/recipes/building_blocks/cut_diorite_stairs_from_stone_types_diorite_stonecutting.json d716f0061b6b8b99ba35db3a6196042af10b6c6d data/create/advancements/recipes/building_blocks/cut_diorite_wall.json -23148b7bf27a481b1470e4ea3fb7cba3e46a6f61 data/create/advancements/recipes/building_blocks/cut_diorite_wall_from_diorite_stonecutting.json b1e18dafd815604c7b5220787fd7916941f1d7ba data/create/advancements/recipes/building_blocks/cut_diorite_wall_from_stone_types_diorite_stonecutting.json -30ea84f16282d2f9eff2ccd023d4ef40059fe6ea data/create/advancements/recipes/building_blocks/cut_dripstone_bricks_from_dripstone_block_stonecutting.json b9030bc3e7373dba83518fefa792153065d971be data/create/advancements/recipes/building_blocks/cut_dripstone_bricks_from_stone_types_dripstone_stonecutting.json b7714fb2dca84382f0f76419f287f52db41404dc data/create/advancements/recipes/building_blocks/cut_dripstone_brick_slab.json -1872499c6f6d289a310c4ce09d1c7a736e3d70e0 data/create/advancements/recipes/building_blocks/cut_dripstone_brick_slab_from_dripstone_block_stonecutting.json 8e500f1a62569bb233a8beac53b137b48c472253 data/create/advancements/recipes/building_blocks/cut_dripstone_brick_slab_from_stone_types_dripstone_stonecutting.json d4aaf6aa370bef0aee964ad95af516a0dde884ab data/create/advancements/recipes/building_blocks/cut_dripstone_brick_slab_recycling.json 3e5e6249ab04fbf33d311d7087c560fe326f30c3 data/create/advancements/recipes/building_blocks/cut_dripstone_brick_stairs.json -38f734b65530ec069523f9fa83318de4bb3ff864 data/create/advancements/recipes/building_blocks/cut_dripstone_brick_stairs_from_dripstone_block_stonecutting.json 61e3602da6c7718fc45d178202f1bbadfb3918e1 data/create/advancements/recipes/building_blocks/cut_dripstone_brick_stairs_from_stone_types_dripstone_stonecutting.json 830680c94855a6fa03c988bc3ddd2d65a31a8f97 data/create/advancements/recipes/building_blocks/cut_dripstone_brick_wall.json -897cb82e590d8ca87ecd1c4197b3e49b0258eee7 data/create/advancements/recipes/building_blocks/cut_dripstone_brick_wall_from_dripstone_block_stonecutting.json 596687e309271cc33f744f812e9aea2e118b247f data/create/advancements/recipes/building_blocks/cut_dripstone_brick_wall_from_stone_types_dripstone_stonecutting.json -f9b080a09988af397756518d9ff6023acba485f0 data/create/advancements/recipes/building_blocks/cut_dripstone_from_dripstone_block_stonecutting.json f739f4fe8184f9dbcc42053f8176c2ef4c88db72 data/create/advancements/recipes/building_blocks/cut_dripstone_from_stone_types_dripstone_stonecutting.json 3e3dd804cc959c860a92f616a9a7a5a08587a1a8 data/create/advancements/recipes/building_blocks/cut_dripstone_slab.json -f602e534be981ea1cca16c6e43ad20a2142bd055 data/create/advancements/recipes/building_blocks/cut_dripstone_slab_from_dripstone_block_stonecutting.json c984c6a4e149083c493691434adf88bbd7095757 data/create/advancements/recipes/building_blocks/cut_dripstone_slab_from_stone_types_dripstone_stonecutting.json d410bf3b921f22e5772ce45b19780ec185904811 data/create/advancements/recipes/building_blocks/cut_dripstone_slab_recycling.json dafdb3144b410324ecc38eca7c4885a7618a695e data/create/advancements/recipes/building_blocks/cut_dripstone_stairs.json -90ea25a4e848bf218bd42989b492c6c71e4b296e data/create/advancements/recipes/building_blocks/cut_dripstone_stairs_from_dripstone_block_stonecutting.json 1eab1b587bfcacc476704a6f8b4f9ee64961e4c3 data/create/advancements/recipes/building_blocks/cut_dripstone_stairs_from_stone_types_dripstone_stonecutting.json f4ce6ceb6c841ce445fbba924806fc13fcf0705b data/create/advancements/recipes/building_blocks/cut_dripstone_wall.json -798461c07d93b43aacc2deaa015d3543adc56be5 data/create/advancements/recipes/building_blocks/cut_dripstone_wall_from_dripstone_block_stonecutting.json b96c2f3cf9709838a972d6aa21c941e05639b8da data/create/advancements/recipes/building_blocks/cut_dripstone_wall_from_stone_types_dripstone_stonecutting.json -0a5ecbc1497b3bdd4fc0da784a31cbe3e6617fbc data/create/advancements/recipes/building_blocks/cut_granite_bricks_from_granite_stonecutting.json 96650d4d0921386d9613e99f4baa2f042c0a5b42 data/create/advancements/recipes/building_blocks/cut_granite_bricks_from_stone_types_granite_stonecutting.json c377471c8e7c0653f869899b927994ad9d412644 data/create/advancements/recipes/building_blocks/cut_granite_brick_slab.json -c39cfc13a38b435c0ada8200e7bc19a90bf4679a data/create/advancements/recipes/building_blocks/cut_granite_brick_slab_from_granite_stonecutting.json da218c04867a52da9b6334055b01d71b4bdf651a data/create/advancements/recipes/building_blocks/cut_granite_brick_slab_from_stone_types_granite_stonecutting.json 0461e4077f6f3d686a517d43ac6c9f06c5405ea2 data/create/advancements/recipes/building_blocks/cut_granite_brick_slab_recycling.json 8a1d57f0847f0e55c79673d65a7f1e701777ff59 data/create/advancements/recipes/building_blocks/cut_granite_brick_stairs.json -37935f48710def2e77726c9c0ac32e93bfbd2881 data/create/advancements/recipes/building_blocks/cut_granite_brick_stairs_from_granite_stonecutting.json fd520491bbcd4575912079e1622e1d7c89c131db data/create/advancements/recipes/building_blocks/cut_granite_brick_stairs_from_stone_types_granite_stonecutting.json a40b37b199babeea632276bf5f1310d6b4d8829e data/create/advancements/recipes/building_blocks/cut_granite_brick_wall.json -10d4b3b2429f2ca7b0c137f268d00aa1eb5bfb8b data/create/advancements/recipes/building_blocks/cut_granite_brick_wall_from_granite_stonecutting.json d068647afab93764854e14a94e5ea1fd6dfb3484 data/create/advancements/recipes/building_blocks/cut_granite_brick_wall_from_stone_types_granite_stonecutting.json -f34b29a07695391fe99779642dcb34afd04f7469 data/create/advancements/recipes/building_blocks/cut_granite_from_granite_stonecutting.json 31748f7ec56093e52d05473f535f2a240e47c830 data/create/advancements/recipes/building_blocks/cut_granite_from_stone_types_granite_stonecutting.json 31226217d85432d4dd7179a055161be3bf16edcb data/create/advancements/recipes/building_blocks/cut_granite_slab.json -8d911f621c6b1b153785082fb2f2d85cddfa9a28 data/create/advancements/recipes/building_blocks/cut_granite_slab_from_granite_stonecutting.json 11f148ffff12d511b53e3d3abe26c5002585a67c data/create/advancements/recipes/building_blocks/cut_granite_slab_from_stone_types_granite_stonecutting.json f2ee1a39c5bcd2b37e387be4e20fdf11c5d78f4c data/create/advancements/recipes/building_blocks/cut_granite_slab_recycling.json 89686a4eb4d188aef0517d2283ee19a5b0a29f0a data/create/advancements/recipes/building_blocks/cut_granite_stairs.json -c25b7a28b8838af602cac80034b0c7a03e225b8e data/create/advancements/recipes/building_blocks/cut_granite_stairs_from_granite_stonecutting.json 180e5839e302870819658ad83e3440f726773072 data/create/advancements/recipes/building_blocks/cut_granite_stairs_from_stone_types_granite_stonecutting.json 6b614a82011720d62151174816c199a594dff58b data/create/advancements/recipes/building_blocks/cut_granite_wall.json -ba748bd337d1d9630952f5fef4d5f49cf2198f15 data/create/advancements/recipes/building_blocks/cut_granite_wall_from_granite_stonecutting.json 5158ed942423382e388e4fe3a2c89fb8cbe796da data/create/advancements/recipes/building_blocks/cut_granite_wall_from_stone_types_granite_stonecutting.json -acdda8b229ae01cdac0c4e9683f997b13b730e33 data/create/advancements/recipes/building_blocks/cut_limestone_bricks_from_limestone_stonecutting.json 79ba7f9095e9c6fbafc2301b5f14853648be7499 data/create/advancements/recipes/building_blocks/cut_limestone_bricks_from_stone_types_limestone_stonecutting.json b784dddc5fd797ef6433ad81d8a9e3e4e3d9e169 data/create/advancements/recipes/building_blocks/cut_limestone_brick_slab.json -07af41858234af8a7fd72e09a168c39d33f2f0cf data/create/advancements/recipes/building_blocks/cut_limestone_brick_slab_from_limestone_stonecutting.json c08f26b595f3698b821442628a76ced351ba22ab data/create/advancements/recipes/building_blocks/cut_limestone_brick_slab_from_stone_types_limestone_stonecutting.json cc9fabd6eff3764e4eacfcdccd0c52d63ca98ed6 data/create/advancements/recipes/building_blocks/cut_limestone_brick_slab_recycling.json 760079b842724c503af85f3f886e6357719a4949 data/create/advancements/recipes/building_blocks/cut_limestone_brick_stairs.json -a9c7ce48f4ed19bc286e21dfb9baf2ca799340b1 data/create/advancements/recipes/building_blocks/cut_limestone_brick_stairs_from_limestone_stonecutting.json d96ea6795a98441103f88192212fc5c58c1f09ef data/create/advancements/recipes/building_blocks/cut_limestone_brick_stairs_from_stone_types_limestone_stonecutting.json e1a3f4d70fc3d0ac9729dad3bd48448684a4ba37 data/create/advancements/recipes/building_blocks/cut_limestone_brick_wall.json -a3e682ae6d72a6ea03944175ddf7dd79a42e0a05 data/create/advancements/recipes/building_blocks/cut_limestone_brick_wall_from_limestone_stonecutting.json 3c4e65f2065dc189aa0a05ac5ccce18f00b47222 data/create/advancements/recipes/building_blocks/cut_limestone_brick_wall_from_stone_types_limestone_stonecutting.json -1db9820651c5bbc36b041950bf0443594ed546a1 data/create/advancements/recipes/building_blocks/cut_limestone_from_limestone_stonecutting.json 344965b0887d70bfbf5bd0d3d20e39caf7feebb0 data/create/advancements/recipes/building_blocks/cut_limestone_from_stone_types_limestone_stonecutting.json a96a733b4764b0a803ddab9cf55e846b3329a6fd data/create/advancements/recipes/building_blocks/cut_limestone_slab.json -ebb6baae16d0a47a37000eba1d18cc0b580372df data/create/advancements/recipes/building_blocks/cut_limestone_slab_from_limestone_stonecutting.json 0613e2241b57cd8891b212d6600040b63cc99920 data/create/advancements/recipes/building_blocks/cut_limestone_slab_from_stone_types_limestone_stonecutting.json 9ca3c0747875febf44ee8d66e06679b29af35a8d data/create/advancements/recipes/building_blocks/cut_limestone_slab_recycling.json b823847bd61bf4d7f4f1628df8ffa75228e4bd1f data/create/advancements/recipes/building_blocks/cut_limestone_stairs.json -c6a71a5a5f679a18223b118c72ca9f22fb5b120d data/create/advancements/recipes/building_blocks/cut_limestone_stairs_from_limestone_stonecutting.json d5197bb60805ebe14bad712ce3c91d80505493dc data/create/advancements/recipes/building_blocks/cut_limestone_stairs_from_stone_types_limestone_stonecutting.json 2d5da1dc9892e8063274859870b360d3c923de2a data/create/advancements/recipes/building_blocks/cut_limestone_wall.json -2797e9747e02fd18efa55ae08a29c1cfa0c8ca50 data/create/advancements/recipes/building_blocks/cut_limestone_wall_from_limestone_stonecutting.json b65bfead9674a9bde10343ac58cc26ae8f297d70 data/create/advancements/recipes/building_blocks/cut_limestone_wall_from_stone_types_limestone_stonecutting.json -bb9bf4b428a71190f126ce61babae82f8704a43e data/create/advancements/recipes/building_blocks/cut_ochrum_bricks_from_ochrum_stonecutting.json a5a6e408e70a40723aa7eb2209229dd31e3d0204 data/create/advancements/recipes/building_blocks/cut_ochrum_bricks_from_stone_types_ochrum_stonecutting.json 38c6bb5fa61edb3109a93c51043a050bf1fcffa2 data/create/advancements/recipes/building_blocks/cut_ochrum_brick_slab.json -b44333e12d37e0f540e9e42ca08525102e7ce1b1 data/create/advancements/recipes/building_blocks/cut_ochrum_brick_slab_from_ochrum_stonecutting.json 90bdf413be0f6292ceccf0670fdca411f6f6971c data/create/advancements/recipes/building_blocks/cut_ochrum_brick_slab_from_stone_types_ochrum_stonecutting.json 97cdc8d1896869a16d33f76e5a7db20fee94b40e data/create/advancements/recipes/building_blocks/cut_ochrum_brick_slab_recycling.json 367ab7ccfef088011bfdc3d8d9e343120d657068 data/create/advancements/recipes/building_blocks/cut_ochrum_brick_stairs.json -71d7855b8e789a64b3bc5c5c8dcd8b52352aeb48 data/create/advancements/recipes/building_blocks/cut_ochrum_brick_stairs_from_ochrum_stonecutting.json 3e35d96f31fa946ae1d85d458ca4edc3a7711668 data/create/advancements/recipes/building_blocks/cut_ochrum_brick_stairs_from_stone_types_ochrum_stonecutting.json df602423bb9c3bede26856f0b11f2da025af688d data/create/advancements/recipes/building_blocks/cut_ochrum_brick_wall.json -9026ed9f112911309cddc106631ed066a3541c93 data/create/advancements/recipes/building_blocks/cut_ochrum_brick_wall_from_ochrum_stonecutting.json bb6dc3849fc45c8819ceae2833a979315ceb28f6 data/create/advancements/recipes/building_blocks/cut_ochrum_brick_wall_from_stone_types_ochrum_stonecutting.json -eb2bf8805ea37a3a45628dec8ffc56c9477775ab data/create/advancements/recipes/building_blocks/cut_ochrum_from_ochrum_stonecutting.json 30fcf27da458a97f62fd9736ae1d7f257c1285c1 data/create/advancements/recipes/building_blocks/cut_ochrum_from_stone_types_ochrum_stonecutting.json 2b88c9eeb81ceaa648d6af36b076af465be25a1d data/create/advancements/recipes/building_blocks/cut_ochrum_slab.json -9e2696912f918f76dfd9cfb3d9a2f09a2f7c867b data/create/advancements/recipes/building_blocks/cut_ochrum_slab_from_ochrum_stonecutting.json bf46068cb39da19fad5d1dac202980106f4ef8d9 data/create/advancements/recipes/building_blocks/cut_ochrum_slab_from_stone_types_ochrum_stonecutting.json e05482fd195f1da78e56a7e22099b370853e3c66 data/create/advancements/recipes/building_blocks/cut_ochrum_slab_recycling.json 1571dc2c5f8756e8c9abbb880883c2a7cc66b7e4 data/create/advancements/recipes/building_blocks/cut_ochrum_stairs.json -860302b624776d0d6dfd7c020a13a4e521c30c9e data/create/advancements/recipes/building_blocks/cut_ochrum_stairs_from_ochrum_stonecutting.json 5035972081ce71fb47d7fda3710952d69d47a011 data/create/advancements/recipes/building_blocks/cut_ochrum_stairs_from_stone_types_ochrum_stonecutting.json 36fd28d75f1daaadc9db8539214cab39a8b43100 data/create/advancements/recipes/building_blocks/cut_ochrum_wall.json -ed79972b188962b505e817b055b7396f9316a54d data/create/advancements/recipes/building_blocks/cut_ochrum_wall_from_ochrum_stonecutting.json 161303d1e900c82fd30525ed8b4da0da520086f8 data/create/advancements/recipes/building_blocks/cut_ochrum_wall_from_stone_types_ochrum_stonecutting.json -54dc84c462fc3da8720a4e1cd708b66e28cf6d6e data/create/advancements/recipes/building_blocks/cut_scorchia_bricks_from_scorchia_stonecutting.json ed9ee091c10e110dd3ab679bf9d4ea61e0b44656 data/create/advancements/recipes/building_blocks/cut_scorchia_bricks_from_stone_types_scorchia_stonecutting.json 98d5b30230229e2d60c45aa95e816c26c0e8ba1f data/create/advancements/recipes/building_blocks/cut_scorchia_brick_slab.json -fad18af568401fdf92b0992c00824d48cf34c731 data/create/advancements/recipes/building_blocks/cut_scorchia_brick_slab_from_scorchia_stonecutting.json 43b71c34677ec02217260ae11d91fc8b12aee135 data/create/advancements/recipes/building_blocks/cut_scorchia_brick_slab_from_stone_types_scorchia_stonecutting.json 516c57259e6f6cc4c45571cc3eff1aa46018d294 data/create/advancements/recipes/building_blocks/cut_scorchia_brick_slab_recycling.json 233bf60edd3c574bc634423d1fd04edf7548f1dd data/create/advancements/recipes/building_blocks/cut_scorchia_brick_stairs.json -e56724641d801bc118fc0a6cd23abee3c0d4b910 data/create/advancements/recipes/building_blocks/cut_scorchia_brick_stairs_from_scorchia_stonecutting.json 2dbc08e67fb633370dc07000d00c40a0aaaa4226 data/create/advancements/recipes/building_blocks/cut_scorchia_brick_stairs_from_stone_types_scorchia_stonecutting.json 1932fb5747a127c8f51b72c5f924973888ed2088 data/create/advancements/recipes/building_blocks/cut_scorchia_brick_wall.json -d46b4a262f5ab63e5b8390f296232cbf37e84a0a data/create/advancements/recipes/building_blocks/cut_scorchia_brick_wall_from_scorchia_stonecutting.json 7feb499670488e0780421351bbc869c898e7ef16 data/create/advancements/recipes/building_blocks/cut_scorchia_brick_wall_from_stone_types_scorchia_stonecutting.json -4b30b16c8bb798dcac82205f73972fea2c9b3219 data/create/advancements/recipes/building_blocks/cut_scorchia_from_scorchia_stonecutting.json ad397fdf5670bf920395092943dc6bdf55f10f80 data/create/advancements/recipes/building_blocks/cut_scorchia_from_stone_types_scorchia_stonecutting.json bd24111dec3fa0d12af98933bc4a752e78df19ac data/create/advancements/recipes/building_blocks/cut_scorchia_slab.json -4b73a206bb2999be336528886037033122b5047c data/create/advancements/recipes/building_blocks/cut_scorchia_slab_from_scorchia_stonecutting.json 86ef51b9eb6876c6cb25e6fde5311b9e1221a4e2 data/create/advancements/recipes/building_blocks/cut_scorchia_slab_from_stone_types_scorchia_stonecutting.json cb643c4dcc020e3e3b9fc7a22aebd2c8acf5d0ce data/create/advancements/recipes/building_blocks/cut_scorchia_slab_recycling.json eda42cf974320d1dbeb369c3429fb8d4ba3dc93f data/create/advancements/recipes/building_blocks/cut_scorchia_stairs.json -7ff8ac4f704395e34fd3039d1744db2bb2bfec96 data/create/advancements/recipes/building_blocks/cut_scorchia_stairs_from_scorchia_stonecutting.json 7d7e87c02f9790b13cb3b2aa2ebdcbb3a09ef283 data/create/advancements/recipes/building_blocks/cut_scorchia_stairs_from_stone_types_scorchia_stonecutting.json 989df5b9969d6f0c30a5551e34092e1bb3e02a72 data/create/advancements/recipes/building_blocks/cut_scorchia_wall.json -b1baa58fe09b12263b4378ff295e18b72d352df0 data/create/advancements/recipes/building_blocks/cut_scorchia_wall_from_scorchia_stonecutting.json 60ad492ec09218adf32b0ccb5c634aeaa7acab4e data/create/advancements/recipes/building_blocks/cut_scorchia_wall_from_stone_types_scorchia_stonecutting.json -77d3d9f50fd3fc666fc987766c9a1ad3d876fd34 data/create/advancements/recipes/building_blocks/cut_scoria_bricks_from_scoria_stonecutting.json 9c4a52735c4ea9a609a091ebf8e42dfb76d7f703 data/create/advancements/recipes/building_blocks/cut_scoria_bricks_from_stone_types_scoria_stonecutting.json d4d22ab2ca7132016be29000bfe9a901f5f1f75a data/create/advancements/recipes/building_blocks/cut_scoria_brick_slab.json -c110264a717eae1f6a011665f624ac265dfc1662 data/create/advancements/recipes/building_blocks/cut_scoria_brick_slab_from_scoria_stonecutting.json f6b957a9b6fc7effe8237607f4ce05fd63302d86 data/create/advancements/recipes/building_blocks/cut_scoria_brick_slab_from_stone_types_scoria_stonecutting.json 6cfa3570b0308c2757fb872d7eeedb999deb0fa6 data/create/advancements/recipes/building_blocks/cut_scoria_brick_slab_recycling.json e71f945ef28a9cf4f08b11207588225b5667a578 data/create/advancements/recipes/building_blocks/cut_scoria_brick_stairs.json -ec4af6f34c536ebf53086eafd1a19d80f5755465 data/create/advancements/recipes/building_blocks/cut_scoria_brick_stairs_from_scoria_stonecutting.json 75f656063f07862c7dc2a521b532bd9506dfabaa data/create/advancements/recipes/building_blocks/cut_scoria_brick_stairs_from_stone_types_scoria_stonecutting.json d7fb1c9baabab142b5e2e5a782a860a10e957082 data/create/advancements/recipes/building_blocks/cut_scoria_brick_wall.json -a387769c09c164cbd78b9cc893f9179e453049d3 data/create/advancements/recipes/building_blocks/cut_scoria_brick_wall_from_scoria_stonecutting.json 58a7308b42028d816d518fee36523d81889d5a08 data/create/advancements/recipes/building_blocks/cut_scoria_brick_wall_from_stone_types_scoria_stonecutting.json -67ea1e4441da82fa02ae14f987acc36c8665bc1a data/create/advancements/recipes/building_blocks/cut_scoria_from_scoria_stonecutting.json 04e9276e96d869dfaf337e437af483620716cab2 data/create/advancements/recipes/building_blocks/cut_scoria_from_stone_types_scoria_stonecutting.json 98b2440c3c364c10a362a7a9800e2eb25117a984 data/create/advancements/recipes/building_blocks/cut_scoria_slab.json -c9932cb7e9dee370da7ea03d6bcc79f818f1c872 data/create/advancements/recipes/building_blocks/cut_scoria_slab_from_scoria_stonecutting.json e4bb42a4e62897c7e2c56c7e0a6ae9c0567c5973 data/create/advancements/recipes/building_blocks/cut_scoria_slab_from_stone_types_scoria_stonecutting.json 5cf1b7fb1d30dd72b569767594c35d91292c987e data/create/advancements/recipes/building_blocks/cut_scoria_slab_recycling.json b4f846b58c8fb233b4dc71c3c6cb7bc66dda4409 data/create/advancements/recipes/building_blocks/cut_scoria_stairs.json -e37677e7be04b3ddab286098fdaa3a6993ccfc41 data/create/advancements/recipes/building_blocks/cut_scoria_stairs_from_scoria_stonecutting.json a4042343319182d29300b7f858d16de14fb557f7 data/create/advancements/recipes/building_blocks/cut_scoria_stairs_from_stone_types_scoria_stonecutting.json a8e4ef868cbacecf0e46cb64cadcfdc743745297 data/create/advancements/recipes/building_blocks/cut_scoria_wall.json -33bbaa2fb618cbe0cb8b45b53358023e49f86c19 data/create/advancements/recipes/building_blocks/cut_scoria_wall_from_scoria_stonecutting.json 38c849899f158855f4fb791aaa74721649582293 data/create/advancements/recipes/building_blocks/cut_scoria_wall_from_stone_types_scoria_stonecutting.json eb2491491a16dd5cb60c09a67b77e4481e3f270c data/create/advancements/recipes/building_blocks/cut_tuff_bricks_from_stone_types_tuff_stonecutting.json -df967cfb1d08ef83d600ccfef37609000f22751e data/create/advancements/recipes/building_blocks/cut_tuff_bricks_from_tuff_stonecutting.json 5aa81455a0d9b811d14c5f53247ec27f4cde08f2 data/create/advancements/recipes/building_blocks/cut_tuff_brick_slab.json 75c8d96609b9ef1fee812be5363825e8a54f5dda data/create/advancements/recipes/building_blocks/cut_tuff_brick_slab_from_stone_types_tuff_stonecutting.json -a5f9f8417f383267194d2664d3fecf261562677d data/create/advancements/recipes/building_blocks/cut_tuff_brick_slab_from_tuff_stonecutting.json 173afee112bcdd2a7b37f2ca722da325159c111f data/create/advancements/recipes/building_blocks/cut_tuff_brick_slab_recycling.json cead30768e5ec30b16d0b7a79b03b84ab3dd7579 data/create/advancements/recipes/building_blocks/cut_tuff_brick_stairs.json b960f114a094f7799fb26eb1d813e0ac53a5c725 data/create/advancements/recipes/building_blocks/cut_tuff_brick_stairs_from_stone_types_tuff_stonecutting.json -0cce8a5c7526570209825a9c3f6fad305eb22b75 data/create/advancements/recipes/building_blocks/cut_tuff_brick_stairs_from_tuff_stonecutting.json 8844c9ad810b7f6cb5394766aada241264e9b4e1 data/create/advancements/recipes/building_blocks/cut_tuff_brick_wall.json e4cc4b782fe7f513a28d0816233557a1e07398f4 data/create/advancements/recipes/building_blocks/cut_tuff_brick_wall_from_stone_types_tuff_stonecutting.json -4af97307dd625d2dbb027b79e0a45e72a3cf8020 data/create/advancements/recipes/building_blocks/cut_tuff_brick_wall_from_tuff_stonecutting.json e6f1ffe762eff05c0362816a95d663d51893c63d data/create/advancements/recipes/building_blocks/cut_tuff_from_stone_types_tuff_stonecutting.json -798b7a82245302f6a6f1a039f2308cc90adfc34a data/create/advancements/recipes/building_blocks/cut_tuff_from_tuff_stonecutting.json 59d165efc116e9c8578df9ba670c3692b83d90c2 data/create/advancements/recipes/building_blocks/cut_tuff_slab.json 7f8734665ee1ea740b23a93253adddda373b768c data/create/advancements/recipes/building_blocks/cut_tuff_slab_from_stone_types_tuff_stonecutting.json -db251babf07944ea73a4a9ee9829efae6cba471b data/create/advancements/recipes/building_blocks/cut_tuff_slab_from_tuff_stonecutting.json 386ebb544c83c98a9081fd2a2c7f21869138cdce data/create/advancements/recipes/building_blocks/cut_tuff_slab_recycling.json 15ea987d28b8d39598a0744db6bff6885d9a06a0 data/create/advancements/recipes/building_blocks/cut_tuff_stairs.json 2ecd34dbf08d7b0fb076d4541951a1af8503988a data/create/advancements/recipes/building_blocks/cut_tuff_stairs_from_stone_types_tuff_stonecutting.json -834b9efde836381d0371ecc6813e6561c3603a0d data/create/advancements/recipes/building_blocks/cut_tuff_stairs_from_tuff_stonecutting.json 41fa7083f2968ec691e614b6aadfc5580f71a9f0 data/create/advancements/recipes/building_blocks/cut_tuff_wall.json 99ffe2f2f0f2fe57ce0a3a8790b7403070dabe0c data/create/advancements/recipes/building_blocks/cut_tuff_wall_from_stone_types_tuff_stonecutting.json -bb0f1482f5fdf9af1175b36c6172e15de53d3adc data/create/advancements/recipes/building_blocks/cut_tuff_wall_from_tuff_stonecutting.json 5efb0e802537382669d543be8581f14af87f2243 data/create/advancements/recipes/building_blocks/cut_veridium_bricks_from_stone_types_veridium_stonecutting.json -e12b80821aa4c84de3d3ab090b02b26da9620f02 data/create/advancements/recipes/building_blocks/cut_veridium_bricks_from_veridium_stonecutting.json 08b84146aec0df756b892b966b8ff584941e3822 data/create/advancements/recipes/building_blocks/cut_veridium_brick_slab.json a15d11707c379ec89f827469ab66185094b83d57 data/create/advancements/recipes/building_blocks/cut_veridium_brick_slab_from_stone_types_veridium_stonecutting.json -dd208ff2321ce2233c702d765bffa233b674ea32 data/create/advancements/recipes/building_blocks/cut_veridium_brick_slab_from_veridium_stonecutting.json 7b0345456315824f48051c441a1af8234185dbb7 data/create/advancements/recipes/building_blocks/cut_veridium_brick_slab_recycling.json 63c8064573effe77eee9f19651a93c6703a8f1a5 data/create/advancements/recipes/building_blocks/cut_veridium_brick_stairs.json c9f04e36272ec15408701cf5f087cfaf5bc86df3 data/create/advancements/recipes/building_blocks/cut_veridium_brick_stairs_from_stone_types_veridium_stonecutting.json -ace8d62f7cce63244166576da46b610e04f6fac5 data/create/advancements/recipes/building_blocks/cut_veridium_brick_stairs_from_veridium_stonecutting.json cc42ae471f9e2206ada28e6a6556bd823fe96297 data/create/advancements/recipes/building_blocks/cut_veridium_brick_wall.json cb27e519f7699a5e406acc38122f78c9bc4ef469 data/create/advancements/recipes/building_blocks/cut_veridium_brick_wall_from_stone_types_veridium_stonecutting.json -723266d55a52c45ec12ed2f8c3dd54115cd2f027 data/create/advancements/recipes/building_blocks/cut_veridium_brick_wall_from_veridium_stonecutting.json 30abd94643a7da5e9121333dcfbae0bd77f3426c data/create/advancements/recipes/building_blocks/cut_veridium_from_stone_types_veridium_stonecutting.json -ad8fa53d153f3b6d762ea24f58e1c23d644d6210 data/create/advancements/recipes/building_blocks/cut_veridium_from_veridium_stonecutting.json 222c2bf6e94ca73bcab991f6a7dc9704d67371a2 data/create/advancements/recipes/building_blocks/cut_veridium_slab.json 4e6a5cf062e512e19e7f48dea4e2284459a9d4fa data/create/advancements/recipes/building_blocks/cut_veridium_slab_from_stone_types_veridium_stonecutting.json -378ae1c96e1e0afc0293cfb88bb270f8c8b1366f data/create/advancements/recipes/building_blocks/cut_veridium_slab_from_veridium_stonecutting.json 9d3ffa5ae608511debd28b9e58bd81f8be00ac5f data/create/advancements/recipes/building_blocks/cut_veridium_slab_recycling.json 8d044d8d6ef860dfb86625985a2737c75c1e4467 data/create/advancements/recipes/building_blocks/cut_veridium_stairs.json 7ba505ccf811a1c5b006b8915a97b644a20065f2 data/create/advancements/recipes/building_blocks/cut_veridium_stairs_from_stone_types_veridium_stonecutting.json -cc54c9be13c8f32496edb53023c26e2e15bc270a data/create/advancements/recipes/building_blocks/cut_veridium_stairs_from_veridium_stonecutting.json 0cb34fe57e0511442d8238b5366392ca6dee5042 data/create/advancements/recipes/building_blocks/cut_veridium_wall.json fe24697ae691e34e57e67e76e890167a5b0c9842 data/create/advancements/recipes/building_blocks/cut_veridium_wall_from_stone_types_veridium_stonecutting.json -965a1e54e1465979b9ec525f6881ac06783eb4d9 data/create/advancements/recipes/building_blocks/cut_veridium_wall_from_veridium_stonecutting.json c9a36346d9d739842bddddf46da7cba53be5ca94 data/create/advancements/recipes/building_blocks/dark_oak_window.json 86f9ec8ac357c859536478d5b4e5a47295b1a3ba data/create/advancements/recipes/building_blocks/dark_oak_window_pane.json -09078c95e0e506b8e1fd425b896d4494f554600b data/create/advancements/recipes/building_blocks/deepslate_pillar_from_deepslate_stonecutting.json +6baae33c4f0576150d86af1402ee7fccba34a3a7 data/create/advancements/recipes/building_blocks/deepslate_from_stone_types_deepslate_stonecutting.json c594333560ef54e1cd7fe01830137c4032e9ed1a data/create/advancements/recipes/building_blocks/deepslate_pillar_from_stone_types_deepslate_stonecutting.json -1c007bafa64424498a52cfeeee92ca02864086d7 data/create/advancements/recipes/building_blocks/diorite_pillar_from_diorite_stonecutting.json +0dd33368f5abff29d3eb575321832cf9410ff238 data/create/advancements/recipes/building_blocks/diorite_from_stone_types_diorite_stonecutting.json 4922ea5e65bd3b4b094a0ebda17f7d57baf98d13 data/create/advancements/recipes/building_blocks/diorite_pillar_from_stone_types_diorite_stonecutting.json -0d9d56e1516f5fc84c77a947d26fb37bfbdcdab4 data/create/advancements/recipes/building_blocks/dripstone_pillar_from_dripstone_block_stonecutting.json +6b635b786be48ff7bbcad7648e75b3a5452fe739 data/create/advancements/recipes/building_blocks/dripstone_block_from_stone_types_dripstone_stonecutting.json 5bdef473b0abedf9419e8b90508f3ab582257044 data/create/advancements/recipes/building_blocks/dripstone_pillar_from_stone_types_dripstone_stonecutting.json 651ca0fa268d08fb50cd14a0a978c10fe1c58ad7 data/create/advancements/recipes/building_blocks/exposed_copper_shingle_slab.json ae6f36f689789a7482919cc5aba073befc3c6911 data/create/advancements/recipes/building_blocks/exposed_copper_shingle_slab_from_exposed_copper_shingles_stonecutting.json @@ -2595,45 +2629,34 @@ d3c94982ffcbed05f030fc337357349e1988b160 data/create/advancements/recipes/buildi affdc8d4e2e6023d829a6fa9274296bbabc205f7 data/create/advancements/recipes/building_blocks/exposed_copper_tile_stairs_from_exposed_copper_tiles_stonecutting.json a4c411397c83da08aff4fdf1e6a152e6920ce041 data/create/advancements/recipes/building_blocks/framed_glass_from_glass_colorless_stonecutting.json 91d78a68f15e58f3bfff27c2b95a2afc541ebc09 data/create/advancements/recipes/building_blocks/framed_glass_pane.json -98c31ae7e1474653c4fac748404ba8e28efe4df1 data/create/advancements/recipes/building_blocks/granite_pillar_from_granite_stonecutting.json +9c7933938b35cda04a6f39185ce6666d08743a96 data/create/advancements/recipes/building_blocks/granite_from_stone_types_granite_stonecutting.json 30bef4f7198cd8c3be730dd535bdee5f4531a333 data/create/advancements/recipes/building_blocks/granite_pillar_from_stone_types_granite_stonecutting.json ffd0d7c16c76f60ce23f719110b0f222821cc141 data/create/advancements/recipes/building_blocks/horizontal_framed_glass_from_glass_colorless_stonecutting.json f468fd03b657eec91e744537078e8fe9856b7678 data/create/advancements/recipes/building_blocks/horizontal_framed_glass_pane.json +bff27fa488addf721ee4fd3dac0fb19ffa6a2d18 data/create/advancements/recipes/building_blocks/industrial_iron_block_from_ingots_iron_stonecutting.json 25c2ade22e31fd8096714aee7cfd6e7001c1cc60 data/create/advancements/recipes/building_blocks/jungle_window.json a6ebf3d38ab309f40d64f84d76f491d0e1b0cb80 data/create/advancements/recipes/building_blocks/jungle_window_pane.json -6c78b7f52deb8b529e6d402b061bb9ed43dc2e18 data/create/advancements/recipes/building_blocks/layered_andesite_from_andesite_stonecutting.json a39f3e144e63fceeb33a234b3b286812f6826c19 data/create/advancements/recipes/building_blocks/layered_andesite_from_stone_types_andesite_stonecutting.json -8623aa35c08fb3dfa26dc65efafc4d80d3f753a4 data/create/advancements/recipes/building_blocks/layered_asurine_from_asurine_stonecutting.json 6daaed4b4616b066c396eb9739807c336b454516 data/create/advancements/recipes/building_blocks/layered_asurine_from_stone_types_asurine_stonecutting.json -f8d18eff90a7963c5e5a41f2d8602120ade433c6 data/create/advancements/recipes/building_blocks/layered_calcite_from_calcite_stonecutting.json 78a11a6f884ad59b2a5ca4f0e505ef98d065d220 data/create/advancements/recipes/building_blocks/layered_calcite_from_stone_types_calcite_stonecutting.json -e1571697be5a836402e1263c78a041853f9d0877 data/create/advancements/recipes/building_blocks/layered_crimsite_from_crimsite_stonecutting.json 66f15a7e69b0144e0c80132441eed4e248dcae70 data/create/advancements/recipes/building_blocks/layered_crimsite_from_stone_types_crimsite_stonecutting.json -f6c91ecb190b987497629f96c312e775b1013378 data/create/advancements/recipes/building_blocks/layered_deepslate_from_deepslate_stonecutting.json 624331627975c134a04ce4f5dd39bd89772b2d51 data/create/advancements/recipes/building_blocks/layered_deepslate_from_stone_types_deepslate_stonecutting.json -06d9a08d34c3755d21bdd3210b8205aa86f401d2 data/create/advancements/recipes/building_blocks/layered_diorite_from_diorite_stonecutting.json 0a275dade16abd876fb89765f93afb24bf02713d data/create/advancements/recipes/building_blocks/layered_diorite_from_stone_types_diorite_stonecutting.json -1fc49676029a6b7f755eb6d28acdb95af13cfecb data/create/advancements/recipes/building_blocks/layered_dripstone_from_dripstone_block_stonecutting.json ab06ad6dd8ac2f426adef80415211cd08939526c data/create/advancements/recipes/building_blocks/layered_dripstone_from_stone_types_dripstone_stonecutting.json -5f53dbbc44dc56e29b85a62956ed6b07d10e8b00 data/create/advancements/recipes/building_blocks/layered_granite_from_granite_stonecutting.json 2dbc9bfe3589ce284dfdf57d787e2ef8c2a40ad2 data/create/advancements/recipes/building_blocks/layered_granite_from_stone_types_granite_stonecutting.json -8f7135a765da22a7404522abc715dfc1264f0be2 data/create/advancements/recipes/building_blocks/layered_limestone_from_limestone_stonecutting.json 68ee05e89aa4f27e0c2f94b1246b4cb495aecc07 data/create/advancements/recipes/building_blocks/layered_limestone_from_stone_types_limestone_stonecutting.json -fd6b29adc71e3642546ac2dcfa8777bc8c680aa5 data/create/advancements/recipes/building_blocks/layered_ochrum_from_ochrum_stonecutting.json 75a7a6e313d32319c32b3ce0df21e8cc6774f402 data/create/advancements/recipes/building_blocks/layered_ochrum_from_stone_types_ochrum_stonecutting.json -2824cc2f2238c63bc5b1a7d69df92434700590e1 data/create/advancements/recipes/building_blocks/layered_scorchia_from_scorchia_stonecutting.json 4f0c829edd12729014dcb63650720aaf917eb439 data/create/advancements/recipes/building_blocks/layered_scorchia_from_stone_types_scorchia_stonecutting.json -122a63ebbefbf8b7d52d3dfc2e140c5e6cf33e53 data/create/advancements/recipes/building_blocks/layered_scoria_from_scoria_stonecutting.json ed3743e70c493b07c3101c0dc92215526c387db0 data/create/advancements/recipes/building_blocks/layered_scoria_from_stone_types_scoria_stonecutting.json e5feef288669aa930ae12cf9a783d620af7d91b4 data/create/advancements/recipes/building_blocks/layered_tuff_from_stone_types_tuff_stonecutting.json -2ad27157bac4c1e216ce8e6e5e27072a475e73ee data/create/advancements/recipes/building_blocks/layered_tuff_from_tuff_stonecutting.json dfb4f2e119b8017d5db975fb541713048703e2c6 data/create/advancements/recipes/building_blocks/layered_veridium_from_stone_types_veridium_stonecutting.json -bb080e7c3cb91c344b5f208a998608f62e7c2b71 data/create/advancements/recipes/building_blocks/layered_veridium_from_veridium_stonecutting.json -da0792b639766a20b70fd5b85b6a60135da7900c data/create/advancements/recipes/building_blocks/limestone_pillar_from_limestone_stonecutting.json +395ac94e392ba5e84588593808411b58439fa00b data/create/advancements/recipes/building_blocks/limestone_from_stone_types_limestone_stonecutting.json de18b7fbe72ebab8664dc8bad74b11c8f963d201 data/create/advancements/recipes/building_blocks/limestone_pillar_from_stone_types_limestone_stonecutting.json +297cef748e21b0615fba6d89e917ca95744eb72c data/create/advancements/recipes/building_blocks/mangrove_window.json +caae52c615f4f73e6197a0f64530d65e032ee86c data/create/advancements/recipes/building_blocks/mangrove_window_pane.json 72a0bf990de9157649f4a35d107691336ac251cd data/create/advancements/recipes/building_blocks/oak_window.json 0df92ddbd45927fffcd6e7dd64e23a9c1a480987 data/create/advancements/recipes/building_blocks/oak_window_pane.json -deb88749c15101a17619e18c4de3a32eac6d674e data/create/advancements/recipes/building_blocks/ochrum_pillar_from_ochrum_stonecutting.json +3af97ef889363105d623983041bc542e42262a81 data/create/advancements/recipes/building_blocks/ochrum_from_stone_types_ochrum_stonecutting.json d1622650c35ab63ad763bcae9daa2faa0475a6c1 data/create/advancements/recipes/building_blocks/ochrum_pillar_from_stone_types_ochrum_stonecutting.json cee0b2d010e5aac246498d3f2e693a229b484de9 data/create/advancements/recipes/building_blocks/ornate_iron_window.json ac65691f3ee1cca8063653605f507de264b90755 data/create/advancements/recipes/building_blocks/ornate_iron_window_pane.json @@ -2645,357 +2668,245 @@ c9ec3f974bda0596b342636024f2d147fdd33c6d data/create/advancements/recipes/buildi 38db970e9383ef2840e59e2d55174b0ef8c452ea data/create/advancements/recipes/building_blocks/oxidized_copper_tile_slab_from_oxidized_copper_tiles_stonecutting.json 323894a12012e29ba987dedff8c3b5ec7b462063 data/create/advancements/recipes/building_blocks/oxidized_copper_tile_stairs.json f8d98349f5d7f485a235989e677429948e6fde01 data/create/advancements/recipes/building_blocks/oxidized_copper_tile_stairs_from_oxidized_copper_tiles_stonecutting.json -f0bfb3c97a0d7f036484326ef25959b956626015 data/create/advancements/recipes/building_blocks/polished_cut_andesite_from_andesite_stonecutting.json 87e2b764ee25608a5e616dd67d457c4683b5f7f0 data/create/advancements/recipes/building_blocks/polished_cut_andesite_from_stone_types_andesite_stonecutting.json 56044e65f870706a64e5db0d31b6bc233b4ca771 data/create/advancements/recipes/building_blocks/polished_cut_andesite_slab.json -24f0ff38c2ba66491895a43256a359ff3917fece data/create/advancements/recipes/building_blocks/polished_cut_andesite_slab_from_andesite_stonecutting.json bd8759817186f4e2ab0626092cf5b3b9ab69dc6e data/create/advancements/recipes/building_blocks/polished_cut_andesite_slab_from_stone_types_andesite_stonecutting.json 0402b4622b45632d9611cff3be31136592db6d9e data/create/advancements/recipes/building_blocks/polished_cut_andesite_slab_recycling.json c81cfec067185165a1291010be997e7c0767679f data/create/advancements/recipes/building_blocks/polished_cut_andesite_stairs.json -1b1c166b6c610c1c4e9a3fe5bb80fc2f92a88ac3 data/create/advancements/recipes/building_blocks/polished_cut_andesite_stairs_from_andesite_stonecutting.json 014828f212838ee0112c93dba1e59e1a3d2951d6 data/create/advancements/recipes/building_blocks/polished_cut_andesite_stairs_from_stone_types_andesite_stonecutting.json 78eb944a0ba1009c083391578210a9dbbbeb1a51 data/create/advancements/recipes/building_blocks/polished_cut_andesite_wall.json -793b9f64260b1ae87791f8155bb3622bfd9a2aa4 data/create/advancements/recipes/building_blocks/polished_cut_andesite_wall_from_andesite_stonecutting.json a99cfabefc305c676adb52688e5465ff1438104b data/create/advancements/recipes/building_blocks/polished_cut_andesite_wall_from_stone_types_andesite_stonecutting.json -ce0d3f812b0ddcba63575d3d3f2279f761241393 data/create/advancements/recipes/building_blocks/polished_cut_asurine_from_asurine_stonecutting.json ce453fa5a19ba6db69f33615bdf6dffc1e061fb1 data/create/advancements/recipes/building_blocks/polished_cut_asurine_from_stone_types_asurine_stonecutting.json 5c3a4cbe313a89bb9298d6adc242ae5a5505299e data/create/advancements/recipes/building_blocks/polished_cut_asurine_slab.json -1a4eb8eee354fe90c6e40f32d2d6bdaa9c15f2c5 data/create/advancements/recipes/building_blocks/polished_cut_asurine_slab_from_asurine_stonecutting.json 9ba88be9d02731b267cebe0cf77cab7b486c80e4 data/create/advancements/recipes/building_blocks/polished_cut_asurine_slab_from_stone_types_asurine_stonecutting.json d9e0db07102ecc634d72fde55d5841b4fec09b3a data/create/advancements/recipes/building_blocks/polished_cut_asurine_slab_recycling.json 78b220c9f84be02e9a21552e60c67a778863935c data/create/advancements/recipes/building_blocks/polished_cut_asurine_stairs.json -fc3372fa3a2a909a5d8b748a189b2334582579d5 data/create/advancements/recipes/building_blocks/polished_cut_asurine_stairs_from_asurine_stonecutting.json 14cae4987773d4126a372b2e0431fafb0112b48d data/create/advancements/recipes/building_blocks/polished_cut_asurine_stairs_from_stone_types_asurine_stonecutting.json a641b25a792497b114867323612ddb4daf112390 data/create/advancements/recipes/building_blocks/polished_cut_asurine_wall.json -c5e3cb2e9bcbacc9c2ca3f72ad85cb66aeb6ccdd data/create/advancements/recipes/building_blocks/polished_cut_asurine_wall_from_asurine_stonecutting.json e45bf9d53e7f30bd4d2b931b640c95e173d4ccd7 data/create/advancements/recipes/building_blocks/polished_cut_asurine_wall_from_stone_types_asurine_stonecutting.json -db1aa527e0da6f634afebb6b813db1454453f45a data/create/advancements/recipes/building_blocks/polished_cut_calcite_from_calcite_stonecutting.json e1be2af7938a206959a9faa8cc822446f256f747 data/create/advancements/recipes/building_blocks/polished_cut_calcite_from_stone_types_calcite_stonecutting.json 0bd8ba44a6008a2429b3f90c44359fd1e1a66227 data/create/advancements/recipes/building_blocks/polished_cut_calcite_slab.json -1f57101dada977599221f46709d64d63b18b10f1 data/create/advancements/recipes/building_blocks/polished_cut_calcite_slab_from_calcite_stonecutting.json fbbc756afe198573208fa5241042565d5c48ffad data/create/advancements/recipes/building_blocks/polished_cut_calcite_slab_from_stone_types_calcite_stonecutting.json b52e69396690a4fbd306cf8c280f0780542418cd data/create/advancements/recipes/building_blocks/polished_cut_calcite_slab_recycling.json 0f85cf66fb414481c848eaaceae4cefa0c7f628f data/create/advancements/recipes/building_blocks/polished_cut_calcite_stairs.json -8a08e6e095dee9deee72ef18bdb77f80c6b688ea data/create/advancements/recipes/building_blocks/polished_cut_calcite_stairs_from_calcite_stonecutting.json 14ad9e88b4671b981441f0a02e8ad3f65b065944 data/create/advancements/recipes/building_blocks/polished_cut_calcite_stairs_from_stone_types_calcite_stonecutting.json a64e4d43cbd115b89245c67907e474215ca64e97 data/create/advancements/recipes/building_blocks/polished_cut_calcite_wall.json -aef9526d769c8b3d78cc7e34bf540a47698b5d78 data/create/advancements/recipes/building_blocks/polished_cut_calcite_wall_from_calcite_stonecutting.json 974cd9faa99230dcbf93d31a80611de8c01dabff data/create/advancements/recipes/building_blocks/polished_cut_calcite_wall_from_stone_types_calcite_stonecutting.json -015feccc9da045e671bc470e44bb31b9cce1aade data/create/advancements/recipes/building_blocks/polished_cut_crimsite_from_crimsite_stonecutting.json 733b5b8c289840efc4d060f2d202d4b90363f675 data/create/advancements/recipes/building_blocks/polished_cut_crimsite_from_stone_types_crimsite_stonecutting.json 1d78f6c45f7c5675e404c40d0dd6abbcb4cda01b data/create/advancements/recipes/building_blocks/polished_cut_crimsite_slab.json -f6fb6766814d066dfe023ae6a69f314002fe7c9d data/create/advancements/recipes/building_blocks/polished_cut_crimsite_slab_from_crimsite_stonecutting.json d5356a34686a0c6f19b47816a8f400512316537f data/create/advancements/recipes/building_blocks/polished_cut_crimsite_slab_from_stone_types_crimsite_stonecutting.json 743fbd4306d368cb4e4b0d22c74c80e74f2cbd91 data/create/advancements/recipes/building_blocks/polished_cut_crimsite_slab_recycling.json 39521721a019e20070320c799c1581d16875bab0 data/create/advancements/recipes/building_blocks/polished_cut_crimsite_stairs.json -5516ddedf37ae6900dae7953dc17fccdd86c6065 data/create/advancements/recipes/building_blocks/polished_cut_crimsite_stairs_from_crimsite_stonecutting.json 750d4d09dd1e2cda1c34a73c449b07b9c2ea4296 data/create/advancements/recipes/building_blocks/polished_cut_crimsite_stairs_from_stone_types_crimsite_stonecutting.json eef80b2717b9092fc958407cddaa4cc89f7cc459 data/create/advancements/recipes/building_blocks/polished_cut_crimsite_wall.json -7e420e5b1e3a1180d9ec7c47d5f9ac9a5404daf8 data/create/advancements/recipes/building_blocks/polished_cut_crimsite_wall_from_crimsite_stonecutting.json d496be98d0943bf49a02c2682d42727362d94f5e data/create/advancements/recipes/building_blocks/polished_cut_crimsite_wall_from_stone_types_crimsite_stonecutting.json -fe4d5f127a5ec1c7e342e9886b01cdb8fc0c3c85 data/create/advancements/recipes/building_blocks/polished_cut_deepslate_from_deepslate_stonecutting.json fc927719af1bd26d3e8cbfaacf4d05afb0ac457f data/create/advancements/recipes/building_blocks/polished_cut_deepslate_from_stone_types_deepslate_stonecutting.json 2e60738cd3dc77fb7dedf3811d6d09ab27230563 data/create/advancements/recipes/building_blocks/polished_cut_deepslate_slab.json -ec3ce9a08e1ba5d2f306a82b9a8a8bef95aa790b data/create/advancements/recipes/building_blocks/polished_cut_deepslate_slab_from_deepslate_stonecutting.json 7e2bdfe97262a51361eb5b8c35ae8e255593f310 data/create/advancements/recipes/building_blocks/polished_cut_deepslate_slab_from_stone_types_deepslate_stonecutting.json 42f31b2ec87726ec51a5b849edaf1a825012a73f data/create/advancements/recipes/building_blocks/polished_cut_deepslate_slab_recycling.json 17030bdcd06e3f52a604aa6c293a11e46dbb0a47 data/create/advancements/recipes/building_blocks/polished_cut_deepslate_stairs.json -9145225b7c5f77d7e0a0720a2e00f11250d59a1e data/create/advancements/recipes/building_blocks/polished_cut_deepslate_stairs_from_deepslate_stonecutting.json 9dfc4fd5f88b60c41b4ab0f5f3677aaab5b28d6a data/create/advancements/recipes/building_blocks/polished_cut_deepslate_stairs_from_stone_types_deepslate_stonecutting.json d08dbd0babed893966486a4545a7a24f6f0f560b data/create/advancements/recipes/building_blocks/polished_cut_deepslate_wall.json -b7a44ceb7656204a7af0809c020f2b647b4fcef0 data/create/advancements/recipes/building_blocks/polished_cut_deepslate_wall_from_deepslate_stonecutting.json 2d311b911fbfdd26c080dbbdcae8cc8a3d2520f1 data/create/advancements/recipes/building_blocks/polished_cut_deepslate_wall_from_stone_types_deepslate_stonecutting.json -74cfe3cfe71046edbde90907100d7bb406af5135 data/create/advancements/recipes/building_blocks/polished_cut_diorite_from_diorite_stonecutting.json de71a69f54bd24d9fc882f4317c8cff7dcd3da48 data/create/advancements/recipes/building_blocks/polished_cut_diorite_from_stone_types_diorite_stonecutting.json d8f9f4daa2bff3b7aba51d27834f4b9c8db7eec8 data/create/advancements/recipes/building_blocks/polished_cut_diorite_slab.json -c78d225547da5c9455ab3914b56a8df2138c4ab6 data/create/advancements/recipes/building_blocks/polished_cut_diorite_slab_from_diorite_stonecutting.json 9a4aea18c2237a714178af2baff90bd958b3d924 data/create/advancements/recipes/building_blocks/polished_cut_diorite_slab_from_stone_types_diorite_stonecutting.json 9e72e81c93cd837fd43a1d77eae8116863bfef17 data/create/advancements/recipes/building_blocks/polished_cut_diorite_slab_recycling.json 90cd3e07b9802619709525a81a1c1fbd74705286 data/create/advancements/recipes/building_blocks/polished_cut_diorite_stairs.json -341bdb4871abb92499807f8acce4fa44c17ae6f1 data/create/advancements/recipes/building_blocks/polished_cut_diorite_stairs_from_diorite_stonecutting.json 85b9d415fef40a8d3ab023c7a9e9117a15b75c94 data/create/advancements/recipes/building_blocks/polished_cut_diorite_stairs_from_stone_types_diorite_stonecutting.json 812a8c9375b2ed654d71748415a14c7b1b1609d0 data/create/advancements/recipes/building_blocks/polished_cut_diorite_wall.json -f75679d70b1de13fccbe76a765830169ae1bee3b data/create/advancements/recipes/building_blocks/polished_cut_diorite_wall_from_diorite_stonecutting.json ca63c7f68fad077053b8b29139f4019bdef0e050 data/create/advancements/recipes/building_blocks/polished_cut_diorite_wall_from_stone_types_diorite_stonecutting.json -c85875b596fdbdb68b57278c4b5621303509471a data/create/advancements/recipes/building_blocks/polished_cut_dripstone_from_dripstone_block_stonecutting.json 11371c271e03942cd49daeed6fa978509eb45e30 data/create/advancements/recipes/building_blocks/polished_cut_dripstone_from_stone_types_dripstone_stonecutting.json cee2143d1ae757492011c281a94e24afe08874dd data/create/advancements/recipes/building_blocks/polished_cut_dripstone_slab.json -e973c34a8921bc4b4098f4772ca29414c45f14b0 data/create/advancements/recipes/building_blocks/polished_cut_dripstone_slab_from_dripstone_block_stonecutting.json 2ddf70a17df85fb6a46ace6141788d2b0dd61980 data/create/advancements/recipes/building_blocks/polished_cut_dripstone_slab_from_stone_types_dripstone_stonecutting.json f7bae45ba3c91ff89a2e641d1277fc188872454b data/create/advancements/recipes/building_blocks/polished_cut_dripstone_slab_recycling.json 9171343ce754e96fc2cc24605e88026be7e20e02 data/create/advancements/recipes/building_blocks/polished_cut_dripstone_stairs.json -33fb066aace3986b7b1f8c515e2cbf6c580e681d data/create/advancements/recipes/building_blocks/polished_cut_dripstone_stairs_from_dripstone_block_stonecutting.json ecd8b7df5c98e854df3c1bf7fd128c3b51dc5fd3 data/create/advancements/recipes/building_blocks/polished_cut_dripstone_stairs_from_stone_types_dripstone_stonecutting.json 1635be562287e2187f6917e234dd5a8b98a94edc data/create/advancements/recipes/building_blocks/polished_cut_dripstone_wall.json -42af59b805726b1c650ad51443694058c968f84f data/create/advancements/recipes/building_blocks/polished_cut_dripstone_wall_from_dripstone_block_stonecutting.json 353d093250d70108453ab7f16c15dfd224515986 data/create/advancements/recipes/building_blocks/polished_cut_dripstone_wall_from_stone_types_dripstone_stonecutting.json -57ff6d8b95242644f06f198c83064a9a23476c90 data/create/advancements/recipes/building_blocks/polished_cut_granite_from_granite_stonecutting.json 42148f769d22b6228a37ca25aaa0b81851ffdef7 data/create/advancements/recipes/building_blocks/polished_cut_granite_from_stone_types_granite_stonecutting.json bec1b27e1b40f88eba68afc83167ed381c2f9ce1 data/create/advancements/recipes/building_blocks/polished_cut_granite_slab.json -5774a14e5c813b41ebcc29534b7fc6092f43a8e8 data/create/advancements/recipes/building_blocks/polished_cut_granite_slab_from_granite_stonecutting.json 2b4c0748f62ecd67fc780c1e39587af095b7dda3 data/create/advancements/recipes/building_blocks/polished_cut_granite_slab_from_stone_types_granite_stonecutting.json 35b15a1c1a985a0527942f374cb7a65016f69a29 data/create/advancements/recipes/building_blocks/polished_cut_granite_slab_recycling.json 05cb927ea057ec082d49a060dd942b27f59316bd data/create/advancements/recipes/building_blocks/polished_cut_granite_stairs.json -0cbe19a89225385e5ae0c79f241a5f41ad06c779 data/create/advancements/recipes/building_blocks/polished_cut_granite_stairs_from_granite_stonecutting.json 747c521600debe796fd82a67bf1d2ee393ada20d data/create/advancements/recipes/building_blocks/polished_cut_granite_stairs_from_stone_types_granite_stonecutting.json 304d47863b4521021081090c6d42f0310b0058bc data/create/advancements/recipes/building_blocks/polished_cut_granite_wall.json -becbe8320b1c7916b734c365b1b4a98feac8c99e data/create/advancements/recipes/building_blocks/polished_cut_granite_wall_from_granite_stonecutting.json 8e23bef4cdc74e74c1046918ef9fe1fd93f438b7 data/create/advancements/recipes/building_blocks/polished_cut_granite_wall_from_stone_types_granite_stonecutting.json -99651c4b19095864948bbe34dfd86b72d80a8f27 data/create/advancements/recipes/building_blocks/polished_cut_limestone_from_limestone_stonecutting.json 32925d1bb83f8039945530aa954c12e2319b7512 data/create/advancements/recipes/building_blocks/polished_cut_limestone_from_stone_types_limestone_stonecutting.json bb1f57bf47974c9b64eebce016f0af6aa7199f64 data/create/advancements/recipes/building_blocks/polished_cut_limestone_slab.json -115220e1ad44ca3585d735e23ec980e72f148e63 data/create/advancements/recipes/building_blocks/polished_cut_limestone_slab_from_limestone_stonecutting.json 103aa558f05728c564480927b25ce32b15870435 data/create/advancements/recipes/building_blocks/polished_cut_limestone_slab_from_stone_types_limestone_stonecutting.json f29077df1a3706614309f5317936b335102bfa06 data/create/advancements/recipes/building_blocks/polished_cut_limestone_slab_recycling.json 820f2c0a803767c325e7589f4643e88dfa160f9c data/create/advancements/recipes/building_blocks/polished_cut_limestone_stairs.json -6efe0166d4d5d2674551f93dc8011abe1c3752c8 data/create/advancements/recipes/building_blocks/polished_cut_limestone_stairs_from_limestone_stonecutting.json f8346a8196fccb3790d444bff91be21bb1551559 data/create/advancements/recipes/building_blocks/polished_cut_limestone_stairs_from_stone_types_limestone_stonecutting.json c22ea50eea88bac5ec22c884fbafa741e3feb8e6 data/create/advancements/recipes/building_blocks/polished_cut_limestone_wall.json -f878e73130a51c3aeae8014f56a4d3d840df7447 data/create/advancements/recipes/building_blocks/polished_cut_limestone_wall_from_limestone_stonecutting.json 5ac9e432dd60a147a86d4a2462438ebe20eeaf26 data/create/advancements/recipes/building_blocks/polished_cut_limestone_wall_from_stone_types_limestone_stonecutting.json -ebef67f5d032d9bf272ad40c6f571c7e47c2c353 data/create/advancements/recipes/building_blocks/polished_cut_ochrum_from_ochrum_stonecutting.json 74eb441ff391d48c2f3bd444d9d113475eed8454 data/create/advancements/recipes/building_blocks/polished_cut_ochrum_from_stone_types_ochrum_stonecutting.json eeb5f15290c193030dda3e67663cee8d821f56e1 data/create/advancements/recipes/building_blocks/polished_cut_ochrum_slab.json -59b0e780eb286f61aa83a93d0d13334b8272e09d data/create/advancements/recipes/building_blocks/polished_cut_ochrum_slab_from_ochrum_stonecutting.json 562f948ee3129177bb0decbf5e794e0da379df35 data/create/advancements/recipes/building_blocks/polished_cut_ochrum_slab_from_stone_types_ochrum_stonecutting.json 844f9a89e6d1e961222be0c36a1a26ad686fd978 data/create/advancements/recipes/building_blocks/polished_cut_ochrum_slab_recycling.json 771ac021228b5a2e9aa79844466383c363d5c429 data/create/advancements/recipes/building_blocks/polished_cut_ochrum_stairs.json -22ebc95b43a8204629d388c7022131b378d5eaac data/create/advancements/recipes/building_blocks/polished_cut_ochrum_stairs_from_ochrum_stonecutting.json 4b10c2073ad9394ab77aaefbb5508d30d8b8dfe2 data/create/advancements/recipes/building_blocks/polished_cut_ochrum_stairs_from_stone_types_ochrum_stonecutting.json 322fdbbb7121cb6dac318ed19ac6cc47445c008d data/create/advancements/recipes/building_blocks/polished_cut_ochrum_wall.json -5f514570f239992fd7b4e98c360763872ed89fa4 data/create/advancements/recipes/building_blocks/polished_cut_ochrum_wall_from_ochrum_stonecutting.json c725c9f6dbc16c6cc3938c30f9443c6187be5bf4 data/create/advancements/recipes/building_blocks/polished_cut_ochrum_wall_from_stone_types_ochrum_stonecutting.json -e84d862c3310a71838bedf280bcda85e226b9a42 data/create/advancements/recipes/building_blocks/polished_cut_scorchia_from_scorchia_stonecutting.json d1f0ce4819a7edade4ab546f6cc5e29690b13b81 data/create/advancements/recipes/building_blocks/polished_cut_scorchia_from_stone_types_scorchia_stonecutting.json 9712d2d270bdba9869cf77b2336b166347128a9a data/create/advancements/recipes/building_blocks/polished_cut_scorchia_slab.json -e0c17f7ae37157ff60ec9a8e9b390fac586c802c data/create/advancements/recipes/building_blocks/polished_cut_scorchia_slab_from_scorchia_stonecutting.json dc5d46d905d0ee24b6271c369b2b13278691b00b data/create/advancements/recipes/building_blocks/polished_cut_scorchia_slab_from_stone_types_scorchia_stonecutting.json 1193b4d04da1c64ba383345c807b0beec15f8aa8 data/create/advancements/recipes/building_blocks/polished_cut_scorchia_slab_recycling.json 2116f04d7857b5fa05c2dc295b4eed7535ea4b70 data/create/advancements/recipes/building_blocks/polished_cut_scorchia_stairs.json -41133a2acc5f56651623f23559e00c2f56a28f17 data/create/advancements/recipes/building_blocks/polished_cut_scorchia_stairs_from_scorchia_stonecutting.json 4684fbf3187c171fd50ec5a4190251f5aa42f9f1 data/create/advancements/recipes/building_blocks/polished_cut_scorchia_stairs_from_stone_types_scorchia_stonecutting.json cc9d5c26274d0a90185399eb6faa584623fa879d data/create/advancements/recipes/building_blocks/polished_cut_scorchia_wall.json -21cb6cfe7956dcdee588c49844c107964193a254 data/create/advancements/recipes/building_blocks/polished_cut_scorchia_wall_from_scorchia_stonecutting.json 52dc08e1a1068e77b36964c0f561477a4d033984 data/create/advancements/recipes/building_blocks/polished_cut_scorchia_wall_from_stone_types_scorchia_stonecutting.json -c45ad4c7732914ce6dd36c22c445d257ba8fe18b data/create/advancements/recipes/building_blocks/polished_cut_scoria_from_scoria_stonecutting.json adac266360d879be47fd07c14ad0251c2751d2c6 data/create/advancements/recipes/building_blocks/polished_cut_scoria_from_stone_types_scoria_stonecutting.json 50b550dd3d2e48173c6124de445e9370590fe1f1 data/create/advancements/recipes/building_blocks/polished_cut_scoria_slab.json -ba60bf03f7135072e41f09e72e8984e0ed733457 data/create/advancements/recipes/building_blocks/polished_cut_scoria_slab_from_scoria_stonecutting.json 2c781b6cacf4f128db1a4d9202a3c7e6d8ba31f6 data/create/advancements/recipes/building_blocks/polished_cut_scoria_slab_from_stone_types_scoria_stonecutting.json 10b1ab8a11f1ae49cd65142fef0ab80c09f95097 data/create/advancements/recipes/building_blocks/polished_cut_scoria_slab_recycling.json 36de862bd8cf39dcef4c1b2f98cf74868897ee3c data/create/advancements/recipes/building_blocks/polished_cut_scoria_stairs.json -f32d2ad9d0092482d6e0cf06d6dc0e5539f085a5 data/create/advancements/recipes/building_blocks/polished_cut_scoria_stairs_from_scoria_stonecutting.json 1e2fd943098090c1dc572f6724f91befebe25835 data/create/advancements/recipes/building_blocks/polished_cut_scoria_stairs_from_stone_types_scoria_stonecutting.json 30d402883893aea3417e78f9dfdc9cb65728717e data/create/advancements/recipes/building_blocks/polished_cut_scoria_wall.json -e5ae4d31cc1c2180e168f635ad0c761ec67d42eb data/create/advancements/recipes/building_blocks/polished_cut_scoria_wall_from_scoria_stonecutting.json 357bbd5b5cfdd3b06fdf64b6717e03817394e6ee data/create/advancements/recipes/building_blocks/polished_cut_scoria_wall_from_stone_types_scoria_stonecutting.json fd183ac1971f718a60a24951511650be0280b85d data/create/advancements/recipes/building_blocks/polished_cut_tuff_from_stone_types_tuff_stonecutting.json -2f12f90f0ef41eac8fe31fa6c85911cb3b4be391 data/create/advancements/recipes/building_blocks/polished_cut_tuff_from_tuff_stonecutting.json 58fa91dc84360c7806a14a840f41f9df41084065 data/create/advancements/recipes/building_blocks/polished_cut_tuff_slab.json d810fea4c007b6efc1b5ba63c7b2ed0e2a1a9e64 data/create/advancements/recipes/building_blocks/polished_cut_tuff_slab_from_stone_types_tuff_stonecutting.json -4712bfe8e6c7a14ad0eb81bc575c85f89de8ea2a data/create/advancements/recipes/building_blocks/polished_cut_tuff_slab_from_tuff_stonecutting.json 61e78fc4390afc28cc4e6a9759f836fe85d2f928 data/create/advancements/recipes/building_blocks/polished_cut_tuff_slab_recycling.json 81b4c37bc0a9b4301079da4050b2084af05329d3 data/create/advancements/recipes/building_blocks/polished_cut_tuff_stairs.json 58ed35ba42820f59385c52e1ab3a701d231c1849 data/create/advancements/recipes/building_blocks/polished_cut_tuff_stairs_from_stone_types_tuff_stonecutting.json -63b41b0e721e959585b78dfc292b9d13e8d7097e data/create/advancements/recipes/building_blocks/polished_cut_tuff_stairs_from_tuff_stonecutting.json 8c50df95e49355504b9475bb97e288be7f9c0068 data/create/advancements/recipes/building_blocks/polished_cut_tuff_wall.json 65e48daaa45b15c2ac5049571bde967a5184e1bf data/create/advancements/recipes/building_blocks/polished_cut_tuff_wall_from_stone_types_tuff_stonecutting.json -b773afaf746e73b4c17542b274192e3876ab6248 data/create/advancements/recipes/building_blocks/polished_cut_tuff_wall_from_tuff_stonecutting.json b4a53b96d45e8b5c0ced15b988174e1fe5944639 data/create/advancements/recipes/building_blocks/polished_cut_veridium_from_stone_types_veridium_stonecutting.json -38072344ca3a2b3a1a8da5aa56c1912bb05ae13d data/create/advancements/recipes/building_blocks/polished_cut_veridium_from_veridium_stonecutting.json 69a10ac4a77c3595350e4dcd5ea837fd96976ccf data/create/advancements/recipes/building_blocks/polished_cut_veridium_slab.json 894f5a897b85ea5407da3efe1dc06e183b6409ca data/create/advancements/recipes/building_blocks/polished_cut_veridium_slab_from_stone_types_veridium_stonecutting.json -ec956d5484f363dd9151cac54644d17a9c9d2f17 data/create/advancements/recipes/building_blocks/polished_cut_veridium_slab_from_veridium_stonecutting.json d4cbeca358f3996000b5278fcd775336dab6378d data/create/advancements/recipes/building_blocks/polished_cut_veridium_slab_recycling.json fb2ee402fe6fd24b2459f133eacdfed19601eef2 data/create/advancements/recipes/building_blocks/polished_cut_veridium_stairs.json 2a8fb44e7534ca0f39bae9cbeab5009bd5a84e07 data/create/advancements/recipes/building_blocks/polished_cut_veridium_stairs_from_stone_types_veridium_stonecutting.json -40d4e6e43b718e882f281d9dcc097fab4d9b330e data/create/advancements/recipes/building_blocks/polished_cut_veridium_stairs_from_veridium_stonecutting.json 052281d742987d3456b91463e390f37726033d4b data/create/advancements/recipes/building_blocks/polished_cut_veridium_wall.json e25273889fffad567fc3d5e6130b0cd7d935829d data/create/advancements/recipes/building_blocks/polished_cut_veridium_wall_from_stone_types_veridium_stonecutting.json -780447628273616412360ba3ced244fe715bbb44 data/create/advancements/recipes/building_blocks/polished_cut_veridium_wall_from_veridium_stonecutting.json 8bea81a106b37711be7e5432d1e6f285887d4646 data/create/advancements/recipes/building_blocks/rose_quartz_block_from_rose_quartz_stonecutting.json 7df54ae1e872e1d61d3158402c2ca12f64f7ffbd data/create/advancements/recipes/building_blocks/rose_quartz_tiles_from_polished_rose_quartz_stonecutting.json -70ef3a57fa2279f49e409b4b799efe5f056b73b4 data/create/advancements/recipes/building_blocks/scorchia_pillar_from_scorchia_stonecutting.json +707ea60c2c14e97dd1ed32a193955e5b01cf1fb8 data/create/advancements/recipes/building_blocks/scorchia_from_stone_types_scorchia_stonecutting.json 1d72cd68a6265a9c4724f0aefd15bc7b4797f559 data/create/advancements/recipes/building_blocks/scorchia_pillar_from_stone_types_scorchia_stonecutting.json -a6b9ed06818f9a49202f420b17270b58f6256784 data/create/advancements/recipes/building_blocks/scoria_pillar_from_scoria_stonecutting.json +94cfe47b892e05cdcee47694b7629968092b1a5b data/create/advancements/recipes/building_blocks/scoria_from_stone_types_scoria_stonecutting.json 0a365d58fbcbad21a77cbf1e20d98d3a8af6f418 data/create/advancements/recipes/building_blocks/scoria_pillar_from_stone_types_scoria_stonecutting.json -4814118f7d05a4bce1dc1b37d1f8055b8249596f data/create/advancements/recipes/building_blocks/small_andesite_bricks_from_andesite_stonecutting.json a7f5ff6824fb2f316616cd4e134797ad22d2ee66 data/create/advancements/recipes/building_blocks/small_andesite_bricks_from_stone_types_andesite_stonecutting.json 1789e279b6de73a98b295c4942a476bc3d38dd9a data/create/advancements/recipes/building_blocks/small_andesite_brick_slab.json -5f98ecd44b886feea3e3b76bed101d044bf6e0ed data/create/advancements/recipes/building_blocks/small_andesite_brick_slab_from_andesite_stonecutting.json 0d1d248f202f0deb40ba49e177df8586f12f37eb data/create/advancements/recipes/building_blocks/small_andesite_brick_slab_from_stone_types_andesite_stonecutting.json bc20a7f4160b5bebfdda451b287f846f91182d5c data/create/advancements/recipes/building_blocks/small_andesite_brick_slab_recycling.json c22d881802f106981fed1ca5cd38ee6862400fd2 data/create/advancements/recipes/building_blocks/small_andesite_brick_stairs.json -dfe3d60b5614282fc622f04676e50d3ad522f20e data/create/advancements/recipes/building_blocks/small_andesite_brick_stairs_from_andesite_stonecutting.json 6540aa9c8d64d7819ae3f517f016dc018a2e0d12 data/create/advancements/recipes/building_blocks/small_andesite_brick_stairs_from_stone_types_andesite_stonecutting.json 8c6d9e3a9511723db7df84c52ea789afec14d39b data/create/advancements/recipes/building_blocks/small_andesite_brick_wall.json -fb67df4773453a1296b44d2ce441200fa7ca1384 data/create/advancements/recipes/building_blocks/small_andesite_brick_wall_from_andesite_stonecutting.json 85456fc1a20cabbe3f5b242852681165ae564b65 data/create/advancements/recipes/building_blocks/small_andesite_brick_wall_from_stone_types_andesite_stonecutting.json -3365609bbda40bc55bc16e421f9e4b9d49dd4820 data/create/advancements/recipes/building_blocks/small_asurine_bricks_from_asurine_stonecutting.json 04b0c0fd65bdee5613cce2af3a70c896bcd05a25 data/create/advancements/recipes/building_blocks/small_asurine_bricks_from_stone_types_asurine_stonecutting.json 20d6b979945c97ad793a2ee7e76462ec8666a2c5 data/create/advancements/recipes/building_blocks/small_asurine_brick_slab.json -cf6f94807f42842e58ed0726188b0298d30bc687 data/create/advancements/recipes/building_blocks/small_asurine_brick_slab_from_asurine_stonecutting.json 3d9fa7cf70db4d36ddc265107af9413cc53e1773 data/create/advancements/recipes/building_blocks/small_asurine_brick_slab_from_stone_types_asurine_stonecutting.json db00b0de569c4e7123ec32594300b81d461e10d1 data/create/advancements/recipes/building_blocks/small_asurine_brick_slab_recycling.json a9c5927c48d20925f6b48de68fd65dc07e63b9a0 data/create/advancements/recipes/building_blocks/small_asurine_brick_stairs.json -f890251ed3367270a9567f52357b677727c31b72 data/create/advancements/recipes/building_blocks/small_asurine_brick_stairs_from_asurine_stonecutting.json 6f06768b6dacd285ebbca197ac3b8143d73ce4f2 data/create/advancements/recipes/building_blocks/small_asurine_brick_stairs_from_stone_types_asurine_stonecutting.json 677b259ea798f8f23d08edd16c882463df2089d9 data/create/advancements/recipes/building_blocks/small_asurine_brick_wall.json -52545ed8d5106f9b197db3b5e1a592adbdc5449c data/create/advancements/recipes/building_blocks/small_asurine_brick_wall_from_asurine_stonecutting.json ddfb29ffebcb2f5af04537c585887c87429715dd data/create/advancements/recipes/building_blocks/small_asurine_brick_wall_from_stone_types_asurine_stonecutting.json -66978cec93e792b13d5eba1140063ea32b1261b3 data/create/advancements/recipes/building_blocks/small_calcite_bricks_from_calcite_stonecutting.json 23fa022abb382a4f80e56af347bd1b4c28d3d720 data/create/advancements/recipes/building_blocks/small_calcite_bricks_from_stone_types_calcite_stonecutting.json ff9e6190e79331b6e0162adbd3c66f1af1bcb7fd data/create/advancements/recipes/building_blocks/small_calcite_brick_slab.json -d2b0e019c102929f7759cee55108c69047a29046 data/create/advancements/recipes/building_blocks/small_calcite_brick_slab_from_calcite_stonecutting.json a1319037285be81db4254f67aaf2ab7fc7ec9127 data/create/advancements/recipes/building_blocks/small_calcite_brick_slab_from_stone_types_calcite_stonecutting.json 56e5164897ed62999c836462b32bd2dc12582ddf data/create/advancements/recipes/building_blocks/small_calcite_brick_slab_recycling.json a7b394adf6157b304069ad946005530083df33bf data/create/advancements/recipes/building_blocks/small_calcite_brick_stairs.json -b479bfe16955d922e99e3533c29c1d6c59eb12ac data/create/advancements/recipes/building_blocks/small_calcite_brick_stairs_from_calcite_stonecutting.json 346f3dc1829a52266c4c900edfb886283715864c data/create/advancements/recipes/building_blocks/small_calcite_brick_stairs_from_stone_types_calcite_stonecutting.json 532b2b55855cdde057d65cfd01ce0cf9ebea6f31 data/create/advancements/recipes/building_blocks/small_calcite_brick_wall.json -39b23661bbf7d9d62eb38b1afe20238e4bad3e16 data/create/advancements/recipes/building_blocks/small_calcite_brick_wall_from_calcite_stonecutting.json 34f37aa07bb36c91d3024d5eda41104208f2080a data/create/advancements/recipes/building_blocks/small_calcite_brick_wall_from_stone_types_calcite_stonecutting.json -adbd957b4dd89e7fe4ba26340ea55c0fb423eef3 data/create/advancements/recipes/building_blocks/small_crimsite_bricks_from_crimsite_stonecutting.json 96b2b6ad28365170ce7f455fbcbca3224ac14933 data/create/advancements/recipes/building_blocks/small_crimsite_bricks_from_stone_types_crimsite_stonecutting.json 7a6b95cb5b8c810ba2d839f69895f389175ff408 data/create/advancements/recipes/building_blocks/small_crimsite_brick_slab.json -2864947509552452071e31a0d1a555432caf8838 data/create/advancements/recipes/building_blocks/small_crimsite_brick_slab_from_crimsite_stonecutting.json 448bc0f89c2225645dd60f9f30c42a39e8bd53cb data/create/advancements/recipes/building_blocks/small_crimsite_brick_slab_from_stone_types_crimsite_stonecutting.json 4482ce2e29bb1521ce2460bbf0b207cf88a19c22 data/create/advancements/recipes/building_blocks/small_crimsite_brick_slab_recycling.json 0f4662e48240abf0e901825e4465207a88a2217c data/create/advancements/recipes/building_blocks/small_crimsite_brick_stairs.json -f2947ab9561bfcba94c8dcff20db4ff795bf107e data/create/advancements/recipes/building_blocks/small_crimsite_brick_stairs_from_crimsite_stonecutting.json 184338025eccdd8d04f845b8258ebd7407835986 data/create/advancements/recipes/building_blocks/small_crimsite_brick_stairs_from_stone_types_crimsite_stonecutting.json 0d6d597aa80b57edde938668385db43d420af98e data/create/advancements/recipes/building_blocks/small_crimsite_brick_wall.json -b58ae10e67304eeb2b3b2f5279b1a64bdcfe4c6c data/create/advancements/recipes/building_blocks/small_crimsite_brick_wall_from_crimsite_stonecutting.json aeb2725cbf8c199dd7265400c572d1ed6ca91562 data/create/advancements/recipes/building_blocks/small_crimsite_brick_wall_from_stone_types_crimsite_stonecutting.json -31620ecb1087061fa0a376d7d53b6c15f0534f9c data/create/advancements/recipes/building_blocks/small_deepslate_bricks_from_deepslate_stonecutting.json 30b85e84ed217d8922e51ec55185427d2a2d086a data/create/advancements/recipes/building_blocks/small_deepslate_bricks_from_stone_types_deepslate_stonecutting.json feedbaf30137c46abee2121d2722ea33093a4416 data/create/advancements/recipes/building_blocks/small_deepslate_brick_slab.json -a40e98e4a73ef619600404ae56a2ad55aa30d524 data/create/advancements/recipes/building_blocks/small_deepslate_brick_slab_from_deepslate_stonecutting.json 8995c947661005788139b21e2619f1effb3cdef3 data/create/advancements/recipes/building_blocks/small_deepslate_brick_slab_from_stone_types_deepslate_stonecutting.json 46499a57073daa229e9d7d246d140613eea6c1f2 data/create/advancements/recipes/building_blocks/small_deepslate_brick_slab_recycling.json c1eed3f8f35e1cc727248739c6dfc895cea582f6 data/create/advancements/recipes/building_blocks/small_deepslate_brick_stairs.json -fbd87be950e5a6208d0bb580359aa0e3d22b4985 data/create/advancements/recipes/building_blocks/small_deepslate_brick_stairs_from_deepslate_stonecutting.json 2edbab4009e556b14401d1b68ea84e2c528a88da data/create/advancements/recipes/building_blocks/small_deepslate_brick_stairs_from_stone_types_deepslate_stonecutting.json 355b624f750b2d7e35e9d702cc49c1a52a256fd4 data/create/advancements/recipes/building_blocks/small_deepslate_brick_wall.json -43ad8f7909ed449bd025d3d76fd6b526b7235461 data/create/advancements/recipes/building_blocks/small_deepslate_brick_wall_from_deepslate_stonecutting.json 49059b58da67551f1a3ab28a928fd7dad9af3ea9 data/create/advancements/recipes/building_blocks/small_deepslate_brick_wall_from_stone_types_deepslate_stonecutting.json -8c0ee02a5dc6aedb59a357c3d89f6ef5e429b050 data/create/advancements/recipes/building_blocks/small_diorite_bricks_from_diorite_stonecutting.json 6927548e361b70e9b8ef0aaaa51b1dfbf65d18fd data/create/advancements/recipes/building_blocks/small_diorite_bricks_from_stone_types_diorite_stonecutting.json 3f790638b8317ad8b9ae6f328f37f9eef25f06d3 data/create/advancements/recipes/building_blocks/small_diorite_brick_slab.json -0f5a6c0a37eeec5882a0511f6c40365745cef6ec data/create/advancements/recipes/building_blocks/small_diorite_brick_slab_from_diorite_stonecutting.json 176a72cc538a2a90b9555f95e32e3d2ce23269d9 data/create/advancements/recipes/building_blocks/small_diorite_brick_slab_from_stone_types_diorite_stonecutting.json fe2754dc055e0354be7c20778fe3e80a810ab438 data/create/advancements/recipes/building_blocks/small_diorite_brick_slab_recycling.json 18f401796ed693dadc4dea18d6037ed69e2c12f6 data/create/advancements/recipes/building_blocks/small_diorite_brick_stairs.json -e18121b3e6039c6179b57833c07fbec1b11f5cd5 data/create/advancements/recipes/building_blocks/small_diorite_brick_stairs_from_diorite_stonecutting.json 3749e01ce6c74a563cd04e978696debbdca203bc data/create/advancements/recipes/building_blocks/small_diorite_brick_stairs_from_stone_types_diorite_stonecutting.json d0ac16024b551016068be0899b733fdef72ea9f9 data/create/advancements/recipes/building_blocks/small_diorite_brick_wall.json -02be9eb2ca70c4e703264fdb21fce75e55e97456 data/create/advancements/recipes/building_blocks/small_diorite_brick_wall_from_diorite_stonecutting.json bc87c8dab082a77c959c827f0701f67850817949 data/create/advancements/recipes/building_blocks/small_diorite_brick_wall_from_stone_types_diorite_stonecutting.json -e6e95a7fbfc8b3496dcdab16ef1eac0b0bb94eae data/create/advancements/recipes/building_blocks/small_dripstone_bricks_from_dripstone_block_stonecutting.json 5878f41ace273540e31b96cbaf02634f8538c88a data/create/advancements/recipes/building_blocks/small_dripstone_bricks_from_stone_types_dripstone_stonecutting.json 836bd34938c6a595cb44eda586bcc192968668e9 data/create/advancements/recipes/building_blocks/small_dripstone_brick_slab.json -e1ae6fed398f564dfc0a4479fb43028354b416c1 data/create/advancements/recipes/building_blocks/small_dripstone_brick_slab_from_dripstone_block_stonecutting.json 27ee215de13d67cce47eee2af17ae9842c970643 data/create/advancements/recipes/building_blocks/small_dripstone_brick_slab_from_stone_types_dripstone_stonecutting.json 4db8af71c3e19b278345b4609b111eb04dbfdf89 data/create/advancements/recipes/building_blocks/small_dripstone_brick_slab_recycling.json 1b1282448e7ead212dc6e06c9be3fb7db085f8b7 data/create/advancements/recipes/building_blocks/small_dripstone_brick_stairs.json -bdf395e8ed249da1be352e60c7887ec2f94e5c8a data/create/advancements/recipes/building_blocks/small_dripstone_brick_stairs_from_dripstone_block_stonecutting.json 5b9ecba2ec4e811cc198900b7a450710b264a753 data/create/advancements/recipes/building_blocks/small_dripstone_brick_stairs_from_stone_types_dripstone_stonecutting.json 139d6afec080422204fcbdc196cb15cd96f46569 data/create/advancements/recipes/building_blocks/small_dripstone_brick_wall.json -d9198ec9f6f32075773242057e1f161073bb2dad data/create/advancements/recipes/building_blocks/small_dripstone_brick_wall_from_dripstone_block_stonecutting.json 66ef69489c13d9ee2c6f95d394f459bd150419d7 data/create/advancements/recipes/building_blocks/small_dripstone_brick_wall_from_stone_types_dripstone_stonecutting.json -302f0c875b3161b3a27317a5c304d58826eaa819 data/create/advancements/recipes/building_blocks/small_granite_bricks_from_granite_stonecutting.json 8f0ce0fdc6fcbeffb6191073bfea9ebd2ad2a02e data/create/advancements/recipes/building_blocks/small_granite_bricks_from_stone_types_granite_stonecutting.json f65865a9e9f16f0fa54c4816d9b0055248fbaa55 data/create/advancements/recipes/building_blocks/small_granite_brick_slab.json -88edd7ff2dfad777cecda4124447efcbdc8e718e data/create/advancements/recipes/building_blocks/small_granite_brick_slab_from_granite_stonecutting.json 446b4826ebcde9b00abf8097dc109d8604264347 data/create/advancements/recipes/building_blocks/small_granite_brick_slab_from_stone_types_granite_stonecutting.json edb952e30dbfeed1ec3e5b7e2c3b4a70e228e6b2 data/create/advancements/recipes/building_blocks/small_granite_brick_slab_recycling.json 2111445829f6df6ba62a9ecb4fb7a3bb34d7b778 data/create/advancements/recipes/building_blocks/small_granite_brick_stairs.json -e96634deadd5921b886da118adb228d3881d5d24 data/create/advancements/recipes/building_blocks/small_granite_brick_stairs_from_granite_stonecutting.json 163fcc206f102e5ce11c892cb8e76c61a569a3d8 data/create/advancements/recipes/building_blocks/small_granite_brick_stairs_from_stone_types_granite_stonecutting.json 67bf539fa68126d305052c391431b1ad7d71144c data/create/advancements/recipes/building_blocks/small_granite_brick_wall.json -7da46eda5f8e9f5db5f4efd46d1ce34b00b63be8 data/create/advancements/recipes/building_blocks/small_granite_brick_wall_from_granite_stonecutting.json cf10fb6a02ae12e65879364c9590432b3498d4e7 data/create/advancements/recipes/building_blocks/small_granite_brick_wall_from_stone_types_granite_stonecutting.json -1b1d08fb045d86572400c286f85cef5989469237 data/create/advancements/recipes/building_blocks/small_limestone_bricks_from_limestone_stonecutting.json 2ff1edd231c0b2acfd34f39eac1fc80bd752f244 data/create/advancements/recipes/building_blocks/small_limestone_bricks_from_stone_types_limestone_stonecutting.json b604dc2918b573af37f718af988cf3c89a24709e data/create/advancements/recipes/building_blocks/small_limestone_brick_slab.json -5955f67784d27b04b30fe27296d2fe63fad9ed39 data/create/advancements/recipes/building_blocks/small_limestone_brick_slab_from_limestone_stonecutting.json a20865d998aa936aad25396be1ff00b6d5e8f63a data/create/advancements/recipes/building_blocks/small_limestone_brick_slab_from_stone_types_limestone_stonecutting.json 9bf7c0d00e9b1f4c7ae36147a5762793236566ea data/create/advancements/recipes/building_blocks/small_limestone_brick_slab_recycling.json 594c73f4ccdd35ee5e911b993917919b17e80714 data/create/advancements/recipes/building_blocks/small_limestone_brick_stairs.json -872266f9aa7571483abf2ca4ec04c0771140eac5 data/create/advancements/recipes/building_blocks/small_limestone_brick_stairs_from_limestone_stonecutting.json cdc07a2d3696bfeb6fb9575f94af1100a0e7de9b data/create/advancements/recipes/building_blocks/small_limestone_brick_stairs_from_stone_types_limestone_stonecutting.json 0f12d7eb36c104ad77399830dd22db77b022f530 data/create/advancements/recipes/building_blocks/small_limestone_brick_wall.json -accc8d340112c86dad6be368eecea3e70aa9d3dd data/create/advancements/recipes/building_blocks/small_limestone_brick_wall_from_limestone_stonecutting.json e6293510710de1f6d307d4b54d84f4bdabbdc345 data/create/advancements/recipes/building_blocks/small_limestone_brick_wall_from_stone_types_limestone_stonecutting.json -7cf0fe6afe51c584a320c4ca2120855a12b30e55 data/create/advancements/recipes/building_blocks/small_ochrum_bricks_from_ochrum_stonecutting.json 44eb790d07b41879e995aeb83795b4cc103eb9f3 data/create/advancements/recipes/building_blocks/small_ochrum_bricks_from_stone_types_ochrum_stonecutting.json 07fffaf1b1bc0f253f6ae543706999a0da4b4c27 data/create/advancements/recipes/building_blocks/small_ochrum_brick_slab.json -c54f7d7b26550b1364201fe3aee0e46ac60521cd data/create/advancements/recipes/building_blocks/small_ochrum_brick_slab_from_ochrum_stonecutting.json 7c2c5022487e4132b9f6be53cccfb4262e9731ba data/create/advancements/recipes/building_blocks/small_ochrum_brick_slab_from_stone_types_ochrum_stonecutting.json e70c573bd8f089c14d383c1c5804840a3b400fff data/create/advancements/recipes/building_blocks/small_ochrum_brick_slab_recycling.json 3e36b894950127455c9bb8b343a78d14476aa400 data/create/advancements/recipes/building_blocks/small_ochrum_brick_stairs.json -fefc69b6b138e86fc11963e8a83bc53936b9a1c4 data/create/advancements/recipes/building_blocks/small_ochrum_brick_stairs_from_ochrum_stonecutting.json 4e629b37d1b744d72a9fc2b65891ec3a705f7248 data/create/advancements/recipes/building_blocks/small_ochrum_brick_stairs_from_stone_types_ochrum_stonecutting.json a5e5c89ac9f955738447dd6ec085cc1e3dcf2b5d data/create/advancements/recipes/building_blocks/small_ochrum_brick_wall.json -ce03b9a6f85015d5299da833fad67576b1430750 data/create/advancements/recipes/building_blocks/small_ochrum_brick_wall_from_ochrum_stonecutting.json be3be3408e5790fe1dde49ca67418727013c30cb data/create/advancements/recipes/building_blocks/small_ochrum_brick_wall_from_stone_types_ochrum_stonecutting.json 5726f2bfc28a2151d9caf157244bfc4f44c40810 data/create/advancements/recipes/building_blocks/small_rose_quartz_tiles_from_polished_rose_quartz_stonecutting.json -6b7fc376cab6110fae81e20859139cec6be18746 data/create/advancements/recipes/building_blocks/small_scorchia_bricks_from_scorchia_stonecutting.json e401f6070e3a3c9a65dd71c9fd53be02f0436cfb data/create/advancements/recipes/building_blocks/small_scorchia_bricks_from_stone_types_scorchia_stonecutting.json f5ffaad4354b5c1a981010f078a044c3ebd8d7f2 data/create/advancements/recipes/building_blocks/small_scorchia_brick_slab.json -26ebf0c69b4afd69f94a6c1eb7715658528dabcd data/create/advancements/recipes/building_blocks/small_scorchia_brick_slab_from_scorchia_stonecutting.json 4c286c0099347c96007e0e691502589ff3e0146d data/create/advancements/recipes/building_blocks/small_scorchia_brick_slab_from_stone_types_scorchia_stonecutting.json c8f638c6f17ac0f32dc04913c47f0c3eea8ed37c data/create/advancements/recipes/building_blocks/small_scorchia_brick_slab_recycling.json 93b46f1d97a536758043cceebc477f627d4101e6 data/create/advancements/recipes/building_blocks/small_scorchia_brick_stairs.json -5c5be6d9797a62a6be548419a9644d66a388f8e4 data/create/advancements/recipes/building_blocks/small_scorchia_brick_stairs_from_scorchia_stonecutting.json 5030c44417e4a91260350832feb9778f69d47d12 data/create/advancements/recipes/building_blocks/small_scorchia_brick_stairs_from_stone_types_scorchia_stonecutting.json d9b1479eb23b05d2f0682de0e87ca2f3742b4411 data/create/advancements/recipes/building_blocks/small_scorchia_brick_wall.json -5833239eb6ffb0a20b460937405830047ab0b6dd data/create/advancements/recipes/building_blocks/small_scorchia_brick_wall_from_scorchia_stonecutting.json 83928d13769bd6ae80aef2db76d11469b7f7c3c4 data/create/advancements/recipes/building_blocks/small_scorchia_brick_wall_from_stone_types_scorchia_stonecutting.json -5607e7047009c3cb6b202d8eaab798aec22d1d33 data/create/advancements/recipes/building_blocks/small_scoria_bricks_from_scoria_stonecutting.json 650c1ab08e635ef947eece59d46d14307ca1197c data/create/advancements/recipes/building_blocks/small_scoria_bricks_from_stone_types_scoria_stonecutting.json 77819931bbbe728366ec869d4fe8021f9db2daae data/create/advancements/recipes/building_blocks/small_scoria_brick_slab.json -8d47ae001eae586ec5a00e33e891fe76a8000fa3 data/create/advancements/recipes/building_blocks/small_scoria_brick_slab_from_scoria_stonecutting.json abd35e55a8ae318c8fb6487054cbdce3a51fe10d data/create/advancements/recipes/building_blocks/small_scoria_brick_slab_from_stone_types_scoria_stonecutting.json f2dd9d62d885293ea4b73a7bac1086e9337416f1 data/create/advancements/recipes/building_blocks/small_scoria_brick_slab_recycling.json 843da192a81e34815359503f0e28e4ff09167dda data/create/advancements/recipes/building_blocks/small_scoria_brick_stairs.json -58f31b26b5e3d5b8a64ac42f65cbfa48d06bf3a7 data/create/advancements/recipes/building_blocks/small_scoria_brick_stairs_from_scoria_stonecutting.json c38bb834170af090f10ad7f31287c7b5a65a197c data/create/advancements/recipes/building_blocks/small_scoria_brick_stairs_from_stone_types_scoria_stonecutting.json 7c92dc02a0aab36049ab5b28d34e5b4d977d78d6 data/create/advancements/recipes/building_blocks/small_scoria_brick_wall.json -422de1524c11b51541d78690f1bff5a63c902b13 data/create/advancements/recipes/building_blocks/small_scoria_brick_wall_from_scoria_stonecutting.json 8a4ba027c1868e1e6bc6b8bb14213bc78516d06b data/create/advancements/recipes/building_blocks/small_scoria_brick_wall_from_stone_types_scoria_stonecutting.json 666043b181f9ef520933c5891b55b0cb8815f569 data/create/advancements/recipes/building_blocks/small_tuff_bricks_from_stone_types_tuff_stonecutting.json -f854d2173b983025e3f77bca4e0f65f98fc74765 data/create/advancements/recipes/building_blocks/small_tuff_bricks_from_tuff_stonecutting.json e5c1b96e7b0649d922b13a4dfb97c7e87cf7810a data/create/advancements/recipes/building_blocks/small_tuff_brick_slab.json cc54d9ae5cee7f64a885ff2dfcf8f32dce300226 data/create/advancements/recipes/building_blocks/small_tuff_brick_slab_from_stone_types_tuff_stonecutting.json -53540225f1dcfa9c27161aa0a158ad02769ec3e4 data/create/advancements/recipes/building_blocks/small_tuff_brick_slab_from_tuff_stonecutting.json 63490d19d507a254964ee8c4a4d727995baa067a data/create/advancements/recipes/building_blocks/small_tuff_brick_slab_recycling.json a8fe179f7828fcd88e7c967f445572d1292b6700 data/create/advancements/recipes/building_blocks/small_tuff_brick_stairs.json a5a474a0ad98a4db967e327189049ac1b1766cae data/create/advancements/recipes/building_blocks/small_tuff_brick_stairs_from_stone_types_tuff_stonecutting.json -0dc82045d3792278f476feb57f7261cdd4362d5c data/create/advancements/recipes/building_blocks/small_tuff_brick_stairs_from_tuff_stonecutting.json e2ca887e45707197386de17a0957d949c232de50 data/create/advancements/recipes/building_blocks/small_tuff_brick_wall.json 2d946f1f93bcab5d8a185084179af23ec892c933 data/create/advancements/recipes/building_blocks/small_tuff_brick_wall_from_stone_types_tuff_stonecutting.json -d35089e98f4d6b505e497e4eaea0f4c50b03af4e data/create/advancements/recipes/building_blocks/small_tuff_brick_wall_from_tuff_stonecutting.json fbe365e0e2af1c1f99486cc63a179c5723c28647 data/create/advancements/recipes/building_blocks/small_veridium_bricks_from_stone_types_veridium_stonecutting.json -32f36849586bd2f1028e5ea672704b608ac497d2 data/create/advancements/recipes/building_blocks/small_veridium_bricks_from_veridium_stonecutting.json c7099d2e99562aff9fb0f1d7eb2bdfa93ba08306 data/create/advancements/recipes/building_blocks/small_veridium_brick_slab.json 57f41a5e2b596b5e0ba585dd94dd3cb58411db47 data/create/advancements/recipes/building_blocks/small_veridium_brick_slab_from_stone_types_veridium_stonecutting.json -8668b73cd9976e496a7e29454867cf3953bc8496 data/create/advancements/recipes/building_blocks/small_veridium_brick_slab_from_veridium_stonecutting.json 1f5c23b6047c0348d3dae55df4046fddcdda182a data/create/advancements/recipes/building_blocks/small_veridium_brick_slab_recycling.json 3a51956ea746166bc970b482f2d45ce66b008ed6 data/create/advancements/recipes/building_blocks/small_veridium_brick_stairs.json eed29c40d4b3462913a0fe788d4bbfe6ff2bbb49 data/create/advancements/recipes/building_blocks/small_veridium_brick_stairs_from_stone_types_veridium_stonecutting.json -61591e5fc2533a8c033eea9ff0616bc97e57d052 data/create/advancements/recipes/building_blocks/small_veridium_brick_stairs_from_veridium_stonecutting.json bb9c80736dee49dc5e41bb023a186ada7357228e data/create/advancements/recipes/building_blocks/small_veridium_brick_wall.json a858e59c54ad76abbb7753e3e4f6158e059a1f35 data/create/advancements/recipes/building_blocks/small_veridium_brick_wall_from_stone_types_veridium_stonecutting.json -4e6b6a5cedf8ae071d48aceb65a64c41c22b44a4 data/create/advancements/recipes/building_blocks/small_veridium_brick_wall_from_veridium_stonecutting.json 4ed9b0fc048e8d78998e0bee17191d9da7a750e3 data/create/advancements/recipes/building_blocks/spruce_window.json 529619c18bd1356ede6f169680a3e12636e2ec2d data/create/advancements/recipes/building_blocks/spruce_window_pane.json 1eb1b91c3bae5e9a661037563dda7f86319a5767 data/create/advancements/recipes/building_blocks/tiled_glass_from_glass_colorless_stonecutting.json 7ac376cb5955695acb2dc5156408be6ee273e3ae data/create/advancements/recipes/building_blocks/tiled_glass_pane.json +93dff0c9e76304a9b94b250cc549f2f48eadc556 data/create/advancements/recipes/building_blocks/tuff_from_stone_types_tuff_stonecutting.json 44be73e4dd89092099eba20c0f6265ec5001b1a8 data/create/advancements/recipes/building_blocks/tuff_pillar_from_stone_types_tuff_stonecutting.json -7b7d81c7a7d2d5ea686b8c7210ba03130b706a3b data/create/advancements/recipes/building_blocks/tuff_pillar_from_tuff_stonecutting.json +129f950cf31629a373b79259bf2143ef905ba92c data/create/advancements/recipes/building_blocks/veridium_from_stone_types_veridium_stonecutting.json feffc531fb2738122f422760156c1c7ca511dbee data/create/advancements/recipes/building_blocks/veridium_pillar_from_stone_types_veridium_stonecutting.json -7aecf8a778275d8e37febd993d618123d52fea90 data/create/advancements/recipes/building_blocks/veridium_pillar_from_veridium_stonecutting.json cf3cd34bbd1914f236a5504a026c889bde3b0b2f data/create/advancements/recipes/building_blocks/vertical_framed_glass_from_glass_colorless_stonecutting.json 52a605757015ad6f87296432de3809ce9572ec87 data/create/advancements/recipes/building_blocks/vertical_framed_glass_pane.json 235d4fd9853e8568e1957a4899cdabcacd669942 data/create/advancements/recipes/building_blocks/warped_window.json @@ -3008,68 +2919,47 @@ b5961084cfcef7cede5a84a2731d63a087aa0fe2 data/create/advancements/recipes/buildi 3152f4f16beeff6cf9b490629b729861a8450822 data/create/advancements/recipes/building_blocks/weathered_copper_tile_slab_from_weathered_copper_tiles_stonecutting.json 8deb43c34b46ca097c61c333080875abf827608d data/create/advancements/recipes/building_blocks/weathered_copper_tile_stairs.json 2c54cd102bf05d2461fda9833be4fa0cb52e8cac data/create/advancements/recipes/building_blocks/weathered_copper_tile_stairs_from_weathered_copper_tiles_stonecutting.json -6316458bc99f3345544ffc6f520040754a25cb28 data/create/advancements/recipes/decorations/brass_ladder_from_plates_brass_stonecutting.json -be5461c9b18fd39c312b38559502121eaa8299b1 data/create/advancements/recipes/decorations/copper_ladder_from_plates_copper_stonecutting.json -3f256f95ccf0acdf47d05893ee4e21d3c7df2c0c data/create/advancements/recipes/misc/crafting/kinetics/black_seat.json -6c41c0225fa2fdd6c52405c6d3c38414fd676aa9 data/create/advancements/recipes/misc/crafting/kinetics/black_seat_from_other_seat.json +b99021acc1fbc1c247a712a0ae6a672cb21bf89d data/create/advancements/recipes/decorations/andesite_bars_from_andesite_alloy_stonecutting.json +6f01a8e667a337e504822e7b75aef37716ed5fab data/create/advancements/recipes/decorations/andesite_ladder_from_andesite_alloy_stonecutting.json +974fce40b47a5c5fcaf5feb09b92d178a63308fb data/create/advancements/recipes/decorations/andesite_scaffolding_from_andesite_alloy_stonecutting.json +2168a6b45f90a210408a78f233248248dece7996 data/create/advancements/recipes/decorations/brass_bars_from_ingots_brass_stonecutting.json +5b7c1693459b38a855c1c7e7bb99c8f4a834347d data/create/advancements/recipes/decorations/brass_ladder_from_ingots_brass_stonecutting.json +0096957aa80383448f683130defa5107214cbd58 data/create/advancements/recipes/decorations/brass_scaffolding_from_ingots_brass_stonecutting.json +0af812662873e0d1fc3d8a820b387e74952f70ee data/create/advancements/recipes/decorations/copper_bars_from_ingots_copper_stonecutting.json +ecc885349bed79171f57b4bdedfbfc224b248f0c data/create/advancements/recipes/decorations/copper_ladder_from_ingots_copper_stonecutting.json +eae4488f646740e7d57b241a6063cf8a4b552e11 data/create/advancements/recipes/decorations/copper_scaffolding_from_ingots_copper_stonecutting.json 1f923bc2a94b18c132c74e3113a2f6cb6ffd3eff data/create/advancements/recipes/misc/crafting/kinetics/black_valve_handle_from_other_valve_handle.json -988d6bb62ca303051a3898632a175cbda12ae289 data/create/advancements/recipes/misc/crafting/kinetics/blue_seat.json -bd1348d231e7c2d306e9cc8a760143bd6cfffb73 data/create/advancements/recipes/misc/crafting/kinetics/blue_seat_from_other_seat.json d0abd9afa18f6bb5f5dde56b9c7ea24e7a72da16 data/create/advancements/recipes/misc/crafting/kinetics/blue_valve_handle_from_other_valve_handle.json -5d729ff1a81a3a0118f5949aaa1111489f88e4ec data/create/advancements/recipes/misc/crafting/kinetics/brown_seat.json -722a52c3a8c23fcbbbc08177ab135ca40c58f53a data/create/advancements/recipes/misc/crafting/kinetics/brown_seat_from_other_seat.json 9af96918d3ac5d7d0e2458377afe57b1a51b5f2b data/create/advancements/recipes/misc/crafting/kinetics/brown_valve_handle_from_other_valve_handle.json -69768ed726ff11680beceb15f34f8a52ba3b6b67 data/create/advancements/recipes/misc/crafting/kinetics/cyan_seat.json -794f03e20084b9fc0d65dfe60b21a34e6e0002ec data/create/advancements/recipes/misc/crafting/kinetics/cyan_seat_from_other_seat.json 320141bd8354173aab49f4872419b823b63ed4c6 data/create/advancements/recipes/misc/crafting/kinetics/cyan_valve_handle_from_other_valve_handle.json -2696a3b8645fd09d830cf7d7a76f5aab54dcd02e data/create/advancements/recipes/misc/crafting/kinetics/gray_seat.json -e55d3bca5ac8090d46ab18b5b768bdd135f3e8ed data/create/advancements/recipes/misc/crafting/kinetics/gray_seat_from_other_seat.json b251ad62b0070165fd7fdd4f4070d81abc3db378 data/create/advancements/recipes/misc/crafting/kinetics/gray_valve_handle_from_other_valve_handle.json -540b652774130e8ad707cb0f79a9397857408563 data/create/advancements/recipes/misc/crafting/kinetics/green_seat.json -717ab89326073d9327767f65c9ef8f0ebca7a02e data/create/advancements/recipes/misc/crafting/kinetics/green_seat_from_other_seat.json fc9dbff58b30fdddab1eede2f9eb363c153e07ba data/create/advancements/recipes/misc/crafting/kinetics/green_valve_handle_from_other_valve_handle.json -93374c0d142ce125b86a7017308eb3da50415a23 data/create/advancements/recipes/misc/crafting/kinetics/light_blue_seat.json -64193680060042e4069497b1ead22470ce1912f8 data/create/advancements/recipes/misc/crafting/kinetics/light_blue_seat_from_other_seat.json c162f742bf7b5dcede43ac9ae554dbcd5aa87c1a data/create/advancements/recipes/misc/crafting/kinetics/light_blue_valve_handle_from_other_valve_handle.json -b2da019020d8feabf57b3d0cedc3e9ecb7331272 data/create/advancements/recipes/misc/crafting/kinetics/light_gray_seat.json -b7e1966db2269995ffa1065a0aeaa6e47e1eda9d data/create/advancements/recipes/misc/crafting/kinetics/light_gray_seat_from_other_seat.json b95ddd390594ecc1f448f90fffd8ae7aa049648a data/create/advancements/recipes/misc/crafting/kinetics/light_gray_valve_handle_from_other_valve_handle.json -481daedd0b8fe95ae10efc38fa34e0bc800512d3 data/create/advancements/recipes/misc/crafting/kinetics/lime_seat.json -4b9f96c0171731bee73512314f7c5d18552601ab data/create/advancements/recipes/misc/crafting/kinetics/lime_seat_from_other_seat.json e5ca46744418212f92b4456caa83190e01cda488 data/create/advancements/recipes/misc/crafting/kinetics/lime_valve_handle_from_other_valve_handle.json -847bc1e330f0c20b728f2c4b1709a34f4322f169 data/create/advancements/recipes/misc/crafting/kinetics/magenta_seat.json -8f42db87f1767fa6fd2847374be3646d72934e7d data/create/advancements/recipes/misc/crafting/kinetics/magenta_seat_from_other_seat.json b62aa1c8ecca4a4b6e23739e4cc174d3cd361198 data/create/advancements/recipes/misc/crafting/kinetics/magenta_valve_handle_from_other_valve_handle.json -7bde8a042ceeeacf716b6b161bafed6d65bade5d data/create/advancements/recipes/misc/crafting/kinetics/orange_seat.json -3148ec4ccf8eb6894f4457a0aa73c89944016a8d data/create/advancements/recipes/misc/crafting/kinetics/orange_seat_from_other_seat.json 8a674107130bc16111e147cb313a521a9a80011b data/create/advancements/recipes/misc/crafting/kinetics/orange_valve_handle_from_other_valve_handle.json -6f9dfb04857f7e442848fa8daab13a28ca35199c data/create/advancements/recipes/misc/crafting/kinetics/pink_seat.json -e8bad3149b616f469e7173e9cd03656f146cdadb data/create/advancements/recipes/misc/crafting/kinetics/pink_seat_from_other_seat.json c76bcc3a4207a4cccb7b0f3ac2fcbb14959c837a data/create/advancements/recipes/misc/crafting/kinetics/pink_valve_handle_from_other_valve_handle.json -6b0f3cbd721e042b6541c1d1eb9fa98afec3c3b7 data/create/advancements/recipes/misc/crafting/kinetics/purple_seat.json -77cc0fed3db9f111dfb453d252a0ea5c2f92f183 data/create/advancements/recipes/misc/crafting/kinetics/purple_seat_from_other_seat.json 3d7c12e26f44b872e3789905aefb993816a856e5 data/create/advancements/recipes/misc/crafting/kinetics/purple_valve_handle_from_other_valve_handle.json -db8494bbd886ca1639541e4d85699d3300da274b data/create/advancements/recipes/misc/crafting/kinetics/red_seat.json -98427f485f606219f1d189b34d4af72bf2a2d248 data/create/advancements/recipes/misc/crafting/kinetics/red_seat_from_other_seat.json 1f58782364747d8286c7dee4d7066e9f2894ee39 data/create/advancements/recipes/misc/crafting/kinetics/red_valve_handle_from_other_valve_handle.json -4a7001a6af435f49a993af706e0b81074d080147 data/create/advancements/recipes/misc/crafting/kinetics/white_seat.json -3b63ced7008a10c802ea5bb30e9a8e040e4b6e53 data/create/advancements/recipes/misc/crafting/kinetics/white_seat_from_other_seat.json c5ab0b03813a31bb26d44aa36e3ad79b61880f05 data/create/advancements/recipes/misc/crafting/kinetics/white_valve_handle_from_other_valve_handle.json -46f6347035596f6cbb8a19aacfe4c89e8ad82ba8 data/create/advancements/recipes/misc/crafting/kinetics/yellow_seat.json -fe5e4d607d6a26ada2e51fc8481a3ce5aea8d3c1 data/create/advancements/recipes/misc/crafting/kinetics/yellow_seat_from_other_seat.json ebb8227c6d5a45448826ae2d72c6f7c52f836ab9 data/create/advancements/recipes/misc/crafting/kinetics/yellow_valve_handle_from_other_valve_handle.json a3f56145a37a381502c8d0f33f3f68d19fbb84a7 data/create/loot_tables/blocks/acacia_window.json 82759d6df5b84d56b8d9900798de33ac2ee386fc data/create/loot_tables/blocks/acacia_window_pane.json 5a11afdbcac60ec59c9d4992612582c0ac4a97c8 data/create/loot_tables/blocks/adjustable_chain_gearshift.json dc713ff2984b1508550a8e4dcc2e2eb14961545b data/create/loot_tables/blocks/analog_lever.json +4f46d9379b063fb40350b0f67149121b45d06be4 data/create/loot_tables/blocks/andesite_alloy_block.json +84a5c5820b7ac54fe5cbc81288d4929d2352e3bb data/create/loot_tables/blocks/andesite_bars.json 4d642dedba06f0561c85af361a00560576a88077 data/create/loot_tables/blocks/andesite_belt_funnel.json 126d941149f72edc6ba8e7798a471e4c1daf6a5c data/create/loot_tables/blocks/andesite_casing.json +550d69206e67de6df23f31d28329070b393d84e1 data/create/loot_tables/blocks/andesite_door.json 13267c1251e76ae6271f7de72db60bde86aa0bfa data/create/loot_tables/blocks/andesite_encased_cogwheel.json 9d010fc3c8d0821d69b550ff0bcbf117be9a7005 data/create/loot_tables/blocks/andesite_encased_large_cogwheel.json 658d76088e3926c72da86a75b4b14946bd809239 data/create/loot_tables/blocks/andesite_encased_shaft.json 4d642dedba06f0561c85af361a00560576a88077 data/create/loot_tables/blocks/andesite_funnel.json 989f9dece4281e85aa64fc45f7a6ee37bc0c9b3e data/create/loot_tables/blocks/andesite_ladder.json f61ca02f172d6a4e922005dee01d64069afc1a01 data/create/loot_tables/blocks/andesite_pillar.json +9fcba98700a95f38898e3a635c252b1806c8c349 data/create/loot_tables/blocks/andesite_scaffolding.json 6d0215a853fafcbe7b3b9b0f02cd5d7440f2f7d3 data/create/loot_tables/blocks/andesite_tunnel.json 9817128641e5c21acd9110a38c451a2374e5611b data/create/loot_tables/blocks/asurine.json daa279a1f4c5aec62fb44bd9c5569a4b2c5cb30b data/create/loot_tables/blocks/asurine_pillar.json @@ -3088,14 +2978,17 @@ f4a50c2bcfc2483168a661d5af233bd043d1ea51 data/create/loot_tables/blocks/blue_nix 3168fb6ceb78d373ff0b8c8d74a4796af0d945dc data/create/loot_tables/blocks/blue_seat.json f7fdef100b60b5cb8fb1189d3e70b9c828a3b8d4 data/create/loot_tables/blocks/blue_toolbox.json 4426cab1afcfca4f71e741dcf877b2a31ca92897 data/create/loot_tables/blocks/blue_valve_handle.json +7090cdfa6d9a0b2062bcab3ee794a681c8fc248d data/create/loot_tables/blocks/brass_bars.json ccd1691115bb92e00c70633b28cb2e5129296326 data/create/loot_tables/blocks/brass_belt_funnel.json 8f9cf04579010ecf2752ad1319ee97dd342dd78b data/create/loot_tables/blocks/brass_block.json fdfce33b43b245a4f87bcf91583211d814ec3448 data/create/loot_tables/blocks/brass_casing.json +bc58021c4337084b3d7d409bd714eef07e1bac6d data/create/loot_tables/blocks/brass_door.json 13267c1251e76ae6271f7de72db60bde86aa0bfa data/create/loot_tables/blocks/brass_encased_cogwheel.json 9d010fc3c8d0821d69b550ff0bcbf117be9a7005 data/create/loot_tables/blocks/brass_encased_large_cogwheel.json 658d76088e3926c72da86a75b4b14946bd809239 data/create/loot_tables/blocks/brass_encased_shaft.json ccd1691115bb92e00c70633b28cb2e5129296326 data/create/loot_tables/blocks/brass_funnel.json 1a84be40ab40c95805dcdb8fcbf80db551b236e5 data/create/loot_tables/blocks/brass_ladder.json +b75c2afc98430d4e55506879a496fe2c4ef35979 data/create/loot_tables/blocks/brass_scaffolding.json df96035dce4aa8f514774f4133d27843ebc3918d data/create/loot_tables/blocks/brass_tunnel.json f4a50c2bcfc2483168a661d5af233bd043d1ea51 data/create/loot_tables/blocks/brown_nixie_tube.json 9466ffd9553b2b18e193543fa00f698ddd21d7d3 data/create/loot_tables/blocks/brown_sail.json @@ -3105,15 +2998,20 @@ e578a068014c1d5a467f2a4e73e4b6d94271eb3d data/create/loot_tables/blocks/brown_va 5cc7f05f186d9158bbf635a622a99b17da294dbb data/create/loot_tables/blocks/calcite_pillar.json 0cb4fd02ee64e1ad37eb8ce89387667f951cf926 data/create/loot_tables/blocks/cart_assembler.json 985a3ce38a503d4b952e4bb7b927823aae8eed58 data/create/loot_tables/blocks/chute.json +1d4929d7d6176f60e5ea991a577527ed251ef375 data/create/loot_tables/blocks/clipboard.json b7f29e901c19e2b8f443dc99d3d8960505bf89c7 data/create/loot_tables/blocks/clockwork_bearing.json 83383e5c7a0cdeb63b5401b43a7f94055ee03d3b data/create/loot_tables/blocks/clutch.json 13267c1251e76ae6271f7de72db60bde86aa0bfa data/create/loot_tables/blocks/cogwheel.json fbf91043151dd047828e9101f08bac463694c303 data/create/loot_tables/blocks/content_observer.json +46cc7c341ecd8e15579c697e4c3eecb7d1225958 data/create/loot_tables/blocks/contraption_controls.json 6ab9e45341420e4760691c471539bbcd222ebac9 data/create/loot_tables/blocks/controller_rail.json feade294112e66f472a3d33d6cfa29145ed136b5 data/create/loot_tables/blocks/controls.json adc3f334ffce3c11fb545a2883edea4d234ace51 data/create/loot_tables/blocks/copper_backtank.json +880f676e83ea2596774e7afe768aa8638dfd64e7 data/create/loot_tables/blocks/copper_bars.json 8d546d5efd1612c1f1c2971216473516b38d748d data/create/loot_tables/blocks/copper_casing.json +cccc03027a7907f86648397c0df6671608312a79 data/create/loot_tables/blocks/copper_door.json 210ca7a6ad459b403dcd41149ad0544df2028143 data/create/loot_tables/blocks/copper_ladder.json +12bb93fd8e39f9d65de0e0812a56f44b522a1f35 data/create/loot_tables/blocks/copper_scaffolding.json c4f60d880f72a24068e35f022ccf646daeea4c24 data/create/loot_tables/blocks/copper_shingles.json ed41ba3fce95485fe143393b19cd5357356ceb9b data/create/loot_tables/blocks/copper_shingle_slab.json 7733a3f8398c19dd51d1528cd85d786895c100ed data/create/loot_tables/blocks/copper_shingle_stairs.json @@ -3121,6 +3019,10 @@ ed41ba3fce95485fe143393b19cd5357356ceb9b data/create/loot_tables/blocks/copper_s 931a705bab6638521964e1ae93cc9980e539bb88 data/create/loot_tables/blocks/copper_tile_slab.json de0fa9ebeabe64dcfe5a64da0e697509b73477f8 data/create/loot_tables/blocks/copper_tile_stairs.json 6ed1886e41def643b9b8881d0b1bcb5b5c80106e data/create/loot_tables/blocks/copper_valve_handle.json +2b2a4bde1a1c86393b28fa3ff9b81ef1ddeed22d data/create/loot_tables/blocks/copycat_bars.json +2b2a4bde1a1c86393b28fa3ff9b81ef1ddeed22d data/create/loot_tables/blocks/copycat_base.json +e1047d6ed7b16a91c73ebc0dbdcef6fe989d79d3 data/create/loot_tables/blocks/copycat_panel.json +95b19cefb50d621a75ed4a3cab369a229940ccf9 data/create/loot_tables/blocks/copycat_step.json 70b7d7cb3d8ae394544e4c5c7c7fdbf3d58c311e data/create/loot_tables/blocks/creative_crate.json dacd34a8c7cadd5679177bd10a4374b4dd7a5fec data/create/loot_tables/blocks/creative_fluid_tank.json f6c2bf40f31406fc1f86d71ba616eac23fc5854a data/create/loot_tables/blocks/creative_motor.json @@ -3257,9 +3159,12 @@ f4a50c2bcfc2483168a661d5af233bd043d1ea51 data/create/loot_tables/blocks/cyan_nix e969a183d6ea9569e40c3d5d17a9eba4999ce220 data/create/loot_tables/blocks/display_board.json e46f3f710972d17bccb9244f22fb267082b2ec7c data/create/loot_tables/blocks/display_link.json 4fabe2419bf98de2d664d782f7decc585a028a65 data/create/loot_tables/blocks/dripstone_pillar.json +07402ea8550107f765a5937dfe180a3800f12f84 data/create/loot_tables/blocks/elevator_contact.json +26f921a590db37215bd8226611e8b29b5805fb0d data/create/loot_tables/blocks/elevator_pulley.json 6df2d9239e5d8897033cb1d7b95b3094654af745 data/create/loot_tables/blocks/encased_chain_drive.json 66008f776f345a3fa3f740790bbc0bf4013bdcd6 data/create/loot_tables/blocks/encased_fan.json 3b11d74298e8f808207d85ce6426d597d51cceef data/create/loot_tables/blocks/encased_fluid_pipe.json +d0278de519828539c2f55f8f1ec320cd620a52fd data/create/loot_tables/blocks/experience_block.json dad8f04e24e5da8b693d4de0e00e5cfafb64cf7b data/create/loot_tables/blocks/exposed_copper_shingles.json dcccb5082e6fbae664c00946402daa1b081c0748 data/create/loot_tables/blocks/exposed_copper_shingle_slab.json c1324ca2cf242708be48c211e411e56c8c3d7c78 data/create/loot_tables/blocks/exposed_copper_shingle_stairs.json @@ -3296,12 +3201,14 @@ f9e23ff774f537a06b4c7909c36d92b2163300b2 data/create/loot_tables/blocks/haunted_ 4abd856b6b3ed7585da0044dd794a733a6f991dc data/create/loot_tables/blocks/horizontal_framed_glass.json 77b52d1c33ce7b867dc6ce61379284b52fa9e957 data/create/loot_tables/blocks/horizontal_framed_glass_pane.json 53eab855ca00e912fa9f99ab57d215e5c6d9fcd6 data/create/loot_tables/blocks/hose_pulley.json +38e108dd3c9dfe01d84c37eca75ec0dc1ccc6d11 data/create/loot_tables/blocks/industrial_iron_block.json 716a25f2e6e647216d6af4773a84f5ba0371096c data/create/loot_tables/blocks/item_drain.json 207c22f3b1ac6b1596a9ea595550f2e6fdd997a1 data/create/loot_tables/blocks/item_vault.json c46cc42432ddc44b89e9c7800a5b3d2a785a317e data/create/loot_tables/blocks/jungle_window.json f7e20610036cd620535fc1544f0ba03936c4545c data/create/loot_tables/blocks/jungle_window_pane.json fee742e0fcd8c3e6e5553d4290cc698fb0a7679f data/create/loot_tables/blocks/large_bogey.json 9d010fc3c8d0821d69b550ff0bcbf117be9a7005 data/create/loot_tables/blocks/large_cogwheel.json +8f52bb13618a882d6d79ab875d7a8fa2c017a59a data/create/loot_tables/blocks/large_water_wheel.json bb8f6da8793701a0e099c797a48e3556705281b4 data/create/loot_tables/blocks/layered_andesite.json d36e3236bcb56a1a5c171cd5023b4a3535b78d8d data/create/loot_tables/blocks/layered_asurine.json b33fb36b8f1869f188f3b372d42d989f29473782 data/create/loot_tables/blocks/layered_calcite.json @@ -3341,6 +3248,8 @@ f4a50c2bcfc2483168a661d5af233bd043d1ea51 data/create/loot_tables/blocks/magenta_ ccae04c0e944f9f3909c3210ae3eb910207cd57c data/create/loot_tables/blocks/magenta_seat.json dbdcad9959ec94b2f214f121a0361f2eeac5cab9 data/create/loot_tables/blocks/magenta_toolbox.json 6020e533ed7121ee33409a4422a8098295af49d0 data/create/loot_tables/blocks/magenta_valve_handle.json +acb87cf1aa3236529a9322e3d04155da16747e1f data/create/loot_tables/blocks/mangrove_window.json +544741628cabdf548d6185bd1e1b3d2675a7c7bb data/create/loot_tables/blocks/mangrove_window_pane.json e86b6745d61732cfd95356df84e71cae8b9be10d data/create/loot_tables/blocks/mechanical_arm.json 6ffb8f41c3c42d57c9ff9ce8520b2327f51e2731 data/create/loot_tables/blocks/mechanical_bearing.json 1f166934a75ea3d1bdcf65394632636e6f9cf5ff data/create/loot_tables/blocks/mechanical_crafter.json @@ -3352,6 +3261,7 @@ ada6bd9d74e6089f89f674a941c67809b238f9ba data/create/loot_tables/blocks/mechanic 7ae5e04247a7865ed31cc371ad320e048705920e data/create/loot_tables/blocks/mechanical_plough.json d7a65d9412c86788a751ac2910a1d12afe5c698d data/create/loot_tables/blocks/mechanical_press.json 7a5b9e322c8cb37c0851dddb9ec5eeee226e3dc7 data/create/loot_tables/blocks/mechanical_pump.json +2a419360a36965c5ecddedecd1ac31f36f8ed4f8 data/create/loot_tables/blocks/mechanical_roller.json f6b645e4fb6cff56c670ebbdac6faf7a54392d54 data/create/loot_tables/blocks/mechanical_saw.json e543aa1464cd13e8584648ec9837bf5668d18676 data/create/loot_tables/blocks/metal_bracket.json 5fef81f04d62c6d568d015348997c3c244140cfa data/create/loot_tables/blocks/metal_girder.json @@ -3359,6 +3269,7 @@ e543aa1464cd13e8584648ec9837bf5668d18676 data/create/loot_tables/blocks/metal_br 1789145ba000b1df482623669ffcf7d596aba556 data/create/loot_tables/blocks/millstone.json 2b2a4bde1a1c86393b28fa3ff9b81ef1ddeed22d data/create/loot_tables/blocks/minecart_anchor.json 8ca400d182203a8edc3e917fd36ae74a2304929e data/create/loot_tables/blocks/mysterious_cuckoo_clock.json +afa80803f5ff718b6c6cfd0845f54ecb4cd30eba data/create/loot_tables/blocks/netherite_backtank.json f4a50c2bcfc2483168a661d5af233bd043d1ea51 data/create/loot_tables/blocks/nixie_tube.json d23b04662f5d0886e1881ce0b83517526886e8de data/create/loot_tables/blocks/nozzle.json be36ab5e2c22d3a8bed728d2ca859212ad75fc08 data/create/loot_tables/blocks/oak_window.json @@ -3570,6 +3481,7 @@ dfefc9afd631cfdff543c11ffd8682617793e204 data/create/loot_tables/blocks/veridium 8e3f9f7ea93908d7cdfe2a11142e1f705c0b8211 data/create/loot_tables/blocks/warped_window.json f60d8b639de25d4829505d994e19afbd1e34df85 data/create/loot_tables/blocks/warped_window_pane.json 17207bb6d7180aa86a59a205f5cd88fea5ec20dd data/create/loot_tables/blocks/water_wheel.json +2b2a4bde1a1c86393b28fa3ff9b81ef1ddeed22d data/create/loot_tables/blocks/water_wheel_structure.json 7037fe5803d3cba148d6a3c608bf3516ce101fe9 data/create/loot_tables/blocks/waxed_copper_shingles.json 46ee38f31f486439c756679ff2e0d99dd08170e0 data/create/loot_tables/blocks/waxed_copper_shingle_slab.json 1bf2316aa8826ed347cd8d4f34c541ca370e885e data/create/loot_tables/blocks/waxed_copper_shingle_stairs.json @@ -3617,26 +3529,35 @@ f4a50c2bcfc2483168a661d5af233bd043d1ea51 data/create/loot_tables/blocks/yellow_n 991d2706fbbb28d4d830af85a8799d49ec6f6881 data/create/loot_tables/blocks/zinc_ore.json 9dd770d35971e53981605e09dee627265993e64e data/create/recipes/acacia_window.json 43f8bcb79885ba6bdae6e3fd564cb01d46e0b85f data/create/recipes/acacia_window_pane.json -18d8161ab7a44900a1d2c6b77cc795d6e352b86a data/create/recipes/andesite_pillar_from_andesite_stonecutting.json +1ae66a840aaf29478510ecb9bbc89416e67ce89e data/create/recipes/andesite_bars_from_andesite_alloy_stonecutting.json +99256a17fb612511b959539e8b8f61ffe1d73aad data/create/recipes/andesite_from_stone_types_andesite_stonecutting.json +20bd65d72f1762edf473b2fafc71fcf7d55c01f9 data/create/recipes/andesite_ladder_from_andesite_alloy_stonecutting.json 0b3896151533d220c2d1f3768c6f8e428516ff5b data/create/recipes/andesite_pillar_from_stone_types_andesite_stonecutting.json -fed1f650ade58ee82afdc29aafa3eba68aa18019 data/create/recipes/asurine_pillar_from_asurine_stonecutting.json +367e57a760156a19fc6805a0f23c3f8194cd4255 data/create/recipes/andesite_scaffolding_from_andesite_alloy_stonecutting.json +5272c61c8c17eb7a528cade93bbc80fd9ef51521 data/create/recipes/asurine_from_stone_types_asurine_stonecutting.json 5bf4b9baf782a461efc36d463b99b9acb0ab4607 data/create/recipes/asurine_pillar_from_stone_types_asurine_stonecutting.json 882faa874d03e4920234a343cb85b62b1b201572 data/create/recipes/birch_window.json fefbe41fd20f6c8cc40f975845340f33681d4f17 data/create/recipes/birch_window_pane.json -c1e8a51e47518b7c8f7d9b3b7524702084222f8a data/create/recipes/brass_ladder_from_plates_brass_stonecutting.json -e9c7070f59841bc69a6c172fd36a29ae8650fe73 data/create/recipes/calcite_pillar_from_calcite_stonecutting.json +5965f3abe435ac0b3a39d8ec31af71808592642b data/create/recipes/brass_bars_from_ingots_brass_stonecutting.json +4b29884cd866dcda1b93899d81fcd3a2ae4c541b data/create/recipes/brass_ladder_from_ingots_brass_stonecutting.json +9c685014019a7a4f1ef47f235cd1e9b3f9093295 data/create/recipes/brass_scaffolding_from_ingots_brass_stonecutting.json +8f21b67e168a14d354b6c00b5ec795355fdd4209 data/create/recipes/calcite_from_stone_types_calcite_stonecutting.json da3692808565988e21ec5b1d5e976338ccc4a037 data/create/recipes/calcite_pillar_from_stone_types_calcite_stonecutting.json -0bd1f4c236e9a1c311f6d6dd0ec0596478df0c1b data/create/recipes/copper_ladder_from_plates_copper_stonecutting.json -a499b2391594f316168c1bf69b9f2348c8f81967 data/create/recipes/copper_shingles_from_plates_copper_stonecutting.json +1157b2eab2ada187ea80feae298b77ed7ece4bfd data/create/recipes/copper_bars_from_ingots_copper_stonecutting.json +b9d4f55128aa03ee6f6ab1831e709629a42c147e data/create/recipes/copper_ladder_from_ingots_copper_stonecutting.json +922c5ac48c8eb8b3a39f5626a381c2252fbac107 data/create/recipes/copper_scaffolding_from_ingots_copper_stonecutting.json +bab9fa969ba95850dc6e3bd0723387a61cbb05cd data/create/recipes/copper_shingles_from_ingots_copper_stonecutting.json 83c46e38ddce0d38f9398682e51c89ef8a7f0d2c data/create/recipes/copper_shingle_slab.json 3689feaca2bd5355fa2d4226cd2cc519fa9b97c1 data/create/recipes/copper_shingle_slab_from_copper_shingles_stonecutting.json 22434772d3d2a365c2b0c0ed89f670a14edc0325 data/create/recipes/copper_shingle_stairs.json 59f672e8e88d5f4655467e2696616b552debaf46 data/create/recipes/copper_shingle_stairs_from_copper_shingles_stonecutting.json -5655027fc198b60cb670c7883b2cc8a95b87ee51 data/create/recipes/copper_tiles_from_plates_copper_stonecutting.json +d463aa891c7ae1b2eb1a758e4100c5a1c16cfffd data/create/recipes/copper_tiles_from_ingots_copper_stonecutting.json 16925af5db450f2387d9358040297f486b50fbc1 data/create/recipes/copper_tile_slab.json 91b0390e0c772d43eb46b94a0113323f0f6a4387 data/create/recipes/copper_tile_slab_from_copper_tiles_stonecutting.json e1495f49a0e8c63f654ed452371f7c6eb76bd500 data/create/recipes/copper_tile_stairs.json bf1b0a447169029161fb07feacd22d5aa806b2bf data/create/recipes/copper_tile_stairs_from_copper_tiles_stonecutting.json +daa54c9ff3612521f06cc1979116beafcda852dd data/create/recipes/copycat_panel_from_ingots_zinc_stonecutting.json +745816d2c3fa29ede2510e39edc76f6fecee963f data/create/recipes/copycat_step_from_ingots_zinc_stonecutting.json 255c32272a704109fccdbb071d4dbf602cb8c1d8 data/create/recipes/crafting/copper/waxed_copper_shingles_from_honeycomb.json 57ae13042e0f96676fa322bf24db4976d75ca6bc data/create/recipes/crafting/copper/waxed_copper_shingle_slab_from_honeycomb.json 790565897535ea2e741d0a0ed7c0b561d594b69a data/create/recipes/crafting/copper/waxed_copper_shingle_stairs_from_honeycomb.json @@ -3661,401 +3582,289 @@ a2cc99ad9b1234f5327971ee535af9bc25d0154c data/create/recipes/crafting/copper/wax 724802d206db185ebf20bafbcfc35fe0f982f58a data/create/recipes/crafting/copper/waxed_weathered_copper_tiles_from_honeycomb.json 98d0b72eb20e1d80cc590800ae2d642a47c3ae5f data/create/recipes/crafting/copper/waxed_weathered_copper_tile_slab_from_honeycomb.json 594b8fd5c30a84df97667b2c6dccc5dedd039d26 data/create/recipes/crafting/copper/waxed_weathered_copper_tile_stairs_from_honeycomb.json -4198f349cbb879368c0b7366556b44af20e51027 data/create/recipes/crafting/kinetics/black_seat.json -e18904f0dabfcafc038731305bac9d8673689971 data/create/recipes/crafting/kinetics/black_seat_from_other_seat.json +97c3e430ef2aecf61c457d0b8c4bbd23e1b01cc3 data/create/recipes/crafting/kinetics/black_seat.json +1129d02609125b48af2efa48f84dd3f90d51a341 data/create/recipes/crafting/kinetics/black_seat_from_other_seat.json 9e5a73e2343054d35e2fbfd20f0c49834d1a87a6 data/create/recipes/crafting/kinetics/black_valve_handle_from_other_valve_handle.json -ce9198a6146517b8c6194a379d7b9e5787d61f1b data/create/recipes/crafting/kinetics/blue_seat.json -d2db76a402bb1eda3035fe9efc881f29a7771eaa data/create/recipes/crafting/kinetics/blue_seat_from_other_seat.json +022b7dc2660bf39606c2394c5af45da16ba375bb data/create/recipes/crafting/kinetics/blue_seat.json +935b63588e9464efc15025c96b89782466d4615d data/create/recipes/crafting/kinetics/blue_seat_from_other_seat.json 33e7767097462139f3faecfc1c6fa22f2839266d data/create/recipes/crafting/kinetics/blue_valve_handle_from_other_valve_handle.json -aeed127ada8fed8604e6bd40d2075638f8339e4c data/create/recipes/crafting/kinetics/brown_seat.json -6b51e53de1bb252c85e0f30877b05f16728fda4b data/create/recipes/crafting/kinetics/brown_seat_from_other_seat.json +f840c8694e8fbbd58c5eee4ed76dbd9aedb2ec31 data/create/recipes/crafting/kinetics/brown_seat.json +68d23b7fdd7db72d14097282172ed0426e6f3cf3 data/create/recipes/crafting/kinetics/brown_seat_from_other_seat.json d677be1e8f6f73979d4f7e04d16030988b0fe2d4 data/create/recipes/crafting/kinetics/brown_valve_handle_from_other_valve_handle.json -54aa1cf28bf9f3fd1103637b94c118257f1fbb2a data/create/recipes/crafting/kinetics/cyan_seat.json -906f4e24dadbba9198ca5e8ff6de5a82cc010b65 data/create/recipes/crafting/kinetics/cyan_seat_from_other_seat.json +d0854f83b60527cd1984a72a0d6e9319b82107c1 data/create/recipes/crafting/kinetics/cyan_seat.json +629f6ce0f47ac3cf500d6b2281873df4fbbb1c93 data/create/recipes/crafting/kinetics/cyan_seat_from_other_seat.json e60baaa1e898975bd2595d50afa8db9cb14ed231 data/create/recipes/crafting/kinetics/cyan_valve_handle_from_other_valve_handle.json -c69115699b22639bd04bde754c169868263d080e data/create/recipes/crafting/kinetics/gray_seat.json -d18bdaede4b7d8dad9b2600d611efa72648e857b data/create/recipes/crafting/kinetics/gray_seat_from_other_seat.json +60f47a9a587de415a2a3c8f0dda7d996ea29d23a data/create/recipes/crafting/kinetics/gray_seat.json +b1b0ac685e81318e92d3880cafa06267ee4ce080 data/create/recipes/crafting/kinetics/gray_seat_from_other_seat.json fac421b61c8ea60ccc14a2d8a75d19d960ebc32e data/create/recipes/crafting/kinetics/gray_valve_handle_from_other_valve_handle.json -5f22a18d6ecdd7001ce7d2e228d6dee7ef275fac data/create/recipes/crafting/kinetics/green_seat.json -00f67c4c0ec0e44237f92a80254a80c868372bf4 data/create/recipes/crafting/kinetics/green_seat_from_other_seat.json +3f81b63ec705052733bfc0b0310193da6ba11745 data/create/recipes/crafting/kinetics/green_seat.json +b8b7f9682e57a4ba9514cec00b2fb07b857e092a data/create/recipes/crafting/kinetics/green_seat_from_other_seat.json a3f3c26dc7fb484b82a35b907b77dc6aff95335e data/create/recipes/crafting/kinetics/green_valve_handle_from_other_valve_handle.json -e0e6e513cae97d7305b042d0ca74af4ed2c638dc data/create/recipes/crafting/kinetics/light_blue_seat.json -e1890d7e0f20a8db688410200be1bd70d3100005 data/create/recipes/crafting/kinetics/light_blue_seat_from_other_seat.json +acd5fae26c3695ddfcaacf0e6d50f14264f3c7dc data/create/recipes/crafting/kinetics/light_blue_seat.json +16d2b63337e94b3df137c2c4b0bcad4703f53960 data/create/recipes/crafting/kinetics/light_blue_seat_from_other_seat.json 49bc8aa18c2a35e7c052f5c1836d0d886dd6f6c8 data/create/recipes/crafting/kinetics/light_blue_valve_handle_from_other_valve_handle.json -ca8ef0f3e60e7e3245d2dcd6f5a7d216644cfeb7 data/create/recipes/crafting/kinetics/light_gray_seat.json -476a865ff2583fa4d86f5272ff7776332b0d5f77 data/create/recipes/crafting/kinetics/light_gray_seat_from_other_seat.json +4a632cfa1a7a43c5762cc8e2c3b8f9238225755d data/create/recipes/crafting/kinetics/light_gray_seat.json +85a0a15f86084bb7efec3a42f2d6311ce3562766 data/create/recipes/crafting/kinetics/light_gray_seat_from_other_seat.json ddf1106372428e9176db89ca095bd9b8b9f0881e data/create/recipes/crafting/kinetics/light_gray_valve_handle_from_other_valve_handle.json -15254bcf0700f300c9dd47972d08611f19304220 data/create/recipes/crafting/kinetics/lime_seat.json -2f3e321dc0271ca984330ee06bc6642a47007508 data/create/recipes/crafting/kinetics/lime_seat_from_other_seat.json +67ce357aa33075cf9c826b068a1e8cbaae444834 data/create/recipes/crafting/kinetics/lime_seat.json +d3d8376c6b65de28c4dfc3de322031c4e10c274d data/create/recipes/crafting/kinetics/lime_seat_from_other_seat.json 608f7e03a7ff320194c89db808c396e50abe8530 data/create/recipes/crafting/kinetics/lime_valve_handle_from_other_valve_handle.json -2e63b4a387c75de96dcd6ddee58d01c5e172830e data/create/recipes/crafting/kinetics/magenta_seat.json -1d9a3b397b005861cf9c4be4efcb0e0dcab3f01c data/create/recipes/crafting/kinetics/magenta_seat_from_other_seat.json +ed93888e77317fe5963189e1fd519473ab657991 data/create/recipes/crafting/kinetics/magenta_seat.json +b2bdda12f4fd27949d693b60c0bd5911ce1e7c62 data/create/recipes/crafting/kinetics/magenta_seat_from_other_seat.json 493709d6800a4199893dace709e538ef24765fef data/create/recipes/crafting/kinetics/magenta_valve_handle_from_other_valve_handle.json -c7f3e941b6e98f1ab25ec13733ef049bb7fcaf05 data/create/recipes/crafting/kinetics/orange_seat.json -58b43273006aa02f91be7c322c70053cf979fc78 data/create/recipes/crafting/kinetics/orange_seat_from_other_seat.json +6bda3df0614945058141ca4e5114ca824004dcab data/create/recipes/crafting/kinetics/orange_seat.json +69f14125d45f8a342c7064cfc86baeeb6ba4ec4b data/create/recipes/crafting/kinetics/orange_seat_from_other_seat.json d27b1c3448c8c1016501cbb09937ae1789d30df9 data/create/recipes/crafting/kinetics/orange_valve_handle_from_other_valve_handle.json -998d51c3709b8b1773c9e5e6bcd1e948e987ffa7 data/create/recipes/crafting/kinetics/pink_seat.json -fe31bd4b345300213f12ca36add5b73f12f9e383 data/create/recipes/crafting/kinetics/pink_seat_from_other_seat.json +6792f96fa2c069f5dc72369cbc066c8f888946ae data/create/recipes/crafting/kinetics/pink_seat.json +d03ab40e2e35b6d338e0f57e052514ca7179c84d data/create/recipes/crafting/kinetics/pink_seat_from_other_seat.json 204728953cb7401a0bacba941cd9197208091a99 data/create/recipes/crafting/kinetics/pink_valve_handle_from_other_valve_handle.json -37a82d95b51b2fb48836b05108f927560cd1829f data/create/recipes/crafting/kinetics/purple_seat.json -344d179410024f5a571ba044b5859ee594db6f63 data/create/recipes/crafting/kinetics/purple_seat_from_other_seat.json +b541e420e0fd274529e5bcb5c22096c27b043256 data/create/recipes/crafting/kinetics/purple_seat.json +c656a06bf435b394d7d1f2de2e5d807863f0b7a9 data/create/recipes/crafting/kinetics/purple_seat_from_other_seat.json ed9f4b3f75b416fcd813625ed1789b63f9c35127 data/create/recipes/crafting/kinetics/purple_valve_handle_from_other_valve_handle.json -63500aba9c9aaecd0f30956362aec71506ed3927 data/create/recipes/crafting/kinetics/red_seat.json -2ab372ae09d37c368af93551ff4b1512cb39b221 data/create/recipes/crafting/kinetics/red_seat_from_other_seat.json +66bca513d27d37492cb5a2ed82da5f874beba0a9 data/create/recipes/crafting/kinetics/red_seat.json +abd86818489edb22e277f2cef81f22b492d34b55 data/create/recipes/crafting/kinetics/red_seat_from_other_seat.json 9d70b0d7193b3cc9deb2436afd7f4c1a7a3aed05 data/create/recipes/crafting/kinetics/red_valve_handle_from_other_valve_handle.json -1a24720d14fa9631347343f9332f1e38b7bb29aa data/create/recipes/crafting/kinetics/white_seat.json -aa98c4f1432b0ade81784ea7517477ea6f935b70 data/create/recipes/crafting/kinetics/white_seat_from_other_seat.json +975439bc9c9f26acb11858ce1f0bba519883c8b5 data/create/recipes/crafting/kinetics/white_seat.json +b04c1cebcfbcf44c4ced04252f54dbfeb8f9ff12 data/create/recipes/crafting/kinetics/white_seat_from_other_seat.json 77eea3d2d6155f8303e632a5e51a6305a9136175 data/create/recipes/crafting/kinetics/white_valve_handle_from_other_valve_handle.json -cde72875aa396ed08be167eb0437ef682a548f66 data/create/recipes/crafting/kinetics/yellow_seat.json -0d355fac7e6c0f26f0863cc80056b6a78c7030e5 data/create/recipes/crafting/kinetics/yellow_seat_from_other_seat.json +48c9e3b9f5a8a0f598ab0f57cd8936724337bf1f data/create/recipes/crafting/kinetics/yellow_seat.json +75633a46c374230fab4096a45628b42d6012627d data/create/recipes/crafting/kinetics/yellow_seat_from_other_seat.json 2be097bb4f1e47a6b3a4a6f0ef222dffe31a1e22 data/create/recipes/crafting/kinetics/yellow_valve_handle_from_other_valve_handle.json -effe2c40e08c7c8e12a416c6f6644ce9800441f9 data/create/recipes/crimsite_pillar_from_crimsite_stonecutting.json +44a59669177a5a1b0b0eb7cb3dd46826311f4dfe data/create/recipes/crimsite_from_stone_types_crimsite_stonecutting.json c3f4fd2206f3885904913289761f2b8b758e4c95 data/create/recipes/crimsite_pillar_from_stone_types_crimsite_stonecutting.json 36e4dee2378e606f8aff84a874170a1696efb8ca data/create/recipes/crimson_window.json 142c0fee3eacea8f96a3ec1f76670d7c03deaf98 data/create/recipes/crimson_window_pane.json -7243161e8af022c06870a9883caaa48979bd9de9 data/create/recipes/cut_andesite_bricks_from_andesite_stonecutting.json 82cb9be82ce5109781169bdb47bbd49238b9824b data/create/recipes/cut_andesite_bricks_from_stone_types_andesite_stonecutting.json 022ab6c5664bf050b10bd1fcc2d84fca91e9e4d4 data/create/recipes/cut_andesite_brick_slab.json -a714f38e3ce53910bf5508a63e89c4dba9b71c2c data/create/recipes/cut_andesite_brick_slab_from_andesite_stonecutting.json edf981198463ac58524606f86dc15d2265e8b993 data/create/recipes/cut_andesite_brick_slab_from_stone_types_andesite_stonecutting.json 72486864f3a0d31a92212552441eb659f2541b60 data/create/recipes/cut_andesite_brick_slab_recycling.json 403560c91998a0347ef1f3353ea0b46d1d778396 data/create/recipes/cut_andesite_brick_stairs.json -8711801778dfcdc332436344b3b1ea01b2374842 data/create/recipes/cut_andesite_brick_stairs_from_andesite_stonecutting.json 22f463c679249738bf1a340a3b8ff14806303a70 data/create/recipes/cut_andesite_brick_stairs_from_stone_types_andesite_stonecutting.json e806e0144782b79fc533ca16687353b3e1be96ff data/create/recipes/cut_andesite_brick_wall.json -b7781431b89171be888c36232e69fa13990b240a data/create/recipes/cut_andesite_brick_wall_from_andesite_stonecutting.json 7d25517650c9f66b65f0f8841cf9bcda7ea401ec data/create/recipes/cut_andesite_brick_wall_from_stone_types_andesite_stonecutting.json -2fd48c9cc76601797d3a9cfc6108caa2ce13ef88 data/create/recipes/cut_andesite_from_andesite_stonecutting.json c3ab483224c3adbd467a4ec0b26a1f6a53fe81c4 data/create/recipes/cut_andesite_from_stone_types_andesite_stonecutting.json 64761361b44ab522d0c07d65680f8853ae2f2042 data/create/recipes/cut_andesite_slab.json -c57c4fefe073bde657432d4a3a65f7744d9a1154 data/create/recipes/cut_andesite_slab_from_andesite_stonecutting.json 50dcff201da369bdc591fdc320aae3547f114284 data/create/recipes/cut_andesite_slab_from_stone_types_andesite_stonecutting.json 033735fd92370adc6e4d3e130ee92f5dd86c0bc2 data/create/recipes/cut_andesite_slab_recycling.json 770f417cb77ca9551c25afa592e50c10b913a844 data/create/recipes/cut_andesite_stairs.json -80a1a2a2738ec674e55d22ae7801a9292fea9694 data/create/recipes/cut_andesite_stairs_from_andesite_stonecutting.json c284fc46aabae9c5ab79071eb63ec9b07a9d1002 data/create/recipes/cut_andesite_stairs_from_stone_types_andesite_stonecutting.json af6443f2bf998f12d965b905f7f5d6b68c3d7639 data/create/recipes/cut_andesite_wall.json -539531924a1efea2f45a5fd94f46c02145d71870 data/create/recipes/cut_andesite_wall_from_andesite_stonecutting.json 5df6e8d558f656533aff514aee8cdec7cf8d6fdf data/create/recipes/cut_andesite_wall_from_stone_types_andesite_stonecutting.json -536de7758c89c7df53df30be0ab7f13f2a050c61 data/create/recipes/cut_asurine_bricks_from_asurine_stonecutting.json e335b15907be053ab0f2649338b12a86371b78f7 data/create/recipes/cut_asurine_bricks_from_stone_types_asurine_stonecutting.json d96a1cd81586540aa471e48003b29b2c0182c8a8 data/create/recipes/cut_asurine_brick_slab.json -17390070f7c90789481b8abad0d9cd3ec5095e5a data/create/recipes/cut_asurine_brick_slab_from_asurine_stonecutting.json cf61e0806a3988a771675a261a540cbb62352d80 data/create/recipes/cut_asurine_brick_slab_from_stone_types_asurine_stonecutting.json 86606a0717bba33f457707d96461fec6a22d23de data/create/recipes/cut_asurine_brick_slab_recycling.json 51c4fa3dffc2e61bf325061cc6379c8cc38089c6 data/create/recipes/cut_asurine_brick_stairs.json -d22bf68c563cff89ed7e73941e4764bb01131846 data/create/recipes/cut_asurine_brick_stairs_from_asurine_stonecutting.json 382a7faa460ac286631fe063280541f2f499d895 data/create/recipes/cut_asurine_brick_stairs_from_stone_types_asurine_stonecutting.json 733db957122d3ecb30d90ad2475b92ec2753e72b data/create/recipes/cut_asurine_brick_wall.json -481c8bdceb10dc381209276d3347732d64d674e0 data/create/recipes/cut_asurine_brick_wall_from_asurine_stonecutting.json 8bb8a9f8e8dd0d6585311c326dcf3f40227149a9 data/create/recipes/cut_asurine_brick_wall_from_stone_types_asurine_stonecutting.json -78b3945f79b97e5c3402ccda04eb9e71cf17ec41 data/create/recipes/cut_asurine_from_asurine_stonecutting.json 0188d62fbeede94f8596dd5cc73d361a160e8c95 data/create/recipes/cut_asurine_from_stone_types_asurine_stonecutting.json d6e9817e0debcc644f536c2e8d20018afd139706 data/create/recipes/cut_asurine_slab.json -7506908017f8d86f8428baf46da2d74469108c66 data/create/recipes/cut_asurine_slab_from_asurine_stonecutting.json 37c502094ee96da9e4983142dae5e023c6bcfe14 data/create/recipes/cut_asurine_slab_from_stone_types_asurine_stonecutting.json fe3dd5c7d5bdea71a75003cf3d50439d9d21458d data/create/recipes/cut_asurine_slab_recycling.json d02b66975694eaf380becf5c7b3e27520dc831df data/create/recipes/cut_asurine_stairs.json -bee833998555b831b2478829a1ac68e34ea3b59e data/create/recipes/cut_asurine_stairs_from_asurine_stonecutting.json cade93c9328afcacf4507aa7699c4b09fb4592d4 data/create/recipes/cut_asurine_stairs_from_stone_types_asurine_stonecutting.json b897ff50963c97740e5ac93bd8b8b0cdf1d5ebcd data/create/recipes/cut_asurine_wall.json -28609858396684bc85694b8cf74545ea2ea8fc0f data/create/recipes/cut_asurine_wall_from_asurine_stonecutting.json 45a712e41a74982cfb94a39da199ec6c95eef798 data/create/recipes/cut_asurine_wall_from_stone_types_asurine_stonecutting.json -a435f899ea6bc1569cbbd356ec9d29f7df0e4d9b data/create/recipes/cut_calcite_bricks_from_calcite_stonecutting.json da11f21280ba1ed06ffe8afe77db3e9e1bbcb1a3 data/create/recipes/cut_calcite_bricks_from_stone_types_calcite_stonecutting.json feb74d5a870b926f80e97ad93ab13a189f0eeebd data/create/recipes/cut_calcite_brick_slab.json -fa5aefb14087829b77c93006eb9dada04f1321d0 data/create/recipes/cut_calcite_brick_slab_from_calcite_stonecutting.json 1c21eb6c785729a8ea274513e1313aed952e105e data/create/recipes/cut_calcite_brick_slab_from_stone_types_calcite_stonecutting.json 2a3f078f7f40ba3bc5c17a037db1f8ee415e4e3f data/create/recipes/cut_calcite_brick_slab_recycling.json b7ca47693e5dc2a698ff55f4bdd0a908e2cba3a9 data/create/recipes/cut_calcite_brick_stairs.json -527d7ba8e8cb74e1b8d3ae20f4b7fd23c40175fd data/create/recipes/cut_calcite_brick_stairs_from_calcite_stonecutting.json 10fe509e01e3ed1b04bd2f384c0aa3db96b117f1 data/create/recipes/cut_calcite_brick_stairs_from_stone_types_calcite_stonecutting.json 0660612a8b535228ded27e416042a18f5f57dc5e data/create/recipes/cut_calcite_brick_wall.json -6798e2458f85eebfa5503a893110333ff3680b0f data/create/recipes/cut_calcite_brick_wall_from_calcite_stonecutting.json 1e67376e484923b84bd64b0b22b4e55b581ac419 data/create/recipes/cut_calcite_brick_wall_from_stone_types_calcite_stonecutting.json -3fcb0b8e66abe09e63de63fee58c2d60d11e66a0 data/create/recipes/cut_calcite_from_calcite_stonecutting.json 98b014b64c97371f04aaacbdd23e13e274e36e3b data/create/recipes/cut_calcite_from_stone_types_calcite_stonecutting.json 841e2e2f5bacf2520bf21306904b353986aaac08 data/create/recipes/cut_calcite_slab.json -6b9dd0dd06a63e2a91a8e631bf013acb36dbb68d data/create/recipes/cut_calcite_slab_from_calcite_stonecutting.json 8426a494b776148056cb4525e62744d0be8b28cd data/create/recipes/cut_calcite_slab_from_stone_types_calcite_stonecutting.json 6b0bff115ff5a8d7392e516ba346ddb4139285b6 data/create/recipes/cut_calcite_slab_recycling.json df6ef977db9c55556f100c188f359373c13e81c9 data/create/recipes/cut_calcite_stairs.json -a16168f0fb539ff961d515492739b05f1f27d6f3 data/create/recipes/cut_calcite_stairs_from_calcite_stonecutting.json a7e7fb425d3c1f21f5ed53da79957363fed824df data/create/recipes/cut_calcite_stairs_from_stone_types_calcite_stonecutting.json c77af660dfe2f6436568eefb0a6c416ede3611da data/create/recipes/cut_calcite_wall.json -4407e77e5521a17237f66004218a0f10f4d557ba data/create/recipes/cut_calcite_wall_from_calcite_stonecutting.json 01b4c23362f15ee0e5c207c46383f96032c89d98 data/create/recipes/cut_calcite_wall_from_stone_types_calcite_stonecutting.json -79de2cf7d1909fe0f8d63b1edf9e517e398a2cdb data/create/recipes/cut_crimsite_bricks_from_crimsite_stonecutting.json 07aff2bb6424de46463b2c965418ed52efd0a790 data/create/recipes/cut_crimsite_bricks_from_stone_types_crimsite_stonecutting.json c353d2a2eae6c08ef47a5225109f68777791f17c data/create/recipes/cut_crimsite_brick_slab.json -7f9ae90ec35513a565b74203b466c3987ff30449 data/create/recipes/cut_crimsite_brick_slab_from_crimsite_stonecutting.json 86c3a5c64561052489b3ceb9e08be5a8729198a9 data/create/recipes/cut_crimsite_brick_slab_from_stone_types_crimsite_stonecutting.json e3215d4e651e70402b896ba50975cb2f23d16278 data/create/recipes/cut_crimsite_brick_slab_recycling.json ee4da7f65ddedbc9f5985d29116f2e6942e114fb data/create/recipes/cut_crimsite_brick_stairs.json -6a704e9f4512270bd3b52af4b1189ec82d5b3fe1 data/create/recipes/cut_crimsite_brick_stairs_from_crimsite_stonecutting.json c7186fb1a75f59aff929e843f50a162a090b7bb3 data/create/recipes/cut_crimsite_brick_stairs_from_stone_types_crimsite_stonecutting.json 4af95056d3314d0894217f1cbfb0501f1b462cdc data/create/recipes/cut_crimsite_brick_wall.json -cbd645a0309985e28bd5e4fb1c3dae4034f6c846 data/create/recipes/cut_crimsite_brick_wall_from_crimsite_stonecutting.json 13ac9464098e8c67e820dc898c025ab0382d852a data/create/recipes/cut_crimsite_brick_wall_from_stone_types_crimsite_stonecutting.json -d4793c400caa6d5db3590635ff59e6b8f1d35adc data/create/recipes/cut_crimsite_from_crimsite_stonecutting.json 18ce9ff32eda2d869bd11f398a86e78b71f6d0fe data/create/recipes/cut_crimsite_from_stone_types_crimsite_stonecutting.json 87a0950dd76edfd3d7815aa62e729adbed719cb6 data/create/recipes/cut_crimsite_slab.json -f50d8b9b7cbd2ea6af7bddc697f71e82b617dd70 data/create/recipes/cut_crimsite_slab_from_crimsite_stonecutting.json 6271d5bc0377814ba06061bfffcb812ca2ef8f03 data/create/recipes/cut_crimsite_slab_from_stone_types_crimsite_stonecutting.json acfe33dbb889c820c213bcbc8593766703bf3a25 data/create/recipes/cut_crimsite_slab_recycling.json e7b8720c5ac60d0a005f4a38d85930983693d308 data/create/recipes/cut_crimsite_stairs.json -eb62c79974224d53e1a67e233346b1659cf64ee3 data/create/recipes/cut_crimsite_stairs_from_crimsite_stonecutting.json 90b03cf1e72d3b803e33755832e0722ff264681b data/create/recipes/cut_crimsite_stairs_from_stone_types_crimsite_stonecutting.json 2b1ae7397428c18865236674997a0e60daff65f9 data/create/recipes/cut_crimsite_wall.json -a5062e05ccd16d605d6259a880cd855592c701a3 data/create/recipes/cut_crimsite_wall_from_crimsite_stonecutting.json 18f9548175baab0173785d7ef308096067712dd2 data/create/recipes/cut_crimsite_wall_from_stone_types_crimsite_stonecutting.json -07c35918ebb5bec0c9823816501ff5236b9da175 data/create/recipes/cut_deepslate_bricks_from_deepslate_stonecutting.json de1a11b7ed71f1f7aeea2791fe922feef689fd35 data/create/recipes/cut_deepslate_bricks_from_stone_types_deepslate_stonecutting.json 4ebf84604094e75d0825e27e2ff53f868fdc5523 data/create/recipes/cut_deepslate_brick_slab.json -abfcb16669e75d653bcf6b264c2b6bce1397a747 data/create/recipes/cut_deepslate_brick_slab_from_deepslate_stonecutting.json 2c0795b92759dab751f86f50aa80440df2245526 data/create/recipes/cut_deepslate_brick_slab_from_stone_types_deepslate_stonecutting.json dbcc41c48cf28b71dcd9f3b6ecae43c8de681532 data/create/recipes/cut_deepslate_brick_slab_recycling.json e483d0e539120d3ff4dc32a01a599e97b2bb2aac data/create/recipes/cut_deepslate_brick_stairs.json -5bde28e0acd2a52933250ef1d6ef2447ce0bfcb7 data/create/recipes/cut_deepslate_brick_stairs_from_deepslate_stonecutting.json 7b3489e5b629a995691be117c5a378769c743449 data/create/recipes/cut_deepslate_brick_stairs_from_stone_types_deepslate_stonecutting.json ec02733f6130beeed404ca06017e010a57cbf2d7 data/create/recipes/cut_deepslate_brick_wall.json -221ad71058cec76b20ea04ad229622f7aa23f610 data/create/recipes/cut_deepslate_brick_wall_from_deepslate_stonecutting.json 73a07a5fa665bb20d131f0a0e40806116316928a data/create/recipes/cut_deepslate_brick_wall_from_stone_types_deepslate_stonecutting.json -4e993c28463098cd05c6455e6fb84a10e78eb8f6 data/create/recipes/cut_deepslate_from_deepslate_stonecutting.json 992fdc2eba2afe3ff8aad0ceee5424ecd3f3026d data/create/recipes/cut_deepslate_from_stone_types_deepslate_stonecutting.json bbd6f6300666f26a53a5b8b412e3efa254143e78 data/create/recipes/cut_deepslate_slab.json -1cd05a86df000c359ea00d0d8ed62c9031265c4d data/create/recipes/cut_deepslate_slab_from_deepslate_stonecutting.json f341d30b7fd427dea09a51d67e1e9532e5184be8 data/create/recipes/cut_deepslate_slab_from_stone_types_deepslate_stonecutting.json 82c9d41186f1f3ba4c110ab84228550574a703de data/create/recipes/cut_deepslate_slab_recycling.json 55d18f3739a807a55636e78420b42217f925daba data/create/recipes/cut_deepslate_stairs.json -ed6b93bef652c01316ef99845b3a396e116719d6 data/create/recipes/cut_deepslate_stairs_from_deepslate_stonecutting.json e6deec1352fb5c74c470dc488b71e5f8f55bdfbf data/create/recipes/cut_deepslate_stairs_from_stone_types_deepslate_stonecutting.json 1abfa4aaa0d001674c260c5f5dffb5fa088d79b6 data/create/recipes/cut_deepslate_wall.json -cecc667302b8c9ceac10980c54366e50fecb8d74 data/create/recipes/cut_deepslate_wall_from_deepslate_stonecutting.json e752527479f71f96bb34878008bf8cfb23fd3045 data/create/recipes/cut_deepslate_wall_from_stone_types_deepslate_stonecutting.json -0b711a1957af3d7b1c73be8ac5ddde05c87a515b data/create/recipes/cut_diorite_bricks_from_diorite_stonecutting.json 2c23d13f48f3685bda6c564e080053fbfa71ab99 data/create/recipes/cut_diorite_bricks_from_stone_types_diorite_stonecutting.json e0a9ac9e180f614c9af55bd1eba8f4e6e4e10eb4 data/create/recipes/cut_diorite_brick_slab.json -662da05168e2236c9495771c94956527b26223f9 data/create/recipes/cut_diorite_brick_slab_from_diorite_stonecutting.json 9d51c690c77321437561a006dc2f9bba975875e6 data/create/recipes/cut_diorite_brick_slab_from_stone_types_diorite_stonecutting.json fa76e64ac9b569f5d5f2f1ecc54e51f9be15aacf data/create/recipes/cut_diorite_brick_slab_recycling.json e8873addeb25ef874328fbd3d71e3651db688bf0 data/create/recipes/cut_diorite_brick_stairs.json -90aef5c6ca96dd88709c08cba87c50e6b8bddb33 data/create/recipes/cut_diorite_brick_stairs_from_diorite_stonecutting.json 9a26c4097519a9300e591b6578bbaf6c11f909e1 data/create/recipes/cut_diorite_brick_stairs_from_stone_types_diorite_stonecutting.json 78d5667bbc06053c4a44981b7055cf77432731fc data/create/recipes/cut_diorite_brick_wall.json -da9a9ff1660ef29d03584649cddb3fe5297ae7c4 data/create/recipes/cut_diorite_brick_wall_from_diorite_stonecutting.json f668f2c78a779bc3d0546a82dea02b9f4688e05c data/create/recipes/cut_diorite_brick_wall_from_stone_types_diorite_stonecutting.json -807be7075019afcca4ba14fe8984e0aed996a584 data/create/recipes/cut_diorite_from_diorite_stonecutting.json 1918ecb2ab16ca7dbb30eee4852b67dd963d872e data/create/recipes/cut_diorite_from_stone_types_diorite_stonecutting.json 5ee52c583315e917b1f5814da24efbe8dc3271b6 data/create/recipes/cut_diorite_slab.json -5adefea65e9c4200d3f10785ee181002df5b238a data/create/recipes/cut_diorite_slab_from_diorite_stonecutting.json 28765ac7f8b62373b32f014d1dd7f4afb50e1906 data/create/recipes/cut_diorite_slab_from_stone_types_diorite_stonecutting.json dd5f3c59a5d292f7b5c046be35da7f67e8383aa1 data/create/recipes/cut_diorite_slab_recycling.json a93fdf69d7c8d59662f56ddc9ba444681107a31b data/create/recipes/cut_diorite_stairs.json -774bdde391828433a8a2a83ff663530a5a86b95d data/create/recipes/cut_diorite_stairs_from_diorite_stonecutting.json be2c6c01630b90895e7215edce3d02352793dbc4 data/create/recipes/cut_diorite_stairs_from_stone_types_diorite_stonecutting.json 972f6e1854d3181940726aabace4c29f8b6900b0 data/create/recipes/cut_diorite_wall.json -035701e0acb53bb936e7453c83cfff1c201f31b1 data/create/recipes/cut_diorite_wall_from_diorite_stonecutting.json 8ff5d1ecff2202595f7cba5bd65c466c53ac2cc5 data/create/recipes/cut_diorite_wall_from_stone_types_diorite_stonecutting.json -6983cdc50f48b70d18552aa03db796892b3acefd data/create/recipes/cut_dripstone_bricks_from_dripstone_block_stonecutting.json 10550b023989113c26d430136daf1dc49f10ce63 data/create/recipes/cut_dripstone_bricks_from_stone_types_dripstone_stonecutting.json 95b2ee29267ca64c207d52611a7e7eda4b1997f4 data/create/recipes/cut_dripstone_brick_slab.json -78bdda67d3272415cb6516d42d44500c61c98815 data/create/recipes/cut_dripstone_brick_slab_from_dripstone_block_stonecutting.json f04bf1189b53e24974779d9e959e8973d9677162 data/create/recipes/cut_dripstone_brick_slab_from_stone_types_dripstone_stonecutting.json 332534fc2909ca83f5f7f4ab3adf92680bb17f79 data/create/recipes/cut_dripstone_brick_slab_recycling.json b5d2f259c90d9d2093e3812e7f187a05304cce99 data/create/recipes/cut_dripstone_brick_stairs.json -b0f62e0ad9a6ed98d242c101bf35fa1d1a24883e data/create/recipes/cut_dripstone_brick_stairs_from_dripstone_block_stonecutting.json 17bf8160eaf16655d454ddfe22b82c9a86462146 data/create/recipes/cut_dripstone_brick_stairs_from_stone_types_dripstone_stonecutting.json 1bb5afcac6281f15d7468a7f018a036d6c7a38a3 data/create/recipes/cut_dripstone_brick_wall.json -b497214a8f711afed01410ce8554591bab1dc531 data/create/recipes/cut_dripstone_brick_wall_from_dripstone_block_stonecutting.json 154931db54115cf4a64147cdd6d1eb7efff48737 data/create/recipes/cut_dripstone_brick_wall_from_stone_types_dripstone_stonecutting.json -fc427cf309998e12606a7513fc4812b777be0d6e data/create/recipes/cut_dripstone_from_dripstone_block_stonecutting.json 7147f9199f174c9864109fe5723528921aaa0c46 data/create/recipes/cut_dripstone_from_stone_types_dripstone_stonecutting.json 6a7a31d3e47bdf079f4174c8dd7816c6f7e69d96 data/create/recipes/cut_dripstone_slab.json -09be97b0367decc3fda8efa9855a258c6f6ef218 data/create/recipes/cut_dripstone_slab_from_dripstone_block_stonecutting.json a4f62a1a30592f82789988f93d8ae35d176eca59 data/create/recipes/cut_dripstone_slab_from_stone_types_dripstone_stonecutting.json 6e3f7b81fd9681782b8b05992312566f58a83f26 data/create/recipes/cut_dripstone_slab_recycling.json 15b68c152a18329a883d077de89100637e5c13a8 data/create/recipes/cut_dripstone_stairs.json -d9b65b1accc87e0140ea6fc220505bfa74248907 data/create/recipes/cut_dripstone_stairs_from_dripstone_block_stonecutting.json f2df5efedb6fb25ecb877b888007990082d9aca4 data/create/recipes/cut_dripstone_stairs_from_stone_types_dripstone_stonecutting.json 139fa4dd5650d1f16ee75f96db08559072709c75 data/create/recipes/cut_dripstone_wall.json -b6c7324e271cb00585b5d251cf19ab341cf40d1b data/create/recipes/cut_dripstone_wall_from_dripstone_block_stonecutting.json a3731ef689d3ac790bc3e3fd507f1134c99a751a data/create/recipes/cut_dripstone_wall_from_stone_types_dripstone_stonecutting.json -49e8e125ec50629b9552d8870b836348bb1fe0ec data/create/recipes/cut_granite_bricks_from_granite_stonecutting.json 9c4c64666b18d3adb11cd3d56667fabf6e88dfe2 data/create/recipes/cut_granite_bricks_from_stone_types_granite_stonecutting.json 02b0ce47ba2235ac4d8d718864e0b62cf6ae0e2b data/create/recipes/cut_granite_brick_slab.json -87660ea785e21396f6bc0ab08c69f8dc9606f690 data/create/recipes/cut_granite_brick_slab_from_granite_stonecutting.json d073b9b0b8ca2fbdc5e1ed16f6f195a5f3af4588 data/create/recipes/cut_granite_brick_slab_from_stone_types_granite_stonecutting.json 1dfd539c17a3342a0cd194ce1465a808aacbeda3 data/create/recipes/cut_granite_brick_slab_recycling.json f5a853aa893c31069248ecd850017689b74a0806 data/create/recipes/cut_granite_brick_stairs.json -24e2aed08787d55404c2d3c8dfc4552fe4569ee0 data/create/recipes/cut_granite_brick_stairs_from_granite_stonecutting.json f38fc7014aa83d4914d50d87ee3f8f762c078a78 data/create/recipes/cut_granite_brick_stairs_from_stone_types_granite_stonecutting.json 5bebafd72c1b22177c11c90a2531f39928d2ad1d data/create/recipes/cut_granite_brick_wall.json -97da75a8c87454c915ccbebef0051ef858d2eb27 data/create/recipes/cut_granite_brick_wall_from_granite_stonecutting.json b81db94b6228f512049324dd1436880f1e86e444 data/create/recipes/cut_granite_brick_wall_from_stone_types_granite_stonecutting.json -5bd19a9545c021ef07febdff8ff7336658ff8e44 data/create/recipes/cut_granite_from_granite_stonecutting.json 01970a95f17648a7ef1fb0337ee2e82eb2279e9e data/create/recipes/cut_granite_from_stone_types_granite_stonecutting.json 8b099242eaa7b7918ee158c99b228779a2d43d23 data/create/recipes/cut_granite_slab.json -e833ef1586e12714979b1230dc23d613bd2635d0 data/create/recipes/cut_granite_slab_from_granite_stonecutting.json d239323b7a3b65b2fd7005350a90d578671c2b81 data/create/recipes/cut_granite_slab_from_stone_types_granite_stonecutting.json 6d78b033634dad8981a7c4c6724e82e9b25be334 data/create/recipes/cut_granite_slab_recycling.json db17e55ce7548bd6c5ac1d2c55dc0a5379a4b08e data/create/recipes/cut_granite_stairs.json -cd07c17c6f4e09f25666bf19e7b359cac4f80f53 data/create/recipes/cut_granite_stairs_from_granite_stonecutting.json 3d85d483073d37fea7d9a95831b3b856c0725b98 data/create/recipes/cut_granite_stairs_from_stone_types_granite_stonecutting.json 44c1e2ccfae04fb29b6855199bcbe9ef36b1c386 data/create/recipes/cut_granite_wall.json -bf395379f03fd47918f1e74c059c823a35d7cde9 data/create/recipes/cut_granite_wall_from_granite_stonecutting.json d43a876bf89bf3536c80fd5e3ef0ee36c147cd06 data/create/recipes/cut_granite_wall_from_stone_types_granite_stonecutting.json -c496c95dd5f3e82dc1cc047285d106657ed30798 data/create/recipes/cut_limestone_bricks_from_limestone_stonecutting.json 7cdd3cf302cfe4ef21c0a89dadef4f781e307bb0 data/create/recipes/cut_limestone_bricks_from_stone_types_limestone_stonecutting.json 57b38eb9dd95a31f1ed5ea43fbc984df010b1cc5 data/create/recipes/cut_limestone_brick_slab.json -e99d1201ec9b3c5ceaf9f61de491812ac6d0380d data/create/recipes/cut_limestone_brick_slab_from_limestone_stonecutting.json c3d3ff37e29c435b2a13d30bd4ded0f6ca9fbfbc data/create/recipes/cut_limestone_brick_slab_from_stone_types_limestone_stonecutting.json 459babb2bd01e9e1ece4c8cd2865690997f01c66 data/create/recipes/cut_limestone_brick_slab_recycling.json f4d26513a0ec971ee196030a0e104c31f121f54e data/create/recipes/cut_limestone_brick_stairs.json -742db2049912dff875beebf1b9a8725328181bf8 data/create/recipes/cut_limestone_brick_stairs_from_limestone_stonecutting.json 570983b2b27862dabe9f3d1bcd76d2909b8bdb3c data/create/recipes/cut_limestone_brick_stairs_from_stone_types_limestone_stonecutting.json f3a601c2e0efdf7f9afe74dac8077c6aaefe187a data/create/recipes/cut_limestone_brick_wall.json -f4a3ef7017bfdcb7dee7840ed58a06a54d143291 data/create/recipes/cut_limestone_brick_wall_from_limestone_stonecutting.json 5ac226aff9d854efc47ed71241e6c098b170b9b0 data/create/recipes/cut_limestone_brick_wall_from_stone_types_limestone_stonecutting.json -a38a4fcfbce4de0af2c930994feb2eb4491ad29a data/create/recipes/cut_limestone_from_limestone_stonecutting.json 329950373aaaf8e70c54cf5e2467c7a84f372078 data/create/recipes/cut_limestone_from_stone_types_limestone_stonecutting.json f143bc09a7315ce8f6c023670f02e022f5fc081b data/create/recipes/cut_limestone_slab.json -1b5723ea0cd76d730f0b1fa1496a1e6eed0657a4 data/create/recipes/cut_limestone_slab_from_limestone_stonecutting.json 628a0a64c2dcd63f17a3ec9ce55ac643b194eacc data/create/recipes/cut_limestone_slab_from_stone_types_limestone_stonecutting.json 94ca5d0fb91c2a326fb6e80c4d179edf9799c31e data/create/recipes/cut_limestone_slab_recycling.json 55ce9ba8654d3fac1941b252019f4c343e27b25a data/create/recipes/cut_limestone_stairs.json -e66de64fc32ebf33fd6618c93f44d8dceb702cc9 data/create/recipes/cut_limestone_stairs_from_limestone_stonecutting.json ba301da212ee14ff42c38487d0906a2da203e3c3 data/create/recipes/cut_limestone_stairs_from_stone_types_limestone_stonecutting.json 832f8c8079cfcf6ec2ccedad4361d7f7940f00cf data/create/recipes/cut_limestone_wall.json -109e7326ec2394c6ed4434f715143870c5870db2 data/create/recipes/cut_limestone_wall_from_limestone_stonecutting.json b14e6972f8586e569a7ab4ecf6ed5d6db1a2bded data/create/recipes/cut_limestone_wall_from_stone_types_limestone_stonecutting.json -190ff1643b6dd7e6695f8cdb3c3c9988db59e94f data/create/recipes/cut_ochrum_bricks_from_ochrum_stonecutting.json a1a2b95283d88e1d990e00da9a095fe928b2aa2f data/create/recipes/cut_ochrum_bricks_from_stone_types_ochrum_stonecutting.json 3046e2e68f48dda4e42567f6ad213d67c7027c13 data/create/recipes/cut_ochrum_brick_slab.json -f199654f858ba908a5395620e147b8f7c980f3a0 data/create/recipes/cut_ochrum_brick_slab_from_ochrum_stonecutting.json 58514a5f216706e9bb62b27ad03701fe02bac013 data/create/recipes/cut_ochrum_brick_slab_from_stone_types_ochrum_stonecutting.json 6cc3167ebf075d7b302a359d1afdddf5753d0e26 data/create/recipes/cut_ochrum_brick_slab_recycling.json 11e4d7b770c0a0c92cdda0582b3d2ce0173e2030 data/create/recipes/cut_ochrum_brick_stairs.json -d1372cf4308badf29f32d0fdf863e4a90c2a1fb3 data/create/recipes/cut_ochrum_brick_stairs_from_ochrum_stonecutting.json ec6339d6658b0d32e46c8a4a4e06d94a388a6332 data/create/recipes/cut_ochrum_brick_stairs_from_stone_types_ochrum_stonecutting.json 675220c28cc18c6764892188ad8c31dc904a71fc data/create/recipes/cut_ochrum_brick_wall.json -c6312c871b0a75eb2024eeacd808a425177e2356 data/create/recipes/cut_ochrum_brick_wall_from_ochrum_stonecutting.json 1b8a4c81680df542a5e6b9e665c96649cf3eb7fa data/create/recipes/cut_ochrum_brick_wall_from_stone_types_ochrum_stonecutting.json -10b1919a030c2a89160dcfc17fde1079c1f9c9b2 data/create/recipes/cut_ochrum_from_ochrum_stonecutting.json 2b967f3424196b5da9b396ea58fb969d406af789 data/create/recipes/cut_ochrum_from_stone_types_ochrum_stonecutting.json ff2afbe40d548f9fea24795adf59882ce1582044 data/create/recipes/cut_ochrum_slab.json -0058b7b0a8d62338528e5b7bfa3c004b4a2c5f49 data/create/recipes/cut_ochrum_slab_from_ochrum_stonecutting.json 9a26cba276cf135a10c71d31f5b960b2ee6ac444 data/create/recipes/cut_ochrum_slab_from_stone_types_ochrum_stonecutting.json 4054864033e52ec77e576fb0df7b872083df583e data/create/recipes/cut_ochrum_slab_recycling.json d4d63261ed37da63456cc949bde89f6fd5063344 data/create/recipes/cut_ochrum_stairs.json -2a6499d322cd1fbe8d5cc70f4eac6456672026c1 data/create/recipes/cut_ochrum_stairs_from_ochrum_stonecutting.json 75a232ccede0ffa7feb3e69da17c6a514a908907 data/create/recipes/cut_ochrum_stairs_from_stone_types_ochrum_stonecutting.json 6bb32a133242936284866eb3947205e1e9f18b65 data/create/recipes/cut_ochrum_wall.json -bffa6c3edddf5870c7b3bb71ea84471683a96e6a data/create/recipes/cut_ochrum_wall_from_ochrum_stonecutting.json ee0dff8e1317aeffd061688879b97e81a00b7adb data/create/recipes/cut_ochrum_wall_from_stone_types_ochrum_stonecutting.json -aace29cc50503c23c5b76f5ee9c7ff31f7dffae0 data/create/recipes/cut_scorchia_bricks_from_scorchia_stonecutting.json 087eefb8ffd61fd88f1db6ca25f9ac31e93f2fdf data/create/recipes/cut_scorchia_bricks_from_stone_types_scorchia_stonecutting.json 10ecf6658288f5414281301670965ae3ce1adb21 data/create/recipes/cut_scorchia_brick_slab.json -394b13f93341e403516ce3624c13395166ab53da data/create/recipes/cut_scorchia_brick_slab_from_scorchia_stonecutting.json 2f38c410d5eb93bdb8c8be0f68ac89726e3c765c data/create/recipes/cut_scorchia_brick_slab_from_stone_types_scorchia_stonecutting.json e296e6af6865bf6e4618dab8a96bb88f6999a9a5 data/create/recipes/cut_scorchia_brick_slab_recycling.json e39e31421c88eb53f362fa62370ce16f76b83c7f data/create/recipes/cut_scorchia_brick_stairs.json -eb94f1fec3887171262630cdd508aa60af0fa094 data/create/recipes/cut_scorchia_brick_stairs_from_scorchia_stonecutting.json bd5c803c855222a29998dd784e6d12a18dd612d9 data/create/recipes/cut_scorchia_brick_stairs_from_stone_types_scorchia_stonecutting.json e35fdde81ab4264052198393c88a89d8f9a03b1c data/create/recipes/cut_scorchia_brick_wall.json -e0b25f32f0c3d1fef071a506d284b6cd4883135b data/create/recipes/cut_scorchia_brick_wall_from_scorchia_stonecutting.json 37fc5ae45d0260de9a5c45b0a1b208e4d146a562 data/create/recipes/cut_scorchia_brick_wall_from_stone_types_scorchia_stonecutting.json -fe22c5c5dd5ece4ed3fe0d665abe1af6bbb22d7f data/create/recipes/cut_scorchia_from_scorchia_stonecutting.json f6dfd648418f24da093b80978c2f6e070f33ff6d data/create/recipes/cut_scorchia_from_stone_types_scorchia_stonecutting.json a93f21cbba37d3c90f6b5520c6e45cd6b93ebdf1 data/create/recipes/cut_scorchia_slab.json -59caf2cdbf6db1e201400003a092c3f0afcb50a1 data/create/recipes/cut_scorchia_slab_from_scorchia_stonecutting.json fbd9a92d3c3d9e823cac51347320219f1734ec04 data/create/recipes/cut_scorchia_slab_from_stone_types_scorchia_stonecutting.json cbb07a542a5f019019f61386c20976cb76ec316f data/create/recipes/cut_scorchia_slab_recycling.json 2c47576f7b6e72d9b0a87973fc49c39fd217f75e data/create/recipes/cut_scorchia_stairs.json -2dcb3dcaff2504cf718a82239b3e6fee95f90e75 data/create/recipes/cut_scorchia_stairs_from_scorchia_stonecutting.json 1ddfefce136201ae78dbc53ba472080332fd6366 data/create/recipes/cut_scorchia_stairs_from_stone_types_scorchia_stonecutting.json 7a5120b5f62a1ec8d386727d891bccf2569bdf2a data/create/recipes/cut_scorchia_wall.json -7872bd382f38ae60418619b2940631a41058f4b7 data/create/recipes/cut_scorchia_wall_from_scorchia_stonecutting.json c594d886a303ad6e24d1283004442835ee861fbc data/create/recipes/cut_scorchia_wall_from_stone_types_scorchia_stonecutting.json -a442cc3ea48102050d46aee6935bf9204036e661 data/create/recipes/cut_scoria_bricks_from_scoria_stonecutting.json 8650c0db70a3521b50404252106e0185b4f25a45 data/create/recipes/cut_scoria_bricks_from_stone_types_scoria_stonecutting.json 2840209bab463b9c527deb21da03f82fa5bc0077 data/create/recipes/cut_scoria_brick_slab.json -2276b9b644ddcd2d66f81244377af184aad3e6e2 data/create/recipes/cut_scoria_brick_slab_from_scoria_stonecutting.json e7080ca9b6a507bec4a4a3dd52a28c1c33975628 data/create/recipes/cut_scoria_brick_slab_from_stone_types_scoria_stonecutting.json f5b56f6eb9c1ac0f8168b2b0f0b0ab00655ebfdb data/create/recipes/cut_scoria_brick_slab_recycling.json 97dceb00ee6bf69ac5b8e3c4712ab7cf046cc2f1 data/create/recipes/cut_scoria_brick_stairs.json -cfa141ea7d8b4ae515a2b129fed06bf98748196c data/create/recipes/cut_scoria_brick_stairs_from_scoria_stonecutting.json 3fd560355163f0afafefe886e75fd8b2c3cf2b6f data/create/recipes/cut_scoria_brick_stairs_from_stone_types_scoria_stonecutting.json ebc78ae650d245c7c8529649783b8517279b0bb3 data/create/recipes/cut_scoria_brick_wall.json -9325c4639c4ee8ad649eb5738a272e276bb8a8b8 data/create/recipes/cut_scoria_brick_wall_from_scoria_stonecutting.json 553642a4e0dc5f934da8127a427ccdf53d3f51f9 data/create/recipes/cut_scoria_brick_wall_from_stone_types_scoria_stonecutting.json -35aa3e233f8293c34c3ca908ae94ac95c1ea6823 data/create/recipes/cut_scoria_from_scoria_stonecutting.json 5702063be3d38fa6b3ae5c998337676a0cf91149 data/create/recipes/cut_scoria_from_stone_types_scoria_stonecutting.json 370837333fbb970b88c3a127bf138ebde8b14051 data/create/recipes/cut_scoria_slab.json -92aa2e15f4fbafe303aa4d5e97ba048c39043fb4 data/create/recipes/cut_scoria_slab_from_scoria_stonecutting.json 1656e822e823fcdf04120b55235aa477845a69a6 data/create/recipes/cut_scoria_slab_from_stone_types_scoria_stonecutting.json d0c88c037004911e377d88cf5a28ff85a413d07e data/create/recipes/cut_scoria_slab_recycling.json 1b497121181dc374f6e5dd2a52a889986690f2dd data/create/recipes/cut_scoria_stairs.json -d836f281d6bdfd0022bbee340977243a9627d1d3 data/create/recipes/cut_scoria_stairs_from_scoria_stonecutting.json 8748df6152c923930452397367562bb6007058cf data/create/recipes/cut_scoria_stairs_from_stone_types_scoria_stonecutting.json 414f6fe12dbeb358583f3d53b846a0f213b49264 data/create/recipes/cut_scoria_wall.json -585e08168d03f722b0cdb40f9fe0940706364072 data/create/recipes/cut_scoria_wall_from_scoria_stonecutting.json 42235c6ded520ecda3321e8cd8910dcfa05cd61e data/create/recipes/cut_scoria_wall_from_stone_types_scoria_stonecutting.json c02b4daf0050d705c145c0698aaa3094724ba2f1 data/create/recipes/cut_tuff_bricks_from_stone_types_tuff_stonecutting.json -c525dceb7dfcadfc8c002c7e33da86e7e843bdca data/create/recipes/cut_tuff_bricks_from_tuff_stonecutting.json 3bbc0727d8f54d4d2dc44259906771121dd54159 data/create/recipes/cut_tuff_brick_slab.json 9e0182206fab754daa0596259be0b98a712ba859 data/create/recipes/cut_tuff_brick_slab_from_stone_types_tuff_stonecutting.json -20e7420ececccf4c04c422a66875c8737afec0de data/create/recipes/cut_tuff_brick_slab_from_tuff_stonecutting.json 86938ed4ef969e85163c25e2a60181433247b73b data/create/recipes/cut_tuff_brick_slab_recycling.json d0c655d5e34c1dc85089857e43da5e882283c026 data/create/recipes/cut_tuff_brick_stairs.json 90f3241a3eb47d9b0902b639fadee76e41b92a72 data/create/recipes/cut_tuff_brick_stairs_from_stone_types_tuff_stonecutting.json -fb4162ca8c2459b539e3908c4f0a42a11735eaf9 data/create/recipes/cut_tuff_brick_stairs_from_tuff_stonecutting.json eb68c56d591ec1cbf11a6699ad21d6988826d03a data/create/recipes/cut_tuff_brick_wall.json aa41f89028dfa995dc11b881894e5a5993e4c4f9 data/create/recipes/cut_tuff_brick_wall_from_stone_types_tuff_stonecutting.json -0a10cc890cf09577aa26efeedfe7de0cb5a4985c data/create/recipes/cut_tuff_brick_wall_from_tuff_stonecutting.json 41dc800ae0a8918f4602d610ff0ba9714cdfe8dc data/create/recipes/cut_tuff_from_stone_types_tuff_stonecutting.json -edb6c5c8646b8ab49978f303f7269ca19013972b data/create/recipes/cut_tuff_from_tuff_stonecutting.json d3f752c2011207681ad1bc04d5611de512b0c9ca data/create/recipes/cut_tuff_slab.json 94667fb1e6203bd66bef10acfee7cd990009d26f data/create/recipes/cut_tuff_slab_from_stone_types_tuff_stonecutting.json -3c6f321e4113a301d1b7a86308391d61db201396 data/create/recipes/cut_tuff_slab_from_tuff_stonecutting.json 1ae833e28f83c5f22f5bb9ece544734a0b2e321f data/create/recipes/cut_tuff_slab_recycling.json 97af803fba08b36a1afaacd309e072d4cc3f34a0 data/create/recipes/cut_tuff_stairs.json 3b3ba319bd67a4e7f555cfcb54f9dc1fc22cf015 data/create/recipes/cut_tuff_stairs_from_stone_types_tuff_stonecutting.json -1a6c1a84daa9900dd7b635c73f512462c902f55c data/create/recipes/cut_tuff_stairs_from_tuff_stonecutting.json 109ad414a11222932465d0e80ff6931a8b1a5833 data/create/recipes/cut_tuff_wall.json 5705b0312c5c70d48662c2ff375f0b2cfe3b4902 data/create/recipes/cut_tuff_wall_from_stone_types_tuff_stonecutting.json -7d3eed92480c491455960b3edce7c8a2ef576f44 data/create/recipes/cut_tuff_wall_from_tuff_stonecutting.json 8ab3c640b57421a8c0341ab4ec5bade31376d059 data/create/recipes/cut_veridium_bricks_from_stone_types_veridium_stonecutting.json -644243f7b0a817c86e92f7ed45d9b972e4c106e7 data/create/recipes/cut_veridium_bricks_from_veridium_stonecutting.json 873d12e6e187f5c5e7f82ca913cb2e25cce8d087 data/create/recipes/cut_veridium_brick_slab.json 1705fd5fc9ecc9a650812c89f500b5ef9aec2626 data/create/recipes/cut_veridium_brick_slab_from_stone_types_veridium_stonecutting.json -80c4661bd1bbd015bbc892441b437d0be61b1e05 data/create/recipes/cut_veridium_brick_slab_from_veridium_stonecutting.json 238aeedf55624671809a37246581d28fe6b2c19e data/create/recipes/cut_veridium_brick_slab_recycling.json e85c68731ecb85752d9df6812ee05201a6731948 data/create/recipes/cut_veridium_brick_stairs.json db2ea87f3ec8924ba9e0b87cd6a6edeb93c0c2d8 data/create/recipes/cut_veridium_brick_stairs_from_stone_types_veridium_stonecutting.json -2facd233cb21df177daedb727a6ba69b479c8a99 data/create/recipes/cut_veridium_brick_stairs_from_veridium_stonecutting.json 5488d54e16c00184183a7868fb0848ed1191e990 data/create/recipes/cut_veridium_brick_wall.json ed752a7f698e3ecbb5e4f848a78f8b3c7c6bf12e data/create/recipes/cut_veridium_brick_wall_from_stone_types_veridium_stonecutting.json -ac149ccb1b622bf6990b0d628a8cfdc0458dc10c data/create/recipes/cut_veridium_brick_wall_from_veridium_stonecutting.json e0355543105e4ec9d672d2a050e70b5c198ea472 data/create/recipes/cut_veridium_from_stone_types_veridium_stonecutting.json -6e3ffb0dce296c09e95d46d00029b3104e32e314 data/create/recipes/cut_veridium_from_veridium_stonecutting.json b81e0152ad3ca7b50815c7a61d436ce98cbb6092 data/create/recipes/cut_veridium_slab.json 7d7c80ac03ad8623f9a5d7f0ff0bb6f68985efa5 data/create/recipes/cut_veridium_slab_from_stone_types_veridium_stonecutting.json -5cd9ba34020421ea7ac27fb85046790c0bb92200 data/create/recipes/cut_veridium_slab_from_veridium_stonecutting.json 366bf29474eee2a9e5f36d6dc1243f847555b838 data/create/recipes/cut_veridium_slab_recycling.json 73aa1af9379b682ef29ecdc293b69c6231ac8c24 data/create/recipes/cut_veridium_stairs.json 9b0e33c891f7b8cdfbf5afb2842f46622d3a60f5 data/create/recipes/cut_veridium_stairs_from_stone_types_veridium_stonecutting.json -ae983b31b3302add7f3af689ca4ccbe89bcefae1 data/create/recipes/cut_veridium_stairs_from_veridium_stonecutting.json 51c00200777ac464a4c7770b632adeb6f0d50c66 data/create/recipes/cut_veridium_wall.json 17bb07daada50992c21df4bb32a5bf4a548aeca7 data/create/recipes/cut_veridium_wall_from_stone_types_veridium_stonecutting.json -15cc8019a19e2946c410ed45ab069587870fa561 data/create/recipes/cut_veridium_wall_from_veridium_stonecutting.json fc58a85ea670d20e82f5f63abaf4f8510aefe7f6 data/create/recipes/dark_oak_window.json 122271e750ca1cc982ec437a1e8ad190232707f8 data/create/recipes/dark_oak_window_pane.json -c2853dcdcc3fce4d7810f4568b4af9bf8c8cc9ce data/create/recipes/deepslate_pillar_from_deepslate_stonecutting.json +7d9034d09815513520d7ec6213d98bbc4c0f3a04 data/create/recipes/deepslate_from_stone_types_deepslate_stonecutting.json 0fc27886b3806a1be2eb3206427f6b06c78dd383 data/create/recipes/deepslate_pillar_from_stone_types_deepslate_stonecutting.json -7cbd2d360c5fc88cebf31ae4f25ad0dc1e5b851e data/create/recipes/diorite_pillar_from_diorite_stonecutting.json +972681c4ca6a31eb017d51c2d951b99b3518cb73 data/create/recipes/diorite_from_stone_types_diorite_stonecutting.json c57911a258f3371c717d2a497c57b9b57639a91b data/create/recipes/diorite_pillar_from_stone_types_diorite_stonecutting.json -e8a6d92296afa51d5c091281660772301e7b1898 data/create/recipes/dripstone_pillar_from_dripstone_block_stonecutting.json +da0a33cc14beb68107b67e6cdd3bb775f761a533 data/create/recipes/dripstone_block_from_stone_types_dripstone_stonecutting.json 48e26ac18bc3d0e965e66b68a91186a0d73dc3b3 data/create/recipes/dripstone_pillar_from_stone_types_dripstone_stonecutting.json 5e90207dff47eefbdeacb1a6fea685c98d359a97 data/create/recipes/exposed_copper_shingle_slab.json c4da022fcd01aa4bc094e2032d1d55a36fd66d9a data/create/recipes/exposed_copper_shingle_slab_from_exposed_copper_shingles_stonecutting.json @@ -4067,45 +3876,34 @@ a30636eeee38297826cb667c89653c5b937135a1 data/create/recipes/exposed_copper_tile ed6a7c88aaeba36b77315b6c35c898ea70eb6852 data/create/recipes/exposed_copper_tile_stairs_from_exposed_copper_tiles_stonecutting.json 33eb062b453631b8341111bffc4b0b14ea74061e data/create/recipes/framed_glass_from_glass_colorless_stonecutting.json c457cfdac58eec0022e71c793990822e22262771 data/create/recipes/framed_glass_pane.json -96b0a69470495dbff4509d640883992d47bc9f7a data/create/recipes/granite_pillar_from_granite_stonecutting.json +c1ac5bad113e067bf5cfa8d730dcc835420aecfb data/create/recipes/granite_from_stone_types_granite_stonecutting.json 1a84a0816303c0cab0cc3c894aaea74d797ae3d3 data/create/recipes/granite_pillar_from_stone_types_granite_stonecutting.json 8d6448c67261138b6331273024b757a9a58b41c4 data/create/recipes/horizontal_framed_glass_from_glass_colorless_stonecutting.json 67087cf802b88de9bd113e730cc82bb41b7f0657 data/create/recipes/horizontal_framed_glass_pane.json +61f759fec228090a60371add88cc90be3a84a735 data/create/recipes/industrial_iron_block_from_ingots_iron_stonecutting.json d86134def91ecca467535ab8c4c6b440e9e203d3 data/create/recipes/jungle_window.json 5d4f531de858264d335d993c8d2210fa0ede76d2 data/create/recipes/jungle_window_pane.json -64adc0f09a3ae56c3f632b2348bb004a05c61f97 data/create/recipes/layered_andesite_from_andesite_stonecutting.json 66da7fc9adbe0119bc41bfad0f6422fb93dcf3b6 data/create/recipes/layered_andesite_from_stone_types_andesite_stonecutting.json -ba92a12179f3f883cc84bc8561949b3de3af8eb0 data/create/recipes/layered_asurine_from_asurine_stonecutting.json 7e665da668493db4528f161811ac25d156490701 data/create/recipes/layered_asurine_from_stone_types_asurine_stonecutting.json -78e4552a5d11356a7b37bff19bbb633a16434e3e data/create/recipes/layered_calcite_from_calcite_stonecutting.json 4d4d3f1881840fc9998d82f5f761940b3c141328 data/create/recipes/layered_calcite_from_stone_types_calcite_stonecutting.json -379858685cdbd8ad9e86286e37ede4684612f4a9 data/create/recipes/layered_crimsite_from_crimsite_stonecutting.json 57380b06939d1403aa735cd6d2e275013c1b2e4c data/create/recipes/layered_crimsite_from_stone_types_crimsite_stonecutting.json -78768a15e4ceb040dc36b7eb4f2bfd0ff2b18ee0 data/create/recipes/layered_deepslate_from_deepslate_stonecutting.json 72270564767247dad20ac22c4c2a5769e4388dc1 data/create/recipes/layered_deepslate_from_stone_types_deepslate_stonecutting.json -13945b89802ab2e22f725d41e494ac8837869345 data/create/recipes/layered_diorite_from_diorite_stonecutting.json 60456938d8741e5974eba1827e8dd2cbbeae4524 data/create/recipes/layered_diorite_from_stone_types_diorite_stonecutting.json -e8df7caafaab9cabecfb74b0f72baad1934b6ceb data/create/recipes/layered_dripstone_from_dripstone_block_stonecutting.json de08436139f2bf8910efaddeb481c4800bf52b58 data/create/recipes/layered_dripstone_from_stone_types_dripstone_stonecutting.json -339776e288b3837258c4646b9a329103745d9473 data/create/recipes/layered_granite_from_granite_stonecutting.json b29698f893ec3462cd0a9da204abbc07fa547894 data/create/recipes/layered_granite_from_stone_types_granite_stonecutting.json -cae27b52731d550c1b9201b2f2988327cd9b6788 data/create/recipes/layered_limestone_from_limestone_stonecutting.json f92843acc321c657c7e8a7d81693e6f4efdc89e8 data/create/recipes/layered_limestone_from_stone_types_limestone_stonecutting.json -427f7e051e48c29fa3e00fcf4adc480cfaeb6c78 data/create/recipes/layered_ochrum_from_ochrum_stonecutting.json dcab6440b947b36f60b8ac45a203302608f8b236 data/create/recipes/layered_ochrum_from_stone_types_ochrum_stonecutting.json -272ba47e33d9f28bb9cb4e3498b5cdf8951fa78f data/create/recipes/layered_scorchia_from_scorchia_stonecutting.json aa336f458af977f8a1e82ba0a449f244f487baa2 data/create/recipes/layered_scorchia_from_stone_types_scorchia_stonecutting.json -5df6873f7c1b280f9300539d1d9e0daf11450131 data/create/recipes/layered_scoria_from_scoria_stonecutting.json c7f5c1245aba2d98590756c6760005a3c622966c data/create/recipes/layered_scoria_from_stone_types_scoria_stonecutting.json efcbb602a5274a037af323bf5ef40756cbb8683c data/create/recipes/layered_tuff_from_stone_types_tuff_stonecutting.json -09b299a0a7d428d91e6aafc7013fe3f528e091b1 data/create/recipes/layered_tuff_from_tuff_stonecutting.json 6861c7c7d75d669a948a3dc617137759fb387d49 data/create/recipes/layered_veridium_from_stone_types_veridium_stonecutting.json -66c5ccfa1c3394f15f1f914ab89ab548adbd14e1 data/create/recipes/layered_veridium_from_veridium_stonecutting.json -b929d6dad71cff79b42d7e9b72072b49d45cb4d0 data/create/recipes/limestone_pillar_from_limestone_stonecutting.json +9882a276da633a82f42cbd809c0a104d2137f7ca data/create/recipes/limestone_from_stone_types_limestone_stonecutting.json 923e6a5bec0018849c1bf9e5714195ab7f839f44 data/create/recipes/limestone_pillar_from_stone_types_limestone_stonecutting.json +7b63fee3fd5fc68844652ff988c9a318f5333f19 data/create/recipes/mangrove_window.json +15eb35a0a8cb80d8e0f006786bd63ff23b8b7609 data/create/recipes/mangrove_window_pane.json efcdb87d347bc5cf234b13e82c9cd1bfc9b6b8c8 data/create/recipes/oak_window.json 3ddc4c3ee17728be60bcc38f6871d15420a02a4a data/create/recipes/oak_window_pane.json -8db8765323edfd6a807e78a32e41bd50da722f0c data/create/recipes/ochrum_pillar_from_ochrum_stonecutting.json +9e1eaa83597afe00485940018be874885f02b1f7 data/create/recipes/ochrum_from_stone_types_ochrum_stonecutting.json 308dbf17a3a418849d9db74e7f88af442f50025a data/create/recipes/ochrum_pillar_from_stone_types_ochrum_stonecutting.json 9c1c761de19b89251fc5553366b85a8924b64909 data/create/recipes/ornate_iron_window.json ba054788c502a1ef1b63bdda26b245c43a911632 data/create/recipes/ornate_iron_window_pane.json @@ -4117,357 +3915,245 @@ f498d544e3fe1ee95c1b2aa8bbe0b46d63ef2e47 data/create/recipes/oxidized_copper_shi 9875c927cc1807066bf58f44a08688127411654d data/create/recipes/oxidized_copper_tile_slab_from_oxidized_copper_tiles_stonecutting.json 4b62c64c4dd26d64b7e7ba835bab8a9917bbee69 data/create/recipes/oxidized_copper_tile_stairs.json cda1bd8a1a97938a7b11666eeaec5e293f52bc85 data/create/recipes/oxidized_copper_tile_stairs_from_oxidized_copper_tiles_stonecutting.json -8d608887a95be067f83d7cebfe6ca94edce4802c data/create/recipes/polished_cut_andesite_from_andesite_stonecutting.json 892f4a5355cbd29c89bc5a5d422c277385e6b145 data/create/recipes/polished_cut_andesite_from_stone_types_andesite_stonecutting.json bda2a6f6026e724cb9ad5625b7fea94e2b9ba668 data/create/recipes/polished_cut_andesite_slab.json -bae14f83750ce9bd97b4b86a531cb9e2c53e0b14 data/create/recipes/polished_cut_andesite_slab_from_andesite_stonecutting.json 3f537f7b1feedcd199024661f492ee02d98565d3 data/create/recipes/polished_cut_andesite_slab_from_stone_types_andesite_stonecutting.json d262cc607729ec96b9b0e552ad9c7284f2dafc19 data/create/recipes/polished_cut_andesite_slab_recycling.json bd03c151a56c459d33fd54c7905a5bdac6901cd6 data/create/recipes/polished_cut_andesite_stairs.json -4dcf620868eaa801fcf1146c269cc053b3470bd1 data/create/recipes/polished_cut_andesite_stairs_from_andesite_stonecutting.json 0b33435c1f9a84c3301a6944389b39c1740d3483 data/create/recipes/polished_cut_andesite_stairs_from_stone_types_andesite_stonecutting.json 9c9c82b0cc8222e7cf92bc5fcd64d367674b3ec0 data/create/recipes/polished_cut_andesite_wall.json -6684d4fc2a8b540888943f1d86c9256ba6ca0490 data/create/recipes/polished_cut_andesite_wall_from_andesite_stonecutting.json c10f8b3e761aad30077da2dae67b76a0ecc6642e data/create/recipes/polished_cut_andesite_wall_from_stone_types_andesite_stonecutting.json -6ef234f6e3b0ab89e5e04be33a9789d693621b54 data/create/recipes/polished_cut_asurine_from_asurine_stonecutting.json 23f0bd64850ac80495b71dce10b3a46ec54d63af data/create/recipes/polished_cut_asurine_from_stone_types_asurine_stonecutting.json d6a83eb98603b6341d130ee8c4a8ea4e9c630b42 data/create/recipes/polished_cut_asurine_slab.json -8b69996a13a9931adf2dcb5c3467a0136792e64d data/create/recipes/polished_cut_asurine_slab_from_asurine_stonecutting.json 15a34f66b742c6e7a777077447eb42592619f877 data/create/recipes/polished_cut_asurine_slab_from_stone_types_asurine_stonecutting.json cb8af35a5f90908217725b0723acbc5e7accc028 data/create/recipes/polished_cut_asurine_slab_recycling.json 977755317ec9567e280db2a619f5631ad425eeec data/create/recipes/polished_cut_asurine_stairs.json -56c9de7b8f1f34418f966efc7d2225848edd92a6 data/create/recipes/polished_cut_asurine_stairs_from_asurine_stonecutting.json c3bab7748fa69d3d9f65231d0bbbbab14a931669 data/create/recipes/polished_cut_asurine_stairs_from_stone_types_asurine_stonecutting.json 6ff3ae9c249e82ff874e1a8208f28ea79eaa2052 data/create/recipes/polished_cut_asurine_wall.json -f6cefce100a37d7736bc34e473a970453dfb57e7 data/create/recipes/polished_cut_asurine_wall_from_asurine_stonecutting.json 2f4c9bca714918532fb553e1292e527f36797b37 data/create/recipes/polished_cut_asurine_wall_from_stone_types_asurine_stonecutting.json -d7d41b9f760d74c7a4e3cc4ddb7f2717eb773bfd data/create/recipes/polished_cut_calcite_from_calcite_stonecutting.json aff85dd6940bc48c8912aeed6f5ab695d2cb5aad data/create/recipes/polished_cut_calcite_from_stone_types_calcite_stonecutting.json 853186b0dda3e3fbe78cbc3785b17edbdffb1f20 data/create/recipes/polished_cut_calcite_slab.json -35211c520ec12743f7ba4b5be0c4cfb6b2c20491 data/create/recipes/polished_cut_calcite_slab_from_calcite_stonecutting.json de13feff1e46ab98ff014cf1ab0206ce4a9ee6d5 data/create/recipes/polished_cut_calcite_slab_from_stone_types_calcite_stonecutting.json c6b132f3f597943c8a3b6447c85e0c695583d9d8 data/create/recipes/polished_cut_calcite_slab_recycling.json 78e255a139aac5b9038f6186298eac2b0535cc23 data/create/recipes/polished_cut_calcite_stairs.json -2aeeb43cbdb4ba04256406dd9799758cb0d4c822 data/create/recipes/polished_cut_calcite_stairs_from_calcite_stonecutting.json b2e00eefb60bdd0516e799861172232e7188704a data/create/recipes/polished_cut_calcite_stairs_from_stone_types_calcite_stonecutting.json 1bbba2f28b846ec78e97d7fa8a1ca24f8b6cc722 data/create/recipes/polished_cut_calcite_wall.json -c675933a02ddd5aa8bbb3a2387d224255b9dd653 data/create/recipes/polished_cut_calcite_wall_from_calcite_stonecutting.json 53f1a4191f28d24dc89f0865f1fcc86c24a3bec1 data/create/recipes/polished_cut_calcite_wall_from_stone_types_calcite_stonecutting.json -160689d60c25ee44813083c8f226f56f191bf49d data/create/recipes/polished_cut_crimsite_from_crimsite_stonecutting.json 46f1a15740c26b3e9958c754ef7107e74776dce3 data/create/recipes/polished_cut_crimsite_from_stone_types_crimsite_stonecutting.json f11d3f44c6f891711e5821fa2ffc71f98701c9c6 data/create/recipes/polished_cut_crimsite_slab.json -b2c1ab2195c72d69fb8d2b4e9222801fe638c50d data/create/recipes/polished_cut_crimsite_slab_from_crimsite_stonecutting.json 801325afb9cbe6f94f98563add4dfc19fc06d0fc data/create/recipes/polished_cut_crimsite_slab_from_stone_types_crimsite_stonecutting.json a223b085fb9561f8e7bab8af06cc44948fd1d3a6 data/create/recipes/polished_cut_crimsite_slab_recycling.json ce953ba69e5adbcc98ec7f8e26cc372ca70a064a data/create/recipes/polished_cut_crimsite_stairs.json -423cd7d3a3f7ef8564f5a01e33723d95cfcdd720 data/create/recipes/polished_cut_crimsite_stairs_from_crimsite_stonecutting.json 8b584a5bcad5c4eba4721eae61d118bb6707d3df data/create/recipes/polished_cut_crimsite_stairs_from_stone_types_crimsite_stonecutting.json d2470986c0a54b428ae358680bca07ce1c77b70f data/create/recipes/polished_cut_crimsite_wall.json -eb5d5e8a7b44a0727d3f8b3dd1fc611b331d0c23 data/create/recipes/polished_cut_crimsite_wall_from_crimsite_stonecutting.json c8b0b21d4377a40dcb259952d564b566fda64a8f data/create/recipes/polished_cut_crimsite_wall_from_stone_types_crimsite_stonecutting.json -43e8f8965bd27eb0a0820d4670a3aefea3d055ee data/create/recipes/polished_cut_deepslate_from_deepslate_stonecutting.json a68bbadd60b37fa9037c554f7335850a5ee04fd3 data/create/recipes/polished_cut_deepslate_from_stone_types_deepslate_stonecutting.json 7dbf86fe34e818f5e33b5bbded3f5385a837b59e data/create/recipes/polished_cut_deepslate_slab.json -153353ff3d67f056336ded0c97a87f3f2415702a data/create/recipes/polished_cut_deepslate_slab_from_deepslate_stonecutting.json 9d899540998649d627ef9b0446134f8d94a567a6 data/create/recipes/polished_cut_deepslate_slab_from_stone_types_deepslate_stonecutting.json 37e3023bb60970ac1e11371441262a706abde805 data/create/recipes/polished_cut_deepslate_slab_recycling.json 7ae3d7c3fd26dd460ba1b634ac1cb48e717f0fc3 data/create/recipes/polished_cut_deepslate_stairs.json -2f5f1bd3e05cc976673b0ee18b1b11071881751b data/create/recipes/polished_cut_deepslate_stairs_from_deepslate_stonecutting.json 95ef22cf96e167e8cba9bc72e23bb03a3144f497 data/create/recipes/polished_cut_deepslate_stairs_from_stone_types_deepslate_stonecutting.json 186c6c06376c0192275e51a32b03be824a8bd1fd data/create/recipes/polished_cut_deepslate_wall.json -73efa954944696c2c945d7f28eb37360c00d0319 data/create/recipes/polished_cut_deepslate_wall_from_deepslate_stonecutting.json d4461e8aa51227196b34fdced1ab8947e29a6027 data/create/recipes/polished_cut_deepslate_wall_from_stone_types_deepslate_stonecutting.json -e9e39ec0b8780b98570bc0b7f28fe43987b50b2a data/create/recipes/polished_cut_diorite_from_diorite_stonecutting.json 3869640b431a841e4363f8fbb63e9468224e2bf8 data/create/recipes/polished_cut_diorite_from_stone_types_diorite_stonecutting.json ef9c689316761a95b44f19c73aaf0a1ed190165d data/create/recipes/polished_cut_diorite_slab.json -00d3671b44775e7e33983746de756acb1ed71086 data/create/recipes/polished_cut_diorite_slab_from_diorite_stonecutting.json 4a69608cbcd70e33602c44d37a5db7811fe5b04c data/create/recipes/polished_cut_diorite_slab_from_stone_types_diorite_stonecutting.json 9d7f5d88e34db4add798960911ed93d855e49182 data/create/recipes/polished_cut_diorite_slab_recycling.json 96d7fd3901872a4553e23c791620aa26940aa022 data/create/recipes/polished_cut_diorite_stairs.json -a70dc0deb0262d822625d165dd797c2067416bb8 data/create/recipes/polished_cut_diorite_stairs_from_diorite_stonecutting.json 6ae315321aea719479cdf081f1ab649f5833bdfa data/create/recipes/polished_cut_diorite_stairs_from_stone_types_diorite_stonecutting.json 5bffd4936fbe6e73e4c9ee406cd80fc53a72d36a data/create/recipes/polished_cut_diorite_wall.json -3b5d8c7dad65206a3fe828acd5a157a652400d79 data/create/recipes/polished_cut_diorite_wall_from_diorite_stonecutting.json 0594aec0451471a90eee3f81b2a642160f829283 data/create/recipes/polished_cut_diorite_wall_from_stone_types_diorite_stonecutting.json -dbbbc4c216659d94f88c9bb147904a96299c11a4 data/create/recipes/polished_cut_dripstone_from_dripstone_block_stonecutting.json c0542972572ee3645374c4495c536b4962071906 data/create/recipes/polished_cut_dripstone_from_stone_types_dripstone_stonecutting.json 57bea3d2b5733c04d1d258e9085d47424379ff9e data/create/recipes/polished_cut_dripstone_slab.json -38783794bb00dd7f8fb8cde35d5674aa273184e1 data/create/recipes/polished_cut_dripstone_slab_from_dripstone_block_stonecutting.json b3aba4c82062407557d4724d8eae5192f093b132 data/create/recipes/polished_cut_dripstone_slab_from_stone_types_dripstone_stonecutting.json 64d352a230c264cffc55b990100e78bcd32781fc data/create/recipes/polished_cut_dripstone_slab_recycling.json 44d62051e8bc0d25cbe936a22debcd1a30605023 data/create/recipes/polished_cut_dripstone_stairs.json -0fb220de87e8484cf7162988116e254c4d3c4880 data/create/recipes/polished_cut_dripstone_stairs_from_dripstone_block_stonecutting.json 039850e397a69f65f406269b4cb131fbfee83978 data/create/recipes/polished_cut_dripstone_stairs_from_stone_types_dripstone_stonecutting.json 0d8b1d8ba816a5c151b8801c14aa2112ecbdd215 data/create/recipes/polished_cut_dripstone_wall.json -69a79a049754b9f84d91042c1b7c4c81e55abfd3 data/create/recipes/polished_cut_dripstone_wall_from_dripstone_block_stonecutting.json 94847065f17859cabaa1ada493df76dd0e1ee88b data/create/recipes/polished_cut_dripstone_wall_from_stone_types_dripstone_stonecutting.json -f0b8079459199b649890dd6d0c1e1f41912b0d60 data/create/recipes/polished_cut_granite_from_granite_stonecutting.json c9858f9023307c5b8a2659f988ec010e1fb579b3 data/create/recipes/polished_cut_granite_from_stone_types_granite_stonecutting.json 7cbe357dccc69319b459da9167319c6ebbd8c4ab data/create/recipes/polished_cut_granite_slab.json -d529b24ee4aa054070f47c540bd8714b8d1b69cb data/create/recipes/polished_cut_granite_slab_from_granite_stonecutting.json a4ddbd03e796d488e40c397f12ba923c4877b9dd data/create/recipes/polished_cut_granite_slab_from_stone_types_granite_stonecutting.json bb7810e26763b23ebac7327bab5b85f781473c9a data/create/recipes/polished_cut_granite_slab_recycling.json 0a567312eb9f05960620c8e56bb4f179aadc02ce data/create/recipes/polished_cut_granite_stairs.json -f6e956175134e4ca727679254a57c8d254377815 data/create/recipes/polished_cut_granite_stairs_from_granite_stonecutting.json 96046c1afebd55964f2c595021d06f91eda3c624 data/create/recipes/polished_cut_granite_stairs_from_stone_types_granite_stonecutting.json 70d00d6d0e49427070d01972c8561e9ec0f3dd0a data/create/recipes/polished_cut_granite_wall.json -f5019720a09dec8ce98f8083164d53baae9e5956 data/create/recipes/polished_cut_granite_wall_from_granite_stonecutting.json 2933927280ceeed29442665f47b5280baf2db2cf data/create/recipes/polished_cut_granite_wall_from_stone_types_granite_stonecutting.json -a56c59b3d453f6e3ab1e35fe9641c57bc37e66eb data/create/recipes/polished_cut_limestone_from_limestone_stonecutting.json 9d08c4c106ec36115b256b0319eeec7c0042b875 data/create/recipes/polished_cut_limestone_from_stone_types_limestone_stonecutting.json f67bc4e0260093f3eedab1ea9baef2dd1335b221 data/create/recipes/polished_cut_limestone_slab.json -5f28c829ef51866d6b229f49abd93d8323e9c960 data/create/recipes/polished_cut_limestone_slab_from_limestone_stonecutting.json bfeded973be92ef8741401c01342564b7620caec data/create/recipes/polished_cut_limestone_slab_from_stone_types_limestone_stonecutting.json 54c81c7444a93491820ff7b71d95dae121be6ca1 data/create/recipes/polished_cut_limestone_slab_recycling.json 5814eb41bab114ce0d4e75cc279fd3d5ad815fc5 data/create/recipes/polished_cut_limestone_stairs.json -9a77b15b623ff6ad8bbc7c4183ab59f13c1ca83a data/create/recipes/polished_cut_limestone_stairs_from_limestone_stonecutting.json dd9383d5b0b6b4fd38bf3025dc443ead77dfd7a0 data/create/recipes/polished_cut_limestone_stairs_from_stone_types_limestone_stonecutting.json 0e67b3e105be37957802e6c083dd36180ab40e74 data/create/recipes/polished_cut_limestone_wall.json -e9e4e3b467e5e2aaae1084f40f17247d19e573c9 data/create/recipes/polished_cut_limestone_wall_from_limestone_stonecutting.json 8676eab4596f7abb4b45b1f17d2b0f317fc4a2a3 data/create/recipes/polished_cut_limestone_wall_from_stone_types_limestone_stonecutting.json -65f0331b1436c0be896a8ed2fcbadd90ce26b6ae data/create/recipes/polished_cut_ochrum_from_ochrum_stonecutting.json da78ba83f0578905cbdbb7f7aed8438f5ba0b6cd data/create/recipes/polished_cut_ochrum_from_stone_types_ochrum_stonecutting.json 8120b187e34f725430860bb75b488a477f52c943 data/create/recipes/polished_cut_ochrum_slab.json -0c347d1a719d4ce654dec73ecb4ca437ed56c432 data/create/recipes/polished_cut_ochrum_slab_from_ochrum_stonecutting.json ba8497aef79a97aa7dcb795f132bc2b1bb40026a data/create/recipes/polished_cut_ochrum_slab_from_stone_types_ochrum_stonecutting.json 20761c91ab105a3a9bee6b8986e9ebe480a7dc29 data/create/recipes/polished_cut_ochrum_slab_recycling.json 0335e447d129392569977a3c24274c2849375ad6 data/create/recipes/polished_cut_ochrum_stairs.json -7dd6eabd4db7400d3048e5fe61370fc4abc4c724 data/create/recipes/polished_cut_ochrum_stairs_from_ochrum_stonecutting.json f0b09407460d27db3367d46e734933d5436711c0 data/create/recipes/polished_cut_ochrum_stairs_from_stone_types_ochrum_stonecutting.json 50aa0bf9c0a782d3cd2431f3e1099e13e8eb59e3 data/create/recipes/polished_cut_ochrum_wall.json -91d9d9561d6c4e91a1da0934442373152e40ad47 data/create/recipes/polished_cut_ochrum_wall_from_ochrum_stonecutting.json 35e975040560b70005d8bfe015782cd4bbe39b27 data/create/recipes/polished_cut_ochrum_wall_from_stone_types_ochrum_stonecutting.json -7112f1216b4c56b39859a6d1ab8b88d142943b14 data/create/recipes/polished_cut_scorchia_from_scorchia_stonecutting.json cf1cd1709341d2f2c280e79a4ca8aa9751df3407 data/create/recipes/polished_cut_scorchia_from_stone_types_scorchia_stonecutting.json 720e4ed86f897df9e09ed80cc65a87b2446d73f6 data/create/recipes/polished_cut_scorchia_slab.json -04d9c95f7b3086fcd34bdd934f5a6b002c6f1ec3 data/create/recipes/polished_cut_scorchia_slab_from_scorchia_stonecutting.json 6f08dab03a2bad2603dce6c248fe13f3608e7424 data/create/recipes/polished_cut_scorchia_slab_from_stone_types_scorchia_stonecutting.json 5d8f4e2317d94c85b8ab433089b914040bffa274 data/create/recipes/polished_cut_scorchia_slab_recycling.json 2b4c82ce172880cf58f2f11ba514b6e876783355 data/create/recipes/polished_cut_scorchia_stairs.json -25b1e29666aff34cd4b06372e36d8ca5d05a057c data/create/recipes/polished_cut_scorchia_stairs_from_scorchia_stonecutting.json 78660fe29058bb61073cdfb6be0003700b9be6e7 data/create/recipes/polished_cut_scorchia_stairs_from_stone_types_scorchia_stonecutting.json d24f332c8b0c6eb2e0dcb1fbaba9261d78c81398 data/create/recipes/polished_cut_scorchia_wall.json -3cb0fe20e0504044af056863616c64351e6e6701 data/create/recipes/polished_cut_scorchia_wall_from_scorchia_stonecutting.json 61d2dcd9716349686175ad70e6054e5e2e7fdc80 data/create/recipes/polished_cut_scorchia_wall_from_stone_types_scorchia_stonecutting.json -ae0b6cc2b250c5ca9e60cfdb7317d28187c13403 data/create/recipes/polished_cut_scoria_from_scoria_stonecutting.json 43660c3c000538f1d4a242ee08033073f564cba9 data/create/recipes/polished_cut_scoria_from_stone_types_scoria_stonecutting.json 972e53d3477576fc0f6be811d33bccc944e94c2c data/create/recipes/polished_cut_scoria_slab.json -c036f5f7f646671da6ec13585e008a7f8f7e83df data/create/recipes/polished_cut_scoria_slab_from_scoria_stonecutting.json 2f56b9f79d59609dbe1f340cad7a6f08d82caf91 data/create/recipes/polished_cut_scoria_slab_from_stone_types_scoria_stonecutting.json 47e74dbe59bbed8af7ef19086ab9a431e969f84d data/create/recipes/polished_cut_scoria_slab_recycling.json 5c80cd576f439135b156dbc73a3687c8515f5ce0 data/create/recipes/polished_cut_scoria_stairs.json -1ae8784b08146deb9f51282a47859aecc425d97e data/create/recipes/polished_cut_scoria_stairs_from_scoria_stonecutting.json a7e9682ddff0aeec17b9d65609e057e80d9348e2 data/create/recipes/polished_cut_scoria_stairs_from_stone_types_scoria_stonecutting.json cd9a2ac79429d14b4ae1bc152ee2fe6a3f97a024 data/create/recipes/polished_cut_scoria_wall.json -fbc8fa39b35259fa1987c499c5a9b87a2a69e94b data/create/recipes/polished_cut_scoria_wall_from_scoria_stonecutting.json 107cb077a12d24d5d2368663f84da083ea0438f1 data/create/recipes/polished_cut_scoria_wall_from_stone_types_scoria_stonecutting.json 14deacf26b83b06de47d5076ea8ba3c24561d966 data/create/recipes/polished_cut_tuff_from_stone_types_tuff_stonecutting.json -d971abfe2c86fe8d4bc0bf2e57f2bed0d2a72df9 data/create/recipes/polished_cut_tuff_from_tuff_stonecutting.json 184eae94b445973ffaf868b74ac7765fcfece2c5 data/create/recipes/polished_cut_tuff_slab.json 0bea69fa87263b4c7b3d3886014fc21ae448227a data/create/recipes/polished_cut_tuff_slab_from_stone_types_tuff_stonecutting.json -a0f24fdeed8add8200e74ecd4868d819b7ed1554 data/create/recipes/polished_cut_tuff_slab_from_tuff_stonecutting.json 207f0ba3ce0a85a47deccb6b82523cee92b74970 data/create/recipes/polished_cut_tuff_slab_recycling.json 50b84abaecc3047746e2bf13cb1d3ff8a8bbb178 data/create/recipes/polished_cut_tuff_stairs.json 3710e827fee86de70d405cd9662392940fe19f48 data/create/recipes/polished_cut_tuff_stairs_from_stone_types_tuff_stonecutting.json -980504b98e72f70ed483a6a8165bf0a7f69693ce data/create/recipes/polished_cut_tuff_stairs_from_tuff_stonecutting.json 87c0417ba37a382ec545ebed386cc2d32d214d99 data/create/recipes/polished_cut_tuff_wall.json 434abdef7effbffb972fa2307d002b4fd9d268be data/create/recipes/polished_cut_tuff_wall_from_stone_types_tuff_stonecutting.json -9f97eb42193d2b53d80f7e5fd5138c4528964679 data/create/recipes/polished_cut_tuff_wall_from_tuff_stonecutting.json 1a7ffa6b0d600e1fd17ad1e191516154bc483143 data/create/recipes/polished_cut_veridium_from_stone_types_veridium_stonecutting.json -b0c83c90ff81cdf64af0c8d2dc30219605132d86 data/create/recipes/polished_cut_veridium_from_veridium_stonecutting.json f3a6bc7d45691b354d199c321777e224bb14bd2c data/create/recipes/polished_cut_veridium_slab.json 6e9c06200021725680567da873cb698e59be9b81 data/create/recipes/polished_cut_veridium_slab_from_stone_types_veridium_stonecutting.json -394e039d0a4750d739a9982e68b4ba2d5f34d3fc data/create/recipes/polished_cut_veridium_slab_from_veridium_stonecutting.json 35c35e0e05b21645184a2606b12035119781c0c8 data/create/recipes/polished_cut_veridium_slab_recycling.json ade198a00c72e6e49800080234b29869875a4c98 data/create/recipes/polished_cut_veridium_stairs.json f5bbca51e5f51d8d9bbcf96232c3cbae5c4b1b9a data/create/recipes/polished_cut_veridium_stairs_from_stone_types_veridium_stonecutting.json -e09041419224b68714e7e95c9ff6c48b8f9e272d data/create/recipes/polished_cut_veridium_stairs_from_veridium_stonecutting.json 4fa16dabf9b69f3be00a681af606ee5d51e97f78 data/create/recipes/polished_cut_veridium_wall.json 08439ab71413688d6f07b41df54eae6c87255ec6 data/create/recipes/polished_cut_veridium_wall_from_stone_types_veridium_stonecutting.json -4129317f4829751bdb5fd8a4bcb2e3fae5b89836 data/create/recipes/polished_cut_veridium_wall_from_veridium_stonecutting.json a157a43e7788d285b8d72eade5955369c9b9a1de data/create/recipes/rose_quartz_block_from_rose_quartz_stonecutting.json 24b3df9eaf6322590029fccc96493ec23aeec931 data/create/recipes/rose_quartz_tiles_from_polished_rose_quartz_stonecutting.json -17e26ceaaeeaf9ff00348e807b8e78813fc00392 data/create/recipes/scorchia_pillar_from_scorchia_stonecutting.json +07cf02a90854223634b69954c1ed086d40994ff7 data/create/recipes/scorchia_from_stone_types_scorchia_stonecutting.json 1268cc2bdd088d26b84fb4e481db27af61f94bd1 data/create/recipes/scorchia_pillar_from_stone_types_scorchia_stonecutting.json -988dca80f01a8ca61bbcf8c67e5434d3d222eb19 data/create/recipes/scoria_pillar_from_scoria_stonecutting.json +2e8f4cdb3498547a5e6fe658bb33d4be5ce8f54b data/create/recipes/scoria_from_stone_types_scoria_stonecutting.json 770d3453c75f77b16db661f6e636892d3117690b data/create/recipes/scoria_pillar_from_stone_types_scoria_stonecutting.json -d7d07a2bb5a27398e1beb6d8fa994f171ce9f74c data/create/recipes/small_andesite_bricks_from_andesite_stonecutting.json 75dc56fcdcd6a10288f2d607bf6dcbbe10b35a64 data/create/recipes/small_andesite_bricks_from_stone_types_andesite_stonecutting.json 4b27705254a54be9b337926d43a82f1aa2e382ad data/create/recipes/small_andesite_brick_slab.json -b0b0a2bf7446990ea221ac6607151b2e468d1e85 data/create/recipes/small_andesite_brick_slab_from_andesite_stonecutting.json 311727e5c08ddbe0aa26275be74e9b83201ac8ab data/create/recipes/small_andesite_brick_slab_from_stone_types_andesite_stonecutting.json 2767e239c9d704b6bb5325b4f40e0aa0acdcdce1 data/create/recipes/small_andesite_brick_slab_recycling.json b1f19fc3de070d576a9ec9d5c12dd49c1e3a3c77 data/create/recipes/small_andesite_brick_stairs.json -acf1e392955749e53062fbb882e6500389ca783c data/create/recipes/small_andesite_brick_stairs_from_andesite_stonecutting.json 9e82896e00c1e14e514fac818e11e5b9ef5b10d7 data/create/recipes/small_andesite_brick_stairs_from_stone_types_andesite_stonecutting.json ddc44137d7482b5b42de95f53b3b3be6ddf9ccd2 data/create/recipes/small_andesite_brick_wall.json -7ebc9fea0900069cf7c225aeec6f532e4f0e01b5 data/create/recipes/small_andesite_brick_wall_from_andesite_stonecutting.json 1172ca76affd948c50b207124ee03c4f480f4ee8 data/create/recipes/small_andesite_brick_wall_from_stone_types_andesite_stonecutting.json -04792833e80ffd0318e473be0cb658ccb93589f0 data/create/recipes/small_asurine_bricks_from_asurine_stonecutting.json e3b69122b2cfe64b043384235eeb6d04f346e58b data/create/recipes/small_asurine_bricks_from_stone_types_asurine_stonecutting.json 75180070a6e1e01f5e8ec90453ce7c83cb64e38b data/create/recipes/small_asurine_brick_slab.json -e205a2b3fbb95fe76122f3438ac8b0accbe0ce27 data/create/recipes/small_asurine_brick_slab_from_asurine_stonecutting.json f4cc3330837a647c098ccb24fbbbf583c3f960fc data/create/recipes/small_asurine_brick_slab_from_stone_types_asurine_stonecutting.json 063b2f0ad7e93698999922040132eb2b23661a38 data/create/recipes/small_asurine_brick_slab_recycling.json ab08d1b1e3ee30e6f2e0e2f046933274dc31bc56 data/create/recipes/small_asurine_brick_stairs.json -6691f4b8b69633af59f73b075b543113a6f33a2e data/create/recipes/small_asurine_brick_stairs_from_asurine_stonecutting.json c7cb218b0d8a1e358d593fc1fef82fc074289552 data/create/recipes/small_asurine_brick_stairs_from_stone_types_asurine_stonecutting.json 7feec44acb8d7e2058015bd3bf76950768ea8181 data/create/recipes/small_asurine_brick_wall.json -cf5e5d494080285b063369b6ebb954b497316a68 data/create/recipes/small_asurine_brick_wall_from_asurine_stonecutting.json 4c0aa6203295a36a6d7ffe9d7bf0973277162689 data/create/recipes/small_asurine_brick_wall_from_stone_types_asurine_stonecutting.json -4ce8b01e8347eccd6cf06dd7e5366ba33aabe755 data/create/recipes/small_calcite_bricks_from_calcite_stonecutting.json 07125218f9025833afa189fa0090f4d6b4660db0 data/create/recipes/small_calcite_bricks_from_stone_types_calcite_stonecutting.json 6e37219b0dad4899c6e42dadb8a4778c38987207 data/create/recipes/small_calcite_brick_slab.json -19965bb00f12fb9ca742f8beb88f07dbc79a69f7 data/create/recipes/small_calcite_brick_slab_from_calcite_stonecutting.json d8ebf6f1eb2e2372fb20def956398089adec5d13 data/create/recipes/small_calcite_brick_slab_from_stone_types_calcite_stonecutting.json ab4cfc2b34989d41a434781a3150ecd530c4f15b data/create/recipes/small_calcite_brick_slab_recycling.json 12011134319a2be792997eb7d4a9385492ba894f data/create/recipes/small_calcite_brick_stairs.json -15c5501609611b529c186beba935d6de1f2889c9 data/create/recipes/small_calcite_brick_stairs_from_calcite_stonecutting.json 4e066bfc60ea142d54ce939d025b6679ac9634ad data/create/recipes/small_calcite_brick_stairs_from_stone_types_calcite_stonecutting.json 602d1de1e9c11112a8c55c88440b7c1c2b128c1d data/create/recipes/small_calcite_brick_wall.json -4bc260bf497f1be3cbccabe7aa03ea6d50bfd5a8 data/create/recipes/small_calcite_brick_wall_from_calcite_stonecutting.json 3ba736ae76249fa61692c13f7879af954f9bbd36 data/create/recipes/small_calcite_brick_wall_from_stone_types_calcite_stonecutting.json -1160e0f8301a93b4cce24c6681978e146d165df6 data/create/recipes/small_crimsite_bricks_from_crimsite_stonecutting.json a3309c81f84bf4fb78e9db2316fb758f9b2f8429 data/create/recipes/small_crimsite_bricks_from_stone_types_crimsite_stonecutting.json 96393065faabeec9060ec2811c3bc4541e7e414e data/create/recipes/small_crimsite_brick_slab.json -8a940cd8e641da477d407da9846e8fa58051bb7c data/create/recipes/small_crimsite_brick_slab_from_crimsite_stonecutting.json b993e081103c019b7b9b73b38ef8c408fb4500ac data/create/recipes/small_crimsite_brick_slab_from_stone_types_crimsite_stonecutting.json 7f6fa1fab65d910388f5f2ec4ee7d99cbda8df57 data/create/recipes/small_crimsite_brick_slab_recycling.json 8c2b1f17ec8fe898f89a01a7f153568c078deb5f data/create/recipes/small_crimsite_brick_stairs.json -1aaa6de353a1e578a76ca5fc0c228db95fa083cd data/create/recipes/small_crimsite_brick_stairs_from_crimsite_stonecutting.json 260da721849d1afd6f431d51538d1587ee3af8d5 data/create/recipes/small_crimsite_brick_stairs_from_stone_types_crimsite_stonecutting.json 58e8a5f150d6a9b25c486feceaf9327ff0143602 data/create/recipes/small_crimsite_brick_wall.json -dc45f0660bb0d93955e03e58ee2ebde089e23649 data/create/recipes/small_crimsite_brick_wall_from_crimsite_stonecutting.json 8b8280a8282fa8718620ee3d69182e241a7852c0 data/create/recipes/small_crimsite_brick_wall_from_stone_types_crimsite_stonecutting.json -433b789160268837fc790cd8525c33b7860b5f08 data/create/recipes/small_deepslate_bricks_from_deepslate_stonecutting.json e7a3cb889ce6b530cd40f19e23bad943374e61b5 data/create/recipes/small_deepslate_bricks_from_stone_types_deepslate_stonecutting.json 9a61cfa51025182870700b8b42276c63455ad790 data/create/recipes/small_deepslate_brick_slab.json -a26f1343be50f143fee2ea8aa65df173d77fb897 data/create/recipes/small_deepslate_brick_slab_from_deepslate_stonecutting.json 655be9ddf21dea2255fb2cb2628a5fee39eb10e2 data/create/recipes/small_deepslate_brick_slab_from_stone_types_deepslate_stonecutting.json d6d3db5604279cd402f64dbdeae7c3bee6d7ab78 data/create/recipes/small_deepslate_brick_slab_recycling.json 9f1ca55fedf45f248c5e91d2d4922113f79c6ec3 data/create/recipes/small_deepslate_brick_stairs.json -945843a822322cc1f271ef058fe22b7a56965b9d data/create/recipes/small_deepslate_brick_stairs_from_deepslate_stonecutting.json 0a458e8248fe395748bd6025d43c002db5a7d343 data/create/recipes/small_deepslate_brick_stairs_from_stone_types_deepslate_stonecutting.json 369adbaa8ff0737320c5f9e1ab4635d1fdfa92e5 data/create/recipes/small_deepslate_brick_wall.json -029dce220f82bc354baaedd5ed3d50c0848996ae data/create/recipes/small_deepslate_brick_wall_from_deepslate_stonecutting.json e5644f4227b9cc9b98158ce3ded98bff1ffb97f9 data/create/recipes/small_deepslate_brick_wall_from_stone_types_deepslate_stonecutting.json -8eb0c1fd2f2a07e0e2a6fa9cec4db9bc078ac615 data/create/recipes/small_diorite_bricks_from_diorite_stonecutting.json 38b80603a86df24f6be0df9fd5f7d9b7aa33d2f9 data/create/recipes/small_diorite_bricks_from_stone_types_diorite_stonecutting.json 3e404e5f87a9f768f95d8a78efbbbf68bd0c8490 data/create/recipes/small_diorite_brick_slab.json -b731f90988862436bc8f19c4db37e8896f6a50ea data/create/recipes/small_diorite_brick_slab_from_diorite_stonecutting.json 801f6cc6e06db56344b37c9b76c69f921c6d9293 data/create/recipes/small_diorite_brick_slab_from_stone_types_diorite_stonecutting.json c1fe4bff306e2d2b5d5595e4b35dd85f7e6bf0ce data/create/recipes/small_diorite_brick_slab_recycling.json 9b5923275d2d74cf6e211907bbaf9089c2f0ab29 data/create/recipes/small_diorite_brick_stairs.json -25fd1dc9c64e21cac58dc6b543300e82664cfffe data/create/recipes/small_diorite_brick_stairs_from_diorite_stonecutting.json 30a6f2bdfec2b3f578572c9f94112906411e7c54 data/create/recipes/small_diorite_brick_stairs_from_stone_types_diorite_stonecutting.json c59055f48a9bc2d7ca2cab0c5aa4fc1239bec422 data/create/recipes/small_diorite_brick_wall.json -63cf4e288cb2e71b5dc3f1ce0710c23ff817b140 data/create/recipes/small_diorite_brick_wall_from_diorite_stonecutting.json 7a1fdcef7091d76230fbee410fa5241f584845c4 data/create/recipes/small_diorite_brick_wall_from_stone_types_diorite_stonecutting.json -31d3e9e79cbe7bdfbb518c4b6b06804f6e51536a data/create/recipes/small_dripstone_bricks_from_dripstone_block_stonecutting.json 8840d538648516dd02628fbe3ea4f032ceda78bb data/create/recipes/small_dripstone_bricks_from_stone_types_dripstone_stonecutting.json 15d869edb9def414a87bea1f24512bbf84f520b6 data/create/recipes/small_dripstone_brick_slab.json -adfb33d0e3267b6608b2fc08ed60fa993da133a6 data/create/recipes/small_dripstone_brick_slab_from_dripstone_block_stonecutting.json c91e4dc211305456c38e5823def91811ad851202 data/create/recipes/small_dripstone_brick_slab_from_stone_types_dripstone_stonecutting.json 55bb37d07e841bb8eecf2013445c01c8e09ff824 data/create/recipes/small_dripstone_brick_slab_recycling.json 93313c044ae36a57ec010f656f0da783ac3ee297 data/create/recipes/small_dripstone_brick_stairs.json -a7a110c9de5d03110c5d3dd00e038b5d29c443fd data/create/recipes/small_dripstone_brick_stairs_from_dripstone_block_stonecutting.json 1e23c8df90aef6cd3561369f72c6c3106da883f5 data/create/recipes/small_dripstone_brick_stairs_from_stone_types_dripstone_stonecutting.json 0cb53a63276183bde22932026a5e3221bab1f4dc data/create/recipes/small_dripstone_brick_wall.json -7dd1b480b1971c0da866013fd4e420217264efe4 data/create/recipes/small_dripstone_brick_wall_from_dripstone_block_stonecutting.json 336e47b35437ffea4bb86d34f94e6361b2bbcfb0 data/create/recipes/small_dripstone_brick_wall_from_stone_types_dripstone_stonecutting.json -5743078fe45348007bf51ce5e2c8a8d8ae751a75 data/create/recipes/small_granite_bricks_from_granite_stonecutting.json 42c74dec6c64d3675e15b2b73cb32fc9d24839e9 data/create/recipes/small_granite_bricks_from_stone_types_granite_stonecutting.json 22b9280c9981648e3a49fa9355e5ed41fcc70c63 data/create/recipes/small_granite_brick_slab.json -d9cb5f8b9c851b6f02dc43a0199d053c492219c1 data/create/recipes/small_granite_brick_slab_from_granite_stonecutting.json ddb2f4652607b56332a927af939212a5789a34db data/create/recipes/small_granite_brick_slab_from_stone_types_granite_stonecutting.json f1388636bcf98d7d9103c23528053b28c6305b4e data/create/recipes/small_granite_brick_slab_recycling.json 3ccb55c1572e8fc18c018c0c52eba6a3904ca68e data/create/recipes/small_granite_brick_stairs.json -c0a6225beecce256b826e6d59c17a8d49c2388a1 data/create/recipes/small_granite_brick_stairs_from_granite_stonecutting.json ba935a3d64eedbd9b7017d0abfab351f57589593 data/create/recipes/small_granite_brick_stairs_from_stone_types_granite_stonecutting.json c069a73636ce94e2089139a08381532d2af38e62 data/create/recipes/small_granite_brick_wall.json -8f0bf921e4ac4e0e61ca4f087c00e910f2c7aa4b data/create/recipes/small_granite_brick_wall_from_granite_stonecutting.json 7a8d9e2291675de9e72363d93410de9039216f32 data/create/recipes/small_granite_brick_wall_from_stone_types_granite_stonecutting.json -c66f188666134d101f450438502c3f3e735d3edc data/create/recipes/small_limestone_bricks_from_limestone_stonecutting.json 714f6a84a5b3d5d57c07364925555e6f545b0b3d data/create/recipes/small_limestone_bricks_from_stone_types_limestone_stonecutting.json 4a3d7200af0cd92c6fef16df46e8b72107c51b26 data/create/recipes/small_limestone_brick_slab.json -a0846474ed3fc69b6fd8178355f2c8d1c8ebc934 data/create/recipes/small_limestone_brick_slab_from_limestone_stonecutting.json a1c0bc263cd4659a89213f4fcdd87eba7ae04427 data/create/recipes/small_limestone_brick_slab_from_stone_types_limestone_stonecutting.json ec9154a3791113f57dc1c16dfef4c837533b6fc6 data/create/recipes/small_limestone_brick_slab_recycling.json 269b50217bcec3f733c815c3ced82cc8a395dab9 data/create/recipes/small_limestone_brick_stairs.json -d4f610b3aeb40a3473dd880c336158e4fd6c6259 data/create/recipes/small_limestone_brick_stairs_from_limestone_stonecutting.json 6943fdc8162e4d53c459f425b2ff5b34e9caa477 data/create/recipes/small_limestone_brick_stairs_from_stone_types_limestone_stonecutting.json a42c32449aa7868d608cf1a3f2795c9d7b6d1d66 data/create/recipes/small_limestone_brick_wall.json -f127558b3a61c158479c3aea7426931a7d20a143 data/create/recipes/small_limestone_brick_wall_from_limestone_stonecutting.json 98a83f757f0ac9cc2a876ae407bb5765071e700d data/create/recipes/small_limestone_brick_wall_from_stone_types_limestone_stonecutting.json -4f94bb5cc07b70bdecb1f063596003c38593e4c1 data/create/recipes/small_ochrum_bricks_from_ochrum_stonecutting.json 22c69e391110280e13d50693b9c81355da57a315 data/create/recipes/small_ochrum_bricks_from_stone_types_ochrum_stonecutting.json edcbce73a1790a18cc34f1d626d6ece5c9c92e59 data/create/recipes/small_ochrum_brick_slab.json -7baf69d884d62320615d22c49633941f018196a5 data/create/recipes/small_ochrum_brick_slab_from_ochrum_stonecutting.json e37612fa2523fa3711242cac4ec5e596b3e55698 data/create/recipes/small_ochrum_brick_slab_from_stone_types_ochrum_stonecutting.json 8f3f47cb3e759104cf86a422339345f8795143d3 data/create/recipes/small_ochrum_brick_slab_recycling.json 842d2a161e816595dfe5c2a222bbc74c718c867b data/create/recipes/small_ochrum_brick_stairs.json -468cca8f2f86763aa46730f308839148d0445b9f data/create/recipes/small_ochrum_brick_stairs_from_ochrum_stonecutting.json 04ebbdd14f81f4b4dc7986cb5241caa9f48f4ff1 data/create/recipes/small_ochrum_brick_stairs_from_stone_types_ochrum_stonecutting.json ec186b1da919dfebd0c3c675e58ef5da0324a996 data/create/recipes/small_ochrum_brick_wall.json -8ad778b534f94e98d2ffffc2382138b8f90961e1 data/create/recipes/small_ochrum_brick_wall_from_ochrum_stonecutting.json 2331801569ec95562afc802f7e2ff191d329a5c6 data/create/recipes/small_ochrum_brick_wall_from_stone_types_ochrum_stonecutting.json 68a9f80b97d9322ed33067d7717180494b904bed data/create/recipes/small_rose_quartz_tiles_from_polished_rose_quartz_stonecutting.json -6a400e581b49f517a7288dd036beb841b4d356ba data/create/recipes/small_scorchia_bricks_from_scorchia_stonecutting.json bf27af2e54ed1b09611d67ee7afa6c7f56d00d09 data/create/recipes/small_scorchia_bricks_from_stone_types_scorchia_stonecutting.json 58bbdc43cd1a4c20c0f9ec18a14ffddbfa4e5fa2 data/create/recipes/small_scorchia_brick_slab.json -6eb5d0dadb6fdc4e0d487465f34a404765022563 data/create/recipes/small_scorchia_brick_slab_from_scorchia_stonecutting.json dad342d215c98f3214752e0ebfaf3015943c5ac7 data/create/recipes/small_scorchia_brick_slab_from_stone_types_scorchia_stonecutting.json 0a57ad5fce22d69cdc1dd880403612ffb47af4ba data/create/recipes/small_scorchia_brick_slab_recycling.json 9203846f117e17b5314542369e8d594cacdad7dc data/create/recipes/small_scorchia_brick_stairs.json -a3d942f204aff7579c8fa7065a59928790d8ae2a data/create/recipes/small_scorchia_brick_stairs_from_scorchia_stonecutting.json 7f89c9c6dcea06a3022c72029a5e547aa1721773 data/create/recipes/small_scorchia_brick_stairs_from_stone_types_scorchia_stonecutting.json 340e089d9c435f7f87c3d5aa4e22115812937c7a data/create/recipes/small_scorchia_brick_wall.json -6a43cb5b1eceeb56e7ef367cc1bce583b2101ff1 data/create/recipes/small_scorchia_brick_wall_from_scorchia_stonecutting.json de8edc4fa5eec031ad0a63c7f59141985ae9af9e data/create/recipes/small_scorchia_brick_wall_from_stone_types_scorchia_stonecutting.json -079301340c00f203663804d83d359f46461f5155 data/create/recipes/small_scoria_bricks_from_scoria_stonecutting.json b1a67d052e26c2129c34ee0732cfe533beb3e571 data/create/recipes/small_scoria_bricks_from_stone_types_scoria_stonecutting.json fa0a0e9712aafc252d6a35e95680746ac626bb63 data/create/recipes/small_scoria_brick_slab.json -d709eb0697dddb8f538259fe56eba34bcccfdf1d data/create/recipes/small_scoria_brick_slab_from_scoria_stonecutting.json 34f4dd094f2949e3fd21f95ac890ae803b81fbea data/create/recipes/small_scoria_brick_slab_from_stone_types_scoria_stonecutting.json f15ad1cb05f5b02b630b982d23bd951178a3650c data/create/recipes/small_scoria_brick_slab_recycling.json c2920ca0d9063d4b2a4c64a1bc5a18e9c7c2b135 data/create/recipes/small_scoria_brick_stairs.json -acabb209031fb745e76f21c6f3b58aaa149543a2 data/create/recipes/small_scoria_brick_stairs_from_scoria_stonecutting.json d36428daf8bf4e560f649e5eb40a8cd7a27e7a0e data/create/recipes/small_scoria_brick_stairs_from_stone_types_scoria_stonecutting.json 01bb6f37087a06c7a11e7587384d526a4e8e3167 data/create/recipes/small_scoria_brick_wall.json -63310cb02151d3ffed614d8ed4b64602dec95e82 data/create/recipes/small_scoria_brick_wall_from_scoria_stonecutting.json 9cff8370aaa81ece466fe15642c00a9992bd416c data/create/recipes/small_scoria_brick_wall_from_stone_types_scoria_stonecutting.json e51ced16059f7c37fe3652a1cf4d938f91e956fc data/create/recipes/small_tuff_bricks_from_stone_types_tuff_stonecutting.json -7c577b883e87755af73fdeb6035af34f75f06128 data/create/recipes/small_tuff_bricks_from_tuff_stonecutting.json e770352752b4454befe8937fd529236a53c8fa3b data/create/recipes/small_tuff_brick_slab.json e3a12b87830e47387e9ac118bb3d12b73558d757 data/create/recipes/small_tuff_brick_slab_from_stone_types_tuff_stonecutting.json -5c019708682bcc4b8b70aae50593a517c6065f2d data/create/recipes/small_tuff_brick_slab_from_tuff_stonecutting.json 85dff00dc49eaf65f1f149a7f21a9f307b1b9710 data/create/recipes/small_tuff_brick_slab_recycling.json 5eff5e100472c2419a6cfa0e9f029af90eaebc4e data/create/recipes/small_tuff_brick_stairs.json cd50bb5842c90038f6ac74e45971ab2e914d1463 data/create/recipes/small_tuff_brick_stairs_from_stone_types_tuff_stonecutting.json -d760d954ec83f0eab9b799d115bc10d8cd6abc62 data/create/recipes/small_tuff_brick_stairs_from_tuff_stonecutting.json 86fbd039188a8793b8edb52c7e6a29eaba5640dd data/create/recipes/small_tuff_brick_wall.json 34471a7ebb431b6d1e3be5fa480b800b96556fee data/create/recipes/small_tuff_brick_wall_from_stone_types_tuff_stonecutting.json -d48d5fc69f9c1dfdb57a51c48dc10925d31c2783 data/create/recipes/small_tuff_brick_wall_from_tuff_stonecutting.json 82f17edc61a319c74dbdfa730584305899bd7572 data/create/recipes/small_veridium_bricks_from_stone_types_veridium_stonecutting.json -4088898aa3fdcf6a4ddecf77265117218e662963 data/create/recipes/small_veridium_bricks_from_veridium_stonecutting.json ad7ff19ef16089170686cbc8e28f384f2b82747b data/create/recipes/small_veridium_brick_slab.json 234c3baee4c9428caab3e344f396ec87064103e3 data/create/recipes/small_veridium_brick_slab_from_stone_types_veridium_stonecutting.json -b645c6def08cd555f7578ce898853b27dae0fd4f data/create/recipes/small_veridium_brick_slab_from_veridium_stonecutting.json b0db8335e3c7fd88f074c3895bea952efc0e8df8 data/create/recipes/small_veridium_brick_slab_recycling.json d50c23f015fe1d4b6085d20c71b362ace745b642 data/create/recipes/small_veridium_brick_stairs.json f63031587a64ed88ddba1df07767dd8d8caa1d2e data/create/recipes/small_veridium_brick_stairs_from_stone_types_veridium_stonecutting.json -5e98ac217a1738c82784c9de6ba5b4439084c70b data/create/recipes/small_veridium_brick_stairs_from_veridium_stonecutting.json 399f40a1a09e1f47b947e775799550ef46de7851 data/create/recipes/small_veridium_brick_wall.json 1ba48c5cae05b6f4b1ad223ce80925f1eaaf5dfd data/create/recipes/small_veridium_brick_wall_from_stone_types_veridium_stonecutting.json -f9905212d11f8b229f55393c693b65dfec8c0956 data/create/recipes/small_veridium_brick_wall_from_veridium_stonecutting.json 820c7a7a581ee4f980be42888582a398d9e03df3 data/create/recipes/spruce_window.json 28ee023b2c63dd35c3291bff8bc4691ecd636f04 data/create/recipes/spruce_window_pane.json e343a80c92dab60f99c9b441d00189aceee477a0 data/create/recipes/tiled_glass_from_glass_colorless_stonecutting.json a38ceb6132a54fee3beea68a9f445bbddd4f36df data/create/recipes/tiled_glass_pane.json +170f4dc4478029ba9ffa149051abb9072c59f3d1 data/create/recipes/tuff_from_stone_types_tuff_stonecutting.json fdd28fc956dbec71ba24cdea5adfc049d6eb31e3 data/create/recipes/tuff_pillar_from_stone_types_tuff_stonecutting.json -38ac241ef03ca06f3b9936e49feeff0c5c869837 data/create/recipes/tuff_pillar_from_tuff_stonecutting.json +4e4861de1b7c989cb29e6383f842d7022f48279b data/create/recipes/veridium_from_stone_types_veridium_stonecutting.json 689c523599dcf37398e7217f2732723f6f726049 data/create/recipes/veridium_pillar_from_stone_types_veridium_stonecutting.json -445d653a5d2622127071155e3b6481907e7e8ade data/create/recipes/veridium_pillar_from_veridium_stonecutting.json 310b9e72aebc37d1e883292c21af914b1026b8fe data/create/recipes/vertical_framed_glass_from_glass_colorless_stonecutting.json c7fb73642aae741af579da19933aae03efbde37d data/create/recipes/vertical_framed_glass_pane.json be859e03587b599707d4d333690af2d96533e806 data/create/recipes/warped_window.json @@ -4482,72 +4168,82 @@ be859e03587b599707d4d333690af2d96533e806 data/create/recipes/warped_window.json f1a03ac86925e26cbec6aeeada2eafb40008fc8e data/create/recipes/weathered_copper_tile_stairs_from_weathered_copper_tiles_stonecutting.json 8b98a671e80724e815a3af0c3764d760e4170e02 data/create/tags/blocks/brittle.json 8b6c0b444b15f7fb2d55b9cbcb68537c1269f877 data/create/tags/blocks/casing.json -e00f26584b23b7c3d9c3c5cc461b6418de4ee0fa data/create/tags/blocks/fan_transparent.json -0b91b64f3b81f85dcb9e56c50264c78f17727303 data/create/tags/blocks/movable_empty_collider.json +35133e95f1c8fdd7a1c21afcc231fc0bffefb9a8 data/create/tags/blocks/contraption_inventory_deny.json +c7ec0dbc18e9c1b58e568ed925287b89df11a136 data/create/tags/blocks/copycat_allow.json +876eb9210f4a14898a2fe6d225699c66b5bdfeef data/create/tags/blocks/copycat_deny.json +6858173c670bb593664ac3c62ded726d57d581f1 data/create/tags/blocks/fan_transparent.json +2589b135c0e96ad29076569e144528fe32ea5b39 data/create/tags/blocks/girdable_tracks.json +a1e21c22f32354fd1a82a1b0a59dd786c0deaba0 data/create/tags/blocks/movable_empty_collider.json 4970078b49ddac1b1d500ed0469cedf42bdc3d35 data/create/tags/blocks/non_movable.json 06e13efbb7b0d09ff7ecd1a7dc45a0760b91ad67 data/create/tags/blocks/ore_override_stone.json a5874f73c7dc0a3ae12999e6ae8abf45bc7fb9be data/create/tags/blocks/passive_boiler_heaters.json -2cfb1f2270ad1616ccd12b1f3871fa6b779be66c data/create/tags/blocks/safe_nbt.json +3928cfdba3f941456bb05005fa0c36966a3aa880 data/create/tags/blocks/safe_nbt.json 79418bd729cef417b322cef9b491e7ae83317d61 data/create/tags/blocks/seats.json 5def5088f7fd31b80e6f28c1c4ea146aa9d7d15b data/create/tags/blocks/toolboxes.json +2589b135c0e96ad29076569e144528fe32ea5b39 data/create/tags/blocks/tracks.json 1b6977d9a399cf6ee042e3f8f5e64e4d3cda5489 data/create/tags/blocks/tree_attachments.json da739ad2160e7df4e0e5cc89587670ce5e9450c3 data/create/tags/blocks/valve_handles.json 72143286fb5cb372a0696550e2eac76ca50e6fbc data/create/tags/blocks/windmill_sails.json -5ce401742b78906ba4a39c8d717283da9aa1c61c data/create/tags/blocks/wrench_pickup.json +58987ea71d488cc48192ceb00c00aa2903e51304 data/create/tags/blocks/wrench_pickup.json 894e1e4fd1e32712abdda18ec64ab13750d3c039 data/create/tags/fluids/bottomless/allow.json 35133e95f1c8fdd7a1c21afcc231fc0bffefb9a8 data/create/tags/fluids/bottomless/deny.json 35133e95f1c8fdd7a1c21afcc231fc0bffefb9a8 data/create/tags/items/blaze_burner_fuel/regular.json 8ba98bf390a326abeebfd5d84be5f740c935a8b6 data/create/tags/items/blaze_burner_fuel/special.json 8b6c0b444b15f7fb2d55b9cbcb68537c1269f877 data/create/tags/items/casing.json +f43cac8216e2a9347e48cf93a43de95dd810ca20 data/create/tags/items/contraption_controlled.json d371dfd35e49a7bef19f59c03e7f4ae20992f03d data/create/tags/items/create_ingots.json -878b7281fa78d0ef5f873322281da8f5ebbb782c data/create/tags/items/crushed_ores.json +910d0f5ccbc4c84b224eca1f1588b1695f41447b data/create/tags/items/crushed_raw_materials.json 0fa526e7e742573b603ad26b09526cf724efa1dc data/create/tags/items/deployable_drink.json 29ca12609f7c419c5c06338a86c7f4ba1fc7390e data/create/tags/items/modded_stripped_logs.json ae63f7dc5d9221890ee593ff03cd2aff8cd6a356 data/create/tags/items/modded_stripped_wood.json -7424e0342059943fab84b7103569d9bed7e871c5 data/create/tags/items/pressurized_air_sources.json +695d75b352fd190b303c724d1aaee9bb786a903b data/create/tags/items/pressurized_air_sources.json 2cd3adffd8b151354df137a990dcb97996a665bb data/create/tags/items/sandpaper.json 79418bd729cef417b322cef9b491e7ae83317d61 data/create/tags/items/seats.json e02cb3bc2373336dc04495b0b414107f6f754b61 data/create/tags/items/sleepers.json -fb26cd137213a6a27522a9bca58848643600295b data/create/tags/items/stone_types/andesite.json -d886a124ebbf89a03b13a2dd54a81964af4ddfd6 data/create/tags/items/stone_types/asurine.json -adf6655f51b7f23a92eaf2ad463a3b908c1bd192 data/create/tags/items/stone_types/calcite.json -cdba278ddf807fe9ed71b1f7c0765353a92393f1 data/create/tags/items/stone_types/crimsite.json -fe5dc1842e27063c5b5c3897fd58d6fe8db9dea6 data/create/tags/items/stone_types/deepslate.json -c3db3eb3fcb8ebe9550d3d51d08ca1418d088718 data/create/tags/items/stone_types/diorite.json -ef42e3be8a8ba26cb8f206cd1fad98bcbf43d0ac data/create/tags/items/stone_types/dripstone.json -b3735b01479b142e3debbc008b4d1df11a502d2e data/create/tags/items/stone_types/granite.json -f705e384898686a9a6fbb7780773c5d1f201a91d data/create/tags/items/stone_types/limestone.json -d9e385892147c5cf3d209a759b0699c4af75f175 data/create/tags/items/stone_types/ochrum.json -991af193106b7935330cbe0d7e46a2f5ae35efea data/create/tags/items/stone_types/scorchia.json -d5f544bfab05d4590a77d70c01df3d417bfae766 data/create/tags/items/stone_types/scoria.json -4652677bbb1188555eedcfb1cf5198521bb216f6 data/create/tags/items/stone_types/tuff.json -260bab070ffdcdd5a9f16d0d0738c37affdd4784 data/create/tags/items/stone_types/veridium.json +ab98061be1e382670efcbce9c3dddf4aeeef68d5 data/create/tags/items/stone_types/andesite.json +c4f7ea1570e9965ff4217acb588d8a1a5fcbe957 data/create/tags/items/stone_types/asurine.json +1a965d3033a2b5a6413c1f9dfa3b982fb027f0a4 data/create/tags/items/stone_types/calcite.json +a970ecabfefc20e8911762495da0d5cf1f99c636 data/create/tags/items/stone_types/crimsite.json +8ee57ecfa4e4e5c67b61ef4dd18c1e2715bbe9d8 data/create/tags/items/stone_types/deepslate.json +f5532145f210fdd0ab12c253d6deabbc8d1601ef data/create/tags/items/stone_types/diorite.json +23aebee6c6614fdf94804f2a227476523844b888 data/create/tags/items/stone_types/dripstone.json +683700c751c964e47707d836986f8415fbf609d5 data/create/tags/items/stone_types/granite.json +00f8eb75e9cd1a19fd21800d03f671cc58dbbbe7 data/create/tags/items/stone_types/limestone.json +00af13f6cea72fb3da0d33e06c16a643ec21b327 data/create/tags/items/stone_types/ochrum.json +e22493305e0cebfb7ededae122e19ee9dd24fc9d data/create/tags/items/stone_types/scorchia.json +8034ddb85922b193ad1e6251fc6b856b4ae622b1 data/create/tags/items/stone_types/scoria.json +7e4d20c52a25a0c0d13e0122be0250718a9fb645 data/create/tags/items/stone_types/tuff.json +076c79e07eb3a65d74107577dbfd993b13780637 data/create/tags/items/stone_types/veridium.json 5def5088f7fd31b80e6f28c1c4ea146aa9d7d15b data/create/tags/items/toolboxes.json 22c744a157399a21492bcd8b211578f8f504e653 data/create/tags/items/upright_on_belt.json da739ad2160e7df4e0e5cc89587670ce5e9450c3 data/create/tags/items/valve_handles.json 03989b943d729293db75c8f681c490c55f594d53 data/create/tags/items/vanilla_stripped_logs.json a82f75a9af4c0b28f08de8dfcaea2dce2accda28 data/create/tags/items/vanilla_stripped_wood.json 10d5f0c1763f80860a39398ecc33dbbe43099471 data/forge/tags/blocks/glass/colorless.json -3101d4cdeb57fae0e777ed7a773eccbd7d757b76 data/forge/tags/blocks/glass_panes.json +de1fc89be6a52473d526d3efe0204b9b8489058c data/forge/tags/blocks/glass_panes.json 81b107ada9c6ac5679a21f8c6a006bf230f69c39 data/forge/tags/blocks/ores.json 81b107ada9c6ac5679a21f8c6a006bf230f69c39 data/forge/tags/blocks/ores/zinc.json e475ad1c52bffedfc544e5331a87c1f5c45149fd data/forge/tags/blocks/ores_in_ground/deepslate.json 2f6068972e364599b6849dc46fcb0724d4219d53 data/forge/tags/blocks/ores_in_ground/stone.json 2589b135c0e96ad29076569e144528fe32ea5b39 data/forge/tags/blocks/relocation_not_supported.json -ef8aee2a9fc838d97ba822d68ff94dbf94da7e61 data/forge/tags/blocks/storage_blocks.json +b3af02a6fa3dc41bc3f4db933485f22b202deea3 data/forge/tags/blocks/storage_blocks.json +7d10cdf9e46a79753d4437c7bb958e3ab8bf0c89 data/forge/tags/blocks/storage_blocks/andesite_alloy.json 70bba470740dc7a77f51b4cb1747a105b62d4bde data/forge/tags/blocks/storage_blocks/brass.json bcd593714f43bc6a0aefbd714c24db3cf9e71250 data/forge/tags/blocks/storage_blocks/raw_zinc.json 41b2a17b5ebcff5623e25dc6232f73cf9aa70387 data/forge/tags/blocks/storage_blocks/zinc.json 8140415f1c16f09167f41eeee25c09706a944be0 data/forge/tags/fluids/chocolate.json 0ccc9ff76001cdd7db1b79c1371f59d3283abe64 data/forge/tags/fluids/honey.json cca816b34ac2e9b7933df680aa9778ff2cfe9605 data/forge/tags/fluids/tea.json +00c856dcfa4368cca671ee5d93c4900835991d68 data/forge/tags/items/armors/boots.json +695d75b352fd190b303c724d1aaee9bb786a903b data/forge/tags/items/armors/chestplates.json +3580dae058fc75b45fab4c4ebbd1b01573ba9e11 data/forge/tags/items/armors/helmets.json 06ebf72e8f6c081862236d4b068b5dfb275a8385 data/forge/tags/items/buckets/honey.json 801d097b0af7153e0c5c72a924d61f8afb4cf264 data/forge/tags/items/dough.json 801d097b0af7153e0c5c72a924d61f8afb4cf264 data/forge/tags/items/dough/wheat.json 745512f10c4ba52f2c224607377e41011fb2ecfe data/forge/tags/items/flour.json 745512f10c4ba52f2c224607377e41011fb2ecfe data/forge/tags/items/flour/wheat.json 10d5f0c1763f80860a39398ecc33dbbe43099471 data/forge/tags/items/glass/colorless.json -3101d4cdeb57fae0e777ed7a773eccbd7d757b76 data/forge/tags/items/glass_panes.json +de1fc89be6a52473d526d3efe0204b9b8489058c data/forge/tags/items/glass_panes.json 01d32d3b7b033aff44c047bf289d696de0b0c715 data/forge/tags/items/ingots.json 5a7bffd1d604bc6ea8b35714ef02b95773240f90 data/forge/tags/items/ingots/brass.json ccf5b08295f6362a3f6b3b595f1de1bba4b224ec data/forge/tags/items/ingots/zinc.json @@ -4567,7 +4263,8 @@ ef5256892a9d4167bf7371c7138a933a107a123a data/forge/tags/items/plates/copper.jso 07a6e69488ff6994a9ef1cca75b6e911bc3e3358 data/forge/tags/items/plates/obsidian.json 30496416fffaf4f845052a264023e64e52894ee7 data/forge/tags/items/raw_materials.json 30496416fffaf4f845052a264023e64e52894ee7 data/forge/tags/items/raw_materials/zinc.json -ef8aee2a9fc838d97ba822d68ff94dbf94da7e61 data/forge/tags/items/storage_blocks.json +b3af02a6fa3dc41bc3f4db933485f22b202deea3 data/forge/tags/items/storage_blocks.json +7d10cdf9e46a79753d4437c7bb958e3ab8bf0c89 data/forge/tags/items/storage_blocks/andesite_alloy.json 70bba470740dc7a77f51b4cb1747a105b62d4bde data/forge/tags/items/storage_blocks/brass.json bcd593714f43bc6a0aefbd714c24db3cf9e71250 data/forge/tags/items/storage_blocks/raw_zinc.json 41b2a17b5ebcff5623e25dc6232f73cf9aa70387 data/forge/tags/items/storage_blocks/zinc.json @@ -4575,14 +4272,14 @@ b69fcc7227d44fc000c8ab94524230f55b89aa27 data/forge/tags/items/stripped_logs.jso 1ac851b8f78458339cf09ad498d14e783615eb3d data/forge/tags/items/stripped_wood.json c741ba83b562ae3459d7c4f2db69537f549ea411 data/forge/tags/items/tools/wrench.json 515a1c773e617dd7e38aa1b893acc7db2dd30e08 data/minecraft/tags/blocks/azalea_root_replaceable.json -4030577647f1d28385f7fca1426b43848263264d data/minecraft/tags/blocks/beacon_base_blocks.json -2eadd112a70daba732d5e982eb0397aa53d16c93 data/minecraft/tags/blocks/climbable.json -b53d2d87aa0c3f62874f418180b0f1ff00d8cae7 data/minecraft/tags/blocks/doors.json +529fa4332dd12a11ebb04e183121a2c63f866761 data/minecraft/tags/blocks/beacon_base_blocks.json +82274e06b6a9f3bfd83c8b59be38dee4a15b8bf3 data/minecraft/tags/blocks/climbable.json +71aef080a900d9e86818cf579438c3d826d6567e data/minecraft/tags/blocks/doors.json 515a1c773e617dd7e38aa1b893acc7db2dd30e08 data/minecraft/tags/blocks/dripstone_replaceable_blocks.json -84c712d8f5ec8ba4e0d9de9a0485af5115a5cfe2 data/minecraft/tags/blocks/impermeable.json +e3321ff14704c031a2c16953b7e391f4f24dd70b data/minecraft/tags/blocks/impermeable.json 515a1c773e617dd7e38aa1b893acc7db2dd30e08 data/minecraft/tags/blocks/lush_ground_replaceable.json -fc6d9f863e27938f8b81bff7e0b613a6776a108e data/minecraft/tags/blocks/mineable/axe.json -1c3912e5e020a47c30f36a058bc2bdcdc58c76ff data/minecraft/tags/blocks/mineable/pickaxe.json +5a030817b2322e363edc8f5376f7c9de73df8b48 data/minecraft/tags/blocks/mineable/axe.json +d794a156fdc9ec9e7c935b3b8962206b7b82eb79 data/minecraft/tags/blocks/mineable/pickaxe.json 515a1c773e617dd7e38aa1b893acc7db2dd30e08 data/minecraft/tags/blocks/moss_replaceable.json 0c13aae0eeb99e89febe8dbe5e002af2ff843a9e data/minecraft/tags/blocks/needs_iron_tool.json 3cb2a92cbdf32ed5978f740dc378d363306c3e84 data/minecraft/tags/blocks/needs_stone_tool.json @@ -4591,12 +4288,12 @@ fc6d9f863e27938f8b81bff7e0b613a6776a108e data/minecraft/tags/blocks/mineable/axe dafa3bdb72fef5e6c0201c05846db3f2b214e587 data/minecraft/tags/blocks/stairs.json 11427a72e181857e22ec37a22462bc652e127cc5 data/minecraft/tags/blocks/trapdoors.json 2bcba05954ff7bc4cf9cc520478083da9973ec76 data/minecraft/tags/blocks/walls.json -b53d2d87aa0c3f62874f418180b0f1ff00d8cae7 data/minecraft/tags/blocks/wooden_doors.json +71aef080a900d9e86818cf579438c3d826d6567e data/minecraft/tags/blocks/wooden_doors.json 01d32d3b7b033aff44c047bf289d696de0b0c715 data/minecraft/tags/items/beacon_payment_items.json -b53d2d87aa0c3f62874f418180b0f1ff00d8cae7 data/minecraft/tags/items/doors.json -a4b539d506b2273020e043c895d7ecc8a2e1064e data/minecraft/tags/items/piglin_loved.json +71aef080a900d9e86818cf579438c3d826d6567e data/minecraft/tags/items/doors.json +0fd9f0786777d613ba7186ec00f9f972d0317c3f data/minecraft/tags/items/piglin_loved.json 1ac7c46815461cbec0d4d97f25c085fdc8375dab data/minecraft/tags/items/slabs.json dafa3bdb72fef5e6c0201c05846db3f2b214e587 data/minecraft/tags/items/stairs.json 11427a72e181857e22ec37a22462bc652e127cc5 data/minecraft/tags/items/trapdoors.json 2bcba05954ff7bc4cf9cc520478083da9973ec76 data/minecraft/tags/items/walls.json -b53d2d87aa0c3f62874f418180b0f1ff00d8cae7 data/quark/tags/blocks/non_double_door.json +71aef080a900d9e86818cf579438c3d826d6567e data/quark/tags/blocks/non_double_door.json diff --git a/src/generated/resources/.cache/6ec3b5a261c9ae3df674f7595dc66530ce54feb9 b/src/generated/resources/.cache/6ec3b5a261c9ae3df674f7595dc66530ce54feb9 index 9a625e020..b5d05e432 100644 --- a/src/generated/resources/.cache/6ec3b5a261c9ae3df674f7595dc66530ce54feb9 +++ b/src/generated/resources/.cache/6ec3b5a261c9ae3df674f7595dc66530ce54feb9 @@ -1,4 +1,4 @@ -// 1.19.3 2023-02-06T18:08:23.2353349 Create's Mechanical Crafting Recipes +// 1.19.3 2023-06-27T03:14:49.7513801 Create's Mechanical Crafting Recipes f076d64d9f30709bed34775136c9241097b28aa9 data/create/recipes/mechanical_crafting/crushing_wheel.json 694dca9dcff246bb7f560b3304fcc244c53217d5 data/create/recipes/mechanical_crafting/extendo_grip.json 3b2837b08607c1ca466fa3eb418209b2e55da6ba data/create/recipes/mechanical_crafting/potato_cannon.json diff --git a/src/generated/resources/.cache/82992cbf8f2794d83ac94034835eac0acd7915b9 b/src/generated/resources/.cache/82992cbf8f2794d83ac94034835eac0acd7915b9 index 97edf031e..c27dfdb9c 100644 --- a/src/generated/resources/.cache/82992cbf8f2794d83ac94034835eac0acd7915b9 +++ b/src/generated/resources/.cache/82992cbf8f2794d83ac94034835eac0acd7915b9 @@ -1,30 +1,41 @@ -// 1.19.3 2023-02-06T18:08:23.2293512 Create's Standard Recipes -58edc0e6eadb9fdd15113d313e331deb15867ab1 data/create/advancements/recipes/misc/blasting/copper_ingot_from_crushed.json -c5c7a524b797c47093c17f363a805df18765e5d1 data/create/advancements/recipes/misc/blasting/gold_ingot_from_crushed.json -b397254b7cdb19d1c64ed1c30e1f6aa5c8af7270 data/create/advancements/recipes/misc/blasting/ingot_aluminum_compat_immersiveengineering.json -c14aec90afe9450b7dd472ff612e2f8013d09abf data/create/advancements/recipes/misc/blasting/ingot_lead_compat_immersiveengineering.json -fd9a8eb94364c8424f23c510900ef9cd0904b53e data/create/advancements/recipes/misc/blasting/ingot_lead_compat_mekanism.json -6ace306d3b83e6cc0f3c958fbfb5b0338ddc9142 data/create/advancements/recipes/misc/blasting/ingot_nickel_compat_immersiveengineering.json -33f823ee80bbe8d9a1f32ce3590887670cdc3210 data/create/advancements/recipes/misc/blasting/ingot_osmium_compat_mekanism.json -60525ff76c59ccf23906a95e16d2b601285845b3 data/create/advancements/recipes/misc/blasting/ingot_silver_compat_immersiveengineering.json -0cb0a85bf670779e53df79e168e4fc9c1beecae1 data/create/advancements/recipes/misc/blasting/ingot_tin_compat_mekanism.json -335bd0bb7eb3536e753cae1fec5d4c3f1b98ff1f data/create/advancements/recipes/misc/blasting/ingot_uranium_compat_immersiveengineering.json -85d5b8d2299cce40661d978a3ef9e621b25ef31f data/create/advancements/recipes/misc/blasting/ingot_uranium_compat_mekanism.json -7330c11fcdd6de110f141ac97b497d57c4e6291b data/create/advancements/recipes/misc/blasting/iron_ingot_from_crushed.json -c4593c1179944d2363b3ef758fc1c3e448862f0d data/create/advancements/recipes/misc/blasting/lead_ingot_compat_thermal.json -d171dcc76bee96f91e9f86d2f773c40ce2a0df8a data/create/advancements/recipes/misc/blasting/nickel_ingot_compat_thermal.json -b659e790ee00e6c610846825a103ec33b9728854 data/create/advancements/recipes/misc/blasting/silver_ingot_compat_thermal.json -f009abec013a0be4b6d091a73cd24726df5247bb data/create/advancements/recipes/misc/blasting/tin_ingot_compat_thermal.json -1c0d9e8b8f722121435e8d142cbc81489d46bb4a data/create/advancements/recipes/misc/blasting/zinc_ingot_from_crushed.json +// 1.19.3 2023-06-27T03:14:49.745773 Create's Standard Recipes +a4fdf3d783049c8f8a8dcaf168616e085e1bbc71 data/create/advancements/recipes/combat/crafting/appliances/netherite_backtank.json +d3409e2449f606794a6b40a9789d53c3619d2a15 data/create/advancements/recipes/combat/crafting/appliances/netherite_backtank_from_netherite.json +4b8fb0fdc52cb06b15822f76652771e9633f7e38 data/create/advancements/recipes/combat/crafting/appliances/netherite_diving_boots.json +d637d8b12ef56164dd4360720d59968ab87ab4a3 data/create/advancements/recipes/combat/crafting/appliances/netherite_diving_boots_from_netherite.json +2a23251616c0231e235cfa1f96ed02d53b5c8a9b data/create/advancements/recipes/combat/crafting/appliances/netherite_diving_helmet.json +06c8467d5a3e1dad78c9779db91fb16fa1431a26 data/create/advancements/recipes/combat/crafting/appliances/netherite_diving_helmet_from_netherite.json +67e218f34cf2eb55ad069628ea215fa93979cdb9 data/create/advancements/recipes/misc/blasting/copper_ingot_from_crushed.json +3d26689c362908cd665fc66cf628e2b1a117457d data/create/advancements/recipes/misc/blasting/gold_ingot_from_crushed.json +ff6a181c36dba79ed4fe7945823f7529bd7913fe data/create/advancements/recipes/misc/blasting/ingot_aluminum_compat_immersiveengineering.json +106354a9eb7379a53eae40a1775f43bf67225919 data/create/advancements/recipes/misc/blasting/ingot_lead_compat_immersiveengineering.json +bb548877a89f41e1bdfe987dd3ec05b6023daa81 data/create/advancements/recipes/misc/blasting/ingot_lead_compat_mekanism.json +960ef229b3d284fbc9001e00145ef2a01df38525 data/create/advancements/recipes/misc/blasting/ingot_nickel_compat_immersiveengineering.json +b0241594379674d8da9f84bed32e44fd46dabc28 data/create/advancements/recipes/misc/blasting/ingot_osmium_compat_mekanism.json +9a2dad54bbd339741815800ac0b2004d5e159a34 data/create/advancements/recipes/misc/blasting/ingot_silver_compat_immersiveengineering.json +af6c91d27c21c75dd79c56f3e20eb98bace21ee5 data/create/advancements/recipes/misc/blasting/ingot_tin_compat_mekanism.json +7a92e711d29d749348dca778bd65a7a43c2f3e90 data/create/advancements/recipes/misc/blasting/ingot_uranium_compat_immersiveengineering.json +80814471952348a0fb5bcd298c30e22a20f5b343 data/create/advancements/recipes/misc/blasting/ingot_uranium_compat_mekanism.json +8770c28909fce8196117a541c045eb5a7fc4d0e4 data/create/advancements/recipes/misc/blasting/iron_ingot_from_crushed.json +8b5c113733ed0c08ab823d98854a60ab3c144b3d data/create/advancements/recipes/misc/blasting/lead_ingot_compat_thermal.json +1007a146a88c5a7adf5b5017edf570032beaa8ae data/create/advancements/recipes/misc/blasting/nickel_ingot_compat_thermal.json +ac1adc1221ae5e6f5c6a9a6f6b1d28eb51756207 data/create/advancements/recipes/misc/blasting/silver_ingot_compat_thermal.json +34efb445714c7e1ff6ab0dbefb58ce946c565209 data/create/advancements/recipes/misc/blasting/tin_ingot_compat_thermal.json +0cbe8ac095dde3586eae7e4363b3886ffd0c463c data/create/advancements/recipes/misc/blasting/zinc_ingot_from_crushed.json 7afe4a5f978a1c3a4224ca9d71b88f5e92e4a74b data/create/advancements/recipes/misc/blasting/zinc_ingot_from_ore.json faeca323b9061761f494a1ad5e9d3eca2b268583 data/create/advancements/recipes/misc/blasting/zinc_ingot_from_raw_ore.json c070b31d39acd1f9a1f5ee9ec23d8e977a2a2be4 data/create/advancements/recipes/misc/campfire_cooking/bread.json +9678042d96351f38df2dd538181c711b7319ac4e data/create/advancements/recipes/misc/crafting/appliances/attribute_filter_clear.json +51161cf88410ddebf4ae77c6823b2311bf837908 data/create/advancements/recipes/misc/crafting/appliances/clipboard.json +bbfc8ec65e608398aacd644d576655667a9b6999 data/create/advancements/recipes/misc/crafting/appliances/clipboard_clear.json d9b8ad4ceef37123bf0eec823084b60f433bec5e data/create/advancements/recipes/misc/crafting/appliances/copper_backtank.json +292b35d32f00a63f6a17ed5b8e3c185f05e21487 data/create/advancements/recipes/misc/crafting/appliances/copper_diving_boots.json +19742dd19cfa57b20abb139c40a07bb36a86cd11 data/create/advancements/recipes/misc/crafting/appliances/copper_diving_helmet.json aba81978b5805f48cd718df2dd80be4f0875f3c3 data/create/advancements/recipes/misc/crafting/appliances/crafting_blueprint.json -3b4d57e676b9e4be4012f6dc0618db30872f7e20 data/create/advancements/recipes/misc/crafting/appliances/diving_boots.json -a5a142e1877ef25523662582c374e95220fe093f data/create/advancements/recipes/misc/crafting/appliances/diving_helmet.json db851de3567c71d078a186afb78f356bd98c5b24 data/create/advancements/recipes/misc/crafting/appliances/dough.json +1af6bbdd5acd6b7fa0a25a4b90f6aaafd5673195 data/create/advancements/recipes/misc/crafting/appliances/filter_clear.json 020c48f351bb8f98ff58e0a44c841cfcbcd2e647 data/create/advancements/recipes/misc/crafting/appliances/linked_controller.json +4f541c22efef5ed3131364cf0609c7fced8f157c data/create/advancements/recipes/misc/crafting/appliances/schedule_clear.json 37b0c39f4cd0f1c983b78f6d6c0bafd766595da5 data/create/advancements/recipes/misc/crafting/appliances/slime_ball.json 702bbec6bc2d272dac2bfe7558b6bc1ef70f4ccb data/create/advancements/recipes/misc/crafting/appliances/tree_fertilizer.json 17c1e7a8ce5b54d00ed5a927d2f5d6e84cd73383 data/create/advancements/recipes/misc/crafting/curiosities/brown_toolbox.json @@ -33,18 +44,21 @@ ca0dbfc3222435fb25e9c188bd1c2e44375ca8e0 data/create/advancements/recipes/misc/c ccff47a9ff3cc5b101e758aa5de747af24c7617e data/create/advancements/recipes/misc/crafting/curiosities/peculiar_bell.json 101605853b71bcb7ef0388f329dffe35549df83e data/create/advancements/recipes/misc/crafting/kinetics/adjustable_chain_gearshift.json 13fd40f039ec9ba07b25ba94ace23f7d0ba61b47 data/create/advancements/recipes/misc/crafting/kinetics/analog_lever.json -099c89be4865d5f5c1c23a4567a63b7c5dc899ab data/create/advancements/recipes/misc/crafting/kinetics/andesite_ladder.json +9e6d2bd857680a6c6371deaa0c60a492c86225e7 data/create/advancements/recipes/misc/crafting/kinetics/andesite_door.json 815d392dde95d1b25792c4e4ddfe50dd3ccc687d data/create/advancements/recipes/misc/crafting/kinetics/attribute_filter.json e0367cd3c396d99c7ffefc8748d1806b27cba1c2 data/create/advancements/recipes/misc/crafting/kinetics/basin.json 77585206954c25c4c1b8c56d72e6f4cc6d639415 data/create/advancements/recipes/misc/crafting/kinetics/belt_connector.json +c5f9897bf57953bf1ac6c4c2a2f0a9d3c95e655b data/create/advancements/recipes/misc/crafting/kinetics/brass_door.json 96fddc180a85bce7f38db24637879a1d3959128a data/create/advancements/recipes/misc/crafting/kinetics/brass_hand.json 0bd6b4c848e848262d21e0066634657e166ceba9 data/create/advancements/recipes/misc/crafting/kinetics/cart_assembler.json 3c5607faec15cee9aa0199ca41f707e54e293d44 data/create/advancements/recipes/misc/crafting/kinetics/chute.json b66fea562c25d0f685271139a6c4a11f01d381eb data/create/advancements/recipes/misc/crafting/kinetics/clockwork_bearing.json 96b037ef1cf8c4f01d3320d96da56866308fef65 data/create/advancements/recipes/misc/crafting/kinetics/clutch.json add1b00551b8bd58b22370cdc45483e1ea8ccd80 data/create/advancements/recipes/misc/crafting/kinetics/cogwheel.json +405071067037023359144b5eff2a990824551959 data/create/advancements/recipes/misc/crafting/kinetics/contraption_controls.json fb224fd7b448c53434d5c65c2114e6041712532f data/create/advancements/recipes/misc/crafting/kinetics/controller_rail.json 635ce0ca8b8a2bc5906adffea10819ded518c781 data/create/advancements/recipes/misc/crafting/kinetics/controls.json +769efe6975d4266342f7fd6b1003d1352fb67c7b data/create/advancements/recipes/misc/crafting/kinetics/copper_door.json 5ce1a2d78f6f3d1cc03084d4d58aa7ba7a9e5f14 data/create/advancements/recipes/misc/crafting/kinetics/copper_valve_handle.json fe3e9d3eeee5c73b08d38d51d503eb1657306208 data/create/advancements/recipes/misc/crafting/kinetics/copper_valve_handle_from_others.json 08d35f93d0be26ef003648d4d9e95fb6c88c132d data/create/advancements/recipes/misc/crafting/kinetics/crafter_slot_cover.json @@ -52,6 +66,7 @@ fe3e9d3eeee5c73b08d38d51d503eb1657306208 data/create/advancements/recipes/misc/c 6a5f75bb1b5388548471cd19b0541d5994a968d7 data/create/advancements/recipes/misc/crafting/kinetics/deployer.json 874a2bb3627a13b812b7d509a4341cc486173034 data/create/advancements/recipes/misc/crafting/kinetics/depot.json 484d3187f638fe6ad2832390faa71d084bf9965c data/create/advancements/recipes/misc/crafting/kinetics/display_board.json +be4cf32b3e65ddd71ff386cf25d0dfb608c96b92 data/create/advancements/recipes/misc/crafting/kinetics/elevator_pulley.json d582587d3b2449468d77bc0017ca22538c5d04a8 data/create/advancements/recipes/misc/crafting/kinetics/empty_blaze_burner.json a8c4c201c452f1cc2135ab241ef08811627759d9 data/create/advancements/recipes/misc/crafting/kinetics/encased_chain_drive.json daa737129d6fad1eab2f6c7c24d420632cf686fc data/create/advancements/recipes/misc/crafting/kinetics/encased_fan.json @@ -75,7 +90,8 @@ a3396e2e838c8b1719ed65e4195afa09c0286e52 data/create/advancements/recipes/misc/c 27619361a9b229791449e9d4954ed0890156efb7 data/create/advancements/recipes/misc/crafting/kinetics/item_drain.json ce49f3e4c85b36298c764e28a14f328194530e6e data/create/advancements/recipes/misc/crafting/kinetics/item_vault.json 38c97a8961dc55b007fc675efaee19be03ba70e9 data/create/advancements/recipes/misc/crafting/kinetics/large_cogwheel.json -3d14c3f268c5ed9b3b335d11fa7bae7d5503278c data/create/advancements/recipes/misc/crafting/kinetics/large_cogwheelfrom_little.json +d411a67fc6d30096ecf8768a6fc105aef796c1b2 data/create/advancements/recipes/misc/crafting/kinetics/large_cogwheel_from_little.json +364f6ab226c5079f68376f2fe85d70b459203827 data/create/advancements/recipes/misc/crafting/kinetics/large_water_wheel.json 66b12ce8935b3b4c2baecad22121b770987e0cbe data/create/advancements/recipes/misc/crafting/kinetics/linear_chassis.json 03541b64f2b6978ec10c71323012b34e80b32a37 data/create/advancements/recipes/misc/crafting/kinetics/linear_chassisfrom_conversion.json 6609c0187d3d9bb0cdfc82019d859930fcd23b3a data/create/advancements/recipes/misc/crafting/kinetics/mechanical_arm.json @@ -88,6 +104,7 @@ c9834e76909bd803f6d8faa5badb4051cd1f4c46 data/create/advancements/recipes/misc/c 53de4ed3248e562ff2c1ac858b7aa0d4c77f5071 data/create/advancements/recipes/misc/crafting/kinetics/mechanical_plough.json 4a4ef72828a33cc31198801421e6e271c18e13f6 data/create/advancements/recipes/misc/crafting/kinetics/mechanical_press.json 9d01d3aeca84606f93225dfb7b625c27617c078d data/create/advancements/recipes/misc/crafting/kinetics/mechanical_pump.json +2fc222814bcd29a2d238c73e4b1540372711afaf data/create/advancements/recipes/misc/crafting/kinetics/mechanical_roller.json f2e0d416f067ec3b9da478d9006b12b02ea053ab data/create/advancements/recipes/misc/crafting/kinetics/mechanical_saw.json 92b97be9722c87ed607458c658da71193f421618 data/create/advancements/recipes/misc/crafting/kinetics/metal_bracket.json 80197e7c951bd45f532af7c952c6c989433433de data/create/advancements/recipes/misc/crafting/kinetics/metal_girder.json @@ -125,8 +142,8 @@ f7ec77491cba04c96a5df0f3a9b66dfdeecd6a67 data/create/advancements/recipes/misc/c f24315de4ad61c85094c1620d47ccc02f94e4498 data/create/advancements/recipes/misc/crafting/kinetics/track_observer_from_other_plates.json eb90657a95c9aecdc3b8ab9aeeb6abe5ccb7ff76 data/create/advancements/recipes/misc/crafting/kinetics/track_signal.json 78cf68d5afca01ea37e2d32f54e655ec87924be1 data/create/advancements/recipes/misc/crafting/kinetics/track_station.json -1b7ea4648eb851560056942ea3cec29ab82e2035 data/create/advancements/recipes/misc/crafting/kinetics/train_door.json -02f3fb7faadd1c56302b94a6b50f58147e481db8 data/create/advancements/recipes/misc/crafting/kinetics/train_trapdoor.json +77f181550c780925243cc268d29aceebfba52915 data/create/advancements/recipes/misc/crafting/kinetics/train_door.json +d74de1be1e383c3d5814bd7e42cc0a60ea75e30e data/create/advancements/recipes/misc/crafting/kinetics/train_trapdoor.json 3fa26c6b2a5ef120aa47b35f7d9eb06fec090149 data/create/advancements/recipes/misc/crafting/kinetics/turntable.json babadcfb9adc3527e03e8f8db57a34cacfffa6a5 data/create/advancements/recipes/misc/crafting/kinetics/vertical_gearboxfrom_conversion.json 0fa99ddc934336fb3d40a69a9ed461dba1d6b99e data/create/advancements/recipes/misc/crafting/kinetics/water_wheel.json @@ -141,8 +158,7 @@ ddd41210dfa2d30b3872c9798b677746bc4e5426 data/create/advancements/recipes/misc/c e7820ca532f075b43b4fea791ad64ab290f25bdc data/create/advancements/recipes/misc/crafting/logistics/andesite_tunnel.json 79e47eb39470f604b3f26ef8af82d3e64611514e data/create/advancements/recipes/misc/crafting/logistics/brass_funnel.json 756a724f71c5946017b6718eb93bff7fe73d4f7f data/create/advancements/recipes/misc/crafting/logistics/brass_tunnel.json -e136998b146cfdf213fd658012d38bf32aeedbd7 data/create/advancements/recipes/misc/crafting/logistics/content_observer.json -cfe99716b3f963dc05675fcc0eb2b26c24269702 data/create/advancements/recipes/misc/crafting/logistics/content_observerfrom_conversion.json +2302e30a226162adb98fccc9e0916203e6744aab data/create/advancements/recipes/misc/crafting/logistics/content_observer.json f1e6f8e73156edebafe619144e82e01c0b5ec93e data/create/advancements/recipes/misc/crafting/logistics/display_link.json f33284d7166e5c6e3adf1b6dca662eb97636b939 data/create/advancements/recipes/misc/crafting/logistics/powered_latch.json 06a42ee83527fdceb7d870b0e4a67245453a2c34 data/create/advancements/recipes/misc/crafting/logistics/powered_toggle_latch.json @@ -150,8 +166,10 @@ f33284d7166e5c6e3adf1b6dca662eb97636b939 data/create/advancements/recipes/misc/c c7c6ca10962f5e42da5319841fbf2866cca30dd3 data/create/advancements/recipes/misc/crafting/logistics/pulse_repeater.json 52ad675c3aaee020376264f9580fcadf12655b21 data/create/advancements/recipes/misc/crafting/logistics/redstone_contact.json 9d7e5cf97bb11473b78d390e936792d9d3c1c276 data/create/advancements/recipes/misc/crafting/logistics/redstone_link.json -cfdfecd3a25123805f5e1cd7930c15d1fecd2270 data/create/advancements/recipes/misc/crafting/logistics/stockpile_switchfrom_conversion.json +a057a1729592691b40f4f1f909d9109565deb28f data/create/advancements/recipes/misc/crafting/logistics/stockpile_switch.json b350925f30c7309038c7f33ee81bda6ada6c4794 data/create/advancements/recipes/misc/crafting/materials/andesite_alloy.json +6d547e7c3dad06dd4d3ff64d0aac380683d26a11 data/create/advancements/recipes/misc/crafting/materials/andesite_alloy_block.json +4efa2e6c87e853fee8e9c1a3bc4924add974c35e data/create/advancements/recipes/misc/crafting/materials/andesite_alloy_from_block.json 58b40049eee5cce2c5d49a0add95732eb49098d0 data/create/advancements/recipes/misc/crafting/materials/andesite_alloy_from_zinc.json e35662919f851ca1c27b56cf71e61cce611a00d7 data/create/advancements/recipes/misc/crafting/materials/brass_block_from_compacting.json e8db20956f6bbf0a895e3d790672ae52d198fc7a data/create/advancements/recipes/misc/crafting/materials/brass_ingot_from_compacting.json @@ -160,6 +178,8 @@ d2823e614d4a333f725d3dce3e543f047f3adbcb data/create/advancements/recipes/misc/c 1c4b5bceed1aed2f09c4544cefe71fae4d1fc1bb data/create/advancements/recipes/misc/crafting/materials/copper_ingot.json f7207947160f3aa549e953bc95e3a64d13bc974c data/create/advancements/recipes/misc/crafting/materials/copper_nugget.json 2da087da9ad33e060e8122e260474d5a2ca3575c data/create/advancements/recipes/misc/crafting/materials/electron_tube.json +80edd0fbd082a4b75814f812c635733295206549 data/create/advancements/recipes/misc/crafting/materials/experience_block.json +494ff67507741956a0f02f73f341b192c66a92f4 data/create/advancements/recipes/misc/crafting/materials/experience_nugget_from_block.json 43333df116133be43c8c164ddd611e2f74e5e540 data/create/advancements/recipes/misc/crafting/materials/raw_zinc.json 2d34f50774357f9ac8a4ae2e23fb668757e09daa data/create/advancements/recipes/misc/crafting/materials/raw_zinc_block.json e59ad68feb5898d04394970ba9d57566b9c19d7e data/create/advancements/recipes/misc/crafting/materials/red_sand_paper.json @@ -177,7 +197,7 @@ ce2986087f7be38db504c202876c8a3c2c885555 data/create/advancements/recipes/misc/c 8379bfe85932f3681f4a59061a1c76192c565c3c data/create/advancements/recipes/misc/crafting/schematics/schematic_and_quill.json ae2e2c9a612d818eab78f140799159fbc5ec0159 data/create/advancements/recipes/misc/crafting/schematics/schematic_table.json 745addcb7d24943c9aa05f16ae1e3d645425093f data/create/advancements/recipes/misc/smelting/bread.json -22506522c5debb2db0f9dc6df6094aadcc0a3aa1 data/create/advancements/recipes/misc/smelting/copper_ingot_from_crushed.json +646003d927eed232ebfd817fe5af533f55ca5e17 data/create/advancements/recipes/misc/smelting/copper_ingot_from_crushed.json f0570274cf54c73b95d9665ea17432b63b2da525 data/create/advancements/recipes/misc/smelting/glass_from_framed_glass.json 7c5a7a087bc6644b0944fd37211d4e69a863a8c2 data/create/advancements/recipes/misc/smelting/glass_from_horizontal_framed_glass.json e83398ba06339e3bd559b839c725de4f7535be5e data/create/advancements/recipes/misc/smelting/glass_from_tiled_glass.json @@ -186,52 +206,63 @@ e83398ba06339e3bd559b839c725de4f7535be5e data/create/advancements/recipes/misc/s 21eeaaa865c069d49dfb85161ea26065f949572c data/create/advancements/recipes/misc/smelting/glass_pane_from_horizontal_framed_glass_pane.json 203c4a4e8fc1959c2e119f26d13f18db803aed06 data/create/advancements/recipes/misc/smelting/glass_pane_from_tiled_glass_pane.json 6bdcc8384564f207c22d4240b341c8ec31188a6d data/create/advancements/recipes/misc/smelting/glass_pane_from_vertical_framed_glass_pane.json -57ac07b3fb4e1213b02eb81ff914be19e53ae174 data/create/advancements/recipes/misc/smelting/gold_ingot_from_crushed.json -dcdb226aa6c01e980167875165b728b108a17e16 data/create/advancements/recipes/misc/smelting/ingot_aluminum_compat_immersiveengineering.json -584fd95f54abebf25128b2fcbe74e40bde27e754 data/create/advancements/recipes/misc/smelting/ingot_lead_compat_immersiveengineering.json -482afbd502aa06474485c7d72dd61d88cef071b0 data/create/advancements/recipes/misc/smelting/ingot_lead_compat_mekanism.json -ddbe38ae24f3acb73f1245b6c85fcc4f84072b70 data/create/advancements/recipes/misc/smelting/ingot_nickel_compat_immersiveengineering.json -4f599f5d0b8161efe5bf80d4a20868b8221f0880 data/create/advancements/recipes/misc/smelting/ingot_osmium_compat_mekanism.json -62cb2511311b46230aaaf01edf078623c4537f3a data/create/advancements/recipes/misc/smelting/ingot_silver_compat_immersiveengineering.json -4f2073e10a7aa2fc04c98af87f2f75ddee299f63 data/create/advancements/recipes/misc/smelting/ingot_tin_compat_mekanism.json -1019b83a4a49d6f4012ee7b684c96e70a85505a2 data/create/advancements/recipes/misc/smelting/ingot_uranium_compat_immersiveengineering.json -aed63497f7722be9f5076627820e02abfb5f2197 data/create/advancements/recipes/misc/smelting/ingot_uranium_compat_mekanism.json -adf07902937c70d3e19fbaf1bdfa368e1ce4b8bf data/create/advancements/recipes/misc/smelting/iron_ingot_from_crushed.json -ebc50e0c5b1e8ad8ac78f312aba6fd191352ad87 data/create/advancements/recipes/misc/smelting/lead_ingot_compat_thermal.json -9b8d60765a963debcd4cc4f8955523b79736ae27 data/create/advancements/recipes/misc/smelting/nickel_ingot_compat_thermal.json +09f0bef676bc7635fab11f670aa422c8c3f3f1d5 data/create/advancements/recipes/misc/smelting/gold_ingot_from_crushed.json +cf1480247e325842aca707d2cfd1ce58aa922f30 data/create/advancements/recipes/misc/smelting/ingot_aluminum_compat_immersiveengineering.json +fe585f32461cd784fda4832d727985a0e20e7cb3 data/create/advancements/recipes/misc/smelting/ingot_lead_compat_immersiveengineering.json +847d5dc5141fd0cea5763466c092507771909054 data/create/advancements/recipes/misc/smelting/ingot_lead_compat_mekanism.json +9f25d73ad5aa1ee47a58ad25232a24399ed8c370 data/create/advancements/recipes/misc/smelting/ingot_nickel_compat_immersiveengineering.json +a3366fc5504f42470bee56fb77255041c7f036a6 data/create/advancements/recipes/misc/smelting/ingot_osmium_compat_mekanism.json +ac28e15859e2e918342bc7498ca27debadcb8886 data/create/advancements/recipes/misc/smelting/ingot_silver_compat_immersiveengineering.json +3b0ce9691e7b9606d81d4cab6a60e37a39de1352 data/create/advancements/recipes/misc/smelting/ingot_tin_compat_mekanism.json +e8b886a019146ac897e7bd8f606c403c02ae7608 data/create/advancements/recipes/misc/smelting/ingot_uranium_compat_immersiveengineering.json +40ad78682d7ca04d714cb47253f0edd90c566ad9 data/create/advancements/recipes/misc/smelting/ingot_uranium_compat_mekanism.json +5cc981625fae8340071022b8a27babb36e51eecf data/create/advancements/recipes/misc/smelting/iron_ingot_from_crushed.json +83e01b2c6edfd14f2c5f8eb786819da27dbf9780 data/create/advancements/recipes/misc/smelting/lead_ingot_compat_thermal.json +824767e900b6cd06bc84a2a9d1ddfc3a8d687e82 data/create/advancements/recipes/misc/smelting/nickel_ingot_compat_thermal.json de7e685c1d81e32d50bfe0445ff5062faff7cbc5 data/create/advancements/recipes/misc/smelting/scoria.json -8487c9879fc1e3ff9c10e4d590810c0dc752ebbd data/create/advancements/recipes/misc/smelting/silver_ingot_compat_thermal.json -cecd6d02b0d0a2c6be92a8c7bbc60cf8fa45b9b9 data/create/advancements/recipes/misc/smelting/tin_ingot_compat_thermal.json -b3e591920caf8a45511cdfa73a24ece466bd019d data/create/advancements/recipes/misc/smelting/zinc_ingot_from_crushed.json +170d4d6ecd99d99e1d670e206c908cc988b72d01 data/create/advancements/recipes/misc/smelting/silver_ingot_compat_thermal.json +a1be6232f3d3a4b02ff9417c2cb5203d228206be data/create/advancements/recipes/misc/smelting/tin_ingot_compat_thermal.json +2181cb41ab36db7d73514cfb80feb5b5ec67f56a data/create/advancements/recipes/misc/smelting/zinc_ingot_from_crushed.json de8a70a51962a8a79c67cc8d71d9855b7ec68f12 data/create/advancements/recipes/misc/smelting/zinc_ingot_from_ore.json d4b80705766e648ca07c682ef53c5e7a8b5011bb data/create/advancements/recipes/misc/smelting/zinc_ingot_from_raw_ore.json d4012346e139ef643ac4c83713cbe6b5a5beac8a data/create/advancements/recipes/misc/smoking/bread.json -f4fbf94fb4cff3cb2b5f891c925e97803212e659 data/create/recipes/blasting/copper_ingot_from_crushed.json -0204175fa2417ecc4c0d3008e5af735e83ba159b data/create/recipes/blasting/gold_ingot_from_crushed.json -5f38bbe183c388bec5767e64f413cdb3a4f6d5f0 data/create/recipes/blasting/ingot_aluminum_compat_immersiveengineering.json -772c6deea3596fabdda73a8e0f779c3e0f0e8d44 data/create/recipes/blasting/ingot_lead_compat_immersiveengineering.json -4df0d2a341e88621ce88576d5c85aec6e6d8a9dd data/create/recipes/blasting/ingot_lead_compat_mekanism.json -9213d08929951057dbb244894183707b568f3432 data/create/recipes/blasting/ingot_nickel_compat_immersiveengineering.json -8fbb8f4ee8fcde4c6939e058911d2fb618419545 data/create/recipes/blasting/ingot_osmium_compat_mekanism.json -98ea5ca3b8fa4eb5d3ab2c25287cdf0fcd7ab07a data/create/recipes/blasting/ingot_silver_compat_immersiveengineering.json -024dfe1aec58ee4634ca04882f175dd5e6cd9f84 data/create/recipes/blasting/ingot_tin_compat_mekanism.json -e88a2849429422246ee89e3312fff3c4e10ec4cb data/create/recipes/blasting/ingot_uranium_compat_immersiveengineering.json -cd8f253f558ac43c4c764ce31203a2bb37f31ce7 data/create/recipes/blasting/ingot_uranium_compat_mekanism.json -59b8ee48115f36700694e0dc6ed67bbf6b6e0d31 data/create/recipes/blasting/iron_ingot_from_crushed.json -5ed42ce02ffa99acc016cd8bb5d44bbc0d5c6714 data/create/recipes/blasting/lead_ingot_compat_thermal.json -5f8bdb79a4b01203dbd8d50489971d1e5882796a data/create/recipes/blasting/nickel_ingot_compat_thermal.json -56846604ac74c1301a4e4bd9bad9e534d92583a5 data/create/recipes/blasting/silver_ingot_compat_thermal.json -e753a9763ae68db84ec0eb518b3c87e149ab2f4a data/create/recipes/blasting/tin_ingot_compat_thermal.json -bc5ecfd79ebc59a7b89c2371dd2d2354831eeadc data/create/recipes/blasting/zinc_ingot_from_crushed.json +3c9dcf347eef42d0cca69ae5bc4a61fe90fb27c8 data/create/recipes/blasting/copper_ingot_from_crushed.json +cbd86c583643e65a0d9b7950dcf593cdf6d43d77 data/create/recipes/blasting/gold_ingot_from_crushed.json +5b1b7981636b211a956e37356423c2ba65c8042c data/create/recipes/blasting/ingot_aluminum_compat_immersiveengineering.json +f794d2eab3922ea7765866d473eb61c74a2678c5 data/create/recipes/blasting/ingot_lead_compat_immersiveengineering.json +7acb7c5bc88b238e914abc07f979c33f8d33123e data/create/recipes/blasting/ingot_lead_compat_mekanism.json +79ad6f95b7f4c75cc0c3fadcf8e16be077bd5874 data/create/recipes/blasting/ingot_nickel_compat_immersiveengineering.json +f403ea128ab6c8bc3e4c4b660bea3d8edb8c8c30 data/create/recipes/blasting/ingot_osmium_compat_mekanism.json +2010401b8c4225226fb213375ba9d3b1ee8a451b data/create/recipes/blasting/ingot_silver_compat_immersiveengineering.json +b979e859e631de8d229f08b0924d37212c7d92ee data/create/recipes/blasting/ingot_tin_compat_mekanism.json +011179ff485992666fdad594d7daa050e44844c7 data/create/recipes/blasting/ingot_uranium_compat_immersiveengineering.json +0f6e3a23e0e1bb6bac077fac2b9cfcf50f3459f1 data/create/recipes/blasting/ingot_uranium_compat_mekanism.json +19d33cb473f7ba1065a7747700248cd8d6738732 data/create/recipes/blasting/iron_ingot_from_crushed.json +701da66616d4d9c3293e410af5e0dd764c9f63e1 data/create/recipes/blasting/lead_ingot_compat_thermal.json +6a10c8bb0b2a939edd79f159ec5acb9b137283c3 data/create/recipes/blasting/nickel_ingot_compat_thermal.json +e1481cbde99b04ce08c7fffdbd24233eb3bb8d0d data/create/recipes/blasting/silver_ingot_compat_thermal.json +150e9b6eaab4b98a326d915bbfe33fcdb95e2beb data/create/recipes/blasting/tin_ingot_compat_thermal.json +b3c4585dc6ed9c4a38d7923ae399b88ab8912df9 data/create/recipes/blasting/zinc_ingot_from_crushed.json 118d41c4194877ae9fffc3a72aae4bec0e9b3b57 data/create/recipes/blasting/zinc_ingot_from_ore.json 7b561a6fc65b9cede6dac0aa9122408ea49767df data/create/recipes/blasting/zinc_ingot_from_raw_ore.json 785636ad3752d7a78059757d7ba21118be2a3289 data/create/recipes/campfire_cooking/bread.json +208487a2d020c2603391f55e815a39a28f8fd9e8 data/create/recipes/crafting/appliances/attribute_filter_clear.json +1927ac4ead139184bcd738ad6157014b61bb449a data/create/recipes/crafting/appliances/clipboard.json +28d1dabd689b855964151100a80247b2ea150bd4 data/create/recipes/crafting/appliances/clipboard_clear.json 63ce275f197c13362df4f2d92a3a504162697f04 data/create/recipes/crafting/appliances/copper_backtank.json +57a7918bd764deb069a1e472707898cdc69fbc27 data/create/recipes/crafting/appliances/copper_diving_boots.json +cc987f4537e7bc1aa09329efc1c0ac9fd47f0928 data/create/recipes/crafting/appliances/copper_diving_helmet.json 3e3f71d579ec7453e453d5b65aaee3c43169b679 data/create/recipes/crafting/appliances/crafting_blueprint.json -a8fb85cae1869dc33a7ea0866062d9001fa1d1dd data/create/recipes/crafting/appliances/diving_boots.json -377fb6c00695dd9ad964af23382bb3bd13c0b2a5 data/create/recipes/crafting/appliances/diving_helmet.json b7c8f3c5e80749c6c38d5c0153dc68a79c32535f data/create/recipes/crafting/appliances/dough.json +409b5d70ee1ef9164c327d79472e6d66ce55dec6 data/create/recipes/crafting/appliances/filter_clear.json 2b936b4c2a10cba937bb59b1d521e21e26c9a622 data/create/recipes/crafting/appliances/linked_controller.json +d948285dc2344dbada3957be890d4cb75f686697 data/create/recipes/crafting/appliances/netherite_backtank.json +d4ed98d873a9eb8faf7c01e7cd0e9bf5b635488d data/create/recipes/crafting/appliances/netherite_backtank_from_netherite.json +f3f8b62e37fd29bd54bbb1ae325b2b1b17f2b197 data/create/recipes/crafting/appliances/netherite_diving_boots.json +ac0debc34634635a6ea2f75230f70f35ceebf5ef data/create/recipes/crafting/appliances/netherite_diving_boots_from_netherite.json +ab4f1cd6c051866a2d1994c7cbae48a0938a16a1 data/create/recipes/crafting/appliances/netherite_diving_helmet.json +afd744ca1c860754f2e44a490638c3389d3f7522 data/create/recipes/crafting/appliances/netherite_diving_helmet_from_netherite.json +0b83c52c90948141e5807b7d1243fb5d48d4c998 data/create/recipes/crafting/appliances/schedule_clear.json 05e4700f7fd59029ba19bcfb7b49fd3a30a93cad data/create/recipes/crafting/appliances/slime_ball.json d0bad974476c54315e4b656c67dbf6165d183bbc data/create/recipes/crafting/appliances/tree_fertilizer.json c67be8fc9582407c28cf9d986a285922391d27c0 data/create/recipes/crafting/curiosities/brown_toolbox.json @@ -241,18 +272,21 @@ c67be8fc9582407c28cf9d986a285922391d27c0 data/create/recipes/crafting/curiositie e54646485af774e490409e9912a3799f7ac44e01 data/create/recipes/crafting/curiosities/toolbox_dyeing.json 615dad758fc75a2ee5ac8ec95559b0cd1f3cdeb0 data/create/recipes/crafting/kinetics/adjustable_chain_gearshift.json 65ff999ecb6b8d1dc0db2ed45cfef7f9c2af2f19 data/create/recipes/crafting/kinetics/analog_lever.json -902f05d2387484e1cdfa97379b5a3e3de4127834 data/create/recipes/crafting/kinetics/andesite_ladder.json +ea6479a3cb257bfe0bfaac380973ed068195620e data/create/recipes/crafting/kinetics/andesite_door.json acee0e84ae44d80d518ac501a4eb6a24321301ac data/create/recipes/crafting/kinetics/attribute_filter.json 17f8ee497cbd07aeb5bda1add044bbf225aea74e data/create/recipes/crafting/kinetics/basin.json 1d02b28910ddfa9392a76607d09b70fa22c3aa38 data/create/recipes/crafting/kinetics/belt_connector.json +989bd8580e18c716d588fbf3cf863ea238fffee8 data/create/recipes/crafting/kinetics/brass_door.json f6d679d1c1e2d4821e6d4df865ded2685da95e14 data/create/recipes/crafting/kinetics/brass_hand.json 3eb1ffa720e02751fe17e13dd7a7b924b1dd7c96 data/create/recipes/crafting/kinetics/cart_assembler.json 6db1db57162b904b1019c6b12898dafa8ae87f8a data/create/recipes/crafting/kinetics/chute.json ff4a44c1fd7b1e8a412d66f4e546730a557b4ffc data/create/recipes/crafting/kinetics/clockwork_bearing.json de55cc506471580096b73c66e14d0d1de2c01f11 data/create/recipes/crafting/kinetics/clutch.json e5b87cc750175d18a636fa249511ccd3b05534a4 data/create/recipes/crafting/kinetics/cogwheel.json +d6d3d9fcd6c6e49419ab19e5534a4986d7cebe4d data/create/recipes/crafting/kinetics/contraption_controls.json 284762906c2165df0d58b09e39cfe37397c4a987 data/create/recipes/crafting/kinetics/controller_rail.json 6c076ba6d174ca172a6327b2a12fd58600fa3f87 data/create/recipes/crafting/kinetics/controls.json +a427bb8d8a43ac01def064584ea48a76d4deffa5 data/create/recipes/crafting/kinetics/copper_door.json 25c459953c65726d973d45a220ba7564a8634ee0 data/create/recipes/crafting/kinetics/copper_valve_handle.json 0a27cbe56b973276519c605acbb923f5e1aaba3d data/create/recipes/crafting/kinetics/copper_valve_handle_from_others.json d88329a4ab785ffd68a5712dbc4f8c8f5f326895 data/create/recipes/crafting/kinetics/crafter_slot_cover.json @@ -260,6 +294,7 @@ d88329a4ab785ffd68a5712dbc4f8c8f5f326895 data/create/recipes/crafting/kinetics/c 7bcdac3527644ea161f31c6c3fd598a6fed87b27 data/create/recipes/crafting/kinetics/deployer.json ae909affec7808069c7eaecfcfc7736fb9c01504 data/create/recipes/crafting/kinetics/depot.json 974c7af7855fbc5ee1d3073127a3b605f5583e59 data/create/recipes/crafting/kinetics/display_board.json +82527bf5bca40f439fc2bca0e44059ff43e5f917 data/create/recipes/crafting/kinetics/elevator_pulley.json f86feea39cb895d9f95de3bbbc127c4dcf11e6a7 data/create/recipes/crafting/kinetics/empty_blaze_burner.json ca3e3063cdf135426e28d3474b5289ba1c5d9a1d data/create/recipes/crafting/kinetics/encased_chain_drive.json de3644be09c6777e3625d6801f95aa2fca9149d6 data/create/recipes/crafting/kinetics/encased_fan.json @@ -283,7 +318,8 @@ a98b568daee4051397176d2fa2b6b2992b412a52 data/create/recipes/crafting/kinetics/g 470b13a8576a49ee28f59b09587b47c682a136b6 data/create/recipes/crafting/kinetics/item_drain.json 167d9e4451fb75cb044ae8ba3318f9e661c1a3e6 data/create/recipes/crafting/kinetics/item_vault.json ef525f4a19bc17fdfdd73c1e7ad65da0c8423b59 data/create/recipes/crafting/kinetics/large_cogwheel.json -04a9cd133f7e1f88a35653ea205bb5a7e63cbecd data/create/recipes/crafting/kinetics/large_cogwheelfrom_little.json +04a9cd133f7e1f88a35653ea205bb5a7e63cbecd data/create/recipes/crafting/kinetics/large_cogwheel_from_little.json +10e51281adf4b0b9708aa9305957e54c3c6df5e4 data/create/recipes/crafting/kinetics/large_water_wheel.json d5e05b12979fc3222cbbdba73f1a34ff033350d2 data/create/recipes/crafting/kinetics/linear_chassis.json 27944146a510a98193140b5bed5feef2c05c8014 data/create/recipes/crafting/kinetics/linear_chassisfrom_conversion.json 2559411020ef1da9b81681c223d056734d48f011 data/create/recipes/crafting/kinetics/mechanical_arm.json @@ -296,6 +332,7 @@ f7a1611e3c18009ff0cafb516bed8b10cb237672 data/create/recipes/crafting/kinetics/m d772cc5717a73ecc5a16ecea1d4252171ad79015 data/create/recipes/crafting/kinetics/mechanical_plough.json 7b27690c7b5eaeab2435fb960f5e4346e9550f09 data/create/recipes/crafting/kinetics/mechanical_press.json 613ec51032193322ef3f04679bafa95999f6cd77 data/create/recipes/crafting/kinetics/mechanical_pump.json +b9405f5b0b21c60943df6779782491e9d93da0a2 data/create/recipes/crafting/kinetics/mechanical_roller.json a3fe69c02e99c04140b23acfa1418b2cbf35e8eb data/create/recipes/crafting/kinetics/mechanical_saw.json 2a007f25fefffff0c61b2c1ec26ae5e2df29c946 data/create/recipes/crafting/kinetics/metal_bracket.json 216d9a733c84e4b41a81d07cccd2e77d1fcbf342 data/create/recipes/crafting/kinetics/metal_girder.json @@ -333,11 +370,11 @@ ae836d3103b16bb7084109c4d25295f0a3bc6f7c data/create/recipes/crafting/kinetics/t 1747771e1eb570c0cfdc97681d8b9d0ccb1db73d data/create/recipes/crafting/kinetics/track_observer_from_other_plates.json af645fe446e0df755fb748383a51facbe9101ede data/create/recipes/crafting/kinetics/track_signal.json 19c3a19c824e283c73400ed6abf5e5b1bfce147c data/create/recipes/crafting/kinetics/track_station.json -04310e7ae51ff0dab56854c4ef997de2a3896f90 data/create/recipes/crafting/kinetics/train_door.json -88d0e6b9058362b4cf5f74e3e1aafe015f339bd2 data/create/recipes/crafting/kinetics/train_trapdoor.json +35037a92ef619eea8c02fe21c1ab3fa567e9fb72 data/create/recipes/crafting/kinetics/train_door.json +26d9401533332cbc7580b32b45cdebf6ad3c523d data/create/recipes/crafting/kinetics/train_trapdoor.json dc79cdf805cb558f5dd2c1eab3348473f782894e data/create/recipes/crafting/kinetics/turntable.json 613d2ef5c381445d9a0bb1020f9d0ab9fb04d766 data/create/recipes/crafting/kinetics/vertical_gearboxfrom_conversion.json -808c7a0072dd7257e7f28039efa62ae13a333e0d data/create/recipes/crafting/kinetics/water_wheel.json +3d92c4ef6f0865ba93747cfad20555b28cb565c1 data/create/recipes/crafting/kinetics/water_wheel.json a9ba7f4d1d66262fc76882c8460066a480ea379f data/create/recipes/crafting/kinetics/weighted_ejector.json 872cb53542b4306898c6e0a9311b39281a8e0052 data/create/recipes/crafting/kinetics/whisk.json f47038671182cec56ca8d9e2d7a7487bb5547b6f data/create/recipes/crafting/kinetics/white_sail.json @@ -349,8 +386,7 @@ f5f0753ba8be9d1bbc2858f60feb00d8ba699550 data/create/recipes/crafting/logistics/ 945085538d9bd3cbc394afb94c35c3181933acd1 data/create/recipes/crafting/logistics/andesite_tunnel.json 37154b49468fecd9a0a8d6fc651b943def186bcc data/create/recipes/crafting/logistics/brass_funnel.json e8d3a2fd4eacdc58b53473f92df67aeab4f9eb2d data/create/recipes/crafting/logistics/brass_tunnel.json -d1552f0a955d27b1c7d7c4ba256b53ee702e44d5 data/create/recipes/crafting/logistics/content_observer.json -dc670e2fcdaa4a8ad5b70472c83fc9b30024f989 data/create/recipes/crafting/logistics/content_observerfrom_conversion.json +e888c1127dbd88c7a37820c00d6a52425a7e4fd3 data/create/recipes/crafting/logistics/content_observer.json 6678d80f36947f4f445660f65b91ce3fd3adbf83 data/create/recipes/crafting/logistics/display_link.json f6172d7e7b56a78e07e3a94c1e345ae4099362c4 data/create/recipes/crafting/logistics/powered_latch.json 4b891ab016f70926edacbcd500e866b0b4bae9d9 data/create/recipes/crafting/logistics/powered_toggle_latch.json @@ -358,8 +394,10 @@ f6172d7e7b56a78e07e3a94c1e345ae4099362c4 data/create/recipes/crafting/logistics/ 8e464f6f2602773d558522bee425a101e5f67b0d data/create/recipes/crafting/logistics/pulse_repeater.json 77b8751f244ef02ca94622094022840e04c8737e data/create/recipes/crafting/logistics/redstone_contact.json f3cf47f83b7d2034112b34d121d8f925de14de50 data/create/recipes/crafting/logistics/redstone_link.json -29b76e32bcef9cc08e7aaf8cb71d1e81abd5f848 data/create/recipes/crafting/logistics/stockpile_switchfrom_conversion.json +00ef81e53c9e71ac14699428d949ab3cdcc2da8a data/create/recipes/crafting/logistics/stockpile_switch.json 09fae6a8ac1b829984a5335035b6556e5c088565 data/create/recipes/crafting/materials/andesite_alloy.json +8dd677dd25b79c2522c6ebec5ef2a6ad65801523 data/create/recipes/crafting/materials/andesite_alloy_block.json +eebacb477bcce876622173289b06e1ad21424686 data/create/recipes/crafting/materials/andesite_alloy_from_block.json 0b446155e261a62582cc57bbdcac1c30b6780d80 data/create/recipes/crafting/materials/andesite_alloy_from_zinc.json e6cd84bf8d6cc055617b478e420303c283d6b97b data/create/recipes/crafting/materials/brass_block_from_compacting.json 177daa1a87adeae33766441fe6d7979a227a646b data/create/recipes/crafting/materials/brass_ingot_from_compacting.json @@ -368,6 +406,8 @@ fe2f3c0722aa0f6b41ad0f497b9742eb856c0dd0 data/create/recipes/crafting/materials/ 70a9b32abcf0a016d07f34d4f5f170002abfbfec data/create/recipes/crafting/materials/copper_ingot.json 9e6e356f4c6b7f018d98b1da1911ea6c5fea3df7 data/create/recipes/crafting/materials/copper_nugget.json 9d91ae29c01af372cb1efa9087509c47a08862fe data/create/recipes/crafting/materials/electron_tube.json +04e48b9eace97606d3655142e1a2e1eb1f85ce7f data/create/recipes/crafting/materials/experience_block.json +bc0a0b576a8895c5e31374cd3e6f9f2c8e20d542 data/create/recipes/crafting/materials/experience_nugget_from_block.json 33cf710546277f3d41af2c2aa736e031f3e37e60 data/create/recipes/crafting/materials/raw_zinc.json 280a1bb2f70a51eac5caadae10c76645afb4af3d data/create/recipes/crafting/materials/raw_zinc_block.json 388654485ad957c58c4d6019273a85cebd468cca data/create/recipes/crafting/materials/red_sand_paper.json @@ -385,7 +425,7 @@ f37ec44b48d033c7fd824e7c5f97ef3142d3b431 data/create/recipes/crafting/schematics 4a20356c9ce01ebfbcacbdc5d3c31094a5599a17 data/create/recipes/crafting/schematics/schematic_and_quill.json daffe186a09183ec1c36aa0e45f9478841a991ce data/create/recipes/crafting/schematics/schematic_table.json 78526658ca5ccaa3729c967b5283069945d183b7 data/create/recipes/smelting/bread.json -b680733ed103c41e6d86951180ce0d47b6f57def data/create/recipes/smelting/copper_ingot_from_crushed.json +04bb0c80f3b5a6fe86fc4a8ed5293fc74c2d9aba data/create/recipes/smelting/copper_ingot_from_crushed.json d5b29fa27977691c3c50eb36c28bfe33b8462d09 data/create/recipes/smelting/glass_from_framed_glass.json 83f03ab4b1ca000ad7fe15c347ea10b728188e57 data/create/recipes/smelting/glass_from_horizontal_framed_glass.json e4d3381d9c063adb3d6c7fa6a684100bc23f45ef data/create/recipes/smelting/glass_from_tiled_glass.json @@ -394,23 +434,23 @@ ab1a181eb787f501ae7b8a8c6da2d3adb35a8f2b data/create/recipes/smelting/glass_pane 1f3432f66d6557e2835457e4dc97ae7561074e79 data/create/recipes/smelting/glass_pane_from_horizontal_framed_glass_pane.json ad412d18c2084dc74fff8a079a2e7ffb20f9a0c6 data/create/recipes/smelting/glass_pane_from_tiled_glass_pane.json 67c1143c7aac88a9cc91b98dbca60770cb1422a5 data/create/recipes/smelting/glass_pane_from_vertical_framed_glass_pane.json -854b1a30fa63eb98dda8dae5f32dd813a9b762a5 data/create/recipes/smelting/gold_ingot_from_crushed.json -d65efcb3f00c650cb791b7a5e108742aeb98fd17 data/create/recipes/smelting/ingot_aluminum_compat_immersiveengineering.json -d923f8238402fabb2b1bc76648bf71c02f1386db data/create/recipes/smelting/ingot_lead_compat_immersiveengineering.json -10e7b260612f9a54b55155d9d2f7d6a06c517567 data/create/recipes/smelting/ingot_lead_compat_mekanism.json -8a2762cc6a55bb1b7e66ed1a9f44e7e33eb5b3c5 data/create/recipes/smelting/ingot_nickel_compat_immersiveengineering.json -c32653462f5147d66d4f22172627999907e0eff7 data/create/recipes/smelting/ingot_osmium_compat_mekanism.json -e253130c1ab4f70182a08e442f27a69a063fb8a8 data/create/recipes/smelting/ingot_silver_compat_immersiveengineering.json -a158704d7426e5354f9d051d9f2ba15f62d39424 data/create/recipes/smelting/ingot_tin_compat_mekanism.json -e9ebe868222a479e40f5e2da40ddbab556eebad5 data/create/recipes/smelting/ingot_uranium_compat_immersiveengineering.json -ce6f69eee942babbfacc9b8cae334284291efaf6 data/create/recipes/smelting/ingot_uranium_compat_mekanism.json -c72008edd68fe2fb49e0dbf117f851e9224d343d data/create/recipes/smelting/iron_ingot_from_crushed.json -27b06c3d51bb3f06370dc94e2f71fe7f158527d8 data/create/recipes/smelting/lead_ingot_compat_thermal.json -3e2962b789f59e56277946a862fe219f7b31e4c9 data/create/recipes/smelting/nickel_ingot_compat_thermal.json +461e4dede50a4a318281ae9c086c8094470e21a1 data/create/recipes/smelting/gold_ingot_from_crushed.json +fa0d3d6f50d344aa83ddf4ac8abf4a80deb9fb32 data/create/recipes/smelting/ingot_aluminum_compat_immersiveengineering.json +4e8cf8775719219849b1a0e95903a3605b665015 data/create/recipes/smelting/ingot_lead_compat_immersiveengineering.json +cfa90e7ba56d1ec6caa11bd019244bddd51da841 data/create/recipes/smelting/ingot_lead_compat_mekanism.json +921031330fc9d1d5cf8293d7863145d9b7c8becf data/create/recipes/smelting/ingot_nickel_compat_immersiveengineering.json +e718631b4ac8e8bb036435dd2b39c0ce77fa290d data/create/recipes/smelting/ingot_osmium_compat_mekanism.json +ba80d1df860afa164dfba71ee3f16438f288b6aa data/create/recipes/smelting/ingot_silver_compat_immersiveengineering.json +9f8472e42fc3b1db65cbf5c878f4788846cf88b6 data/create/recipes/smelting/ingot_tin_compat_mekanism.json +b7830b774bfab54957b55c8ddc414b2427a49191 data/create/recipes/smelting/ingot_uranium_compat_immersiveengineering.json +a7b6ae172fb21be2d2b66da82a603300fae16185 data/create/recipes/smelting/ingot_uranium_compat_mekanism.json +5865b56a6e7dfc486235b635cf5a40e9d82cb79d data/create/recipes/smelting/iron_ingot_from_crushed.json +76336bf2c2f35386a997cbc3125ae423595dd207 data/create/recipes/smelting/lead_ingot_compat_thermal.json +cc1e46b361bffebdf63c970d6f8bf09068e28e5b data/create/recipes/smelting/nickel_ingot_compat_thermal.json 0421f39da684e9cdd35c43d6e7e4706a2438d9d5 data/create/recipes/smelting/scoria.json -a87fa7d568d8c2170e923f97e6e38e3f730c9651 data/create/recipes/smelting/silver_ingot_compat_thermal.json -5446801a833cfa19978f90d71ea5539212a15372 data/create/recipes/smelting/tin_ingot_compat_thermal.json -c2b566d8635545dd3a015a57400711a82db52840 data/create/recipes/smelting/zinc_ingot_from_crushed.json +51d4140efc896d4cf426426101048405fc4243bc data/create/recipes/smelting/silver_ingot_compat_thermal.json +fd994dc211b5da51c440703f3b3e14caa04de562 data/create/recipes/smelting/tin_ingot_compat_thermal.json +8ea35f78211932c11630cb03625b269ef55ef11a data/create/recipes/smelting/zinc_ingot_from_crushed.json 2b7206a2dce9613094ca53cf4653eab178bcb2dc data/create/recipes/smelting/zinc_ingot_from_ore.json 513adf2dca653a48b90a37c905a8da117c0365e7 data/create/recipes/smelting/zinc_ingot_from_raw_ore.json 874cf17060240c3e4e13f95d024b108650716d7d data/create/recipes/smoking/bread.json diff --git a/src/generated/resources/.cache/b256105d8411632b0d585496ea8944a751a08034 b/src/generated/resources/.cache/b256105d8411632b0d585496ea8944a751a08034 index 701d5c57d..9abfa21cb 100644 --- a/src/generated/resources/.cache/b256105d8411632b0d585496ea8944a751a08034 +++ b/src/generated/resources/.cache/b256105d8411632b0d585496ea8944a751a08034 @@ -1,29 +1,29 @@ -// 1.19.3 2023-02-06T18:08:23.2203754 Create's Processing Recipes +// 1.19.3 2023-06-27T03:14:49.7377928 Create's Processing Recipes 3c94326fb730f68c1e44fe1e2ef09c9db6ffd92b data/create/recipes/compacting/andesite_from_flint.json 8d3d5b31f3601b9f681ff710e0545a483a1494c6 data/create/recipes/compacting/blaze_cake.json 8bd7f4e3a686ab520b2d55594d2018d0e9a50c91 data/create/recipes/compacting/chocolate.json 5e2514e027cc0dbad48160e6b8e5bf0f25eba8f0 data/create/recipes/compacting/diorite_from_flint.json 54c94ae8d964dba1de2441088f6a312c687cbf71 data/create/recipes/compacting/granite_from_flint.json c558dddeacf6f8bfa29d74b68093ecfea619d43f data/create/recipes/compacting/honey.json -636b8147ff2f133e473df6fd277f5d0400ea9fbc data/create/recipes/crushing/aluminum_ore.json +e00be6905b6bcf72de937e3fe8bbceee6440a6b1 data/create/recipes/crushing/aluminum_ore.json 60262e911676a7f8309408fd15b373f1498493b9 data/create/recipes/crushing/amethyst_block.json 8e20ddc94fda889dbac25de59e7a3158984098c3 data/create/recipes/crushing/amethyst_cluster.json -c9265011e7953d9edb7d58663bbc608bea0c235a data/create/recipes/crushing/asurine.json -a158bc7f2d3d0a7e15600ac3cd5fc5f636a71119 data/create/recipes/crushing/asurine_recycling.json +419e80e49fc24da0b5c6aa1fbdee1a1dc01960fb data/create/recipes/crushing/asurine.json +c444abdd432670f6a2b508c513302e119cb07186 data/create/recipes/crushing/asurine_recycling.json 66b51fd1036641802667338a1d79a825a338077c data/create/recipes/crushing/blaze_rod.json 29e7e74108755e0a07b1d3d1e8d4dcaf2b401572 data/create/recipes/crushing/coal_ore.json -2c24633f90cd5349b65bd1d132545bafe405d711 data/create/recipes/crushing/copper_ore.json -548215e02e7dbe83d94002bd95e500123eeb4427 data/create/recipes/crushing/crimsite.json -e6bd623592a604751e5559dbc78f964ab1779a86 data/create/recipes/crushing/crimsite_recycling.json +ad91e6a560bdb8ef311862a0fee1f316529ed439 data/create/recipes/crushing/copper_ore.json +0ff7fa09b2ae808bc29c4d87985deccab5de2de5 data/create/recipes/crushing/crimsite.json +50c9a45e77d266852317fa1bac6c17443cfd986c data/create/recipes/crushing/crimsite_recycling.json b6995978092ed3080efd49e52571ff59205f7c85 data/create/recipes/crushing/deepslate_coal_ore.json -bbc5320b1441b6873c48545fa272eecc537e88ab data/create/recipes/crushing/deepslate_copper_ore.json +9aa9bcd71da7ebb25301211426e988e71c9bff97 data/create/recipes/crushing/deepslate_copper_ore.json 4afc9cc723bdee47ed2176f32323f1fca152765f data/create/recipes/crushing/deepslate_diamond_ore.json 94d706cac7779cf8dc3aa8822605a4ee9d0ba047 data/create/recipes/crushing/deepslate_emerald_ore.json -8821dce4f4e5ae2f9f165a16869789987d836a71 data/create/recipes/crushing/deepslate_gold_ore.json -6d4f5d66dff59118515e23ae8434075236da6a5c data/create/recipes/crushing/deepslate_iron_ore.json +9922535a4b41d6af68df94168276abf308ea432c data/create/recipes/crushing/deepslate_gold_ore.json +e266d091252d692dcd0618f34754536fe0aa98b3 data/create/recipes/crushing/deepslate_iron_ore.json 8b721de1578798a8996d2f8dec61b3bc03b8064d data/create/recipes/crushing/deepslate_lapis_ore.json 26365dd1f80ecc859dc510cd5278907d2fa6f2f7 data/create/recipes/crushing/deepslate_redstone_ore.json -4815670dfd6a51ff8b018d95dccbc8bc2f7074d8 data/create/recipes/crushing/deepslate_zinc_ore.json +64688579de20cbc0f4a7e4a589140fbbce408fcf data/create/recipes/crushing/deepslate_zinc_ore.json 69e0a401b424cb82ab3387a0b23bd7241f80f56e data/create/recipes/crushing/diamond_horse_armor.json 35cff9ebc59e837a2beafd2d4ec80e088459344c data/create/recipes/crushing/diamond_ore.json a0511a15499653d983ad8b85b9f763643cca3aca data/create/recipes/crushing/diorite.json @@ -31,61 +31,61 @@ df364151c75a7d84446b2c6213e339115bc9d298 data/create/recipes/crushing/diorite_re 9e89294e53a94a05af47948c21ad192ef18f7710 data/create/recipes/crushing/emerald_ore.json 3c4c78e3a7137022f8f6e90324af6c8f97050e80 data/create/recipes/crushing/glowstone.json 95b76da439260151355fff74b3b7398ce13d6968 data/create/recipes/crushing/golden_horse_armor.json -5134f5386ce39bba41b184ef4ac1d0aa9d6155d7 data/create/recipes/crushing/gold_ore.json +b036b1654d2deec20aca95ff43b60c7d0b28b2fc data/create/recipes/crushing/gold_ore.json cc939ba59b95db1c7a034df6f9e656772074a5fd data/create/recipes/crushing/gravel.json 17ab2d789c9c2df122b6a96ab06bbe2c02592a93 data/create/recipes/crushing/iron_horse_armor.json -cf3a2fc0ff89209f4503f1f5a1a3020e73e8be61 data/create/recipes/crushing/iron_ore.json +c9a47b29ba75ba29c8cb630fe32c4bf2f1f1d1ae data/create/recipes/crushing/iron_ore.json 855b6655dea911724ee68d07b993f17440ac422e data/create/recipes/crushing/lapis_ore.json -06a4b918304db3e72240848fd0c7f6553f86a4f4 data/create/recipes/crushing/lead_ore.json +492827ab3d55ca3edfef5eb006b1f77d62e1b446 data/create/recipes/crushing/lead_ore.json e170bc17a796c73a05d2d77a85c086cfaac55c31 data/create/recipes/crushing/leather_horse_armor.json 4317165fc125d179cfbe66d15ba6368cdf1d7811 data/create/recipes/crushing/netherrack.json 07e8991a2161aab4dd73bb74900fd0c70aad2847 data/create/recipes/crushing/nether_gold_ore.json c7c0d94707c2858a87d01cff6b284d7fb85acdbe data/create/recipes/crushing/nether_quartz_ore.json 0380b9416b263de2ee6a6cd1f4064df2e243c047 data/create/recipes/crushing/nether_wart_block.json -28fbbccacd4ad5dee14c3240a0e29d533061ec4b data/create/recipes/crushing/nickel_ore.json +d3534d606382ec7c1d34275c5f069543d0955906 data/create/recipes/crushing/nickel_ore.json 66f75530e30d8572bdbf4696a32edc5a7850ac00 data/create/recipes/crushing/obsidian.json -fd82103848126334c3dcca9dbb59bd4802c7e1ae data/create/recipes/crushing/ochrum.json -076c3c8f1cfeb13ae0926e0613074c9e90a4e8a2 data/create/recipes/crushing/ochrum_recycling.json -386493bbd6435079a1c7fc88e9d2970fe10e4388 data/create/recipes/crushing/osmium_ore.json -fde0abe21825c231937c4cd5ed08bebd0bef48f6 data/create/recipes/crushing/platinum_ore.json +17cacb19493b9bbe7236b19a2a50a817c449a915 data/create/recipes/crushing/ochrum.json +5db58119de29083c865ef86f824fe7dd15e6507f data/create/recipes/crushing/ochrum_recycling.json +1bcd6676fe2dc3715b7aab0411962c81dd3797ce data/create/recipes/crushing/osmium_ore.json +d391ef171a3ece91ae72697ceba36b71b19f4fae data/create/recipes/crushing/platinum_ore.json acb785fd57d14ac337beacc0a0a0651d75dd45da data/create/recipes/crushing/prismarine_crystals.json -d0b4791661e13d0f2b660e99fc3ddc03e9d8ad35 data/create/recipes/crushing/quicksilver_ore.json -e24db46d1709bf8b36dbcc6bbac19f84a6652349 data/create/recipes/crushing/raw_aluminum_block.json -be8178791bd977ca9f085fe2d3e716bb65314def data/create/recipes/crushing/raw_aluminum_ore.json -e670e09323c301f2246e3f896a2523180e8d3adc data/create/recipes/crushing/raw_copper.json -1bccbf51b1452309a4cd0299bfc6c4aaa9f933c3 data/create/recipes/crushing/raw_copper_block.json -4cc836b7188d4d8e3f01f6df8ae0b3ee74f717c2 data/create/recipes/crushing/raw_gold.json -bb2d461ebe8ea19f7308c89da1042a1822b6f1fc data/create/recipes/crushing/raw_gold_block.json -b207fbee07bc36c8bebaca0384e4ac956fa29c99 data/create/recipes/crushing/raw_iron.json -1b747fad32f8a660c8beb2a7f25da40683f4f562 data/create/recipes/crushing/raw_iron_block.json -cba8acb9c98438a8711a20082a9e02efb9e1a087 data/create/recipes/crushing/raw_lead_block.json -7123b82799c75944e305b961cfcbdfe781a137a0 data/create/recipes/crushing/raw_lead_ore.json -676d32c3d34dcb777a05a1df29f78ea16a573f99 data/create/recipes/crushing/raw_nickel_block.json -f06197145fa972a4fdbe91553f3bd24b6e907193 data/create/recipes/crushing/raw_nickel_ore.json -934dab7a0a7aaaf44c6e309c7dc3ab46bc438212 data/create/recipes/crushing/raw_osmium_block.json -7514b24afa93d6aeee7a89bc87e1ef10c2c784b3 data/create/recipes/crushing/raw_osmium_ore.json -009da27a12e0191ca88c2aebc25380206a25b3ac data/create/recipes/crushing/raw_platinum_block.json -e4be847fe279dd906992020348a5ff2f28dc6be8 data/create/recipes/crushing/raw_platinum_ore.json -c2fdb33f73b63b17bfa24e7018d21b955b1eae85 data/create/recipes/crushing/raw_quicksilver_block.json -847049b925146f2af7cbfddfd24a488e27bf43bf data/create/recipes/crushing/raw_quicksilver_ore.json -e0ca95946955ade59f0ed4272b556facd6e29daa data/create/recipes/crushing/raw_silver_block.json -a6cffb8fa65a55876105295c18bfc8f00317dcec data/create/recipes/crushing/raw_silver_ore.json -d92c7cbaaee6c0d082a50f5b1629d62edd944151 data/create/recipes/crushing/raw_tin_block.json -0ac72f60b0de26b051cdc54243b501640cc4173e data/create/recipes/crushing/raw_tin_ore.json -da12942204f6aee63d7a8112a410e6aec74370e5 data/create/recipes/crushing/raw_uranium_block.json -4e90a98768c0c462b4bdf1c827461af17b5d8561 data/create/recipes/crushing/raw_uranium_ore.json -5a3bb980c8583e2e8bc3484e20d3ee0932d48b61 data/create/recipes/crushing/raw_zinc.json -628dcdf4d230362ef574be978e0e38a6fadc5824 data/create/recipes/crushing/raw_zinc_block.json +1126e9f29bf15c56917168d53e9f533c171ad2fb data/create/recipes/crushing/quicksilver_ore.json +a0a9e118317e2aabdafc94d19dedb05ccc751630 data/create/recipes/crushing/raw_aluminum_block.json +00c7c3bc45245749ad7cc4ba3ae4b1958bd6bab7 data/create/recipes/crushing/raw_aluminum_ore.json +b490b3ef4f62e2d225c82693955f9a3e70a33e32 data/create/recipes/crushing/raw_copper.json +efa4c84119f0aa998a6b3f477884f81b28d8bd91 data/create/recipes/crushing/raw_copper_block.json +26577895a8ac3c61187171784c5aa30d334ddc17 data/create/recipes/crushing/raw_gold.json +94606b52a715c2118afa63d0df4791167ec78570 data/create/recipes/crushing/raw_gold_block.json +f48f8f1702697f04f420008a002561a96087d424 data/create/recipes/crushing/raw_iron.json +f77190f83190cb0491d77c79f618c7ecb1169dd9 data/create/recipes/crushing/raw_iron_block.json +bb958be3f923c7b921b1fe4e1fffaf612313bc3b data/create/recipes/crushing/raw_lead_block.json +8bcbe26c99259814cda03c7e702cb2b9cdb703be data/create/recipes/crushing/raw_lead_ore.json +b32aeba202cb46ca597c45b321df087629b0d529 data/create/recipes/crushing/raw_nickel_block.json +fe4987e15391a89865021c8ffc39f552d972ce6c data/create/recipes/crushing/raw_nickel_ore.json +ba9ac5dac3bebb11ca29c31da6929c1e4bc42a82 data/create/recipes/crushing/raw_osmium_block.json +f170312878e061b588780f694b3069b07c6a9145 data/create/recipes/crushing/raw_osmium_ore.json +7862c43aeabec2ce7f9c57237f12cb1e57ba19f3 data/create/recipes/crushing/raw_platinum_block.json +948c8d58b5ff186e1a6822ea30310f8fb2d04c0a data/create/recipes/crushing/raw_platinum_ore.json +44f93dc5967c395116f2f88440b6551ae37492fd data/create/recipes/crushing/raw_quicksilver_block.json +a47988609aa65204f28a08f92330947264bae99c data/create/recipes/crushing/raw_quicksilver_ore.json +edb7cd8356c53e9d6c26385e7daba2477d1c0fc3 data/create/recipes/crushing/raw_silver_block.json +c76409d69a9639c32bd95988bc6ae937d2b9ab3d data/create/recipes/crushing/raw_silver_ore.json +7a7aebffec77b5735ff94b36ea7d624012129b36 data/create/recipes/crushing/raw_tin_block.json +1416215d01c218bcf9138368237ad49a7e3401f7 data/create/recipes/crushing/raw_tin_ore.json +537963e4b7d514c6829091f80454d3722cdc1b66 data/create/recipes/crushing/raw_uranium_block.json +4614b1f29655509da43e7b9bf0b2dc25c1a5968e data/create/recipes/crushing/raw_uranium_ore.json +29b1755e48b902c1123eafa75a8fa00325bd3b8b data/create/recipes/crushing/raw_zinc.json +79775097db26ca297b8b1ab1b0f6a1666df0c39e data/create/recipes/crushing/raw_zinc_block.json 268f64d9d7f99e12d0a8228d3455c70e436ebd7f data/create/recipes/crushing/redstone_ore.json -e1181a36ecf2b628c3630031ccd2e21d0c16c49f data/create/recipes/crushing/silver_ore.json -8468739f330361e9fadbd2dcfc71372d30718d16 data/create/recipes/crushing/tin_ore.json +6ae95e2551fe11bceea7f473c04b158c0518508e data/create/recipes/crushing/silver_ore.json +caffc0003ad99160c866ee0e71a345dbe7f696b2 data/create/recipes/crushing/tin_ore.json 97beb27a8fb05f799c215a4cb5691d4e03a6820e data/create/recipes/crushing/tuff.json d16603ecf47014f2f8c6d9b5ce0ec5a5a398978f data/create/recipes/crushing/tuff_recycling.json -e80e766d07a0ab4ab6308749efa33ca1b930136d data/create/recipes/crushing/uranium_ore.json -37267cc5414a10929dcf1a6632f88557bd28547e data/create/recipes/crushing/veridium.json -560634c216c8bd55e72007a81cd2acb6d56f955f data/create/recipes/crushing/veridium_recycling.json +91dfb90e0efc81de398477039a6670a8ac30ab36 data/create/recipes/crushing/uranium_ore.json +e4cdcc67baffa90e27a73a2ba59ec92b323e1d4f data/create/recipes/crushing/veridium.json +bfd5baa72a48ef29c3141b57a88f5ead0f723614 data/create/recipes/crushing/veridium_recycling.json b135e3faf6afef4b6a5f00197997b47ff8e90568 data/create/recipes/crushing/wool.json -b62894fb1442ad947a976284bd7c1b23a6143798 data/create/recipes/crushing/zinc_ore.json +931a66992ccb5accdb435dca6fe6532e86250c0d data/create/recipes/crushing/zinc_ore.json b5c33d039e3c9771b3ffc322aadae7e75a823635 data/create/recipes/cutting/acacia_log.json b45b88bf2ac614b2518437656746f8e8a465d693 data/create/recipes/cutting/acacia_wood.json cdb26cd91feeda5901f31f57c16517dda5287810 data/create/recipes/cutting/andesite_alloy.json @@ -235,8 +235,6 @@ a24ac854f3b3ebf57bea9ebd58fd9655fed8e922 data/create/recipes/cutting/compat/byg/ d93f6deefd5bcf4d91242534d9b588fa2ab1a7de data/create/recipes/cutting/compat/byg/lament_wood.json 6f3a120fae7fdcc98a416185107381a6caf739b0 data/create/recipes/cutting/compat/byg/mahogany_log.json 19cf897802135c3ebdf68f6e2bc41f3cf8d0ddb0 data/create/recipes/cutting/compat/byg/mahogany_wood.json -3a43eb5e02d1ac6f4ea95d4b376d5876a36f0b61 data/create/recipes/cutting/compat/byg/mangrove_log.json -9660d7a107fecef2975f55aa4a221742abb6095f data/create/recipes/cutting/compat/byg/mangrove_wood.json d13e02245ca4acd0c4c4d38359eddf3b22fcff7f data/create/recipes/cutting/compat/byg/maple_log.json 9c947dd9fb94709b481daa3ec5156b227b061cdd data/create/recipes/cutting/compat/byg/maple_wood.json f25cdfa7c0ff0d9c0bfb8fd4c678d1ad61d6f755 data/create/recipes/cutting/compat/byg/nightshade_log.json @@ -283,8 +281,6 @@ b7647e89ee29a4e116c49c1ae419d3d053608017 data/create/recipes/cutting/compat/byg/ 0b4478eba4e2d9bd835d9ad91dcf2eccfc538f12 data/create/recipes/cutting/compat/byg/stripped_lament_wood.json 3550d5eb7f8eab95f4dd840d72cc14dea7acdb67 data/create/recipes/cutting/compat/byg/stripped_mahogany_log.json d66b3e69b6bcf38a9d01fc9290b81778b46459f0 data/create/recipes/cutting/compat/byg/stripped_mahogany_wood.json -e82ba4d10c33003e06c85bc4f21092453a3a8286 data/create/recipes/cutting/compat/byg/stripped_mangrove_log.json -15fbb8520e495097186a1563fc185c0e14f06951 data/create/recipes/cutting/compat/byg/stripped_mangrove_wood.json 4778e5d9e1b5a5d254483dedf9cf22cbda73ca2d data/create/recipes/cutting/compat/byg/stripped_maple_log.json 18b5f67be3d28bc6c8764d2ad576f16745d95109 data/create/recipes/cutting/compat/byg/stripped_maple_wood.json 1446329655130e0cf0f0da7c1c17f517bbfb9d79 data/create/recipes/cutting/compat/byg/stripped_nightshade_log.json @@ -576,29 +572,29 @@ eaff1b1f905b1073366cb8b504f0ae68a59ad3a3 data/create/recipes/sandpaper_polishing 1eb8656f14fffd3e6c3791465e6880ab8c179765 data/create/recipes/splashing/black_concrete_powder.json 5215f9b283ba582e1029de2b21cac5986c1eadbd data/create/recipes/splashing/blue_concrete_powder.json 3ce6bc6cfbdeb52c2514f5620db9f0b95ee18d3a data/create/recipes/splashing/brown_concrete_powder.json -d2aad9e39b79334927d96a00a4ad6b090ca9f506 data/create/recipes/splashing/crushed_copper_ore.json -52eb840345f866a62b8d75501699eb8b8603415c data/create/recipes/splashing/crushed_gold_ore.json -8f2216a9038deaaf0ffe606024ea1e1ce6f5c6d5 data/create/recipes/splashing/crushed_iron_ore.json -f5f7c1ca90e474ae1803120953bcf94f1a016111 data/create/recipes/splashing/crushed_zinc_ore.json +20fa6574bd8903f2cc0e352bcd8fd6580b598365 data/create/recipes/splashing/crushed_raw_copper.json +909331cf4a04345ad4be47848d2850f0133240bd data/create/recipes/splashing/crushed_raw_gold.json +7f516ebd70fd756ae6d0f07c625ab72bf1859cb2 data/create/recipes/splashing/crushed_raw_iron.json +84fa67d901de38656af11bbcf644361abf651ebb data/create/recipes/splashing/crushed_raw_zinc.json e0746e69dbfee5a7e226980d496490b534f848a9 data/create/recipes/splashing/cyan_concrete_powder.json 64535aaa3a5d4b98791337b1a8ce50ad3d39a8ac data/create/recipes/splashing/gravel.json dd9508767f68cc8b5cc2f642690961e0c22c9985 data/create/recipes/splashing/gray_concrete_powder.json 8908b452e6bc1290ebb8cfefc2c066460de93bff data/create/recipes/splashing/green_concrete_powder.json 32d3cbf2d10b97a40c9f1f70b004c720782eabda data/create/recipes/splashing/ice.json -ad4f0b1d7b4217a9f42aaab32e49a9eb87fdae33 data/create/recipes/splashing/immersiveengineering/crushed_aluminum_ore.json -19078e218768b271e7cd15fbd8e5c931af6725b9 data/create/recipes/splashing/immersiveengineering/crushed_lead_ore.json -90830efd768c4fc4977420a19aa3bfa831e1b947 data/create/recipes/splashing/immersiveengineering/crushed_nickel_ore.json -261cfdeb96c717eb08abe51260a69f7b32a2ad60 data/create/recipes/splashing/immersiveengineering/crushed_silver_ore.json -b674384fde3e03b72f73cb8191c5d827d69e0ca6 data/create/recipes/splashing/immersiveengineering/crushed_uranium_ore.json +856e240d49ecf0b722ed13f8310d93f388ffcede data/create/recipes/splashing/immersiveengineering/crushed_raw_aluminum.json +5dd083b9e4cf459b9567ee17f2ad71ca31161200 data/create/recipes/splashing/immersiveengineering/crushed_raw_lead.json +6707b4319280ce28e1edd594e58549f65cd8376c data/create/recipes/splashing/immersiveengineering/crushed_raw_nickel.json +d379607eda7fba5048751d806a245d58e91acc1f data/create/recipes/splashing/immersiveengineering/crushed_raw_silver.json +8afc0810a0166a62d8d394f2841d27e7f7a3e6c5 data/create/recipes/splashing/immersiveengineering/crushed_raw_uranium.json 676a409aadcbf2497b366234c5186c6192a67c8d data/create/recipes/splashing/light_blue_concrete_powder.json d4053dba524524329f43df5bdde81d9ee07838b5 data/create/recipes/splashing/light_gray_concrete_powder.json 3d87975758344a4e420c3c5a138dd300e97cf3c4 data/create/recipes/splashing/lime_concrete_powder.json a7d14062310d6c34aebd20dc7ea1f81d8877fe5f data/create/recipes/splashing/magenta_concrete_powder.json 8d787ccbb817d773616405afc255e298803c9573 data/create/recipes/splashing/magma_block.json -95738b9fbf01d379e349b15d8c7794e60e29bdee data/create/recipes/splashing/mekanism/crushed_lead_ore.json -d390c3cf34ae98508be18c2841ccd99a82ee2229 data/create/recipes/splashing/mekanism/crushed_osmium_ore.json -d621005642e070acfa7b3f589bd680e6263f9d52 data/create/recipes/splashing/mekanism/crushed_tin_ore.json -8bbd37609e1d95b623e7421027a9966f090c5e4e data/create/recipes/splashing/mekanism/crushed_uranium_ore.json +a5a73229d315571f28660a23a93a4581061a1809 data/create/recipes/splashing/mekanism/crushed_raw_lead.json +ba674b07d9f6b288ab79917c21e435b7205cbf4f data/create/recipes/splashing/mekanism/crushed_raw_osmium.json +44ffc1132df9ea418453dc580d8250107c34b1a2 data/create/recipes/splashing/mekanism/crushed_raw_tin.json +7960240bceacdbba1458e354823ae5b4e076d4d0 data/create/recipes/splashing/mekanism/crushed_raw_uranium.json 33010500d02167a49b9e697fdeba3c169a80dee3 data/create/recipes/splashing/orange_concrete_powder.json bead7ac4cb59e935f62bb87c077494fcbca6f18f data/create/recipes/splashing/pink_concrete_powder.json 2b2404f137bb0fac204abddd4259e916a0b1c7b5 data/create/recipes/splashing/purple_concrete_powder.json @@ -608,10 +604,10 @@ cccf4ef0891992687dcb7ce5c644499d93210b8a data/create/recipes/splashing/sand.json 5f830a62c14cfa86fdc59d3405ac79fa626c53ea data/create/recipes/splashing/soul_sand.json 0ee6d52e8966b6189f2841bcdf41417df1ab072c data/create/recipes/splashing/stained_glass.json f241ec6a8ad063b28281c18e1fbb03c482d7af8b data/create/recipes/splashing/stained_glass_pane.json -f1f13577f5c652994badea98607a62ec9eb16723 data/create/recipes/splashing/thermal/crushed_lead_ore.json -371cc9440b2eb4fb3a5a669092e66fb75d822a58 data/create/recipes/splashing/thermal/crushed_nickel_ore.json -8c0c0a2dc62f48478cec15b78445d0f6bb02e3f2 data/create/recipes/splashing/thermal/crushed_silver_ore.json -52820b76b21e2c58c615f6c52ee53245118448b2 data/create/recipes/splashing/thermal/crushed_tin_ore.json +43bcc2f22cca830f11a48f4b48f699001f4ffbb5 data/create/recipes/splashing/thermal/crushed_raw_lead.json +4bc875e07f963f417e0a427ca7a6f9f9a40213ac data/create/recipes/splashing/thermal/crushed_raw_nickel.json +0ceeb253b478dde532e4de01d1ff60ed09819388 data/create/recipes/splashing/thermal/crushed_raw_silver.json +5fa818c04cb65048be0246ade3946cc1e01a0772 data/create/recipes/splashing/thermal/crushed_raw_tin.json 23d70b869e50a1e11df264f3640becac4ec9100d data/create/recipes/splashing/wheat_flour.json a883796342143a5f2b5bc68d230b725964abdb8f data/create/recipes/splashing/white_concrete_powder.json d09bcaa2334e05e6cce37b7342c7de84ce954bb9 data/create/recipes/splashing/wool.json diff --git a/src/generated/resources/.cache/c24b4d2b8d15abff51c78bd94f4403d9eae6c139 b/src/generated/resources/.cache/c24b4d2b8d15abff51c78bd94f4403d9eae6c139 index 26098ee5f..3eac66149 100644 --- a/src/generated/resources/.cache/c24b4d2b8d15abff51c78bd94f4403d9eae6c139 +++ b/src/generated/resources/.cache/c24b4d2b8d15abff51c78bd94f4403d9eae6c139 @@ -1,2 +1,2 @@ -// 1.19.3 2023-02-06T18:08:23.2263588 Create's Custom Sounds +// 1.19.3 2023-06-27T03:14:49.7437772 Create's Custom Sounds 043955db25ffe58e7debb9a4f11e41a9571376e6 assets/create/sounds.json diff --git a/src/generated/resources/assets/create/blockstates/andesite_alloy_block.json b/src/generated/resources/assets/create/blockstates/andesite_alloy_block.json new file mode 100644 index 000000000..1a141d07c --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/andesite_alloy_block.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "create:block/andesite_alloy_block" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/andesite_bars.json b/src/generated/resources/assets/create/blockstates/andesite_bars.json new file mode 100644 index 000000000..b19dd25ad --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/andesite_bars.json @@ -0,0 +1,100 @@ +{ + "multipart": [ + { + "apply": { + "model": "create:block/andesite_post_ends" + } + }, + { + "apply": { + "model": "create:block/andesite_post" + }, + "when": { + "east": "false", + "north": "false", + "south": "false", + "west": "false" + } + }, + { + "apply": { + "model": "create:block/andesite_cap" + }, + "when": { + "east": "false", + "north": "true", + "south": "false", + "west": "false" + } + }, + { + "apply": { + "model": "create:block/andesite_cap", + "y": 90 + }, + "when": { + "east": "true", + "north": "false", + "south": "false", + "west": "false" + } + }, + { + "apply": { + "model": "create:block/andesite_cap_alt" + }, + "when": { + "east": "false", + "north": "false", + "south": "true", + "west": "false" + } + }, + { + "apply": { + "model": "create:block/andesite_cap_alt", + "y": 90 + }, + "when": { + "east": "false", + "north": "false", + "south": "false", + "west": "true" + } + }, + { + "apply": { + "model": "create:block/andesite_side" + }, + "when": { + "north": "true" + } + }, + { + "apply": { + "model": "create:block/andesite_side", + "y": 90 + }, + "when": { + "east": "true" + } + }, + { + "apply": { + "model": "create:block/andesite_side_alt" + }, + "when": { + "south": "true" + } + }, + { + "apply": { + "model": "create:block/andesite_side_alt", + "y": 90 + }, + "when": { + "west": "true" + } + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/andesite_belt_funnel.json b/src/generated/resources/assets/create/blockstates/andesite_belt_funnel.json index 5e8c26aea..995611eb8 100644 --- a/src/generated/resources/assets/create/blockstates/andesite_belt_funnel.json +++ b/src/generated/resources/assets/create/blockstates/andesite_belt_funnel.json @@ -1,122 +1,242 @@ { "variants": { - "facing=east,powered=false,shape=extended": { - "model": "create:block/andesite_belt_funnel_extended", + "facing=east,powered=false,shape=extended,waterlogged=false": { + "model": "create:block/andesite_belt_funnel_extended_unpowered", "y": 90 }, - "facing=east,powered=false,shape=pulling": { - "model": "create:block/andesite_belt_funnel_pulling", + "facing=east,powered=false,shape=extended,waterlogged=true": { + "model": "create:block/andesite_belt_funnel_extended_unpowered", "y": 90 }, - "facing=east,powered=false,shape=pushing": { - "model": "create:block/andesite_belt_funnel_pushing", + "facing=east,powered=false,shape=pulling,waterlogged=false": { + "model": "create:block/andesite_belt_funnel_pulling_unpowered", "y": 90 }, - "facing=east,powered=false,shape=retracted": { - "model": "create:block/andesite_belt_funnel_retracted", + "facing=east,powered=false,shape=pulling,waterlogged=true": { + "model": "create:block/andesite_belt_funnel_pulling_unpowered", "y": 90 }, - "facing=east,powered=true,shape=extended": { + "facing=east,powered=false,shape=pushing,waterlogged=false": { + "model": "create:block/andesite_belt_funnel_pushing_unpowered", + "y": 90 + }, + "facing=east,powered=false,shape=pushing,waterlogged=true": { + "model": "create:block/andesite_belt_funnel_pushing_unpowered", + "y": 90 + }, + "facing=east,powered=false,shape=retracted,waterlogged=false": { + "model": "create:block/andesite_belt_funnel_retracted_unpowered", + "y": 90 + }, + "facing=east,powered=false,shape=retracted,waterlogged=true": { + "model": "create:block/andesite_belt_funnel_retracted_unpowered", + "y": 90 + }, + "facing=east,powered=true,shape=extended,waterlogged=false": { "model": "create:block/andesite_belt_funnel_extended_powered", "y": 90 }, - "facing=east,powered=true,shape=pulling": { + "facing=east,powered=true,shape=extended,waterlogged=true": { + "model": "create:block/andesite_belt_funnel_extended_powered", + "y": 90 + }, + "facing=east,powered=true,shape=pulling,waterlogged=false": { "model": "create:block/andesite_belt_funnel_pulling_powered", "y": 90 }, - "facing=east,powered=true,shape=pushing": { + "facing=east,powered=true,shape=pulling,waterlogged=true": { + "model": "create:block/andesite_belt_funnel_pulling_powered", + "y": 90 + }, + "facing=east,powered=true,shape=pushing,waterlogged=false": { "model": "create:block/andesite_belt_funnel_pushing_powered", "y": 90 }, - "facing=east,powered=true,shape=retracted": { + "facing=east,powered=true,shape=pushing,waterlogged=true": { + "model": "create:block/andesite_belt_funnel_pushing_powered", + "y": 90 + }, + "facing=east,powered=true,shape=retracted,waterlogged=false": { "model": "create:block/andesite_belt_funnel_retracted_powered", "y": 90 }, - "facing=north,powered=false,shape=extended": { - "model": "create:block/andesite_belt_funnel_extended" + "facing=east,powered=true,shape=retracted,waterlogged=true": { + "model": "create:block/andesite_belt_funnel_retracted_powered", + "y": 90 }, - "facing=north,powered=false,shape=pulling": { - "model": "create:block/andesite_belt_funnel_pulling" + "facing=north,powered=false,shape=extended,waterlogged=false": { + "model": "create:block/andesite_belt_funnel_extended_unpowered" }, - "facing=north,powered=false,shape=pushing": { - "model": "create:block/andesite_belt_funnel_pushing" + "facing=north,powered=false,shape=extended,waterlogged=true": { + "model": "create:block/andesite_belt_funnel_extended_unpowered" }, - "facing=north,powered=false,shape=retracted": { - "model": "create:block/andesite_belt_funnel_retracted" + "facing=north,powered=false,shape=pulling,waterlogged=false": { + "model": "create:block/andesite_belt_funnel_pulling_unpowered" }, - "facing=north,powered=true,shape=extended": { + "facing=north,powered=false,shape=pulling,waterlogged=true": { + "model": "create:block/andesite_belt_funnel_pulling_unpowered" + }, + "facing=north,powered=false,shape=pushing,waterlogged=false": { + "model": "create:block/andesite_belt_funnel_pushing_unpowered" + }, + "facing=north,powered=false,shape=pushing,waterlogged=true": { + "model": "create:block/andesite_belt_funnel_pushing_unpowered" + }, + "facing=north,powered=false,shape=retracted,waterlogged=false": { + "model": "create:block/andesite_belt_funnel_retracted_unpowered" + }, + "facing=north,powered=false,shape=retracted,waterlogged=true": { + "model": "create:block/andesite_belt_funnel_retracted_unpowered" + }, + "facing=north,powered=true,shape=extended,waterlogged=false": { "model": "create:block/andesite_belt_funnel_extended_powered" }, - "facing=north,powered=true,shape=pulling": { + "facing=north,powered=true,shape=extended,waterlogged=true": { + "model": "create:block/andesite_belt_funnel_extended_powered" + }, + "facing=north,powered=true,shape=pulling,waterlogged=false": { "model": "create:block/andesite_belt_funnel_pulling_powered" }, - "facing=north,powered=true,shape=pushing": { + "facing=north,powered=true,shape=pulling,waterlogged=true": { + "model": "create:block/andesite_belt_funnel_pulling_powered" + }, + "facing=north,powered=true,shape=pushing,waterlogged=false": { "model": "create:block/andesite_belt_funnel_pushing_powered" }, - "facing=north,powered=true,shape=retracted": { + "facing=north,powered=true,shape=pushing,waterlogged=true": { + "model": "create:block/andesite_belt_funnel_pushing_powered" + }, + "facing=north,powered=true,shape=retracted,waterlogged=false": { "model": "create:block/andesite_belt_funnel_retracted_powered" }, - "facing=south,powered=false,shape=extended": { - "model": "create:block/andesite_belt_funnel_extended", + "facing=north,powered=true,shape=retracted,waterlogged=true": { + "model": "create:block/andesite_belt_funnel_retracted_powered" + }, + "facing=south,powered=false,shape=extended,waterlogged=false": { + "model": "create:block/andesite_belt_funnel_extended_unpowered", "y": 180 }, - "facing=south,powered=false,shape=pulling": { - "model": "create:block/andesite_belt_funnel_pulling", + "facing=south,powered=false,shape=extended,waterlogged=true": { + "model": "create:block/andesite_belt_funnel_extended_unpowered", "y": 180 }, - "facing=south,powered=false,shape=pushing": { - "model": "create:block/andesite_belt_funnel_pushing", + "facing=south,powered=false,shape=pulling,waterlogged=false": { + "model": "create:block/andesite_belt_funnel_pulling_unpowered", "y": 180 }, - "facing=south,powered=false,shape=retracted": { - "model": "create:block/andesite_belt_funnel_retracted", + "facing=south,powered=false,shape=pulling,waterlogged=true": { + "model": "create:block/andesite_belt_funnel_pulling_unpowered", "y": 180 }, - "facing=south,powered=true,shape=extended": { + "facing=south,powered=false,shape=pushing,waterlogged=false": { + "model": "create:block/andesite_belt_funnel_pushing_unpowered", + "y": 180 + }, + "facing=south,powered=false,shape=pushing,waterlogged=true": { + "model": "create:block/andesite_belt_funnel_pushing_unpowered", + "y": 180 + }, + "facing=south,powered=false,shape=retracted,waterlogged=false": { + "model": "create:block/andesite_belt_funnel_retracted_unpowered", + "y": 180 + }, + "facing=south,powered=false,shape=retracted,waterlogged=true": { + "model": "create:block/andesite_belt_funnel_retracted_unpowered", + "y": 180 + }, + "facing=south,powered=true,shape=extended,waterlogged=false": { "model": "create:block/andesite_belt_funnel_extended_powered", "y": 180 }, - "facing=south,powered=true,shape=pulling": { + "facing=south,powered=true,shape=extended,waterlogged=true": { + "model": "create:block/andesite_belt_funnel_extended_powered", + "y": 180 + }, + "facing=south,powered=true,shape=pulling,waterlogged=false": { "model": "create:block/andesite_belt_funnel_pulling_powered", "y": 180 }, - "facing=south,powered=true,shape=pushing": { + "facing=south,powered=true,shape=pulling,waterlogged=true": { + "model": "create:block/andesite_belt_funnel_pulling_powered", + "y": 180 + }, + "facing=south,powered=true,shape=pushing,waterlogged=false": { "model": "create:block/andesite_belt_funnel_pushing_powered", "y": 180 }, - "facing=south,powered=true,shape=retracted": { + "facing=south,powered=true,shape=pushing,waterlogged=true": { + "model": "create:block/andesite_belt_funnel_pushing_powered", + "y": 180 + }, + "facing=south,powered=true,shape=retracted,waterlogged=false": { "model": "create:block/andesite_belt_funnel_retracted_powered", "y": 180 }, - "facing=west,powered=false,shape=extended": { - "model": "create:block/andesite_belt_funnel_extended", + "facing=south,powered=true,shape=retracted,waterlogged=true": { + "model": "create:block/andesite_belt_funnel_retracted_powered", + "y": 180 + }, + "facing=west,powered=false,shape=extended,waterlogged=false": { + "model": "create:block/andesite_belt_funnel_extended_unpowered", "y": 270 }, - "facing=west,powered=false,shape=pulling": { - "model": "create:block/andesite_belt_funnel_pulling", + "facing=west,powered=false,shape=extended,waterlogged=true": { + "model": "create:block/andesite_belt_funnel_extended_unpowered", "y": 270 }, - "facing=west,powered=false,shape=pushing": { - "model": "create:block/andesite_belt_funnel_pushing", + "facing=west,powered=false,shape=pulling,waterlogged=false": { + "model": "create:block/andesite_belt_funnel_pulling_unpowered", "y": 270 }, - "facing=west,powered=false,shape=retracted": { - "model": "create:block/andesite_belt_funnel_retracted", + "facing=west,powered=false,shape=pulling,waterlogged=true": { + "model": "create:block/andesite_belt_funnel_pulling_unpowered", "y": 270 }, - "facing=west,powered=true,shape=extended": { + "facing=west,powered=false,shape=pushing,waterlogged=false": { + "model": "create:block/andesite_belt_funnel_pushing_unpowered", + "y": 270 + }, + "facing=west,powered=false,shape=pushing,waterlogged=true": { + "model": "create:block/andesite_belt_funnel_pushing_unpowered", + "y": 270 + }, + "facing=west,powered=false,shape=retracted,waterlogged=false": { + "model": "create:block/andesite_belt_funnel_retracted_unpowered", + "y": 270 + }, + "facing=west,powered=false,shape=retracted,waterlogged=true": { + "model": "create:block/andesite_belt_funnel_retracted_unpowered", + "y": 270 + }, + "facing=west,powered=true,shape=extended,waterlogged=false": { "model": "create:block/andesite_belt_funnel_extended_powered", "y": 270 }, - "facing=west,powered=true,shape=pulling": { + "facing=west,powered=true,shape=extended,waterlogged=true": { + "model": "create:block/andesite_belt_funnel_extended_powered", + "y": 270 + }, + "facing=west,powered=true,shape=pulling,waterlogged=false": { "model": "create:block/andesite_belt_funnel_pulling_powered", "y": 270 }, - "facing=west,powered=true,shape=pushing": { + "facing=west,powered=true,shape=pulling,waterlogged=true": { + "model": "create:block/andesite_belt_funnel_pulling_powered", + "y": 270 + }, + "facing=west,powered=true,shape=pushing,waterlogged=false": { "model": "create:block/andesite_belt_funnel_pushing_powered", "y": 270 }, - "facing=west,powered=true,shape=retracted": { + "facing=west,powered=true,shape=pushing,waterlogged=true": { + "model": "create:block/andesite_belt_funnel_pushing_powered", + "y": 270 + }, + "facing=west,powered=true,shape=retracted,waterlogged=false": { + "model": "create:block/andesite_belt_funnel_retracted_powered", + "y": 270 + }, + "facing=west,powered=true,shape=retracted,waterlogged=true": { "model": "create:block/andesite_belt_funnel_retracted_powered", "y": 270 } diff --git a/src/generated/resources/assets/create/blockstates/andesite_door.json b/src/generated/resources/assets/create/blockstates/andesite_door.json new file mode 100644 index 000000000..624be8620 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/andesite_door.json @@ -0,0 +1,244 @@ +{ + "variants": { + "facing=east,half=lower,hinge=left,open=false,visible=false": { + "model": "create:block/andesite_door/block_bottom" + }, + "facing=east,half=lower,hinge=left,open=false,visible=true": { + "model": "create:block/andesite_door/block_bottom" + }, + "facing=east,half=lower,hinge=left,open=true,visible=false": { + "model": "create:block/andesite_door/block_bottom", + "y": 90 + }, + "facing=east,half=lower,hinge=left,open=true,visible=true": { + "model": "create:block/andesite_door/block_bottom", + "y": 90 + }, + "facing=east,half=lower,hinge=right,open=false,visible=false": { + "model": "create:block/andesite_door/block_bottom" + }, + "facing=east,half=lower,hinge=right,open=false,visible=true": { + "model": "create:block/andesite_door/block_bottom" + }, + "facing=east,half=lower,hinge=right,open=true,visible=false": { + "model": "create:block/andesite_door/block_bottom", + "y": 270 + }, + "facing=east,half=lower,hinge=right,open=true,visible=true": { + "model": "create:block/andesite_door/block_bottom", + "y": 270 + }, + "facing=east,half=upper,hinge=left,open=false,visible=false": { + "model": "create:block/andesite_door/block_top" + }, + "facing=east,half=upper,hinge=left,open=false,visible=true": { + "model": "create:block/andesite_door/block_top" + }, + "facing=east,half=upper,hinge=left,open=true,visible=false": { + "model": "create:block/andesite_door/block_top", + "y": 90 + }, + "facing=east,half=upper,hinge=left,open=true,visible=true": { + "model": "create:block/andesite_door/block_top", + "y": 90 + }, + "facing=east,half=upper,hinge=right,open=false,visible=false": { + "model": "create:block/andesite_door/block_top" + }, + "facing=east,half=upper,hinge=right,open=false,visible=true": { + "model": "create:block/andesite_door/block_top" + }, + "facing=east,half=upper,hinge=right,open=true,visible=false": { + "model": "create:block/andesite_door/block_top", + "y": 270 + }, + "facing=east,half=upper,hinge=right,open=true,visible=true": { + "model": "create:block/andesite_door/block_top", + "y": 270 + }, + "facing=north,half=lower,hinge=left,open=false,visible=false": { + "model": "create:block/andesite_door/block_bottom", + "y": 270 + }, + "facing=north,half=lower,hinge=left,open=false,visible=true": { + "model": "create:block/andesite_door/block_bottom", + "y": 270 + }, + "facing=north,half=lower,hinge=left,open=true,visible=false": { + "model": "create:block/andesite_door/block_bottom" + }, + "facing=north,half=lower,hinge=left,open=true,visible=true": { + "model": "create:block/andesite_door/block_bottom" + }, + "facing=north,half=lower,hinge=right,open=false,visible=false": { + "model": "create:block/andesite_door/block_bottom", + "y": 270 + }, + "facing=north,half=lower,hinge=right,open=false,visible=true": { + "model": "create:block/andesite_door/block_bottom", + "y": 270 + }, + "facing=north,half=lower,hinge=right,open=true,visible=false": { + "model": "create:block/andesite_door/block_bottom", + "y": 180 + }, + "facing=north,half=lower,hinge=right,open=true,visible=true": { + "model": "create:block/andesite_door/block_bottom", + "y": 180 + }, + "facing=north,half=upper,hinge=left,open=false,visible=false": { + "model": "create:block/andesite_door/block_top", + "y": 270 + }, + "facing=north,half=upper,hinge=left,open=false,visible=true": { + "model": "create:block/andesite_door/block_top", + "y": 270 + }, + "facing=north,half=upper,hinge=left,open=true,visible=false": { + "model": "create:block/andesite_door/block_top" + }, + "facing=north,half=upper,hinge=left,open=true,visible=true": { + "model": "create:block/andesite_door/block_top" + }, + "facing=north,half=upper,hinge=right,open=false,visible=false": { + "model": "create:block/andesite_door/block_top", + "y": 270 + }, + "facing=north,half=upper,hinge=right,open=false,visible=true": { + "model": "create:block/andesite_door/block_top", + "y": 270 + }, + "facing=north,half=upper,hinge=right,open=true,visible=false": { + "model": "create:block/andesite_door/block_top", + "y": 180 + }, + "facing=north,half=upper,hinge=right,open=true,visible=true": { + "model": "create:block/andesite_door/block_top", + "y": 180 + }, + "facing=south,half=lower,hinge=left,open=false,visible=false": { + "model": "create:block/andesite_door/block_bottom", + "y": 90 + }, + "facing=south,half=lower,hinge=left,open=false,visible=true": { + "model": "create:block/andesite_door/block_bottom", + "y": 90 + }, + "facing=south,half=lower,hinge=left,open=true,visible=false": { + "model": "create:block/andesite_door/block_bottom", + "y": 180 + }, + "facing=south,half=lower,hinge=left,open=true,visible=true": { + "model": "create:block/andesite_door/block_bottom", + "y": 180 + }, + "facing=south,half=lower,hinge=right,open=false,visible=false": { + "model": "create:block/andesite_door/block_bottom", + "y": 90 + }, + "facing=south,half=lower,hinge=right,open=false,visible=true": { + "model": "create:block/andesite_door/block_bottom", + "y": 90 + }, + "facing=south,half=lower,hinge=right,open=true,visible=false": { + "model": "create:block/andesite_door/block_bottom" + }, + "facing=south,half=lower,hinge=right,open=true,visible=true": { + "model": "create:block/andesite_door/block_bottom" + }, + "facing=south,half=upper,hinge=left,open=false,visible=false": { + "model": "create:block/andesite_door/block_top", + "y": 90 + }, + "facing=south,half=upper,hinge=left,open=false,visible=true": { + "model": "create:block/andesite_door/block_top", + "y": 90 + }, + "facing=south,half=upper,hinge=left,open=true,visible=false": { + "model": "create:block/andesite_door/block_top", + "y": 180 + }, + "facing=south,half=upper,hinge=left,open=true,visible=true": { + "model": "create:block/andesite_door/block_top", + "y": 180 + }, + "facing=south,half=upper,hinge=right,open=false,visible=false": { + "model": "create:block/andesite_door/block_top", + "y": 90 + }, + "facing=south,half=upper,hinge=right,open=false,visible=true": { + "model": "create:block/andesite_door/block_top", + "y": 90 + }, + "facing=south,half=upper,hinge=right,open=true,visible=false": { + "model": "create:block/andesite_door/block_top" + }, + "facing=south,half=upper,hinge=right,open=true,visible=true": { + "model": "create:block/andesite_door/block_top" + }, + "facing=west,half=lower,hinge=left,open=false,visible=false": { + "model": "create:block/andesite_door/block_bottom", + "y": 180 + }, + "facing=west,half=lower,hinge=left,open=false,visible=true": { + "model": "create:block/andesite_door/block_bottom", + "y": 180 + }, + "facing=west,half=lower,hinge=left,open=true,visible=false": { + "model": "create:block/andesite_door/block_bottom", + "y": 270 + }, + "facing=west,half=lower,hinge=left,open=true,visible=true": { + "model": "create:block/andesite_door/block_bottom", + "y": 270 + }, + "facing=west,half=lower,hinge=right,open=false,visible=false": { + "model": "create:block/andesite_door/block_bottom", + "y": 180 + }, + "facing=west,half=lower,hinge=right,open=false,visible=true": { + "model": "create:block/andesite_door/block_bottom", + "y": 180 + }, + "facing=west,half=lower,hinge=right,open=true,visible=false": { + "model": "create:block/andesite_door/block_bottom", + "y": 90 + }, + "facing=west,half=lower,hinge=right,open=true,visible=true": { + "model": "create:block/andesite_door/block_bottom", + "y": 90 + }, + "facing=west,half=upper,hinge=left,open=false,visible=false": { + "model": "create:block/andesite_door/block_top", + "y": 180 + }, + "facing=west,half=upper,hinge=left,open=false,visible=true": { + "model": "create:block/andesite_door/block_top", + "y": 180 + }, + "facing=west,half=upper,hinge=left,open=true,visible=false": { + "model": "create:block/andesite_door/block_top", + "y": 270 + }, + "facing=west,half=upper,hinge=left,open=true,visible=true": { + "model": "create:block/andesite_door/block_top", + "y": 270 + }, + "facing=west,half=upper,hinge=right,open=false,visible=false": { + "model": "create:block/andesite_door/block_top", + "y": 180 + }, + "facing=west,half=upper,hinge=right,open=false,visible=true": { + "model": "create:block/andesite_door/block_top", + "y": 180 + }, + "facing=west,half=upper,hinge=right,open=true,visible=false": { + "model": "create:block/andesite_door/block_top", + "y": 90 + }, + "facing=west,half=upper,hinge=right,open=true,visible=true": { + "model": "create:block/andesite_door/block_top", + "y": 90 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/andesite_funnel.json b/src/generated/resources/assets/create/blockstates/andesite_funnel.json index 6078134f2..80a697c16 100644 --- a/src/generated/resources/assets/create/blockstates/andesite_funnel.json +++ b/src/generated/resources/assets/create/blockstates/andesite_funnel.json @@ -1,98 +1,194 @@ { "variants": { - "extracting=false,facing=down,powered=false": { - "model": "create:block/andesite_funnel_vertical_filterless_pull", + "extracting=false,facing=down,powered=false,waterlogged=false": { + "model": "create:block/andesite_funnel_vertical_filterless_pull_unpowered", "x": 180, "y": 180 }, - "extracting=false,facing=down,powered=true": { + "extracting=false,facing=down,powered=false,waterlogged=true": { + "model": "create:block/andesite_funnel_vertical_filterless_pull_unpowered", + "x": 180, + "y": 180 + }, + "extracting=false,facing=down,powered=true,waterlogged=false": { "model": "create:block/andesite_funnel_vertical_filterless_pull_powered", "x": 180, "y": 180 }, - "extracting=false,facing=east,powered=false": { - "model": "create:block/andesite_funnel_horizontal_pull", + "extracting=false,facing=down,powered=true,waterlogged=true": { + "model": "create:block/andesite_funnel_vertical_filterless_pull_powered", + "x": 180, + "y": 180 + }, + "extracting=false,facing=east,powered=false,waterlogged=false": { + "model": "create:block/andesite_funnel_horizontal_pull_unpowered", "y": 90 }, - "extracting=false,facing=east,powered=true": { + "extracting=false,facing=east,powered=false,waterlogged=true": { + "model": "create:block/andesite_funnel_horizontal_pull_unpowered", + "y": 90 + }, + "extracting=false,facing=east,powered=true,waterlogged=false": { "model": "create:block/andesite_funnel_horizontal_pull_powered", "y": 90 }, - "extracting=false,facing=north,powered=false": { - "model": "create:block/andesite_funnel_horizontal_pull" + "extracting=false,facing=east,powered=true,waterlogged=true": { + "model": "create:block/andesite_funnel_horizontal_pull_powered", + "y": 90 }, - "extracting=false,facing=north,powered=true": { + "extracting=false,facing=north,powered=false,waterlogged=false": { + "model": "create:block/andesite_funnel_horizontal_pull_unpowered" + }, + "extracting=false,facing=north,powered=false,waterlogged=true": { + "model": "create:block/andesite_funnel_horizontal_pull_unpowered" + }, + "extracting=false,facing=north,powered=true,waterlogged=false": { "model": "create:block/andesite_funnel_horizontal_pull_powered" }, - "extracting=false,facing=south,powered=false": { - "model": "create:block/andesite_funnel_horizontal_pull", + "extracting=false,facing=north,powered=true,waterlogged=true": { + "model": "create:block/andesite_funnel_horizontal_pull_powered" + }, + "extracting=false,facing=south,powered=false,waterlogged=false": { + "model": "create:block/andesite_funnel_horizontal_pull_unpowered", "y": 180 }, - "extracting=false,facing=south,powered=true": { + "extracting=false,facing=south,powered=false,waterlogged=true": { + "model": "create:block/andesite_funnel_horizontal_pull_unpowered", + "y": 180 + }, + "extracting=false,facing=south,powered=true,waterlogged=false": { "model": "create:block/andesite_funnel_horizontal_pull_powered", "y": 180 }, - "extracting=false,facing=up,powered=false": { - "model": "create:block/andesite_funnel_vertical_filterless_pull", + "extracting=false,facing=south,powered=true,waterlogged=true": { + "model": "create:block/andesite_funnel_horizontal_pull_powered", "y": 180 }, - "extracting=false,facing=up,powered=true": { + "extracting=false,facing=up,powered=false,waterlogged=false": { + "model": "create:block/andesite_funnel_vertical_filterless_pull_unpowered", + "y": 180 + }, + "extracting=false,facing=up,powered=false,waterlogged=true": { + "model": "create:block/andesite_funnel_vertical_filterless_pull_unpowered", + "y": 180 + }, + "extracting=false,facing=up,powered=true,waterlogged=false": { "model": "create:block/andesite_funnel_vertical_filterless_pull_powered", "y": 180 }, - "extracting=false,facing=west,powered=false": { - "model": "create:block/andesite_funnel_horizontal_pull", + "extracting=false,facing=up,powered=true,waterlogged=true": { + "model": "create:block/andesite_funnel_vertical_filterless_pull_powered", + "y": 180 + }, + "extracting=false,facing=west,powered=false,waterlogged=false": { + "model": "create:block/andesite_funnel_horizontal_pull_unpowered", "y": 270 }, - "extracting=false,facing=west,powered=true": { + "extracting=false,facing=west,powered=false,waterlogged=true": { + "model": "create:block/andesite_funnel_horizontal_pull_unpowered", + "y": 270 + }, + "extracting=false,facing=west,powered=true,waterlogged=false": { "model": "create:block/andesite_funnel_horizontal_pull_powered", "y": 270 }, - "extracting=true,facing=down,powered=false": { - "model": "create:block/andesite_funnel_vertical_filterless_push", - "x": 180, - "y": 180 - }, - "extracting=true,facing=down,powered=true": { - "model": "create:block/andesite_funnel_vertical_filterless_push_powered", - "x": 180, - "y": 180 - }, - "extracting=true,facing=east,powered=false": { - "model": "create:block/andesite_funnel_horizontal_push", - "y": 90 - }, - "extracting=true,facing=east,powered=true": { - "model": "create:block/andesite_funnel_horizontal_push_powered", - "y": 90 - }, - "extracting=true,facing=north,powered=false": { - "model": "create:block/andesite_funnel_horizontal_push" - }, - "extracting=true,facing=north,powered=true": { - "model": "create:block/andesite_funnel_horizontal_push_powered" - }, - "extracting=true,facing=south,powered=false": { - "model": "create:block/andesite_funnel_horizontal_push", - "y": 180 - }, - "extracting=true,facing=south,powered=true": { - "model": "create:block/andesite_funnel_horizontal_push_powered", - "y": 180 - }, - "extracting=true,facing=up,powered=false": { - "model": "create:block/andesite_funnel_vertical_filterless_push", - "y": 180 - }, - "extracting=true,facing=up,powered=true": { - "model": "create:block/andesite_funnel_vertical_filterless_push_powered", - "y": 180 - }, - "extracting=true,facing=west,powered=false": { - "model": "create:block/andesite_funnel_horizontal_push", + "extracting=false,facing=west,powered=true,waterlogged=true": { + "model": "create:block/andesite_funnel_horizontal_pull_powered", "y": 270 }, - "extracting=true,facing=west,powered=true": { + "extracting=true,facing=down,powered=false,waterlogged=false": { + "model": "create:block/andesite_funnel_vertical_filterless_push_unpowered", + "x": 180, + "y": 180 + }, + "extracting=true,facing=down,powered=false,waterlogged=true": { + "model": "create:block/andesite_funnel_vertical_filterless_push_unpowered", + "x": 180, + "y": 180 + }, + "extracting=true,facing=down,powered=true,waterlogged=false": { + "model": "create:block/andesite_funnel_vertical_filterless_push_powered", + "x": 180, + "y": 180 + }, + "extracting=true,facing=down,powered=true,waterlogged=true": { + "model": "create:block/andesite_funnel_vertical_filterless_push_powered", + "x": 180, + "y": 180 + }, + "extracting=true,facing=east,powered=false,waterlogged=false": { + "model": "create:block/andesite_funnel_horizontal_push_unpowered", + "y": 90 + }, + "extracting=true,facing=east,powered=false,waterlogged=true": { + "model": "create:block/andesite_funnel_horizontal_push_unpowered", + "y": 90 + }, + "extracting=true,facing=east,powered=true,waterlogged=false": { + "model": "create:block/andesite_funnel_horizontal_push_powered", + "y": 90 + }, + "extracting=true,facing=east,powered=true,waterlogged=true": { + "model": "create:block/andesite_funnel_horizontal_push_powered", + "y": 90 + }, + "extracting=true,facing=north,powered=false,waterlogged=false": { + "model": "create:block/andesite_funnel_horizontal_push_unpowered" + }, + "extracting=true,facing=north,powered=false,waterlogged=true": { + "model": "create:block/andesite_funnel_horizontal_push_unpowered" + }, + "extracting=true,facing=north,powered=true,waterlogged=false": { + "model": "create:block/andesite_funnel_horizontal_push_powered" + }, + "extracting=true,facing=north,powered=true,waterlogged=true": { + "model": "create:block/andesite_funnel_horizontal_push_powered" + }, + "extracting=true,facing=south,powered=false,waterlogged=false": { + "model": "create:block/andesite_funnel_horizontal_push_unpowered", + "y": 180 + }, + "extracting=true,facing=south,powered=false,waterlogged=true": { + "model": "create:block/andesite_funnel_horizontal_push_unpowered", + "y": 180 + }, + "extracting=true,facing=south,powered=true,waterlogged=false": { + "model": "create:block/andesite_funnel_horizontal_push_powered", + "y": 180 + }, + "extracting=true,facing=south,powered=true,waterlogged=true": { + "model": "create:block/andesite_funnel_horizontal_push_powered", + "y": 180 + }, + "extracting=true,facing=up,powered=false,waterlogged=false": { + "model": "create:block/andesite_funnel_vertical_filterless_push_unpowered", + "y": 180 + }, + "extracting=true,facing=up,powered=false,waterlogged=true": { + "model": "create:block/andesite_funnel_vertical_filterless_push_unpowered", + "y": 180 + }, + "extracting=true,facing=up,powered=true,waterlogged=false": { + "model": "create:block/andesite_funnel_vertical_filterless_push_powered", + "y": 180 + }, + "extracting=true,facing=up,powered=true,waterlogged=true": { + "model": "create:block/andesite_funnel_vertical_filterless_push_powered", + "y": 180 + }, + "extracting=true,facing=west,powered=false,waterlogged=false": { + "model": "create:block/andesite_funnel_horizontal_push_unpowered", + "y": 270 + }, + "extracting=true,facing=west,powered=false,waterlogged=true": { + "model": "create:block/andesite_funnel_horizontal_push_unpowered", + "y": 270 + }, + "extracting=true,facing=west,powered=true,waterlogged=false": { + "model": "create:block/andesite_funnel_horizontal_push_powered", + "y": 270 + }, + "extracting=true,facing=west,powered=true,waterlogged=true": { "model": "create:block/andesite_funnel_horizontal_push_powered", "y": 270 } diff --git a/src/generated/resources/assets/create/blockstates/andesite_scaffolding.json b/src/generated/resources/assets/create/blockstates/andesite_scaffolding.json new file mode 100644 index 000000000..153f5928b --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/andesite_scaffolding.json @@ -0,0 +1,10 @@ +{ + "variants": { + "bottom=false": { + "model": "create:block/andesite_scaffolding" + }, + "bottom=true": { + "model": "create:block/andesite_scaffolding_horizontal" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/andesite_tunnel.json b/src/generated/resources/assets/create/blockstates/andesite_tunnel.json index dfa395099..b3773ea78 100644 --- a/src/generated/resources/assets/create/blockstates/andesite_tunnel.json +++ b/src/generated/resources/assets/create/blockstates/andesite_tunnel.json @@ -1,45 +1,45 @@ { "variants": { "axis=x,shape=closed": { - "model": "create:block/andesite_tunnel/straight" + "model": "create:block/tunnel/andesite_tunnel/straight" }, "axis=x,shape=cross": { - "model": "create:block/andesite_tunnel/cross" + "model": "create:block/tunnel/andesite_tunnel/cross" }, "axis=x,shape=straight": { - "model": "create:block/andesite_tunnel/straight" + "model": "create:block/tunnel/andesite_tunnel/straight" }, "axis=x,shape=t_left": { - "model": "create:block/andesite_tunnel/t_left" + "model": "create:block/tunnel/andesite_tunnel/t_left" }, "axis=x,shape=t_right": { - "model": "create:block/andesite_tunnel/t_right" + "model": "create:block/tunnel/andesite_tunnel/t_right" }, "axis=x,shape=window": { - "model": "create:block/andesite_tunnel/window" + "model": "create:block/tunnel/andesite_tunnel/window" }, "axis=z,shape=closed": { - "model": "create:block/andesite_tunnel/straight", + "model": "create:block/tunnel/andesite_tunnel/straight", "y": 90 }, "axis=z,shape=cross": { - "model": "create:block/andesite_tunnel/cross", + "model": "create:block/tunnel/andesite_tunnel/cross", "y": 90 }, "axis=z,shape=straight": { - "model": "create:block/andesite_tunnel/straight", + "model": "create:block/tunnel/andesite_tunnel/straight", "y": 90 }, "axis=z,shape=t_left": { - "model": "create:block/andesite_tunnel/t_left", + "model": "create:block/tunnel/andesite_tunnel/t_left", "y": 90 }, "axis=z,shape=t_right": { - "model": "create:block/andesite_tunnel/t_right", + "model": "create:block/tunnel/andesite_tunnel/t_right", "y": 90 }, "axis=z,shape=window": { - "model": "create:block/andesite_tunnel/window", + "model": "create:block/tunnel/andesite_tunnel/window", "y": 90 } } diff --git a/src/generated/resources/assets/create/blockstates/asurine.json b/src/generated/resources/assets/create/blockstates/asurine.json index 36e4d318f..9411ef97a 100644 --- a/src/generated/resources/assets/create/blockstates/asurine.json +++ b/src/generated/resources/assets/create/blockstates/asurine.json @@ -1,7 +1,18 @@ { "variants": { - "": { - "model": "create:block/asurine" - } + "": [ + { + "model": "create:block/asurine_natural_0" + }, + { + "model": "create:block/asurine_natural_1" + }, + { + "model": "create:block/asurine_natural_2" + }, + { + "model": "create:block/asurine_natural_3" + } + ] } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/belt.json b/src/generated/resources/assets/create/blockstates/belt.json index 1a446f785..8ae0fa27b 100644 --- a/src/generated/resources/assets/create/blockstates/belt.json +++ b/src/generated/resources/assets/create/blockstates/belt.json @@ -1,649 +1,1297 @@ { "variants": { - "casing=false,facing=east,part=end,slope=downward": { + "casing=false,facing=east,part=end,slope=downward,waterlogged=false": { "model": "create:block/belt/particle", "y": 270 }, - "casing=false,facing=east,part=end,slope=horizontal": { + "casing=false,facing=east,part=end,slope=downward,waterlogged=true": { "model": "create:block/belt/particle", "y": 270 }, - "casing=false,facing=east,part=end,slope=sideways": { + "casing=false,facing=east,part=end,slope=horizontal,waterlogged=false": { "model": "create:block/belt/particle", "y": 270 }, - "casing=false,facing=east,part=end,slope=upward": { + "casing=false,facing=east,part=end,slope=horizontal,waterlogged=true": { + "model": "create:block/belt/particle", + "y": 270 + }, + "casing=false,facing=east,part=end,slope=sideways,waterlogged=false": { + "model": "create:block/belt/particle", + "y": 270 + }, + "casing=false,facing=east,part=end,slope=sideways,waterlogged=true": { + "model": "create:block/belt/particle", + "y": 270 + }, + "casing=false,facing=east,part=end,slope=upward,waterlogged=false": { "model": "create:block/belt/particle", "y": 90 }, - "casing=false,facing=east,part=end,slope=vertical": { + "casing=false,facing=east,part=end,slope=upward,waterlogged=true": { + "model": "create:block/belt/particle", + "y": 90 + }, + "casing=false,facing=east,part=end,slope=vertical,waterlogged=false": { "model": "create:block/belt/particle", "x": 90, "y": 270 }, - "casing=false,facing=east,part=middle,slope=downward": { - "model": "create:block/belt/particle", - "y": 270 - }, - "casing=false,facing=east,part=middle,slope=horizontal": { - "model": "create:block/belt/particle", - "y": 270 - }, - "casing=false,facing=east,part=middle,slope=sideways": { - "model": "create:block/belt/particle", - "y": 270 - }, - "casing=false,facing=east,part=middle,slope=upward": { - "model": "create:block/belt/particle", - "y": 90 - }, - "casing=false,facing=east,part=middle,slope=vertical": { + "casing=false,facing=east,part=end,slope=vertical,waterlogged=true": { "model": "create:block/belt/particle", "x": 90, "y": 270 }, - "casing=false,facing=east,part=pulley,slope=downward": { + "casing=false,facing=east,part=middle,slope=downward,waterlogged=false": { "model": "create:block/belt/particle", "y": 270 }, - "casing=false,facing=east,part=pulley,slope=horizontal": { + "casing=false,facing=east,part=middle,slope=downward,waterlogged=true": { "model": "create:block/belt/particle", "y": 270 }, - "casing=false,facing=east,part=pulley,slope=sideways": { + "casing=false,facing=east,part=middle,slope=horizontal,waterlogged=false": { "model": "create:block/belt/particle", "y": 270 }, - "casing=false,facing=east,part=pulley,slope=upward": { + "casing=false,facing=east,part=middle,slope=horizontal,waterlogged=true": { + "model": "create:block/belt/particle", + "y": 270 + }, + "casing=false,facing=east,part=middle,slope=sideways,waterlogged=false": { + "model": "create:block/belt/particle", + "y": 270 + }, + "casing=false,facing=east,part=middle,slope=sideways,waterlogged=true": { + "model": "create:block/belt/particle", + "y": 270 + }, + "casing=false,facing=east,part=middle,slope=upward,waterlogged=false": { "model": "create:block/belt/particle", "y": 90 }, - "casing=false,facing=east,part=pulley,slope=vertical": { + "casing=false,facing=east,part=middle,slope=upward,waterlogged=true": { + "model": "create:block/belt/particle", + "y": 90 + }, + "casing=false,facing=east,part=middle,slope=vertical,waterlogged=false": { "model": "create:block/belt/particle", "x": 90, "y": 270 }, - "casing=false,facing=east,part=start,slope=downward": { - "model": "create:block/belt/particle", - "y": 270 - }, - "casing=false,facing=east,part=start,slope=horizontal": { - "model": "create:block/belt/particle", - "y": 270 - }, - "casing=false,facing=east,part=start,slope=sideways": { - "model": "create:block/belt/particle", - "y": 270 - }, - "casing=false,facing=east,part=start,slope=upward": { - "model": "create:block/belt/particle", - "y": 90 - }, - "casing=false,facing=east,part=start,slope=vertical": { + "casing=false,facing=east,part=middle,slope=vertical,waterlogged=true": { "model": "create:block/belt/particle", "x": 90, "y": 270 }, - "casing=false,facing=north,part=end,slope=downward": { + "casing=false,facing=east,part=pulley,slope=downward,waterlogged=false": { + "model": "create:block/belt/particle", + "y": 270 + }, + "casing=false,facing=east,part=pulley,slope=downward,waterlogged=true": { + "model": "create:block/belt/particle", + "y": 270 + }, + "casing=false,facing=east,part=pulley,slope=horizontal,waterlogged=false": { + "model": "create:block/belt/particle", + "y": 270 + }, + "casing=false,facing=east,part=pulley,slope=horizontal,waterlogged=true": { + "model": "create:block/belt/particle", + "y": 270 + }, + "casing=false,facing=east,part=pulley,slope=sideways,waterlogged=false": { + "model": "create:block/belt/particle", + "y": 270 + }, + "casing=false,facing=east,part=pulley,slope=sideways,waterlogged=true": { + "model": "create:block/belt/particle", + "y": 270 + }, + "casing=false,facing=east,part=pulley,slope=upward,waterlogged=false": { + "model": "create:block/belt/particle", + "y": 90 + }, + "casing=false,facing=east,part=pulley,slope=upward,waterlogged=true": { + "model": "create:block/belt/particle", + "y": 90 + }, + "casing=false,facing=east,part=pulley,slope=vertical,waterlogged=false": { + "model": "create:block/belt/particle", + "x": 90, + "y": 270 + }, + "casing=false,facing=east,part=pulley,slope=vertical,waterlogged=true": { + "model": "create:block/belt/particle", + "x": 90, + "y": 270 + }, + "casing=false,facing=east,part=start,slope=downward,waterlogged=false": { + "model": "create:block/belt/particle", + "y": 270 + }, + "casing=false,facing=east,part=start,slope=downward,waterlogged=true": { + "model": "create:block/belt/particle", + "y": 270 + }, + "casing=false,facing=east,part=start,slope=horizontal,waterlogged=false": { + "model": "create:block/belt/particle", + "y": 270 + }, + "casing=false,facing=east,part=start,slope=horizontal,waterlogged=true": { + "model": "create:block/belt/particle", + "y": 270 + }, + "casing=false,facing=east,part=start,slope=sideways,waterlogged=false": { + "model": "create:block/belt/particle", + "y": 270 + }, + "casing=false,facing=east,part=start,slope=sideways,waterlogged=true": { + "model": "create:block/belt/particle", + "y": 270 + }, + "casing=false,facing=east,part=start,slope=upward,waterlogged=false": { + "model": "create:block/belt/particle", + "y": 90 + }, + "casing=false,facing=east,part=start,slope=upward,waterlogged=true": { + "model": "create:block/belt/particle", + "y": 90 + }, + "casing=false,facing=east,part=start,slope=vertical,waterlogged=false": { + "model": "create:block/belt/particle", + "x": 90, + "y": 270 + }, + "casing=false,facing=east,part=start,slope=vertical,waterlogged=true": { + "model": "create:block/belt/particle", + "x": 90, + "y": 270 + }, + "casing=false,facing=north,part=end,slope=downward,waterlogged=false": { "model": "create:block/belt/particle", "y": 180 }, - "casing=false,facing=north,part=end,slope=horizontal": { + "casing=false,facing=north,part=end,slope=downward,waterlogged=true": { "model": "create:block/belt/particle", "y": 180 }, - "casing=false,facing=north,part=end,slope=sideways": { + "casing=false,facing=north,part=end,slope=horizontal,waterlogged=false": { + "model": "create:block/belt/particle", + "y": 180 + }, + "casing=false,facing=north,part=end,slope=horizontal,waterlogged=true": { + "model": "create:block/belt/particle", + "y": 180 + }, + "casing=false,facing=north,part=end,slope=sideways,waterlogged=false": { "model": "create:block/belt/particle", "x": 180, "y": 180 }, - "casing=false,facing=north,part=end,slope=upward": { - "model": "create:block/belt/particle" - }, - "casing=false,facing=north,part=end,slope=vertical": { - "model": "create:block/belt/particle", - "x": 90, - "y": 180 - }, - "casing=false,facing=north,part=middle,slope=downward": { - "model": "create:block/belt/particle", - "y": 180 - }, - "casing=false,facing=north,part=middle,slope=horizontal": { - "model": "create:block/belt/particle", - "y": 180 - }, - "casing=false,facing=north,part=middle,slope=sideways": { + "casing=false,facing=north,part=end,slope=sideways,waterlogged=true": { "model": "create:block/belt/particle", "x": 180, "y": 180 }, - "casing=false,facing=north,part=middle,slope=upward": { + "casing=false,facing=north,part=end,slope=upward,waterlogged=false": { "model": "create:block/belt/particle" }, - "casing=false,facing=north,part=middle,slope=vertical": { + "casing=false,facing=north,part=end,slope=upward,waterlogged=true": { + "model": "create:block/belt/particle" + }, + "casing=false,facing=north,part=end,slope=vertical,waterlogged=false": { "model": "create:block/belt/particle", "x": 90, "y": 180 }, - "casing=false,facing=north,part=pulley,slope=downward": { + "casing=false,facing=north,part=end,slope=vertical,waterlogged=true": { + "model": "create:block/belt/particle", + "x": 90, + "y": 180 + }, + "casing=false,facing=north,part=middle,slope=downward,waterlogged=false": { "model": "create:block/belt/particle", "y": 180 }, - "casing=false,facing=north,part=pulley,slope=horizontal": { + "casing=false,facing=north,part=middle,slope=downward,waterlogged=true": { "model": "create:block/belt/particle", "y": 180 }, - "casing=false,facing=north,part=pulley,slope=sideways": { + "casing=false,facing=north,part=middle,slope=horizontal,waterlogged=false": { + "model": "create:block/belt/particle", + "y": 180 + }, + "casing=false,facing=north,part=middle,slope=horizontal,waterlogged=true": { + "model": "create:block/belt/particle", + "y": 180 + }, + "casing=false,facing=north,part=middle,slope=sideways,waterlogged=false": { "model": "create:block/belt/particle", "x": 180, "y": 180 }, - "casing=false,facing=north,part=pulley,slope=upward": { - "model": "create:block/belt/particle" - }, - "casing=false,facing=north,part=pulley,slope=vertical": { - "model": "create:block/belt/particle", - "x": 90, - "y": 180 - }, - "casing=false,facing=north,part=start,slope=downward": { - "model": "create:block/belt/particle", - "y": 180 - }, - "casing=false,facing=north,part=start,slope=horizontal": { - "model": "create:block/belt/particle", - "y": 180 - }, - "casing=false,facing=north,part=start,slope=sideways": { + "casing=false,facing=north,part=middle,slope=sideways,waterlogged=true": { "model": "create:block/belt/particle", "x": 180, "y": 180 }, - "casing=false,facing=north,part=start,slope=upward": { + "casing=false,facing=north,part=middle,slope=upward,waterlogged=false": { "model": "create:block/belt/particle" }, - "casing=false,facing=north,part=start,slope=vertical": { + "casing=false,facing=north,part=middle,slope=upward,waterlogged=true": { + "model": "create:block/belt/particle" + }, + "casing=false,facing=north,part=middle,slope=vertical,waterlogged=false": { "model": "create:block/belt/particle", "x": 90, "y": 180 }, - "casing=false,facing=south,part=end,slope=downward": { - "model": "create:block/belt/particle" + "casing=false,facing=north,part=middle,slope=vertical,waterlogged=true": { + "model": "create:block/belt/particle", + "x": 90, + "y": 180 }, - "casing=false,facing=south,part=end,slope=horizontal": { - "model": "create:block/belt/particle" - }, - "casing=false,facing=south,part=end,slope=sideways": { - "model": "create:block/belt/particle" - }, - "casing=false,facing=south,part=end,slope=upward": { + "casing=false,facing=north,part=pulley,slope=downward,waterlogged=false": { "model": "create:block/belt/particle", "y": 180 }, - "casing=false,facing=south,part=end,slope=vertical": { + "casing=false,facing=north,part=pulley,slope=downward,waterlogged=true": { + "model": "create:block/belt/particle", + "y": 180 + }, + "casing=false,facing=north,part=pulley,slope=horizontal,waterlogged=false": { + "model": "create:block/belt/particle", + "y": 180 + }, + "casing=false,facing=north,part=pulley,slope=horizontal,waterlogged=true": { + "model": "create:block/belt/particle", + "y": 180 + }, + "casing=false,facing=north,part=pulley,slope=sideways,waterlogged=false": { + "model": "create:block/belt/particle", + "x": 180, + "y": 180 + }, + "casing=false,facing=north,part=pulley,slope=sideways,waterlogged=true": { + "model": "create:block/belt/particle", + "x": 180, + "y": 180 + }, + "casing=false,facing=north,part=pulley,slope=upward,waterlogged=false": { + "model": "create:block/belt/particle" + }, + "casing=false,facing=north,part=pulley,slope=upward,waterlogged=true": { + "model": "create:block/belt/particle" + }, + "casing=false,facing=north,part=pulley,slope=vertical,waterlogged=false": { + "model": "create:block/belt/particle", + "x": 90, + "y": 180 + }, + "casing=false,facing=north,part=pulley,slope=vertical,waterlogged=true": { + "model": "create:block/belt/particle", + "x": 90, + "y": 180 + }, + "casing=false,facing=north,part=start,slope=downward,waterlogged=false": { + "model": "create:block/belt/particle", + "y": 180 + }, + "casing=false,facing=north,part=start,slope=downward,waterlogged=true": { + "model": "create:block/belt/particle", + "y": 180 + }, + "casing=false,facing=north,part=start,slope=horizontal,waterlogged=false": { + "model": "create:block/belt/particle", + "y": 180 + }, + "casing=false,facing=north,part=start,slope=horizontal,waterlogged=true": { + "model": "create:block/belt/particle", + "y": 180 + }, + "casing=false,facing=north,part=start,slope=sideways,waterlogged=false": { + "model": "create:block/belt/particle", + "x": 180, + "y": 180 + }, + "casing=false,facing=north,part=start,slope=sideways,waterlogged=true": { + "model": "create:block/belt/particle", + "x": 180, + "y": 180 + }, + "casing=false,facing=north,part=start,slope=upward,waterlogged=false": { + "model": "create:block/belt/particle" + }, + "casing=false,facing=north,part=start,slope=upward,waterlogged=true": { + "model": "create:block/belt/particle" + }, + "casing=false,facing=north,part=start,slope=vertical,waterlogged=false": { + "model": "create:block/belt/particle", + "x": 90, + "y": 180 + }, + "casing=false,facing=north,part=start,slope=vertical,waterlogged=true": { + "model": "create:block/belt/particle", + "x": 90, + "y": 180 + }, + "casing=false,facing=south,part=end,slope=downward,waterlogged=false": { + "model": "create:block/belt/particle" + }, + "casing=false,facing=south,part=end,slope=downward,waterlogged=true": { + "model": "create:block/belt/particle" + }, + "casing=false,facing=south,part=end,slope=horizontal,waterlogged=false": { + "model": "create:block/belt/particle" + }, + "casing=false,facing=south,part=end,slope=horizontal,waterlogged=true": { + "model": "create:block/belt/particle" + }, + "casing=false,facing=south,part=end,slope=sideways,waterlogged=false": { + "model": "create:block/belt/particle" + }, + "casing=false,facing=south,part=end,slope=sideways,waterlogged=true": { + "model": "create:block/belt/particle" + }, + "casing=false,facing=south,part=end,slope=upward,waterlogged=false": { + "model": "create:block/belt/particle", + "y": 180 + }, + "casing=false,facing=south,part=end,slope=upward,waterlogged=true": { + "model": "create:block/belt/particle", + "y": 180 + }, + "casing=false,facing=south,part=end,slope=vertical,waterlogged=false": { "model": "create:block/belt/particle", "x": 90 }, - "casing=false,facing=south,part=middle,slope=downward": { - "model": "create:block/belt/particle" - }, - "casing=false,facing=south,part=middle,slope=horizontal": { - "model": "create:block/belt/particle" - }, - "casing=false,facing=south,part=middle,slope=sideways": { - "model": "create:block/belt/particle" - }, - "casing=false,facing=south,part=middle,slope=upward": { - "model": "create:block/belt/particle", - "y": 180 - }, - "casing=false,facing=south,part=middle,slope=vertical": { + "casing=false,facing=south,part=end,slope=vertical,waterlogged=true": { "model": "create:block/belt/particle", "x": 90 }, - "casing=false,facing=south,part=pulley,slope=downward": { + "casing=false,facing=south,part=middle,slope=downward,waterlogged=false": { "model": "create:block/belt/particle" }, - "casing=false,facing=south,part=pulley,slope=horizontal": { + "casing=false,facing=south,part=middle,slope=downward,waterlogged=true": { "model": "create:block/belt/particle" }, - "casing=false,facing=south,part=pulley,slope=sideways": { + "casing=false,facing=south,part=middle,slope=horizontal,waterlogged=false": { "model": "create:block/belt/particle" }, - "casing=false,facing=south,part=pulley,slope=upward": { + "casing=false,facing=south,part=middle,slope=horizontal,waterlogged=true": { + "model": "create:block/belt/particle" + }, + "casing=false,facing=south,part=middle,slope=sideways,waterlogged=false": { + "model": "create:block/belt/particle" + }, + "casing=false,facing=south,part=middle,slope=sideways,waterlogged=true": { + "model": "create:block/belt/particle" + }, + "casing=false,facing=south,part=middle,slope=upward,waterlogged=false": { "model": "create:block/belt/particle", "y": 180 }, - "casing=false,facing=south,part=pulley,slope=vertical": { - "model": "create:block/belt/particle", - "x": 90 - }, - "casing=false,facing=south,part=start,slope=downward": { - "model": "create:block/belt/particle" - }, - "casing=false,facing=south,part=start,slope=horizontal": { - "model": "create:block/belt/particle" - }, - "casing=false,facing=south,part=start,slope=sideways": { - "model": "create:block/belt/particle" - }, - "casing=false,facing=south,part=start,slope=upward": { + "casing=false,facing=south,part=middle,slope=upward,waterlogged=true": { "model": "create:block/belt/particle", "y": 180 }, - "casing=false,facing=south,part=start,slope=vertical": { + "casing=false,facing=south,part=middle,slope=vertical,waterlogged=false": { "model": "create:block/belt/particle", "x": 90 }, - "casing=false,facing=west,part=end,slope=downward": { + "casing=false,facing=south,part=middle,slope=vertical,waterlogged=true": { + "model": "create:block/belt/particle", + "x": 90 + }, + "casing=false,facing=south,part=pulley,slope=downward,waterlogged=false": { + "model": "create:block/belt/particle" + }, + "casing=false,facing=south,part=pulley,slope=downward,waterlogged=true": { + "model": "create:block/belt/particle" + }, + "casing=false,facing=south,part=pulley,slope=horizontal,waterlogged=false": { + "model": "create:block/belt/particle" + }, + "casing=false,facing=south,part=pulley,slope=horizontal,waterlogged=true": { + "model": "create:block/belt/particle" + }, + "casing=false,facing=south,part=pulley,slope=sideways,waterlogged=false": { + "model": "create:block/belt/particle" + }, + "casing=false,facing=south,part=pulley,slope=sideways,waterlogged=true": { + "model": "create:block/belt/particle" + }, + "casing=false,facing=south,part=pulley,slope=upward,waterlogged=false": { + "model": "create:block/belt/particle", + "y": 180 + }, + "casing=false,facing=south,part=pulley,slope=upward,waterlogged=true": { + "model": "create:block/belt/particle", + "y": 180 + }, + "casing=false,facing=south,part=pulley,slope=vertical,waterlogged=false": { + "model": "create:block/belt/particle", + "x": 90 + }, + "casing=false,facing=south,part=pulley,slope=vertical,waterlogged=true": { + "model": "create:block/belt/particle", + "x": 90 + }, + "casing=false,facing=south,part=start,slope=downward,waterlogged=false": { + "model": "create:block/belt/particle" + }, + "casing=false,facing=south,part=start,slope=downward,waterlogged=true": { + "model": "create:block/belt/particle" + }, + "casing=false,facing=south,part=start,slope=horizontal,waterlogged=false": { + "model": "create:block/belt/particle" + }, + "casing=false,facing=south,part=start,slope=horizontal,waterlogged=true": { + "model": "create:block/belt/particle" + }, + "casing=false,facing=south,part=start,slope=sideways,waterlogged=false": { + "model": "create:block/belt/particle" + }, + "casing=false,facing=south,part=start,slope=sideways,waterlogged=true": { + "model": "create:block/belt/particle" + }, + "casing=false,facing=south,part=start,slope=upward,waterlogged=false": { + "model": "create:block/belt/particle", + "y": 180 + }, + "casing=false,facing=south,part=start,slope=upward,waterlogged=true": { + "model": "create:block/belt/particle", + "y": 180 + }, + "casing=false,facing=south,part=start,slope=vertical,waterlogged=false": { + "model": "create:block/belt/particle", + "x": 90 + }, + "casing=false,facing=south,part=start,slope=vertical,waterlogged=true": { + "model": "create:block/belt/particle", + "x": 90 + }, + "casing=false,facing=west,part=end,slope=downward,waterlogged=false": { "model": "create:block/belt/particle", "y": 90 }, - "casing=false,facing=west,part=end,slope=horizontal": { + "casing=false,facing=west,part=end,slope=downward,waterlogged=true": { "model": "create:block/belt/particle", "y": 90 }, - "casing=false,facing=west,part=end,slope=sideways": { + "casing=false,facing=west,part=end,slope=horizontal,waterlogged=false": { + "model": "create:block/belt/particle", + "y": 90 + }, + "casing=false,facing=west,part=end,slope=horizontal,waterlogged=true": { + "model": "create:block/belt/particle", + "y": 90 + }, + "casing=false,facing=west,part=end,slope=sideways,waterlogged=false": { "model": "create:block/belt/particle", "x": 180, "y": 90 }, - "casing=false,facing=west,part=end,slope=upward": { - "model": "create:block/belt/particle", - "y": 270 - }, - "casing=false,facing=west,part=end,slope=vertical": { - "model": "create:block/belt/particle", - "x": 90, - "y": 90 - }, - "casing=false,facing=west,part=middle,slope=downward": { - "model": "create:block/belt/particle", - "y": 90 - }, - "casing=false,facing=west,part=middle,slope=horizontal": { - "model": "create:block/belt/particle", - "y": 90 - }, - "casing=false,facing=west,part=middle,slope=sideways": { + "casing=false,facing=west,part=end,slope=sideways,waterlogged=true": { "model": "create:block/belt/particle", "x": 180, "y": 90 }, - "casing=false,facing=west,part=middle,slope=upward": { + "casing=false,facing=west,part=end,slope=upward,waterlogged=false": { "model": "create:block/belt/particle", "y": 270 }, - "casing=false,facing=west,part=middle,slope=vertical": { + "casing=false,facing=west,part=end,slope=upward,waterlogged=true": { + "model": "create:block/belt/particle", + "y": 270 + }, + "casing=false,facing=west,part=end,slope=vertical,waterlogged=false": { "model": "create:block/belt/particle", "x": 90, "y": 90 }, - "casing=false,facing=west,part=pulley,slope=downward": { + "casing=false,facing=west,part=end,slope=vertical,waterlogged=true": { + "model": "create:block/belt/particle", + "x": 90, + "y": 90 + }, + "casing=false,facing=west,part=middle,slope=downward,waterlogged=false": { "model": "create:block/belt/particle", "y": 90 }, - "casing=false,facing=west,part=pulley,slope=horizontal": { + "casing=false,facing=west,part=middle,slope=downward,waterlogged=true": { "model": "create:block/belt/particle", "y": 90 }, - "casing=false,facing=west,part=pulley,slope=sideways": { + "casing=false,facing=west,part=middle,slope=horizontal,waterlogged=false": { + "model": "create:block/belt/particle", + "y": 90 + }, + "casing=false,facing=west,part=middle,slope=horizontal,waterlogged=true": { + "model": "create:block/belt/particle", + "y": 90 + }, + "casing=false,facing=west,part=middle,slope=sideways,waterlogged=false": { "model": "create:block/belt/particle", "x": 180, "y": 90 }, - "casing=false,facing=west,part=pulley,slope=upward": { - "model": "create:block/belt/particle", - "y": 270 - }, - "casing=false,facing=west,part=pulley,slope=vertical": { - "model": "create:block/belt/particle", - "x": 90, - "y": 90 - }, - "casing=false,facing=west,part=start,slope=downward": { - "model": "create:block/belt/particle", - "y": 90 - }, - "casing=false,facing=west,part=start,slope=horizontal": { - "model": "create:block/belt/particle", - "y": 90 - }, - "casing=false,facing=west,part=start,slope=sideways": { + "casing=false,facing=west,part=middle,slope=sideways,waterlogged=true": { "model": "create:block/belt/particle", "x": 180, "y": 90 }, - "casing=false,facing=west,part=start,slope=upward": { + "casing=false,facing=west,part=middle,slope=upward,waterlogged=false": { "model": "create:block/belt/particle", "y": 270 }, - "casing=false,facing=west,part=start,slope=vertical": { + "casing=false,facing=west,part=middle,slope=upward,waterlogged=true": { + "model": "create:block/belt/particle", + "y": 270 + }, + "casing=false,facing=west,part=middle,slope=vertical,waterlogged=false": { "model": "create:block/belt/particle", "x": 90, "y": 90 }, - "casing=true,facing=east,part=end,slope=downward": { + "casing=false,facing=west,part=middle,slope=vertical,waterlogged=true": { + "model": "create:block/belt/particle", + "x": 90, + "y": 90 + }, + "casing=false,facing=west,part=pulley,slope=downward,waterlogged=false": { + "model": "create:block/belt/particle", + "y": 90 + }, + "casing=false,facing=west,part=pulley,slope=downward,waterlogged=true": { + "model": "create:block/belt/particle", + "y": 90 + }, + "casing=false,facing=west,part=pulley,slope=horizontal,waterlogged=false": { + "model": "create:block/belt/particle", + "y": 90 + }, + "casing=false,facing=west,part=pulley,slope=horizontal,waterlogged=true": { + "model": "create:block/belt/particle", + "y": 90 + }, + "casing=false,facing=west,part=pulley,slope=sideways,waterlogged=false": { + "model": "create:block/belt/particle", + "x": 180, + "y": 90 + }, + "casing=false,facing=west,part=pulley,slope=sideways,waterlogged=true": { + "model": "create:block/belt/particle", + "x": 180, + "y": 90 + }, + "casing=false,facing=west,part=pulley,slope=upward,waterlogged=false": { + "model": "create:block/belt/particle", + "y": 270 + }, + "casing=false,facing=west,part=pulley,slope=upward,waterlogged=true": { + "model": "create:block/belt/particle", + "y": 270 + }, + "casing=false,facing=west,part=pulley,slope=vertical,waterlogged=false": { + "model": "create:block/belt/particle", + "x": 90, + "y": 90 + }, + "casing=false,facing=west,part=pulley,slope=vertical,waterlogged=true": { + "model": "create:block/belt/particle", + "x": 90, + "y": 90 + }, + "casing=false,facing=west,part=start,slope=downward,waterlogged=false": { + "model": "create:block/belt/particle", + "y": 90 + }, + "casing=false,facing=west,part=start,slope=downward,waterlogged=true": { + "model": "create:block/belt/particle", + "y": 90 + }, + "casing=false,facing=west,part=start,slope=horizontal,waterlogged=false": { + "model": "create:block/belt/particle", + "y": 90 + }, + "casing=false,facing=west,part=start,slope=horizontal,waterlogged=true": { + "model": "create:block/belt/particle", + "y": 90 + }, + "casing=false,facing=west,part=start,slope=sideways,waterlogged=false": { + "model": "create:block/belt/particle", + "x": 180, + "y": 90 + }, + "casing=false,facing=west,part=start,slope=sideways,waterlogged=true": { + "model": "create:block/belt/particle", + "x": 180, + "y": 90 + }, + "casing=false,facing=west,part=start,slope=upward,waterlogged=false": { + "model": "create:block/belt/particle", + "y": 270 + }, + "casing=false,facing=west,part=start,slope=upward,waterlogged=true": { + "model": "create:block/belt/particle", + "y": 270 + }, + "casing=false,facing=west,part=start,slope=vertical,waterlogged=false": { + "model": "create:block/belt/particle", + "x": 90, + "y": 90 + }, + "casing=false,facing=west,part=start,slope=vertical,waterlogged=true": { + "model": "create:block/belt/particle", + "x": 90, + "y": 90 + }, + "casing=true,facing=east,part=end,slope=downward,waterlogged=false": { "model": "create:block/belt_casing/diagonal_start", "y": 270 }, - "casing=true,facing=east,part=end,slope=horizontal": { + "casing=true,facing=east,part=end,slope=downward,waterlogged=true": { + "model": "create:block/belt_casing/diagonal_start", + "y": 270 + }, + "casing=true,facing=east,part=end,slope=horizontal,waterlogged=false": { "model": "create:block/belt_casing/horizontal_end", "y": 270 }, - "casing=true,facing=east,part=end,slope=sideways": { + "casing=true,facing=east,part=end,slope=horizontal,waterlogged=true": { + "model": "create:block/belt_casing/horizontal_end", + "y": 270 + }, + "casing=true,facing=east,part=end,slope=sideways,waterlogged=false": { "model": "create:block/belt_casing/sideways_end", "y": 270 }, - "casing=true,facing=east,part=end,slope=upward": { + "casing=true,facing=east,part=end,slope=sideways,waterlogged=true": { + "model": "create:block/belt_casing/sideways_end", + "y": 270 + }, + "casing=true,facing=east,part=end,slope=upward,waterlogged=false": { "model": "create:block/belt_casing/diagonal_end", "y": 90 }, - "casing=true,facing=east,part=end,slope=vertical": { + "casing=true,facing=east,part=end,slope=upward,waterlogged=true": { + "model": "create:block/belt_casing/diagonal_end", + "y": 90 + }, + "casing=true,facing=east,part=end,slope=vertical,waterlogged=false": { "model": "create:block/belt_casing/sideways_end", "x": 90 }, - "casing=true,facing=east,part=middle,slope=downward": { + "casing=true,facing=east,part=end,slope=vertical,waterlogged=true": { + "model": "create:block/belt_casing/sideways_end", + "x": 90 + }, + "casing=true,facing=east,part=middle,slope=downward,waterlogged=false": { "model": "create:block/belt_casing/diagonal_middle", "y": 270 }, - "casing=true,facing=east,part=middle,slope=horizontal": { + "casing=true,facing=east,part=middle,slope=downward,waterlogged=true": { + "model": "create:block/belt_casing/diagonal_middle", + "y": 270 + }, + "casing=true,facing=east,part=middle,slope=horizontal,waterlogged=false": { "model": "create:block/belt_casing/horizontal_middle", "y": 270 }, - "casing=true,facing=east,part=middle,slope=sideways": { + "casing=true,facing=east,part=middle,slope=horizontal,waterlogged=true": { + "model": "create:block/belt_casing/horizontal_middle", + "y": 270 + }, + "casing=true,facing=east,part=middle,slope=sideways,waterlogged=false": { "model": "create:block/belt_casing/sideways_middle", "y": 270 }, - "casing=true,facing=east,part=middle,slope=upward": { + "casing=true,facing=east,part=middle,slope=sideways,waterlogged=true": { + "model": "create:block/belt_casing/sideways_middle", + "y": 270 + }, + "casing=true,facing=east,part=middle,slope=upward,waterlogged=false": { "model": "create:block/belt_casing/diagonal_middle", "y": 90 }, - "casing=true,facing=east,part=middle,slope=vertical": { + "casing=true,facing=east,part=middle,slope=upward,waterlogged=true": { + "model": "create:block/belt_casing/diagonal_middle", + "y": 90 + }, + "casing=true,facing=east,part=middle,slope=vertical,waterlogged=false": { "model": "create:block/belt_casing/sideways_middle", "x": 90 }, - "casing=true,facing=east,part=pulley,slope=downward": { + "casing=true,facing=east,part=middle,slope=vertical,waterlogged=true": { + "model": "create:block/belt_casing/sideways_middle", + "x": 90 + }, + "casing=true,facing=east,part=pulley,slope=downward,waterlogged=false": { "model": "create:block/belt_casing/diagonal_pulley", "y": 270 }, - "casing=true,facing=east,part=pulley,slope=horizontal": { + "casing=true,facing=east,part=pulley,slope=downward,waterlogged=true": { + "model": "create:block/belt_casing/diagonal_pulley", + "y": 270 + }, + "casing=true,facing=east,part=pulley,slope=horizontal,waterlogged=false": { "model": "create:block/belt_casing/horizontal_pulley", "y": 270 }, - "casing=true,facing=east,part=pulley,slope=sideways": { + "casing=true,facing=east,part=pulley,slope=horizontal,waterlogged=true": { + "model": "create:block/belt_casing/horizontal_pulley", + "y": 270 + }, + "casing=true,facing=east,part=pulley,slope=sideways,waterlogged=false": { "model": "create:block/belt_casing/sideways_pulley", "y": 270 }, - "casing=true,facing=east,part=pulley,slope=upward": { + "casing=true,facing=east,part=pulley,slope=sideways,waterlogged=true": { + "model": "create:block/belt_casing/sideways_pulley", + "y": 270 + }, + "casing=true,facing=east,part=pulley,slope=upward,waterlogged=false": { "model": "create:block/belt_casing/diagonal_pulley", "y": 90 }, - "casing=true,facing=east,part=pulley,slope=vertical": { + "casing=true,facing=east,part=pulley,slope=upward,waterlogged=true": { + "model": "create:block/belt_casing/diagonal_pulley", + "y": 90 + }, + "casing=true,facing=east,part=pulley,slope=vertical,waterlogged=false": { "model": "create:block/belt_casing/sideways_pulley", "x": 90 }, - "casing=true,facing=east,part=start,slope=downward": { + "casing=true,facing=east,part=pulley,slope=vertical,waterlogged=true": { + "model": "create:block/belt_casing/sideways_pulley", + "x": 90 + }, + "casing=true,facing=east,part=start,slope=downward,waterlogged=false": { "model": "create:block/belt_casing/diagonal_end", "y": 270 }, - "casing=true,facing=east,part=start,slope=horizontal": { + "casing=true,facing=east,part=start,slope=downward,waterlogged=true": { + "model": "create:block/belt_casing/diagonal_end", + "y": 270 + }, + "casing=true,facing=east,part=start,slope=horizontal,waterlogged=false": { "model": "create:block/belt_casing/horizontal_start", "y": 270 }, - "casing=true,facing=east,part=start,slope=sideways": { + "casing=true,facing=east,part=start,slope=horizontal,waterlogged=true": { + "model": "create:block/belt_casing/horizontal_start", + "y": 270 + }, + "casing=true,facing=east,part=start,slope=sideways,waterlogged=false": { "model": "create:block/belt_casing/sideways_start", "y": 270 }, - "casing=true,facing=east,part=start,slope=upward": { + "casing=true,facing=east,part=start,slope=sideways,waterlogged=true": { + "model": "create:block/belt_casing/sideways_start", + "y": 270 + }, + "casing=true,facing=east,part=start,slope=upward,waterlogged=false": { "model": "create:block/belt_casing/diagonal_start", "y": 90 }, - "casing=true,facing=east,part=start,slope=vertical": { + "casing=true,facing=east,part=start,slope=upward,waterlogged=true": { + "model": "create:block/belt_casing/diagonal_start", + "y": 90 + }, + "casing=true,facing=east,part=start,slope=vertical,waterlogged=false": { "model": "create:block/belt_casing/sideways_start", "x": 90 }, - "casing=true,facing=north,part=end,slope=downward": { + "casing=true,facing=east,part=start,slope=vertical,waterlogged=true": { + "model": "create:block/belt_casing/sideways_start", + "x": 90 + }, + "casing=true,facing=north,part=end,slope=downward,waterlogged=false": { "model": "create:block/belt_casing/diagonal_start", "y": 180 }, - "casing=true,facing=north,part=end,slope=horizontal": { + "casing=true,facing=north,part=end,slope=downward,waterlogged=true": { + "model": "create:block/belt_casing/diagonal_start", + "y": 180 + }, + "casing=true,facing=north,part=end,slope=horizontal,waterlogged=false": { "model": "create:block/belt_casing/horizontal_end", "y": 180 }, - "casing=true,facing=north,part=end,slope=sideways": { + "casing=true,facing=north,part=end,slope=horizontal,waterlogged=true": { + "model": "create:block/belt_casing/horizontal_end", + "y": 180 + }, + "casing=true,facing=north,part=end,slope=sideways,waterlogged=false": { "model": "create:block/belt_casing/sideways_start", "x": 180, "y": 180 }, - "casing=true,facing=north,part=end,slope=upward": { + "casing=true,facing=north,part=end,slope=sideways,waterlogged=true": { + "model": "create:block/belt_casing/sideways_start", + "x": 180, + "y": 180 + }, + "casing=true,facing=north,part=end,slope=upward,waterlogged=false": { "model": "create:block/belt_casing/diagonal_end" }, - "casing=true,facing=north,part=end,slope=vertical": { + "casing=true,facing=north,part=end,slope=upward,waterlogged=true": { + "model": "create:block/belt_casing/diagonal_end" + }, + "casing=true,facing=north,part=end,slope=vertical,waterlogged=false": { "model": "create:block/belt_casing/sideways_start", "x": 90, "y": 270 }, - "casing=true,facing=north,part=middle,slope=downward": { + "casing=true,facing=north,part=end,slope=vertical,waterlogged=true": { + "model": "create:block/belt_casing/sideways_start", + "x": 90, + "y": 270 + }, + "casing=true,facing=north,part=middle,slope=downward,waterlogged=false": { "model": "create:block/belt_casing/diagonal_middle", "y": 180 }, - "casing=true,facing=north,part=middle,slope=horizontal": { + "casing=true,facing=north,part=middle,slope=downward,waterlogged=true": { + "model": "create:block/belt_casing/diagonal_middle", + "y": 180 + }, + "casing=true,facing=north,part=middle,slope=horizontal,waterlogged=false": { "model": "create:block/belt_casing/horizontal_middle", "y": 180 }, - "casing=true,facing=north,part=middle,slope=sideways": { + "casing=true,facing=north,part=middle,slope=horizontal,waterlogged=true": { + "model": "create:block/belt_casing/horizontal_middle", + "y": 180 + }, + "casing=true,facing=north,part=middle,slope=sideways,waterlogged=false": { "model": "create:block/belt_casing/sideways_middle", "x": 180, "y": 180 }, - "casing=true,facing=north,part=middle,slope=upward": { + "casing=true,facing=north,part=middle,slope=sideways,waterlogged=true": { + "model": "create:block/belt_casing/sideways_middle", + "x": 180, + "y": 180 + }, + "casing=true,facing=north,part=middle,slope=upward,waterlogged=false": { "model": "create:block/belt_casing/diagonal_middle" }, - "casing=true,facing=north,part=middle,slope=vertical": { + "casing=true,facing=north,part=middle,slope=upward,waterlogged=true": { + "model": "create:block/belt_casing/diagonal_middle" + }, + "casing=true,facing=north,part=middle,slope=vertical,waterlogged=false": { "model": "create:block/belt_casing/sideways_middle", "x": 90, "y": 270 }, - "casing=true,facing=north,part=pulley,slope=downward": { + "casing=true,facing=north,part=middle,slope=vertical,waterlogged=true": { + "model": "create:block/belt_casing/sideways_middle", + "x": 90, + "y": 270 + }, + "casing=true,facing=north,part=pulley,slope=downward,waterlogged=false": { "model": "create:block/belt_casing/diagonal_pulley", "y": 180 }, - "casing=true,facing=north,part=pulley,slope=horizontal": { + "casing=true,facing=north,part=pulley,slope=downward,waterlogged=true": { + "model": "create:block/belt_casing/diagonal_pulley", + "y": 180 + }, + "casing=true,facing=north,part=pulley,slope=horizontal,waterlogged=false": { "model": "create:block/belt_casing/horizontal_pulley", "y": 180 }, - "casing=true,facing=north,part=pulley,slope=sideways": { + "casing=true,facing=north,part=pulley,slope=horizontal,waterlogged=true": { + "model": "create:block/belt_casing/horizontal_pulley", + "y": 180 + }, + "casing=true,facing=north,part=pulley,slope=sideways,waterlogged=false": { "model": "create:block/belt_casing/sideways_pulley", "x": 180, "y": 180 }, - "casing=true,facing=north,part=pulley,slope=upward": { + "casing=true,facing=north,part=pulley,slope=sideways,waterlogged=true": { + "model": "create:block/belt_casing/sideways_pulley", + "x": 180, + "y": 180 + }, + "casing=true,facing=north,part=pulley,slope=upward,waterlogged=false": { "model": "create:block/belt_casing/diagonal_pulley" }, - "casing=true,facing=north,part=pulley,slope=vertical": { + "casing=true,facing=north,part=pulley,slope=upward,waterlogged=true": { + "model": "create:block/belt_casing/diagonal_pulley" + }, + "casing=true,facing=north,part=pulley,slope=vertical,waterlogged=false": { "model": "create:block/belt_casing/sideways_pulley", "x": 90, "y": 270 }, - "casing=true,facing=north,part=start,slope=downward": { + "casing=true,facing=north,part=pulley,slope=vertical,waterlogged=true": { + "model": "create:block/belt_casing/sideways_pulley", + "x": 90, + "y": 270 + }, + "casing=true,facing=north,part=start,slope=downward,waterlogged=false": { "model": "create:block/belt_casing/diagonal_end", "y": 180 }, - "casing=true,facing=north,part=start,slope=horizontal": { + "casing=true,facing=north,part=start,slope=downward,waterlogged=true": { + "model": "create:block/belt_casing/diagonal_end", + "y": 180 + }, + "casing=true,facing=north,part=start,slope=horizontal,waterlogged=false": { "model": "create:block/belt_casing/horizontal_start", "y": 180 }, - "casing=true,facing=north,part=start,slope=sideways": { + "casing=true,facing=north,part=start,slope=horizontal,waterlogged=true": { + "model": "create:block/belt_casing/horizontal_start", + "y": 180 + }, + "casing=true,facing=north,part=start,slope=sideways,waterlogged=false": { "model": "create:block/belt_casing/sideways_end", "x": 180, "y": 180 }, - "casing=true,facing=north,part=start,slope=upward": { + "casing=true,facing=north,part=start,slope=sideways,waterlogged=true": { + "model": "create:block/belt_casing/sideways_end", + "x": 180, + "y": 180 + }, + "casing=true,facing=north,part=start,slope=upward,waterlogged=false": { "model": "create:block/belt_casing/diagonal_start" }, - "casing=true,facing=north,part=start,slope=vertical": { + "casing=true,facing=north,part=start,slope=upward,waterlogged=true": { + "model": "create:block/belt_casing/diagonal_start" + }, + "casing=true,facing=north,part=start,slope=vertical,waterlogged=false": { "model": "create:block/belt_casing/sideways_end", "x": 90, "y": 270 }, - "casing=true,facing=south,part=end,slope=downward": { + "casing=true,facing=north,part=start,slope=vertical,waterlogged=true": { + "model": "create:block/belt_casing/sideways_end", + "x": 90, + "y": 270 + }, + "casing=true,facing=south,part=end,slope=downward,waterlogged=false": { "model": "create:block/belt_casing/diagonal_start" }, - "casing=true,facing=south,part=end,slope=horizontal": { + "casing=true,facing=south,part=end,slope=downward,waterlogged=true": { + "model": "create:block/belt_casing/diagonal_start" + }, + "casing=true,facing=south,part=end,slope=horizontal,waterlogged=false": { "model": "create:block/belt_casing/horizontal_end" }, - "casing=true,facing=south,part=end,slope=sideways": { + "casing=true,facing=south,part=end,slope=horizontal,waterlogged=true": { + "model": "create:block/belt_casing/horizontal_end" + }, + "casing=true,facing=south,part=end,slope=sideways,waterlogged=false": { "model": "create:block/belt_casing/sideways_end" }, - "casing=true,facing=south,part=end,slope=upward": { + "casing=true,facing=south,part=end,slope=sideways,waterlogged=true": { + "model": "create:block/belt_casing/sideways_end" + }, + "casing=true,facing=south,part=end,slope=upward,waterlogged=false": { "model": "create:block/belt_casing/diagonal_end", "y": 180 }, - "casing=true,facing=south,part=end,slope=vertical": { + "casing=true,facing=south,part=end,slope=upward,waterlogged=true": { + "model": "create:block/belt_casing/diagonal_end", + "y": 180 + }, + "casing=true,facing=south,part=end,slope=vertical,waterlogged=false": { "model": "create:block/belt_casing/sideways_end", "x": 90, "y": 90 }, - "casing=true,facing=south,part=middle,slope=downward": { + "casing=true,facing=south,part=end,slope=vertical,waterlogged=true": { + "model": "create:block/belt_casing/sideways_end", + "x": 90, + "y": 90 + }, + "casing=true,facing=south,part=middle,slope=downward,waterlogged=false": { "model": "create:block/belt_casing/diagonal_middle" }, - "casing=true,facing=south,part=middle,slope=horizontal": { + "casing=true,facing=south,part=middle,slope=downward,waterlogged=true": { + "model": "create:block/belt_casing/diagonal_middle" + }, + "casing=true,facing=south,part=middle,slope=horizontal,waterlogged=false": { "model": "create:block/belt_casing/horizontal_middle" }, - "casing=true,facing=south,part=middle,slope=sideways": { + "casing=true,facing=south,part=middle,slope=horizontal,waterlogged=true": { + "model": "create:block/belt_casing/horizontal_middle" + }, + "casing=true,facing=south,part=middle,slope=sideways,waterlogged=false": { "model": "create:block/belt_casing/sideways_middle" }, - "casing=true,facing=south,part=middle,slope=upward": { + "casing=true,facing=south,part=middle,slope=sideways,waterlogged=true": { + "model": "create:block/belt_casing/sideways_middle" + }, + "casing=true,facing=south,part=middle,slope=upward,waterlogged=false": { "model": "create:block/belt_casing/diagonal_middle", "y": 180 }, - "casing=true,facing=south,part=middle,slope=vertical": { + "casing=true,facing=south,part=middle,slope=upward,waterlogged=true": { + "model": "create:block/belt_casing/diagonal_middle", + "y": 180 + }, + "casing=true,facing=south,part=middle,slope=vertical,waterlogged=false": { "model": "create:block/belt_casing/sideways_middle", "x": 90, "y": 90 }, - "casing=true,facing=south,part=pulley,slope=downward": { + "casing=true,facing=south,part=middle,slope=vertical,waterlogged=true": { + "model": "create:block/belt_casing/sideways_middle", + "x": 90, + "y": 90 + }, + "casing=true,facing=south,part=pulley,slope=downward,waterlogged=false": { "model": "create:block/belt_casing/diagonal_pulley" }, - "casing=true,facing=south,part=pulley,slope=horizontal": { + "casing=true,facing=south,part=pulley,slope=downward,waterlogged=true": { + "model": "create:block/belt_casing/diagonal_pulley" + }, + "casing=true,facing=south,part=pulley,slope=horizontal,waterlogged=false": { "model": "create:block/belt_casing/horizontal_pulley" }, - "casing=true,facing=south,part=pulley,slope=sideways": { + "casing=true,facing=south,part=pulley,slope=horizontal,waterlogged=true": { + "model": "create:block/belt_casing/horizontal_pulley" + }, + "casing=true,facing=south,part=pulley,slope=sideways,waterlogged=false": { "model": "create:block/belt_casing/sideways_pulley" }, - "casing=true,facing=south,part=pulley,slope=upward": { + "casing=true,facing=south,part=pulley,slope=sideways,waterlogged=true": { + "model": "create:block/belt_casing/sideways_pulley" + }, + "casing=true,facing=south,part=pulley,slope=upward,waterlogged=false": { "model": "create:block/belt_casing/diagonal_pulley", "y": 180 }, - "casing=true,facing=south,part=pulley,slope=vertical": { + "casing=true,facing=south,part=pulley,slope=upward,waterlogged=true": { + "model": "create:block/belt_casing/diagonal_pulley", + "y": 180 + }, + "casing=true,facing=south,part=pulley,slope=vertical,waterlogged=false": { "model": "create:block/belt_casing/sideways_pulley", "x": 90, "y": 90 }, - "casing=true,facing=south,part=start,slope=downward": { + "casing=true,facing=south,part=pulley,slope=vertical,waterlogged=true": { + "model": "create:block/belt_casing/sideways_pulley", + "x": 90, + "y": 90 + }, + "casing=true,facing=south,part=start,slope=downward,waterlogged=false": { "model": "create:block/belt_casing/diagonal_end" }, - "casing=true,facing=south,part=start,slope=horizontal": { + "casing=true,facing=south,part=start,slope=downward,waterlogged=true": { + "model": "create:block/belt_casing/diagonal_end" + }, + "casing=true,facing=south,part=start,slope=horizontal,waterlogged=false": { "model": "create:block/belt_casing/horizontal_start" }, - "casing=true,facing=south,part=start,slope=sideways": { + "casing=true,facing=south,part=start,slope=horizontal,waterlogged=true": { + "model": "create:block/belt_casing/horizontal_start" + }, + "casing=true,facing=south,part=start,slope=sideways,waterlogged=false": { "model": "create:block/belt_casing/sideways_start" }, - "casing=true,facing=south,part=start,slope=upward": { + "casing=true,facing=south,part=start,slope=sideways,waterlogged=true": { + "model": "create:block/belt_casing/sideways_start" + }, + "casing=true,facing=south,part=start,slope=upward,waterlogged=false": { "model": "create:block/belt_casing/diagonal_start", "y": 180 }, - "casing=true,facing=south,part=start,slope=vertical": { + "casing=true,facing=south,part=start,slope=upward,waterlogged=true": { + "model": "create:block/belt_casing/diagonal_start", + "y": 180 + }, + "casing=true,facing=south,part=start,slope=vertical,waterlogged=false": { "model": "create:block/belt_casing/sideways_start", "x": 90, "y": 90 }, - "casing=true,facing=west,part=end,slope=downward": { + "casing=true,facing=south,part=start,slope=vertical,waterlogged=true": { + "model": "create:block/belt_casing/sideways_start", + "x": 90, + "y": 90 + }, + "casing=true,facing=west,part=end,slope=downward,waterlogged=false": { "model": "create:block/belt_casing/diagonal_start", "y": 90 }, - "casing=true,facing=west,part=end,slope=horizontal": { + "casing=true,facing=west,part=end,slope=downward,waterlogged=true": { + "model": "create:block/belt_casing/diagonal_start", + "y": 90 + }, + "casing=true,facing=west,part=end,slope=horizontal,waterlogged=false": { "model": "create:block/belt_casing/horizontal_end", "y": 90 }, - "casing=true,facing=west,part=end,slope=sideways": { + "casing=true,facing=west,part=end,slope=horizontal,waterlogged=true": { + "model": "create:block/belt_casing/horizontal_end", + "y": 90 + }, + "casing=true,facing=west,part=end,slope=sideways,waterlogged=false": { "model": "create:block/belt_casing/sideways_start", "x": 180, "y": 90 }, - "casing=true,facing=west,part=end,slope=upward": { + "casing=true,facing=west,part=end,slope=sideways,waterlogged=true": { + "model": "create:block/belt_casing/sideways_start", + "x": 180, + "y": 90 + }, + "casing=true,facing=west,part=end,slope=upward,waterlogged=false": { "model": "create:block/belt_casing/diagonal_end", "y": 270 }, - "casing=true,facing=west,part=end,slope=vertical": { + "casing=true,facing=west,part=end,slope=upward,waterlogged=true": { + "model": "create:block/belt_casing/diagonal_end", + "y": 270 + }, + "casing=true,facing=west,part=end,slope=vertical,waterlogged=false": { "model": "create:block/belt_casing/sideways_start", "x": 90, "y": 180 }, - "casing=true,facing=west,part=middle,slope=downward": { + "casing=true,facing=west,part=end,slope=vertical,waterlogged=true": { + "model": "create:block/belt_casing/sideways_start", + "x": 90, + "y": 180 + }, + "casing=true,facing=west,part=middle,slope=downward,waterlogged=false": { "model": "create:block/belt_casing/diagonal_middle", "y": 90 }, - "casing=true,facing=west,part=middle,slope=horizontal": { + "casing=true,facing=west,part=middle,slope=downward,waterlogged=true": { + "model": "create:block/belt_casing/diagonal_middle", + "y": 90 + }, + "casing=true,facing=west,part=middle,slope=horizontal,waterlogged=false": { "model": "create:block/belt_casing/horizontal_middle", "y": 90 }, - "casing=true,facing=west,part=middle,slope=sideways": { + "casing=true,facing=west,part=middle,slope=horizontal,waterlogged=true": { + "model": "create:block/belt_casing/horizontal_middle", + "y": 90 + }, + "casing=true,facing=west,part=middle,slope=sideways,waterlogged=false": { "model": "create:block/belt_casing/sideways_middle", "x": 180, "y": 90 }, - "casing=true,facing=west,part=middle,slope=upward": { + "casing=true,facing=west,part=middle,slope=sideways,waterlogged=true": { + "model": "create:block/belt_casing/sideways_middle", + "x": 180, + "y": 90 + }, + "casing=true,facing=west,part=middle,slope=upward,waterlogged=false": { "model": "create:block/belt_casing/diagonal_middle", "y": 270 }, - "casing=true,facing=west,part=middle,slope=vertical": { + "casing=true,facing=west,part=middle,slope=upward,waterlogged=true": { + "model": "create:block/belt_casing/diagonal_middle", + "y": 270 + }, + "casing=true,facing=west,part=middle,slope=vertical,waterlogged=false": { "model": "create:block/belt_casing/sideways_middle", "x": 90, "y": 180 }, - "casing=true,facing=west,part=pulley,slope=downward": { + "casing=true,facing=west,part=middle,slope=vertical,waterlogged=true": { + "model": "create:block/belt_casing/sideways_middle", + "x": 90, + "y": 180 + }, + "casing=true,facing=west,part=pulley,slope=downward,waterlogged=false": { "model": "create:block/belt_casing/diagonal_pulley", "y": 90 }, - "casing=true,facing=west,part=pulley,slope=horizontal": { + "casing=true,facing=west,part=pulley,slope=downward,waterlogged=true": { + "model": "create:block/belt_casing/diagonal_pulley", + "y": 90 + }, + "casing=true,facing=west,part=pulley,slope=horizontal,waterlogged=false": { "model": "create:block/belt_casing/horizontal_pulley", "y": 90 }, - "casing=true,facing=west,part=pulley,slope=sideways": { + "casing=true,facing=west,part=pulley,slope=horizontal,waterlogged=true": { + "model": "create:block/belt_casing/horizontal_pulley", + "y": 90 + }, + "casing=true,facing=west,part=pulley,slope=sideways,waterlogged=false": { "model": "create:block/belt_casing/sideways_pulley", "x": 180, "y": 90 }, - "casing=true,facing=west,part=pulley,slope=upward": { + "casing=true,facing=west,part=pulley,slope=sideways,waterlogged=true": { + "model": "create:block/belt_casing/sideways_pulley", + "x": 180, + "y": 90 + }, + "casing=true,facing=west,part=pulley,slope=upward,waterlogged=false": { "model": "create:block/belt_casing/diagonal_pulley", "y": 270 }, - "casing=true,facing=west,part=pulley,slope=vertical": { + "casing=true,facing=west,part=pulley,slope=upward,waterlogged=true": { + "model": "create:block/belt_casing/diagonal_pulley", + "y": 270 + }, + "casing=true,facing=west,part=pulley,slope=vertical,waterlogged=false": { "model": "create:block/belt_casing/sideways_pulley", "x": 90, "y": 180 }, - "casing=true,facing=west,part=start,slope=downward": { + "casing=true,facing=west,part=pulley,slope=vertical,waterlogged=true": { + "model": "create:block/belt_casing/sideways_pulley", + "x": 90, + "y": 180 + }, + "casing=true,facing=west,part=start,slope=downward,waterlogged=false": { "model": "create:block/belt_casing/diagonal_end", "y": 90 }, - "casing=true,facing=west,part=start,slope=horizontal": { + "casing=true,facing=west,part=start,slope=downward,waterlogged=true": { + "model": "create:block/belt_casing/diagonal_end", + "y": 90 + }, + "casing=true,facing=west,part=start,slope=horizontal,waterlogged=false": { "model": "create:block/belt_casing/horizontal_start", "y": 90 }, - "casing=true,facing=west,part=start,slope=sideways": { + "casing=true,facing=west,part=start,slope=horizontal,waterlogged=true": { + "model": "create:block/belt_casing/horizontal_start", + "y": 90 + }, + "casing=true,facing=west,part=start,slope=sideways,waterlogged=false": { "model": "create:block/belt_casing/sideways_end", "x": 180, "y": 90 }, - "casing=true,facing=west,part=start,slope=upward": { + "casing=true,facing=west,part=start,slope=sideways,waterlogged=true": { + "model": "create:block/belt_casing/sideways_end", + "x": 180, + "y": 90 + }, + "casing=true,facing=west,part=start,slope=upward,waterlogged=false": { "model": "create:block/belt_casing/diagonal_start", "y": 270 }, - "casing=true,facing=west,part=start,slope=vertical": { + "casing=true,facing=west,part=start,slope=upward,waterlogged=true": { + "model": "create:block/belt_casing/diagonal_start", + "y": 270 + }, + "casing=true,facing=west,part=start,slope=vertical,waterlogged=false": { + "model": "create:block/belt_casing/sideways_end", + "x": 90, + "y": 180 + }, + "casing=true,facing=west,part=start,slope=vertical,waterlogged=true": { "model": "create:block/belt_casing/sideways_end", "x": 90, "y": 180 diff --git a/src/generated/resources/assets/create/blockstates/brass_bars.json b/src/generated/resources/assets/create/blockstates/brass_bars.json new file mode 100644 index 000000000..2063ddf82 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/brass_bars.json @@ -0,0 +1,100 @@ +{ + "multipart": [ + { + "apply": { + "model": "create:block/brass_post_ends" + } + }, + { + "apply": { + "model": "create:block/brass_post" + }, + "when": { + "east": "false", + "north": "false", + "south": "false", + "west": "false" + } + }, + { + "apply": { + "model": "create:block/brass_cap" + }, + "when": { + "east": "false", + "north": "true", + "south": "false", + "west": "false" + } + }, + { + "apply": { + "model": "create:block/brass_cap", + "y": 90 + }, + "when": { + "east": "true", + "north": "false", + "south": "false", + "west": "false" + } + }, + { + "apply": { + "model": "create:block/brass_cap_alt" + }, + "when": { + "east": "false", + "north": "false", + "south": "true", + "west": "false" + } + }, + { + "apply": { + "model": "create:block/brass_cap_alt", + "y": 90 + }, + "when": { + "east": "false", + "north": "false", + "south": "false", + "west": "true" + } + }, + { + "apply": { + "model": "create:block/brass_side" + }, + "when": { + "north": "true" + } + }, + { + "apply": { + "model": "create:block/brass_side", + "y": 90 + }, + "when": { + "east": "true" + } + }, + { + "apply": { + "model": "create:block/brass_side_alt" + }, + "when": { + "south": "true" + } + }, + { + "apply": { + "model": "create:block/brass_side_alt", + "y": 90 + }, + "when": { + "west": "true" + } + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/brass_belt_funnel.json b/src/generated/resources/assets/create/blockstates/brass_belt_funnel.json index 2e22faa40..eb314bc97 100644 --- a/src/generated/resources/assets/create/blockstates/brass_belt_funnel.json +++ b/src/generated/resources/assets/create/blockstates/brass_belt_funnel.json @@ -1,122 +1,242 @@ { "variants": { - "facing=east,powered=false,shape=extended": { - "model": "create:block/brass_belt_funnel_extended", + "facing=east,powered=false,shape=extended,waterlogged=false": { + "model": "create:block/brass_belt_funnel_extended_unpowered", "y": 90 }, - "facing=east,powered=false,shape=pulling": { - "model": "create:block/brass_belt_funnel_pulling", + "facing=east,powered=false,shape=extended,waterlogged=true": { + "model": "create:block/brass_belt_funnel_extended_unpowered", "y": 90 }, - "facing=east,powered=false,shape=pushing": { - "model": "create:block/brass_belt_funnel_pushing", + "facing=east,powered=false,shape=pulling,waterlogged=false": { + "model": "create:block/brass_belt_funnel_pulling_unpowered", "y": 90 }, - "facing=east,powered=false,shape=retracted": { - "model": "create:block/brass_belt_funnel_retracted", + "facing=east,powered=false,shape=pulling,waterlogged=true": { + "model": "create:block/brass_belt_funnel_pulling_unpowered", "y": 90 }, - "facing=east,powered=true,shape=extended": { + "facing=east,powered=false,shape=pushing,waterlogged=false": { + "model": "create:block/brass_belt_funnel_pushing_unpowered", + "y": 90 + }, + "facing=east,powered=false,shape=pushing,waterlogged=true": { + "model": "create:block/brass_belt_funnel_pushing_unpowered", + "y": 90 + }, + "facing=east,powered=false,shape=retracted,waterlogged=false": { + "model": "create:block/brass_belt_funnel_retracted_unpowered", + "y": 90 + }, + "facing=east,powered=false,shape=retracted,waterlogged=true": { + "model": "create:block/brass_belt_funnel_retracted_unpowered", + "y": 90 + }, + "facing=east,powered=true,shape=extended,waterlogged=false": { "model": "create:block/brass_belt_funnel_extended_powered", "y": 90 }, - "facing=east,powered=true,shape=pulling": { + "facing=east,powered=true,shape=extended,waterlogged=true": { + "model": "create:block/brass_belt_funnel_extended_powered", + "y": 90 + }, + "facing=east,powered=true,shape=pulling,waterlogged=false": { "model": "create:block/brass_belt_funnel_pulling_powered", "y": 90 }, - "facing=east,powered=true,shape=pushing": { + "facing=east,powered=true,shape=pulling,waterlogged=true": { + "model": "create:block/brass_belt_funnel_pulling_powered", + "y": 90 + }, + "facing=east,powered=true,shape=pushing,waterlogged=false": { "model": "create:block/brass_belt_funnel_pushing_powered", "y": 90 }, - "facing=east,powered=true,shape=retracted": { + "facing=east,powered=true,shape=pushing,waterlogged=true": { + "model": "create:block/brass_belt_funnel_pushing_powered", + "y": 90 + }, + "facing=east,powered=true,shape=retracted,waterlogged=false": { "model": "create:block/brass_belt_funnel_retracted_powered", "y": 90 }, - "facing=north,powered=false,shape=extended": { - "model": "create:block/brass_belt_funnel_extended" + "facing=east,powered=true,shape=retracted,waterlogged=true": { + "model": "create:block/brass_belt_funnel_retracted_powered", + "y": 90 }, - "facing=north,powered=false,shape=pulling": { - "model": "create:block/brass_belt_funnel_pulling" + "facing=north,powered=false,shape=extended,waterlogged=false": { + "model": "create:block/brass_belt_funnel_extended_unpowered" }, - "facing=north,powered=false,shape=pushing": { - "model": "create:block/brass_belt_funnel_pushing" + "facing=north,powered=false,shape=extended,waterlogged=true": { + "model": "create:block/brass_belt_funnel_extended_unpowered" }, - "facing=north,powered=false,shape=retracted": { - "model": "create:block/brass_belt_funnel_retracted" + "facing=north,powered=false,shape=pulling,waterlogged=false": { + "model": "create:block/brass_belt_funnel_pulling_unpowered" }, - "facing=north,powered=true,shape=extended": { + "facing=north,powered=false,shape=pulling,waterlogged=true": { + "model": "create:block/brass_belt_funnel_pulling_unpowered" + }, + "facing=north,powered=false,shape=pushing,waterlogged=false": { + "model": "create:block/brass_belt_funnel_pushing_unpowered" + }, + "facing=north,powered=false,shape=pushing,waterlogged=true": { + "model": "create:block/brass_belt_funnel_pushing_unpowered" + }, + "facing=north,powered=false,shape=retracted,waterlogged=false": { + "model": "create:block/brass_belt_funnel_retracted_unpowered" + }, + "facing=north,powered=false,shape=retracted,waterlogged=true": { + "model": "create:block/brass_belt_funnel_retracted_unpowered" + }, + "facing=north,powered=true,shape=extended,waterlogged=false": { "model": "create:block/brass_belt_funnel_extended_powered" }, - "facing=north,powered=true,shape=pulling": { + "facing=north,powered=true,shape=extended,waterlogged=true": { + "model": "create:block/brass_belt_funnel_extended_powered" + }, + "facing=north,powered=true,shape=pulling,waterlogged=false": { "model": "create:block/brass_belt_funnel_pulling_powered" }, - "facing=north,powered=true,shape=pushing": { + "facing=north,powered=true,shape=pulling,waterlogged=true": { + "model": "create:block/brass_belt_funnel_pulling_powered" + }, + "facing=north,powered=true,shape=pushing,waterlogged=false": { "model": "create:block/brass_belt_funnel_pushing_powered" }, - "facing=north,powered=true,shape=retracted": { + "facing=north,powered=true,shape=pushing,waterlogged=true": { + "model": "create:block/brass_belt_funnel_pushing_powered" + }, + "facing=north,powered=true,shape=retracted,waterlogged=false": { "model": "create:block/brass_belt_funnel_retracted_powered" }, - "facing=south,powered=false,shape=extended": { - "model": "create:block/brass_belt_funnel_extended", + "facing=north,powered=true,shape=retracted,waterlogged=true": { + "model": "create:block/brass_belt_funnel_retracted_powered" + }, + "facing=south,powered=false,shape=extended,waterlogged=false": { + "model": "create:block/brass_belt_funnel_extended_unpowered", "y": 180 }, - "facing=south,powered=false,shape=pulling": { - "model": "create:block/brass_belt_funnel_pulling", + "facing=south,powered=false,shape=extended,waterlogged=true": { + "model": "create:block/brass_belt_funnel_extended_unpowered", "y": 180 }, - "facing=south,powered=false,shape=pushing": { - "model": "create:block/brass_belt_funnel_pushing", + "facing=south,powered=false,shape=pulling,waterlogged=false": { + "model": "create:block/brass_belt_funnel_pulling_unpowered", "y": 180 }, - "facing=south,powered=false,shape=retracted": { - "model": "create:block/brass_belt_funnel_retracted", + "facing=south,powered=false,shape=pulling,waterlogged=true": { + "model": "create:block/brass_belt_funnel_pulling_unpowered", "y": 180 }, - "facing=south,powered=true,shape=extended": { + "facing=south,powered=false,shape=pushing,waterlogged=false": { + "model": "create:block/brass_belt_funnel_pushing_unpowered", + "y": 180 + }, + "facing=south,powered=false,shape=pushing,waterlogged=true": { + "model": "create:block/brass_belt_funnel_pushing_unpowered", + "y": 180 + }, + "facing=south,powered=false,shape=retracted,waterlogged=false": { + "model": "create:block/brass_belt_funnel_retracted_unpowered", + "y": 180 + }, + "facing=south,powered=false,shape=retracted,waterlogged=true": { + "model": "create:block/brass_belt_funnel_retracted_unpowered", + "y": 180 + }, + "facing=south,powered=true,shape=extended,waterlogged=false": { "model": "create:block/brass_belt_funnel_extended_powered", "y": 180 }, - "facing=south,powered=true,shape=pulling": { + "facing=south,powered=true,shape=extended,waterlogged=true": { + "model": "create:block/brass_belt_funnel_extended_powered", + "y": 180 + }, + "facing=south,powered=true,shape=pulling,waterlogged=false": { "model": "create:block/brass_belt_funnel_pulling_powered", "y": 180 }, - "facing=south,powered=true,shape=pushing": { + "facing=south,powered=true,shape=pulling,waterlogged=true": { + "model": "create:block/brass_belt_funnel_pulling_powered", + "y": 180 + }, + "facing=south,powered=true,shape=pushing,waterlogged=false": { "model": "create:block/brass_belt_funnel_pushing_powered", "y": 180 }, - "facing=south,powered=true,shape=retracted": { + "facing=south,powered=true,shape=pushing,waterlogged=true": { + "model": "create:block/brass_belt_funnel_pushing_powered", + "y": 180 + }, + "facing=south,powered=true,shape=retracted,waterlogged=false": { "model": "create:block/brass_belt_funnel_retracted_powered", "y": 180 }, - "facing=west,powered=false,shape=extended": { - "model": "create:block/brass_belt_funnel_extended", + "facing=south,powered=true,shape=retracted,waterlogged=true": { + "model": "create:block/brass_belt_funnel_retracted_powered", + "y": 180 + }, + "facing=west,powered=false,shape=extended,waterlogged=false": { + "model": "create:block/brass_belt_funnel_extended_unpowered", "y": 270 }, - "facing=west,powered=false,shape=pulling": { - "model": "create:block/brass_belt_funnel_pulling", + "facing=west,powered=false,shape=extended,waterlogged=true": { + "model": "create:block/brass_belt_funnel_extended_unpowered", "y": 270 }, - "facing=west,powered=false,shape=pushing": { - "model": "create:block/brass_belt_funnel_pushing", + "facing=west,powered=false,shape=pulling,waterlogged=false": { + "model": "create:block/brass_belt_funnel_pulling_unpowered", "y": 270 }, - "facing=west,powered=false,shape=retracted": { - "model": "create:block/brass_belt_funnel_retracted", + "facing=west,powered=false,shape=pulling,waterlogged=true": { + "model": "create:block/brass_belt_funnel_pulling_unpowered", "y": 270 }, - "facing=west,powered=true,shape=extended": { + "facing=west,powered=false,shape=pushing,waterlogged=false": { + "model": "create:block/brass_belt_funnel_pushing_unpowered", + "y": 270 + }, + "facing=west,powered=false,shape=pushing,waterlogged=true": { + "model": "create:block/brass_belt_funnel_pushing_unpowered", + "y": 270 + }, + "facing=west,powered=false,shape=retracted,waterlogged=false": { + "model": "create:block/brass_belt_funnel_retracted_unpowered", + "y": 270 + }, + "facing=west,powered=false,shape=retracted,waterlogged=true": { + "model": "create:block/brass_belt_funnel_retracted_unpowered", + "y": 270 + }, + "facing=west,powered=true,shape=extended,waterlogged=false": { "model": "create:block/brass_belt_funnel_extended_powered", "y": 270 }, - "facing=west,powered=true,shape=pulling": { + "facing=west,powered=true,shape=extended,waterlogged=true": { + "model": "create:block/brass_belt_funnel_extended_powered", + "y": 270 + }, + "facing=west,powered=true,shape=pulling,waterlogged=false": { "model": "create:block/brass_belt_funnel_pulling_powered", "y": 270 }, - "facing=west,powered=true,shape=pushing": { + "facing=west,powered=true,shape=pulling,waterlogged=true": { + "model": "create:block/brass_belt_funnel_pulling_powered", + "y": 270 + }, + "facing=west,powered=true,shape=pushing,waterlogged=false": { "model": "create:block/brass_belt_funnel_pushing_powered", "y": 270 }, - "facing=west,powered=true,shape=retracted": { + "facing=west,powered=true,shape=pushing,waterlogged=true": { + "model": "create:block/brass_belt_funnel_pushing_powered", + "y": 270 + }, + "facing=west,powered=true,shape=retracted,waterlogged=false": { + "model": "create:block/brass_belt_funnel_retracted_powered", + "y": 270 + }, + "facing=west,powered=true,shape=retracted,waterlogged=true": { "model": "create:block/brass_belt_funnel_retracted_powered", "y": 270 } diff --git a/src/generated/resources/assets/create/blockstates/brass_door.json b/src/generated/resources/assets/create/blockstates/brass_door.json new file mode 100644 index 000000000..e11c07deb --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/brass_door.json @@ -0,0 +1,244 @@ +{ + "variants": { + "facing=east,half=lower,hinge=left,open=false,visible=false": { + "model": "create:block/brass_door/block_bottom" + }, + "facing=east,half=lower,hinge=left,open=false,visible=true": { + "model": "create:block/brass_door/block_bottom" + }, + "facing=east,half=lower,hinge=left,open=true,visible=false": { + "model": "create:block/brass_door/block_bottom", + "y": 90 + }, + "facing=east,half=lower,hinge=left,open=true,visible=true": { + "model": "create:block/brass_door/block_bottom", + "y": 90 + }, + "facing=east,half=lower,hinge=right,open=false,visible=false": { + "model": "create:block/brass_door/block_bottom" + }, + "facing=east,half=lower,hinge=right,open=false,visible=true": { + "model": "create:block/brass_door/block_bottom" + }, + "facing=east,half=lower,hinge=right,open=true,visible=false": { + "model": "create:block/brass_door/block_bottom", + "y": 270 + }, + "facing=east,half=lower,hinge=right,open=true,visible=true": { + "model": "create:block/brass_door/block_bottom", + "y": 270 + }, + "facing=east,half=upper,hinge=left,open=false,visible=false": { + "model": "create:block/brass_door/block_top" + }, + "facing=east,half=upper,hinge=left,open=false,visible=true": { + "model": "create:block/brass_door/block_top" + }, + "facing=east,half=upper,hinge=left,open=true,visible=false": { + "model": "create:block/brass_door/block_top", + "y": 90 + }, + "facing=east,half=upper,hinge=left,open=true,visible=true": { + "model": "create:block/brass_door/block_top", + "y": 90 + }, + "facing=east,half=upper,hinge=right,open=false,visible=false": { + "model": "create:block/brass_door/block_top" + }, + "facing=east,half=upper,hinge=right,open=false,visible=true": { + "model": "create:block/brass_door/block_top" + }, + "facing=east,half=upper,hinge=right,open=true,visible=false": { + "model": "create:block/brass_door/block_top", + "y": 270 + }, + "facing=east,half=upper,hinge=right,open=true,visible=true": { + "model": "create:block/brass_door/block_top", + "y": 270 + }, + "facing=north,half=lower,hinge=left,open=false,visible=false": { + "model": "create:block/brass_door/block_bottom", + "y": 270 + }, + "facing=north,half=lower,hinge=left,open=false,visible=true": { + "model": "create:block/brass_door/block_bottom", + "y": 270 + }, + "facing=north,half=lower,hinge=left,open=true,visible=false": { + "model": "create:block/brass_door/block_bottom" + }, + "facing=north,half=lower,hinge=left,open=true,visible=true": { + "model": "create:block/brass_door/block_bottom" + }, + "facing=north,half=lower,hinge=right,open=false,visible=false": { + "model": "create:block/brass_door/block_bottom", + "y": 270 + }, + "facing=north,half=lower,hinge=right,open=false,visible=true": { + "model": "create:block/brass_door/block_bottom", + "y": 270 + }, + "facing=north,half=lower,hinge=right,open=true,visible=false": { + "model": "create:block/brass_door/block_bottom", + "y": 180 + }, + "facing=north,half=lower,hinge=right,open=true,visible=true": { + "model": "create:block/brass_door/block_bottom", + "y": 180 + }, + "facing=north,half=upper,hinge=left,open=false,visible=false": { + "model": "create:block/brass_door/block_top", + "y": 270 + }, + "facing=north,half=upper,hinge=left,open=false,visible=true": { + "model": "create:block/brass_door/block_top", + "y": 270 + }, + "facing=north,half=upper,hinge=left,open=true,visible=false": { + "model": "create:block/brass_door/block_top" + }, + "facing=north,half=upper,hinge=left,open=true,visible=true": { + "model": "create:block/brass_door/block_top" + }, + "facing=north,half=upper,hinge=right,open=false,visible=false": { + "model": "create:block/brass_door/block_top", + "y": 270 + }, + "facing=north,half=upper,hinge=right,open=false,visible=true": { + "model": "create:block/brass_door/block_top", + "y": 270 + }, + "facing=north,half=upper,hinge=right,open=true,visible=false": { + "model": "create:block/brass_door/block_top", + "y": 180 + }, + "facing=north,half=upper,hinge=right,open=true,visible=true": { + "model": "create:block/brass_door/block_top", + "y": 180 + }, + "facing=south,half=lower,hinge=left,open=false,visible=false": { + "model": "create:block/brass_door/block_bottom", + "y": 90 + }, + "facing=south,half=lower,hinge=left,open=false,visible=true": { + "model": "create:block/brass_door/block_bottom", + "y": 90 + }, + "facing=south,half=lower,hinge=left,open=true,visible=false": { + "model": "create:block/brass_door/block_bottom", + "y": 180 + }, + "facing=south,half=lower,hinge=left,open=true,visible=true": { + "model": "create:block/brass_door/block_bottom", + "y": 180 + }, + "facing=south,half=lower,hinge=right,open=false,visible=false": { + "model": "create:block/brass_door/block_bottom", + "y": 90 + }, + "facing=south,half=lower,hinge=right,open=false,visible=true": { + "model": "create:block/brass_door/block_bottom", + "y": 90 + }, + "facing=south,half=lower,hinge=right,open=true,visible=false": { + "model": "create:block/brass_door/block_bottom" + }, + "facing=south,half=lower,hinge=right,open=true,visible=true": { + "model": "create:block/brass_door/block_bottom" + }, + "facing=south,half=upper,hinge=left,open=false,visible=false": { + "model": "create:block/brass_door/block_top", + "y": 90 + }, + "facing=south,half=upper,hinge=left,open=false,visible=true": { + "model": "create:block/brass_door/block_top", + "y": 90 + }, + "facing=south,half=upper,hinge=left,open=true,visible=false": { + "model": "create:block/brass_door/block_top", + "y": 180 + }, + "facing=south,half=upper,hinge=left,open=true,visible=true": { + "model": "create:block/brass_door/block_top", + "y": 180 + }, + "facing=south,half=upper,hinge=right,open=false,visible=false": { + "model": "create:block/brass_door/block_top", + "y": 90 + }, + "facing=south,half=upper,hinge=right,open=false,visible=true": { + "model": "create:block/brass_door/block_top", + "y": 90 + }, + "facing=south,half=upper,hinge=right,open=true,visible=false": { + "model": "create:block/brass_door/block_top" + }, + "facing=south,half=upper,hinge=right,open=true,visible=true": { + "model": "create:block/brass_door/block_top" + }, + "facing=west,half=lower,hinge=left,open=false,visible=false": { + "model": "create:block/brass_door/block_bottom", + "y": 180 + }, + "facing=west,half=lower,hinge=left,open=false,visible=true": { + "model": "create:block/brass_door/block_bottom", + "y": 180 + }, + "facing=west,half=lower,hinge=left,open=true,visible=false": { + "model": "create:block/brass_door/block_bottom", + "y": 270 + }, + "facing=west,half=lower,hinge=left,open=true,visible=true": { + "model": "create:block/brass_door/block_bottom", + "y": 270 + }, + "facing=west,half=lower,hinge=right,open=false,visible=false": { + "model": "create:block/brass_door/block_bottom", + "y": 180 + }, + "facing=west,half=lower,hinge=right,open=false,visible=true": { + "model": "create:block/brass_door/block_bottom", + "y": 180 + }, + "facing=west,half=lower,hinge=right,open=true,visible=false": { + "model": "create:block/brass_door/block_bottom", + "y": 90 + }, + "facing=west,half=lower,hinge=right,open=true,visible=true": { + "model": "create:block/brass_door/block_bottom", + "y": 90 + }, + "facing=west,half=upper,hinge=left,open=false,visible=false": { + "model": "create:block/brass_door/block_top", + "y": 180 + }, + "facing=west,half=upper,hinge=left,open=false,visible=true": { + "model": "create:block/brass_door/block_top", + "y": 180 + }, + "facing=west,half=upper,hinge=left,open=true,visible=false": { + "model": "create:block/brass_door/block_top", + "y": 270 + }, + "facing=west,half=upper,hinge=left,open=true,visible=true": { + "model": "create:block/brass_door/block_top", + "y": 270 + }, + "facing=west,half=upper,hinge=right,open=false,visible=false": { + "model": "create:block/brass_door/block_top", + "y": 180 + }, + "facing=west,half=upper,hinge=right,open=false,visible=true": { + "model": "create:block/brass_door/block_top", + "y": 180 + }, + "facing=west,half=upper,hinge=right,open=true,visible=false": { + "model": "create:block/brass_door/block_top", + "y": 90 + }, + "facing=west,half=upper,hinge=right,open=true,visible=true": { + "model": "create:block/brass_door/block_top", + "y": 90 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/brass_funnel.json b/src/generated/resources/assets/create/blockstates/brass_funnel.json index 3c6d9e073..cab8c6786 100644 --- a/src/generated/resources/assets/create/blockstates/brass_funnel.json +++ b/src/generated/resources/assets/create/blockstates/brass_funnel.json @@ -1,98 +1,194 @@ { "variants": { - "extracting=false,facing=down,powered=false": { - "model": "create:block/brass_funnel_vertical_pull", + "extracting=false,facing=down,powered=false,waterlogged=false": { + "model": "create:block/brass_funnel_vertical_pull_unpowered", "x": 180, "y": 180 }, - "extracting=false,facing=down,powered=true": { + "extracting=false,facing=down,powered=false,waterlogged=true": { + "model": "create:block/brass_funnel_vertical_pull_unpowered", + "x": 180, + "y": 180 + }, + "extracting=false,facing=down,powered=true,waterlogged=false": { "model": "create:block/brass_funnel_vertical_pull_powered", "x": 180, "y": 180 }, - "extracting=false,facing=east,powered=false": { - "model": "create:block/brass_funnel_horizontal_pull", + "extracting=false,facing=down,powered=true,waterlogged=true": { + "model": "create:block/brass_funnel_vertical_pull_powered", + "x": 180, + "y": 180 + }, + "extracting=false,facing=east,powered=false,waterlogged=false": { + "model": "create:block/brass_funnel_horizontal_pull_unpowered", "y": 90 }, - "extracting=false,facing=east,powered=true": { + "extracting=false,facing=east,powered=false,waterlogged=true": { + "model": "create:block/brass_funnel_horizontal_pull_unpowered", + "y": 90 + }, + "extracting=false,facing=east,powered=true,waterlogged=false": { "model": "create:block/brass_funnel_horizontal_pull_powered", "y": 90 }, - "extracting=false,facing=north,powered=false": { - "model": "create:block/brass_funnel_horizontal_pull" + "extracting=false,facing=east,powered=true,waterlogged=true": { + "model": "create:block/brass_funnel_horizontal_pull_powered", + "y": 90 }, - "extracting=false,facing=north,powered=true": { + "extracting=false,facing=north,powered=false,waterlogged=false": { + "model": "create:block/brass_funnel_horizontal_pull_unpowered" + }, + "extracting=false,facing=north,powered=false,waterlogged=true": { + "model": "create:block/brass_funnel_horizontal_pull_unpowered" + }, + "extracting=false,facing=north,powered=true,waterlogged=false": { "model": "create:block/brass_funnel_horizontal_pull_powered" }, - "extracting=false,facing=south,powered=false": { - "model": "create:block/brass_funnel_horizontal_pull", + "extracting=false,facing=north,powered=true,waterlogged=true": { + "model": "create:block/brass_funnel_horizontal_pull_powered" + }, + "extracting=false,facing=south,powered=false,waterlogged=false": { + "model": "create:block/brass_funnel_horizontal_pull_unpowered", "y": 180 }, - "extracting=false,facing=south,powered=true": { + "extracting=false,facing=south,powered=false,waterlogged=true": { + "model": "create:block/brass_funnel_horizontal_pull_unpowered", + "y": 180 + }, + "extracting=false,facing=south,powered=true,waterlogged=false": { "model": "create:block/brass_funnel_horizontal_pull_powered", "y": 180 }, - "extracting=false,facing=up,powered=false": { - "model": "create:block/brass_funnel_vertical_pull", + "extracting=false,facing=south,powered=true,waterlogged=true": { + "model": "create:block/brass_funnel_horizontal_pull_powered", "y": 180 }, - "extracting=false,facing=up,powered=true": { + "extracting=false,facing=up,powered=false,waterlogged=false": { + "model": "create:block/brass_funnel_vertical_pull_unpowered", + "y": 180 + }, + "extracting=false,facing=up,powered=false,waterlogged=true": { + "model": "create:block/brass_funnel_vertical_pull_unpowered", + "y": 180 + }, + "extracting=false,facing=up,powered=true,waterlogged=false": { "model": "create:block/brass_funnel_vertical_pull_powered", "y": 180 }, - "extracting=false,facing=west,powered=false": { - "model": "create:block/brass_funnel_horizontal_pull", + "extracting=false,facing=up,powered=true,waterlogged=true": { + "model": "create:block/brass_funnel_vertical_pull_powered", + "y": 180 + }, + "extracting=false,facing=west,powered=false,waterlogged=false": { + "model": "create:block/brass_funnel_horizontal_pull_unpowered", "y": 270 }, - "extracting=false,facing=west,powered=true": { + "extracting=false,facing=west,powered=false,waterlogged=true": { + "model": "create:block/brass_funnel_horizontal_pull_unpowered", + "y": 270 + }, + "extracting=false,facing=west,powered=true,waterlogged=false": { "model": "create:block/brass_funnel_horizontal_pull_powered", "y": 270 }, - "extracting=true,facing=down,powered=false": { - "model": "create:block/brass_funnel_vertical_push", - "x": 180, - "y": 180 - }, - "extracting=true,facing=down,powered=true": { - "model": "create:block/brass_funnel_vertical_push_powered", - "x": 180, - "y": 180 - }, - "extracting=true,facing=east,powered=false": { - "model": "create:block/brass_funnel_horizontal_push", - "y": 90 - }, - "extracting=true,facing=east,powered=true": { - "model": "create:block/brass_funnel_horizontal_push_powered", - "y": 90 - }, - "extracting=true,facing=north,powered=false": { - "model": "create:block/brass_funnel_horizontal_push" - }, - "extracting=true,facing=north,powered=true": { - "model": "create:block/brass_funnel_horizontal_push_powered" - }, - "extracting=true,facing=south,powered=false": { - "model": "create:block/brass_funnel_horizontal_push", - "y": 180 - }, - "extracting=true,facing=south,powered=true": { - "model": "create:block/brass_funnel_horizontal_push_powered", - "y": 180 - }, - "extracting=true,facing=up,powered=false": { - "model": "create:block/brass_funnel_vertical_push", - "y": 180 - }, - "extracting=true,facing=up,powered=true": { - "model": "create:block/brass_funnel_vertical_push_powered", - "y": 180 - }, - "extracting=true,facing=west,powered=false": { - "model": "create:block/brass_funnel_horizontal_push", + "extracting=false,facing=west,powered=true,waterlogged=true": { + "model": "create:block/brass_funnel_horizontal_pull_powered", "y": 270 }, - "extracting=true,facing=west,powered=true": { + "extracting=true,facing=down,powered=false,waterlogged=false": { + "model": "create:block/brass_funnel_vertical_push_unpowered", + "x": 180, + "y": 180 + }, + "extracting=true,facing=down,powered=false,waterlogged=true": { + "model": "create:block/brass_funnel_vertical_push_unpowered", + "x": 180, + "y": 180 + }, + "extracting=true,facing=down,powered=true,waterlogged=false": { + "model": "create:block/brass_funnel_vertical_push_powered", + "x": 180, + "y": 180 + }, + "extracting=true,facing=down,powered=true,waterlogged=true": { + "model": "create:block/brass_funnel_vertical_push_powered", + "x": 180, + "y": 180 + }, + "extracting=true,facing=east,powered=false,waterlogged=false": { + "model": "create:block/brass_funnel_horizontal_push_unpowered", + "y": 90 + }, + "extracting=true,facing=east,powered=false,waterlogged=true": { + "model": "create:block/brass_funnel_horizontal_push_unpowered", + "y": 90 + }, + "extracting=true,facing=east,powered=true,waterlogged=false": { + "model": "create:block/brass_funnel_horizontal_push_powered", + "y": 90 + }, + "extracting=true,facing=east,powered=true,waterlogged=true": { + "model": "create:block/brass_funnel_horizontal_push_powered", + "y": 90 + }, + "extracting=true,facing=north,powered=false,waterlogged=false": { + "model": "create:block/brass_funnel_horizontal_push_unpowered" + }, + "extracting=true,facing=north,powered=false,waterlogged=true": { + "model": "create:block/brass_funnel_horizontal_push_unpowered" + }, + "extracting=true,facing=north,powered=true,waterlogged=false": { + "model": "create:block/brass_funnel_horizontal_push_powered" + }, + "extracting=true,facing=north,powered=true,waterlogged=true": { + "model": "create:block/brass_funnel_horizontal_push_powered" + }, + "extracting=true,facing=south,powered=false,waterlogged=false": { + "model": "create:block/brass_funnel_horizontal_push_unpowered", + "y": 180 + }, + "extracting=true,facing=south,powered=false,waterlogged=true": { + "model": "create:block/brass_funnel_horizontal_push_unpowered", + "y": 180 + }, + "extracting=true,facing=south,powered=true,waterlogged=false": { + "model": "create:block/brass_funnel_horizontal_push_powered", + "y": 180 + }, + "extracting=true,facing=south,powered=true,waterlogged=true": { + "model": "create:block/brass_funnel_horizontal_push_powered", + "y": 180 + }, + "extracting=true,facing=up,powered=false,waterlogged=false": { + "model": "create:block/brass_funnel_vertical_push_unpowered", + "y": 180 + }, + "extracting=true,facing=up,powered=false,waterlogged=true": { + "model": "create:block/brass_funnel_vertical_push_unpowered", + "y": 180 + }, + "extracting=true,facing=up,powered=true,waterlogged=false": { + "model": "create:block/brass_funnel_vertical_push_powered", + "y": 180 + }, + "extracting=true,facing=up,powered=true,waterlogged=true": { + "model": "create:block/brass_funnel_vertical_push_powered", + "y": 180 + }, + "extracting=true,facing=west,powered=false,waterlogged=false": { + "model": "create:block/brass_funnel_horizontal_push_unpowered", + "y": 270 + }, + "extracting=true,facing=west,powered=false,waterlogged=true": { + "model": "create:block/brass_funnel_horizontal_push_unpowered", + "y": 270 + }, + "extracting=true,facing=west,powered=true,waterlogged=false": { + "model": "create:block/brass_funnel_horizontal_push_powered", + "y": 270 + }, + "extracting=true,facing=west,powered=true,waterlogged=true": { "model": "create:block/brass_funnel_horizontal_push_powered", "y": 270 } diff --git a/src/generated/resources/assets/create/blockstates/brass_scaffolding.json b/src/generated/resources/assets/create/blockstates/brass_scaffolding.json new file mode 100644 index 000000000..422df16da --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/brass_scaffolding.json @@ -0,0 +1,10 @@ +{ + "variants": { + "bottom=false": { + "model": "create:block/brass_scaffolding" + }, + "bottom=true": { + "model": "create:block/brass_scaffolding_horizontal" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/brass_tunnel.json b/src/generated/resources/assets/create/blockstates/brass_tunnel.json index 7edc2c490..a740f53b1 100644 --- a/src/generated/resources/assets/create/blockstates/brass_tunnel.json +++ b/src/generated/resources/assets/create/blockstates/brass_tunnel.json @@ -1,45 +1,45 @@ { "variants": { "axis=x,shape=closed": { - "model": "create:block/brass_tunnel/straight" + "model": "create:block/tunnel/brass_tunnel/straight" }, "axis=x,shape=cross": { - "model": "create:block/brass_tunnel/cross" + "model": "create:block/tunnel/brass_tunnel/cross" }, "axis=x,shape=straight": { - "model": "create:block/brass_tunnel/straight" + "model": "create:block/tunnel/brass_tunnel/straight" }, "axis=x,shape=t_left": { - "model": "create:block/brass_tunnel/t_left" + "model": "create:block/tunnel/brass_tunnel/t_left" }, "axis=x,shape=t_right": { - "model": "create:block/brass_tunnel/t_right" + "model": "create:block/tunnel/brass_tunnel/t_right" }, "axis=x,shape=window": { - "model": "create:block/brass_tunnel/window" + "model": "create:block/tunnel/brass_tunnel/window" }, "axis=z,shape=closed": { - "model": "create:block/brass_tunnel/straight", + "model": "create:block/tunnel/brass_tunnel/straight", "y": 90 }, "axis=z,shape=cross": { - "model": "create:block/brass_tunnel/cross", + "model": "create:block/tunnel/brass_tunnel/cross", "y": 90 }, "axis=z,shape=straight": { - "model": "create:block/brass_tunnel/straight", + "model": "create:block/tunnel/brass_tunnel/straight", "y": 90 }, "axis=z,shape=t_left": { - "model": "create:block/brass_tunnel/t_left", + "model": "create:block/tunnel/brass_tunnel/t_left", "y": 90 }, "axis=z,shape=t_right": { - "model": "create:block/brass_tunnel/t_right", + "model": "create:block/tunnel/brass_tunnel/t_right", "y": 90 }, "axis=z,shape=window": { - "model": "create:block/brass_tunnel/window", + "model": "create:block/tunnel/brass_tunnel/window", "y": 90 } } diff --git a/src/generated/resources/assets/create/blockstates/chute.json b/src/generated/resources/assets/create/blockstates/chute.json index ee09f0e44..664aa6519 100644 --- a/src/generated/resources/assets/create/blockstates/chute.json +++ b/src/generated/resources/assets/create/blockstates/chute.json @@ -1,56 +1,146 @@ { "variants": { - "facing=down,shape=intersection": { + "facing=down,shape=encased,waterlogged=false": { "model": "create:block/chute/block_intersection" }, - "facing=down,shape=normal": { + "facing=down,shape=encased,waterlogged=true": { + "model": "create:block/chute/block_intersection" + }, + "facing=down,shape=intersection,waterlogged=false": { + "model": "create:block/chute/block_intersection" + }, + "facing=down,shape=intersection,waterlogged=true": { + "model": "create:block/chute/block_intersection" + }, + "facing=down,shape=normal,waterlogged=false": { "model": "create:block/chute/block" }, - "facing=down,shape=window": { + "facing=down,shape=normal,waterlogged=true": { + "model": "create:block/chute/block" + }, + "facing=down,shape=window,waterlogged=false": { "model": "create:block/chute/block_windowed" }, - "facing=east,shape=intersection": { + "facing=down,shape=window,waterlogged=true": { + "model": "create:block/chute/block_windowed" + }, + "facing=east,shape=encased,waterlogged=false": { + "model": "create:block/chute/block_diagonal_encased", + "y": 270 + }, + "facing=east,shape=encased,waterlogged=true": { + "model": "create:block/chute/block_diagonal_encased", + "y": 270 + }, + "facing=east,shape=intersection,waterlogged=false": { "model": "create:block/chute/block_diagonal_intersection", "y": 270 }, - "facing=east,shape=normal": { + "facing=east,shape=intersection,waterlogged=true": { + "model": "create:block/chute/block_diagonal_intersection", + "y": 270 + }, + "facing=east,shape=normal,waterlogged=false": { "model": "create:block/chute/block_diagonal", "y": 270 }, - "facing=east,shape=window": { + "facing=east,shape=normal,waterlogged=true": { "model": "create:block/chute/block_diagonal", "y": 270 }, - "facing=north,shape=intersection": { + "facing=east,shape=window,waterlogged=false": { + "model": "create:block/chute/block_diagonal", + "y": 270 + }, + "facing=east,shape=window,waterlogged=true": { + "model": "create:block/chute/block_diagonal", + "y": 270 + }, + "facing=north,shape=encased,waterlogged=false": { + "model": "create:block/chute/block_diagonal_encased", + "y": 180 + }, + "facing=north,shape=encased,waterlogged=true": { + "model": "create:block/chute/block_diagonal_encased", + "y": 180 + }, + "facing=north,shape=intersection,waterlogged=false": { "model": "create:block/chute/block_diagonal_intersection", "y": 180 }, - "facing=north,shape=normal": { + "facing=north,shape=intersection,waterlogged=true": { + "model": "create:block/chute/block_diagonal_intersection", + "y": 180 + }, + "facing=north,shape=normal,waterlogged=false": { "model": "create:block/chute/block_diagonal", "y": 180 }, - "facing=north,shape=window": { + "facing=north,shape=normal,waterlogged=true": { "model": "create:block/chute/block_diagonal", "y": 180 }, - "facing=south,shape=intersection": { + "facing=north,shape=window,waterlogged=false": { + "model": "create:block/chute/block_diagonal", + "y": 180 + }, + "facing=north,shape=window,waterlogged=true": { + "model": "create:block/chute/block_diagonal", + "y": 180 + }, + "facing=south,shape=encased,waterlogged=false": { + "model": "create:block/chute/block_diagonal_encased" + }, + "facing=south,shape=encased,waterlogged=true": { + "model": "create:block/chute/block_diagonal_encased" + }, + "facing=south,shape=intersection,waterlogged=false": { "model": "create:block/chute/block_diagonal_intersection" }, - "facing=south,shape=normal": { + "facing=south,shape=intersection,waterlogged=true": { + "model": "create:block/chute/block_diagonal_intersection" + }, + "facing=south,shape=normal,waterlogged=false": { "model": "create:block/chute/block_diagonal" }, - "facing=south,shape=window": { + "facing=south,shape=normal,waterlogged=true": { "model": "create:block/chute/block_diagonal" }, - "facing=west,shape=intersection": { + "facing=south,shape=window,waterlogged=false": { + "model": "create:block/chute/block_diagonal" + }, + "facing=south,shape=window,waterlogged=true": { + "model": "create:block/chute/block_diagonal" + }, + "facing=west,shape=encased,waterlogged=false": { + "model": "create:block/chute/block_diagonal_encased", + "y": 90 + }, + "facing=west,shape=encased,waterlogged=true": { + "model": "create:block/chute/block_diagonal_encased", + "y": 90 + }, + "facing=west,shape=intersection,waterlogged=false": { "model": "create:block/chute/block_diagonal_intersection", "y": 90 }, - "facing=west,shape=normal": { + "facing=west,shape=intersection,waterlogged=true": { + "model": "create:block/chute/block_diagonal_intersection", + "y": 90 + }, + "facing=west,shape=normal,waterlogged=false": { "model": "create:block/chute/block_diagonal", "y": 90 }, - "facing=west,shape=window": { + "facing=west,shape=normal,waterlogged=true": { + "model": "create:block/chute/block_diagonal", + "y": 90 + }, + "facing=west,shape=window,waterlogged=false": { + "model": "create:block/chute/block_diagonal", + "y": 90 + }, + "facing=west,shape=window,waterlogged=true": { "model": "create:block/chute/block_diagonal", "y": 90 } diff --git a/src/generated/resources/assets/create/blockstates/clipboard.json b/src/generated/resources/assets/create/blockstates/clipboard.json new file mode 100644 index 000000000..72645941e --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/clipboard.json @@ -0,0 +1,216 @@ +{ + "variants": { + "face=ceiling,facing=east,waterlogged=false,written=false": { + "model": "create:block/clipboard/block_empty", + "x": 180, + "y": 270 + }, + "face=ceiling,facing=east,waterlogged=false,written=true": { + "model": "create:block/clipboard/block_written", + "x": 180, + "y": 270 + }, + "face=ceiling,facing=east,waterlogged=true,written=false": { + "model": "create:block/clipboard/block_empty", + "x": 180, + "y": 270 + }, + "face=ceiling,facing=east,waterlogged=true,written=true": { + "model": "create:block/clipboard/block_written", + "x": 180, + "y": 270 + }, + "face=ceiling,facing=north,waterlogged=false,written=false": { + "model": "create:block/clipboard/block_empty", + "x": 180, + "y": 180 + }, + "face=ceiling,facing=north,waterlogged=false,written=true": { + "model": "create:block/clipboard/block_written", + "x": 180, + "y": 180 + }, + "face=ceiling,facing=north,waterlogged=true,written=false": { + "model": "create:block/clipboard/block_empty", + "x": 180, + "y": 180 + }, + "face=ceiling,facing=north,waterlogged=true,written=true": { + "model": "create:block/clipboard/block_written", + "x": 180, + "y": 180 + }, + "face=ceiling,facing=south,waterlogged=false,written=false": { + "model": "create:block/clipboard/block_empty", + "x": 180 + }, + "face=ceiling,facing=south,waterlogged=false,written=true": { + "model": "create:block/clipboard/block_written", + "x": 180 + }, + "face=ceiling,facing=south,waterlogged=true,written=false": { + "model": "create:block/clipboard/block_empty", + "x": 180 + }, + "face=ceiling,facing=south,waterlogged=true,written=true": { + "model": "create:block/clipboard/block_written", + "x": 180 + }, + "face=ceiling,facing=west,waterlogged=false,written=false": { + "model": "create:block/clipboard/block_empty", + "x": 180, + "y": 90 + }, + "face=ceiling,facing=west,waterlogged=false,written=true": { + "model": "create:block/clipboard/block_written", + "x": 180, + "y": 90 + }, + "face=ceiling,facing=west,waterlogged=true,written=false": { + "model": "create:block/clipboard/block_empty", + "x": 180, + "y": 90 + }, + "face=ceiling,facing=west,waterlogged=true,written=true": { + "model": "create:block/clipboard/block_written", + "x": 180, + "y": 90 + }, + "face=floor,facing=east,waterlogged=false,written=false": { + "model": "create:block/clipboard/block_empty", + "y": 90 + }, + "face=floor,facing=east,waterlogged=false,written=true": { + "model": "create:block/clipboard/block_written", + "y": 90 + }, + "face=floor,facing=east,waterlogged=true,written=false": { + "model": "create:block/clipboard/block_empty", + "y": 90 + }, + "face=floor,facing=east,waterlogged=true,written=true": { + "model": "create:block/clipboard/block_written", + "y": 90 + }, + "face=floor,facing=north,waterlogged=false,written=false": { + "model": "create:block/clipboard/block_empty" + }, + "face=floor,facing=north,waterlogged=false,written=true": { + "model": "create:block/clipboard/block_written" + }, + "face=floor,facing=north,waterlogged=true,written=false": { + "model": "create:block/clipboard/block_empty" + }, + "face=floor,facing=north,waterlogged=true,written=true": { + "model": "create:block/clipboard/block_written" + }, + "face=floor,facing=south,waterlogged=false,written=false": { + "model": "create:block/clipboard/block_empty", + "y": 180 + }, + "face=floor,facing=south,waterlogged=false,written=true": { + "model": "create:block/clipboard/block_written", + "y": 180 + }, + "face=floor,facing=south,waterlogged=true,written=false": { + "model": "create:block/clipboard/block_empty", + "y": 180 + }, + "face=floor,facing=south,waterlogged=true,written=true": { + "model": "create:block/clipboard/block_written", + "y": 180 + }, + "face=floor,facing=west,waterlogged=false,written=false": { + "model": "create:block/clipboard/block_empty", + "y": 270 + }, + "face=floor,facing=west,waterlogged=false,written=true": { + "model": "create:block/clipboard/block_written", + "y": 270 + }, + "face=floor,facing=west,waterlogged=true,written=false": { + "model": "create:block/clipboard/block_empty", + "y": 270 + }, + "face=floor,facing=west,waterlogged=true,written=true": { + "model": "create:block/clipboard/block_written", + "y": 270 + }, + "face=wall,facing=east,waterlogged=false,written=false": { + "model": "create:block/clipboard/block_empty", + "x": 90, + "y": 90 + }, + "face=wall,facing=east,waterlogged=false,written=true": { + "model": "create:block/clipboard/block_written", + "x": 90, + "y": 90 + }, + "face=wall,facing=east,waterlogged=true,written=false": { + "model": "create:block/clipboard/block_empty", + "x": 90, + "y": 90 + }, + "face=wall,facing=east,waterlogged=true,written=true": { + "model": "create:block/clipboard/block_written", + "x": 90, + "y": 90 + }, + "face=wall,facing=north,waterlogged=false,written=false": { + "model": "create:block/clipboard/block_empty", + "x": 90 + }, + "face=wall,facing=north,waterlogged=false,written=true": { + "model": "create:block/clipboard/block_written", + "x": 90 + }, + "face=wall,facing=north,waterlogged=true,written=false": { + "model": "create:block/clipboard/block_empty", + "x": 90 + }, + "face=wall,facing=north,waterlogged=true,written=true": { + "model": "create:block/clipboard/block_written", + "x": 90 + }, + "face=wall,facing=south,waterlogged=false,written=false": { + "model": "create:block/clipboard/block_empty", + "x": 90, + "y": 180 + }, + "face=wall,facing=south,waterlogged=false,written=true": { + "model": "create:block/clipboard/block_written", + "x": 90, + "y": 180 + }, + "face=wall,facing=south,waterlogged=true,written=false": { + "model": "create:block/clipboard/block_empty", + "x": 90, + "y": 180 + }, + "face=wall,facing=south,waterlogged=true,written=true": { + "model": "create:block/clipboard/block_written", + "x": 90, + "y": 180 + }, + "face=wall,facing=west,waterlogged=false,written=false": { + "model": "create:block/clipboard/block_empty", + "x": 90, + "y": 270 + }, + "face=wall,facing=west,waterlogged=false,written=true": { + "model": "create:block/clipboard/block_written", + "x": 90, + "y": 270 + }, + "face=wall,facing=west,waterlogged=true,written=false": { + "model": "create:block/clipboard/block_empty", + "x": 90, + "y": 270 + }, + "face=wall,facing=west,waterlogged=true,written=true": { + "model": "create:block/clipboard/block_written", + "x": 90, + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/content_observer.json b/src/generated/resources/assets/create/blockstates/content_observer.json index f974c2332..a4ef705c2 100644 --- a/src/generated/resources/assets/create/blockstates/content_observer.json +++ b/src/generated/resources/assets/create/blockstates/content_observer.json @@ -1,32 +1,108 @@ { "variants": { - "facing=east,powered=false": { + "facing=east,powered=false,target=ceiling": { + "model": "create:block/content_observer/block", + "x": 270, + "y": 90 + }, + "facing=east,powered=false,target=floor": { + "model": "create:block/content_observer/block", + "x": 90, + "y": 90 + }, + "facing=east,powered=false,target=wall": { "model": "create:block/content_observer/block", "y": 90 }, - "facing=east,powered=true": { + "facing=east,powered=true,target=ceiling": { + "model": "create:block/content_observer/block_powered", + "x": 270, + "y": 90 + }, + "facing=east,powered=true,target=floor": { + "model": "create:block/content_observer/block_powered", + "x": 90, + "y": 90 + }, + "facing=east,powered=true,target=wall": { "model": "create:block/content_observer/block_powered", "y": 90 }, - "facing=north,powered=false": { + "facing=north,powered=false,target=ceiling": { + "model": "create:block/content_observer/block", + "x": 270 + }, + "facing=north,powered=false,target=floor": { + "model": "create:block/content_observer/block", + "x": 90 + }, + "facing=north,powered=false,target=wall": { "model": "create:block/content_observer/block" }, - "facing=north,powered=true": { + "facing=north,powered=true,target=ceiling": { + "model": "create:block/content_observer/block_powered", + "x": 270 + }, + "facing=north,powered=true,target=floor": { + "model": "create:block/content_observer/block_powered", + "x": 90 + }, + "facing=north,powered=true,target=wall": { "model": "create:block/content_observer/block_powered" }, - "facing=south,powered=false": { + "facing=south,powered=false,target=ceiling": { + "model": "create:block/content_observer/block", + "x": 270, + "y": 180 + }, + "facing=south,powered=false,target=floor": { + "model": "create:block/content_observer/block", + "x": 90, + "y": 180 + }, + "facing=south,powered=false,target=wall": { "model": "create:block/content_observer/block", "y": 180 }, - "facing=south,powered=true": { + "facing=south,powered=true,target=ceiling": { + "model": "create:block/content_observer/block_powered", + "x": 270, + "y": 180 + }, + "facing=south,powered=true,target=floor": { + "model": "create:block/content_observer/block_powered", + "x": 90, + "y": 180 + }, + "facing=south,powered=true,target=wall": { "model": "create:block/content_observer/block_powered", "y": 180 }, - "facing=west,powered=false": { + "facing=west,powered=false,target=ceiling": { + "model": "create:block/content_observer/block", + "x": 270, + "y": 270 + }, + "facing=west,powered=false,target=floor": { + "model": "create:block/content_observer/block", + "x": 90, + "y": 270 + }, + "facing=west,powered=false,target=wall": { "model": "create:block/content_observer/block", "y": 270 }, - "facing=west,powered=true": { + "facing=west,powered=true,target=ceiling": { + "model": "create:block/content_observer/block_powered", + "x": 270, + "y": 270 + }, + "facing=west,powered=true,target=floor": { + "model": "create:block/content_observer/block_powered", + "x": 90, + "y": 270 + }, + "facing=west,powered=true,target=wall": { "model": "create:block/content_observer/block_powered", "y": 270 } diff --git a/src/generated/resources/assets/create/blockstates/contraption_controls.json b/src/generated/resources/assets/create/blockstates/contraption_controls.json new file mode 100644 index 000000000..62c765e7c --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/contraption_controls.json @@ -0,0 +1,124 @@ +{ + "variants": { + "facing=east,open=false,virtual=false,waterlogged=false": { + "model": "create:block/contraption_controls/block", + "y": 90 + }, + "facing=east,open=false,virtual=false,waterlogged=true": { + "model": "create:block/contraption_controls/block", + "y": 90 + }, + "facing=east,open=false,virtual=true,waterlogged=false": { + "model": "create:block/contraption_controls/block", + "y": 90 + }, + "facing=east,open=false,virtual=true,waterlogged=true": { + "model": "create:block/contraption_controls/block", + "y": 90 + }, + "facing=east,open=true,virtual=false,waterlogged=false": { + "model": "create:block/contraption_controls/block", + "y": 90 + }, + "facing=east,open=true,virtual=false,waterlogged=true": { + "model": "create:block/contraption_controls/block", + "y": 90 + }, + "facing=east,open=true,virtual=true,waterlogged=false": { + "model": "create:block/contraption_controls/block", + "y": 90 + }, + "facing=east,open=true,virtual=true,waterlogged=true": { + "model": "create:block/contraption_controls/block", + "y": 90 + }, + "facing=north,open=false,virtual=false,waterlogged=false": { + "model": "create:block/contraption_controls/block" + }, + "facing=north,open=false,virtual=false,waterlogged=true": { + "model": "create:block/contraption_controls/block" + }, + "facing=north,open=false,virtual=true,waterlogged=false": { + "model": "create:block/contraption_controls/block" + }, + "facing=north,open=false,virtual=true,waterlogged=true": { + "model": "create:block/contraption_controls/block" + }, + "facing=north,open=true,virtual=false,waterlogged=false": { + "model": "create:block/contraption_controls/block" + }, + "facing=north,open=true,virtual=false,waterlogged=true": { + "model": "create:block/contraption_controls/block" + }, + "facing=north,open=true,virtual=true,waterlogged=false": { + "model": "create:block/contraption_controls/block" + }, + "facing=north,open=true,virtual=true,waterlogged=true": { + "model": "create:block/contraption_controls/block" + }, + "facing=south,open=false,virtual=false,waterlogged=false": { + "model": "create:block/contraption_controls/block", + "y": 180 + }, + "facing=south,open=false,virtual=false,waterlogged=true": { + "model": "create:block/contraption_controls/block", + "y": 180 + }, + "facing=south,open=false,virtual=true,waterlogged=false": { + "model": "create:block/contraption_controls/block", + "y": 180 + }, + "facing=south,open=false,virtual=true,waterlogged=true": { + "model": "create:block/contraption_controls/block", + "y": 180 + }, + "facing=south,open=true,virtual=false,waterlogged=false": { + "model": "create:block/contraption_controls/block", + "y": 180 + }, + "facing=south,open=true,virtual=false,waterlogged=true": { + "model": "create:block/contraption_controls/block", + "y": 180 + }, + "facing=south,open=true,virtual=true,waterlogged=false": { + "model": "create:block/contraption_controls/block", + "y": 180 + }, + "facing=south,open=true,virtual=true,waterlogged=true": { + "model": "create:block/contraption_controls/block", + "y": 180 + }, + "facing=west,open=false,virtual=false,waterlogged=false": { + "model": "create:block/contraption_controls/block", + "y": 270 + }, + "facing=west,open=false,virtual=false,waterlogged=true": { + "model": "create:block/contraption_controls/block", + "y": 270 + }, + "facing=west,open=false,virtual=true,waterlogged=false": { + "model": "create:block/contraption_controls/block", + "y": 270 + }, + "facing=west,open=false,virtual=true,waterlogged=true": { + "model": "create:block/contraption_controls/block", + "y": 270 + }, + "facing=west,open=true,virtual=false,waterlogged=false": { + "model": "create:block/contraption_controls/block", + "y": 270 + }, + "facing=west,open=true,virtual=false,waterlogged=true": { + "model": "create:block/contraption_controls/block", + "y": 270 + }, + "facing=west,open=true,virtual=true,waterlogged=false": { + "model": "create:block/contraption_controls/block", + "y": 270 + }, + "facing=west,open=true,virtual=true,waterlogged=true": { + "model": "create:block/contraption_controls/block", + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/copper_bars.json b/src/generated/resources/assets/create/blockstates/copper_bars.json new file mode 100644 index 000000000..f9418ab30 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/copper_bars.json @@ -0,0 +1,100 @@ +{ + "multipart": [ + { + "apply": { + "model": "create:block/copper_post_ends" + } + }, + { + "apply": { + "model": "create:block/copper_post" + }, + "when": { + "east": "false", + "north": "false", + "south": "false", + "west": "false" + } + }, + { + "apply": { + "model": "create:block/copper_cap" + }, + "when": { + "east": "false", + "north": "true", + "south": "false", + "west": "false" + } + }, + { + "apply": { + "model": "create:block/copper_cap", + "y": 90 + }, + "when": { + "east": "true", + "north": "false", + "south": "false", + "west": "false" + } + }, + { + "apply": { + "model": "create:block/copper_cap_alt" + }, + "when": { + "east": "false", + "north": "false", + "south": "true", + "west": "false" + } + }, + { + "apply": { + "model": "create:block/copper_cap_alt", + "y": 90 + }, + "when": { + "east": "false", + "north": "false", + "south": "false", + "west": "true" + } + }, + { + "apply": { + "model": "create:block/copper_side" + }, + "when": { + "north": "true" + } + }, + { + "apply": { + "model": "create:block/copper_side", + "y": 90 + }, + "when": { + "east": "true" + } + }, + { + "apply": { + "model": "create:block/copper_side_alt" + }, + "when": { + "south": "true" + } + }, + { + "apply": { + "model": "create:block/copper_side_alt", + "y": 90 + }, + "when": { + "west": "true" + } + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/copper_door.json b/src/generated/resources/assets/create/blockstates/copper_door.json new file mode 100644 index 000000000..26854d6f9 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/copper_door.json @@ -0,0 +1,244 @@ +{ + "variants": { + "facing=east,half=lower,hinge=left,open=false,visible=false": { + "model": "create:block/copper_door/block_bottom" + }, + "facing=east,half=lower,hinge=left,open=false,visible=true": { + "model": "create:block/copper_door/block_bottom" + }, + "facing=east,half=lower,hinge=left,open=true,visible=false": { + "model": "create:block/copper_door/block_bottom", + "y": 90 + }, + "facing=east,half=lower,hinge=left,open=true,visible=true": { + "model": "create:block/copper_door/block_bottom", + "y": 90 + }, + "facing=east,half=lower,hinge=right,open=false,visible=false": { + "model": "create:block/copper_door/block_bottom" + }, + "facing=east,half=lower,hinge=right,open=false,visible=true": { + "model": "create:block/copper_door/block_bottom" + }, + "facing=east,half=lower,hinge=right,open=true,visible=false": { + "model": "create:block/copper_door/block_bottom", + "y": 270 + }, + "facing=east,half=lower,hinge=right,open=true,visible=true": { + "model": "create:block/copper_door/block_bottom", + "y": 270 + }, + "facing=east,half=upper,hinge=left,open=false,visible=false": { + "model": "create:block/copper_door/block_top" + }, + "facing=east,half=upper,hinge=left,open=false,visible=true": { + "model": "create:block/copper_door/block_top" + }, + "facing=east,half=upper,hinge=left,open=true,visible=false": { + "model": "create:block/copper_door/block_top", + "y": 90 + }, + "facing=east,half=upper,hinge=left,open=true,visible=true": { + "model": "create:block/copper_door/block_top", + "y": 90 + }, + "facing=east,half=upper,hinge=right,open=false,visible=false": { + "model": "create:block/copper_door/block_top" + }, + "facing=east,half=upper,hinge=right,open=false,visible=true": { + "model": "create:block/copper_door/block_top" + }, + "facing=east,half=upper,hinge=right,open=true,visible=false": { + "model": "create:block/copper_door/block_top", + "y": 270 + }, + "facing=east,half=upper,hinge=right,open=true,visible=true": { + "model": "create:block/copper_door/block_top", + "y": 270 + }, + "facing=north,half=lower,hinge=left,open=false,visible=false": { + "model": "create:block/copper_door/block_bottom", + "y": 270 + }, + "facing=north,half=lower,hinge=left,open=false,visible=true": { + "model": "create:block/copper_door/block_bottom", + "y": 270 + }, + "facing=north,half=lower,hinge=left,open=true,visible=false": { + "model": "create:block/copper_door/block_bottom" + }, + "facing=north,half=lower,hinge=left,open=true,visible=true": { + "model": "create:block/copper_door/block_bottom" + }, + "facing=north,half=lower,hinge=right,open=false,visible=false": { + "model": "create:block/copper_door/block_bottom", + "y": 270 + }, + "facing=north,half=lower,hinge=right,open=false,visible=true": { + "model": "create:block/copper_door/block_bottom", + "y": 270 + }, + "facing=north,half=lower,hinge=right,open=true,visible=false": { + "model": "create:block/copper_door/block_bottom", + "y": 180 + }, + "facing=north,half=lower,hinge=right,open=true,visible=true": { + "model": "create:block/copper_door/block_bottom", + "y": 180 + }, + "facing=north,half=upper,hinge=left,open=false,visible=false": { + "model": "create:block/copper_door/block_top", + "y": 270 + }, + "facing=north,half=upper,hinge=left,open=false,visible=true": { + "model": "create:block/copper_door/block_top", + "y": 270 + }, + "facing=north,half=upper,hinge=left,open=true,visible=false": { + "model": "create:block/copper_door/block_top" + }, + "facing=north,half=upper,hinge=left,open=true,visible=true": { + "model": "create:block/copper_door/block_top" + }, + "facing=north,half=upper,hinge=right,open=false,visible=false": { + "model": "create:block/copper_door/block_top", + "y": 270 + }, + "facing=north,half=upper,hinge=right,open=false,visible=true": { + "model": "create:block/copper_door/block_top", + "y": 270 + }, + "facing=north,half=upper,hinge=right,open=true,visible=false": { + "model": "create:block/copper_door/block_top", + "y": 180 + }, + "facing=north,half=upper,hinge=right,open=true,visible=true": { + "model": "create:block/copper_door/block_top", + "y": 180 + }, + "facing=south,half=lower,hinge=left,open=false,visible=false": { + "model": "create:block/copper_door/block_bottom", + "y": 90 + }, + "facing=south,half=lower,hinge=left,open=false,visible=true": { + "model": "create:block/copper_door/block_bottom", + "y": 90 + }, + "facing=south,half=lower,hinge=left,open=true,visible=false": { + "model": "create:block/copper_door/block_bottom", + "y": 180 + }, + "facing=south,half=lower,hinge=left,open=true,visible=true": { + "model": "create:block/copper_door/block_bottom", + "y": 180 + }, + "facing=south,half=lower,hinge=right,open=false,visible=false": { + "model": "create:block/copper_door/block_bottom", + "y": 90 + }, + "facing=south,half=lower,hinge=right,open=false,visible=true": { + "model": "create:block/copper_door/block_bottom", + "y": 90 + }, + "facing=south,half=lower,hinge=right,open=true,visible=false": { + "model": "create:block/copper_door/block_bottom" + }, + "facing=south,half=lower,hinge=right,open=true,visible=true": { + "model": "create:block/copper_door/block_bottom" + }, + "facing=south,half=upper,hinge=left,open=false,visible=false": { + "model": "create:block/copper_door/block_top", + "y": 90 + }, + "facing=south,half=upper,hinge=left,open=false,visible=true": { + "model": "create:block/copper_door/block_top", + "y": 90 + }, + "facing=south,half=upper,hinge=left,open=true,visible=false": { + "model": "create:block/copper_door/block_top", + "y": 180 + }, + "facing=south,half=upper,hinge=left,open=true,visible=true": { + "model": "create:block/copper_door/block_top", + "y": 180 + }, + "facing=south,half=upper,hinge=right,open=false,visible=false": { + "model": "create:block/copper_door/block_top", + "y": 90 + }, + "facing=south,half=upper,hinge=right,open=false,visible=true": { + "model": "create:block/copper_door/block_top", + "y": 90 + }, + "facing=south,half=upper,hinge=right,open=true,visible=false": { + "model": "create:block/copper_door/block_top" + }, + "facing=south,half=upper,hinge=right,open=true,visible=true": { + "model": "create:block/copper_door/block_top" + }, + "facing=west,half=lower,hinge=left,open=false,visible=false": { + "model": "create:block/copper_door/block_bottom", + "y": 180 + }, + "facing=west,half=lower,hinge=left,open=false,visible=true": { + "model": "create:block/copper_door/block_bottom", + "y": 180 + }, + "facing=west,half=lower,hinge=left,open=true,visible=false": { + "model": "create:block/copper_door/block_bottom", + "y": 270 + }, + "facing=west,half=lower,hinge=left,open=true,visible=true": { + "model": "create:block/copper_door/block_bottom", + "y": 270 + }, + "facing=west,half=lower,hinge=right,open=false,visible=false": { + "model": "create:block/copper_door/block_bottom", + "y": 180 + }, + "facing=west,half=lower,hinge=right,open=false,visible=true": { + "model": "create:block/copper_door/block_bottom", + "y": 180 + }, + "facing=west,half=lower,hinge=right,open=true,visible=false": { + "model": "create:block/copper_door/block_bottom", + "y": 90 + }, + "facing=west,half=lower,hinge=right,open=true,visible=true": { + "model": "create:block/copper_door/block_bottom", + "y": 90 + }, + "facing=west,half=upper,hinge=left,open=false,visible=false": { + "model": "create:block/copper_door/block_top", + "y": 180 + }, + "facing=west,half=upper,hinge=left,open=false,visible=true": { + "model": "create:block/copper_door/block_top", + "y": 180 + }, + "facing=west,half=upper,hinge=left,open=true,visible=false": { + "model": "create:block/copper_door/block_top", + "y": 270 + }, + "facing=west,half=upper,hinge=left,open=true,visible=true": { + "model": "create:block/copper_door/block_top", + "y": 270 + }, + "facing=west,half=upper,hinge=right,open=false,visible=false": { + "model": "create:block/copper_door/block_top", + "y": 180 + }, + "facing=west,half=upper,hinge=right,open=false,visible=true": { + "model": "create:block/copper_door/block_top", + "y": 180 + }, + "facing=west,half=upper,hinge=right,open=true,visible=false": { + "model": "create:block/copper_door/block_top", + "y": 90 + }, + "facing=west,half=upper,hinge=right,open=true,visible=true": { + "model": "create:block/copper_door/block_top", + "y": 90 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/copper_scaffolding.json b/src/generated/resources/assets/create/blockstates/copper_scaffolding.json new file mode 100644 index 000000000..32d6ffe91 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/copper_scaffolding.json @@ -0,0 +1,10 @@ +{ + "variants": { + "bottom=false": { + "model": "create:block/copper_scaffolding" + }, + "bottom=true": { + "model": "create:block/copper_scaffolding_horizontal" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/copycat_bars.json b/src/generated/resources/assets/create/blockstates/copycat_bars.json new file mode 100644 index 000000000..9b9d85d16 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/copycat_bars.json @@ -0,0 +1,26 @@ +{ + "variants": { + "facing=down": { + "model": "create:block/copycat_panel/bars_vertical", + "x": 180 + }, + "facing=east": { + "model": "create:block/copycat_panel/bars", + "y": 270 + }, + "facing=north": { + "model": "create:block/copycat_panel/bars", + "y": 180 + }, + "facing=south": { + "model": "create:block/copycat_panel/bars" + }, + "facing=up": { + "model": "create:block/copycat_panel/bars_vertical" + }, + "facing=west": { + "model": "create:block/copycat_panel/bars", + "y": 90 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/copycat_base.json b/src/generated/resources/assets/create/blockstates/copycat_base.json new file mode 100644 index 000000000..739d7181a --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/copycat_base.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "create:block/copycat_base/block" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/copycat_panel.json b/src/generated/resources/assets/create/blockstates/copycat_panel.json new file mode 100644 index 000000000..2c8f02f06 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/copycat_panel.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "minecraft:block/air" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/copycat_step.json b/src/generated/resources/assets/create/blockstates/copycat_step.json new file mode 100644 index 000000000..2c8f02f06 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/copycat_step.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "minecraft:block/air" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/crimsite.json b/src/generated/resources/assets/create/blockstates/crimsite.json index 61ca89d58..495e95c1f 100644 --- a/src/generated/resources/assets/create/blockstates/crimsite.json +++ b/src/generated/resources/assets/create/blockstates/crimsite.json @@ -1,7 +1,18 @@ { "variants": { - "": { - "model": "create:block/crimsite" - } + "": [ + { + "model": "create:block/crimsite_natural_0" + }, + { + "model": "create:block/crimsite_natural_1" + }, + { + "model": "create:block/crimsite_natural_2" + }, + { + "model": "create:block/crimsite_natural_3" + } + ] } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/crushing_wheel.json b/src/generated/resources/assets/create/blockstates/crushing_wheel.json index b0a631e3a..f358bb1cf 100644 --- a/src/generated/resources/assets/create/blockstates/crushing_wheel.json +++ b/src/generated/resources/assets/create/blockstates/crushing_wheel.json @@ -1,15 +1,15 @@ { "variants": { "axis=x": { - "model": "create:block/crushing_wheel", + "model": "create:block/crushing_wheel/block", "x": 90, "y": 90 }, "axis=y": { - "model": "create:block/crushing_wheel" + "model": "create:block/crushing_wheel/block" }, "axis=z": { - "model": "create:block/crushing_wheel", + "model": "create:block/crushing_wheel/block", "x": 90, "y": 180 } diff --git a/src/generated/resources/assets/create/blockstates/elevator_contact.json b/src/generated/resources/assets/create/blockstates/elevator_contact.json new file mode 100644 index 000000000..eec0f4fa5 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/elevator_contact.json @@ -0,0 +1,212 @@ +{ + "variants": { + "calling=false,facing=down,powered=false,powering=false": { + "model": "create:block/elevator_contact/block", + "x": 180 + }, + "calling=false,facing=down,powered=false,powering=true": { + "model": "create:block/elevator_contact/block_powered", + "x": 180 + }, + "calling=false,facing=down,powered=true,powering=false": { + "model": "create:block/elevator_contact/block", + "x": 180 + }, + "calling=false,facing=down,powered=true,powering=true": { + "model": "create:block/elevator_contact/block_powered", + "x": 180 + }, + "calling=false,facing=east,powered=false,powering=false": { + "model": "create:block/elevator_contact/block", + "x": 90, + "y": 90 + }, + "calling=false,facing=east,powered=false,powering=true": { + "model": "create:block/elevator_contact/block_powered", + "x": 90, + "y": 90 + }, + "calling=false,facing=east,powered=true,powering=false": { + "model": "create:block/elevator_contact/block", + "x": 90, + "y": 90 + }, + "calling=false,facing=east,powered=true,powering=true": { + "model": "create:block/elevator_contact/block_powered", + "x": 90, + "y": 90 + }, + "calling=false,facing=north,powered=false,powering=false": { + "model": "create:block/elevator_contact/block", + "x": 90 + }, + "calling=false,facing=north,powered=false,powering=true": { + "model": "create:block/elevator_contact/block_powered", + "x": 90 + }, + "calling=false,facing=north,powered=true,powering=false": { + "model": "create:block/elevator_contact/block", + "x": 90 + }, + "calling=false,facing=north,powered=true,powering=true": { + "model": "create:block/elevator_contact/block_powered", + "x": 90 + }, + "calling=false,facing=south,powered=false,powering=false": { + "model": "create:block/elevator_contact/block", + "x": 90, + "y": 180 + }, + "calling=false,facing=south,powered=false,powering=true": { + "model": "create:block/elevator_contact/block_powered", + "x": 90, + "y": 180 + }, + "calling=false,facing=south,powered=true,powering=false": { + "model": "create:block/elevator_contact/block", + "x": 90, + "y": 180 + }, + "calling=false,facing=south,powered=true,powering=true": { + "model": "create:block/elevator_contact/block_powered", + "x": 90, + "y": 180 + }, + "calling=false,facing=up,powered=false,powering=false": { + "model": "create:block/elevator_contact/block" + }, + "calling=false,facing=up,powered=false,powering=true": { + "model": "create:block/elevator_contact/block_powered" + }, + "calling=false,facing=up,powered=true,powering=false": { + "model": "create:block/elevator_contact/block" + }, + "calling=false,facing=up,powered=true,powering=true": { + "model": "create:block/elevator_contact/block_powered" + }, + "calling=false,facing=west,powered=false,powering=false": { + "model": "create:block/elevator_contact/block", + "x": 90, + "y": 270 + }, + "calling=false,facing=west,powered=false,powering=true": { + "model": "create:block/elevator_contact/block_powered", + "x": 90, + "y": 270 + }, + "calling=false,facing=west,powered=true,powering=false": { + "model": "create:block/elevator_contact/block", + "x": 90, + "y": 270 + }, + "calling=false,facing=west,powered=true,powering=true": { + "model": "create:block/elevator_contact/block_powered", + "x": 90, + "y": 270 + }, + "calling=true,facing=down,powered=false,powering=false": { + "model": "create:block/elevator_contact/block_dim", + "x": 180 + }, + "calling=true,facing=down,powered=false,powering=true": { + "model": "create:block/elevator_contact/block_powered", + "x": 180 + }, + "calling=true,facing=down,powered=true,powering=false": { + "model": "create:block/elevator_contact/block_dim", + "x": 180 + }, + "calling=true,facing=down,powered=true,powering=true": { + "model": "create:block/elevator_contact/block_powered", + "x": 180 + }, + "calling=true,facing=east,powered=false,powering=false": { + "model": "create:block/elevator_contact/block_dim", + "x": 90, + "y": 90 + }, + "calling=true,facing=east,powered=false,powering=true": { + "model": "create:block/elevator_contact/block_powered", + "x": 90, + "y": 90 + }, + "calling=true,facing=east,powered=true,powering=false": { + "model": "create:block/elevator_contact/block_dim", + "x": 90, + "y": 90 + }, + "calling=true,facing=east,powered=true,powering=true": { + "model": "create:block/elevator_contact/block_powered", + "x": 90, + "y": 90 + }, + "calling=true,facing=north,powered=false,powering=false": { + "model": "create:block/elevator_contact/block_dim", + "x": 90 + }, + "calling=true,facing=north,powered=false,powering=true": { + "model": "create:block/elevator_contact/block_powered", + "x": 90 + }, + "calling=true,facing=north,powered=true,powering=false": { + "model": "create:block/elevator_contact/block_dim", + "x": 90 + }, + "calling=true,facing=north,powered=true,powering=true": { + "model": "create:block/elevator_contact/block_powered", + "x": 90 + }, + "calling=true,facing=south,powered=false,powering=false": { + "model": "create:block/elevator_contact/block_dim", + "x": 90, + "y": 180 + }, + "calling=true,facing=south,powered=false,powering=true": { + "model": "create:block/elevator_contact/block_powered", + "x": 90, + "y": 180 + }, + "calling=true,facing=south,powered=true,powering=false": { + "model": "create:block/elevator_contact/block_dim", + "x": 90, + "y": 180 + }, + "calling=true,facing=south,powered=true,powering=true": { + "model": "create:block/elevator_contact/block_powered", + "x": 90, + "y": 180 + }, + "calling=true,facing=up,powered=false,powering=false": { + "model": "create:block/elevator_contact/block_dim" + }, + "calling=true,facing=up,powered=false,powering=true": { + "model": "create:block/elevator_contact/block_powered" + }, + "calling=true,facing=up,powered=true,powering=false": { + "model": "create:block/elevator_contact/block_dim" + }, + "calling=true,facing=up,powered=true,powering=true": { + "model": "create:block/elevator_contact/block_powered" + }, + "calling=true,facing=west,powered=false,powering=false": { + "model": "create:block/elevator_contact/block_dim", + "x": 90, + "y": 270 + }, + "calling=true,facing=west,powered=false,powering=true": { + "model": "create:block/elevator_contact/block_powered", + "x": 90, + "y": 270 + }, + "calling=true,facing=west,powered=true,powering=false": { + "model": "create:block/elevator_contact/block_dim", + "x": 90, + "y": 270 + }, + "calling=true,facing=west,powered=true,powering=true": { + "model": "create:block/elevator_contact/block_powered", + "x": 90, + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/elevator_pulley.json b/src/generated/resources/assets/create/blockstates/elevator_pulley.json new file mode 100644 index 000000000..72cca14db --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/elevator_pulley.json @@ -0,0 +1,19 @@ +{ + "variants": { + "facing=east": { + "model": "create:block/elevator_pulley/block", + "y": 90 + }, + "facing=north": { + "model": "create:block/elevator_pulley/block" + }, + "facing=south": { + "model": "create:block/elevator_pulley/block", + "y": 180 + }, + "facing=west": { + "model": "create:block/elevator_pulley/block", + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/experience_block.json b/src/generated/resources/assets/create/blockstates/experience_block.json new file mode 100644 index 000000000..96bde6400 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/experience_block.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "create:block/experience_block" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/industrial_iron_block.json b/src/generated/resources/assets/create/blockstates/industrial_iron_block.json new file mode 100644 index 000000000..c38604b94 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/industrial_iron_block.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "create:block/industrial_iron_block" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/large_water_wheel.json b/src/generated/resources/assets/create/blockstates/large_water_wheel.json new file mode 100644 index 000000000..b847ee26b --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/large_water_wheel.json @@ -0,0 +1,30 @@ +{ + "variants": { + "axis=x,extension=false": { + "model": "create:block/large_water_wheel/block", + "x": 90, + "y": 90 + }, + "axis=x,extension=true": { + "model": "create:block/large_water_wheel/block_extension", + "x": 90, + "y": 90 + }, + "axis=y,extension=false": { + "model": "create:block/large_water_wheel/block" + }, + "axis=y,extension=true": { + "model": "create:block/large_water_wheel/block_extension" + }, + "axis=z,extension=false": { + "model": "create:block/large_water_wheel/block", + "x": 90, + "y": 180 + }, + "axis=z,extension=true": { + "model": "create:block/large_water_wheel/block_extension", + "x": 90, + "y": 180 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/mangrove_window.json b/src/generated/resources/assets/create/blockstates/mangrove_window.json new file mode 100644 index 000000000..937ec8d85 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/mangrove_window.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "create:block/mangrove_window" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/mangrove_window_pane.json b/src/generated/resources/assets/create/blockstates/mangrove_window_pane.json new file mode 100644 index 000000000..f459d6f8d --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/mangrove_window_pane.json @@ -0,0 +1,77 @@ +{ + "multipart": [ + { + "apply": { + "model": "create:block/mangrove_window_pane_post" + } + }, + { + "apply": { + "model": "create:block/mangrove_window_pane_side" + }, + "when": { + "north": "true" + } + }, + { + "apply": { + "model": "create:block/mangrove_window_pane_noside" + }, + "when": { + "north": "false" + } + }, + { + "apply": { + "model": "create:block/mangrove_window_pane_side_alt" + }, + "when": { + "south": "true" + } + }, + { + "apply": { + "model": "create:block/mangrove_window_pane_noside_alt", + "y": 90 + }, + "when": { + "south": "false" + } + }, + { + "apply": { + "model": "create:block/mangrove_window_pane_side_alt", + "y": 90 + }, + "when": { + "west": "true" + } + }, + { + "apply": { + "model": "create:block/mangrove_window_pane_noside", + "y": 270 + }, + "when": { + "west": "false" + } + }, + { + "apply": { + "model": "create:block/mangrove_window_pane_side", + "y": 90 + }, + "when": { + "east": "true" + } + }, + { + "apply": { + "model": "create:block/mangrove_window_pane_noside_alt" + }, + "when": { + "east": "false" + } + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/mechanical_harvester.json b/src/generated/resources/assets/create/blockstates/mechanical_harvester.json index 2669ab3cb..0e90506fb 100644 --- a/src/generated/resources/assets/create/blockstates/mechanical_harvester.json +++ b/src/generated/resources/assets/create/blockstates/mechanical_harvester.json @@ -1,17 +1,32 @@ { "variants": { - "facing=east": { + "facing=east,waterlogged=false": { "model": "create:block/mechanical_harvester/block", "y": 90 }, - "facing=north": { + "facing=east,waterlogged=true": { + "model": "create:block/mechanical_harvester/block", + "y": 90 + }, + "facing=north,waterlogged=false": { "model": "create:block/mechanical_harvester/block" }, - "facing=south": { + "facing=north,waterlogged=true": { + "model": "create:block/mechanical_harvester/block" + }, + "facing=south,waterlogged=false": { "model": "create:block/mechanical_harvester/block", "y": 180 }, - "facing=west": { + "facing=south,waterlogged=true": { + "model": "create:block/mechanical_harvester/block", + "y": 180 + }, + "facing=west,waterlogged=false": { + "model": "create:block/mechanical_harvester/block", + "y": 270 + }, + "facing=west,waterlogged=true": { "model": "create:block/mechanical_harvester/block", "y": 270 } diff --git a/src/generated/resources/assets/create/blockstates/mechanical_plough.json b/src/generated/resources/assets/create/blockstates/mechanical_plough.json index 716f103e0..e608885a3 100644 --- a/src/generated/resources/assets/create/blockstates/mechanical_plough.json +++ b/src/generated/resources/assets/create/blockstates/mechanical_plough.json @@ -1,17 +1,32 @@ { "variants": { - "facing=east": { + "facing=east,waterlogged=false": { "model": "create:block/mechanical_plough", "y": 90 }, - "facing=north": { + "facing=east,waterlogged=true": { + "model": "create:block/mechanical_plough", + "y": 90 + }, + "facing=north,waterlogged=false": { "model": "create:block/mechanical_plough" }, - "facing=south": { + "facing=north,waterlogged=true": { + "model": "create:block/mechanical_plough" + }, + "facing=south,waterlogged=false": { "model": "create:block/mechanical_plough", "y": 180 }, - "facing=west": { + "facing=south,waterlogged=true": { + "model": "create:block/mechanical_plough", + "y": 180 + }, + "facing=west,waterlogged=false": { + "model": "create:block/mechanical_plough", + "y": 270 + }, + "facing=west,waterlogged=true": { "model": "create:block/mechanical_plough", "y": 270 } diff --git a/src/generated/resources/assets/create/blockstates/mechanical_roller.json b/src/generated/resources/assets/create/blockstates/mechanical_roller.json new file mode 100644 index 000000000..c9077b1a2 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/mechanical_roller.json @@ -0,0 +1,34 @@ +{ + "variants": { + "facing=east,waterlogged=false": { + "model": "create:block/mechanical_roller/block", + "y": 90 + }, + "facing=east,waterlogged=true": { + "model": "create:block/mechanical_roller/block", + "y": 90 + }, + "facing=north,waterlogged=false": { + "model": "create:block/mechanical_roller/block" + }, + "facing=north,waterlogged=true": { + "model": "create:block/mechanical_roller/block" + }, + "facing=south,waterlogged=false": { + "model": "create:block/mechanical_roller/block", + "y": 180 + }, + "facing=south,waterlogged=true": { + "model": "create:block/mechanical_roller/block", + "y": 180 + }, + "facing=west,waterlogged=false": { + "model": "create:block/mechanical_roller/block", + "y": 270 + }, + "facing=west,waterlogged=true": { + "model": "create:block/mechanical_roller/block", + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/mechanical_saw.json b/src/generated/resources/assets/create/blockstates/mechanical_saw.json index 80617ec97..b9605800b 100644 --- a/src/generated/resources/assets/create/blockstates/mechanical_saw.json +++ b/src/generated/resources/assets/create/blockstates/mechanical_saw.json @@ -1,48 +1,96 @@ { "variants": { - "axis_along_first=false,facing=down": { + "axis_along_first=false,facing=down,flipped=false": { "model": "create:block/mechanical_saw/vertical", "x": 180 }, - "axis_along_first=false,facing=east": { + "axis_along_first=false,facing=down,flipped=true": { + "model": "create:block/mechanical_saw/vertical", + "x": 180, + "y": 180 + }, + "axis_along_first=false,facing=east,flipped=false": { "model": "create:block/mechanical_saw/horizontal", "y": 270 }, - "axis_along_first=false,facing=north": { + "axis_along_first=false,facing=east,flipped=true": { + "model": "create:block/mechanical_saw/horizontal", + "y": 270 + }, + "axis_along_first=false,facing=north,flipped=false": { "model": "create:block/mechanical_saw/horizontal", "y": 180 }, - "axis_along_first=false,facing=south": { + "axis_along_first=false,facing=north,flipped=true": { + "model": "create:block/mechanical_saw/horizontal", + "y": 180 + }, + "axis_along_first=false,facing=south,flipped=false": { "model": "create:block/mechanical_saw/horizontal" }, - "axis_along_first=false,facing=up": { + "axis_along_first=false,facing=south,flipped=true": { + "model": "create:block/mechanical_saw/horizontal" + }, + "axis_along_first=false,facing=up,flipped=false": { "model": "create:block/mechanical_saw/vertical" }, - "axis_along_first=false,facing=west": { + "axis_along_first=false,facing=up,flipped=true": { + "model": "create:block/mechanical_saw/vertical", + "y": 180 + }, + "axis_along_first=false,facing=west,flipped=false": { "model": "create:block/mechanical_saw/horizontal", "y": 90 }, - "axis_along_first=true,facing=down": { + "axis_along_first=false,facing=west,flipped=true": { + "model": "create:block/mechanical_saw/horizontal", + "y": 90 + }, + "axis_along_first=true,facing=down,flipped=false": { + "model": "create:block/mechanical_saw/vertical", + "x": 180, + "y": 270 + }, + "axis_along_first=true,facing=down,flipped=true": { "model": "create:block/mechanical_saw/vertical", "x": 180, "y": 90 }, - "axis_along_first=true,facing=east": { + "axis_along_first=true,facing=east,flipped=false": { "model": "create:block/mechanical_saw/horizontal", "y": 270 }, - "axis_along_first=true,facing=north": { + "axis_along_first=true,facing=east,flipped=true": { + "model": "create:block/mechanical_saw/horizontal", + "y": 270 + }, + "axis_along_first=true,facing=north,flipped=false": { "model": "create:block/mechanical_saw/horizontal", "y": 180 }, - "axis_along_first=true,facing=south": { + "axis_along_first=true,facing=north,flipped=true": { + "model": "create:block/mechanical_saw/horizontal", + "y": 180 + }, + "axis_along_first=true,facing=south,flipped=false": { "model": "create:block/mechanical_saw/horizontal" }, - "axis_along_first=true,facing=up": { + "axis_along_first=true,facing=south,flipped=true": { + "model": "create:block/mechanical_saw/horizontal" + }, + "axis_along_first=true,facing=up,flipped=false": { + "model": "create:block/mechanical_saw/vertical", + "y": 270 + }, + "axis_along_first=true,facing=up,flipped=true": { "model": "create:block/mechanical_saw/vertical", "y": 90 }, - "axis_along_first=true,facing=west": { + "axis_along_first=true,facing=west,flipped=false": { + "model": "create:block/mechanical_saw/horizontal", + "y": 90 + }, + "axis_along_first=true,facing=west,flipped=true": { "model": "create:block/mechanical_saw/horizontal", "y": 90 } diff --git a/src/generated/resources/assets/create/blockstates/netherite_backtank.json b/src/generated/resources/assets/create/blockstates/netherite_backtank.json new file mode 100644 index 000000000..7adacbc27 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/netherite_backtank.json @@ -0,0 +1,34 @@ +{ + "variants": { + "facing=east,waterlogged=false": { + "model": "create:block/netherite_backtank/block", + "y": 90 + }, + "facing=east,waterlogged=true": { + "model": "create:block/netherite_backtank/block", + "y": 90 + }, + "facing=north,waterlogged=false": { + "model": "create:block/netherite_backtank/block" + }, + "facing=north,waterlogged=true": { + "model": "create:block/netherite_backtank/block" + }, + "facing=south,waterlogged=false": { + "model": "create:block/netherite_backtank/block", + "y": 180 + }, + "facing=south,waterlogged=true": { + "model": "create:block/netherite_backtank/block", + "y": 180 + }, + "facing=west,waterlogged=false": { + "model": "create:block/netherite_backtank/block", + "y": 270 + }, + "facing=west,waterlogged=true": { + "model": "create:block/netherite_backtank/block", + "y": 270 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/ochrum.json b/src/generated/resources/assets/create/blockstates/ochrum.json index cc43d8475..024cf71fb 100644 --- a/src/generated/resources/assets/create/blockstates/ochrum.json +++ b/src/generated/resources/assets/create/blockstates/ochrum.json @@ -1,7 +1,18 @@ { "variants": { - "": { - "model": "create:block/ochrum" - } + "": [ + { + "model": "create:block/ochrum_natural_0" + }, + { + "model": "create:block/ochrum_natural_1" + }, + { + "model": "create:block/ochrum_natural_2" + }, + { + "model": "create:block/ochrum_natural_3" + } + ] } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/stockpile_switch.json b/src/generated/resources/assets/create/blockstates/stockpile_switch.json index 361d0ea74..10e03d9c4 100644 --- a/src/generated/resources/assets/create/blockstates/stockpile_switch.json +++ b/src/generated/resources/assets/create/blockstates/stockpile_switch.json @@ -1,108 +1,273 @@ { "variants": { - "facing=east,indicator=0": { - "model": "create:block/stockpile_switch_0", + "facing=east,level=0,target=ceiling": { + "model": "create:threshold_switch/block_ceiling_0", "y": 90 }, - "facing=east,indicator=1": { - "model": "create:block/stockpile_switch_1", + "facing=east,level=0,target=floor": { + "model": "create:threshold_switch/block_floor_0", "y": 90 }, - "facing=east,indicator=2": { - "model": "create:block/stockpile_switch_2", + "facing=east,level=0,target=wall": { + "model": "create:threshold_switch/block_wall_0", "y": 90 }, - "facing=east,indicator=3": { - "model": "create:block/stockpile_switch_3", + "facing=east,level=1,target=ceiling": { + "model": "create:threshold_switch/block_ceiling_1", "y": 90 }, - "facing=east,indicator=4": { - "model": "create:block/stockpile_switch_4", + "facing=east,level=1,target=floor": { + "model": "create:threshold_switch/block_floor_1", "y": 90 }, - "facing=east,indicator=5": { - "model": "create:block/stockpile_switch_5", + "facing=east,level=1,target=wall": { + "model": "create:threshold_switch/block_wall_1", "y": 90 }, - "facing=east,indicator=6": { - "model": "create:block/stockpile_switch_6", + "facing=east,level=2,target=ceiling": { + "model": "create:threshold_switch/block_ceiling_2", "y": 90 }, - "facing=north,indicator=0": { - "model": "create:block/stockpile_switch_0" + "facing=east,level=2,target=floor": { + "model": "create:threshold_switch/block_floor_2", + "y": 90 }, - "facing=north,indicator=1": { - "model": "create:block/stockpile_switch_1" + "facing=east,level=2,target=wall": { + "model": "create:threshold_switch/block_wall_2", + "y": 90 }, - "facing=north,indicator=2": { - "model": "create:block/stockpile_switch_2" + "facing=east,level=3,target=ceiling": { + "model": "create:threshold_switch/block_ceiling_3", + "y": 90 }, - "facing=north,indicator=3": { - "model": "create:block/stockpile_switch_3" + "facing=east,level=3,target=floor": { + "model": "create:threshold_switch/block_floor_3", + "y": 90 }, - "facing=north,indicator=4": { - "model": "create:block/stockpile_switch_4" + "facing=east,level=3,target=wall": { + "model": "create:threshold_switch/block_wall_3", + "y": 90 }, - "facing=north,indicator=5": { - "model": "create:block/stockpile_switch_5" + "facing=east,level=4,target=ceiling": { + "model": "create:threshold_switch/block_ceiling_4", + "y": 90 }, - "facing=north,indicator=6": { - "model": "create:block/stockpile_switch_6" + "facing=east,level=4,target=floor": { + "model": "create:threshold_switch/block_floor_4", + "y": 90 }, - "facing=south,indicator=0": { - "model": "create:block/stockpile_switch_0", + "facing=east,level=4,target=wall": { + "model": "create:threshold_switch/block_wall_4", + "y": 90 + }, + "facing=east,level=5,target=ceiling": { + "model": "create:threshold_switch/block_ceiling_5", + "y": 90 + }, + "facing=east,level=5,target=floor": { + "model": "create:threshold_switch/block_floor_5", + "y": 90 + }, + "facing=east,level=5,target=wall": { + "model": "create:threshold_switch/block_wall_5", + "y": 90 + }, + "facing=north,level=0,target=ceiling": { + "model": "create:threshold_switch/block_ceiling_0" + }, + "facing=north,level=0,target=floor": { + "model": "create:threshold_switch/block_floor_0" + }, + "facing=north,level=0,target=wall": { + "model": "create:threshold_switch/block_wall_0" + }, + "facing=north,level=1,target=ceiling": { + "model": "create:threshold_switch/block_ceiling_1" + }, + "facing=north,level=1,target=floor": { + "model": "create:threshold_switch/block_floor_1" + }, + "facing=north,level=1,target=wall": { + "model": "create:threshold_switch/block_wall_1" + }, + "facing=north,level=2,target=ceiling": { + "model": "create:threshold_switch/block_ceiling_2" + }, + "facing=north,level=2,target=floor": { + "model": "create:threshold_switch/block_floor_2" + }, + "facing=north,level=2,target=wall": { + "model": "create:threshold_switch/block_wall_2" + }, + "facing=north,level=3,target=ceiling": { + "model": "create:threshold_switch/block_ceiling_3" + }, + "facing=north,level=3,target=floor": { + "model": "create:threshold_switch/block_floor_3" + }, + "facing=north,level=3,target=wall": { + "model": "create:threshold_switch/block_wall_3" + }, + "facing=north,level=4,target=ceiling": { + "model": "create:threshold_switch/block_ceiling_4" + }, + "facing=north,level=4,target=floor": { + "model": "create:threshold_switch/block_floor_4" + }, + "facing=north,level=4,target=wall": { + "model": "create:threshold_switch/block_wall_4" + }, + "facing=north,level=5,target=ceiling": { + "model": "create:threshold_switch/block_ceiling_5" + }, + "facing=north,level=5,target=floor": { + "model": "create:threshold_switch/block_floor_5" + }, + "facing=north,level=5,target=wall": { + "model": "create:threshold_switch/block_wall_5" + }, + "facing=south,level=0,target=ceiling": { + "model": "create:threshold_switch/block_ceiling_0", "y": 180 }, - "facing=south,indicator=1": { - "model": "create:block/stockpile_switch_1", + "facing=south,level=0,target=floor": { + "model": "create:threshold_switch/block_floor_0", "y": 180 }, - "facing=south,indicator=2": { - "model": "create:block/stockpile_switch_2", + "facing=south,level=0,target=wall": { + "model": "create:threshold_switch/block_wall_0", "y": 180 }, - "facing=south,indicator=3": { - "model": "create:block/stockpile_switch_3", + "facing=south,level=1,target=ceiling": { + "model": "create:threshold_switch/block_ceiling_1", "y": 180 }, - "facing=south,indicator=4": { - "model": "create:block/stockpile_switch_4", + "facing=south,level=1,target=floor": { + "model": "create:threshold_switch/block_floor_1", "y": 180 }, - "facing=south,indicator=5": { - "model": "create:block/stockpile_switch_5", + "facing=south,level=1,target=wall": { + "model": "create:threshold_switch/block_wall_1", "y": 180 }, - "facing=south,indicator=6": { - "model": "create:block/stockpile_switch_6", + "facing=south,level=2,target=ceiling": { + "model": "create:threshold_switch/block_ceiling_2", "y": 180 }, - "facing=west,indicator=0": { - "model": "create:block/stockpile_switch_0", + "facing=south,level=2,target=floor": { + "model": "create:threshold_switch/block_floor_2", + "y": 180 + }, + "facing=south,level=2,target=wall": { + "model": "create:threshold_switch/block_wall_2", + "y": 180 + }, + "facing=south,level=3,target=ceiling": { + "model": "create:threshold_switch/block_ceiling_3", + "y": 180 + }, + "facing=south,level=3,target=floor": { + "model": "create:threshold_switch/block_floor_3", + "y": 180 + }, + "facing=south,level=3,target=wall": { + "model": "create:threshold_switch/block_wall_3", + "y": 180 + }, + "facing=south,level=4,target=ceiling": { + "model": "create:threshold_switch/block_ceiling_4", + "y": 180 + }, + "facing=south,level=4,target=floor": { + "model": "create:threshold_switch/block_floor_4", + "y": 180 + }, + "facing=south,level=4,target=wall": { + "model": "create:threshold_switch/block_wall_4", + "y": 180 + }, + "facing=south,level=5,target=ceiling": { + "model": "create:threshold_switch/block_ceiling_5", + "y": 180 + }, + "facing=south,level=5,target=floor": { + "model": "create:threshold_switch/block_floor_5", + "y": 180 + }, + "facing=south,level=5,target=wall": { + "model": "create:threshold_switch/block_wall_5", + "y": 180 + }, + "facing=west,level=0,target=ceiling": { + "model": "create:threshold_switch/block_ceiling_0", "y": 270 }, - "facing=west,indicator=1": { - "model": "create:block/stockpile_switch_1", + "facing=west,level=0,target=floor": { + "model": "create:threshold_switch/block_floor_0", "y": 270 }, - "facing=west,indicator=2": { - "model": "create:block/stockpile_switch_2", + "facing=west,level=0,target=wall": { + "model": "create:threshold_switch/block_wall_0", "y": 270 }, - "facing=west,indicator=3": { - "model": "create:block/stockpile_switch_3", + "facing=west,level=1,target=ceiling": { + "model": "create:threshold_switch/block_ceiling_1", "y": 270 }, - "facing=west,indicator=4": { - "model": "create:block/stockpile_switch_4", + "facing=west,level=1,target=floor": { + "model": "create:threshold_switch/block_floor_1", "y": 270 }, - "facing=west,indicator=5": { - "model": "create:block/stockpile_switch_5", + "facing=west,level=1,target=wall": { + "model": "create:threshold_switch/block_wall_1", "y": 270 }, - "facing=west,indicator=6": { - "model": "create:block/stockpile_switch_6", + "facing=west,level=2,target=ceiling": { + "model": "create:threshold_switch/block_ceiling_2", + "y": 270 + }, + "facing=west,level=2,target=floor": { + "model": "create:threshold_switch/block_floor_2", + "y": 270 + }, + "facing=west,level=2,target=wall": { + "model": "create:threshold_switch/block_wall_2", + "y": 270 + }, + "facing=west,level=3,target=ceiling": { + "model": "create:threshold_switch/block_ceiling_3", + "y": 270 + }, + "facing=west,level=3,target=floor": { + "model": "create:threshold_switch/block_floor_3", + "y": 270 + }, + "facing=west,level=3,target=wall": { + "model": "create:threshold_switch/block_wall_3", + "y": 270 + }, + "facing=west,level=4,target=ceiling": { + "model": "create:threshold_switch/block_ceiling_4", + "y": 270 + }, + "facing=west,level=4,target=floor": { + "model": "create:threshold_switch/block_floor_4", + "y": 270 + }, + "facing=west,level=4,target=wall": { + "model": "create:threshold_switch/block_wall_4", + "y": 270 + }, + "facing=west,level=5,target=ceiling": { + "model": "create:threshold_switch/block_ceiling_5", + "y": 270 + }, + "facing=west,level=5,target=floor": { + "model": "create:threshold_switch/block_floor_5", + "y": 270 + }, + "facing=west,level=5,target=wall": { + "model": "create:threshold_switch/block_wall_5", "y": 270 } } diff --git a/src/generated/resources/assets/create/blockstates/veridium.json b/src/generated/resources/assets/create/blockstates/veridium.json index 447fd84cd..5e9b5c981 100644 --- a/src/generated/resources/assets/create/blockstates/veridium.json +++ b/src/generated/resources/assets/create/blockstates/veridium.json @@ -1,7 +1,18 @@ { "variants": { - "": { - "model": "create:block/veridium" - } + "": [ + { + "model": "create:block/veridium_natural_0" + }, + { + "model": "create:block/veridium_natural_1" + }, + { + "model": "create:block/veridium_natural_2" + }, + { + "model": "create:block/veridium_natural_3" + } + ] } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/water_wheel.json b/src/generated/resources/assets/create/blockstates/water_wheel.json index c7e608eaf..80bec7d86 100644 --- a/src/generated/resources/assets/create/blockstates/water_wheel.json +++ b/src/generated/resources/assets/create/blockstates/water_wheel.json @@ -1,28 +1,28 @@ { "variants": { "facing=down": { - "model": "create:block/water_wheel", + "model": "create:block/water_wheel/block", "x": 180 }, "facing=east": { - "model": "create:block/water_wheel", + "model": "create:block/water_wheel/block", "x": 90, "y": 90 }, "facing=north": { - "model": "create:block/water_wheel", + "model": "create:block/water_wheel/block", "x": 90 }, "facing=south": { - "model": "create:block/water_wheel", + "model": "create:block/water_wheel/block", "x": 90, "y": 180 }, "facing=up": { - "model": "create:block/water_wheel" + "model": "create:block/water_wheel/block" }, "facing=west": { - "model": "create:block/water_wheel", + "model": "create:block/water_wheel/block", "x": 90, "y": 270 } diff --git a/src/generated/resources/assets/create/blockstates/water_wheel_structure.json b/src/generated/resources/assets/create/blockstates/water_wheel_structure.json new file mode 100644 index 000000000..2c8f02f06 --- /dev/null +++ b/src/generated/resources/assets/create/blockstates/water_wheel_structure.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "minecraft:block/air" + } + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/blockstates/weighted_ejector.json b/src/generated/resources/assets/create/blockstates/weighted_ejector.json index 8ed3f1e40..bc13cc66d 100644 --- a/src/generated/resources/assets/create/blockstates/weighted_ejector.json +++ b/src/generated/resources/assets/create/blockstates/weighted_ejector.json @@ -1,17 +1,32 @@ { "variants": { - "facing=east": { + "facing=east,waterlogged=false": { "model": "create:block/weighted_ejector/block", "y": 90 }, - "facing=north": { + "facing=east,waterlogged=true": { + "model": "create:block/weighted_ejector/block", + "y": 90 + }, + "facing=north,waterlogged=false": { "model": "create:block/weighted_ejector/block" }, - "facing=south": { + "facing=north,waterlogged=true": { + "model": "create:block/weighted_ejector/block" + }, + "facing=south,waterlogged=false": { "model": "create:block/weighted_ejector/block", "y": 180 }, - "facing=west": { + "facing=south,waterlogged=true": { + "model": "create:block/weighted_ejector/block", + "y": 180 + }, + "facing=west,waterlogged=false": { + "model": "create:block/weighted_ejector/block", + "y": 270 + }, + "facing=west,waterlogged=true": { "model": "create:block/weighted_ejector/block", "y": 270 } diff --git a/src/generated/resources/assets/create/lang/en_ud.json b/src/generated/resources/assets/create/lang/en_ud.json index 9f83c6fc8..dcce724a3 100644 --- a/src/generated/resources/assets/create/lang/en_ud.json +++ b/src/generated/resources/assets/create/lang/en_ud.json @@ -3,14 +3,18 @@ "block.create.acacia_window_pane": "ǝuɐԀ ʍopuıM ɐıɔɐɔⱯ", "block.create.adjustable_chain_gearshift": "ʇɟıɥsɹɐǝ⅁ uıɐɥƆ ǝןqɐʇsnظpⱯ", "block.create.analog_lever": "ɹǝʌǝꞀ boןɐuⱯ", + "block.create.andesite_alloy_block": "ʎoןןⱯ ǝʇısǝpuⱯ ɟo ʞɔoןᗺ", + "block.create.andesite_bars": "sɹɐᗺ ǝʇısǝpuⱯ", "block.create.andesite_belt_funnel": "ןǝuunℲ ʇןǝᗺ ǝʇısǝpuⱯ", "block.create.andesite_casing": "buısɐƆ ǝʇısǝpuⱯ", + "block.create.andesite_door": "ɹooᗡ ǝʇısǝpuⱯ", "block.create.andesite_encased_cogwheel": "ןǝǝɥʍboƆ pǝsɐɔuƎ ǝʇısǝpuⱯ", "block.create.andesite_encased_large_cogwheel": "ןǝǝɥʍboƆ ǝbɹɐꞀ pǝsɐɔuƎ ǝʇısǝpuⱯ", "block.create.andesite_encased_shaft": "ʇɟɐɥS pǝsɐɔuƎ ǝʇısǝpuⱯ", "block.create.andesite_funnel": "ןǝuunℲ ǝʇısǝpuⱯ", "block.create.andesite_ladder": "ɹǝppɐꞀ ǝʇısǝpuⱯ", "block.create.andesite_pillar": "ɹɐןןıԀ ǝʇısǝpuⱯ", + "block.create.andesite_scaffolding": "buıpןoɟɟɐɔS ǝʇısǝpuⱯ", "block.create.andesite_tunnel": "ןǝuun⟘ ǝʇısǝpuⱯ", "block.create.asurine": "ǝuıɹnsⱯ", "block.create.asurine_pillar": "ɹɐןןıԀ ǝuıɹnsⱯ", @@ -29,14 +33,17 @@ "block.create.blue_seat": "ʇɐǝS ǝnןᗺ", "block.create.blue_toolbox": "xoqןoo⟘ ǝnןᗺ", "block.create.blue_valve_handle": "ǝןpuɐH ǝʌןɐΛ ǝnןᗺ", + "block.create.brass_bars": "sɹɐᗺ ssɐɹᗺ", "block.create.brass_belt_funnel": "ןǝuunℲ ʇןǝᗺ ssɐɹᗺ", "block.create.brass_block": "ssɐɹᗺ ɟo ʞɔoןᗺ", "block.create.brass_casing": "buısɐƆ ssɐɹᗺ", + "block.create.brass_door": "ɹooᗡ ssɐɹᗺ", "block.create.brass_encased_cogwheel": "ןǝǝɥʍboƆ pǝsɐɔuƎ ssɐɹᗺ", "block.create.brass_encased_large_cogwheel": "ןǝǝɥʍboƆ ǝbɹɐꞀ pǝsɐɔuƎ ssɐɹᗺ", "block.create.brass_encased_shaft": "ʇɟɐɥS pǝsɐɔuƎ ssɐɹᗺ", "block.create.brass_funnel": "ןǝuunℲ ssɐɹᗺ", "block.create.brass_ladder": "ɹǝppɐꞀ ssɐɹᗺ", + "block.create.brass_scaffolding": "buıpןoɟɟɐɔS ssɐɹᗺ", "block.create.brass_tunnel": "ןǝuun⟘ ssɐɹᗺ", "block.create.brown_nixie_tube": "ǝqn⟘ ǝıxıN uʍoɹᗺ", "block.create.brown_sail": "ןıɐS uʍoɹᗺ", @@ -47,15 +54,20 @@ "block.create.cart_assembler": "ɹǝןqɯǝssⱯ ʇɹɐƆ", "block.create.chocolate": "ǝʇɐןoɔoɥƆ", "block.create.chute": "ǝʇnɥƆ", + "block.create.clipboard": "pɹɐoqdıןƆ", "block.create.clockwork_bearing": "buıɹɐǝᗺ ʞɹoʍʞɔoןƆ", "block.create.clutch": "ɥɔʇnןƆ", "block.create.cogwheel": "ןǝǝɥʍboƆ", - "block.create.content_observer": "ɹǝʌɹǝsqO ʇuǝʇuoƆ", + "block.create.content_observer": "ɹǝʌɹǝsqO ʇɹɐɯS", + "block.create.contraption_controls": "sןoɹʇuoƆ uoıʇdɐɹʇuoƆ", "block.create.controller_rail": "ןıɐᴚ ɹǝןןoɹʇuoƆ", "block.create.controls": "sןoɹʇuoƆ uıɐɹ⟘", "block.create.copper_backtank": "ʞuɐʇʞɔɐᗺ ɹǝddoƆ", + "block.create.copper_bars": "sɹɐᗺ ɹǝddoƆ", "block.create.copper_casing": "buısɐƆ ɹǝddoƆ", + "block.create.copper_door": "ɹooᗡ ɹǝddoƆ", "block.create.copper_ladder": "ɹǝppɐꞀ ɹǝddoƆ", + "block.create.copper_scaffolding": "buıpןoɟɟɐɔS ɹǝddoƆ", "block.create.copper_shingle_slab": "qɐןS ǝןbuıɥS ɹǝddoƆ", "block.create.copper_shingle_stairs": "sɹıɐʇS ǝןbuıɥS ɹǝddoƆ", "block.create.copper_shingles": "sǝןbuıɥS ɹǝddoƆ", @@ -63,6 +75,10 @@ "block.create.copper_tile_stairs": "sɹıɐʇS ǝןı⟘ ɹǝddoƆ", "block.create.copper_tiles": "sǝןı⟘ ɹǝddoƆ", "block.create.copper_valve_handle": "ǝןpuɐH ǝʌןɐΛ ɹǝddoƆ", + "block.create.copycat_bars": "sɹɐᗺ ʇɐɔʎdoƆ", + "block.create.copycat_base": "ǝsɐᗺ ʇɐɔʎdoƆ", + "block.create.copycat_panel": "ןǝuɐԀ ʇɐɔʎdoƆ", + "block.create.copycat_step": "dǝʇS ʇɐɔʎdoƆ", "block.create.creative_crate": "ǝʇɐɹƆ ǝʌıʇɐǝɹƆ", "block.create.creative_fluid_tank": "ʞuɐ⟘ pınןℲ ǝʌıʇɐǝɹƆ", "block.create.creative_motor": "ɹoʇoW ǝʌıʇɐǝɹƆ", @@ -200,9 +216,12 @@ "block.create.display_board": "pɹɐoᗺ ʎɐןdsıᗡ", "block.create.display_link": "ʞuıꞀ ʎɐןdsıᗡ", "block.create.dripstone_pillar": "ɹɐןןıԀ ǝuoʇsdıɹᗡ", + "block.create.elevator_contact": "ʇɔɐʇuoƆ ɹoʇɐʌǝןƎ", + "block.create.elevator_pulley": "ʎǝןןnԀ ɹoʇɐʌǝןƎ", "block.create.encased_chain_drive": "ǝʌıɹᗡ uıɐɥƆ pǝsɐɔuƎ", "block.create.encased_fan": "uɐℲ pǝsɐɔuƎ", "block.create.encased_fluid_pipe": "ǝdıԀ pınןℲ pǝsɐɔuƎ", + "block.create.experience_block": "ǝɔuǝıɹǝdxƎ ɟo ʞɔoןᗺ", "block.create.exposed_copper_shingle_slab": "qɐןS ǝןbuıɥS ɹǝddoƆ pǝsodxƎ", "block.create.exposed_copper_shingle_stairs": "sɹıɐʇS ǝןbuıɥS ɹǝddoƆ pǝsodxƎ", "block.create.exposed_copper_shingles": "sǝןbuıɥS ɹǝddoƆ pǝsodxƎ", @@ -240,12 +259,14 @@ "block.create.horizontal_framed_glass": "ssɐן⅁ pǝɯɐɹℲ ןɐʇuozıɹoH", "block.create.horizontal_framed_glass_pane": "ǝuɐԀ ssɐן⅁ pǝɯɐɹℲ ןɐʇuozıɹoH", "block.create.hose_pulley": "ʎǝןןnԀ ǝsoH", + "block.create.industrial_iron_block": "uoɹI ןɐıɹʇsnpuI ɟo ʞɔoןᗺ", "block.create.item_drain": "uıɐɹᗡ ɯǝʇI", "block.create.item_vault": "ʇןnɐΛ ɯǝʇI", "block.create.jungle_window": "ʍopuıM ǝןbunſ", "block.create.jungle_window_pane": "ǝuɐԀ ʍopuıM ǝןbunſ", "block.create.large_bogey": "ʎǝboᗺ ǝbɹɐꞀ", "block.create.large_cogwheel": "ןǝǝɥʍboƆ ǝbɹɐꞀ", + "block.create.large_water_wheel": "ןǝǝɥM ɹǝʇɐM ǝbɹɐꞀ", "block.create.layered_andesite": "ǝʇısǝpuⱯ pǝɹǝʎɐꞀ", "block.create.layered_asurine": "ǝuıɹnsⱯ pǝɹǝʎɐꞀ", "block.create.layered_calcite": "ǝʇıɔןɐƆ pǝɹǝʎɐꞀ", @@ -285,6 +306,8 @@ "block.create.magenta_seat": "ʇɐǝS ɐʇuǝbɐW", "block.create.magenta_toolbox": "xoqןoo⟘ ɐʇuǝbɐW", "block.create.magenta_valve_handle": "ǝןpuɐH ǝʌןɐΛ ɐʇuǝbɐW", + "block.create.mangrove_window": "ʍopuıM ǝʌoɹbuɐW", + "block.create.mangrove_window_pane": "ǝuɐԀ ʍopuıM ǝʌoɹbuɐW", "block.create.mechanical_arm": "ɯɹⱯ ןɐɔıuɐɥɔǝW", "block.create.mechanical_bearing": "buıɹɐǝᗺ ןɐɔıuɐɥɔǝW", "block.create.mechanical_crafter": "ɹǝʇɟɐɹƆ ןɐɔıuɐɥɔǝW", @@ -296,6 +319,7 @@ "block.create.mechanical_plough": "ɥbnoןԀ ןɐɔıuɐɥɔǝW", "block.create.mechanical_press": "ssǝɹԀ ןɐɔıuɐɥɔǝW", "block.create.mechanical_pump": "dɯnԀ ןɐɔıuɐɥɔǝW", + "block.create.mechanical_roller": "ɹǝןןoᴚ ןɐɔıuɐɥɔǝW", "block.create.mechanical_saw": "ʍɐS ןɐɔıuɐɥɔǝW", "block.create.metal_bracket": "ʇǝʞɔɐɹᗺ ןɐʇǝW", "block.create.metal_girder": "ɹǝpɹı⅁ ןɐʇǝW", @@ -303,6 +327,7 @@ "block.create.millstone": "ǝuoʇsןןıW", "block.create.minecart_anchor": "ɹoɥɔuⱯ ʇɹɐɔǝuıW", "block.create.mysterious_cuckoo_clock": "ʞɔoןƆ ooʞɔnƆ", + "block.create.netherite_backtank": "ʞuɐʇʞɔɐᗺ ǝʇıɹǝɥʇǝN", "block.create.nixie_tube": "ǝqn⟘ ǝıxıN", "block.create.nozzle": "ǝןzzoN", "block.create.oak_window": "ʍopuıM ʞɐO", @@ -415,7 +440,7 @@ "block.create.rose_quartz_lamp": "dɯɐꞀ zʇɹɐnὉ ǝsoᴚ", "block.create.rose_quartz_tiles": "sǝןı⟘ zʇɹɐnὉ ǝsoᴚ", "block.create.rotation_speed_controller": "ɹǝןןoɹʇuoƆ pǝǝdS uoıʇɐʇoᴚ", - "block.create.sail_frame": "ǝɯɐɹℲ ןıɐS", + "block.create.sail_frame": "ǝɯɐɹℲ ןıɐS ןןıɯpuıM", "block.create.schematic_table": "ǝןqɐ⟘ ɔıʇɐɯǝɥɔS", "block.create.schematicannon": "uouuɐɔıʇɐɯǝɥɔS", "block.create.scorchia": "ɐıɥɔɹoɔS", @@ -495,7 +520,7 @@ "block.create.steam_whistle_extension": "uoısuǝʇxƎ ǝןʇsıɥM ɯɐǝʇS", "block.create.sticker": "ɹǝʞɔıʇS", "block.create.sticky_mechanical_piston": "uoʇsıԀ ןɐɔıuɐɥɔǝW ʎʞɔıʇS", - "block.create.stockpile_switch": "ɥɔʇıʍS ǝןıdʞɔoʇS", + "block.create.stockpile_switch": "ɥɔʇıʍS pןoɥsǝɹɥ⟘", "block.create.stressometer": "ɹǝʇǝɯossǝɹʇS", "block.create.tiled_glass": "ssɐן⅁ pǝןı⟘", "block.create.tiled_glass_pane": "ǝuɐԀ ssɐן⅁ pǝןı⟘", @@ -514,6 +539,7 @@ "block.create.warped_window": "ʍopuıM pǝdɹɐM", "block.create.warped_window_pane": "ǝuɐԀ ʍopuıM pǝdɹɐM", "block.create.water_wheel": "ןǝǝɥM ɹǝʇɐM", + "block.create.water_wheel_structure": "ןǝǝɥM ɹǝʇɐM ǝbɹɐꞀ", "block.create.waxed_copper_shingle_slab": "qɐןS ǝןbuıɥS ɹǝddoƆ pǝxɐM", "block.create.waxed_copper_shingle_stairs": "sɹıɐʇS ǝןbuıɥS ɹǝddoƆ pǝxɐM", "block.create.waxed_copper_shingles": "sǝןbuıɥS ɹǝddoƆ pǝxɐM", @@ -546,7 +572,7 @@ "block.create.weathered_copper_tiles": "sǝןı⟘ ɹǝddoƆ pǝɹǝɥʇɐǝM", "block.create.weighted_ejector": "ɹoʇɔǝظƎ pǝʇɥbıǝM", "block.create.white_nixie_tube": "ǝqn⟘ ǝıxıN ǝʇıɥM", - "block.create.white_sail": "ןıɐS ǝʇıɥM", + "block.create.white_sail": "ןıɐS ןןıɯpuıM", "block.create.white_seat": "ʇɐǝS ǝʇıɥM", "block.create.white_toolbox": "xoqןoo⟘ ǝʇıɥM", "block.create.white_valve_handle": "ǝןpuɐH ǝʌןɐΛ ǝʇıɥM", @@ -591,33 +617,33 @@ "item.create.cinder_flour": "ɹnoןℲ ɹǝpuıƆ", "item.create.copper_backtank": "ʞuɐʇʞɔɐᗺ ɹǝddoƆ", "item.create.copper_backtank_placeable": "ǝןqɐǝɔɐןԀ ʞuɐʇʞɔɐᗺ ɹǝddoƆ", + "item.create.copper_diving_boots": "sʇooᗺ buıʌıᗡ ɹǝddoƆ", + "item.create.copper_diving_helmet": "ʇǝɯןǝH buıʌıᗡ ɹǝddoƆ", "item.create.copper_nugget": "ʇǝbbnN ɹǝddoƆ", "item.create.copper_sheet": "ʇǝǝɥS ɹǝddoƆ", "item.create.crafter_slot_cover": "ɹǝʌoƆ ʇoןS ɹǝʇɟɐɹƆ", "item.create.crafting_blueprint": "ʇuıɹdǝnןᗺ buıʇɟɐɹƆ", "item.create.creative_blaze_cake": "ǝʞɐƆ ǝzɐןᗺ ǝʌıʇɐǝɹƆ", - "item.create.crushed_aluminum_ore": "ǝɹO ɯnuıɯnןⱯ pǝɥsnɹƆ", - "item.create.crushed_copper_ore": "ǝɹO ɹǝddoƆ pǝɥsnɹƆ", - "item.create.crushed_gold_ore": "ǝɹO pןo⅁ pǝɥsnɹƆ", - "item.create.crushed_iron_ore": "ǝɹO uoɹI pǝɥsnɹƆ", - "item.create.crushed_lead_ore": "ǝɹO pɐǝꞀ pǝɥsnɹƆ", - "item.create.crushed_nickel_ore": "ǝɹO ןǝʞɔıN pǝɥsnɹƆ", - "item.create.crushed_osmium_ore": "ǝɹO ɯnıɯsO pǝɥsnɹƆ", - "item.create.crushed_platinum_ore": "ǝɹO ɯnuıʇɐןԀ pǝɥsnɹƆ", - "item.create.crushed_quicksilver_ore": "ǝɹO ɹǝʌןısʞɔınὉ pǝɥsnɹƆ", - "item.create.crushed_silver_ore": "ǝɹO ɹǝʌןıS pǝɥsnɹƆ", - "item.create.crushed_tin_ore": "ǝɹO uı⟘ pǝɥsnɹƆ", - "item.create.crushed_uranium_ore": "ǝɹO ɯnıuɐɹ∩ pǝɥsnɹƆ", - "item.create.crushed_zinc_ore": "ǝɹO ɔuıZ pǝɥsnɹƆ", - "item.create.diving_boots": "sʇooᗺ buıʌıᗡ", - "item.create.diving_helmet": "ʇǝɯןǝH buıʌıᗡ", + "item.create.crushed_raw_aluminum": "ɯnuıɯnןⱯ ʍɐᴚ pǝɥsnɹƆ", + "item.create.crushed_raw_copper": "ɹǝddoƆ ʍɐᴚ pǝɥsnɹƆ", + "item.create.crushed_raw_gold": "pןo⅁ ʍɐᴚ pǝɥsnɹƆ", + "item.create.crushed_raw_iron": "uoɹI ʍɐᴚ pǝɥsnɹƆ", + "item.create.crushed_raw_lead": "pɐǝꞀ ʍɐᴚ pǝɥsnɹƆ", + "item.create.crushed_raw_nickel": "ןǝʞɔıN ʍɐᴚ pǝɥsnɹƆ", + "item.create.crushed_raw_osmium": "ɯnıɯsO ʍɐᴚ pǝɥsnɹƆ", + "item.create.crushed_raw_platinum": "ɯnuıʇɐןԀ ʍɐᴚ pǝɥsnɹƆ", + "item.create.crushed_raw_quicksilver": "ɹǝʌןısʞɔınὉ ʍɐᴚ pǝɥsnɹƆ", + "item.create.crushed_raw_silver": "ɹǝʌןıS ʍɐᴚ pǝɥsnɹƆ", + "item.create.crushed_raw_tin": "uı⟘ ʍɐᴚ pǝɥsnɹƆ", + "item.create.crushed_raw_uranium": "ɯnıuɐɹ∩ ʍɐᴚ pǝɥsnɹƆ", + "item.create.crushed_raw_zinc": "ɔuıZ ʍɐᴚ pǝɥsnɹƆ", "item.create.dough": "ɥbnoᗡ", "item.create.electron_tube": "ǝqn⟘ uoɹʇɔǝןƎ", "item.create.empty_blaze_burner": "ɹǝuɹnᗺ ǝzɐןᗺ ʎʇdɯƎ", "item.create.empty_schematic": "ɔıʇɐɯǝɥɔS ʎʇdɯƎ", "item.create.experience_nugget": "ǝɔuǝıɹǝdxƎ ɟo ʇǝbbnN", "item.create.extendo_grip": "dıɹ⅁ opuǝʇxƎ", - "item.create.filter": "ɹǝʇןıℲ", + "item.create.filter": "ɹǝʇןıℲ ʇsıꞀ", "item.create.furnace_minecart_contraption": "uoıʇdɐɹʇuoƆ ʇɹɐɔǝuıW ǝɔɐuɹnℲ", "item.create.goggles": "sǝןbbo⅁ s,ɹǝǝuıbuƎ", "item.create.golden_sheet": "ʇǝǝɥS uǝpןo⅁", @@ -630,6 +656,10 @@ "item.create.linked_controller": "ɹǝןןoɹʇuoƆ pǝʞuıꞀ", "item.create.minecart_contraption": "uoıʇdɐɹʇuoƆ ʇɹɐɔǝuıW", "item.create.minecart_coupling": "buıןdnoƆ ʇɹɐɔǝuıW", + "item.create.netherite_backtank": "ʞuɐʇʞɔɐᗺ ǝʇıɹǝɥʇǝN", + "item.create.netherite_backtank_placeable": "ǝןqɐǝɔɐןԀ ʞuɐʇʞɔɐᗺ ǝʇıɹǝɥʇǝN", + "item.create.netherite_diving_boots": "sʇooᗺ buıʌıᗡ ǝʇıɹǝɥʇǝN", + "item.create.netherite_diving_helmet": "ʇǝɯןǝH buıʌıᗡ ǝʇıɹǝɥʇǝN", "item.create.polished_rose_quartz": "zʇɹɐnὉ ǝsoᴚ pǝɥsıןoԀ", "item.create.potato_cannon": "uouuɐƆ oʇɐʇoԀ", "item.create.powdered_obsidian": "uɐıpısqO pǝɹǝpʍoԀ", diff --git a/src/generated/resources/assets/create/lang/en_us.json b/src/generated/resources/assets/create/lang/en_us.json index 566bc6fca..6d5b564e2 100644 --- a/src/generated/resources/assets/create/lang/en_us.json +++ b/src/generated/resources/assets/create/lang/en_us.json @@ -6,14 +6,18 @@ "block.create.acacia_window_pane": "Acacia Window Pane", "block.create.adjustable_chain_gearshift": "Adjustable Chain Gearshift", "block.create.analog_lever": "Analog Lever", + "block.create.andesite_alloy_block": "Block of Andesite Alloy", + "block.create.andesite_bars": "Andesite Bars", "block.create.andesite_belt_funnel": "Andesite Belt Funnel", "block.create.andesite_casing": "Andesite Casing", + "block.create.andesite_door": "Andesite Door", "block.create.andesite_encased_cogwheel": "Andesite Encased Cogwheel", "block.create.andesite_encased_large_cogwheel": "Andesite Encased Large Cogwheel", "block.create.andesite_encased_shaft": "Andesite Encased Shaft", "block.create.andesite_funnel": "Andesite Funnel", "block.create.andesite_ladder": "Andesite Ladder", "block.create.andesite_pillar": "Andesite Pillar", + "block.create.andesite_scaffolding": "Andesite Scaffolding", "block.create.andesite_tunnel": "Andesite Tunnel", "block.create.asurine": "Asurine", "block.create.asurine_pillar": "Asurine Pillar", @@ -32,14 +36,17 @@ "block.create.blue_seat": "Blue Seat", "block.create.blue_toolbox": "Blue Toolbox", "block.create.blue_valve_handle": "Blue Valve Handle", + "block.create.brass_bars": "Brass Bars", "block.create.brass_belt_funnel": "Brass Belt Funnel", "block.create.brass_block": "Block of Brass", "block.create.brass_casing": "Brass Casing", + "block.create.brass_door": "Brass Door", "block.create.brass_encased_cogwheel": "Brass Encased Cogwheel", "block.create.brass_encased_large_cogwheel": "Brass Encased Large Cogwheel", "block.create.brass_encased_shaft": "Brass Encased Shaft", "block.create.brass_funnel": "Brass Funnel", "block.create.brass_ladder": "Brass Ladder", + "block.create.brass_scaffolding": "Brass Scaffolding", "block.create.brass_tunnel": "Brass Tunnel", "block.create.brown_nixie_tube": "Brown Nixie Tube", "block.create.brown_sail": "Brown Sail", @@ -50,15 +57,20 @@ "block.create.cart_assembler": "Cart Assembler", "block.create.chocolate": "Chocolate", "block.create.chute": "Chute", + "block.create.clipboard": "Clipboard", "block.create.clockwork_bearing": "Clockwork Bearing", "block.create.clutch": "Clutch", "block.create.cogwheel": "Cogwheel", - "block.create.content_observer": "Content Observer", + "block.create.content_observer": "Smart Observer", + "block.create.contraption_controls": "Contraption Controls", "block.create.controller_rail": "Controller Rail", "block.create.controls": "Train Controls", "block.create.copper_backtank": "Copper Backtank", + "block.create.copper_bars": "Copper Bars", "block.create.copper_casing": "Copper Casing", + "block.create.copper_door": "Copper Door", "block.create.copper_ladder": "Copper Ladder", + "block.create.copper_scaffolding": "Copper Scaffolding", "block.create.copper_shingle_slab": "Copper Shingle Slab", "block.create.copper_shingle_stairs": "Copper Shingle Stairs", "block.create.copper_shingles": "Copper Shingles", @@ -66,6 +78,10 @@ "block.create.copper_tile_stairs": "Copper Tile Stairs", "block.create.copper_tiles": "Copper Tiles", "block.create.copper_valve_handle": "Copper Valve Handle", + "block.create.copycat_bars": "Copycat Bars", + "block.create.copycat_base": "Copycat Base", + "block.create.copycat_panel": "Copycat Panel", + "block.create.copycat_step": "Copycat Step", "block.create.creative_crate": "Creative Crate", "block.create.creative_fluid_tank": "Creative Fluid Tank", "block.create.creative_motor": "Creative Motor", @@ -203,9 +219,12 @@ "block.create.display_board": "Display Board", "block.create.display_link": "Display Link", "block.create.dripstone_pillar": "Dripstone Pillar", + "block.create.elevator_contact": "Elevator Contact", + "block.create.elevator_pulley": "Elevator Pulley", "block.create.encased_chain_drive": "Encased Chain Drive", "block.create.encased_fan": "Encased Fan", "block.create.encased_fluid_pipe": "Encased Fluid Pipe", + "block.create.experience_block": "Block of Experience", "block.create.exposed_copper_shingle_slab": "Exposed Copper Shingle Slab", "block.create.exposed_copper_shingle_stairs": "Exposed Copper Shingle Stairs", "block.create.exposed_copper_shingles": "Exposed Copper Shingles", @@ -243,12 +262,14 @@ "block.create.horizontal_framed_glass": "Horizontal Framed Glass", "block.create.horizontal_framed_glass_pane": "Horizontal Framed Glass Pane", "block.create.hose_pulley": "Hose Pulley", + "block.create.industrial_iron_block": "Block of Industrial Iron", "block.create.item_drain": "Item Drain", "block.create.item_vault": "Item Vault", "block.create.jungle_window": "Jungle Window", "block.create.jungle_window_pane": "Jungle Window Pane", "block.create.large_bogey": "Large Bogey", "block.create.large_cogwheel": "Large Cogwheel", + "block.create.large_water_wheel": "Large Water Wheel", "block.create.layered_andesite": "Layered Andesite", "block.create.layered_asurine": "Layered Asurine", "block.create.layered_calcite": "Layered Calcite", @@ -288,6 +309,8 @@ "block.create.magenta_seat": "Magenta Seat", "block.create.magenta_toolbox": "Magenta Toolbox", "block.create.magenta_valve_handle": "Magenta Valve Handle", + "block.create.mangrove_window": "Mangrove Window", + "block.create.mangrove_window_pane": "Mangrove Window Pane", "block.create.mechanical_arm": "Mechanical Arm", "block.create.mechanical_bearing": "Mechanical Bearing", "block.create.mechanical_crafter": "Mechanical Crafter", @@ -299,6 +322,7 @@ "block.create.mechanical_plough": "Mechanical Plough", "block.create.mechanical_press": "Mechanical Press", "block.create.mechanical_pump": "Mechanical Pump", + "block.create.mechanical_roller": "Mechanical Roller", "block.create.mechanical_saw": "Mechanical Saw", "block.create.metal_bracket": "Metal Bracket", "block.create.metal_girder": "Metal Girder", @@ -306,6 +330,7 @@ "block.create.millstone": "Millstone", "block.create.minecart_anchor": "Minecart Anchor", "block.create.mysterious_cuckoo_clock": "Cuckoo Clock", + "block.create.netherite_backtank": "Netherite Backtank", "block.create.nixie_tube": "Nixie Tube", "block.create.nozzle": "Nozzle", "block.create.oak_window": "Oak Window", @@ -418,7 +443,7 @@ "block.create.rose_quartz_lamp": "Rose Quartz Lamp", "block.create.rose_quartz_tiles": "Rose Quartz Tiles", "block.create.rotation_speed_controller": "Rotation Speed Controller", - "block.create.sail_frame": "Sail Frame", + "block.create.sail_frame": "Windmill Sail Frame", "block.create.schematic_table": "Schematic Table", "block.create.schematicannon": "Schematicannon", "block.create.scorchia": "Scorchia", @@ -498,7 +523,7 @@ "block.create.steam_whistle_extension": "Steam Whistle Extension", "block.create.sticker": "Sticker", "block.create.sticky_mechanical_piston": "Sticky Mechanical Piston", - "block.create.stockpile_switch": "Stockpile Switch", + "block.create.stockpile_switch": "Threshold Switch", "block.create.stressometer": "Stressometer", "block.create.tiled_glass": "Tiled Glass", "block.create.tiled_glass_pane": "Tiled Glass Pane", @@ -517,6 +542,7 @@ "block.create.warped_window": "Warped Window", "block.create.warped_window_pane": "Warped Window Pane", "block.create.water_wheel": "Water Wheel", + "block.create.water_wheel_structure": "Large Water Wheel", "block.create.waxed_copper_shingle_slab": "Waxed Copper Shingle Slab", "block.create.waxed_copper_shingle_stairs": "Waxed Copper Shingle Stairs", "block.create.waxed_copper_shingles": "Waxed Copper Shingles", @@ -549,7 +575,7 @@ "block.create.weathered_copper_tiles": "Weathered Copper Tiles", "block.create.weighted_ejector": "Weighted Ejector", "block.create.white_nixie_tube": "White Nixie Tube", - "block.create.white_sail": "White Sail", + "block.create.white_sail": "Windmill Sail", "block.create.white_seat": "White Seat", "block.create.white_toolbox": "White Toolbox", "block.create.white_valve_handle": "White Valve Handle", @@ -598,33 +624,33 @@ "item.create.cinder_flour": "Cinder Flour", "item.create.copper_backtank": "Copper Backtank", "item.create.copper_backtank_placeable": "Copper Backtank Placeable", + "item.create.copper_diving_boots": "Copper Diving Boots", + "item.create.copper_diving_helmet": "Copper Diving Helmet", "item.create.copper_nugget": "Copper Nugget", "item.create.copper_sheet": "Copper Sheet", "item.create.crafter_slot_cover": "Crafter Slot Cover", "item.create.crafting_blueprint": "Crafting Blueprint", "item.create.creative_blaze_cake": "Creative Blaze Cake", - "item.create.crushed_aluminum_ore": "Crushed Aluminum Ore", - "item.create.crushed_copper_ore": "Crushed Copper Ore", - "item.create.crushed_gold_ore": "Crushed Gold Ore", - "item.create.crushed_iron_ore": "Crushed Iron Ore", - "item.create.crushed_lead_ore": "Crushed Lead Ore", - "item.create.crushed_nickel_ore": "Crushed Nickel Ore", - "item.create.crushed_osmium_ore": "Crushed Osmium Ore", - "item.create.crushed_platinum_ore": "Crushed Platinum Ore", - "item.create.crushed_quicksilver_ore": "Crushed Quicksilver Ore", - "item.create.crushed_silver_ore": "Crushed Silver Ore", - "item.create.crushed_tin_ore": "Crushed Tin Ore", - "item.create.crushed_uranium_ore": "Crushed Uranium Ore", - "item.create.crushed_zinc_ore": "Crushed Zinc Ore", - "item.create.diving_boots": "Diving Boots", - "item.create.diving_helmet": "Diving Helmet", + "item.create.crushed_raw_aluminum": "Crushed Raw Aluminum", + "item.create.crushed_raw_copper": "Crushed Raw Copper", + "item.create.crushed_raw_gold": "Crushed Raw Gold", + "item.create.crushed_raw_iron": "Crushed Raw Iron", + "item.create.crushed_raw_lead": "Crushed Raw Lead", + "item.create.crushed_raw_nickel": "Crushed Raw Nickel", + "item.create.crushed_raw_osmium": "Crushed Raw Osmium", + "item.create.crushed_raw_platinum": "Crushed Raw Platinum", + "item.create.crushed_raw_quicksilver": "Crushed Raw Quicksilver", + "item.create.crushed_raw_silver": "Crushed Raw Silver", + "item.create.crushed_raw_tin": "Crushed Raw Tin", + "item.create.crushed_raw_uranium": "Crushed Raw Uranium", + "item.create.crushed_raw_zinc": "Crushed Raw Zinc", "item.create.dough": "Dough", "item.create.electron_tube": "Electron Tube", "item.create.empty_blaze_burner": "Empty Blaze Burner", "item.create.empty_schematic": "Empty Schematic", "item.create.experience_nugget": "Nugget of Experience", "item.create.extendo_grip": "Extendo Grip", - "item.create.filter": "Filter", + "item.create.filter": "List Filter", "item.create.furnace_minecart_contraption": "Furnace Minecart Contraption", "item.create.goggles": "Engineer's Goggles", "item.create.golden_sheet": "Golden Sheet", @@ -637,6 +663,10 @@ "item.create.linked_controller": "Linked Controller", "item.create.minecart_contraption": "Minecart Contraption", "item.create.minecart_coupling": "Minecart Coupling", + "item.create.netherite_backtank": "Netherite Backtank", + "item.create.netherite_backtank_placeable": "Netherite Backtank Placeable", + "item.create.netherite_diving_boots": "Netherite Diving Boots", + "item.create.netherite_diving_helmet": "Netherite Diving Helmet", "item.create.polished_rose_quartz": "Polished Rose Quartz", "item.create.potato_cannon": "Potato Cannon", "item.create.powdered_obsidian": "Powdered Obsidian", @@ -841,8 +871,6 @@ "advancement.create.train_portal.desc": "Ride a Train through a Nether portal", "advancement.create.track_crafting_factory": "Track Factory", "advancement.create.track_crafting_factory.desc": "Produce more than 1000 Train Tracks with the same Mechanical Press", - "advancement.create.long_bend": "The Longest Bend", - "advancement.create.long_bend.desc": "Create a curved track section that spans more than 30 blocks in length", "advancement.create.long_train": "Ambitious Endeavours", "advancement.create.long_train.desc": "Create a Train with at least 6 carriages", "advancement.create.long_travel": "Field Trip", @@ -870,6 +898,8 @@ "death.attack.create.fan_lava.player": "%1$s was thrown into a smelter by %2$s", "death.attack.create.mechanical_drill": "%1$s was impaled by a Mechanical Drill", "death.attack.create.mechanical_drill.player": "%1$s was thrown in front of a Drill by %2$s", + "death.attack.create.mechanical_roller": "%1$s was flattened by a Mechanical Roller", + "death.attack.create.mechanical_roller.player": "%1$s was thrown in front of a Mechanical Roller by %2$s", "death.attack.create.mechanical_saw": "%1$s got cut in half by a Mechanical Saw", "death.attack.create.mechanical_saw.player": "%1$s was thrown into a Saw by %2$s", "death.attack.create.potato_cannon": "%1$s was shot by %2$s's Potato Cannon", @@ -939,6 +969,7 @@ "create.generic.length": "Length", "create.generic.speed": "Speed", "create.generic.delay": "Delay", + "create.generic.angle": "Angle", "create.generic.duration": "Duration", "create.generic.timeUnit": "Time Unit", "create.generic.unit.ticks": "Ticks", @@ -1030,12 +1061,15 @@ "create.terrainzapper.usingBlock": "Using: %1$s", "create.terrainzapper.leftClickToSet": "Left-Click a Block to set Material", + "create.large_water_wheel.not_enough_space": "Clear Blocks for Placement", + "create.minecart_coupling.two_couplings_max": "Minecarts cannot have more than two couplings each", "create.minecart_coupling.unloaded": "Parts of your train seem to be in unloaded chunks", "create.minecart_coupling.no_loops": "Couplings cannot form a loop", "create.minecart_coupling.removed": "Removed all couplings from minecart", "create.minecart_coupling.too_far": "Minecarts are too far apart", + "create.contraptions.moving_container": "Moving %1$s", "create.contraptions.movement_mode": "Movement Mode", "create.contraptions.movement_mode.move_place": "Always Place when Stopped", "create.contraptions.movement_mode.move_place_returned": "Place only in Starting Position", @@ -1047,25 +1081,55 @@ "create.contraptions.cart_movement_mode.rotate": "Always face toward motion", "create.contraptions.cart_movement_mode.rotate_paused": "Pause actors while rotating", "create.contraptions.cart_movement_mode.rotation_locked": "Lock rotation", + "create.contraptions.roller_mode": "Roller Mode", + "create.contraptions.roller_mode.tunnel_pave": "Clear Blocks and Pave", + "create.contraptions.roller_mode.straight_fill": "Straight Fill Below", + "create.contraptions.roller_mode.wide_fill": "Sloped Fill Below", "create.contraptions.windmill.rotation_direction": "Rotation Direction", - "create.contraptions.clockwork.clock_hands": "Clock Hands", + "create.contraptions.clockwork.clock_hands": "Clock Hand Arrangement", "create.contraptions.clockwork.hour_first": "Hour hand first", "create.contraptions.clockwork.minute_first": "Minute hand first", "create.contraptions.clockwork.hour_first_24": "24-Hour hand first", + "create.logistics.crafter.connected": "Connected Crafters", + "create.logistics.crafter.click_to_merge": "Click to merge Inventories", + "create.logistics.crafter.click_to_separate": "Click to separate Inventories", "create.logistics.filter": "Filter", "create.logistics.recipe_filter": "Recipe Filter", "create.logistics.fluid_filter": "Fluid Filter", - "create.logistics.firstFrequency": "Freq. #1", - "create.logistics.secondFrequency": "Freq. #2", - "create.logistics.filter.apply": "Applied filter to %1$s.", - "create.logistics.filter.apply_click_again": "Applied filter to %1$s, click again to copy the amount.", - "create.logistics.filter.apply_count": "Applied extraction count to filter.", + "create.logistics.firstFrequency": "Frequency #1", + "create.logistics.secondFrequency": "Frequency #2", + "create.logistics.filter.click_to_set": "Click with item to set", + "create.logistics.filter.click_to_replace": "Click with item to replace", + "create.logistics.filter.hold_to_set_amount": "Click and hold for amount", + "create.logistics.filter.invalid_item": "Cannot use this item here.", + "create.logistics.filter.extracted_amount": "Extracted Amount", + "create.logistics.filter.any_amount_short": "Any", + "create.logistics.filter.up_to": "Up to", + "create.logistics.filter.exactly": "Exactly", + "create.logistics.filter.requires_item_in_inventory": "Requires %1$s item in Inventory", + "create.logistics.creative_crate.supply": "Infinite Supply", + "create.logistics.train_observer.cargo_filter": "Cargo Filter", + "create.kinetics.creative_motor.rotation_speed": "Generated Speed in RPM", + "create.kinetics.speed_controller.rotation_speed": "Targeted Speed in RPM", + "create.kinetics.valve_handle.rotated_angle": "Rotation when used", + + "create.logistics.redstone_interval": "Redstone Interval", + + "create.contraptions.contoller.target": "Targeted Component", + "create.contraptions.mechanical_roller.pave_material": "Paving Material", + "create.contraptions.chassis.radius": "Radius when Sticky", + "create.contraptions.chassis.range": "Range of Sticky Sides", + "create.contraptions.chassis.distance": "Distance", + + "create.gui.value_settings.hold_to_edit": "Click and hold to edit", + "create.gui.value_settings.release_to_confirm": "Release %1$s to Confirm", "create.gui.goggles.generator_stats": "Generator Stats:", "create.gui.goggles.kinetic_stats": "Kinetic Stats:", "create.gui.goggles.at_current_speed": "at current speed", "create.gui.goggles.pole_length": "Pole Length:", + "create.gui.goggles.basin_contents": "Basin Contents:", "create.gui.goggles.fluid_container": "Fluid Container Info:", "create.gui.goggles.fluid_container.capacity": "Capacity: ", "create.gui.assembly.exception": "This Contraption was unable to assemble:", @@ -1075,6 +1139,9 @@ "create.gui.assembly.exception.tooManyPistonPoles": "There are too many extension Poles attached to this Piston.\nThe configured maximum is: %1$s", "create.gui.assembly.exception.noPistonPoles": "The Piston is missing some extension Poles", "create.gui.assembly.exception.not_enough_sails": "Attached structure does not include enough sail-like blocks: %1$s\nA minimum of %2$s are required", + "create.gui.assembly.exception.no_contacts": "Elevators require a horizontal _Redstone_ _Contact_ attached to the structure", + "create.gui.assembly.exception.too_many_contacts": "Cannot attach more than one _Redstone_ _Contact_ to Elevators", + "create.gui.assembly.exception.column_conflict": "Another Elevator is already targeting this column of contacts", "create.gui.gauge.info_header": "Gauge Information:", "create.gui.speedometer.title": "Rotation Speed", "create.gui.stressometer.title": "Network Stress", @@ -1085,10 +1152,10 @@ "create.gui.contraptions.network_overstressed": "It appears that this contraption is _overstressed_. Add more sources or _slow_ _down_ the components with a high _stress_ _impact_.", "create.gui.adjustable_crate.title": "Adjustable Crate", "create.gui.adjustable_crate.storageSpace": "Storage Space", - "create.gui.stockpile_switch.title": "Stockpile Switch", - "create.gui.stockpile_switch.invert_signal": "Invert Signal", - "create.gui.stockpile_switch.move_to_lower_at": "Move to lower lane at %1$s%%", - "create.gui.stockpile_switch.move_to_upper_at": "Move to upper lane at %1$s%%", + "create.gui.threshold_switch.title": "Threshold Switch", + "create.gui.threshold_switch.invert_signal": "Invert Signal", + "create.gui.threshold_switch.move_to_lower_at": "Move to lower lane at %1$s%%", + "create.gui.threshold_switch.move_to_upper_at": "Move to upper lane at %1$s%%", "create.gui.sequenced_gearshift.title": "Sequenced Gearshift", "create.gui.sequenced_gearshift.instruction": "Instruction", "create.gui.sequenced_gearshift.instruction.turn_angle.descriptive": "Turn by angle", @@ -1109,6 +1176,13 @@ "create.gui.sequenced_gearshift.speed.forward_fast": "Double speed, Forwards", "create.gui.sequenced_gearshift.speed.back": "Input speed, Reversed", "create.gui.sequenced_gearshift.speed.back_fast": "Double speed, Reversed", + "create.gui.clipboard.erase_checked": "Erase checked items", + + "create.clipboard.actions": "Clipboard Actions", + "create.clipboard.to_copy": "%1$s to Copy settings", + "create.clipboard.to_paste": "%1$s to Paste settings", + "create.clipboard.copied_from": "Copying settings from %1$s", + "create.clipboard.pasted_to": "Applied settings to %1$s", "create.schematicAndQuill.dimensions": "Schematic Size: %1$sx%2$sx%3$s", "create.schematicAndQuill.firstPos": "First position set.", @@ -1119,6 +1193,8 @@ "create.schematicAndQuill.convert": "Save and Upload Immediately", "create.schematicAndQuill.fallbackName": "My Schematic", "create.schematicAndQuill.saved": "Saved as %1$s", + "create.schematicAndQuill.failed": "Failed to save schematic, check logs for details", + "create.schematicAndQuill.instant_failed": "Schematic instant-upload failed, check logs for details", "create.schematic.invalid": "[!] Invalid Item - Use the Schematic Table instead", "create.schematic.error": "Schematic failed to Load - Check Game Logs", @@ -1134,7 +1210,7 @@ "create.schematic.mirror.leftRight": "Left-Right", "create.schematic.tool.deploy": "Position", "create.schematic.tool.move": "Move XZ", - "create.schematic.tool.movey": "Move Y", + "create.schematic.tool.move_y": "Move Y", "create.schematic.tool.rotate": "Rotate", "create.schematic.tool.print": "Print", "create.schematic.tool.flip": "Mirror", @@ -1146,10 +1222,10 @@ "create.schematic.tool.move.description.1": "Point at the Schematic and [CTRL]-Scroll to push it.", "create.schematic.tool.move.description.2": "", "create.schematic.tool.move.description.3": "", - "create.schematic.tool.movey.description.0": "Shifts the Schematic Vertically.", - "create.schematic.tool.movey.description.1": "[CTRL]-Scroll to move it up/down.", - "create.schematic.tool.movey.description.2": "", - "create.schematic.tool.movey.description.3": "", + "create.schematic.tool.move_y.description.0": "Shifts the Schematic Vertically.", + "create.schematic.tool.move_y.description.1": "[CTRL]-Scroll to move it up/down.", + "create.schematic.tool.move_y.description.2": "", + "create.schematic.tool.move_y.description.3": "", "create.schematic.tool.rotate.description.0": "Rotates the Schematic around its center.", "create.schematic.tool.rotate.description.1": "[CTRL]-Scroll to rotate by 90 Degrees.", "create.schematic.tool.rotate.description.2": "", @@ -1187,12 +1263,12 @@ "create.gui.schematicannon.option.replaceWithAny": "Replace Solid with Any", "create.gui.schematicannon.option.replaceWithEmpty": "Replace Solid with Empty", "create.gui.schematicannon.option.skipMissing": "Skip missing Blocks", - "create.gui.schematicannon.option.skipTileEntities": "Protect Tile Entities", + "create.gui.schematicannon.option.skipBlockEntities": "Protect Block Entities", "create.gui.schematicannon.slot.gunpowder": "Add gunpowder to fuel the cannon", - "create.gui.schematicannon.slot.listPrinter": "Place books here to print a Checklist for your Schematic", + "create.gui.schematicannon.slot.listPrinter": "Place a Clipboard or Book here to print a Checklist for your Schematic", "create.gui.schematicannon.slot.schematic": "Add your Schematic here. Make sure it is deployed at a specific location.", "create.gui.schematicannon.option.skipMissing.description": "If the cannon cannot find a required Block for placement, it will continue at the next Location.", - "create.gui.schematicannon.option.skipTileEntities.description": "The cannon will avoid replacing data holding blocks such as Chests.", + "create.gui.schematicannon.option.skipBlockEntities.description": "The cannon will avoid replacing data holding blocks such as Chests.", "create.gui.schematicannon.option.dontReplaceSolid.description": "The cannon will never replace any Solid blocks in its working area, only non-Solid and Air.", "create.gui.schematicannon.option.replaceWithSolid.description": "The cannon will only replace Solid blocks in its working area if the Schematic contains a solid Block at the Location.", "create.gui.schematicannon.option.replaceWithAny.description": "The cannon will replace Solid blocks in its working area if the Schematic contains any Block at the Location.", @@ -1349,7 +1425,7 @@ "create.weighted_ejector.targeting": "Ejecting to [%1$s,%2$s,%3$s]", "create.weighted_ejector.stack_size": "Ejected Stack Size", - "create.logistics.when_multiple_outputs_available": "When Multiple Outputs Available", + "create.logistics.when_multiple_outputs_available": "Distribution Method", "create.mechanical_arm.selection_mode.round_robin": "Round Robin", "create.mechanical_arm.selection_mode.forced_round_robin": "Forced Round Robin", @@ -1404,7 +1480,7 @@ "create.hint.mechanical_arm_no_targets": "It appears this _Mechanical_ _Arm_ has not been assigned any _targets._ Select belts, depots, funnels and other blocks by _right-clicking_ them while _holding_ the _Mechanical_ _Arm_ in your _hand_.", "create.hint.empty_bearing.title": "Update Bearing", "create.hint.empty_bearing": "_Right-click_ the bearing with an _empty_ _hand_ to _attach_ the structure you just built in front of it.", - "create.hint.full_deployer.title": "Deployer Item Overflow", + "create.hint.full_deployer.title": "Deployer cannot activate", "create.hint.full_deployer": "It appears this _Deployer_ contains _excess_ _items_ that need to be _extracted._ Use a _hopper,_ _funnel_ or other means to free it from its overflow.", "create.backtank.low": "Backtank pressure low", @@ -1427,6 +1503,12 @@ "create.boiler.heat_dots": "...... ", "create.boiler.via_one_engine": "via 1 engine", "create.boiler.via_engines": "via %1$s engines", + "create.boiler.water_input_rate": "Water input rate", + "create.boiler.per_tick": "%1$s per Tick", + + "create.elevator_contact.title": "Elevator Contact", + "create.elevator_contact.floor_identifier": "Floor Identifier", + "create.elevator_contact.floor_description": "Floor Description", "create.gui.schedule.lmb_edit": "Left-Click to Edit", "create.gui.schedule.rmb_remove": "Right-Click to Remove", @@ -1549,6 +1631,7 @@ "create.track.turn_start": "Cannot start connection from a Turn", "create.track.not_enough_tracks": "Not holding enough tracks", "create.track.not_enough_pavement": "Not holding enough pavement blocks", + "create.track.hold_for_smooth_curve": "Hold %1$s for maximized turn", "create.portal_track.failed": "Cannot place portal track:", "create.portal_track.missing": "Target portal not generated yet", @@ -1587,8 +1670,8 @@ "create.train_assembly.bogeys_too_close": "Bogeys %1$s and %2$s are too close to each other", "create.train_assembly.single_bogey_carriage": "This Bogey type cannot support a carriage on its own", "create.train_assembly.nothing_attached": "No structure attached to Bogey %1$s", - "create.train_assembly.no_controls": "At least one forward-facing controls block needs to be mounted on the train", - "create.train_assembly.sideways_controls": "A mounted controls block is facing sideways", + "create.train_assembly.no_controls": "Attach at least one forward-facing Train Controls block (Are you missing Super Glue?)", + "create.train_assembly.sideways_controls": "Train Controls cannot face sideways", "create.train_assembly.bogey_created": "Bogey created. Click again to cycle type", "create.train_assembly.requires_casing": "Use Railway Casing to create bogeys on tracks", @@ -1633,6 +1716,25 @@ "create.contraption.controls.start_controlling": "Now controlling: %1$s", "create.contraption.controls.stop_controlling": "Stopped controlling contraption", "create.contraption.controls.approach_station": "Hold %1$s to approach %2$s", + "create.contraption.controls.specific_actor_toggle": "%1$s Actors: %2$s", + "create.contraption.controls.all_actor_toggle": "All Actors: %1$s", + "create.contraption.controls.actor_toggle.on": "On", + "create.contraption.controls.actor_toggle.off": "Off", + "create.contraption.controls.floor_unreachable": "Unreachable", + "create.contraption.door_control": "Onboard Door Control", + "create.contraption.door_control.all": "Open All Doors", + "create.contraption.door_control.all.short": "Open All", + "create.contraption.door_control.north": "North Side Only", + "create.contraption.door_control.north.short": "North", + "create.contraption.door_control.east": "East Side Only", + "create.contraption.door_control.east.short": "East", + "create.contraption.door_control.south": "South Side Only", + "create.contraption.door_control.south.short": "South", + "create.contraption.door_control.west": "West Side Only", + "create.contraption.door_control.west.short": "West", + "create.contraption.door_control.none": "Keep Doors Closed", + "create.contraption.door_control.none.short": "None", + "create.contraption.door_control.player_facing": "You are facing: %1$s", "create.display_link.set": "Targeted position selected", "create.display_link.success": "Successfully bound to targeted position", @@ -1695,6 +1797,7 @@ "create.display_source.max_enchant_level": "Max Enchanting Cost", "create.display_source.boiler_status": "Boiler Status", "create.display_source.entity_name": "Entity Name", + "create.display_source.current_floor": "Elevator Location", "create.display_source.kinetic_speed": "Rotation Speed (RPM)", "create.display_source.kinetic_speed.absolute": "Ignore Direction", "create.display_source.kinetic_speed.directional": "Include Direction", @@ -1711,6 +1814,7 @@ "create.display_source.redstone_power.progress_bar": "Progress Bar", "create.display_source.boiler.not_enough_space": "Not enough space ", "create.display_source.boiler.for_boiler_status": "for Boiler Status", + "create.display_source.computer_display_source": "From Computer", "create.display_target.line": "Line %1$s", "create.display_target.page": "Page %1$s", @@ -1733,6 +1837,8 @@ "create.super_glue.not_enough": "Not enough glue in inventory", "create.super_glue.success": "Applying Glue...", + "create.gui.attached_computer.controlled": "This device is being controlled by a computer", + "create.gui.attached_computer.hint": "To use device manually, disconnect all computers and modems", "create.gui.config.overlay1": "Hi :)", "create.gui.config.overlay2": "This is a sample overlay", "create.gui.config.overlay3": "Click or drag with your mouse", @@ -1756,6 +1862,12 @@ "enchantment.create.capacity.desc": "Increases Backtank air capacity.", "enchantment.create.potato_recovery.desc": "Potato Cannon projectiles have a chance to be reused.", + "create.bogey.style.updated_style": "Updated style", + "create.bogey.style.updated_style_and_size": "Updated style and size", + "create.bogey.style.no_other_sizes": "No other sizes", + "create.bogey.style.invalid": "Unnamed style", + "create.bogey.style.standard": "Standard", + "_": "->------------------------] Subtitles [------------------------<-", @@ -1833,57 +1945,49 @@ "item.create.blaze_cake.tooltip.summary": "A Delicious treat for your hard-working _Blaze Burners_. Gets them all fired up!", "item.create.wand_of_symmetry.tooltip": "SYMMETRY WAND", - "item.create.wand_of_symmetry.tooltip.summary": "Perfectly mirrors Block placement across configured planes.", - "item.create.wand_of_symmetry.tooltip.condition1": "When in Hotbar", - "item.create.wand_of_symmetry.tooltip.behaviour1": "Stays Active", - "item.create.wand_of_symmetry.tooltip.control1": "R-Click on Ground", - "item.create.wand_of_symmetry.tooltip.action1": "_Creates_ or _Moves_ the Mirror", - "item.create.wand_of_symmetry.tooltip.control2": "R-Click in the Air", - "item.create.wand_of_symmetry.tooltip.action2": "_Removes_ the active Mirror", - "item.create.wand_of_symmetry.tooltip.control3": "R-Click while Sneaking", - "item.create.wand_of_symmetry.tooltip.action3": "Opens the _Configuration Interface_", + "item.create.wand_of_symmetry.tooltip.summary": "_Mirrors Block placement_ while present in any _Hotbar Slot_.", + "item.create.wand_of_symmetry.tooltip.condition1": "When used on a Surface", + "item.create.wand_of_symmetry.tooltip.behaviour1": "_Creates_ or _Moves_ its Mirror. _Sneak_ while using to open the _Configuration Interface_", + "item.create.wand_of_symmetry.tooltip.condition2": "When used with no target", + "item.create.wand_of_symmetry.tooltip.behaviour2": "_Removes_ the active Mirror", "item.create.handheld_worldshaper.tooltip": "HANDHELD WORLDSHAPER", - "item.create.handheld_worldshaper.tooltip.summary": "Handy tool for creating _landscapes_ and _terrain features_.", - "item.create.handheld_worldshaper.tooltip.control1": "L-Click at Block", - "item.create.handheld_worldshaper.tooltip.action1": "Sets blocks placed by the tool to the targeted block.", - "item.create.handheld_worldshaper.tooltip.control2": "R-Click at Block", - "item.create.handheld_worldshaper.tooltip.action2": "Applies the currently selected _Brush_ and _Tool_ at the targeted location.", - "item.create.handheld_worldshaper.tooltip.control3": "R-Click while Sneaking", - "item.create.handheld_worldshaper.tooltip.action3": "Opens the _Configuration Interface_", + "item.create.handheld_worldshaper.tooltip.summary": "_Creative mode_ tool for large-scale _landscaping_ from a distance.", + "item.create.handheld_worldshaper.tooltip.condition1": "L-Click at Block", + "item.create.handheld_worldshaper.tooltip.behaviour1": "_Targeted block_ will become the _material_ placed by the shaper.", + "item.create.handheld_worldshaper.tooltip.condition2": "R-Click at Block", + "item.create.handheld_worldshaper.tooltip.behaviour2": "Applies currently selected _Brush_ and _Tool_ at the targeted location.", + "item.create.handheld_worldshaper.tooltip.condition3": "R-Click while Sneaking", + "item.create.handheld_worldshaper.tooltip.behaviour3": "Opens the _Configuration Interface_", "item.create.tree_fertilizer.tooltip": "TREE FERTILIZER", - "item.create.tree_fertilizer.tooltip.summary": "A powerful combination of minerals suitable for speeding up the growth of common tree types.", + "item.create.tree_fertilizer.tooltip.summary": "A powerful combination of minerals useful for _growing saplings_ in tight spaces.", "item.create.tree_fertilizer.tooltip.condition1": "When used on a Sapling", - "item.create.tree_fertilizer.tooltip.behaviour1": "Grows Trees _regardless_ of their _spacing conditions_", + "item.create.tree_fertilizer.tooltip.behaviour1": "Creates a tree _regardless_ of its _spacing conditions_", "item.create.extendo_grip.tooltip": "EXTENDO GRIP", - "item.create.extendo_grip.tooltip.summary": "Boioioing! Greatly _increases reach distance_ of the wielder. Can be powered with Air Pressure from a _Copper_ _Backtank_", + "item.create.extendo_grip.tooltip.summary": "Greatly _increases reach distance_ of the wielder. Can be powered with _Air_ _Pressure_ from a _Backtank_", "item.create.extendo_grip.tooltip.condition1": "When in Off-Hand", "item.create.extendo_grip.tooltip.behaviour1": "Increases _reach distance_ of items used in the _Main-Hand_.", - "item.create.extendo_grip.tooltip.condition2": "While wearing Copper Backtank", + "item.create.extendo_grip.tooltip.condition2": "While wearing Backtank", "item.create.extendo_grip.tooltip.behaviour2": "_No_ _Durability_ will be used. Instead, _Air_ _pressure_ is drained from the Tank", "item.create.potato_cannon.tooltip": "POTATO CANNON", - "item.create.potato_cannon.tooltip.summary": "Fwoomp! Launch your home-grown vegetables at your Enemies. Can be powered with Air Pressure from a _Copper_ _Backtank_", + "item.create.potato_cannon.tooltip.summary": "Launches your home-grown vegetables at Enemies. Can be powered with _Air_ _Pressure_ from a _Backtank_", "item.create.potato_cannon.tooltip.condition1": "When R-Clicked", "item.create.potato_cannon.tooltip.behaviour1": "_Shoots_ a suitable item from your _Inventory_.", - "item.create.potato_cannon.tooltip.condition2": "While wearing Copper Backtank", + "item.create.potato_cannon.tooltip.condition2": "While wearing Backtank", "item.create.potato_cannon.tooltip.behaviour2": "_No_ _Durability_ will be used. Instead, _Air_ _pressure_ is drained from the Tank", - "item.create.filter.tooltip": "FILTER", - "item.create.filter.tooltip.summary": "_Controls outputs_ and _inputs_ of logistical devices with more _precision_, matching them against a _set of items_ or several _nested filters_.", - "item.create.filter.tooltip.condition1": "When in filter slot", - "item.create.filter.tooltip.behaviour1": "_Controls_ item flow according to its _configuration_.", - "item.create.filter.tooltip.condition2": "When R-Clicked", - "item.create.filter.tooltip.behaviour2": "Opens the _configuration interface_.", + "item.create.filter.tooltip": "LIST FILTER", + "item.create.filter.tooltip.summary": "_Matches items_ against a collection of _items_ or _other filters_. Can be used in _Filter Slots_ of Create's Components", + "item.create.filter.tooltip.condition1": "When R-Clicked", + "item.create.filter.tooltip.behaviour1": "Opens the _configuration interface_.", "item.create.attribute_filter.tooltip": "ATTRIBUTE FILTER", - "item.create.attribute_filter.tooltip.summary": "_Controls outputs_ and _inputs_ of logistical devices with more _precision_, matching them against a _set of_ item _attributes_ and _categories_.", - "item.create.attribute_filter.tooltip.condition1": "When in filter slot", - "item.create.attribute_filter.tooltip.behaviour1": "_Controls_ item flow according to its _configuration_.", - "item.create.attribute_filter.tooltip.condition2": "When R-Clicked", - "item.create.attribute_filter.tooltip.behaviour2": "Opens the _configuration interface_.", + "item.create.attribute_filter.tooltip.summary": "_Matches items_ against a set of _attributes_ or _categories_. Can be used in _Filter Slots_ of Create's Components", + "item.create.attribute_filter.tooltip.condition1": "When R-Clicked", + "item.create.attribute_filter.tooltip.behaviour1": "Opens the _configuration interface_.", "item.create.empty_schematic.tooltip": "EMPTY SCHEMATIC", "item.create.empty_schematic.tooltip.summary": "Used as a recipe ingredient and for writing at the _Schematic Table_.", @@ -1892,21 +1996,15 @@ "item.create.schematic.tooltip.summary": "Holds a structure to be positioned and placed into the world. Position the Hologram as desired and use a _Schematicannon_ to build it.", "item.create.schematic.tooltip.condition1": "When Held", "item.create.schematic.tooltip.behaviour1": "Can be positioned using the Tools on Screen.", - "item.create.schematic.tooltip.control1": "R-Click while Sneaking", - "item.create.schematic.tooltip.action1": "Opens an _Interface_ for entering exact _Coordinates_.", + "item.create.schematic.tooltip.condition2": "R-Click while Sneaking", + "item.create.schematic.tooltip.behaviour2": "Opens an _Interface_ for entering exact _Coordinates_.", "item.create.schematic_and_quill.tooltip": "SCHEMATIC AND QUILL", - "item.create.schematic_and_quill.tooltip.summary": "Used for saving a Structure in your world to a .nbt file.", - "item.create.schematic_and_quill.tooltip.condition1": "Step 1", - "item.create.schematic_and_quill.tooltip.behaviour1": "Select two corner points using R-Click.", - "item.create.schematic_and_quill.tooltip.condition2": "Step 2", - "item.create.schematic_and_quill.tooltip.behaviour2": "_Ctrl-Scroll_ on the faces to adjust the size. R-Click again to Save.", - "item.create.schematic_and_quill.tooltip.control1": "R-Click", - "item.create.schematic_and_quill.tooltip.action1": "Select a corner point / confirm save.", - "item.create.schematic_and_quill.tooltip.control2": "Ctrl Held", - "item.create.schematic_and_quill.tooltip.action2": "Select points in _mid-air_. _Scroll_ to adjust the distance.", - "item.create.schematic_and_quill.tooltip.control3": "R-Click while Sneaking", - "item.create.schematic_and_quill.tooltip.action3": "_Resets_ and removes the selection.", + "item.create.schematic_and_quill.tooltip.summary": "Used for _saving a Structure_ in your world to a _.nbt file_.", + "item.create.schematic_and_quill.tooltip.condition1": "Creating a selection", + "item.create.schematic_and_quill.tooltip.behaviour1": "Select two _corner points_ using _R-Click_. Hold _Ctrl_ and Scroll to select locations mid-air.", + "item.create.schematic_and_quill.tooltip.condition2": "Adjusting and Saving", + "item.create.schematic_and_quill.tooltip.behaviour2": "_Ctrl-Scroll_ on the faces to adjust the size, then R-Click again to Save.", "block.create.schematicannon.tooltip": "SCHEMATICANNON", "block.create.schematicannon.tooltip.summary": "Shoots blocks to recreate a deployed _Schematic_ in the World. Uses items from adjacent Inventories and _Gunpowder_ as fuel.", @@ -1919,20 +2017,16 @@ "block.create.schematic_table.tooltip.behaviour1": "Uploads a chosen File from your Schematics Folder.", "item.create.goggles.tooltip": "GOGGLES", - "item.create.goggles.tooltip.summary": "A pair of glasses to augment your vision with useful _kinetic information_.", - "item.create.goggles.tooltip.condition1": "When worn", - "item.create.goggles.tooltip.behaviour1": "Shows _colored indicators_ corresponding to the _Speed Level_ of a placed kinetic component as well as _Stress Impact_ and _Capacity_ of individual components.", - "item.create.goggles.tooltip.condition2": "When looking at gauge", - "item.create.goggles.tooltip.behaviour2": "Shows detailed information about _Speed_ or _Stress_ of the network to which the gauge is connected.", - "item.create.goggles.tooltip.condition3": "When looking at fluid containers", - "item.create.goggles.tooltip.behaviour3": "Shows detailed information about the _Capacity_ of the block and any _Fluids_ stored within.", + "item.create.goggles.tooltip.summary": "Augments your HUD with _miscellaneous information_ about placed components.", + "item.create.goggles.tooltip.condition1": "When looking at blocks", + "item.create.goggles.tooltip.behaviour1": "_Kinetic components_ show added _Stress Impact_ or _Capacity_. _Stressometers_ show statistics of their _attached kinetic network_. Some other blocks reveal information such as item and fluid content.", "item.create.wrench.tooltip": "WRENCH", - "item.create.wrench.tooltip.summary": "A useful tool for working on kinetic contraptions. Can be used to _Rotate_, _Dismantle_ and to _Configure_ components.", - "item.create.wrench.tooltip.control1": "Right-Click a kinetic block", - "item.create.wrench.tooltip.action1": "_Rotates components_ toward or away from the face with which you interacted.", - "item.create.wrench.tooltip.control2": "R-Click while Sneaking", - "item.create.wrench.tooltip.action2": "_Disassembles Kinetic components_ and places them back in _your inventory_.", + "item.create.wrench.tooltip.summary": "Multi-purpose tool for working with your kinetic contraptions.", + "item.create.wrench.tooltip.condition1": "When used on Blocks", + "item.create.wrench.tooltip.behaviour1": "_Rotates components_ around the clicked face. _Sneak_ while interacting to _dismantle_ components.", + "item.create.wrench.tooltip.condition2": "When used on Contraptions", + "item.create.wrench.tooltip.behaviour2": "_Relocates_ assembled minecart- and train-based contraptions.", "block.create.nozzle.tooltip": "NOZZLE", "block.create.nozzle.tooltip.summary": "Attach to the front of an _Encased Fan_ to distribute its effect on Entities in _all directions_.", @@ -1943,7 +2037,7 @@ "block.create.cuckoo_clock.tooltip.behaviour1": "Shows the _current time_ and plays a tune twice a day. _Activates_ once at _noon_ and at dusk, as soon as _players can sleep_.", "block.create.turntable.tooltip": "TURNTABLE", - "block.create.turntable.tooltip.summary": "Turns _Rotational Force_ into refined Motion Sickness.", + "block.create.turntable.tooltip.summary": "Uses _Rotational Force_ to create Motion Sickness.", "block.create.toolbox.tooltip": "TOOLBOX", "block.create.toolbox.tooltip.summary": "Every Inventors' dearest Companion. Conveniently _holds_ a large amount of _8 Different_ item types.", @@ -1954,51 +2048,29 @@ "block.create.toolbox.tooltip.condition3": "When R-Clicked", "block.create.toolbox.tooltip.behaviour3": "Opens the _Container Interface_.", - "block.create.stockpile_switch.tooltip": "STOCKPILE SWITCH", - "block.create.stockpile_switch.tooltip.summary": "Toggles a Redstone signal based on the amount of _Stored Items_ or _Fluids_ in the attached Container. Comes with a handy filter. As opposed to a _Comparator,_ the _Stockpile Switch_ allows configuration of _thresholds,_ at which signals are inverted.", - "block.create.stockpile_switch.tooltip.condition1": "When R-Clicked", - "block.create.stockpile_switch.tooltip.behaviour1": "Opens the _Configuration Interface_.", - - "block.create.content_observer.tooltip": "CONTENT OBSERVER", - "block.create.content_observer.tooltip.summary": "_Detects Items_ or _Fluids_ inside _containers_, _pipes_ or _conveyors_ matching a configured _filter_.", - "block.create.content_observer.tooltip.condition1": "When observing a Container", - "block.create.content_observer.tooltip.behaviour1": "Emits a _Redstone Signal_ while the observed container has _matching_ _content_.", - "block.create.content_observer.tooltip.condition2": "When observing a Funnel", - "block.create.content_observer.tooltip.behaviour2": "Emits a _Redstone Pulse_ when a _matching_ Item is _transferred_.", - "block.create.creative_crate.tooltip": "CREATIVE CRATE", - "block.create.creative_crate.tooltip.summary": "This _Storage Container_ allows infinite replication of any item. Place next to a _Schematicannon_ to remove any material requirements.", + "block.create.creative_crate.tooltip.summary": "This _Storage Container_ allows infinite replication of items.", "block.create.creative_crate.tooltip.condition1": "When Item in Filter Slot", "block.create.creative_crate.tooltip.behaviour1": "Anything _extracting_ from this container will provide an _endless supply_ of the item specified. Items _inserted_ into this crate will be _voided._", + "block.create.creative_crate.tooltip.condition2": "When next to Schematicannon", + "block.create.creative_crate.tooltip.behaviour2": "Provides any material required by the Schematic.", - "item.create.creative_blaze_cake.tooltip": "CREATIVE CAKE", + "item.create.creative_blaze_cake.tooltip": "CREATIVE BLAZE CAKE", "item.create.creative_blaze_cake.tooltip.summary": "A very special treat for your _Blaze Burners_. After eating this cake, Blaze Burners will _never run out of fuel_.", "item.create.creative_blaze_cake.tooltip.condition1": "When Used", "item.create.creative_blaze_cake.tooltip.behaviour1": "_Cycles_ a Blaze Burner's heat level.", "block.create.controller_rail.tooltip": "CONTROLLER RAIL", - "block.create.controller_rail.tooltip.summary": "A _uni-directional powered rail_ capable of _fine control_ over a minecarts' _movement speed_.", - "block.create.controller_rail.tooltip.condition1": "When Powered by Redstone", - "block.create.controller_rail.tooltip.behaviour1": "_Accelerates_ or _Decelerates_ passing _minecarts_ corresponding to the _signal strength_. Propagates redstone power to adjacent controller rails. Powering two controller rails with different strengths will cause tracks between them to interpolate their signal.", + "block.create.controller_rail.tooltip.summary": "A _uni-directional_ powered rail with _variable speed_, controlled by the _signal strength_ supplied to it.", "item.create.sand_paper.tooltip": "SAND PAPER", - "item.create.sand_paper.tooltip.summary": "A rough paper that can be used to _polish materials_. Can be automatically applied using the Deployer.", + "item.create.sand_paper.tooltip.summary": "Can be used to _refine materials_. The process can be automated with a Deployer.", "item.create.sand_paper.tooltip.condition1": "When Used", "item.create.sand_paper.tooltip.behaviour1": "Applies polish to items held in the _offhand_ or lying on the _floor_ when _looking at them_", "item.create.builders_tea.tooltip": "BUILDERS TEA", "item.create.builders_tea.tooltip.summary": "The perfect drink to get the day started- _Motivating_ and _Saturating._", - "item.create.refined_radiance.tooltip": "REFINED RADIANCE", - "item.create.refined_radiance.tooltip.summary": "A Chromatic material forged from _absorbed light_.", - "item.create.refined_radiance.tooltip.condition1": "Work In Progress", - "item.create.refined_radiance.tooltip.behaviour1": "Usages for this material will be available in a future release.", - - "item.create.shadow_steel.tooltip": "SHADOW STEEL", - "item.create.shadow_steel.tooltip.summary": "A Chromatic material forged _in the void_.", - "item.create.shadow_steel.tooltip.condition1": "Work In Progress", - "item.create.shadow_steel.tooltip.behaviour1": "Usages for this material will be available in a future release.", - "item.create.linked_controller.tooltip": "LINKED CONTROLLER", "item.create.linked_controller.tooltip.summary": "Grants _handheld_ _control_ over _Redstone Link_ frequencies assigned to its _six_ _buttons_.", "item.create.linked_controller.tooltip.condition1": "R-Click", @@ -2010,10 +2082,15 @@ "item.create.linked_controller.tooltip.condition4": "R-Click on Lectern", "item.create.linked_controller.tooltip.behaviour4": "Places the Controller into the Lectern for easy activation. (R-Click while Sneaking to retrieve it)", - "item.create.diving_helmet.tooltip": "DIVING HELMET", - "item.create.diving_helmet.tooltip.summary": "Together with a _Copper_ _Backtank_, allows the wielder to _breathe_ _underwater_ for an extended amount of time.", - "item.create.diving_helmet.tooltip.condition1": "When Worn", - "item.create.diving_helmet.tooltip.behaviour1": "Provides the _Water Breathing_ effect, slowly draining _Air Pressure_ from the Backtank.", + "item.create.copper_diving_helmet.tooltip": "COPPER DIVING HELMET", + "item.create.copper_diving_helmet.tooltip.summary": "Together with a _Backtank_, allows the wielder to _breathe_ _underwater_ for an extended amount of time.", + "item.create.copper_diving_helmet.tooltip.condition1": "When Worn", + "item.create.copper_diving_helmet.tooltip.behaviour1": "Provides the _Water Breathing_ effect, slowly draining _Air Pressure_ from the Backtank.", + + "item.create.netherite_diving_helmet.tooltip": "NETHERITE DIVING HELMET", + "item.create.netherite_diving_helmet.tooltip.summary": "Together with a _Netherite Backtank_, this can protect you from _extreme heat_. To be effective, _Legs and Feet_ have to be covered in _Netherite_, too.", + "item.create.netherite_diving_helmet.tooltip.condition1": "When Worn (Full set)", + "item.create.netherite_diving_helmet.tooltip.behaviour1": "Provides immunity to _Fire_ and _Lava_, slowly draining _Air Pressure_ from the Backtank. Also grants _improved vision_ in Lava", "item.create.copper_backtank.tooltip": "COPPER BACKTANK", "item.create.copper_backtank.tooltip.summary": "A _Wearable_ _Tank_ for carrying Pressurized Air.", @@ -2022,6 +2099,13 @@ "item.create.copper_backtank.tooltip.condition2": "When placed, Powered by Kinetics", "item.create.copper_backtank.tooltip.behaviour2": "_Collects_ _Pressurized_ _Air_ at a rate depending on the Rotational Speed.", + "item.create.netherite_backtank.tooltip": "NETHERITE BACKTANK", + "item.create.netherite_backtank.tooltip.summary": "A _Wearable_ _Tank_ for carrying Pressurized Air.", + "item.create.netherite_backtank.tooltip.condition1": "When Worn", + "item.create.netherite_backtank.tooltip.behaviour1": "Provides _Pressurized_ _Air_ to Equipment that requires it.", + "item.create.netherite_backtank.tooltip.condition2": "When placed, Powered by Kinetics", + "item.create.netherite_backtank.tooltip.behaviour2": "_Collects_ _Pressurized_ _Air_ at a rate depending on the Rotational Speed.", + "block.create.placard.tooltip": "PLACARD", "block.create.placard.tooltip.summary": "_Frame_ your _items_ in brass using this fancy wall panel. Safe for contraptions!", "block.create.placard.tooltip.condition1": "When R-Clicked with Item", @@ -2034,10 +2118,15 @@ "block.create.flywheel.tooltip.condition1": "When Powered by Kinetics", "block.create.flywheel.tooltip.behaviour1": "Starts spinning.", - "item.create.diving_boots.tooltip": "DIVING BOOTS", - "item.create.diving_boots.tooltip.summary": "A pair of _heavy_ _boots_, allowing for better traversal of the Ocean floor.", - "item.create.diving_boots.tooltip.condition1": "When Worn", - "item.create.diving_boots.tooltip.behaviour1": "Wielder _sinks_ _faster_ and _cannot_ _swim_. Grants the ability to _walk_ and _jump_ underwater. Wielder also is no longer affected by _Mechanical_ _Belts_.", + "item.create.copper_diving_boots.tooltip": "COPPER DIVING BOOTS", + "item.create.copper_diving_boots.tooltip.summary": "A pair of _heavy_ _boots_, allowing for better traversal of the Ocean floor.", + "item.create.copper_diving_boots.tooltip.condition1": "When Worn", + "item.create.copper_diving_boots.tooltip.behaviour1": "Wielder _descends_ more _quickly_ in liquids. Grants the ability to _walk_ and _jump_ underwater. Wielder also is no longer affected by _Mechanical_ _Belts_.", + + "item.create.netherite_diving_boots.tooltip": "NETHERITE DIVING BOOTS", + "item.create.netherite_diving_boots.tooltip.summary": "A pair of _heavy_ _boots_, allowing for better traversal of the Ocean floor, including Oceans made of Lava.", + "item.create.netherite_diving_boots.tooltip.condition1": "When Worn", + "item.create.netherite_diving_boots.tooltip.behaviour1": "Wielder _descends_ more _quickly_ in liquids. Grants the ability to _walk_ and _jump_ underwater. Wielder also is no longer affected by _Mechanical_ _Belts_.", "item.create.crafting_blueprint.tooltip": "CRAFTING BLUEPRINT", "item.create.crafting_blueprint.tooltip.summary": "_Placed_ on a wall, it can be used to _specify_ _ingredient_ _arrangements_ for easier manual crafting. Each slot represents a Recipe.", @@ -2047,23 +2136,38 @@ "item.create.crafting_blueprint.behaviour2": "_Applies_ the _configured_ _recipe_ with matching Ingredients found in your _Inventory_. _Sneak_ to craft up to a _Stack_ of items.", "item.create.minecart_coupling.tooltip": "MINECART COUPLING", - "item.create.minecart_coupling.tooltip.summary": "_Chains_ all your _Minecarts_ or _Carriage Contraptions_ together to form a majestic Train.", - "item.create.minecart_coupling.tooltip.condition1": "When Used on Minecart", - "item.create.minecart_coupling.tooltip.behaviour1": "_Couples_ two Minecarts together, attempting to keep them at a _constant distance_ while moving.", + "item.create.minecart_coupling.tooltip.summary": "_Chains_ together individual _Minecarts_, causing them to move as a group.", "item.create.experience_nugget.tooltip": "NUGGET OF EXPERIENCE", - "item.create.experience_nugget.tooltip.summary": "_Ding!_ A speck of _inspiration_ from your fantastic inventions.", + "item.create.experience_nugget.tooltip.summary": "A speck of _inspiration_ from your fantastic inventions.", "item.create.experience_nugget.tooltip.condition1": "When Used", "item.create.experience_nugget.tooltip.behaviour1": "_Redeems_ _Experience_ points contained within.", "block.create.peculiar_bell.tooltip": "PECULIAR BELL", - "block.create.peculiar_bell.tooltip.summary": "A decorative _Brass Bell_. Placing it right above open _Soul Fire_ may cause side-effects...", + "block.create.peculiar_bell.tooltip.summary": "A decorative _Brass Bell_. Placing it right above open _Soul Fire_ may have side-effects...", "block.create.haunted_bell.tooltip": "HAUNTED BELL", "block.create.haunted_bell.tooltip.summary": "A _Cursed Bell_ haunted by lost souls of the Nether.", "block.create.haunted_bell.tooltip.condition1": "When Held or Rang", "block.create.haunted_bell.tooltip.behaviour1": "Highlights nearby _Lightless Spots_ on which _Hostile Mobs_ can spawn.", + "block.create.copycat_panel.tooltip": "COPYCAT PANEL", + "block.create.copycat_panel.tooltip.summary": "_Converts_ any _full block_ into a decorative panel. Also accepts _Bars_ and _Trapdoors_.", + "block.create.copycat_panel.tooltip.condition1": "When R-Clicked", + "block.create.copycat_panel.tooltip.behaviour1": "Applies _held item_ as its _material_ if possible. _Click again_ to cycle _orientation_ or _powered_ state. Use a _Wrench_ to _reset_ the material.", + + "block.create.copycat_step.tooltip": "COPYCAT STEP", + "block.create.copycat_step.tooltip.summary": "_Converts_ any _full block_ into a decorative step.", + "block.create.copycat_step.tooltip.condition1": "When R-Clicked", + "block.create.copycat_step.tooltip.behaviour1": "Applies _held item_ as its _material_ if possible. _Click again_ to cycle _orientation_ or _powered_ state. Use a _Wrench_ to _reset_ the material.", + + "block.create.clipboard.tooltip": "CLIPBOARD", + "block.create.clipboard.tooltip.summary": "_Keeps your notes_ and makes you look more professional.", + "block.create.clipboard.tooltip.condition1": "When R-Clicked", + "block.create.clipboard.tooltip.behaviour1": "Opens the _Interface_. _Sneak-Click_ to _place_ it on a surface.", + "block.create.clipboard.tooltip.condition2": "When Used on Blocks", + "block.create.clipboard.tooltip.behaviour2": "Some blocks' _settings_, such as filters, can be _copied (R-Click)_ and _applied (L-Click)_ elsewhere.", + "_": "->------------------------] Ponder Content [------------------------<-", @@ -2086,18 +2190,20 @@ "create.ponder.index_description": "Click one of the icons to learn about its associated Items and Blocks", "create.ponder.index_title": "Ponder Index", "create.ponder.shared.rpm16": "16 RPM", - "create.ponder.shared.behaviour_modify_wrench": "This behaviour can be modified using a Wrench", "create.ponder.shared.storage_on_contraption": "Inventories attached to the Contraption will pick up their drops automatically", "create.ponder.shared.sneak_and": "Sneak +", "create.ponder.shared.rpm8": "8 RPM", "create.ponder.shared.ctrl_and": "Ctrl +", "create.ponder.shared.rpm32": "32 RPM", + "create.ponder.shared.behaviour_modify_value_panel": "This behaviour can be modified using the value panel", "create.ponder.shared.rpm16_source": "Source: 16 RPM", - "create.ponder.shared.movement_anchors": "With the help of Super Glue, larger structures can be moved.", + "create.ponder.shared.movement_anchors": "With the help of Super Glue, larger structures can be moved", "create.ponder.tag.redstone": "Logic Components", "create.ponder.tag.redstone.description": "Components which help with redstone engineering", "create.ponder.tag.contraption_assembly": "Block Attachment Utility", "create.ponder.tag.contraption_assembly.description": "Tools and Components used to assemble structures moved as an animated Contraption", + "create.ponder.tag.recently_updated": "Recent Changes", + "create.ponder.tag.recently_updated.description": "Components that have been added or changed significantly in the latest versions of Create", "create.ponder.tag.fluids": "Fluid Manipulators", "create.ponder.tag.fluids.description": "Components which help relaying and making use of Fluids", "create.ponder.tag.decoration": "Aesthetics", @@ -2194,7 +2300,7 @@ "create.ponder.brass_funnel.header": "The Brass Funnel", "create.ponder.brass_funnel.text_1": "Andesite Funnels can only ever extract single items.", "create.ponder.brass_funnel.text_2": "Brass Funnels can extract up to a full stack.", - "create.ponder.brass_funnel.text_3": "Scrolling on the filter slot allows for precise control over the extracted stack size.", + "create.ponder.brass_funnel.text_3": "The value panel allows for precise control over the extracted stack size.", "create.ponder.brass_funnel.text_4": "Using items on the filter slot will restrict the funnel to only transfer matching stacks.", "create.ponder.brass_tunnel.header": "Using Brass Tunnels", @@ -2208,7 +2314,7 @@ "create.ponder.brass_tunnel.text_8": "For this, items can also be inserted into the Tunnel block directly", "create.ponder.brass_tunnel_modes.header": "Distribution Modes of the Brass Tunnel", - "create.ponder.brass_tunnel_modes.text_1": "Using a Wrench, the distribution behaviour of Brass Tunnels can be configured", + "create.ponder.brass_tunnel_modes.text_1": "The distribution behaviour of Brass Tunnels can be configured", "create.ponder.brass_tunnel_modes.text_10": "'Synchronize Inputs' is a unique setting for Brass Tunnels", "create.ponder.brass_tunnel_modes.text_11": "Items are only allowed past if every tunnel in the group has one waiting", "create.ponder.brass_tunnel_modes.text_12": "This ensures that all affected belts supply items at the same rate", @@ -2258,7 +2364,8 @@ "create.ponder.chute.header": "Transporting Items downward via Chutes", "create.ponder.chute.text_1": "Chutes can transport items vertically from and to inventories", "create.ponder.chute.text_2": "Using the Wrench, a window can be created", - "create.ponder.chute.text_3": "Placing chutes targeting the side faces of another will make it diagonal", + "create.ponder.chute.text_3": "Using Industrial Iron Blocks, chutes can be encased", + "create.ponder.chute.text_4": "Placing chutes targeting the side faces of another will make it diagonal", "create.ponder.chute_upward.header": "Transporting Items upward via Chutes", "create.ponder.chute_upward.text_1": "Using Encased Fans at the top or bottom, a Chute can move items upward", @@ -2293,6 +2400,14 @@ "create.ponder.cogwheel_casing.text_2": "Components added after encasing will not connect to the shaft outputs", "create.ponder.cogwheel_casing.text_3": "The Wrench can be used to toggle connections", + "create.ponder.contraption_controls.header": "Using Contraption Controls", + "create.ponder.contraption_controls.text_1": "Actors on moving contraptions are always active by default", + "create.ponder.contraption_controls.text_2": "Contraption Controls can be used to toggle them on the fly", + "create.ponder.contraption_controls.text_3": "They can be attached anywhere on the contraption", + "create.ponder.contraption_controls.text_4": "While disassembled, the filter can be changed to target specific types of actors", + "create.ponder.contraption_controls.text_5": "If it is redstone-activated during assembly...", + "create.ponder.contraption_controls.text_6": "...targeted actors will be turned off from the start", + "create.ponder.creative_fluid_tank.header": "Creative Fluid Tanks", "create.ponder.creative_fluid_tank.text_1": "Creative Fluid Tanks can be used to provide a bottomless supply of fluid", "create.ponder.creative_fluid_tank.text_2": "Right-Click with a fluid containing item to configure it", @@ -2301,7 +2416,7 @@ "create.ponder.creative_motor.header": "Generating Rotational Force using Creative Motors", "create.ponder.creative_motor.text_1": "Creative motors are a compact and configurable source of Rotational Force", - "create.ponder.creative_motor.text_2": "Scrolling on the back panel changes the RPM of the motors' rotational output", + "create.ponder.creative_motor.text_2": "The generated speed can be configured on its input panels", "create.ponder.creative_motor_mojang.header": "Mojang's Enigma", @@ -2357,8 +2472,8 @@ "create.ponder.display_board.header": "Using Display Boards", "create.ponder.display_board.text_1": "Display Boards are a scalable alternative to the sign", "create.ponder.display_board.text_2": "They require Rotational Force to operate", - "create.ponder.display_board.text_3": "Text can be displayed using Name Tags...", - "create.ponder.display_board.text_4": "...or through the use of Display Links", + "create.ponder.display_board.text_3": "Static text can be applied using written Clipboards", + "create.ponder.display_board.text_4": "And dynamic text through the use of Display Links", "create.ponder.display_board.text_5": "Dyes can be applied to individual lines of the board", "create.ponder.display_board.text_6": "Lines can be reset by clicking them with an empty hand", @@ -2377,6 +2492,31 @@ "create.ponder.display_link_redstone.text_2": "Once unpowered, the Timer is reset and new info is sent immediately", "create.ponder.display_link_redstone.text_3": "Signals emitted from the source do not affect the Link", + "create.ponder.elevator_pulley.header": "Using the Elevator Pulley", + "create.ponder.elevator_pulley.text_1": "Elevator Pulleys can move structures vertically between marked locations", + "create.ponder.elevator_pulley.text_10": "Any redstone contact sharing this column will be converted", + "create.ponder.elevator_pulley.text_11": "Supply a redstone pulse to call the elevator to the contact", + "create.ponder.elevator_pulley.text_12": "The movement speed depends on the rotation input on the pulley", + "create.ponder.elevator_pulley.text_13": "Scroll and click on the controls block to choose a floor while on-board", + "create.ponder.elevator_pulley.text_14": "Right-Clicking the assembled pulley will turn the cabin back into blocks", + "create.ponder.elevator_pulley.text_15": "Sliding doors attached to the cabin will open and close automatically", + "create.ponder.elevator_pulley.text_16": "Elevator Contacts emit a signal while the cabin is on their floor", + "create.ponder.elevator_pulley.text_17": "This can be useful to trigger doors or special effects upon arrival", + "create.ponder.elevator_pulley.text_18": "Display Links on any of the contacts can show the current floor of the elevator", + "create.ponder.elevator_pulley.text_2": "Start by constructing a cabin", + "create.ponder.elevator_pulley.text_3": "Place a pair of Redstone Contacts facing each other...", + "create.ponder.elevator_pulley.text_4": "...and glue one of them to your moving structure", + "create.ponder.elevator_pulley.text_5": "Contraption Controls can be attached to make floor selection easier", + "create.ponder.elevator_pulley.text_6": "Ensure that the pulley is supplied with Rotational Power", + "create.ponder.elevator_pulley.text_7": "Right-Clicking the pulley assembles the elevator", + "create.ponder.elevator_pulley.text_8": "The stationary contact now turns into an Elevator Contact", + "create.ponder.elevator_pulley.text_9": "Elevator Contacts represent a 'floor' and can be configured", + + "create.ponder.elevator_pulley_multi_rope.header": "Synchronised Pulley Movement", + "create.ponder.elevator_pulley_multi_rope.text_1": "Whenever a pulley assembles a contraption...", + "create.ponder.elevator_pulley_multi_rope.text_2": "...other pulleys on the same layer will connect to the structure", + "create.ponder.elevator_pulley_multi_rope.text_3": "They do not require to be powered, the effect is purely cosmetic", + "create.ponder.empty_blaze_burner.header": "Using Empty Blaze Burners", "create.ponder.empty_blaze_burner.text_1": "Right-click a Blaze with the empty burner to capture it", "create.ponder.empty_blaze_burner.text_2": "Alternatively, Blazes can be collected from their Spawners directly", @@ -2387,7 +2527,7 @@ "create.ponder.encased_fluid_pipe.header": "Encasing Fluid Pipes", "create.ponder.encased_fluid_pipe.text_1": "Copper Casing can be used to decorate Fluid Pipes", - "create.ponder.encased_fluid_pipe.text_2": "Aside from being conceiled, Encased Pipes are locked into their connectivity state", + "create.ponder.encased_fluid_pipe.text_2": "Aside from being concealed, Encased Pipes are locked into their connectivity state", "create.ponder.encased_fluid_pipe.text_3": "It will no longer react to any neighbouring blocks being added or removed", "create.ponder.fan_direction.header": "Air flow of Encased Fans", @@ -2493,8 +2633,7 @@ "create.ponder.hand_crank.header": "Generating Rotational Force using Hand Cranks", "create.ponder.hand_crank.text_1": "Hand Cranks can be used by players to apply rotational force manually", "create.ponder.hand_crank.text_2": "Hold Right-Click to rotate it Counter-Clockwise", - "create.ponder.hand_crank.text_3": "Its conveyed speed is relatively high", - "create.ponder.hand_crank.text_4": "Sneak and Hold Right-Click to rotate it Clockwise", + "create.ponder.hand_crank.text_3": "Sneak and Hold Right-Click to rotate it Clockwise", "create.ponder.hose_pulley.header": "Source Filling and Draining using Hose Pulleys", "create.ponder.hose_pulley.text_1": "Hose Pulleys can be used to fill or drain large bodies of Fluid", @@ -2539,13 +2678,20 @@ "create.ponder.large_cogwheel.text_1": "Large cogwheels can connect to each other at right angles", "create.ponder.large_cogwheel.text_2": "It will help relaying conveyed speed to other axes of rotation", + "create.ponder.large_water_wheel.header": "Generating Rotational Force using Large Water Wheels", + "create.ponder.large_water_wheel.text_1": "Large Water Wheels draw force from adjacent Water Currents", + "create.ponder.large_water_wheel.text_2": "Covering additional sides will not improve its kinetic output further", + "create.ponder.large_water_wheel.text_3": "These rotate only at half the speed of regular water wheels...", + "create.ponder.large_water_wheel.text_4": "...but provide a substantially higher stress capacity", + "create.ponder.large_water_wheel.text_5": "Use wood planks on the wheel to change its appearance", + "create.ponder.linear_chassis_attachment.header": "Attaching blocks using Linear Chassis", "create.ponder.linear_chassis_attachment.text_1": "The open faces of a Linear Chassis can be made Sticky", "create.ponder.linear_chassis_attachment.text_2": "Click again to make the opposite side sticky", "create.ponder.linear_chassis_attachment.text_3": "Sneak and Right-Click with an empty hand to remove the slime", "create.ponder.linear_chassis_attachment.text_4": "Stickied faces of the Linear Chassis will attach a line of blocks in front of it", "create.ponder.linear_chassis_attachment.text_5": "Using a Wrench, a precise Range can be specified for this chassis", - "create.ponder.linear_chassis_attachment.text_6": "Holding CTRL and scrolling adjusts the range of all attached Chassis Blocks", + "create.ponder.linear_chassis_attachment.text_6": "Holding CTRL adjusts the range of all connected Chassis Blocks", "create.ponder.linear_chassis_attachment.text_7": "Attaching blocks to any other side requires the use of Super Glue", "create.ponder.linear_chassis_attachment.text_8": "Using these mechanics, structures of any shape can move as a Contraption", @@ -2557,7 +2703,7 @@ "create.ponder.mechanical_arm.header": "Setting up Mechanical Arms", "create.ponder.mechanical_arm.text_1": "Mechanical Arms have to be assigned their in- and outputs before they are placed", "create.ponder.mechanical_arm.text_2": "Right-Click inventories while holding the Arm to assign them as Targets", - "create.ponder.mechanical_arm.text_3": "Right-Click again to toggle between Input (Blue) and Output (Orange)", + "create.ponder.mechanical_arm.text_3": "Right-Click again to toggle between Input (Blue) and Output (Yellow)", "create.ponder.mechanical_arm.text_4": "Left-Click components to remove their Selection", "create.ponder.mechanical_arm.text_5": "Once placed, the Mechanical Arm will target the blocks selected previously", "create.ponder.mechanical_arm.text_6": "They can have any amount of in- and outputs within their range", @@ -2577,7 +2723,7 @@ "create.ponder.mechanical_arm_modes.text_2": "Outputs", "create.ponder.mechanical_arm_modes.text_3": "Whenever an Arm has to choose between multiple valid outputs...", "create.ponder.mechanical_arm_modes.text_4": "...it will act according to its setting", - "create.ponder.mechanical_arm_modes.text_5": "Scrolling with a Wrench will allow you to configure it", + "create.ponder.mechanical_arm_modes.text_5": "The value panel will allow you to configure it", "create.ponder.mechanical_arm_modes.text_6": "Round Robin mode simply cycles through all outputs that are available", "create.ponder.mechanical_arm_modes.text_7": "If an output is unable to take more items, it will be skipped", "create.ponder.mechanical_arm_modes.text_8": "Forced Round Robin mode will never skip outputs, and instead wait until they are free", @@ -2659,18 +2805,34 @@ "create.ponder.mechanical_pump_flow.header": "Fluid Transportation using Mechanical Pumps", "create.ponder.mechanical_pump_flow.text_1": "Mechanical Pumps govern the flow of their attached pipe networks", - "create.ponder.mechanical_pump_flow.text_2": "When powered, their arrow indicates the direction of flow", + "create.ponder.mechanical_pump_flow.text_2": "Their arrow indicates the direction of flow", "create.ponder.mechanical_pump_flow.text_3": "The network behind is now pulling fluids...", "create.ponder.mechanical_pump_flow.text_4": "...while the network in front is transferring it outward", - "create.ponder.mechanical_pump_flow.text_5": "Reversing the input rotation reverses the direction of flow", - "create.ponder.mechanical_pump_flow.text_6": "Use a Wrench to reverse the orientation of pumps manually", + "create.ponder.mechanical_pump_flow.text_5": "The pumps direction is unaffected by the input rotation", + "create.ponder.mechanical_pump_flow.text_6": "Instead, a Wrench can be used to reverse the direction", "create.ponder.mechanical_pump_speed.header": "Throughput of Mechanical Pumps", "create.ponder.mechanical_pump_speed.text_1": "Regardless of speed, Mechanical Pumps affect pipes connected up to 16 blocks away", "create.ponder.mechanical_pump_speed.text_2": "Speeding up the input rotation changes the speed of flow propagation...", - "create.ponder.mechanical_pump_speed.text_3": "...aswell as how quickly fluids are transferred", + "create.ponder.mechanical_pump_speed.text_3": "...and the speed at which fluids are transferred", "create.ponder.mechanical_pump_speed.text_4": "Pumps can combine their throughputs within shared pipe networks", - "create.ponder.mechanical_pump_speed.text_5": "Alternating their orientation can help align their flow directions", + "create.ponder.mechanical_pump_speed.text_5": "Ensure that all of them are facing in the same direction", + + "create.ponder.mechanical_roller_fill.header": "Filling terrain with the Roller", + "create.ponder.mechanical_roller_fill.text_1": "While disassembled, rollers can be set to other modes", + "create.ponder.mechanical_roller_fill.text_2": "The 'fill' modes can help to bridge gaps between pavement and terrain", + "create.ponder.mechanical_roller_fill.text_3": "On 'straight fill', they will place simple columns down to the surface", + "create.ponder.mechanical_roller_fill.text_4": "On 'sloped fill', layers placed further down will increase in size", + "create.ponder.mechanical_roller_fill.text_5": "As opposed to 'clear & pave', neither of these modes will cause the rollers to break existing blocks", + + "create.ponder.mechanical_roller_pave.header": "Clearing and Paving with the Roller", + "create.ponder.mechanical_roller_pave.text_1": "Mechanical rollers help to clean up terrain around tracks or paths", + "create.ponder.mechanical_roller_pave.text_2": "In its default mode, without a material set, it will simply clear blocks like a Drill", + "create.ponder.mechanical_roller_pave.text_3": "While disassembled, a suitable paving material can be specified", + "create.ponder.mechanical_roller_pave.text_4": "Materials can be supplied via chests or barrels attached to the structure", + "create.ponder.mechanical_roller_pave.text_5": "In addition to breaking blocks, it will now replace the layer beneath them", + "create.ponder.mechanical_roller_pave.text_6": "Note that any block destroyed by a roller has a chance not to yield drops", + "create.ponder.mechanical_roller_pave.text_7": "Rollers are especially useful on Trains, but can also be used on most other types of moving contraptions", "create.ponder.mechanical_saw_breaker.header": "Cutting Trees with the Mechanical Saw", "create.ponder.mechanical_saw_breaker.text_1": "When given Rotational Force, a Mechanical Saw will cut trees directly in front of it", @@ -2695,8 +2857,8 @@ "create.ponder.millstone.text_5": "The outputs can also be extracted by automation", "create.ponder.nixie_tube.header": "Using Nixie Tubes", - "create.ponder.nixie_tube.text_1": "When powered by Redstone, Nixie Tubes will display the redstone signals' strength", - "create.ponder.nixie_tube.text_2": "Using name tags edited with an anvil, custom text can be displayed", + "create.ponder.nixie_tube.text_1": "When powered by Redstone, Nixie Tubes will display the signal strength", + "create.ponder.nixie_tube.text_2": "Using written Clipboards, custom text can be displayed", "create.ponder.nixie_tube.text_3": "Right-Click with Dye to change their display colour", "create.ponder.piston_pole.header": "Piston Extension Poles", @@ -2714,7 +2876,7 @@ "create.ponder.portable_fluid_interface.text_8": "After no contents have been exchanged for a while, the contraption will continue on its way", "create.ponder.portable_storage_interface.header": "Contraption Storage Exchange", - "create.ponder.portable_storage_interface.text_1": "Inventories on moving contraptions cannot be accessed by players.", + "create.ponder.portable_storage_interface.text_1": "Moving inventories can be tricky to access with automation.", "create.ponder.portable_storage_interface.text_2": "This component can interact with storage without the need to stop the contraption.", "create.ponder.portable_storage_interface.text_3": "Place a second one with a gap of 1 or 2 blocks inbetween", "create.ponder.portable_storage_interface.text_4": "Whenever they pass by each other, they will engage in a connection", @@ -2742,13 +2904,13 @@ "create.ponder.pulse_extender.text_1": "Pulse Extenders can lengthen a signal passing through", "create.ponder.pulse_extender.text_2": "They activate after a short delay...", "create.ponder.pulse_extender.text_3": "...and cool down for the configured duration", - "create.ponder.pulse_extender.text_4": "Using the mouse wheel, the discharge time can be configured", - "create.ponder.pulse_extender.text_5": "The configured duration can range up to 30 minutes", + "create.ponder.pulse_extender.text_4": "Using the value panel, the discharge time can be configured", + "create.ponder.pulse_extender.text_5": "The configured duration can range up to an hour", "create.ponder.pulse_repeater.header": "Controlling signals using Pulse Repeaters", - "create.ponder.pulse_repeater.text_1": "Pulse Repeaters emit a short pulse at a delay", - "create.ponder.pulse_repeater.text_2": "Using the mouse wheel, the charge time can be configured", - "create.ponder.pulse_repeater.text_3": "Configured delays can range up to 30 minutes", + "create.ponder.pulse_repeater.text_1": "Pulse Repeaters emit a short pulse after a delay", + "create.ponder.pulse_repeater.text_2": "Using the value panel, the charge time can be configured", + "create.ponder.pulse_repeater.text_3": "Configured delays can range up to an hour", "create.ponder.radial_chassis.header": "Attaching blocks using Radial Chassis", "create.ponder.radial_chassis.text_1": "Radial Chassis connect to identical Chassis blocks in a row", @@ -2786,6 +2948,11 @@ "create.ponder.rope_pulley_modes.text_1": "Whenever Pulleys stop moving, the moved structure reverts to blocks", "create.ponder.rope_pulley_modes.text_2": "It can be configured never to revert to solid blocks, or only at the location it started at", + "create.ponder.rope_pulley_multi_rope.header": "Synchronised Pulley Movement", + "create.ponder.rope_pulley_multi_rope.text_1": "Whenever a pulley assembles a contraption...", + "create.ponder.rope_pulley_multi_rope.text_2": "...other pulleys on the same layer will connect to the structure", + "create.ponder.rope_pulley_multi_rope.text_3": "They do not require to be powered, the effect is purely cosmetic", + "create.ponder.rose_quartz_lamp.header": "Rose Quartz Lamps", "create.ponder.rose_quartz_lamp.text_1": "Rose Quartz Lamps activate on a Redstone signal", "create.ponder.rose_quartz_lamp.text_2": "They will continue to emit redstone power afterwards", @@ -2796,7 +2963,7 @@ "create.ponder.rotation_speed_controller.header": "Using the Rotational Speed Controller", "create.ponder.rotation_speed_controller.text_1": "Rot. Speed Controllers relay rotation from their axis to a Large Cogwheel above them", - "create.ponder.rotation_speed_controller.text_2": "Using the scroll input on its side, the conveyed speed can be configured", + "create.ponder.rotation_speed_controller.text_2": "Using the value panel on its side, the conveyed speed can be configured", "create.ponder.sail.header": "Assembling Windmills using Sails", "create.ponder.sail.text_1": "Sails are handy blocks to create Windmills with", @@ -2823,10 +2990,18 @@ "create.ponder.smart_chute.header": "Filtering Items using Smart Chutes", "create.ponder.smart_chute.text_1": "Smart Chutes are vertical chutes with additional control", - "create.ponder.smart_chute.text_2": "Items in the filter slot specify what exactly they can extract and transfer", - "create.ponder.smart_chute.text_3": "Use the Mouse Wheel to specify the extracted stack size", + "create.ponder.smart_chute.text_2": "Items in the filter slot specify what to extract or transfer", + "create.ponder.smart_chute.text_3": "Use the value panel to specify the extracted stack size", "create.ponder.smart_chute.text_4": "Redstone power will prevent Smart Chutes from acting.", + "create.ponder.smart_observer.header": "Advanced detection with Smart Observers", + "create.ponder.smart_observer.text_1": "Smart Observers can be used to detect a variety of events", + "create.ponder.smart_observer.text_2": "It can detect items or fluids inside of generic containers", + "create.ponder.smart_observer.text_3": "The filter slot can be used to look for specific contents only", + "create.ponder.smart_observer.text_4": "It also activates when the block itself matches the filter", + "create.ponder.smart_observer.text_5": "Additionally, smart observers can monitor belts, chutes and pipes", + "create.ponder.smart_observer.text_6": "...and will emit a pulse, if an item enters or exits a funnel", + "create.ponder.smart_pipe.header": "Controlling Fluid flow using Smart Pipes", "create.ponder.smart_pipe.text_1": "Smart pipes can help control flows by fluid type", "create.ponder.smart_pipe.text_2": "When placed directly at the source, they can specify the type of fluid to extract", @@ -2834,7 +3009,7 @@ "create.ponder.smart_pipe.text_4": "When placed further down a pipe network, smart pipes will only let matching fluids continue", "create.ponder.speedometer.header": "Monitoring Kinetic information using the Speedometer", - "create.ponder.speedometer.text_1": "The Speedometer displays the current Speed of the attached components", + "create.ponder.speedometer.text_1": "The Speedometer displays the current Speed of attached components", "create.ponder.speedometer.text_2": "When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", "create.ponder.speedometer.text_3": "Comparators can emit analog Restone Signals relative to the Speedometer's measurements", @@ -2894,6 +3069,17 @@ "create.ponder.super_glue.text_5": "Overlapping glue volumes will move together", "create.ponder.super_glue.text_6": "Blocks hanging on others usually do not require glue", + "create.ponder.threshold_switch.header": "Monitoring with the Threshold Switch", + "create.ponder.threshold_switch.text_1": "Threshold Switches monitor the fill level of containers", + "create.ponder.threshold_switch.text_2": "When the inventory content exceeds the upper threshold...", + "create.ponder.threshold_switch.text_3": "...the switch will change its redstone output", + "create.ponder.threshold_switch.text_4": "The signal stays until the lower threshold is reached", + "create.ponder.threshold_switch.text_5": "The redstone output can now be used to control item supply, keeping the buffer filled", + "create.ponder.threshold_switch.text_6": "The specific thresholds can be changed in the UI", + "create.ponder.threshold_switch.text_7": "A filter can help to only count specific contents toward the total", + "create.ponder.threshold_switch.text_8": "Fluid buffers can be monitored in a similar fashion", + "create.ponder.threshold_switch.text_9": "...as well as, curiously, the length of an extended rope pulley", + "create.ponder.track_chunks.header": "Traversing unloaded Chunks", "create.ponder.track_chunks.text_1": "Tracks stay functional outside of loaded chunks", "create.ponder.track_chunks.text_2": "Trains will travel through inactive sections of the world without issue", @@ -2965,7 +3151,7 @@ "create.ponder.train_signal_redstone.header": "Signals & Redstone", "create.ponder.train_signal_redstone.text_1": "Signals can be forced red by a redstone signal", - "create.ponder.train_signal_redstone.text_2": "Reversely, red signals emit a comparator output", + "create.ponder.train_signal_redstone.text_2": "Conversely, red signals emit a comparator output", "create.ponder.train_signal_signaling.header": "Collision Prevention with Signals", "create.ponder.train_signal_signaling.text_1": "Train Signals divide a track into segments", @@ -2978,12 +3164,13 @@ "create.ponder.train_signal_signaling.text_8": "...would not be able to leave the Segment immediately", "create.ponder.train_signal_signaling.text_9": "This helps keeping queued Trains out of a busy Segment", - "create.ponder.valve_handle.header": "Generating Rotational Force using Valve Handles", - "create.ponder.valve_handle.text_1": "Valve Handles can be used by players to apply rotational force manually", - "create.ponder.valve_handle.text_2": "Hold Right-Click to rotate it Counter-Clockwise", - "create.ponder.valve_handle.text_3": "Its conveyed speed is slow and precise", - "create.ponder.valve_handle.text_4": "Sneak and Hold Right-Click to rotate it Clockwise", - "create.ponder.valve_handle.text_5": "Valve handles can be dyed for aesthetic purposes", + "create.ponder.valve_handle.header": "Precise rotation using Valve Handles", + "create.ponder.valve_handle.text_1": "Valve handles can be used to rotate components by a precise angle", + "create.ponder.valve_handle.text_2": "The angle can be configured on the input panel", + "create.ponder.valve_handle.text_3": "Right-Click to activate one rotation", + "create.ponder.valve_handle.text_4": "Sneak-Right-Click to activate it in the opposite direction", + "create.ponder.valve_handle.text_5": "Mind that Bearings have to be specifically told not to disassemble", + "create.ponder.valve_handle.text_6": "Valve handles can be dyed for aesthetic purposes", "create.ponder.valve_pipe.header": "Controlling Fluid flow using Valves", "create.ponder.valve_pipe.text_1": "Valve pipes help control fluids propagating through pipe networks", @@ -2993,14 +3180,13 @@ "create.ponder.water_wheel.header": "Generating Rotational Force using Water Wheels", "create.ponder.water_wheel.text_1": "Water Wheels draw force from adjacent Water Currents", - "create.ponder.water_wheel.text_2": "The more faces are powered, the faster the Water Wheel will rotate", - "create.ponder.water_wheel.text_3": "The Wheels' blades should be oriented against the flow", - "create.ponder.water_wheel.text_4": "Facing the opposite way, they will not be as effective", + "create.ponder.water_wheel.text_2": "Covering additional sides will not improve its kinetic output further", + "create.ponder.water_wheel.text_3": "Use wood planks on the wheel to change its appearance", "create.ponder.weighted_ejector.header": "Using Weighted Ejectors", "create.ponder.weighted_ejector.text_1": "Sneak and Right-Click holding an Ejector to select its target location", "create.ponder.weighted_ejector.text_10": "It is now limited to this stack size, and only activates when its held stack reaches this amount", - "create.ponder.weighted_ejector.text_11": "Other Entities will always trigger an Ejector when stepping on it", + "create.ponder.weighted_ejector.text_11": "Mobs and Players will always trigger an Ejector when stepping on it", "create.ponder.weighted_ejector.text_2": "The placed ejector will now launch objects to the marked location", "create.ponder.weighted_ejector.text_3": "A valid target can be at any height or distance within range", "create.ponder.weighted_ejector.text_4": "They cannot however be off to a side", @@ -3008,11 +3194,11 @@ "create.ponder.weighted_ejector.text_6": "Supply Rotational Force in order to charge it up", "create.ponder.weighted_ejector.text_7": "Items placed on the ejector cause it to trigger", "create.ponder.weighted_ejector.text_8": "If Inventories are targeted, the ejector will wait until there is space", - "create.ponder.weighted_ejector.text_9": "Using the Wrench, a required Stack Size can be configured", + "create.ponder.weighted_ejector.text_9": "Using the value panel, a required Stack Size can be configured", "create.ponder.weighted_ejector_redstone.header": "Controlling Weighted Ejectors with Redstone", "create.ponder.weighted_ejector_redstone.text_1": "When powered by Redstone, Ejectors will not activate", - "create.ponder.weighted_ejector_redstone.text_2": "Furthermore, Observers can detect when Ejectors activate", + "create.ponder.weighted_ejector_redstone.text_2": "Observers can detect when Ejectors activate", "create.ponder.weighted_ejector_tunnel.header": "Splitting item stacks using Weighted Ejectors", "create.ponder.weighted_ejector_tunnel.text_1": "Combined with Brass Tunnels, Ejectors can split item stacks by specific amounts", @@ -3027,7 +3213,7 @@ "create.ponder.windmill_source.text_3": "If enough Sail-like blocks are included, this can act as a Windmill", "create.ponder.windmill_source.text_4": "Activated with Right-Click, the Windmill Bearing will start providing Rotational Force", "create.ponder.windmill_source.text_5": "The Amount of Sail Blocks determine its Rotation Speed", - "create.ponder.windmill_source.text_6": "Use a Wrench to configure its rotation direction", + "create.ponder.windmill_source.text_6": "Use the value panel to configure its rotation direction", "create.ponder.windmill_source.text_7": "Right-click the Bearing anytime to stop and edit the Structure again", "create.ponder.windmill_structure.header": "Windmill Contraptions", diff --git a/src/generated/resources/assets/create/models/block/andesite_alloy_block.json b/src/generated/resources/assets/create/models/block/andesite_alloy_block.json new file mode 100644 index 000000000..10e0cb6b8 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/andesite_alloy_block.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "create:block/andesite_block" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_belt_funnel_extended.json b/src/generated/resources/assets/create/models/block/andesite_belt_funnel_extended.json deleted file mode 100644 index 8e1194a33..000000000 --- a/src/generated/resources/assets/create/models/block/andesite_belt_funnel_extended.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "parent": "create:block/belt_funnel/block_extended", - "textures": { - "2": "create:block/andesite_funnel_neutral", - "2_1": "create:block/andesite_funnel_push", - "2_2": "create:block/andesite_funnel_pull", - "3": "create:block/andesite_funnel_back", - "5": "create:block/andesite_funnel_tall", - "6": "create:block/andesite_funnel", - "7": "create:block/andesite_funnel_plating", - "particle": "minecraft:block/polished_andesite" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_belt_funnel_extended_powered.json b/src/generated/resources/assets/create/models/block/andesite_belt_funnel_extended_powered.json index f330b9e46..3df948eb7 100644 --- a/src/generated/resources/assets/create/models/block/andesite_belt_funnel_extended_powered.json +++ b/src/generated/resources/assets/create/models/block/andesite_belt_funnel_extended_powered.json @@ -1,13 +1,10 @@ { "parent": "create:block/belt_funnel/block_extended", "textures": { - "2": "create:block/andesite_funnel_neutral", - "2_1": "create:block/andesite_funnel_push", - "2_2": "create:block/andesite_funnel_pull", - "3": "create:block/andesite_funnel_back", - "5": "create:block/andesite_funnel_tall_powered", - "6": "create:block/andesite_funnel_powered", - "7": "create:block/andesite_funnel_plating", - "particle": "minecraft:block/polished_andesite" + "base": "create:block/funnel/andesite_funnel", + "block": "create:block/andesite_block", + "direction": "create:block/funnel/andesite_funnel_neutral", + "particle": "create:block/andesite_block", + "redstone": "create:block/funnel/andesite_funnel_powered" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_belt_funnel_extended_unpowered.json b/src/generated/resources/assets/create/models/block/andesite_belt_funnel_extended_unpowered.json new file mode 100644 index 000000000..7ad8d1517 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/andesite_belt_funnel_extended_unpowered.json @@ -0,0 +1,10 @@ +{ + "parent": "create:block/belt_funnel/block_extended", + "textures": { + "base": "create:block/funnel/andesite_funnel", + "block": "create:block/andesite_block", + "direction": "create:block/funnel/andesite_funnel_neutral", + "particle": "create:block/andesite_block", + "redstone": "create:block/funnel/andesite_funnel_unpowered" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_belt_funnel_pulling.json b/src/generated/resources/assets/create/models/block/andesite_belt_funnel_pulling.json deleted file mode 100644 index c29ede474..000000000 --- a/src/generated/resources/assets/create/models/block/andesite_belt_funnel_pulling.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "parent": "create:block/belt_funnel/block_pulling", - "textures": { - "2": "create:block/andesite_funnel_neutral", - "2_1": "create:block/andesite_funnel_push", - "2_2": "create:block/andesite_funnel_pull", - "3": "create:block/andesite_funnel_back", - "5": "create:block/andesite_funnel_tall", - "6": "create:block/andesite_funnel", - "7": "create:block/andesite_funnel_plating", - "particle": "minecraft:block/polished_andesite" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_belt_funnel_pulling_powered.json b/src/generated/resources/assets/create/models/block/andesite_belt_funnel_pulling_powered.json index e00f253a4..f0cacfcde 100644 --- a/src/generated/resources/assets/create/models/block/andesite_belt_funnel_pulling_powered.json +++ b/src/generated/resources/assets/create/models/block/andesite_belt_funnel_pulling_powered.json @@ -1,13 +1,10 @@ { "parent": "create:block/belt_funnel/block_pulling", "textures": { - "2": "create:block/andesite_funnel_neutral", - "2_1": "create:block/andesite_funnel_push", - "2_2": "create:block/andesite_funnel_pull", - "3": "create:block/andesite_funnel_back", - "5": "create:block/andesite_funnel_tall_powered", - "6": "create:block/andesite_funnel_powered", - "7": "create:block/andesite_funnel_plating", - "particle": "minecraft:block/polished_andesite" + "base": "create:block/funnel/andesite_funnel", + "block": "create:block/andesite_block", + "direction": "create:block/funnel/andesite_funnel_pull", + "particle": "create:block/andesite_block", + "redstone": "create:block/funnel/andesite_funnel_powered" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_belt_funnel_pulling_unpowered.json b/src/generated/resources/assets/create/models/block/andesite_belt_funnel_pulling_unpowered.json new file mode 100644 index 000000000..7ac13c274 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/andesite_belt_funnel_pulling_unpowered.json @@ -0,0 +1,10 @@ +{ + "parent": "create:block/belt_funnel/block_pulling", + "textures": { + "base": "create:block/funnel/andesite_funnel", + "block": "create:block/andesite_block", + "direction": "create:block/funnel/andesite_funnel_pull", + "particle": "create:block/andesite_block", + "redstone": "create:block/funnel/andesite_funnel_unpowered" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_belt_funnel_pushing.json b/src/generated/resources/assets/create/models/block/andesite_belt_funnel_pushing.json deleted file mode 100644 index 49c4f3126..000000000 --- a/src/generated/resources/assets/create/models/block/andesite_belt_funnel_pushing.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "parent": "create:block/belt_funnel/block_pushing", - "textures": { - "2": "create:block/andesite_funnel_neutral", - "2_1": "create:block/andesite_funnel_push", - "2_2": "create:block/andesite_funnel_pull", - "3": "create:block/andesite_funnel_back", - "5": "create:block/andesite_funnel_tall", - "6": "create:block/andesite_funnel", - "7": "create:block/andesite_funnel_plating", - "particle": "minecraft:block/polished_andesite" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_belt_funnel_pushing_powered.json b/src/generated/resources/assets/create/models/block/andesite_belt_funnel_pushing_powered.json index 0ad12757f..83732c7b8 100644 --- a/src/generated/resources/assets/create/models/block/andesite_belt_funnel_pushing_powered.json +++ b/src/generated/resources/assets/create/models/block/andesite_belt_funnel_pushing_powered.json @@ -1,13 +1,10 @@ { "parent": "create:block/belt_funnel/block_pushing", "textures": { - "2": "create:block/andesite_funnel_neutral", - "2_1": "create:block/andesite_funnel_push", - "2_2": "create:block/andesite_funnel_pull", - "3": "create:block/andesite_funnel_back", - "5": "create:block/andesite_funnel_tall_powered", - "6": "create:block/andesite_funnel_powered", - "7": "create:block/andesite_funnel_plating", - "particle": "minecraft:block/polished_andesite" + "base": "create:block/funnel/andesite_funnel", + "block": "create:block/andesite_block", + "direction": "create:block/funnel/andesite_funnel_push", + "particle": "create:block/andesite_block", + "redstone": "create:block/funnel/andesite_funnel_powered" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_belt_funnel_pushing_unpowered.json b/src/generated/resources/assets/create/models/block/andesite_belt_funnel_pushing_unpowered.json new file mode 100644 index 000000000..7360e4d61 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/andesite_belt_funnel_pushing_unpowered.json @@ -0,0 +1,10 @@ +{ + "parent": "create:block/belt_funnel/block_pushing", + "textures": { + "base": "create:block/funnel/andesite_funnel", + "block": "create:block/andesite_block", + "direction": "create:block/funnel/andesite_funnel_push", + "particle": "create:block/andesite_block", + "redstone": "create:block/funnel/andesite_funnel_unpowered" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_belt_funnel_retracted.json b/src/generated/resources/assets/create/models/block/andesite_belt_funnel_retracted.json deleted file mode 100644 index 24acc9e2d..000000000 --- a/src/generated/resources/assets/create/models/block/andesite_belt_funnel_retracted.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "parent": "create:block/belt_funnel/block_retracted", - "textures": { - "2": "create:block/andesite_funnel_neutral", - "2_1": "create:block/andesite_funnel_push", - "2_2": "create:block/andesite_funnel_pull", - "3": "create:block/andesite_funnel_back", - "5": "create:block/andesite_funnel_tall", - "6": "create:block/andesite_funnel", - "7": "create:block/andesite_funnel_plating", - "particle": "minecraft:block/polished_andesite" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_belt_funnel_retracted_powered.json b/src/generated/resources/assets/create/models/block/andesite_belt_funnel_retracted_powered.json index 1e8178bb5..291f3db83 100644 --- a/src/generated/resources/assets/create/models/block/andesite_belt_funnel_retracted_powered.json +++ b/src/generated/resources/assets/create/models/block/andesite_belt_funnel_retracted_powered.json @@ -1,13 +1,10 @@ { "parent": "create:block/belt_funnel/block_retracted", "textures": { - "2": "create:block/andesite_funnel_neutral", - "2_1": "create:block/andesite_funnel_push", - "2_2": "create:block/andesite_funnel_pull", - "3": "create:block/andesite_funnel_back", - "5": "create:block/andesite_funnel_tall_powered", - "6": "create:block/andesite_funnel_powered", - "7": "create:block/andesite_funnel_plating", - "particle": "minecraft:block/polished_andesite" + "base": "create:block/funnel/andesite_funnel", + "block": "create:block/andesite_block", + "direction": "create:block/funnel/andesite_funnel_neutral", + "particle": "create:block/andesite_block", + "redstone": "create:block/funnel/andesite_funnel_powered" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_belt_funnel_retracted_unpowered.json b/src/generated/resources/assets/create/models/block/andesite_belt_funnel_retracted_unpowered.json new file mode 100644 index 000000000..5a8874fe1 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/andesite_belt_funnel_retracted_unpowered.json @@ -0,0 +1,10 @@ +{ + "parent": "create:block/belt_funnel/block_retracted", + "textures": { + "base": "create:block/funnel/andesite_funnel", + "block": "create:block/andesite_block", + "direction": "create:block/funnel/andesite_funnel_neutral", + "particle": "create:block/andesite_block", + "redstone": "create:block/funnel/andesite_funnel_unpowered" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_cap.json b/src/generated/resources/assets/create/models/block/andesite_cap.json new file mode 100644 index 000000000..1d3c07a2b --- /dev/null +++ b/src/generated/resources/assets/create/models/block/andesite_cap.json @@ -0,0 +1,8 @@ +{ + "parent": "create:block/bars/cap", + "textures": { + "bars": "create:block/bars/andesite_bars", + "edge": "create:block/bars/andesite_bars_edge", + "particle": "create:block/bars/andesite_bars" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_cap_alt.json b/src/generated/resources/assets/create/models/block/andesite_cap_alt.json new file mode 100644 index 000000000..93b5a8e98 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/andesite_cap_alt.json @@ -0,0 +1,8 @@ +{ + "parent": "create:block/bars/cap_alt", + "textures": { + "bars": "create:block/bars/andesite_bars", + "edge": "create:block/bars/andesite_bars_edge", + "particle": "create:block/bars/andesite_bars" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_encased_cogwheel.json b/src/generated/resources/assets/create/models/block/andesite_encased_cogwheel.json index 89c8c3cd3..e591e2358 100644 --- a/src/generated/resources/assets/create/models/block/andesite_encased_cogwheel.json +++ b/src/generated/resources/assets/create/models/block/andesite_encased_cogwheel.json @@ -2,7 +2,9 @@ "parent": "create:block/encased_cogwheel/block", "textures": { "1": "minecraft:block/stripped_spruce_log_top", + "4": "create:block/gearbox", "casing": "create:block/andesite_casing", + "particle": "create:block/andesite_casing", "side": "create:block/andesite_encased_cogwheel_side" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_encased_cogwheel_bottom.json b/src/generated/resources/assets/create/models/block/andesite_encased_cogwheel_bottom.json index 6b57d336e..a9ddc1431 100644 --- a/src/generated/resources/assets/create/models/block/andesite_encased_cogwheel_bottom.json +++ b/src/generated/resources/assets/create/models/block/andesite_encased_cogwheel_bottom.json @@ -2,7 +2,9 @@ "parent": "create:block/encased_cogwheel/block_bottom", "textures": { "1": "minecraft:block/stripped_spruce_log_top", + "4": "create:block/gearbox", "casing": "create:block/andesite_casing", + "particle": "create:block/andesite_casing", "side": "create:block/andesite_encased_cogwheel_side" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_encased_cogwheel_top.json b/src/generated/resources/assets/create/models/block/andesite_encased_cogwheel_top.json index 83b934fab..d4ceb6d43 100644 --- a/src/generated/resources/assets/create/models/block/andesite_encased_cogwheel_top.json +++ b/src/generated/resources/assets/create/models/block/andesite_encased_cogwheel_top.json @@ -2,7 +2,9 @@ "parent": "create:block/encased_cogwheel/block_top", "textures": { "1": "minecraft:block/stripped_spruce_log_top", + "4": "create:block/gearbox", "casing": "create:block/andesite_casing", + "particle": "create:block/andesite_casing", "side": "create:block/andesite_encased_cogwheel_side" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_encased_cogwheel_top_bottom.json b/src/generated/resources/assets/create/models/block/andesite_encased_cogwheel_top_bottom.json index a0a6dc4d4..9787fa099 100644 --- a/src/generated/resources/assets/create/models/block/andesite_encased_cogwheel_top_bottom.json +++ b/src/generated/resources/assets/create/models/block/andesite_encased_cogwheel_top_bottom.json @@ -2,7 +2,9 @@ "parent": "create:block/encased_cogwheel/block_top_bottom", "textures": { "1": "minecraft:block/stripped_spruce_log_top", + "4": "create:block/gearbox", "casing": "create:block/andesite_casing", + "particle": "create:block/andesite_casing", "side": "create:block/andesite_encased_cogwheel_side" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_encased_large_cogwheel.json b/src/generated/resources/assets/create/models/block/andesite_encased_large_cogwheel.json index 7da833e3d..c606564c6 100644 --- a/src/generated/resources/assets/create/models/block/andesite_encased_large_cogwheel.json +++ b/src/generated/resources/assets/create/models/block/andesite_encased_large_cogwheel.json @@ -2,7 +2,9 @@ "parent": "create:block/encased_large_cogwheel/block", "textures": { "1": "minecraft:block/stripped_spruce_log_top", + "4": "create:block/gearbox", "casing": "create:block/andesite_casing", + "particle": "create:block/andesite_casing", "side": "create:block/andesite_encased_cogwheel_side_connected" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_encased_large_cogwheel_bottom.json b/src/generated/resources/assets/create/models/block/andesite_encased_large_cogwheel_bottom.json index f3e6810f1..192673126 100644 --- a/src/generated/resources/assets/create/models/block/andesite_encased_large_cogwheel_bottom.json +++ b/src/generated/resources/assets/create/models/block/andesite_encased_large_cogwheel_bottom.json @@ -2,7 +2,9 @@ "parent": "create:block/encased_large_cogwheel/block_bottom", "textures": { "1": "minecraft:block/stripped_spruce_log_top", + "4": "create:block/gearbox", "casing": "create:block/andesite_casing", + "particle": "create:block/andesite_casing", "side": "create:block/andesite_encased_cogwheel_side_connected" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_encased_large_cogwheel_top.json b/src/generated/resources/assets/create/models/block/andesite_encased_large_cogwheel_top.json index c898d5c4f..cb2f508d1 100644 --- a/src/generated/resources/assets/create/models/block/andesite_encased_large_cogwheel_top.json +++ b/src/generated/resources/assets/create/models/block/andesite_encased_large_cogwheel_top.json @@ -2,7 +2,9 @@ "parent": "create:block/encased_large_cogwheel/block_top", "textures": { "1": "minecraft:block/stripped_spruce_log_top", + "4": "create:block/gearbox", "casing": "create:block/andesite_casing", + "particle": "create:block/andesite_casing", "side": "create:block/andesite_encased_cogwheel_side_connected" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_encased_large_cogwheel_top_bottom.json b/src/generated/resources/assets/create/models/block/andesite_encased_large_cogwheel_top_bottom.json index 5e34071df..60d8a326e 100644 --- a/src/generated/resources/assets/create/models/block/andesite_encased_large_cogwheel_top_bottom.json +++ b/src/generated/resources/assets/create/models/block/andesite_encased_large_cogwheel_top_bottom.json @@ -2,7 +2,9 @@ "parent": "create:block/encased_large_cogwheel/block_top_bottom", "textures": { "1": "minecraft:block/stripped_spruce_log_top", + "4": "create:block/gearbox", "casing": "create:block/andesite_casing", + "particle": "create:block/andesite_casing", "side": "create:block/andesite_encased_cogwheel_side_connected" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_funnel_horizontal_pull.json b/src/generated/resources/assets/create/models/block/andesite_funnel_horizontal_pull.json deleted file mode 100644 index e4f91baef..000000000 --- a/src/generated/resources/assets/create/models/block/andesite_funnel_horizontal_pull.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "parent": "create:block/funnel/block_horizontal", - "textures": { - "2_2": "create:block/andesite_funnel_pull", - "3": "create:block/andesite_funnel_back", - "5": "create:block/andesite_funnel_tall", - "6": "create:block/andesite_funnel", - "7": "create:block/andesite_funnel_plating", - "particle": "create:block/andesite_casing" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_funnel_horizontal_pull_powered.json b/src/generated/resources/assets/create/models/block/andesite_funnel_horizontal_pull_powered.json index 7264e418b..d70b44204 100644 --- a/src/generated/resources/assets/create/models/block/andesite_funnel_horizontal_pull_powered.json +++ b/src/generated/resources/assets/create/models/block/andesite_funnel_horizontal_pull_powered.json @@ -1,11 +1,10 @@ { "parent": "create:block/funnel/block_horizontal", "textures": { - "2_2": "create:block/andesite_funnel_pull", - "3": "create:block/andesite_funnel_back", - "5": "create:block/andesite_funnel_tall_powered", - "6": "create:block/andesite_funnel_powered", - "7": "create:block/andesite_funnel_plating", - "particle": "create:block/andesite_casing" + "base": "create:block/funnel/andesite_funnel", + "block": "create:block/andesite_block", + "direction": "create:block/funnel/andesite_funnel_pull", + "particle": "create:block/andesite_block", + "redstone": "create:block/funnel/andesite_funnel_powered" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_funnel_horizontal_pull_unpowered.json b/src/generated/resources/assets/create/models/block/andesite_funnel_horizontal_pull_unpowered.json new file mode 100644 index 000000000..21ed5cbe8 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/andesite_funnel_horizontal_pull_unpowered.json @@ -0,0 +1,10 @@ +{ + "parent": "create:block/funnel/block_horizontal", + "textures": { + "base": "create:block/funnel/andesite_funnel", + "block": "create:block/andesite_block", + "direction": "create:block/funnel/andesite_funnel_pull", + "particle": "create:block/andesite_block", + "redstone": "create:block/funnel/andesite_funnel_unpowered" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_funnel_horizontal_push.json b/src/generated/resources/assets/create/models/block/andesite_funnel_horizontal_push.json deleted file mode 100644 index 2f12908c4..000000000 --- a/src/generated/resources/assets/create/models/block/andesite_funnel_horizontal_push.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "parent": "create:block/funnel/block_horizontal", - "textures": { - "2_2": "create:block/andesite_funnel_push", - "3": "create:block/andesite_funnel_back", - "5": "create:block/andesite_funnel_tall", - "6": "create:block/andesite_funnel", - "7": "create:block/andesite_funnel_plating", - "particle": "create:block/andesite_casing" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_funnel_horizontal_push_powered.json b/src/generated/resources/assets/create/models/block/andesite_funnel_horizontal_push_powered.json index ca6b8ecd7..b5ab9ce7b 100644 --- a/src/generated/resources/assets/create/models/block/andesite_funnel_horizontal_push_powered.json +++ b/src/generated/resources/assets/create/models/block/andesite_funnel_horizontal_push_powered.json @@ -1,11 +1,10 @@ { "parent": "create:block/funnel/block_horizontal", "textures": { - "2_2": "create:block/andesite_funnel_push", - "3": "create:block/andesite_funnel_back", - "5": "create:block/andesite_funnel_tall_powered", - "6": "create:block/andesite_funnel_powered", - "7": "create:block/andesite_funnel_plating", - "particle": "create:block/andesite_casing" + "base": "create:block/funnel/andesite_funnel", + "block": "create:block/andesite_block", + "direction": "create:block/funnel/andesite_funnel_push", + "particle": "create:block/andesite_block", + "redstone": "create:block/funnel/andesite_funnel_powered" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_funnel_horizontal_push_unpowered.json b/src/generated/resources/assets/create/models/block/andesite_funnel_horizontal_push_unpowered.json new file mode 100644 index 000000000..6c4e41756 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/andesite_funnel_horizontal_push_unpowered.json @@ -0,0 +1,10 @@ +{ + "parent": "create:block/funnel/block_horizontal", + "textures": { + "base": "create:block/funnel/andesite_funnel", + "block": "create:block/andesite_block", + "direction": "create:block/funnel/andesite_funnel_push", + "particle": "create:block/andesite_block", + "redstone": "create:block/funnel/andesite_funnel_unpowered" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_funnel_vertical_filterless_pull.json b/src/generated/resources/assets/create/models/block/andesite_funnel_vertical_filterless_pull.json deleted file mode 100644 index f869205d3..000000000 --- a/src/generated/resources/assets/create/models/block/andesite_funnel_vertical_filterless_pull.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "parent": "create:block/funnel/block_vertical_filterless", - "textures": { - "10": "create:block/funnel_open", - "2_2": "create:block/andesite_funnel_pull", - "3": "create:block/andesite_funnel_back", - "5": "create:block/andesite_funnel_tall", - "7": "create:block/andesite_funnel_plating", - "8": "create:block/andesite_casing", - "9": "create:block/andesite_funnel_slope", - "particle": "create:block/andesite_casing" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_funnel_vertical_filterless_pull_powered.json b/src/generated/resources/assets/create/models/block/andesite_funnel_vertical_filterless_pull_powered.json index 385f51a2d..f575627e1 100644 --- a/src/generated/resources/assets/create/models/block/andesite_funnel_vertical_filterless_pull_powered.json +++ b/src/generated/resources/assets/create/models/block/andesite_funnel_vertical_filterless_pull_powered.json @@ -1,13 +1,11 @@ { "parent": "create:block/funnel/block_vertical_filterless", "textures": { - "10": "create:block/funnel_closed", - "2_2": "create:block/andesite_funnel_pull", - "3": "create:block/andesite_funnel_back", - "5": "create:block/andesite_funnel_tall_powered", - "7": "create:block/andesite_funnel_plating", - "8": "create:block/andesite_casing", - "9": "create:block/andesite_funnel_slope", - "particle": "create:block/andesite_casing" + "base": "create:block/funnel/andesite_funnel", + "direction": "create:block/funnel/andesite_funnel_pull", + "frame": "create:block/funnel/andesite_funnel_frame", + "open": "create:block/funnel/funnel_closed", + "particle": "create:block/andesite_block", + "redstone": "create:block/funnel/andesite_funnel_powered" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_funnel_vertical_filterless_pull_unpowered.json b/src/generated/resources/assets/create/models/block/andesite_funnel_vertical_filterless_pull_unpowered.json new file mode 100644 index 000000000..2504297f5 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/andesite_funnel_vertical_filterless_pull_unpowered.json @@ -0,0 +1,11 @@ +{ + "parent": "create:block/funnel/block_vertical_filterless", + "textures": { + "base": "create:block/funnel/andesite_funnel", + "direction": "create:block/funnel/andesite_funnel_pull", + "frame": "create:block/funnel/andesite_funnel_frame", + "open": "create:block/funnel/funnel_open", + "particle": "create:block/andesite_block", + "redstone": "create:block/funnel/andesite_funnel_unpowered" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_funnel_vertical_filterless_push.json b/src/generated/resources/assets/create/models/block/andesite_funnel_vertical_filterless_push.json deleted file mode 100644 index baa4c6f3b..000000000 --- a/src/generated/resources/assets/create/models/block/andesite_funnel_vertical_filterless_push.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "parent": "create:block/funnel/block_vertical_filterless", - "textures": { - "10": "create:block/funnel_open", - "2_2": "create:block/andesite_funnel_push", - "3": "create:block/andesite_funnel_back", - "5": "create:block/andesite_funnel_tall", - "7": "create:block/andesite_funnel_plating", - "8": "create:block/andesite_casing", - "9": "create:block/andesite_funnel_slope", - "particle": "create:block/andesite_casing" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_funnel_vertical_filterless_push_powered.json b/src/generated/resources/assets/create/models/block/andesite_funnel_vertical_filterless_push_powered.json index 87377182c..0e0a7e55a 100644 --- a/src/generated/resources/assets/create/models/block/andesite_funnel_vertical_filterless_push_powered.json +++ b/src/generated/resources/assets/create/models/block/andesite_funnel_vertical_filterless_push_powered.json @@ -1,13 +1,11 @@ { "parent": "create:block/funnel/block_vertical_filterless", "textures": { - "10": "create:block/funnel_closed", - "2_2": "create:block/andesite_funnel_push", - "3": "create:block/andesite_funnel_back", - "5": "create:block/andesite_funnel_tall_powered", - "7": "create:block/andesite_funnel_plating", - "8": "create:block/andesite_casing", - "9": "create:block/andesite_funnel_slope", - "particle": "create:block/andesite_casing" + "base": "create:block/funnel/andesite_funnel", + "direction": "create:block/funnel/andesite_funnel_push", + "frame": "create:block/funnel/andesite_funnel_frame", + "open": "create:block/funnel/funnel_closed", + "particle": "create:block/andesite_block", + "redstone": "create:block/funnel/andesite_funnel_powered" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_funnel_vertical_filterless_push_unpowered.json b/src/generated/resources/assets/create/models/block/andesite_funnel_vertical_filterless_push_unpowered.json new file mode 100644 index 000000000..a01805fe5 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/andesite_funnel_vertical_filterless_push_unpowered.json @@ -0,0 +1,11 @@ +{ + "parent": "create:block/funnel/block_vertical_filterless", + "textures": { + "base": "create:block/funnel/andesite_funnel", + "direction": "create:block/funnel/andesite_funnel_push", + "frame": "create:block/funnel/andesite_funnel_frame", + "open": "create:block/funnel/funnel_open", + "particle": "create:block/andesite_block", + "redstone": "create:block/funnel/andesite_funnel_unpowered" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_post.json b/src/generated/resources/assets/create/models/block/andesite_post.json new file mode 100644 index 000000000..c388f4f42 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/andesite_post.json @@ -0,0 +1,8 @@ +{ + "parent": "create:block/bars/post", + "textures": { + "bars": "create:block/bars/andesite_bars", + "edge": "create:block/bars/andesite_bars_edge", + "particle": "create:block/bars/andesite_bars" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_post_ends.json b/src/generated/resources/assets/create/models/block/andesite_post_ends.json new file mode 100644 index 000000000..ee5dd4c2b --- /dev/null +++ b/src/generated/resources/assets/create/models/block/andesite_post_ends.json @@ -0,0 +1,8 @@ +{ + "parent": "create:block/bars/post_ends", + "textures": { + "bars": "create:block/bars/andesite_bars", + "edge": "create:block/bars/andesite_bars_edge", + "particle": "create:block/bars/andesite_bars" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_scaffolding.json b/src/generated/resources/assets/create/models/block/andesite_scaffolding.json new file mode 100644 index 000000000..c08ef5c20 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/andesite_scaffolding.json @@ -0,0 +1,10 @@ +{ + "parent": "create:block/scaffold/block", + "textures": { + "casing": "create:block/andesite_casing", + "inside": "create:block/scaffold/andesite_scaffold_inside", + "particle": "create:block/scaffold/andesite_scaffold", + "side": "create:block/scaffold/andesite_scaffold", + "top": "create:block/funnel/andesite_funnel_frame" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_scaffolding_horizontal.json b/src/generated/resources/assets/create/models/block/andesite_scaffolding_horizontal.json new file mode 100644 index 000000000..c1a9500f5 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/andesite_scaffolding_horizontal.json @@ -0,0 +1,10 @@ +{ + "parent": "create:block/scaffold/block_horizontal", + "textures": { + "casing": "create:block/andesite_casing", + "inside": "create:block/scaffold/andesite_scaffold_inside", + "particle": "create:block/scaffold/andesite_scaffold", + "side": "create:block/scaffold/andesite_scaffold", + "top": "create:block/funnel/andesite_funnel_frame" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_side.json b/src/generated/resources/assets/create/models/block/andesite_side.json new file mode 100644 index 000000000..8905197b6 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/andesite_side.json @@ -0,0 +1,8 @@ +{ + "parent": "create:block/bars/side", + "textures": { + "bars": "create:block/bars/andesite_bars", + "edge": "create:block/bars/andesite_bars_edge", + "particle": "create:block/bars/andesite_bars" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_side_alt.json b/src/generated/resources/assets/create/models/block/andesite_side_alt.json new file mode 100644 index 000000000..692b13aee --- /dev/null +++ b/src/generated/resources/assets/create/models/block/andesite_side_alt.json @@ -0,0 +1,8 @@ +{ + "parent": "create:block/bars/side_alt", + "textures": { + "bars": "create:block/bars/andesite_bars", + "edge": "create:block/bars/andesite_bars_edge", + "particle": "create:block/bars/andesite_bars" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_tunnel/cross.json b/src/generated/resources/assets/create/models/block/andesite_tunnel/cross.json deleted file mode 100644 index 26d9a16a2..000000000 --- a/src/generated/resources/assets/create/models/block/andesite_tunnel/cross.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "parent": "create:block/belt_tunnel/cross", - "textures": { - "1": "create:block/andesite_tunnel_top", - "2": "create:block/andesite_tunnel", - "3": "create:block/andesite_tunnel_top_window", - "particle": "minecraft:block/polished_andesite" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_tunnel/straight.json b/src/generated/resources/assets/create/models/block/andesite_tunnel/straight.json deleted file mode 100644 index c09b27740..000000000 --- a/src/generated/resources/assets/create/models/block/andesite_tunnel/straight.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "parent": "create:block/belt_tunnel/straight", - "textures": { - "1": "create:block/andesite_tunnel_top", - "2": "create:block/andesite_tunnel", - "3": "create:block/andesite_tunnel_top_window", - "particle": "minecraft:block/polished_andesite" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_tunnel/t_left.json b/src/generated/resources/assets/create/models/block/andesite_tunnel/t_left.json deleted file mode 100644 index 2f3779c2d..000000000 --- a/src/generated/resources/assets/create/models/block/andesite_tunnel/t_left.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "parent": "create:block/belt_tunnel/t_left", - "textures": { - "1": "create:block/andesite_tunnel_top", - "2": "create:block/andesite_tunnel", - "3": "create:block/andesite_tunnel_top_window", - "particle": "minecraft:block/polished_andesite" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_tunnel/t_right.json b/src/generated/resources/assets/create/models/block/andesite_tunnel/t_right.json deleted file mode 100644 index 52212c4a7..000000000 --- a/src/generated/resources/assets/create/models/block/andesite_tunnel/t_right.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "parent": "create:block/belt_tunnel/t_right", - "textures": { - "1": "create:block/andesite_tunnel_top", - "2": "create:block/andesite_tunnel", - "3": "create:block/andesite_tunnel_top_window", - "particle": "minecraft:block/polished_andesite" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/andesite_tunnel/window.json b/src/generated/resources/assets/create/models/block/andesite_tunnel/window.json deleted file mode 100644 index 71fd705dc..000000000 --- a/src/generated/resources/assets/create/models/block/andesite_tunnel/window.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "parent": "create:block/belt_tunnel/window", - "textures": { - "1": "create:block/andesite_tunnel_top", - "2": "create:block/andesite_tunnel", - "3": "create:block/andesite_tunnel_top_window", - "particle": "minecraft:block/polished_andesite" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/asurine.json b/src/generated/resources/assets/create/models/block/asurine.json deleted file mode 100644 index 800055e27..000000000 --- a/src/generated/resources/assets/create/models/block/asurine.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:block/cube_all", - "textures": { - "all": "create:block/palettes/stone_types/asurine" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/asurine_natural_0.json b/src/generated/resources/assets/create/models/block/asurine_natural_0.json new file mode 100644 index 000000000..215bad507 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/asurine_natural_0.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "create:block/palettes/stone_types/natural/asurine_0" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/asurine_natural_1.json b/src/generated/resources/assets/create/models/block/asurine_natural_1.json new file mode 100644 index 000000000..1075b117c --- /dev/null +++ b/src/generated/resources/assets/create/models/block/asurine_natural_1.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "create:block/palettes/stone_types/natural/asurine_1" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/asurine_natural_2.json b/src/generated/resources/assets/create/models/block/asurine_natural_2.json new file mode 100644 index 000000000..0dc373e4c --- /dev/null +++ b/src/generated/resources/assets/create/models/block/asurine_natural_2.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "create:block/palettes/stone_types/natural/asurine_2" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/asurine_natural_3.json b/src/generated/resources/assets/create/models/block/asurine_natural_3.json new file mode 100644 index 000000000..ac3daef70 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/asurine_natural_3.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "create:block/palettes/stone_types/natural/asurine_3" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_belt_funnel_extended.json b/src/generated/resources/assets/create/models/block/brass_belt_funnel_extended.json deleted file mode 100644 index 249e33f78..000000000 --- a/src/generated/resources/assets/create/models/block/brass_belt_funnel_extended.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "parent": "create:block/belt_funnel/block_extended", - "textures": { - "2": "create:block/brass_funnel_neutral", - "2_1": "create:block/brass_funnel_push", - "2_2": "create:block/brass_funnel_pull", - "3": "create:block/brass_funnel_back", - "5": "create:block/brass_funnel_tall", - "6": "create:block/brass_funnel", - "7": "create:block/brass_funnel_plating", - "particle": "create:block/brass_block" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_belt_funnel_extended_powered.json b/src/generated/resources/assets/create/models/block/brass_belt_funnel_extended_powered.json index dd9997607..2217322f7 100644 --- a/src/generated/resources/assets/create/models/block/brass_belt_funnel_extended_powered.json +++ b/src/generated/resources/assets/create/models/block/brass_belt_funnel_extended_powered.json @@ -1,13 +1,10 @@ { "parent": "create:block/belt_funnel/block_extended", "textures": { - "2": "create:block/brass_funnel_neutral", - "2_1": "create:block/brass_funnel_push", - "2_2": "create:block/brass_funnel_pull", - "3": "create:block/brass_funnel_back", - "5": "create:block/brass_funnel_tall_powered", - "6": "create:block/brass_funnel_powered", - "7": "create:block/brass_funnel_plating", - "particle": "create:block/brass_block" + "base": "create:block/funnel/brass_funnel", + "block": "create:block/brass_block", + "direction": "create:block/funnel/brass_funnel_neutral", + "particle": "create:block/brass_block", + "redstone": "create:block/funnel/brass_funnel_powered" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_belt_funnel_extended_unpowered.json b/src/generated/resources/assets/create/models/block/brass_belt_funnel_extended_unpowered.json new file mode 100644 index 000000000..0751e40ed --- /dev/null +++ b/src/generated/resources/assets/create/models/block/brass_belt_funnel_extended_unpowered.json @@ -0,0 +1,10 @@ +{ + "parent": "create:block/belt_funnel/block_extended", + "textures": { + "base": "create:block/funnel/brass_funnel", + "block": "create:block/brass_block", + "direction": "create:block/funnel/brass_funnel_neutral", + "particle": "create:block/brass_block", + "redstone": "create:block/funnel/brass_funnel_unpowered" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_belt_funnel_pulling.json b/src/generated/resources/assets/create/models/block/brass_belt_funnel_pulling.json deleted file mode 100644 index 63ae99547..000000000 --- a/src/generated/resources/assets/create/models/block/brass_belt_funnel_pulling.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "parent": "create:block/belt_funnel/block_pulling", - "textures": { - "2": "create:block/brass_funnel_neutral", - "2_1": "create:block/brass_funnel_push", - "2_2": "create:block/brass_funnel_pull", - "3": "create:block/brass_funnel_back", - "5": "create:block/brass_funnel_tall", - "6": "create:block/brass_funnel", - "7": "create:block/brass_funnel_plating", - "particle": "create:block/brass_block" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_belt_funnel_pulling_powered.json b/src/generated/resources/assets/create/models/block/brass_belt_funnel_pulling_powered.json index 0c531e3e8..4f3558ee9 100644 --- a/src/generated/resources/assets/create/models/block/brass_belt_funnel_pulling_powered.json +++ b/src/generated/resources/assets/create/models/block/brass_belt_funnel_pulling_powered.json @@ -1,13 +1,10 @@ { "parent": "create:block/belt_funnel/block_pulling", "textures": { - "2": "create:block/brass_funnel_neutral", - "2_1": "create:block/brass_funnel_push", - "2_2": "create:block/brass_funnel_pull", - "3": "create:block/brass_funnel_back", - "5": "create:block/brass_funnel_tall_powered", - "6": "create:block/brass_funnel_powered", - "7": "create:block/brass_funnel_plating", - "particle": "create:block/brass_block" + "base": "create:block/funnel/brass_funnel", + "block": "create:block/brass_block", + "direction": "create:block/funnel/brass_funnel_pull", + "particle": "create:block/brass_block", + "redstone": "create:block/funnel/brass_funnel_powered" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_belt_funnel_pulling_unpowered.json b/src/generated/resources/assets/create/models/block/brass_belt_funnel_pulling_unpowered.json new file mode 100644 index 000000000..5536fb5b4 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/brass_belt_funnel_pulling_unpowered.json @@ -0,0 +1,10 @@ +{ + "parent": "create:block/belt_funnel/block_pulling", + "textures": { + "base": "create:block/funnel/brass_funnel", + "block": "create:block/brass_block", + "direction": "create:block/funnel/brass_funnel_pull", + "particle": "create:block/brass_block", + "redstone": "create:block/funnel/brass_funnel_unpowered" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_belt_funnel_pushing.json b/src/generated/resources/assets/create/models/block/brass_belt_funnel_pushing.json deleted file mode 100644 index 7f4309fdc..000000000 --- a/src/generated/resources/assets/create/models/block/brass_belt_funnel_pushing.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "parent": "create:block/belt_funnel/block_pushing", - "textures": { - "2": "create:block/brass_funnel_neutral", - "2_1": "create:block/brass_funnel_push", - "2_2": "create:block/brass_funnel_pull", - "3": "create:block/brass_funnel_back", - "5": "create:block/brass_funnel_tall", - "6": "create:block/brass_funnel", - "7": "create:block/brass_funnel_plating", - "particle": "create:block/brass_block" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_belt_funnel_pushing_powered.json b/src/generated/resources/assets/create/models/block/brass_belt_funnel_pushing_powered.json index b14faa192..a00814ded 100644 --- a/src/generated/resources/assets/create/models/block/brass_belt_funnel_pushing_powered.json +++ b/src/generated/resources/assets/create/models/block/brass_belt_funnel_pushing_powered.json @@ -1,13 +1,10 @@ { "parent": "create:block/belt_funnel/block_pushing", "textures": { - "2": "create:block/brass_funnel_neutral", - "2_1": "create:block/brass_funnel_push", - "2_2": "create:block/brass_funnel_pull", - "3": "create:block/brass_funnel_back", - "5": "create:block/brass_funnel_tall_powered", - "6": "create:block/brass_funnel_powered", - "7": "create:block/brass_funnel_plating", - "particle": "create:block/brass_block" + "base": "create:block/funnel/brass_funnel", + "block": "create:block/brass_block", + "direction": "create:block/funnel/brass_funnel_push", + "particle": "create:block/brass_block", + "redstone": "create:block/funnel/brass_funnel_powered" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_belt_funnel_pushing_unpowered.json b/src/generated/resources/assets/create/models/block/brass_belt_funnel_pushing_unpowered.json new file mode 100644 index 000000000..9d386a3b8 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/brass_belt_funnel_pushing_unpowered.json @@ -0,0 +1,10 @@ +{ + "parent": "create:block/belt_funnel/block_pushing", + "textures": { + "base": "create:block/funnel/brass_funnel", + "block": "create:block/brass_block", + "direction": "create:block/funnel/brass_funnel_push", + "particle": "create:block/brass_block", + "redstone": "create:block/funnel/brass_funnel_unpowered" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_belt_funnel_retracted.json b/src/generated/resources/assets/create/models/block/brass_belt_funnel_retracted.json deleted file mode 100644 index cf6305eaa..000000000 --- a/src/generated/resources/assets/create/models/block/brass_belt_funnel_retracted.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "parent": "create:block/belt_funnel/block_retracted", - "textures": { - "2": "create:block/brass_funnel_neutral", - "2_1": "create:block/brass_funnel_push", - "2_2": "create:block/brass_funnel_pull", - "3": "create:block/brass_funnel_back", - "5": "create:block/brass_funnel_tall", - "6": "create:block/brass_funnel", - "7": "create:block/brass_funnel_plating", - "particle": "create:block/brass_block" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_belt_funnel_retracted_powered.json b/src/generated/resources/assets/create/models/block/brass_belt_funnel_retracted_powered.json index 973589265..5c464d57d 100644 --- a/src/generated/resources/assets/create/models/block/brass_belt_funnel_retracted_powered.json +++ b/src/generated/resources/assets/create/models/block/brass_belt_funnel_retracted_powered.json @@ -1,13 +1,10 @@ { "parent": "create:block/belt_funnel/block_retracted", "textures": { - "2": "create:block/brass_funnel_neutral", - "2_1": "create:block/brass_funnel_push", - "2_2": "create:block/brass_funnel_pull", - "3": "create:block/brass_funnel_back", - "5": "create:block/brass_funnel_tall_powered", - "6": "create:block/brass_funnel_powered", - "7": "create:block/brass_funnel_plating", - "particle": "create:block/brass_block" + "base": "create:block/funnel/brass_funnel", + "block": "create:block/brass_block", + "direction": "create:block/funnel/brass_funnel_neutral", + "particle": "create:block/brass_block", + "redstone": "create:block/funnel/brass_funnel_powered" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_belt_funnel_retracted_unpowered.json b/src/generated/resources/assets/create/models/block/brass_belt_funnel_retracted_unpowered.json new file mode 100644 index 000000000..1da2e9124 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/brass_belt_funnel_retracted_unpowered.json @@ -0,0 +1,10 @@ +{ + "parent": "create:block/belt_funnel/block_retracted", + "textures": { + "base": "create:block/funnel/brass_funnel", + "block": "create:block/brass_block", + "direction": "create:block/funnel/brass_funnel_neutral", + "particle": "create:block/brass_block", + "redstone": "create:block/funnel/brass_funnel_unpowered" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_block.json b/src/generated/resources/assets/create/models/block/brass_block.json index c3d4b94f4..124827f00 100644 --- a/src/generated/resources/assets/create/models/block/brass_block.json +++ b/src/generated/resources/assets/create/models/block/brass_block.json @@ -1,6 +1,6 @@ { "parent": "minecraft:block/cube_all", "textures": { - "all": "create:block/brass_storage_block" + "all": "create:block/brass_block" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_cap.json b/src/generated/resources/assets/create/models/block/brass_cap.json new file mode 100644 index 000000000..8f165512c --- /dev/null +++ b/src/generated/resources/assets/create/models/block/brass_cap.json @@ -0,0 +1,8 @@ +{ + "parent": "create:block/bars/cap", + "textures": { + "bars": "create:block/bars/brass_bars", + "edge": "create:block/bars/brass_bars_edge", + "particle": "create:block/bars/brass_bars" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_cap_alt.json b/src/generated/resources/assets/create/models/block/brass_cap_alt.json new file mode 100644 index 000000000..0460fc6c1 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/brass_cap_alt.json @@ -0,0 +1,8 @@ +{ + "parent": "create:block/bars/cap_alt", + "textures": { + "bars": "create:block/bars/brass_bars", + "edge": "create:block/bars/brass_bars_edge", + "particle": "create:block/bars/brass_bars" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_encased_cogwheel.json b/src/generated/resources/assets/create/models/block/brass_encased_cogwheel.json index c44239d7a..e1e6ea74e 100644 --- a/src/generated/resources/assets/create/models/block/brass_encased_cogwheel.json +++ b/src/generated/resources/assets/create/models/block/brass_encased_cogwheel.json @@ -2,7 +2,9 @@ "parent": "create:block/encased_cogwheel/block", "textures": { "1": "minecraft:block/stripped_dark_oak_log_top", + "4": "create:block/brass_gearbox", "casing": "create:block/brass_casing", + "particle": "create:block/brass_casing", "side": "create:block/brass_encased_cogwheel_side" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_encased_cogwheel_bottom.json b/src/generated/resources/assets/create/models/block/brass_encased_cogwheel_bottom.json index aad1288a1..f1d17e0cc 100644 --- a/src/generated/resources/assets/create/models/block/brass_encased_cogwheel_bottom.json +++ b/src/generated/resources/assets/create/models/block/brass_encased_cogwheel_bottom.json @@ -2,7 +2,9 @@ "parent": "create:block/encased_cogwheel/block_bottom", "textures": { "1": "minecraft:block/stripped_dark_oak_log_top", + "4": "create:block/brass_gearbox", "casing": "create:block/brass_casing", + "particle": "create:block/brass_casing", "side": "create:block/brass_encased_cogwheel_side" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_encased_cogwheel_top.json b/src/generated/resources/assets/create/models/block/brass_encased_cogwheel_top.json index b2666233f..1cca92fb9 100644 --- a/src/generated/resources/assets/create/models/block/brass_encased_cogwheel_top.json +++ b/src/generated/resources/assets/create/models/block/brass_encased_cogwheel_top.json @@ -2,7 +2,9 @@ "parent": "create:block/encased_cogwheel/block_top", "textures": { "1": "minecraft:block/stripped_dark_oak_log_top", + "4": "create:block/brass_gearbox", "casing": "create:block/brass_casing", + "particle": "create:block/brass_casing", "side": "create:block/brass_encased_cogwheel_side" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_encased_cogwheel_top_bottom.json b/src/generated/resources/assets/create/models/block/brass_encased_cogwheel_top_bottom.json index 2e5efeea1..5c50d1285 100644 --- a/src/generated/resources/assets/create/models/block/brass_encased_cogwheel_top_bottom.json +++ b/src/generated/resources/assets/create/models/block/brass_encased_cogwheel_top_bottom.json @@ -2,7 +2,9 @@ "parent": "create:block/encased_cogwheel/block_top_bottom", "textures": { "1": "minecraft:block/stripped_dark_oak_log_top", + "4": "create:block/brass_gearbox", "casing": "create:block/brass_casing", + "particle": "create:block/brass_casing", "side": "create:block/brass_encased_cogwheel_side" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_encased_large_cogwheel.json b/src/generated/resources/assets/create/models/block/brass_encased_large_cogwheel.json index e14c2099d..131f3e1b1 100644 --- a/src/generated/resources/assets/create/models/block/brass_encased_large_cogwheel.json +++ b/src/generated/resources/assets/create/models/block/brass_encased_large_cogwheel.json @@ -2,7 +2,9 @@ "parent": "create:block/encased_large_cogwheel/block", "textures": { "1": "minecraft:block/stripped_dark_oak_log_top", + "4": "create:block/brass_gearbox", "casing": "create:block/brass_casing", + "particle": "create:block/brass_casing", "side": "create:block/brass_encased_cogwheel_side_connected" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_encased_large_cogwheel_bottom.json b/src/generated/resources/assets/create/models/block/brass_encased_large_cogwheel_bottom.json index 9e2bafd6a..e056b96d2 100644 --- a/src/generated/resources/assets/create/models/block/brass_encased_large_cogwheel_bottom.json +++ b/src/generated/resources/assets/create/models/block/brass_encased_large_cogwheel_bottom.json @@ -2,7 +2,9 @@ "parent": "create:block/encased_large_cogwheel/block_bottom", "textures": { "1": "minecraft:block/stripped_dark_oak_log_top", + "4": "create:block/brass_gearbox", "casing": "create:block/brass_casing", + "particle": "create:block/brass_casing", "side": "create:block/brass_encased_cogwheel_side_connected" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_encased_large_cogwheel_top.json b/src/generated/resources/assets/create/models/block/brass_encased_large_cogwheel_top.json index 1bb5214e8..10fc0b944 100644 --- a/src/generated/resources/assets/create/models/block/brass_encased_large_cogwheel_top.json +++ b/src/generated/resources/assets/create/models/block/brass_encased_large_cogwheel_top.json @@ -2,7 +2,9 @@ "parent": "create:block/encased_large_cogwheel/block_top", "textures": { "1": "minecraft:block/stripped_dark_oak_log_top", + "4": "create:block/brass_gearbox", "casing": "create:block/brass_casing", + "particle": "create:block/brass_casing", "side": "create:block/brass_encased_cogwheel_side_connected" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_encased_large_cogwheel_top_bottom.json b/src/generated/resources/assets/create/models/block/brass_encased_large_cogwheel_top_bottom.json index e08885adb..d694732b3 100644 --- a/src/generated/resources/assets/create/models/block/brass_encased_large_cogwheel_top_bottom.json +++ b/src/generated/resources/assets/create/models/block/brass_encased_large_cogwheel_top_bottom.json @@ -2,7 +2,9 @@ "parent": "create:block/encased_large_cogwheel/block_top_bottom", "textures": { "1": "minecraft:block/stripped_dark_oak_log_top", + "4": "create:block/brass_gearbox", "casing": "create:block/brass_casing", + "particle": "create:block/brass_casing", "side": "create:block/brass_encased_cogwheel_side_connected" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_funnel_horizontal_pull.json b/src/generated/resources/assets/create/models/block/brass_funnel_horizontal_pull.json deleted file mode 100644 index 2bab46d13..000000000 --- a/src/generated/resources/assets/create/models/block/brass_funnel_horizontal_pull.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "parent": "create:block/funnel/block_horizontal", - "textures": { - "2_2": "create:block/brass_funnel_pull", - "3": "create:block/brass_funnel_back", - "5": "create:block/brass_funnel_tall", - "6": "create:block/brass_funnel", - "7": "create:block/brass_funnel_plating", - "particle": "create:block/brass_casing" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_funnel_horizontal_pull_powered.json b/src/generated/resources/assets/create/models/block/brass_funnel_horizontal_pull_powered.json index 5d421462d..f91567d02 100644 --- a/src/generated/resources/assets/create/models/block/brass_funnel_horizontal_pull_powered.json +++ b/src/generated/resources/assets/create/models/block/brass_funnel_horizontal_pull_powered.json @@ -1,11 +1,10 @@ { "parent": "create:block/funnel/block_horizontal", "textures": { - "2_2": "create:block/brass_funnel_pull", - "3": "create:block/brass_funnel_back", - "5": "create:block/brass_funnel_tall_powered", - "6": "create:block/brass_funnel_powered", - "7": "create:block/brass_funnel_plating", - "particle": "create:block/brass_casing" + "base": "create:block/funnel/brass_funnel", + "block": "create:block/brass_block", + "direction": "create:block/funnel/brass_funnel_pull", + "particle": "create:block/brass_block", + "redstone": "create:block/funnel/brass_funnel_powered" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_funnel_horizontal_pull_unpowered.json b/src/generated/resources/assets/create/models/block/brass_funnel_horizontal_pull_unpowered.json new file mode 100644 index 000000000..e58171427 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/brass_funnel_horizontal_pull_unpowered.json @@ -0,0 +1,10 @@ +{ + "parent": "create:block/funnel/block_horizontal", + "textures": { + "base": "create:block/funnel/brass_funnel", + "block": "create:block/brass_block", + "direction": "create:block/funnel/brass_funnel_pull", + "particle": "create:block/brass_block", + "redstone": "create:block/funnel/brass_funnel_unpowered" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_funnel_horizontal_push.json b/src/generated/resources/assets/create/models/block/brass_funnel_horizontal_push.json deleted file mode 100644 index bc9fbbf72..000000000 --- a/src/generated/resources/assets/create/models/block/brass_funnel_horizontal_push.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "parent": "create:block/funnel/block_horizontal", - "textures": { - "2_2": "create:block/brass_funnel_push", - "3": "create:block/brass_funnel_back", - "5": "create:block/brass_funnel_tall", - "6": "create:block/brass_funnel", - "7": "create:block/brass_funnel_plating", - "particle": "create:block/brass_casing" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_funnel_horizontal_push_powered.json b/src/generated/resources/assets/create/models/block/brass_funnel_horizontal_push_powered.json index 03ba11b36..a31cdee5e 100644 --- a/src/generated/resources/assets/create/models/block/brass_funnel_horizontal_push_powered.json +++ b/src/generated/resources/assets/create/models/block/brass_funnel_horizontal_push_powered.json @@ -1,11 +1,10 @@ { "parent": "create:block/funnel/block_horizontal", "textures": { - "2_2": "create:block/brass_funnel_push", - "3": "create:block/brass_funnel_back", - "5": "create:block/brass_funnel_tall_powered", - "6": "create:block/brass_funnel_powered", - "7": "create:block/brass_funnel_plating", - "particle": "create:block/brass_casing" + "base": "create:block/funnel/brass_funnel", + "block": "create:block/brass_block", + "direction": "create:block/funnel/brass_funnel_push", + "particle": "create:block/brass_block", + "redstone": "create:block/funnel/brass_funnel_powered" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_funnel_horizontal_push_unpowered.json b/src/generated/resources/assets/create/models/block/brass_funnel_horizontal_push_unpowered.json new file mode 100644 index 000000000..597424efd --- /dev/null +++ b/src/generated/resources/assets/create/models/block/brass_funnel_horizontal_push_unpowered.json @@ -0,0 +1,10 @@ +{ + "parent": "create:block/funnel/block_horizontal", + "textures": { + "base": "create:block/funnel/brass_funnel", + "block": "create:block/brass_block", + "direction": "create:block/funnel/brass_funnel_push", + "particle": "create:block/brass_block", + "redstone": "create:block/funnel/brass_funnel_unpowered" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_funnel_vertical_pull.json b/src/generated/resources/assets/create/models/block/brass_funnel_vertical_pull.json deleted file mode 100644 index 491cc736f..000000000 --- a/src/generated/resources/assets/create/models/block/brass_funnel_vertical_pull.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "parent": "create:block/funnel/block_vertical", - "textures": { - "10": "create:block/funnel_open", - "2_2": "create:block/brass_funnel_pull", - "3": "create:block/brass_funnel_back", - "5": "create:block/brass_funnel_tall", - "7": "create:block/brass_funnel_plating", - "8": "create:block/brass_casing", - "9": "create:block/brass_funnel_slope", - "particle": "create:block/brass_casing" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_funnel_vertical_pull_powered.json b/src/generated/resources/assets/create/models/block/brass_funnel_vertical_pull_powered.json index 6d83aa24d..9c2fd1eaf 100644 --- a/src/generated/resources/assets/create/models/block/brass_funnel_vertical_pull_powered.json +++ b/src/generated/resources/assets/create/models/block/brass_funnel_vertical_pull_powered.json @@ -1,13 +1,11 @@ { "parent": "create:block/funnel/block_vertical", "textures": { - "10": "create:block/funnel_closed", - "2_2": "create:block/brass_funnel_pull", - "3": "create:block/brass_funnel_back", - "5": "create:block/brass_funnel_tall_powered", - "7": "create:block/brass_funnel_plating", - "8": "create:block/brass_casing", - "9": "create:block/brass_funnel_slope", - "particle": "create:block/brass_casing" + "base": "create:block/funnel/brass_funnel", + "direction": "create:block/funnel/brass_funnel_pull", + "frame": "create:block/funnel/brass_funnel_frame", + "open": "create:block/funnel/funnel_closed", + "particle": "create:block/brass_block", + "redstone": "create:block/funnel/brass_funnel_powered" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_funnel_vertical_pull_unpowered.json b/src/generated/resources/assets/create/models/block/brass_funnel_vertical_pull_unpowered.json new file mode 100644 index 000000000..f4c22ba35 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/brass_funnel_vertical_pull_unpowered.json @@ -0,0 +1,11 @@ +{ + "parent": "create:block/funnel/block_vertical", + "textures": { + "base": "create:block/funnel/brass_funnel", + "direction": "create:block/funnel/brass_funnel_pull", + "frame": "create:block/funnel/brass_funnel_frame", + "open": "create:block/funnel/funnel_open", + "particle": "create:block/brass_block", + "redstone": "create:block/funnel/brass_funnel_unpowered" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_funnel_vertical_push.json b/src/generated/resources/assets/create/models/block/brass_funnel_vertical_push.json deleted file mode 100644 index 5dfa13376..000000000 --- a/src/generated/resources/assets/create/models/block/brass_funnel_vertical_push.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "parent": "create:block/funnel/block_vertical", - "textures": { - "10": "create:block/funnel_open", - "2_2": "create:block/brass_funnel_push", - "3": "create:block/brass_funnel_back", - "5": "create:block/brass_funnel_tall", - "7": "create:block/brass_funnel_plating", - "8": "create:block/brass_casing", - "9": "create:block/brass_funnel_slope", - "particle": "create:block/brass_casing" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_funnel_vertical_push_powered.json b/src/generated/resources/assets/create/models/block/brass_funnel_vertical_push_powered.json index 760dfa133..9e25372e5 100644 --- a/src/generated/resources/assets/create/models/block/brass_funnel_vertical_push_powered.json +++ b/src/generated/resources/assets/create/models/block/brass_funnel_vertical_push_powered.json @@ -1,13 +1,11 @@ { "parent": "create:block/funnel/block_vertical", "textures": { - "10": "create:block/funnel_closed", - "2_2": "create:block/brass_funnel_push", - "3": "create:block/brass_funnel_back", - "5": "create:block/brass_funnel_tall_powered", - "7": "create:block/brass_funnel_plating", - "8": "create:block/brass_casing", - "9": "create:block/brass_funnel_slope", - "particle": "create:block/brass_casing" + "base": "create:block/funnel/brass_funnel", + "direction": "create:block/funnel/brass_funnel_push", + "frame": "create:block/funnel/brass_funnel_frame", + "open": "create:block/funnel/funnel_closed", + "particle": "create:block/brass_block", + "redstone": "create:block/funnel/brass_funnel_powered" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_funnel_vertical_push_unpowered.json b/src/generated/resources/assets/create/models/block/brass_funnel_vertical_push_unpowered.json new file mode 100644 index 000000000..757fb58a4 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/brass_funnel_vertical_push_unpowered.json @@ -0,0 +1,11 @@ +{ + "parent": "create:block/funnel/block_vertical", + "textures": { + "base": "create:block/funnel/brass_funnel", + "direction": "create:block/funnel/brass_funnel_push", + "frame": "create:block/funnel/brass_funnel_frame", + "open": "create:block/funnel/funnel_open", + "particle": "create:block/brass_block", + "redstone": "create:block/funnel/brass_funnel_unpowered" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_post.json b/src/generated/resources/assets/create/models/block/brass_post.json new file mode 100644 index 000000000..927ccd0b4 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/brass_post.json @@ -0,0 +1,8 @@ +{ + "parent": "create:block/bars/post", + "textures": { + "bars": "create:block/bars/brass_bars", + "edge": "create:block/bars/brass_bars_edge", + "particle": "create:block/bars/brass_bars" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_post_ends.json b/src/generated/resources/assets/create/models/block/brass_post_ends.json new file mode 100644 index 000000000..f2424943d --- /dev/null +++ b/src/generated/resources/assets/create/models/block/brass_post_ends.json @@ -0,0 +1,8 @@ +{ + "parent": "create:block/bars/post_ends", + "textures": { + "bars": "create:block/bars/brass_bars", + "edge": "create:block/bars/brass_bars_edge", + "particle": "create:block/bars/brass_bars" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_scaffolding.json b/src/generated/resources/assets/create/models/block/brass_scaffolding.json new file mode 100644 index 000000000..b8be38dba --- /dev/null +++ b/src/generated/resources/assets/create/models/block/brass_scaffolding.json @@ -0,0 +1,10 @@ +{ + "parent": "create:block/scaffold/block", + "textures": { + "casing": "create:block/brass_casing", + "inside": "create:block/scaffold/brass_scaffold_inside", + "particle": "create:block/scaffold/brass_scaffold", + "side": "create:block/scaffold/brass_scaffold", + "top": "create:block/funnel/brass_funnel_frame" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_scaffolding_horizontal.json b/src/generated/resources/assets/create/models/block/brass_scaffolding_horizontal.json new file mode 100644 index 000000000..71881ce95 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/brass_scaffolding_horizontal.json @@ -0,0 +1,10 @@ +{ + "parent": "create:block/scaffold/block_horizontal", + "textures": { + "casing": "create:block/brass_casing", + "inside": "create:block/scaffold/brass_scaffold_inside", + "particle": "create:block/scaffold/brass_scaffold", + "side": "create:block/scaffold/brass_scaffold", + "top": "create:block/funnel/brass_funnel_frame" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_side.json b/src/generated/resources/assets/create/models/block/brass_side.json new file mode 100644 index 000000000..82aba3074 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/brass_side.json @@ -0,0 +1,8 @@ +{ + "parent": "create:block/bars/side", + "textures": { + "bars": "create:block/bars/brass_bars", + "edge": "create:block/bars/brass_bars_edge", + "particle": "create:block/bars/brass_bars" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_side_alt.json b/src/generated/resources/assets/create/models/block/brass_side_alt.json new file mode 100644 index 000000000..05cdc21db --- /dev/null +++ b/src/generated/resources/assets/create/models/block/brass_side_alt.json @@ -0,0 +1,8 @@ +{ + "parent": "create:block/bars/side_alt", + "textures": { + "bars": "create:block/bars/brass_bars", + "edge": "create:block/bars/brass_bars_edge", + "particle": "create:block/bars/brass_bars" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_tunnel/cross.json b/src/generated/resources/assets/create/models/block/brass_tunnel/cross.json deleted file mode 100644 index 35f563cc3..000000000 --- a/src/generated/resources/assets/create/models/block/brass_tunnel/cross.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "parent": "create:block/belt_tunnel/cross", - "textures": { - "1": "create:block/brass_tunnel_top", - "2": "create:block/brass_tunnel", - "3": "create:block/brass_tunnel_top_window", - "particle": "create:block/brass_block" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_tunnel/straight.json b/src/generated/resources/assets/create/models/block/brass_tunnel/straight.json deleted file mode 100644 index 219f22257..000000000 --- a/src/generated/resources/assets/create/models/block/brass_tunnel/straight.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "parent": "create:block/belt_tunnel/straight", - "textures": { - "1": "create:block/brass_tunnel_top", - "2": "create:block/brass_tunnel", - "3": "create:block/brass_tunnel_top_window", - "particle": "create:block/brass_block" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_tunnel/t_left.json b/src/generated/resources/assets/create/models/block/brass_tunnel/t_left.json deleted file mode 100644 index 62165f533..000000000 --- a/src/generated/resources/assets/create/models/block/brass_tunnel/t_left.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "parent": "create:block/belt_tunnel/t_left", - "textures": { - "1": "create:block/brass_tunnel_top", - "2": "create:block/brass_tunnel", - "3": "create:block/brass_tunnel_top_window", - "particle": "create:block/brass_block" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_tunnel/t_right.json b/src/generated/resources/assets/create/models/block/brass_tunnel/t_right.json deleted file mode 100644 index a9da1c54a..000000000 --- a/src/generated/resources/assets/create/models/block/brass_tunnel/t_right.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "parent": "create:block/belt_tunnel/t_right", - "textures": { - "1": "create:block/brass_tunnel_top", - "2": "create:block/brass_tunnel", - "3": "create:block/brass_tunnel_top_window", - "particle": "create:block/brass_block" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/brass_tunnel/window.json b/src/generated/resources/assets/create/models/block/brass_tunnel/window.json deleted file mode 100644 index 0c62dcab8..000000000 --- a/src/generated/resources/assets/create/models/block/brass_tunnel/window.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "parent": "create:block/belt_tunnel/window", - "textures": { - "1": "create:block/brass_tunnel_top", - "2": "create:block/brass_tunnel", - "3": "create:block/brass_tunnel_top_window", - "particle": "create:block/brass_block" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/clockwork_bearing.json b/src/generated/resources/assets/create/models/block/clockwork_bearing.json index 0f7ef945f..afadeaedf 100644 --- a/src/generated/resources/assets/create/models/block/clockwork_bearing.json +++ b/src/generated/resources/assets/create/models/block/clockwork_bearing.json @@ -2,7 +2,6 @@ "parent": "create:block/bearing/block", "textures": { "back": "create:block/brass_gearbox", - "nook": "create:block/brass_casing", "side": "create:block/clockwork_bearing_side" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/copper_cap.json b/src/generated/resources/assets/create/models/block/copper_cap.json new file mode 100644 index 000000000..f4467b314 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/copper_cap.json @@ -0,0 +1,8 @@ +{ + "parent": "create:block/bars/cap", + "textures": { + "bars": "create:block/bars/copper_bars", + "edge": "create:block/bars/copper_bars_edge", + "particle": "create:block/bars/copper_bars" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/copper_cap_alt.json b/src/generated/resources/assets/create/models/block/copper_cap_alt.json new file mode 100644 index 000000000..81d5392ce --- /dev/null +++ b/src/generated/resources/assets/create/models/block/copper_cap_alt.json @@ -0,0 +1,8 @@ +{ + "parent": "create:block/bars/cap_alt", + "textures": { + "bars": "create:block/bars/copper_bars", + "edge": "create:block/bars/copper_bars_edge", + "particle": "create:block/bars/copper_bars" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/copper_post.json b/src/generated/resources/assets/create/models/block/copper_post.json new file mode 100644 index 000000000..135ba3ab7 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/copper_post.json @@ -0,0 +1,8 @@ +{ + "parent": "create:block/bars/post", + "textures": { + "bars": "create:block/bars/copper_bars", + "edge": "create:block/bars/copper_bars_edge", + "particle": "create:block/bars/copper_bars" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/copper_post_ends.json b/src/generated/resources/assets/create/models/block/copper_post_ends.json new file mode 100644 index 000000000..6de1f191f --- /dev/null +++ b/src/generated/resources/assets/create/models/block/copper_post_ends.json @@ -0,0 +1,8 @@ +{ + "parent": "create:block/bars/post_ends", + "textures": { + "bars": "create:block/bars/copper_bars", + "edge": "create:block/bars/copper_bars_edge", + "particle": "create:block/bars/copper_bars" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/copper_scaffolding.json b/src/generated/resources/assets/create/models/block/copper_scaffolding.json new file mode 100644 index 000000000..fff21fb4e --- /dev/null +++ b/src/generated/resources/assets/create/models/block/copper_scaffolding.json @@ -0,0 +1,10 @@ +{ + "parent": "create:block/scaffold/block", + "textures": { + "casing": "create:block/copper_casing", + "inside": "create:block/scaffold/copper_scaffold_inside", + "particle": "create:block/scaffold/copper_scaffold", + "side": "create:block/scaffold/copper_scaffold", + "top": "create:block/funnel/copper_funnel_frame" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/copper_scaffolding_horizontal.json b/src/generated/resources/assets/create/models/block/copper_scaffolding_horizontal.json new file mode 100644 index 000000000..7e8e31eb9 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/copper_scaffolding_horizontal.json @@ -0,0 +1,10 @@ +{ + "parent": "create:block/scaffold/block_horizontal", + "textures": { + "casing": "create:block/copper_casing", + "inside": "create:block/scaffold/copper_scaffold_inside", + "particle": "create:block/scaffold/copper_scaffold", + "side": "create:block/scaffold/copper_scaffold", + "top": "create:block/funnel/copper_funnel_frame" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/copper_side.json b/src/generated/resources/assets/create/models/block/copper_side.json new file mode 100644 index 000000000..a8932702b --- /dev/null +++ b/src/generated/resources/assets/create/models/block/copper_side.json @@ -0,0 +1,8 @@ +{ + "parent": "create:block/bars/side", + "textures": { + "bars": "create:block/bars/copper_bars", + "edge": "create:block/bars/copper_bars_edge", + "particle": "create:block/bars/copper_bars" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/copper_side_alt.json b/src/generated/resources/assets/create/models/block/copper_side_alt.json new file mode 100644 index 000000000..ddc0826d9 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/copper_side_alt.json @@ -0,0 +1,8 @@ +{ + "parent": "create:block/bars/side_alt", + "textures": { + "bars": "create:block/bars/copper_bars", + "edge": "create:block/bars/copper_bars_edge", + "particle": "create:block/bars/copper_bars" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/crimsite.json b/src/generated/resources/assets/create/models/block/crimsite.json deleted file mode 100644 index a7c02eec1..000000000 --- a/src/generated/resources/assets/create/models/block/crimsite.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:block/cube_all", - "textures": { - "all": "create:block/palettes/stone_types/crimsite" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/crimsite_natural_0.json b/src/generated/resources/assets/create/models/block/crimsite_natural_0.json new file mode 100644 index 000000000..7199eff11 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/crimsite_natural_0.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "create:block/palettes/stone_types/natural/crimsite_0" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/crimsite_natural_1.json b/src/generated/resources/assets/create/models/block/crimsite_natural_1.json new file mode 100644 index 000000000..c006ddbf6 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/crimsite_natural_1.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "create:block/palettes/stone_types/natural/crimsite_1" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/crimsite_natural_2.json b/src/generated/resources/assets/create/models/block/crimsite_natural_2.json new file mode 100644 index 000000000..55208b5a0 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/crimsite_natural_2.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "create:block/palettes/stone_types/natural/crimsite_2" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/crimsite_natural_3.json b/src/generated/resources/assets/create/models/block/crimsite_natural_3.json new file mode 100644 index 000000000..a76aabcbe --- /dev/null +++ b/src/generated/resources/assets/create/models/block/crimsite_natural_3.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "create:block/palettes/stone_types/natural/crimsite_3" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/industrial_iron_block.json b/src/generated/resources/assets/create/models/block/industrial_iron_block.json new file mode 100644 index 000000000..9d0c8facf --- /dev/null +++ b/src/generated/resources/assets/create/models/block/industrial_iron_block.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:block/cube_column", + "textures": { + "end": "create:block/industrial_iron_block_top", + "side": "create:block/industrial_iron_block" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/mangrove_window.json b/src/generated/resources/assets/create/models/block/mangrove_window.json new file mode 100644 index 000000000..142956d8a --- /dev/null +++ b/src/generated/resources/assets/create/models/block/mangrove_window.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:block/cube_column", + "textures": { + "end": "minecraft:block/mangrove_planks", + "side": "create:block/palettes/mangrove_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/mangrove_window_pane_noside.json b/src/generated/resources/assets/create/models/block/mangrove_window_pane_noside.json new file mode 100644 index 000000000..61852efde --- /dev/null +++ b/src/generated/resources/assets/create/models/block/mangrove_window_pane_noside.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/connected_glass_pane/noside", + "textures": { + "edge": "minecraft:block/mangrove_planks", + "pane": "create:block/palettes/mangrove_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/mangrove_window_pane_noside_alt.json b/src/generated/resources/assets/create/models/block/mangrove_window_pane_noside_alt.json new file mode 100644 index 000000000..903a01929 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/mangrove_window_pane_noside_alt.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/connected_glass_pane/noside_alt", + "textures": { + "edge": "minecraft:block/mangrove_planks", + "pane": "create:block/palettes/mangrove_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/mangrove_window_pane_post.json b/src/generated/resources/assets/create/models/block/mangrove_window_pane_post.json new file mode 100644 index 000000000..230bc4703 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/mangrove_window_pane_post.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/connected_glass_pane/post", + "textures": { + "edge": "minecraft:block/mangrove_planks", + "pane": "create:block/palettes/mangrove_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/mangrove_window_pane_side.json b/src/generated/resources/assets/create/models/block/mangrove_window_pane_side.json new file mode 100644 index 000000000..ae91e5005 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/mangrove_window_pane_side.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/connected_glass_pane/side", + "textures": { + "edge": "minecraft:block/mangrove_planks", + "pane": "create:block/palettes/mangrove_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/mangrove_window_pane_side_alt.json b/src/generated/resources/assets/create/models/block/mangrove_window_pane_side_alt.json new file mode 100644 index 000000000..1044018d2 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/mangrove_window_pane_side_alt.json @@ -0,0 +1,7 @@ +{ + "parent": "create:block/connected_glass_pane/side_alt", + "textures": { + "edge": "minecraft:block/mangrove_planks", + "pane": "create:block/palettes/mangrove_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/mechanical_bearing.json b/src/generated/resources/assets/create/models/block/mechanical_bearing.json index 58f925520..ecf4dd2b0 100644 --- a/src/generated/resources/assets/create/models/block/mechanical_bearing.json +++ b/src/generated/resources/assets/create/models/block/mechanical_bearing.json @@ -2,7 +2,6 @@ "parent": "create:block/bearing/block", "textures": { "back": "create:block/gearbox", - "nook": "create:block/brass_casing", "side": "create:block/mechanical_bearing_side" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/ochrum.json b/src/generated/resources/assets/create/models/block/ochrum.json deleted file mode 100644 index aa1b78ea5..000000000 --- a/src/generated/resources/assets/create/models/block/ochrum.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:block/cube_all", - "textures": { - "all": "create:block/palettes/stone_types/ochrum" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/ochrum_natural_0.json b/src/generated/resources/assets/create/models/block/ochrum_natural_0.json new file mode 100644 index 000000000..a09dbd318 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/ochrum_natural_0.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "create:block/palettes/stone_types/natural/ochrum_0" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/ochrum_natural_1.json b/src/generated/resources/assets/create/models/block/ochrum_natural_1.json new file mode 100644 index 000000000..c765a7db2 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/ochrum_natural_1.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "create:block/palettes/stone_types/natural/ochrum_1" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/ochrum_natural_2.json b/src/generated/resources/assets/create/models/block/ochrum_natural_2.json new file mode 100644 index 000000000..31a26ea70 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/ochrum_natural_2.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "create:block/palettes/stone_types/natural/ochrum_2" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/ochrum_natural_3.json b/src/generated/resources/assets/create/models/block/ochrum_natural_3.json new file mode 100644 index 000000000..366b54a88 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/ochrum_natural_3.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "create:block/palettes/stone_types/natural/ochrum_3" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/stockpile_switch_0.json b/src/generated/resources/assets/create/models/block/stockpile_switch_0.json deleted file mode 100644 index 4d1b9b70e..000000000 --- a/src/generated/resources/assets/create/models/block/stockpile_switch_0.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "create:block/stockpile_switch", - "textures": { - "indicator": "create:block/indicator/0" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/stockpile_switch_1.json b/src/generated/resources/assets/create/models/block/stockpile_switch_1.json deleted file mode 100644 index 288dc2927..000000000 --- a/src/generated/resources/assets/create/models/block/stockpile_switch_1.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "create:block/stockpile_switch", - "textures": { - "indicator": "create:block/indicator/1" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/stockpile_switch_2.json b/src/generated/resources/assets/create/models/block/stockpile_switch_2.json deleted file mode 100644 index 8b0da8a21..000000000 --- a/src/generated/resources/assets/create/models/block/stockpile_switch_2.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "create:block/stockpile_switch", - "textures": { - "indicator": "create:block/indicator/2" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/stockpile_switch_3.json b/src/generated/resources/assets/create/models/block/stockpile_switch_3.json deleted file mode 100644 index fc3e40132..000000000 --- a/src/generated/resources/assets/create/models/block/stockpile_switch_3.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "create:block/stockpile_switch", - "textures": { - "indicator": "create:block/indicator/3" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/stockpile_switch_4.json b/src/generated/resources/assets/create/models/block/stockpile_switch_4.json deleted file mode 100644 index 2194e2c69..000000000 --- a/src/generated/resources/assets/create/models/block/stockpile_switch_4.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "create:block/stockpile_switch", - "textures": { - "indicator": "create:block/indicator/4" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/stockpile_switch_5.json b/src/generated/resources/assets/create/models/block/stockpile_switch_5.json deleted file mode 100644 index eb0f8298c..000000000 --- a/src/generated/resources/assets/create/models/block/stockpile_switch_5.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "create:block/stockpile_switch", - "textures": { - "indicator": "create:block/indicator/5" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/stockpile_switch_6.json b/src/generated/resources/assets/create/models/block/stockpile_switch_6.json deleted file mode 100644 index 58a83e646..000000000 --- a/src/generated/resources/assets/create/models/block/stockpile_switch_6.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "create:block/stockpile_switch", - "textures": { - "indicator": "create:block/indicator/6" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/tunnel/andesite_tunnel/cross.json b/src/generated/resources/assets/create/models/block/tunnel/andesite_tunnel/cross.json new file mode 100644 index 000000000..73b9e9a19 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/tunnel/andesite_tunnel/cross.json @@ -0,0 +1,10 @@ +{ + "parent": "create:block/belt_tunnel/cross", + "textures": { + "direction": "create:block/funnel/andesite_funnel_neutral", + "frame": "create:block/funnel/andesite_funnel_frame", + "particle": "minecraft:block/polished_andesite", + "top": "create:block/tunnel/andesite_tunnel_top", + "tunnel": "create:block/tunnel/andesite_tunnel" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/tunnel/andesite_tunnel/straight.json b/src/generated/resources/assets/create/models/block/tunnel/andesite_tunnel/straight.json new file mode 100644 index 000000000..595675435 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/tunnel/andesite_tunnel/straight.json @@ -0,0 +1,10 @@ +{ + "parent": "create:block/belt_tunnel/straight", + "textures": { + "direction": "create:block/funnel/andesite_funnel_neutral", + "frame": "create:block/funnel/andesite_funnel_frame", + "particle": "minecraft:block/polished_andesite", + "top": "create:block/tunnel/andesite_tunnel_top", + "tunnel": "create:block/tunnel/andesite_tunnel" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/tunnel/andesite_tunnel/t_left.json b/src/generated/resources/assets/create/models/block/tunnel/andesite_tunnel/t_left.json new file mode 100644 index 000000000..8ae552715 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/tunnel/andesite_tunnel/t_left.json @@ -0,0 +1,10 @@ +{ + "parent": "create:block/belt_tunnel/t_left", + "textures": { + "direction": "create:block/funnel/andesite_funnel_neutral", + "frame": "create:block/funnel/andesite_funnel_frame", + "particle": "minecraft:block/polished_andesite", + "top": "create:block/tunnel/andesite_tunnel_top", + "tunnel": "create:block/tunnel/andesite_tunnel" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/tunnel/andesite_tunnel/t_right.json b/src/generated/resources/assets/create/models/block/tunnel/andesite_tunnel/t_right.json new file mode 100644 index 000000000..681c4964c --- /dev/null +++ b/src/generated/resources/assets/create/models/block/tunnel/andesite_tunnel/t_right.json @@ -0,0 +1,10 @@ +{ + "parent": "create:block/belt_tunnel/t_right", + "textures": { + "direction": "create:block/funnel/andesite_funnel_neutral", + "frame": "create:block/funnel/andesite_funnel_frame", + "particle": "minecraft:block/polished_andesite", + "top": "create:block/tunnel/andesite_tunnel_top", + "tunnel": "create:block/tunnel/andesite_tunnel" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/tunnel/andesite_tunnel/window.json b/src/generated/resources/assets/create/models/block/tunnel/andesite_tunnel/window.json new file mode 100644 index 000000000..d45ef0a15 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/tunnel/andesite_tunnel/window.json @@ -0,0 +1,10 @@ +{ + "parent": "create:block/belt_tunnel/window", + "textures": { + "direction": "create:block/funnel/andesite_funnel_neutral", + "frame": "create:block/funnel/andesite_funnel_frame", + "particle": "minecraft:block/polished_andesite", + "top": "create:block/tunnel/andesite_tunnel_top_window", + "tunnel": "create:block/tunnel/andesite_tunnel" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/tunnel/brass_tunnel/cross.json b/src/generated/resources/assets/create/models/block/tunnel/brass_tunnel/cross.json new file mode 100644 index 000000000..6173e4a97 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/tunnel/brass_tunnel/cross.json @@ -0,0 +1,10 @@ +{ + "parent": "create:block/belt_tunnel/cross", + "textures": { + "direction": "create:block/funnel/brass_funnel_neutral", + "frame": "create:block/funnel/brass_funnel_frame", + "particle": "create:block/brass_block", + "top": "create:block/tunnel/brass_tunnel_top", + "tunnel": "create:block/tunnel/brass_tunnel" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/tunnel/brass_tunnel/straight.json b/src/generated/resources/assets/create/models/block/tunnel/brass_tunnel/straight.json new file mode 100644 index 000000000..b8355a41d --- /dev/null +++ b/src/generated/resources/assets/create/models/block/tunnel/brass_tunnel/straight.json @@ -0,0 +1,10 @@ +{ + "parent": "create:block/belt_tunnel/straight", + "textures": { + "direction": "create:block/funnel/brass_funnel_neutral", + "frame": "create:block/funnel/brass_funnel_frame", + "particle": "create:block/brass_block", + "top": "create:block/tunnel/brass_tunnel_top", + "tunnel": "create:block/tunnel/brass_tunnel" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/tunnel/brass_tunnel/t_left.json b/src/generated/resources/assets/create/models/block/tunnel/brass_tunnel/t_left.json new file mode 100644 index 000000000..0e479a569 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/tunnel/brass_tunnel/t_left.json @@ -0,0 +1,10 @@ +{ + "parent": "create:block/belt_tunnel/t_left", + "textures": { + "direction": "create:block/funnel/brass_funnel_neutral", + "frame": "create:block/funnel/brass_funnel_frame", + "particle": "create:block/brass_block", + "top": "create:block/tunnel/brass_tunnel_top", + "tunnel": "create:block/tunnel/brass_tunnel" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/tunnel/brass_tunnel/t_right.json b/src/generated/resources/assets/create/models/block/tunnel/brass_tunnel/t_right.json new file mode 100644 index 000000000..eb7879336 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/tunnel/brass_tunnel/t_right.json @@ -0,0 +1,10 @@ +{ + "parent": "create:block/belt_tunnel/t_right", + "textures": { + "direction": "create:block/funnel/brass_funnel_neutral", + "frame": "create:block/funnel/brass_funnel_frame", + "particle": "create:block/brass_block", + "top": "create:block/tunnel/brass_tunnel_top", + "tunnel": "create:block/tunnel/brass_tunnel" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/tunnel/brass_tunnel/window.json b/src/generated/resources/assets/create/models/block/tunnel/brass_tunnel/window.json new file mode 100644 index 000000000..260680abf --- /dev/null +++ b/src/generated/resources/assets/create/models/block/tunnel/brass_tunnel/window.json @@ -0,0 +1,10 @@ +{ + "parent": "create:block/belt_tunnel/window", + "textures": { + "direction": "create:block/funnel/brass_funnel_neutral", + "frame": "create:block/funnel/brass_funnel_frame", + "particle": "create:block/brass_block", + "top": "create:block/tunnel/brass_tunnel_top_window", + "tunnel": "create:block/tunnel/brass_tunnel" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/veridium.json b/src/generated/resources/assets/create/models/block/veridium.json deleted file mode 100644 index fe23b9d7a..000000000 --- a/src/generated/resources/assets/create/models/block/veridium.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:block/cube_all", - "textures": { - "all": "create:block/palettes/stone_types/veridium" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/veridium_natural_0.json b/src/generated/resources/assets/create/models/block/veridium_natural_0.json new file mode 100644 index 000000000..ec6d94630 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/veridium_natural_0.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "create:block/palettes/stone_types/natural/veridium_0" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/veridium_natural_1.json b/src/generated/resources/assets/create/models/block/veridium_natural_1.json new file mode 100644 index 000000000..52e7c814d --- /dev/null +++ b/src/generated/resources/assets/create/models/block/veridium_natural_1.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "create:block/palettes/stone_types/natural/veridium_1" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/veridium_natural_2.json b/src/generated/resources/assets/create/models/block/veridium_natural_2.json new file mode 100644 index 000000000..75f8fd7c3 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/veridium_natural_2.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "create:block/palettes/stone_types/natural/veridium_2" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/veridium_natural_3.json b/src/generated/resources/assets/create/models/block/veridium_natural_3.json new file mode 100644 index 000000000..d8f40fe31 --- /dev/null +++ b/src/generated/resources/assets/create/models/block/veridium_natural_3.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "create:block/palettes/stone_types/natural/veridium_3" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/block/windmill_bearing.json b/src/generated/resources/assets/create/models/block/windmill_bearing.json index 59002e009..5985340b3 100644 --- a/src/generated/resources/assets/create/models/block/windmill_bearing.json +++ b/src/generated/resources/assets/create/models/block/windmill_bearing.json @@ -2,7 +2,6 @@ "parent": "create:block/bearing/block", "textures": { "back": "create:block/gearbox", - "nook": "create:block/andesite_casing", "side": "create:block/windmill_bearing_side" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/andesite_alloy_block.json b/src/generated/resources/assets/create/models/item/andesite_alloy_block.json new file mode 100644 index 000000000..177e920a3 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/andesite_alloy_block.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/andesite_alloy_block" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/andesite_bars.json b/src/generated/resources/assets/create/models/item/andesite_bars.json new file mode 100644 index 000000000..a881e12f6 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/andesite_bars.json @@ -0,0 +1,7 @@ +{ + "parent": "create:item/bars", + "textures": { + "bars": "create:block/bars/andesite_bars", + "edge": "create:block/bars/andesite_bars_edge" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/andesite_door.json b/src/generated/resources/assets/create/models/item/andesite_door.json new file mode 100644 index 000000000..644fdf227 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/andesite_door.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/andesite_door" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/andesite_encased_cogwheel.json b/src/generated/resources/assets/create/models/item/andesite_encased_cogwheel.json index 30be3b80a..50c221d8d 100644 --- a/src/generated/resources/assets/create/models/item/andesite_encased_cogwheel.json +++ b/src/generated/resources/assets/create/models/item/andesite_encased_cogwheel.json @@ -3,6 +3,7 @@ "textures": { "1": "minecraft:block/stripped_spruce_log_top", "casing": "create:block/andesite_casing", + "particle": "create:block/andesite_casing", "side": "create:block/andesite_encased_cogwheel_side" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/andesite_encased_large_cogwheel.json b/src/generated/resources/assets/create/models/item/andesite_encased_large_cogwheel.json index 57c3142c2..3aa578bf9 100644 --- a/src/generated/resources/assets/create/models/item/andesite_encased_large_cogwheel.json +++ b/src/generated/resources/assets/create/models/item/andesite_encased_large_cogwheel.json @@ -3,6 +3,7 @@ "textures": { "1": "minecraft:block/stripped_spruce_log_top", "casing": "create:block/andesite_casing", + "particle": "create:block/andesite_casing", "side": "create:block/andesite_encased_cogwheel_side_connected" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/andesite_funnel.json b/src/generated/resources/assets/create/models/item/andesite_funnel.json index a0b71f181..081a19fc3 100644 --- a/src/generated/resources/assets/create/models/item/andesite_funnel.json +++ b/src/generated/resources/assets/create/models/item/andesite_funnel.json @@ -1,11 +1,10 @@ { "parent": "create:block/funnel/item", "textures": { - "2": "create:block/andesite_funnel_neutral", - "3": "create:block/andesite_funnel_back", - "5": "create:block/andesite_funnel_tall", - "6": "create:block/andesite_funnel", - "7": "create:block/andesite_funnel_plating", - "particle": "create:block/andesite_casing" + "base": "create:block/funnel/andesite_funnel", + "block": "create:block/andesite_block", + "direction": "create:block/funnel/andesite_funnel_neutral", + "particle": "create:block/andesite_block", + "redstone": "create:block/funnel/andesite_funnel_unpowered" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/andesite_scaffolding.json b/src/generated/resources/assets/create/models/item/andesite_scaffolding.json new file mode 100644 index 000000000..1178fb151 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/andesite_scaffolding.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/andesite_scaffolding" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/andesite_tunnel.json b/src/generated/resources/assets/create/models/item/andesite_tunnel.json index b8a1aa70a..4d658108d 100644 --- a/src/generated/resources/assets/create/models/item/andesite_tunnel.json +++ b/src/generated/resources/assets/create/models/item/andesite_tunnel.json @@ -1,8 +1,10 @@ { "parent": "create:block/belt_tunnel/item", "textures": { - "1": "create:block/andesite_tunnel_top", - "2": "create:block/andesite_tunnel", - "particle": "minecraft:block/polished_andesite" + "direction": "create:block/funnel/andesite_funnel_neutral", + "frame": "create:block/funnel/andesite_funnel_frame", + "particle": "minecraft:block/polished_andesite", + "top": "create:block/tunnel/andesite_tunnel_top", + "tunnel": "create:block/tunnel/andesite_tunnel" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/asurine.json b/src/generated/resources/assets/create/models/item/asurine.json index 777afa919..1075b117c 100644 --- a/src/generated/resources/assets/create/models/item/asurine.json +++ b/src/generated/resources/assets/create/models/item/asurine.json @@ -1,3 +1,6 @@ { - "parent": "create:block/asurine" + "parent": "minecraft:block/cube_all", + "textures": { + "all": "create:block/palettes/stone_types/natural/asurine_1" + } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/attribute_filter.json b/src/generated/resources/assets/create/models/item/attribute_filter.json new file mode 100644 index 000000000..e20fe2e5f --- /dev/null +++ b/src/generated/resources/assets/create/models/item/attribute_filter.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/attribute_filter" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/brass_bars.json b/src/generated/resources/assets/create/models/item/brass_bars.json new file mode 100644 index 000000000..e1b32edd8 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/brass_bars.json @@ -0,0 +1,7 @@ +{ + "parent": "create:item/bars", + "textures": { + "bars": "create:block/bars/brass_bars", + "edge": "create:block/bars/brass_bars_edge" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/brass_door.json b/src/generated/resources/assets/create/models/item/brass_door.json new file mode 100644 index 000000000..814256ba6 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/brass_door.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/brass_door" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/brass_encased_cogwheel.json b/src/generated/resources/assets/create/models/item/brass_encased_cogwheel.json index 06cfabf4f..904d3264c 100644 --- a/src/generated/resources/assets/create/models/item/brass_encased_cogwheel.json +++ b/src/generated/resources/assets/create/models/item/brass_encased_cogwheel.json @@ -3,6 +3,7 @@ "textures": { "1": "minecraft:block/stripped_dark_oak_log_top", "casing": "create:block/brass_casing", + "particle": "create:block/brass_casing", "side": "create:block/brass_encased_cogwheel_side" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/brass_encased_large_cogwheel.json b/src/generated/resources/assets/create/models/item/brass_encased_large_cogwheel.json index d108c78dc..1ace5bb4c 100644 --- a/src/generated/resources/assets/create/models/item/brass_encased_large_cogwheel.json +++ b/src/generated/resources/assets/create/models/item/brass_encased_large_cogwheel.json @@ -3,6 +3,7 @@ "textures": { "1": "minecraft:block/stripped_dark_oak_log_top", "casing": "create:block/brass_casing", + "particle": "create:block/brass_casing", "side": "create:block/brass_encased_cogwheel_side_connected" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/brass_funnel.json b/src/generated/resources/assets/create/models/item/brass_funnel.json index 8512e8f19..1a303367b 100644 --- a/src/generated/resources/assets/create/models/item/brass_funnel.json +++ b/src/generated/resources/assets/create/models/item/brass_funnel.json @@ -1,11 +1,10 @@ { "parent": "create:block/funnel/item", "textures": { - "2": "create:block/brass_funnel_neutral", - "3": "create:block/brass_funnel_back", - "5": "create:block/brass_funnel_tall", - "6": "create:block/brass_funnel", - "7": "create:block/brass_funnel_plating", - "particle": "create:block/brass_casing" + "base": "create:block/funnel/brass_funnel", + "block": "create:block/brass_block", + "direction": "create:block/funnel/brass_funnel_neutral", + "particle": "create:block/brass_block", + "redstone": "create:block/funnel/brass_funnel_unpowered" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/brass_scaffolding.json b/src/generated/resources/assets/create/models/item/brass_scaffolding.json new file mode 100644 index 000000000..94a4c5a95 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/brass_scaffolding.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/brass_scaffolding" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/brass_tunnel.json b/src/generated/resources/assets/create/models/item/brass_tunnel.json index b78dea50b..bfc991f55 100644 --- a/src/generated/resources/assets/create/models/item/brass_tunnel.json +++ b/src/generated/resources/assets/create/models/item/brass_tunnel.json @@ -1,8 +1,10 @@ { "parent": "create:block/belt_tunnel/item", "textures": { - "1": "create:block/brass_tunnel_top", - "2": "create:block/brass_tunnel", - "particle": "create:block/brass_block" + "direction": "create:block/funnel/brass_funnel_neutral", + "frame": "create:block/funnel/brass_funnel_frame", + "particle": "create:block/brass_block", + "top": "create:block/tunnel/brass_tunnel_top", + "tunnel": "create:block/tunnel/brass_tunnel" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/clipboard.json b/src/generated/resources/assets/create/models/item/clipboard.json new file mode 100644 index 000000000..7e7b2234e --- /dev/null +++ b/src/generated/resources/assets/create/models/item/clipboard.json @@ -0,0 +1,26 @@ +{ + "parent": "minecraft:item/generated", + "overrides": [ + { + "model": "create:item/clipboard_0", + "predicate": { + "create:clipboard_type": 0.0 + } + }, + { + "model": "create:item/clipboard_1", + "predicate": { + "create:clipboard_type": 1.0 + } + }, + { + "model": "create:item/clipboard_2", + "predicate": { + "create:clipboard_type": 2.0 + } + } + ], + "textures": { + "layer0": "create:item/clipboard" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/clipboard_0.json b/src/generated/resources/assets/create/models/item/clipboard_0.json new file mode 100644 index 000000000..46f7226fa --- /dev/null +++ b/src/generated/resources/assets/create/models/item/clipboard_0.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/empty_clipboard" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/clipboard_1.json b/src/generated/resources/assets/create/models/item/clipboard_1.json new file mode 100644 index 000000000..ee59b74f7 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/clipboard_1.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/clipboard" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/clipboard_2.json b/src/generated/resources/assets/create/models/item/clipboard_2.json new file mode 100644 index 000000000..a51972bbc --- /dev/null +++ b/src/generated/resources/assets/create/models/item/clipboard_2.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/clipboard_and_quill" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/contraption_controls.json b/src/generated/resources/assets/create/models/item/contraption_controls.json new file mode 100644 index 000000000..07a722d36 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/contraption_controls.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/contraption_controls/item" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/copper_bars.json b/src/generated/resources/assets/create/models/item/copper_bars.json new file mode 100644 index 000000000..66553f12e --- /dev/null +++ b/src/generated/resources/assets/create/models/item/copper_bars.json @@ -0,0 +1,7 @@ +{ + "parent": "create:item/bars", + "textures": { + "bars": "create:block/bars/copper_bars", + "edge": "create:block/bars/copper_bars_edge" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/copper_diving_boots.json b/src/generated/resources/assets/create/models/item/copper_diving_boots.json new file mode 100644 index 000000000..fab121e04 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/copper_diving_boots.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/copper_diving_boots" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/copper_diving_helmet.json b/src/generated/resources/assets/create/models/item/copper_diving_helmet.json new file mode 100644 index 000000000..e21e9b4ee --- /dev/null +++ b/src/generated/resources/assets/create/models/item/copper_diving_helmet.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/copper_diving_helmet" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/copper_door.json b/src/generated/resources/assets/create/models/item/copper_door.json new file mode 100644 index 000000000..8e2e20d3e --- /dev/null +++ b/src/generated/resources/assets/create/models/item/copper_door.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/copper_door" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/copper_scaffolding.json b/src/generated/resources/assets/create/models/item/copper_scaffolding.json new file mode 100644 index 000000000..6908ad367 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/copper_scaffolding.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/copper_scaffolding" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/copycat_panel.json b/src/generated/resources/assets/create/models/item/copycat_panel.json new file mode 100644 index 000000000..5772b8c88 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/copycat_panel.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/copycat_base/panel" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/copycat_step.json b/src/generated/resources/assets/create/models/item/copycat_step.json new file mode 100644 index 000000000..dd2286908 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/copycat_step.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/copycat_base/step" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/crimsite.json b/src/generated/resources/assets/create/models/item/crimsite.json index a55548874..c006ddbf6 100644 --- a/src/generated/resources/assets/create/models/item/crimsite.json +++ b/src/generated/resources/assets/create/models/item/crimsite.json @@ -1,3 +1,6 @@ { - "parent": "create:block/crimsite" + "parent": "minecraft:block/cube_all", + "textures": { + "all": "create:block/palettes/stone_types/natural/crimsite_1" + } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/crushed_aluminum_ore.json b/src/generated/resources/assets/create/models/item/crushed_aluminum_ore.json deleted file mode 100644 index 662060f98..000000000 --- a/src/generated/resources/assets/create/models/item/crushed_aluminum_ore.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "create:item/crushed_aluminum_ore" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/crushed_copper_ore.json b/src/generated/resources/assets/create/models/item/crushed_copper_ore.json deleted file mode 100644 index 500b00124..000000000 --- a/src/generated/resources/assets/create/models/item/crushed_copper_ore.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "create:item/crushed_copper_ore" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/crushed_gold_ore.json b/src/generated/resources/assets/create/models/item/crushed_gold_ore.json deleted file mode 100644 index dc00a3611..000000000 --- a/src/generated/resources/assets/create/models/item/crushed_gold_ore.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "create:item/crushed_gold_ore" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/crushed_iron_ore.json b/src/generated/resources/assets/create/models/item/crushed_iron_ore.json deleted file mode 100644 index 9ac971ece..000000000 --- a/src/generated/resources/assets/create/models/item/crushed_iron_ore.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "create:item/crushed_iron_ore" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/crushed_lead_ore.json b/src/generated/resources/assets/create/models/item/crushed_lead_ore.json deleted file mode 100644 index 1c2c6911b..000000000 --- a/src/generated/resources/assets/create/models/item/crushed_lead_ore.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "create:item/crushed_lead_ore" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/crushed_nickel_ore.json b/src/generated/resources/assets/create/models/item/crushed_nickel_ore.json deleted file mode 100644 index 4a47620f7..000000000 --- a/src/generated/resources/assets/create/models/item/crushed_nickel_ore.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "create:item/crushed_nickel_ore" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/crushed_osmium_ore.json b/src/generated/resources/assets/create/models/item/crushed_osmium_ore.json deleted file mode 100644 index bffaad165..000000000 --- a/src/generated/resources/assets/create/models/item/crushed_osmium_ore.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "create:item/crushed_osmium_ore" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/crushed_platinum_ore.json b/src/generated/resources/assets/create/models/item/crushed_platinum_ore.json deleted file mode 100644 index 6b2d3a4a1..000000000 --- a/src/generated/resources/assets/create/models/item/crushed_platinum_ore.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "create:item/crushed_platinum_ore" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/crushed_quicksilver_ore.json b/src/generated/resources/assets/create/models/item/crushed_quicksilver_ore.json deleted file mode 100644 index 755ae5489..000000000 --- a/src/generated/resources/assets/create/models/item/crushed_quicksilver_ore.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "create:item/crushed_quicksilver_ore" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/crushed_raw_aluminum.json b/src/generated/resources/assets/create/models/item/crushed_raw_aluminum.json new file mode 100644 index 000000000..f5e02b9dc --- /dev/null +++ b/src/generated/resources/assets/create/models/item/crushed_raw_aluminum.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/crushed_raw_aluminum" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/crushed_raw_copper.json b/src/generated/resources/assets/create/models/item/crushed_raw_copper.json new file mode 100644 index 000000000..e5d40a25d --- /dev/null +++ b/src/generated/resources/assets/create/models/item/crushed_raw_copper.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/crushed_raw_copper" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/crushed_raw_gold.json b/src/generated/resources/assets/create/models/item/crushed_raw_gold.json new file mode 100644 index 000000000..fe99490a1 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/crushed_raw_gold.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/crushed_raw_gold" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/crushed_raw_iron.json b/src/generated/resources/assets/create/models/item/crushed_raw_iron.json new file mode 100644 index 000000000..a8daf7cd1 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/crushed_raw_iron.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/crushed_raw_iron" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/crushed_raw_lead.json b/src/generated/resources/assets/create/models/item/crushed_raw_lead.json new file mode 100644 index 000000000..320d9ffe2 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/crushed_raw_lead.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/crushed_raw_lead" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/crushed_raw_nickel.json b/src/generated/resources/assets/create/models/item/crushed_raw_nickel.json new file mode 100644 index 000000000..ef46ce734 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/crushed_raw_nickel.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/crushed_raw_nickel" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/crushed_raw_osmium.json b/src/generated/resources/assets/create/models/item/crushed_raw_osmium.json new file mode 100644 index 000000000..e763e3794 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/crushed_raw_osmium.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/crushed_raw_osmium" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/crushed_raw_platinum.json b/src/generated/resources/assets/create/models/item/crushed_raw_platinum.json new file mode 100644 index 000000000..ce40617e9 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/crushed_raw_platinum.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/crushed_raw_platinum" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/crushed_raw_quicksilver.json b/src/generated/resources/assets/create/models/item/crushed_raw_quicksilver.json new file mode 100644 index 000000000..289805476 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/crushed_raw_quicksilver.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/crushed_raw_quicksilver" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/crushed_raw_silver.json b/src/generated/resources/assets/create/models/item/crushed_raw_silver.json new file mode 100644 index 000000000..a7e28cfbc --- /dev/null +++ b/src/generated/resources/assets/create/models/item/crushed_raw_silver.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/crushed_raw_silver" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/crushed_raw_tin.json b/src/generated/resources/assets/create/models/item/crushed_raw_tin.json new file mode 100644 index 000000000..de7e79455 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/crushed_raw_tin.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/crushed_raw_tin" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/crushed_raw_uranium.json b/src/generated/resources/assets/create/models/item/crushed_raw_uranium.json new file mode 100644 index 000000000..d1e470743 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/crushed_raw_uranium.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/crushed_raw_uranium" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/crushed_raw_zinc.json b/src/generated/resources/assets/create/models/item/crushed_raw_zinc.json new file mode 100644 index 000000000..97a98e7e6 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/crushed_raw_zinc.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/crushed_raw_zinc" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/crushed_silver_ore.json b/src/generated/resources/assets/create/models/item/crushed_silver_ore.json deleted file mode 100644 index 98054fe18..000000000 --- a/src/generated/resources/assets/create/models/item/crushed_silver_ore.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "create:item/crushed_silver_ore" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/crushed_tin_ore.json b/src/generated/resources/assets/create/models/item/crushed_tin_ore.json deleted file mode 100644 index 6e0bb6e65..000000000 --- a/src/generated/resources/assets/create/models/item/crushed_tin_ore.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "create:item/crushed_tin_ore" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/crushed_uranium_ore.json b/src/generated/resources/assets/create/models/item/crushed_uranium_ore.json deleted file mode 100644 index b377d5915..000000000 --- a/src/generated/resources/assets/create/models/item/crushed_uranium_ore.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "create:item/crushed_uranium_ore" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/crushed_zinc_ore.json b/src/generated/resources/assets/create/models/item/crushed_zinc_ore.json deleted file mode 100644 index ee85115fc..000000000 --- a/src/generated/resources/assets/create/models/item/crushed_zinc_ore.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "create:item/crushed_zinc_ore" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/crushing_wheel.json b/src/generated/resources/assets/create/models/item/crushing_wheel.json index 5a8ad3362..872fef2b0 100644 --- a/src/generated/resources/assets/create/models/item/crushing_wheel.json +++ b/src/generated/resources/assets/create/models/item/crushing_wheel.json @@ -1,3 +1,3 @@ { - "parent": "create:block/crushing_wheel" + "parent": "create:block/crushing_wheel/item" } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/diving_boots.json b/src/generated/resources/assets/create/models/item/diving_boots.json deleted file mode 100644 index 88c9dccb5..000000000 --- a/src/generated/resources/assets/create/models/item/diving_boots.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "create:item/diving_boots" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/diving_helmet.json b/src/generated/resources/assets/create/models/item/diving_helmet.json deleted file mode 100644 index f287c2ca8..000000000 --- a/src/generated/resources/assets/create/models/item/diving_helmet.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "create:item/diving_helmet" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/elevator_contact.json b/src/generated/resources/assets/create/models/item/elevator_contact.json new file mode 100644 index 000000000..50fc0dfa9 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/elevator_contact.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/elevator_contact/block" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/elevator_pulley.json b/src/generated/resources/assets/create/models/item/elevator_pulley.json new file mode 100644 index 000000000..df00e5656 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/elevator_pulley.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/elevator_pulley/item" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/experience_block.json b/src/generated/resources/assets/create/models/item/experience_block.json new file mode 100644 index 000000000..450f5d371 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/experience_block.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/experience_block" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/filter.json b/src/generated/resources/assets/create/models/item/filter.json new file mode 100644 index 000000000..584b3303f --- /dev/null +++ b/src/generated/resources/assets/create/models/item/filter.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/filter" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/industrial_iron_block.json b/src/generated/resources/assets/create/models/item/industrial_iron_block.json new file mode 100644 index 000000000..5938f808e --- /dev/null +++ b/src/generated/resources/assets/create/models/item/industrial_iron_block.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/industrial_iron_block" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/large_water_wheel.json b/src/generated/resources/assets/create/models/item/large_water_wheel.json new file mode 100644 index 000000000..e4beac8d7 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/large_water_wheel.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/large_water_wheel/item" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/limestone.json b/src/generated/resources/assets/create/models/item/limestone.json index 450a981f7..4e8cd81fa 100644 --- a/src/generated/resources/assets/create/models/item/limestone.json +++ b/src/generated/resources/assets/create/models/item/limestone.json @@ -1,3 +1,6 @@ { - "parent": "create:block/limestone" + "parent": "minecraft:block/cube_all", + "textures": { + "all": "create:block/palettes/stone_types/limestone" + } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/mangrove_window.json b/src/generated/resources/assets/create/models/item/mangrove_window.json new file mode 100644 index 000000000..5780c9a18 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/mangrove_window.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/mangrove_window" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/mangrove_window_pane.json b/src/generated/resources/assets/create/models/item/mangrove_window_pane.json new file mode 100644 index 000000000..e34b9714e --- /dev/null +++ b/src/generated/resources/assets/create/models/item/mangrove_window_pane.json @@ -0,0 +1,7 @@ +{ + "parent": "create:item/pane", + "textures": { + "edge": "minecraft:block/mangrove_planks", + "pane": "create:block/palettes/mangrove_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/mechanical_roller.json b/src/generated/resources/assets/create/models/item/mechanical_roller.json new file mode 100644 index 000000000..fc689e02a --- /dev/null +++ b/src/generated/resources/assets/create/models/item/mechanical_roller.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/mechanical_roller/item" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/netherite_backtank.json b/src/generated/resources/assets/create/models/item/netherite_backtank.json new file mode 100644 index 000000000..267a98e10 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/netherite_backtank.json @@ -0,0 +1,3 @@ +{ + "parent": "create:block/netherite_backtank/item" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/netherite_backtank_placeable.json b/src/generated/resources/assets/create/models/item/netherite_backtank_placeable.json new file mode 100644 index 000000000..ff77c281b --- /dev/null +++ b/src/generated/resources/assets/create/models/item/netherite_backtank_placeable.json @@ -0,0 +1,3 @@ +{ + "parent": "minecraft:item/barrier" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/netherite_diving_boots.json b/src/generated/resources/assets/create/models/item/netherite_diving_boots.json new file mode 100644 index 000000000..ed1728d3f --- /dev/null +++ b/src/generated/resources/assets/create/models/item/netherite_diving_boots.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/netherite_diving_boots" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/netherite_diving_helmet.json b/src/generated/resources/assets/create/models/item/netherite_diving_helmet.json new file mode 100644 index 000000000..fde66a4b6 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/netherite_diving_helmet.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/netherite_diving_helmet" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/ochrum.json b/src/generated/resources/assets/create/models/item/ochrum.json index 9d6f5b134..c765a7db2 100644 --- a/src/generated/resources/assets/create/models/item/ochrum.json +++ b/src/generated/resources/assets/create/models/item/ochrum.json @@ -1,3 +1,6 @@ { - "parent": "create:block/ochrum" + "parent": "minecraft:block/cube_all", + "textures": { + "all": "create:block/palettes/stone_types/natural/ochrum_1" + } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/scorchia.json b/src/generated/resources/assets/create/models/item/scorchia.json index b4fee0dd1..29730b192 100644 --- a/src/generated/resources/assets/create/models/item/scorchia.json +++ b/src/generated/resources/assets/create/models/item/scorchia.json @@ -1,3 +1,6 @@ { - "parent": "create:block/scorchia" + "parent": "minecraft:block/cube_all", + "textures": { + "all": "create:block/palettes/stone_types/scorchia" + } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/scoria.json b/src/generated/resources/assets/create/models/item/scoria.json index f1fc1af40..cf031beed 100644 --- a/src/generated/resources/assets/create/models/item/scoria.json +++ b/src/generated/resources/assets/create/models/item/scoria.json @@ -1,3 +1,6 @@ { - "parent": "create:block/scoria" + "parent": "minecraft:block/cube_all", + "textures": { + "all": "create:block/palettes/stone_types/scoria" + } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/stockpile_switch.json b/src/generated/resources/assets/create/models/item/stockpile_switch.json index 3e623a7d5..8455dde8b 100644 --- a/src/generated/resources/assets/create/models/item/stockpile_switch.json +++ b/src/generated/resources/assets/create/models/item/stockpile_switch.json @@ -1,3 +1,3 @@ { - "parent": "create:block/stockpile_switch" + "parent": "create:block/threshold_switch/block_wall" } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/veridium.json b/src/generated/resources/assets/create/models/item/veridium.json index 5391052db..52e7c814d 100644 --- a/src/generated/resources/assets/create/models/item/veridium.json +++ b/src/generated/resources/assets/create/models/item/veridium.json @@ -1,3 +1,6 @@ { - "parent": "create:block/veridium" + "parent": "minecraft:block/cube_all", + "textures": { + "all": "create:block/palettes/stone_types/natural/veridium_1" + } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/water_wheel.json b/src/generated/resources/assets/create/models/item/water_wheel.json index 1fe80c21b..5b83b2a7e 100644 --- a/src/generated/resources/assets/create/models/item/water_wheel.json +++ b/src/generated/resources/assets/create/models/item/water_wheel.json @@ -1,3 +1,3 @@ { - "parent": "create:block/water_wheel" + "parent": "create:block/water_wheel/item" } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/windmill_bearing.json b/src/generated/resources/assets/create/models/item/windmill_bearing.json index b38b6ca46..0b2883550 100644 --- a/src/generated/resources/assets/create/models/item/windmill_bearing.json +++ b/src/generated/resources/assets/create/models/item/windmill_bearing.json @@ -3,6 +3,6 @@ "textures": { "back": "create:block/gearbox", "side": "create:block/windmill_bearing_side", - "top": "create:block/bearing_top_wooden" + "top": "create:block/bearing_top" } } \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/threshold_switch/block_ceiling_0.json b/src/generated/resources/assets/create/models/threshold_switch/block_ceiling_0.json new file mode 100644 index 000000000..f5da60e99 --- /dev/null +++ b/src/generated/resources/assets/create/models/threshold_switch/block_ceiling_0.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/threshold_switch/block_ceiling", + "textures": { + "level": "create:block/threshold_switch/level_0" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/threshold_switch/block_ceiling_1.json b/src/generated/resources/assets/create/models/threshold_switch/block_ceiling_1.json new file mode 100644 index 000000000..77d321740 --- /dev/null +++ b/src/generated/resources/assets/create/models/threshold_switch/block_ceiling_1.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/threshold_switch/block_ceiling", + "textures": { + "level": "create:block/threshold_switch/level_1" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/threshold_switch/block_ceiling_2.json b/src/generated/resources/assets/create/models/threshold_switch/block_ceiling_2.json new file mode 100644 index 000000000..041c46a2d --- /dev/null +++ b/src/generated/resources/assets/create/models/threshold_switch/block_ceiling_2.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/threshold_switch/block_ceiling", + "textures": { + "level": "create:block/threshold_switch/level_2" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/threshold_switch/block_ceiling_3.json b/src/generated/resources/assets/create/models/threshold_switch/block_ceiling_3.json new file mode 100644 index 000000000..8ccaf704a --- /dev/null +++ b/src/generated/resources/assets/create/models/threshold_switch/block_ceiling_3.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/threshold_switch/block_ceiling", + "textures": { + "level": "create:block/threshold_switch/level_3" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/threshold_switch/block_ceiling_4.json b/src/generated/resources/assets/create/models/threshold_switch/block_ceiling_4.json new file mode 100644 index 000000000..fc36e6d52 --- /dev/null +++ b/src/generated/resources/assets/create/models/threshold_switch/block_ceiling_4.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/threshold_switch/block_ceiling", + "textures": { + "level": "create:block/threshold_switch/level_4" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/threshold_switch/block_ceiling_5.json b/src/generated/resources/assets/create/models/threshold_switch/block_ceiling_5.json new file mode 100644 index 000000000..b708eae93 --- /dev/null +++ b/src/generated/resources/assets/create/models/threshold_switch/block_ceiling_5.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/threshold_switch/block_ceiling", + "textures": { + "level": "create:block/threshold_switch/level_5" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/threshold_switch/block_floor_0.json b/src/generated/resources/assets/create/models/threshold_switch/block_floor_0.json new file mode 100644 index 000000000..2fff31978 --- /dev/null +++ b/src/generated/resources/assets/create/models/threshold_switch/block_floor_0.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/threshold_switch/block_floor", + "textures": { + "level": "create:block/threshold_switch/level_0" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/threshold_switch/block_floor_1.json b/src/generated/resources/assets/create/models/threshold_switch/block_floor_1.json new file mode 100644 index 000000000..9ecd2edad --- /dev/null +++ b/src/generated/resources/assets/create/models/threshold_switch/block_floor_1.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/threshold_switch/block_floor", + "textures": { + "level": "create:block/threshold_switch/level_1" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/threshold_switch/block_floor_2.json b/src/generated/resources/assets/create/models/threshold_switch/block_floor_2.json new file mode 100644 index 000000000..f9fa8d137 --- /dev/null +++ b/src/generated/resources/assets/create/models/threshold_switch/block_floor_2.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/threshold_switch/block_floor", + "textures": { + "level": "create:block/threshold_switch/level_2" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/threshold_switch/block_floor_3.json b/src/generated/resources/assets/create/models/threshold_switch/block_floor_3.json new file mode 100644 index 000000000..116663358 --- /dev/null +++ b/src/generated/resources/assets/create/models/threshold_switch/block_floor_3.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/threshold_switch/block_floor", + "textures": { + "level": "create:block/threshold_switch/level_3" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/threshold_switch/block_floor_4.json b/src/generated/resources/assets/create/models/threshold_switch/block_floor_4.json new file mode 100644 index 000000000..b2e82e522 --- /dev/null +++ b/src/generated/resources/assets/create/models/threshold_switch/block_floor_4.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/threshold_switch/block_floor", + "textures": { + "level": "create:block/threshold_switch/level_4" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/threshold_switch/block_floor_5.json b/src/generated/resources/assets/create/models/threshold_switch/block_floor_5.json new file mode 100644 index 000000000..7a8bc7ac3 --- /dev/null +++ b/src/generated/resources/assets/create/models/threshold_switch/block_floor_5.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/threshold_switch/block_floor", + "textures": { + "level": "create:block/threshold_switch/level_5" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/threshold_switch/block_wall_0.json b/src/generated/resources/assets/create/models/threshold_switch/block_wall_0.json new file mode 100644 index 000000000..e602f46ef --- /dev/null +++ b/src/generated/resources/assets/create/models/threshold_switch/block_wall_0.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/threshold_switch/block_wall", + "textures": { + "level": "create:block/threshold_switch/level_0" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/threshold_switch/block_wall_1.json b/src/generated/resources/assets/create/models/threshold_switch/block_wall_1.json new file mode 100644 index 000000000..f4fa237f5 --- /dev/null +++ b/src/generated/resources/assets/create/models/threshold_switch/block_wall_1.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/threshold_switch/block_wall", + "textures": { + "level": "create:block/threshold_switch/level_1" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/threshold_switch/block_wall_2.json b/src/generated/resources/assets/create/models/threshold_switch/block_wall_2.json new file mode 100644 index 000000000..7c489af9c --- /dev/null +++ b/src/generated/resources/assets/create/models/threshold_switch/block_wall_2.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/threshold_switch/block_wall", + "textures": { + "level": "create:block/threshold_switch/level_2" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/threshold_switch/block_wall_3.json b/src/generated/resources/assets/create/models/threshold_switch/block_wall_3.json new file mode 100644 index 000000000..1ac6d64dd --- /dev/null +++ b/src/generated/resources/assets/create/models/threshold_switch/block_wall_3.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/threshold_switch/block_wall", + "textures": { + "level": "create:block/threshold_switch/level_3" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/threshold_switch/block_wall_4.json b/src/generated/resources/assets/create/models/threshold_switch/block_wall_4.json new file mode 100644 index 000000000..79047ddc6 --- /dev/null +++ b/src/generated/resources/assets/create/models/threshold_switch/block_wall_4.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/threshold_switch/block_wall", + "textures": { + "level": "create:block/threshold_switch/level_4" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/threshold_switch/block_wall_5.json b/src/generated/resources/assets/create/models/threshold_switch/block_wall_5.json new file mode 100644 index 000000000..8e5ea3d59 --- /dev/null +++ b/src/generated/resources/assets/create/models/threshold_switch/block_wall_5.json @@ -0,0 +1,6 @@ +{ + "parent": "create:block/threshold_switch/block_wall", + "textures": { + "level": "create:block/threshold_switch/level_5" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/diving_suit.json b/src/generated/resources/data/create/advancements/diving_suit.json index f987840bd..41f3ef6c3 100644 --- a/src/generated/resources/data/create/advancements/diving_suit.json +++ b/src/generated/resources/data/create/advancements/diving_suit.json @@ -15,7 +15,7 @@ "frame": "task", "hidden": false, "icon": { - "item": "create:diving_helmet", + "item": "create:copper_diving_helmet", "nbt": "{Damage:0}" }, "show_toast": true, diff --git a/src/generated/resources/data/create/advancements/diving_suit_lava.json b/src/generated/resources/data/create/advancements/diving_suit_lava.json index a41b439f1..219d764a8 100644 --- a/src/generated/resources/data/create/advancements/diving_suit_lava.json +++ b/src/generated/resources/data/create/advancements/diving_suit_lava.json @@ -15,7 +15,7 @@ "frame": "goal", "hidden": true, "icon": { - "item": "create:diving_helmet", + "item": "create:copper_diving_helmet", "nbt": "{Damage:0}" }, "show_toast": true, diff --git a/src/generated/resources/data/create/advancements/long_bend.json b/src/generated/resources/data/create/advancements/long_bend.json deleted file mode 100644 index f37ffbaa7..000000000 --- a/src/generated/resources/data/create/advancements/long_bend.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "parent": "create:track_crafting_factory", - "criteria": { - "0": { - "conditions": {}, - "trigger": "create:long_bend_builtin" - } - }, - "display": { - "announce_to_chat": true, - "description": { - "color": "#DBA213", - "translate": "advancement.create.long_bend.desc" - }, - "frame": "goal", - "hidden": false, - "icon": { - "item": "create:track" - }, - "show_toast": true, - "title": { - "translate": "advancement.create.long_bend" - } - }, - "requirements": [ - [ - "0" - ] - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/long_train.json b/src/generated/resources/data/create/advancements/long_train.json index 80e4d4477..6c6ec5b2b 100644 --- a/src/generated/resources/data/create/advancements/long_train.json +++ b/src/generated/resources/data/create/advancements/long_train.json @@ -1,5 +1,5 @@ { - "parent": "create:long_bend", + "parent": "create:track_crafting_factory", "criteria": { "0": { "conditions": {}, diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/andesite_from_stone_types_andesite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/andesite_from_stone_types_andesite_stonecutting.json new file mode 100644 index 000000000..a7896b0bf --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/andesite_from_stone_types_andesite_stonecutting.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_stone_types_andesite": { + "conditions": { + "items": [ + { + "tag": "create:stone_types/andesite" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:andesite_from_stone_types_andesite_stonecutting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_stone_types_andesite", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:andesite_from_stone_types_andesite_stonecutting" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/andesite_pillar_from_andesite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/andesite_pillar_from_andesite_stonecutting.json deleted file mode 100644 index f57e8f8a6..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/andesite_pillar_from_andesite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_andesite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:andesite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:andesite_pillar_from_andesite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_andesite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:andesite_pillar_from_andesite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/asurine_from_stone_types_asurine_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/asurine_from_stone_types_asurine_stonecutting.json new file mode 100644 index 000000000..bec60fbbe --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/asurine_from_stone_types_asurine_stonecutting.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_stone_types_asurine": { + "conditions": { + "items": [ + { + "tag": "create:stone_types/asurine" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:asurine_from_stone_types_asurine_stonecutting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_stone_types_asurine", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:asurine_from_stone_types_asurine_stonecutting" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/asurine_pillar_from_asurine_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/asurine_pillar_from_asurine_stonecutting.json deleted file mode 100644 index 925890cc5..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/asurine_pillar_from_asurine_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_asurine": { - "conditions": { - "items": [ - { - "items": [ - "create:asurine" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:asurine_pillar_from_asurine_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_asurine", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:asurine_pillar_from_asurine_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/calcite_from_stone_types_calcite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/calcite_from_stone_types_calcite_stonecutting.json new file mode 100644 index 000000000..3c3e680c1 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/calcite_from_stone_types_calcite_stonecutting.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_stone_types_calcite": { + "conditions": { + "items": [ + { + "tag": "create:stone_types/calcite" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:calcite_from_stone_types_calcite_stonecutting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_stone_types_calcite", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:calcite_from_stone_types_calcite_stonecutting" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/calcite_pillar_from_calcite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/calcite_pillar_from_calcite_stonecutting.json deleted file mode 100644 index fe023557a..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/calcite_pillar_from_calcite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_calcite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:calcite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:calcite_pillar_from_calcite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_calcite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:calcite_pillar_from_calcite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/copper_shingles_from_ingots_copper_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/copper_shingles_from_ingots_copper_stonecutting.json new file mode 100644 index 000000000..05d4b0a1b --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/copper_shingles_from_ingots_copper_stonecutting.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_ingots_copper": { + "conditions": { + "items": [ + { + "tag": "forge:ingots/copper" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:copper_shingles_from_ingots_copper_stonecutting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_ingots_copper", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:copper_shingles_from_ingots_copper_stonecutting" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/copper_shingles_from_plates_copper_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/copper_shingles_from_plates_copper_stonecutting.json deleted file mode 100644 index dfa9a85aa..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/copper_shingles_from_plates_copper_stonecutting.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_plates_copper": { - "conditions": { - "items": [ - { - "tag": "forge:plates/copper" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:copper_shingles_from_plates_copper_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_plates_copper", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:copper_shingles_from_plates_copper_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/copper_tiles_from_ingots_copper_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/copper_tiles_from_ingots_copper_stonecutting.json new file mode 100644 index 000000000..becef66ac --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/copper_tiles_from_ingots_copper_stonecutting.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_ingots_copper": { + "conditions": { + "items": [ + { + "tag": "forge:ingots/copper" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:copper_tiles_from_ingots_copper_stonecutting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_ingots_copper", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:copper_tiles_from_ingots_copper_stonecutting" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/copper_tiles_from_plates_copper_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/copper_tiles_from_plates_copper_stonecutting.json deleted file mode 100644 index 26104a1dd..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/copper_tiles_from_plates_copper_stonecutting.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_plates_copper": { - "conditions": { - "items": [ - { - "tag": "forge:plates/copper" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:copper_tiles_from_plates_copper_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_plates_copper", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:copper_tiles_from_plates_copper_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/copycat_panel_from_ingots_zinc_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/copycat_panel_from_ingots_zinc_stonecutting.json new file mode 100644 index 000000000..398dc8671 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/copycat_panel_from_ingots_zinc_stonecutting.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_ingots_zinc": { + "conditions": { + "items": [ + { + "tag": "forge:ingots/zinc" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:copycat_panel_from_ingots_zinc_stonecutting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_ingots_zinc", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:copycat_panel_from_ingots_zinc_stonecutting" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/copycat_step_from_ingots_zinc_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/copycat_step_from_ingots_zinc_stonecutting.json new file mode 100644 index 000000000..2004119c6 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/copycat_step_from_ingots_zinc_stonecutting.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_ingots_zinc": { + "conditions": { + "items": [ + { + "tag": "forge:ingots/zinc" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:copycat_step_from_ingots_zinc_stonecutting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_ingots_zinc", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:copycat_step_from_ingots_zinc_stonecutting" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/black_seat.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/black_seat.json similarity index 100% rename from src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/black_seat.json rename to src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/black_seat.json diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/black_seat_from_other_seat.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/black_seat_from_other_seat.json similarity index 100% rename from src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/black_seat_from_other_seat.json rename to src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/black_seat_from_other_seat.json diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/blue_seat.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/blue_seat.json similarity index 100% rename from src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/blue_seat.json rename to src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/blue_seat.json diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/blue_seat_from_other_seat.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/blue_seat_from_other_seat.json similarity index 100% rename from src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/blue_seat_from_other_seat.json rename to src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/blue_seat_from_other_seat.json diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/brown_seat.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/brown_seat.json similarity index 100% rename from src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/brown_seat.json rename to src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/brown_seat.json diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/brown_seat_from_other_seat.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/brown_seat_from_other_seat.json similarity index 100% rename from src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/brown_seat_from_other_seat.json rename to src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/brown_seat_from_other_seat.json diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/cyan_seat.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/cyan_seat.json similarity index 100% rename from src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/cyan_seat.json rename to src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/cyan_seat.json diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/cyan_seat_from_other_seat.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/cyan_seat_from_other_seat.json similarity index 100% rename from src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/cyan_seat_from_other_seat.json rename to src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/cyan_seat_from_other_seat.json diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/gray_seat.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/gray_seat.json similarity index 100% rename from src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/gray_seat.json rename to src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/gray_seat.json diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/gray_seat_from_other_seat.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/gray_seat_from_other_seat.json similarity index 100% rename from src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/gray_seat_from_other_seat.json rename to src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/gray_seat_from_other_seat.json diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/green_seat.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/green_seat.json similarity index 100% rename from src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/green_seat.json rename to src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/green_seat.json diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/green_seat_from_other_seat.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/green_seat_from_other_seat.json similarity index 100% rename from src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/green_seat_from_other_seat.json rename to src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/green_seat_from_other_seat.json diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/light_blue_seat.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/light_blue_seat.json similarity index 100% rename from src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/light_blue_seat.json rename to src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/light_blue_seat.json diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/light_blue_seat_from_other_seat.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/light_blue_seat_from_other_seat.json similarity index 100% rename from src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/light_blue_seat_from_other_seat.json rename to src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/light_blue_seat_from_other_seat.json diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/light_gray_seat.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/light_gray_seat.json similarity index 100% rename from src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/light_gray_seat.json rename to src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/light_gray_seat.json diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/light_gray_seat_from_other_seat.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/light_gray_seat_from_other_seat.json similarity index 100% rename from src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/light_gray_seat_from_other_seat.json rename to src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/light_gray_seat_from_other_seat.json diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/lime_seat.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/lime_seat.json similarity index 100% rename from src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/lime_seat.json rename to src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/lime_seat.json diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/lime_seat_from_other_seat.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/lime_seat_from_other_seat.json similarity index 100% rename from src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/lime_seat_from_other_seat.json rename to src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/lime_seat_from_other_seat.json diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/magenta_seat.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/magenta_seat.json similarity index 100% rename from src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/magenta_seat.json rename to src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/magenta_seat.json diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/magenta_seat_from_other_seat.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/magenta_seat_from_other_seat.json similarity index 100% rename from src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/magenta_seat_from_other_seat.json rename to src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/magenta_seat_from_other_seat.json diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/orange_seat.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/orange_seat.json similarity index 100% rename from src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/orange_seat.json rename to src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/orange_seat.json diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/orange_seat_from_other_seat.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/orange_seat_from_other_seat.json similarity index 100% rename from src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/orange_seat_from_other_seat.json rename to src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/orange_seat_from_other_seat.json diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/pink_seat.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/pink_seat.json similarity index 100% rename from src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/pink_seat.json rename to src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/pink_seat.json diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/pink_seat_from_other_seat.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/pink_seat_from_other_seat.json similarity index 100% rename from src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/pink_seat_from_other_seat.json rename to src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/pink_seat_from_other_seat.json diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/purple_seat.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/purple_seat.json similarity index 100% rename from src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/purple_seat.json rename to src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/purple_seat.json diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/purple_seat_from_other_seat.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/purple_seat_from_other_seat.json similarity index 100% rename from src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/purple_seat_from_other_seat.json rename to src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/purple_seat_from_other_seat.json diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/red_seat.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/red_seat.json similarity index 100% rename from src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/red_seat.json rename to src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/red_seat.json diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/red_seat_from_other_seat.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/red_seat_from_other_seat.json similarity index 100% rename from src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/red_seat_from_other_seat.json rename to src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/red_seat_from_other_seat.json diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/white_seat.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/white_seat.json similarity index 100% rename from src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/white_seat.json rename to src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/white_seat.json diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/white_seat_from_other_seat.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/white_seat_from_other_seat.json similarity index 100% rename from src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/white_seat_from_other_seat.json rename to src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/white_seat_from_other_seat.json diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/yellow_seat.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/yellow_seat.json similarity index 100% rename from src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/yellow_seat.json rename to src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/yellow_seat.json diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/yellow_seat_from_other_seat.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/yellow_seat_from_other_seat.json similarity index 100% rename from src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/yellow_seat_from_other_seat.json rename to src/generated/resources/data/create/advancements/recipes/building_blocks/crafting/kinetics/yellow_seat_from_other_seat.json diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crimsite_from_stone_types_crimsite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crimsite_from_stone_types_crimsite_stonecutting.json new file mode 100644 index 000000000..e4e05d97d --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/crimsite_from_stone_types_crimsite_stonecutting.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_stone_types_crimsite": { + "conditions": { + "items": [ + { + "tag": "create:stone_types/crimsite" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crimsite_from_stone_types_crimsite_stonecutting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_stone_types_crimsite", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crimsite_from_stone_types_crimsite_stonecutting" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/crimsite_pillar_from_crimsite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/crimsite_pillar_from_crimsite_stonecutting.json deleted file mode 100644 index 0470967bf..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/crimsite_pillar_from_crimsite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_crimsite": { - "conditions": { - "items": [ - { - "items": [ - "create:crimsite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:crimsite_pillar_from_crimsite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_crimsite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:crimsite_pillar_from_crimsite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_andesite_brick_slab_from_andesite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_andesite_brick_slab_from_andesite_stonecutting.json deleted file mode 100644 index 1eb17f6c1..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_andesite_brick_slab_from_andesite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_andesite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:andesite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_andesite_brick_slab_from_andesite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_andesite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_andesite_brick_slab_from_andesite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_andesite_brick_stairs_from_andesite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_andesite_brick_stairs_from_andesite_stonecutting.json deleted file mode 100644 index 5900d1531..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_andesite_brick_stairs_from_andesite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_andesite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:andesite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_andesite_brick_stairs_from_andesite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_andesite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_andesite_brick_stairs_from_andesite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_andesite_brick_wall_from_andesite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_andesite_brick_wall_from_andesite_stonecutting.json deleted file mode 100644 index 62f79e123..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_andesite_brick_wall_from_andesite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_andesite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:andesite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_andesite_brick_wall_from_andesite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_andesite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_andesite_brick_wall_from_andesite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_andesite_bricks_from_andesite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_andesite_bricks_from_andesite_stonecutting.json deleted file mode 100644 index fc4ec7fc7..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_andesite_bricks_from_andesite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_andesite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:andesite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_andesite_bricks_from_andesite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_andesite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_andesite_bricks_from_andesite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_andesite_from_andesite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_andesite_from_andesite_stonecutting.json deleted file mode 100644 index ec026598e..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_andesite_from_andesite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_andesite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:andesite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_andesite_from_andesite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_andesite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_andesite_from_andesite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_andesite_slab_from_andesite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_andesite_slab_from_andesite_stonecutting.json deleted file mode 100644 index 6d84564d8..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_andesite_slab_from_andesite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_andesite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:andesite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_andesite_slab_from_andesite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_andesite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_andesite_slab_from_andesite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_andesite_stairs_from_andesite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_andesite_stairs_from_andesite_stonecutting.json deleted file mode 100644 index aaf4c0c21..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_andesite_stairs_from_andesite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_andesite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:andesite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_andesite_stairs_from_andesite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_andesite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_andesite_stairs_from_andesite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_andesite_wall_from_andesite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_andesite_wall_from_andesite_stonecutting.json deleted file mode 100644 index d48146f92..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_andesite_wall_from_andesite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_andesite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:andesite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_andesite_wall_from_andesite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_andesite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_andesite_wall_from_andesite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_asurine_brick_slab_from_asurine_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_asurine_brick_slab_from_asurine_stonecutting.json deleted file mode 100644 index 85babc1ec..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_asurine_brick_slab_from_asurine_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_asurine": { - "conditions": { - "items": [ - { - "items": [ - "create:asurine" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_asurine_brick_slab_from_asurine_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_asurine", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_asurine_brick_slab_from_asurine_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_asurine_brick_stairs_from_asurine_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_asurine_brick_stairs_from_asurine_stonecutting.json deleted file mode 100644 index d0eddbc57..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_asurine_brick_stairs_from_asurine_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_asurine": { - "conditions": { - "items": [ - { - "items": [ - "create:asurine" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_asurine_brick_stairs_from_asurine_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_asurine", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_asurine_brick_stairs_from_asurine_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_asurine_brick_wall_from_asurine_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_asurine_brick_wall_from_asurine_stonecutting.json deleted file mode 100644 index 8861b32ec..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_asurine_brick_wall_from_asurine_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_asurine": { - "conditions": { - "items": [ - { - "items": [ - "create:asurine" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_asurine_brick_wall_from_asurine_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_asurine", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_asurine_brick_wall_from_asurine_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_asurine_bricks_from_asurine_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_asurine_bricks_from_asurine_stonecutting.json deleted file mode 100644 index 945738ec2..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_asurine_bricks_from_asurine_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_asurine": { - "conditions": { - "items": [ - { - "items": [ - "create:asurine" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_asurine_bricks_from_asurine_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_asurine", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_asurine_bricks_from_asurine_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_asurine_from_asurine_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_asurine_from_asurine_stonecutting.json deleted file mode 100644 index 08186fbb8..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_asurine_from_asurine_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_asurine": { - "conditions": { - "items": [ - { - "items": [ - "create:asurine" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_asurine_from_asurine_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_asurine", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_asurine_from_asurine_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_asurine_slab_from_asurine_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_asurine_slab_from_asurine_stonecutting.json deleted file mode 100644 index d7f754df4..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_asurine_slab_from_asurine_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_asurine": { - "conditions": { - "items": [ - { - "items": [ - "create:asurine" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_asurine_slab_from_asurine_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_asurine", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_asurine_slab_from_asurine_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_asurine_stairs_from_asurine_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_asurine_stairs_from_asurine_stonecutting.json deleted file mode 100644 index 94e6cdc5c..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_asurine_stairs_from_asurine_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_asurine": { - "conditions": { - "items": [ - { - "items": [ - "create:asurine" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_asurine_stairs_from_asurine_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_asurine", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_asurine_stairs_from_asurine_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_asurine_wall_from_asurine_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_asurine_wall_from_asurine_stonecutting.json deleted file mode 100644 index 9fc6f77a8..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_asurine_wall_from_asurine_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_asurine": { - "conditions": { - "items": [ - { - "items": [ - "create:asurine" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_asurine_wall_from_asurine_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_asurine", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_asurine_wall_from_asurine_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_calcite_brick_slab_from_calcite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_calcite_brick_slab_from_calcite_stonecutting.json deleted file mode 100644 index c041d8b79..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_calcite_brick_slab_from_calcite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_calcite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:calcite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_calcite_brick_slab_from_calcite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_calcite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_calcite_brick_slab_from_calcite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_calcite_brick_stairs_from_calcite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_calcite_brick_stairs_from_calcite_stonecutting.json deleted file mode 100644 index 6ae2fb40d..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_calcite_brick_stairs_from_calcite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_calcite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:calcite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_calcite_brick_stairs_from_calcite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_calcite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_calcite_brick_stairs_from_calcite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_calcite_brick_wall_from_calcite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_calcite_brick_wall_from_calcite_stonecutting.json deleted file mode 100644 index 06016435b..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_calcite_brick_wall_from_calcite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_calcite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:calcite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_calcite_brick_wall_from_calcite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_calcite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_calcite_brick_wall_from_calcite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_calcite_bricks_from_calcite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_calcite_bricks_from_calcite_stonecutting.json deleted file mode 100644 index 96ef10432..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_calcite_bricks_from_calcite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_calcite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:calcite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_calcite_bricks_from_calcite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_calcite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_calcite_bricks_from_calcite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_calcite_from_calcite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_calcite_from_calcite_stonecutting.json deleted file mode 100644 index 727371d90..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_calcite_from_calcite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_calcite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:calcite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_calcite_from_calcite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_calcite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_calcite_from_calcite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_calcite_slab_from_calcite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_calcite_slab_from_calcite_stonecutting.json deleted file mode 100644 index 0390c0d0c..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_calcite_slab_from_calcite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_calcite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:calcite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_calcite_slab_from_calcite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_calcite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_calcite_slab_from_calcite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_calcite_stairs_from_calcite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_calcite_stairs_from_calcite_stonecutting.json deleted file mode 100644 index 1ef72d994..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_calcite_stairs_from_calcite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_calcite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:calcite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_calcite_stairs_from_calcite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_calcite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_calcite_stairs_from_calcite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_calcite_wall_from_calcite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_calcite_wall_from_calcite_stonecutting.json deleted file mode 100644 index 5fc94f0c0..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_calcite_wall_from_calcite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_calcite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:calcite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_calcite_wall_from_calcite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_calcite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_calcite_wall_from_calcite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_crimsite_brick_slab_from_crimsite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_crimsite_brick_slab_from_crimsite_stonecutting.json deleted file mode 100644 index 73eb3f615..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_crimsite_brick_slab_from_crimsite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_crimsite": { - "conditions": { - "items": [ - { - "items": [ - "create:crimsite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_crimsite_brick_slab_from_crimsite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_crimsite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_crimsite_brick_slab_from_crimsite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_crimsite_brick_stairs_from_crimsite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_crimsite_brick_stairs_from_crimsite_stonecutting.json deleted file mode 100644 index fc515686b..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_crimsite_brick_stairs_from_crimsite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_crimsite": { - "conditions": { - "items": [ - { - "items": [ - "create:crimsite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_crimsite_brick_stairs_from_crimsite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_crimsite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_crimsite_brick_stairs_from_crimsite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_crimsite_brick_wall_from_crimsite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_crimsite_brick_wall_from_crimsite_stonecutting.json deleted file mode 100644 index c42a2d642..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_crimsite_brick_wall_from_crimsite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_crimsite": { - "conditions": { - "items": [ - { - "items": [ - "create:crimsite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_crimsite_brick_wall_from_crimsite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_crimsite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_crimsite_brick_wall_from_crimsite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_crimsite_bricks_from_crimsite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_crimsite_bricks_from_crimsite_stonecutting.json deleted file mode 100644 index d4c15fad2..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_crimsite_bricks_from_crimsite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_crimsite": { - "conditions": { - "items": [ - { - "items": [ - "create:crimsite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_crimsite_bricks_from_crimsite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_crimsite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_crimsite_bricks_from_crimsite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_crimsite_from_crimsite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_crimsite_from_crimsite_stonecutting.json deleted file mode 100644 index 4f65d5acc..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_crimsite_from_crimsite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_crimsite": { - "conditions": { - "items": [ - { - "items": [ - "create:crimsite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_crimsite_from_crimsite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_crimsite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_crimsite_from_crimsite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_crimsite_slab_from_crimsite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_crimsite_slab_from_crimsite_stonecutting.json deleted file mode 100644 index 19fc630bb..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_crimsite_slab_from_crimsite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_crimsite": { - "conditions": { - "items": [ - { - "items": [ - "create:crimsite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_crimsite_slab_from_crimsite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_crimsite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_crimsite_slab_from_crimsite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_crimsite_stairs_from_crimsite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_crimsite_stairs_from_crimsite_stonecutting.json deleted file mode 100644 index d90701de2..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_crimsite_stairs_from_crimsite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_crimsite": { - "conditions": { - "items": [ - { - "items": [ - "create:crimsite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_crimsite_stairs_from_crimsite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_crimsite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_crimsite_stairs_from_crimsite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_crimsite_wall_from_crimsite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_crimsite_wall_from_crimsite_stonecutting.json deleted file mode 100644 index 8cd0446a4..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_crimsite_wall_from_crimsite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_crimsite": { - "conditions": { - "items": [ - { - "items": [ - "create:crimsite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_crimsite_wall_from_crimsite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_crimsite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_crimsite_wall_from_crimsite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_deepslate_brick_slab_from_deepslate_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_deepslate_brick_slab_from_deepslate_stonecutting.json deleted file mode 100644 index 1c7f91949..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_deepslate_brick_slab_from_deepslate_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_deepslate": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:deepslate" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_deepslate_brick_slab_from_deepslate_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_deepslate", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_deepslate_brick_slab_from_deepslate_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_deepslate_brick_stairs_from_deepslate_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_deepslate_brick_stairs_from_deepslate_stonecutting.json deleted file mode 100644 index e7f854c5d..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_deepslate_brick_stairs_from_deepslate_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_deepslate": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:deepslate" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_deepslate_brick_stairs_from_deepslate_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_deepslate", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_deepslate_brick_stairs_from_deepslate_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_deepslate_brick_wall_from_deepslate_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_deepslate_brick_wall_from_deepslate_stonecutting.json deleted file mode 100644 index 109dc8c7d..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_deepslate_brick_wall_from_deepslate_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_deepslate": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:deepslate" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_deepslate_brick_wall_from_deepslate_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_deepslate", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_deepslate_brick_wall_from_deepslate_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_deepslate_bricks_from_deepslate_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_deepslate_bricks_from_deepslate_stonecutting.json deleted file mode 100644 index 2ec454495..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_deepslate_bricks_from_deepslate_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_deepslate": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:deepslate" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_deepslate_bricks_from_deepslate_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_deepslate", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_deepslate_bricks_from_deepslate_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_deepslate_from_deepslate_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_deepslate_from_deepslate_stonecutting.json deleted file mode 100644 index 3c594b96c..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_deepslate_from_deepslate_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_deepslate": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:deepslate" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_deepslate_from_deepslate_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_deepslate", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_deepslate_from_deepslate_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_deepslate_slab_from_deepslate_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_deepslate_slab_from_deepslate_stonecutting.json deleted file mode 100644 index 89c7616d0..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_deepslate_slab_from_deepslate_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_deepslate": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:deepslate" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_deepslate_slab_from_deepslate_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_deepslate", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_deepslate_slab_from_deepslate_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_deepslate_stairs_from_deepslate_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_deepslate_stairs_from_deepslate_stonecutting.json deleted file mode 100644 index 585f9c679..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_deepslate_stairs_from_deepslate_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_deepslate": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:deepslate" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_deepslate_stairs_from_deepslate_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_deepslate", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_deepslate_stairs_from_deepslate_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_deepslate_wall_from_deepslate_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_deepslate_wall_from_deepslate_stonecutting.json deleted file mode 100644 index 96881e8a5..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_deepslate_wall_from_deepslate_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_deepslate": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:deepslate" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_deepslate_wall_from_deepslate_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_deepslate", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_deepslate_wall_from_deepslate_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_diorite_brick_slab_from_diorite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_diorite_brick_slab_from_diorite_stonecutting.json deleted file mode 100644 index c97f9619d..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_diorite_brick_slab_from_diorite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_diorite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:diorite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_diorite_brick_slab_from_diorite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_diorite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_diorite_brick_slab_from_diorite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_diorite_brick_stairs_from_diorite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_diorite_brick_stairs_from_diorite_stonecutting.json deleted file mode 100644 index c35c1d97c..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_diorite_brick_stairs_from_diorite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_diorite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:diorite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_diorite_brick_stairs_from_diorite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_diorite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_diorite_brick_stairs_from_diorite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_diorite_brick_wall_from_diorite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_diorite_brick_wall_from_diorite_stonecutting.json deleted file mode 100644 index 6285b8e7a..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_diorite_brick_wall_from_diorite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_diorite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:diorite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_diorite_brick_wall_from_diorite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_diorite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_diorite_brick_wall_from_diorite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_diorite_bricks_from_diorite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_diorite_bricks_from_diorite_stonecutting.json deleted file mode 100644 index 860f30685..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_diorite_bricks_from_diorite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_diorite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:diorite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_diorite_bricks_from_diorite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_diorite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_diorite_bricks_from_diorite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_diorite_from_diorite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_diorite_from_diorite_stonecutting.json deleted file mode 100644 index 53a9edd06..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_diorite_from_diorite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_diorite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:diorite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_diorite_from_diorite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_diorite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_diorite_from_diorite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_diorite_slab_from_diorite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_diorite_slab_from_diorite_stonecutting.json deleted file mode 100644 index 81aa26ee9..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_diorite_slab_from_diorite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_diorite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:diorite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_diorite_slab_from_diorite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_diorite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_diorite_slab_from_diorite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_diorite_stairs_from_diorite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_diorite_stairs_from_diorite_stonecutting.json deleted file mode 100644 index bdf3e69ee..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_diorite_stairs_from_diorite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_diorite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:diorite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_diorite_stairs_from_diorite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_diorite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_diorite_stairs_from_diorite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_diorite_wall_from_diorite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_diorite_wall_from_diorite_stonecutting.json deleted file mode 100644 index 77c8dd896..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_diorite_wall_from_diorite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_diorite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:diorite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_diorite_wall_from_diorite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_diorite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_diorite_wall_from_diorite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_dripstone_brick_slab_from_dripstone_block_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_dripstone_brick_slab_from_dripstone_block_stonecutting.json deleted file mode 100644 index 568e53d01..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_dripstone_brick_slab_from_dripstone_block_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_dripstone_block": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:dripstone_block" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_dripstone_brick_slab_from_dripstone_block_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_dripstone_block", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_dripstone_brick_slab_from_dripstone_block_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_dripstone_brick_stairs_from_dripstone_block_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_dripstone_brick_stairs_from_dripstone_block_stonecutting.json deleted file mode 100644 index 5cc1dae01..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_dripstone_brick_stairs_from_dripstone_block_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_dripstone_block": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:dripstone_block" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_dripstone_brick_stairs_from_dripstone_block_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_dripstone_block", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_dripstone_brick_stairs_from_dripstone_block_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_dripstone_brick_wall_from_dripstone_block_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_dripstone_brick_wall_from_dripstone_block_stonecutting.json deleted file mode 100644 index e21c42fae..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_dripstone_brick_wall_from_dripstone_block_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_dripstone_block": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:dripstone_block" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_dripstone_brick_wall_from_dripstone_block_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_dripstone_block", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_dripstone_brick_wall_from_dripstone_block_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_dripstone_bricks_from_dripstone_block_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_dripstone_bricks_from_dripstone_block_stonecutting.json deleted file mode 100644 index c6a562e5e..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_dripstone_bricks_from_dripstone_block_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_dripstone_block": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:dripstone_block" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_dripstone_bricks_from_dripstone_block_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_dripstone_block", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_dripstone_bricks_from_dripstone_block_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_dripstone_from_dripstone_block_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_dripstone_from_dripstone_block_stonecutting.json deleted file mode 100644 index a784169ea..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_dripstone_from_dripstone_block_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_dripstone_block": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:dripstone_block" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_dripstone_from_dripstone_block_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_dripstone_block", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_dripstone_from_dripstone_block_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_dripstone_slab_from_dripstone_block_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_dripstone_slab_from_dripstone_block_stonecutting.json deleted file mode 100644 index b26814eaf..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_dripstone_slab_from_dripstone_block_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_dripstone_block": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:dripstone_block" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_dripstone_slab_from_dripstone_block_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_dripstone_block", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_dripstone_slab_from_dripstone_block_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_dripstone_stairs_from_dripstone_block_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_dripstone_stairs_from_dripstone_block_stonecutting.json deleted file mode 100644 index c966cc67d..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_dripstone_stairs_from_dripstone_block_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_dripstone_block": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:dripstone_block" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_dripstone_stairs_from_dripstone_block_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_dripstone_block", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_dripstone_stairs_from_dripstone_block_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_dripstone_wall_from_dripstone_block_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_dripstone_wall_from_dripstone_block_stonecutting.json deleted file mode 100644 index 04b3f0e23..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_dripstone_wall_from_dripstone_block_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_dripstone_block": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:dripstone_block" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_dripstone_wall_from_dripstone_block_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_dripstone_block", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_dripstone_wall_from_dripstone_block_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_granite_brick_slab_from_granite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_granite_brick_slab_from_granite_stonecutting.json deleted file mode 100644 index 2b0900fcc..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_granite_brick_slab_from_granite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_granite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:granite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_granite_brick_slab_from_granite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_granite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_granite_brick_slab_from_granite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_granite_brick_stairs_from_granite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_granite_brick_stairs_from_granite_stonecutting.json deleted file mode 100644 index 783b598d8..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_granite_brick_stairs_from_granite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_granite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:granite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_granite_brick_stairs_from_granite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_granite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_granite_brick_stairs_from_granite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_granite_brick_wall_from_granite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_granite_brick_wall_from_granite_stonecutting.json deleted file mode 100644 index 18b73467d..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_granite_brick_wall_from_granite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_granite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:granite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_granite_brick_wall_from_granite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_granite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_granite_brick_wall_from_granite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_granite_bricks_from_granite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_granite_bricks_from_granite_stonecutting.json deleted file mode 100644 index 644e6d0ae..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_granite_bricks_from_granite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_granite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:granite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_granite_bricks_from_granite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_granite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_granite_bricks_from_granite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_granite_from_granite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_granite_from_granite_stonecutting.json deleted file mode 100644 index 9eee48120..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_granite_from_granite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_granite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:granite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_granite_from_granite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_granite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_granite_from_granite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_granite_slab_from_granite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_granite_slab_from_granite_stonecutting.json deleted file mode 100644 index a4f6b0f80..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_granite_slab_from_granite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_granite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:granite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_granite_slab_from_granite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_granite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_granite_slab_from_granite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_granite_stairs_from_granite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_granite_stairs_from_granite_stonecutting.json deleted file mode 100644 index 4a9518fe6..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_granite_stairs_from_granite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_granite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:granite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_granite_stairs_from_granite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_granite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_granite_stairs_from_granite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_granite_wall_from_granite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_granite_wall_from_granite_stonecutting.json deleted file mode 100644 index 0661a0fca..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_granite_wall_from_granite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_granite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:granite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_granite_wall_from_granite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_granite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_granite_wall_from_granite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_limestone_brick_slab_from_limestone_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_limestone_brick_slab_from_limestone_stonecutting.json deleted file mode 100644 index ff5200bad..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_limestone_brick_slab_from_limestone_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_limestone": { - "conditions": { - "items": [ - { - "items": [ - "create:limestone" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_limestone_brick_slab_from_limestone_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_limestone", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_limestone_brick_slab_from_limestone_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_limestone_brick_stairs_from_limestone_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_limestone_brick_stairs_from_limestone_stonecutting.json deleted file mode 100644 index 9beac88e5..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_limestone_brick_stairs_from_limestone_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_limestone": { - "conditions": { - "items": [ - { - "items": [ - "create:limestone" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_limestone_brick_stairs_from_limestone_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_limestone", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_limestone_brick_stairs_from_limestone_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_limestone_brick_wall_from_limestone_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_limestone_brick_wall_from_limestone_stonecutting.json deleted file mode 100644 index 5a4b3c954..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_limestone_brick_wall_from_limestone_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_limestone": { - "conditions": { - "items": [ - { - "items": [ - "create:limestone" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_limestone_brick_wall_from_limestone_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_limestone", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_limestone_brick_wall_from_limestone_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_limestone_bricks_from_limestone_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_limestone_bricks_from_limestone_stonecutting.json deleted file mode 100644 index 6d172a5aa..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_limestone_bricks_from_limestone_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_limestone": { - "conditions": { - "items": [ - { - "items": [ - "create:limestone" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_limestone_bricks_from_limestone_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_limestone", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_limestone_bricks_from_limestone_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_limestone_from_limestone_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_limestone_from_limestone_stonecutting.json deleted file mode 100644 index 6ab209923..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_limestone_from_limestone_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_limestone": { - "conditions": { - "items": [ - { - "items": [ - "create:limestone" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_limestone_from_limestone_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_limestone", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_limestone_from_limestone_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_limestone_slab_from_limestone_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_limestone_slab_from_limestone_stonecutting.json deleted file mode 100644 index d34f9b789..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_limestone_slab_from_limestone_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_limestone": { - "conditions": { - "items": [ - { - "items": [ - "create:limestone" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_limestone_slab_from_limestone_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_limestone", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_limestone_slab_from_limestone_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_limestone_stairs_from_limestone_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_limestone_stairs_from_limestone_stonecutting.json deleted file mode 100644 index 0260303e7..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_limestone_stairs_from_limestone_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_limestone": { - "conditions": { - "items": [ - { - "items": [ - "create:limestone" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_limestone_stairs_from_limestone_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_limestone", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_limestone_stairs_from_limestone_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_limestone_wall_from_limestone_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_limestone_wall_from_limestone_stonecutting.json deleted file mode 100644 index a49638579..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_limestone_wall_from_limestone_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_limestone": { - "conditions": { - "items": [ - { - "items": [ - "create:limestone" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_limestone_wall_from_limestone_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_limestone", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_limestone_wall_from_limestone_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_ochrum_brick_slab_from_ochrum_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_ochrum_brick_slab_from_ochrum_stonecutting.json deleted file mode 100644 index 908b22d48..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_ochrum_brick_slab_from_ochrum_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_ochrum": { - "conditions": { - "items": [ - { - "items": [ - "create:ochrum" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_ochrum_brick_slab_from_ochrum_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_ochrum", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_ochrum_brick_slab_from_ochrum_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_ochrum_brick_stairs_from_ochrum_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_ochrum_brick_stairs_from_ochrum_stonecutting.json deleted file mode 100644 index 2f4ad31b6..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_ochrum_brick_stairs_from_ochrum_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_ochrum": { - "conditions": { - "items": [ - { - "items": [ - "create:ochrum" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_ochrum_brick_stairs_from_ochrum_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_ochrum", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_ochrum_brick_stairs_from_ochrum_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_ochrum_brick_wall_from_ochrum_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_ochrum_brick_wall_from_ochrum_stonecutting.json deleted file mode 100644 index d90773dfd..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_ochrum_brick_wall_from_ochrum_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_ochrum": { - "conditions": { - "items": [ - { - "items": [ - "create:ochrum" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_ochrum_brick_wall_from_ochrum_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_ochrum", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_ochrum_brick_wall_from_ochrum_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_ochrum_bricks_from_ochrum_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_ochrum_bricks_from_ochrum_stonecutting.json deleted file mode 100644 index 79bf8eaa6..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_ochrum_bricks_from_ochrum_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_ochrum": { - "conditions": { - "items": [ - { - "items": [ - "create:ochrum" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_ochrum_bricks_from_ochrum_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_ochrum", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_ochrum_bricks_from_ochrum_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_ochrum_from_ochrum_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_ochrum_from_ochrum_stonecutting.json deleted file mode 100644 index c758022e3..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_ochrum_from_ochrum_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_ochrum": { - "conditions": { - "items": [ - { - "items": [ - "create:ochrum" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_ochrum_from_ochrum_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_ochrum", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_ochrum_from_ochrum_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_ochrum_slab_from_ochrum_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_ochrum_slab_from_ochrum_stonecutting.json deleted file mode 100644 index 877eec9f6..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_ochrum_slab_from_ochrum_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_ochrum": { - "conditions": { - "items": [ - { - "items": [ - "create:ochrum" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_ochrum_slab_from_ochrum_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_ochrum", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_ochrum_slab_from_ochrum_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_ochrum_stairs_from_ochrum_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_ochrum_stairs_from_ochrum_stonecutting.json deleted file mode 100644 index e421aaced..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_ochrum_stairs_from_ochrum_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_ochrum": { - "conditions": { - "items": [ - { - "items": [ - "create:ochrum" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_ochrum_stairs_from_ochrum_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_ochrum", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_ochrum_stairs_from_ochrum_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_ochrum_wall_from_ochrum_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_ochrum_wall_from_ochrum_stonecutting.json deleted file mode 100644 index 4a49eb077..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_ochrum_wall_from_ochrum_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_ochrum": { - "conditions": { - "items": [ - { - "items": [ - "create:ochrum" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_ochrum_wall_from_ochrum_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_ochrum", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_ochrum_wall_from_ochrum_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scorchia_brick_slab_from_scorchia_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scorchia_brick_slab_from_scorchia_stonecutting.json deleted file mode 100644 index ef0eb7d3e..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scorchia_brick_slab_from_scorchia_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_scorchia": { - "conditions": { - "items": [ - { - "items": [ - "create:scorchia" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_scorchia_brick_slab_from_scorchia_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_scorchia", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_scorchia_brick_slab_from_scorchia_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scorchia_brick_stairs_from_scorchia_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scorchia_brick_stairs_from_scorchia_stonecutting.json deleted file mode 100644 index 6e02bb28e..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scorchia_brick_stairs_from_scorchia_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_scorchia": { - "conditions": { - "items": [ - { - "items": [ - "create:scorchia" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_scorchia_brick_stairs_from_scorchia_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_scorchia", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_scorchia_brick_stairs_from_scorchia_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scorchia_brick_wall_from_scorchia_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scorchia_brick_wall_from_scorchia_stonecutting.json deleted file mode 100644 index c29b1dd4f..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scorchia_brick_wall_from_scorchia_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_scorchia": { - "conditions": { - "items": [ - { - "items": [ - "create:scorchia" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_scorchia_brick_wall_from_scorchia_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_scorchia", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_scorchia_brick_wall_from_scorchia_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scorchia_bricks_from_scorchia_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scorchia_bricks_from_scorchia_stonecutting.json deleted file mode 100644 index 34eff8fe2..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scorchia_bricks_from_scorchia_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_scorchia": { - "conditions": { - "items": [ - { - "items": [ - "create:scorchia" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_scorchia_bricks_from_scorchia_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_scorchia", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_scorchia_bricks_from_scorchia_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scorchia_from_scorchia_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scorchia_from_scorchia_stonecutting.json deleted file mode 100644 index e91948bf0..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scorchia_from_scorchia_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_scorchia": { - "conditions": { - "items": [ - { - "items": [ - "create:scorchia" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_scorchia_from_scorchia_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_scorchia", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_scorchia_from_scorchia_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scorchia_slab_from_scorchia_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scorchia_slab_from_scorchia_stonecutting.json deleted file mode 100644 index 5306ac81e..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scorchia_slab_from_scorchia_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_scorchia": { - "conditions": { - "items": [ - { - "items": [ - "create:scorchia" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_scorchia_slab_from_scorchia_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_scorchia", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_scorchia_slab_from_scorchia_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scorchia_stairs_from_scorchia_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scorchia_stairs_from_scorchia_stonecutting.json deleted file mode 100644 index e44791fae..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scorchia_stairs_from_scorchia_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_scorchia": { - "conditions": { - "items": [ - { - "items": [ - "create:scorchia" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_scorchia_stairs_from_scorchia_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_scorchia", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_scorchia_stairs_from_scorchia_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scorchia_wall_from_scorchia_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scorchia_wall_from_scorchia_stonecutting.json deleted file mode 100644 index f60415cbb..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scorchia_wall_from_scorchia_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_scorchia": { - "conditions": { - "items": [ - { - "items": [ - "create:scorchia" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_scorchia_wall_from_scorchia_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_scorchia", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_scorchia_wall_from_scorchia_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scoria_brick_slab_from_scoria_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scoria_brick_slab_from_scoria_stonecutting.json deleted file mode 100644 index a69145b4a..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scoria_brick_slab_from_scoria_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_scoria": { - "conditions": { - "items": [ - { - "items": [ - "create:scoria" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_scoria_brick_slab_from_scoria_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_scoria", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_scoria_brick_slab_from_scoria_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scoria_brick_stairs_from_scoria_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scoria_brick_stairs_from_scoria_stonecutting.json deleted file mode 100644 index cb28125b0..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scoria_brick_stairs_from_scoria_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_scoria": { - "conditions": { - "items": [ - { - "items": [ - "create:scoria" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_scoria_brick_stairs_from_scoria_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_scoria", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_scoria_brick_stairs_from_scoria_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scoria_brick_wall_from_scoria_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scoria_brick_wall_from_scoria_stonecutting.json deleted file mode 100644 index e8e77e410..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scoria_brick_wall_from_scoria_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_scoria": { - "conditions": { - "items": [ - { - "items": [ - "create:scoria" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_scoria_brick_wall_from_scoria_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_scoria", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_scoria_brick_wall_from_scoria_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scoria_bricks_from_scoria_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scoria_bricks_from_scoria_stonecutting.json deleted file mode 100644 index a4bc564fa..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scoria_bricks_from_scoria_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_scoria": { - "conditions": { - "items": [ - { - "items": [ - "create:scoria" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_scoria_bricks_from_scoria_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_scoria", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_scoria_bricks_from_scoria_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scoria_from_scoria_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scoria_from_scoria_stonecutting.json deleted file mode 100644 index 2362b7114..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scoria_from_scoria_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_scoria": { - "conditions": { - "items": [ - { - "items": [ - "create:scoria" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_scoria_from_scoria_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_scoria", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_scoria_from_scoria_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scoria_slab_from_scoria_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scoria_slab_from_scoria_stonecutting.json deleted file mode 100644 index c86cf91c8..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scoria_slab_from_scoria_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_scoria": { - "conditions": { - "items": [ - { - "items": [ - "create:scoria" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_scoria_slab_from_scoria_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_scoria", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_scoria_slab_from_scoria_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scoria_stairs_from_scoria_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scoria_stairs_from_scoria_stonecutting.json deleted file mode 100644 index 2398d1fc3..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scoria_stairs_from_scoria_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_scoria": { - "conditions": { - "items": [ - { - "items": [ - "create:scoria" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_scoria_stairs_from_scoria_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_scoria", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_scoria_stairs_from_scoria_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scoria_wall_from_scoria_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scoria_wall_from_scoria_stonecutting.json deleted file mode 100644 index ce327afe1..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_scoria_wall_from_scoria_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_scoria": { - "conditions": { - "items": [ - { - "items": [ - "create:scoria" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_scoria_wall_from_scoria_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_scoria", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_scoria_wall_from_scoria_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_tuff_brick_slab_from_tuff_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_tuff_brick_slab_from_tuff_stonecutting.json deleted file mode 100644 index 72d4bd542..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_tuff_brick_slab_from_tuff_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_tuff_brick_slab_from_tuff_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - }, - "has_tuff": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:tuff" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "requirements": [ - [ - "has_tuff", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_tuff_brick_slab_from_tuff_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_tuff_brick_stairs_from_tuff_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_tuff_brick_stairs_from_tuff_stonecutting.json deleted file mode 100644 index 9c062078f..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_tuff_brick_stairs_from_tuff_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_tuff_brick_stairs_from_tuff_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - }, - "has_tuff": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:tuff" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "requirements": [ - [ - "has_tuff", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_tuff_brick_stairs_from_tuff_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_tuff_brick_wall_from_tuff_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_tuff_brick_wall_from_tuff_stonecutting.json deleted file mode 100644 index 7ce331baf..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_tuff_brick_wall_from_tuff_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_tuff_brick_wall_from_tuff_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - }, - "has_tuff": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:tuff" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "requirements": [ - [ - "has_tuff", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_tuff_brick_wall_from_tuff_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_tuff_bricks_from_tuff_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_tuff_bricks_from_tuff_stonecutting.json deleted file mode 100644 index bf6fbd05c..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_tuff_bricks_from_tuff_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_tuff_bricks_from_tuff_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - }, - "has_tuff": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:tuff" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "requirements": [ - [ - "has_tuff", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_tuff_bricks_from_tuff_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_tuff_from_tuff_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_tuff_from_tuff_stonecutting.json deleted file mode 100644 index 31ad07336..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_tuff_from_tuff_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_tuff_from_tuff_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - }, - "has_tuff": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:tuff" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "requirements": [ - [ - "has_tuff", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_tuff_from_tuff_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_tuff_slab_from_tuff_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_tuff_slab_from_tuff_stonecutting.json deleted file mode 100644 index d8d23cde3..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_tuff_slab_from_tuff_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_tuff_slab_from_tuff_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - }, - "has_tuff": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:tuff" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "requirements": [ - [ - "has_tuff", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_tuff_slab_from_tuff_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_tuff_stairs_from_tuff_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_tuff_stairs_from_tuff_stonecutting.json deleted file mode 100644 index 9efc0555d..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_tuff_stairs_from_tuff_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_tuff_stairs_from_tuff_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - }, - "has_tuff": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:tuff" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "requirements": [ - [ - "has_tuff", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_tuff_stairs_from_tuff_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_tuff_wall_from_tuff_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_tuff_wall_from_tuff_stonecutting.json deleted file mode 100644 index 9a492f25c..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_tuff_wall_from_tuff_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_tuff_wall_from_tuff_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - }, - "has_tuff": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:tuff" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "requirements": [ - [ - "has_tuff", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_tuff_wall_from_tuff_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_veridium_brick_slab_from_veridium_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_veridium_brick_slab_from_veridium_stonecutting.json deleted file mode 100644 index 51b8e71e3..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_veridium_brick_slab_from_veridium_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_veridium_brick_slab_from_veridium_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - }, - "has_veridium": { - "conditions": { - "items": [ - { - "items": [ - "create:veridium" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "requirements": [ - [ - "has_veridium", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_veridium_brick_slab_from_veridium_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_veridium_brick_stairs_from_veridium_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_veridium_brick_stairs_from_veridium_stonecutting.json deleted file mode 100644 index 7df8efd8c..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_veridium_brick_stairs_from_veridium_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_veridium_brick_stairs_from_veridium_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - }, - "has_veridium": { - "conditions": { - "items": [ - { - "items": [ - "create:veridium" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "requirements": [ - [ - "has_veridium", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_veridium_brick_stairs_from_veridium_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_veridium_brick_wall_from_veridium_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_veridium_brick_wall_from_veridium_stonecutting.json deleted file mode 100644 index 7c72e910d..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_veridium_brick_wall_from_veridium_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_veridium_brick_wall_from_veridium_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - }, - "has_veridium": { - "conditions": { - "items": [ - { - "items": [ - "create:veridium" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "requirements": [ - [ - "has_veridium", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_veridium_brick_wall_from_veridium_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_veridium_bricks_from_veridium_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_veridium_bricks_from_veridium_stonecutting.json deleted file mode 100644 index 0ddfa7687..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_veridium_bricks_from_veridium_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_veridium_bricks_from_veridium_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - }, - "has_veridium": { - "conditions": { - "items": [ - { - "items": [ - "create:veridium" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "requirements": [ - [ - "has_veridium", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_veridium_bricks_from_veridium_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_veridium_from_veridium_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_veridium_from_veridium_stonecutting.json deleted file mode 100644 index 78536da8c..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_veridium_from_veridium_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_veridium_from_veridium_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - }, - "has_veridium": { - "conditions": { - "items": [ - { - "items": [ - "create:veridium" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "requirements": [ - [ - "has_veridium", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_veridium_from_veridium_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_veridium_slab_from_veridium_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_veridium_slab_from_veridium_stonecutting.json deleted file mode 100644 index 60339ef1a..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_veridium_slab_from_veridium_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_veridium_slab_from_veridium_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - }, - "has_veridium": { - "conditions": { - "items": [ - { - "items": [ - "create:veridium" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "requirements": [ - [ - "has_veridium", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_veridium_slab_from_veridium_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_veridium_stairs_from_veridium_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_veridium_stairs_from_veridium_stonecutting.json deleted file mode 100644 index c8d502f64..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_veridium_stairs_from_veridium_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_veridium_stairs_from_veridium_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - }, - "has_veridium": { - "conditions": { - "items": [ - { - "items": [ - "create:veridium" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "requirements": [ - [ - "has_veridium", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_veridium_stairs_from_veridium_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_veridium_wall_from_veridium_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_veridium_wall_from_veridium_stonecutting.json deleted file mode 100644 index f751aa7ee..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/cut_veridium_wall_from_veridium_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_the_recipe": { - "conditions": { - "recipe": "create:cut_veridium_wall_from_veridium_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - }, - "has_veridium": { - "conditions": { - "items": [ - { - "items": [ - "create:veridium" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "requirements": [ - [ - "has_veridium", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:cut_veridium_wall_from_veridium_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/deepslate_from_stone_types_deepslate_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/deepslate_from_stone_types_deepslate_stonecutting.json new file mode 100644 index 000000000..547bad0f1 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/deepslate_from_stone_types_deepslate_stonecutting.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_stone_types_deepslate": { + "conditions": { + "items": [ + { + "tag": "create:stone_types/deepslate" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:deepslate_from_stone_types_deepslate_stonecutting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_stone_types_deepslate", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:deepslate_from_stone_types_deepslate_stonecutting" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/deepslate_pillar_from_deepslate_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/deepslate_pillar_from_deepslate_stonecutting.json deleted file mode 100644 index 55181c12f..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/deepslate_pillar_from_deepslate_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_deepslate": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:deepslate" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:deepslate_pillar_from_deepslate_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_deepslate", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:deepslate_pillar_from_deepslate_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/diorite_from_stone_types_diorite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/diorite_from_stone_types_diorite_stonecutting.json new file mode 100644 index 000000000..85219b15f --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/diorite_from_stone_types_diorite_stonecutting.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_stone_types_diorite": { + "conditions": { + "items": [ + { + "tag": "create:stone_types/diorite" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:diorite_from_stone_types_diorite_stonecutting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_stone_types_diorite", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:diorite_from_stone_types_diorite_stonecutting" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/diorite_pillar_from_diorite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/diorite_pillar_from_diorite_stonecutting.json deleted file mode 100644 index 78f497baa..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/diorite_pillar_from_diorite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_diorite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:diorite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:diorite_pillar_from_diorite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_diorite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:diorite_pillar_from_diorite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/dripstone_block_from_stone_types_dripstone_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/dripstone_block_from_stone_types_dripstone_stonecutting.json new file mode 100644 index 000000000..8f41c54b6 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/dripstone_block_from_stone_types_dripstone_stonecutting.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_stone_types_dripstone": { + "conditions": { + "items": [ + { + "tag": "create:stone_types/dripstone" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:dripstone_block_from_stone_types_dripstone_stonecutting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_stone_types_dripstone", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:dripstone_block_from_stone_types_dripstone_stonecutting" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/dripstone_pillar_from_dripstone_block_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/dripstone_pillar_from_dripstone_block_stonecutting.json deleted file mode 100644 index edab39153..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/dripstone_pillar_from_dripstone_block_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_dripstone_block": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:dripstone_block" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:dripstone_pillar_from_dripstone_block_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_dripstone_block", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:dripstone_pillar_from_dripstone_block_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/granite_from_stone_types_granite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/granite_from_stone_types_granite_stonecutting.json new file mode 100644 index 000000000..ebe3068de --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/granite_from_stone_types_granite_stonecutting.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_stone_types_granite": { + "conditions": { + "items": [ + { + "tag": "create:stone_types/granite" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:granite_from_stone_types_granite_stonecutting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_stone_types_granite", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:granite_from_stone_types_granite_stonecutting" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/granite_pillar_from_granite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/granite_pillar_from_granite_stonecutting.json deleted file mode 100644 index 72f671d50..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/granite_pillar_from_granite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_granite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:granite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:granite_pillar_from_granite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_granite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:granite_pillar_from_granite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/industrial_iron_block_from_ingots_iron_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/industrial_iron_block_from_ingots_iron_stonecutting.json new file mode 100644 index 000000000..59af43110 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/industrial_iron_block_from_ingots_iron_stonecutting.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_ingots_iron": { + "conditions": { + "items": [ + { + "tag": "forge:ingots/iron" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:industrial_iron_block_from_ingots_iron_stonecutting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_ingots_iron", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:industrial_iron_block_from_ingots_iron_stonecutting" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_andesite_from_andesite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_andesite_from_andesite_stonecutting.json deleted file mode 100644 index e50f9cab7..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_andesite_from_andesite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_andesite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:andesite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:layered_andesite_from_andesite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_andesite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:layered_andesite_from_andesite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_asurine_from_asurine_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_asurine_from_asurine_stonecutting.json deleted file mode 100644 index eb9bf2139..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_asurine_from_asurine_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_asurine": { - "conditions": { - "items": [ - { - "items": [ - "create:asurine" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:layered_asurine_from_asurine_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_asurine", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:layered_asurine_from_asurine_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_calcite_from_calcite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_calcite_from_calcite_stonecutting.json deleted file mode 100644 index 4cdde2734..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_calcite_from_calcite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_calcite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:calcite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:layered_calcite_from_calcite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_calcite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:layered_calcite_from_calcite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_crimsite_from_crimsite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_crimsite_from_crimsite_stonecutting.json deleted file mode 100644 index 5a52f9a0c..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_crimsite_from_crimsite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_crimsite": { - "conditions": { - "items": [ - { - "items": [ - "create:crimsite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:layered_crimsite_from_crimsite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_crimsite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:layered_crimsite_from_crimsite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_deepslate_from_deepslate_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_deepslate_from_deepslate_stonecutting.json deleted file mode 100644 index 1ea4cb0d5..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_deepslate_from_deepslate_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_deepslate": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:deepslate" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:layered_deepslate_from_deepslate_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_deepslate", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:layered_deepslate_from_deepslate_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_diorite_from_diorite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_diorite_from_diorite_stonecutting.json deleted file mode 100644 index d1b187f53..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_diorite_from_diorite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_diorite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:diorite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:layered_diorite_from_diorite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_diorite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:layered_diorite_from_diorite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_dripstone_from_dripstone_block_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_dripstone_from_dripstone_block_stonecutting.json deleted file mode 100644 index d41f8174f..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_dripstone_from_dripstone_block_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_dripstone_block": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:dripstone_block" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:layered_dripstone_from_dripstone_block_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_dripstone_block", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:layered_dripstone_from_dripstone_block_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_granite_from_granite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_granite_from_granite_stonecutting.json deleted file mode 100644 index e20d76ce9..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_granite_from_granite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_granite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:granite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:layered_granite_from_granite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_granite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:layered_granite_from_granite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_limestone_from_limestone_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_limestone_from_limestone_stonecutting.json deleted file mode 100644 index bd1727ba6..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_limestone_from_limestone_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_limestone": { - "conditions": { - "items": [ - { - "items": [ - "create:limestone" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:layered_limestone_from_limestone_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_limestone", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:layered_limestone_from_limestone_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_ochrum_from_ochrum_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_ochrum_from_ochrum_stonecutting.json deleted file mode 100644 index caec90d3f..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_ochrum_from_ochrum_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_ochrum": { - "conditions": { - "items": [ - { - "items": [ - "create:ochrum" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:layered_ochrum_from_ochrum_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_ochrum", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:layered_ochrum_from_ochrum_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_scorchia_from_scorchia_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_scorchia_from_scorchia_stonecutting.json deleted file mode 100644 index 84f8c80e7..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_scorchia_from_scorchia_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_scorchia": { - "conditions": { - "items": [ - { - "items": [ - "create:scorchia" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:layered_scorchia_from_scorchia_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_scorchia", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:layered_scorchia_from_scorchia_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_scoria_from_scoria_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_scoria_from_scoria_stonecutting.json deleted file mode 100644 index ae6f6a5a1..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_scoria_from_scoria_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_scoria": { - "conditions": { - "items": [ - { - "items": [ - "create:scoria" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:layered_scoria_from_scoria_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_scoria", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:layered_scoria_from_scoria_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_tuff_from_tuff_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_tuff_from_tuff_stonecutting.json deleted file mode 100644 index a47a8633e..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_tuff_from_tuff_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_the_recipe": { - "conditions": { - "recipe": "create:layered_tuff_from_tuff_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - }, - "has_tuff": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:tuff" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "requirements": [ - [ - "has_tuff", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:layered_tuff_from_tuff_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_veridium_from_veridium_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_veridium_from_veridium_stonecutting.json deleted file mode 100644 index 55ba19ae4..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/layered_veridium_from_veridium_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_the_recipe": { - "conditions": { - "recipe": "create:layered_veridium_from_veridium_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - }, - "has_veridium": { - "conditions": { - "items": [ - { - "items": [ - "create:veridium" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "requirements": [ - [ - "has_veridium", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:layered_veridium_from_veridium_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/limestone_from_stone_types_limestone_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/limestone_from_stone_types_limestone_stonecutting.json new file mode 100644 index 000000000..a71cc57cb --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/limestone_from_stone_types_limestone_stonecutting.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_stone_types_limestone": { + "conditions": { + "items": [ + { + "tag": "create:stone_types/limestone" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:limestone_from_stone_types_limestone_stonecutting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_stone_types_limestone", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:limestone_from_stone_types_limestone_stonecutting" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/limestone_pillar_from_limestone_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/limestone_pillar_from_limestone_stonecutting.json deleted file mode 100644 index 8047792aa..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/limestone_pillar_from_limestone_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_limestone": { - "conditions": { - "items": [ - { - "items": [ - "create:limestone" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:limestone_pillar_from_limestone_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_limestone", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:limestone_pillar_from_limestone_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/mangrove_window.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/mangrove_window.json new file mode 100644 index 000000000..73115a879 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/mangrove_window.json @@ -0,0 +1,34 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_ingredient": { + "conditions": { + "items": [ + { + "items": [ + "minecraft:mangrove_planks" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:mangrove_window" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_ingredient", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:mangrove_window" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/mangrove_window_pane.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/mangrove_window_pane.json new file mode 100644 index 000000000..e3f7dfb93 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/mangrove_window_pane.json @@ -0,0 +1,34 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_ingredient": { + "conditions": { + "items": [ + { + "items": [ + "create:mangrove_window" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:mangrove_window_pane" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_ingredient", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:mangrove_window_pane" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/ochrum_from_stone_types_ochrum_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/ochrum_from_stone_types_ochrum_stonecutting.json new file mode 100644 index 000000000..a6fdfcac4 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/ochrum_from_stone_types_ochrum_stonecutting.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_stone_types_ochrum": { + "conditions": { + "items": [ + { + "tag": "create:stone_types/ochrum" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:ochrum_from_stone_types_ochrum_stonecutting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_stone_types_ochrum", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:ochrum_from_stone_types_ochrum_stonecutting" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/ochrum_pillar_from_ochrum_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/ochrum_pillar_from_ochrum_stonecutting.json deleted file mode 100644 index 0bd7edc3a..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/ochrum_pillar_from_ochrum_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_ochrum": { - "conditions": { - "items": [ - { - "items": [ - "create:ochrum" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:ochrum_pillar_from_ochrum_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_ochrum", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:ochrum_pillar_from_ochrum_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_andesite_from_andesite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_andesite_from_andesite_stonecutting.json deleted file mode 100644 index bf91c2cdf..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_andesite_from_andesite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_andesite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:andesite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_andesite_from_andesite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_andesite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_andesite_from_andesite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_andesite_slab_from_andesite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_andesite_slab_from_andesite_stonecutting.json deleted file mode 100644 index df78390a9..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_andesite_slab_from_andesite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_andesite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:andesite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_andesite_slab_from_andesite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_andesite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_andesite_slab_from_andesite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_andesite_stairs_from_andesite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_andesite_stairs_from_andesite_stonecutting.json deleted file mode 100644 index 3c3df0646..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_andesite_stairs_from_andesite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_andesite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:andesite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_andesite_stairs_from_andesite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_andesite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_andesite_stairs_from_andesite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_andesite_wall_from_andesite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_andesite_wall_from_andesite_stonecutting.json deleted file mode 100644 index 39a911a0c..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_andesite_wall_from_andesite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_andesite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:andesite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_andesite_wall_from_andesite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_andesite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_andesite_wall_from_andesite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_asurine_from_asurine_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_asurine_from_asurine_stonecutting.json deleted file mode 100644 index 715f17824..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_asurine_from_asurine_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_asurine": { - "conditions": { - "items": [ - { - "items": [ - "create:asurine" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_asurine_from_asurine_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_asurine", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_asurine_from_asurine_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_asurine_slab_from_asurine_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_asurine_slab_from_asurine_stonecutting.json deleted file mode 100644 index f68ee210a..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_asurine_slab_from_asurine_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_asurine": { - "conditions": { - "items": [ - { - "items": [ - "create:asurine" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_asurine_slab_from_asurine_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_asurine", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_asurine_slab_from_asurine_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_asurine_stairs_from_asurine_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_asurine_stairs_from_asurine_stonecutting.json deleted file mode 100644 index eb5f52cf8..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_asurine_stairs_from_asurine_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_asurine": { - "conditions": { - "items": [ - { - "items": [ - "create:asurine" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_asurine_stairs_from_asurine_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_asurine", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_asurine_stairs_from_asurine_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_asurine_wall_from_asurine_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_asurine_wall_from_asurine_stonecutting.json deleted file mode 100644 index 357082606..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_asurine_wall_from_asurine_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_asurine": { - "conditions": { - "items": [ - { - "items": [ - "create:asurine" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_asurine_wall_from_asurine_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_asurine", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_asurine_wall_from_asurine_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_calcite_from_calcite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_calcite_from_calcite_stonecutting.json deleted file mode 100644 index c26b3dffb..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_calcite_from_calcite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_calcite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:calcite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_calcite_from_calcite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_calcite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_calcite_from_calcite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_calcite_slab_from_calcite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_calcite_slab_from_calcite_stonecutting.json deleted file mode 100644 index b1f65f4b4..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_calcite_slab_from_calcite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_calcite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:calcite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_calcite_slab_from_calcite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_calcite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_calcite_slab_from_calcite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_calcite_stairs_from_calcite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_calcite_stairs_from_calcite_stonecutting.json deleted file mode 100644 index f19e396be..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_calcite_stairs_from_calcite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_calcite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:calcite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_calcite_stairs_from_calcite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_calcite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_calcite_stairs_from_calcite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_calcite_wall_from_calcite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_calcite_wall_from_calcite_stonecutting.json deleted file mode 100644 index a46612559..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_calcite_wall_from_calcite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_calcite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:calcite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_calcite_wall_from_calcite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_calcite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_calcite_wall_from_calcite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_crimsite_from_crimsite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_crimsite_from_crimsite_stonecutting.json deleted file mode 100644 index 034cfde25..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_crimsite_from_crimsite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_crimsite": { - "conditions": { - "items": [ - { - "items": [ - "create:crimsite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_crimsite_from_crimsite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_crimsite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_crimsite_from_crimsite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_crimsite_slab_from_crimsite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_crimsite_slab_from_crimsite_stonecutting.json deleted file mode 100644 index 56c363a11..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_crimsite_slab_from_crimsite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_crimsite": { - "conditions": { - "items": [ - { - "items": [ - "create:crimsite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_crimsite_slab_from_crimsite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_crimsite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_crimsite_slab_from_crimsite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_crimsite_stairs_from_crimsite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_crimsite_stairs_from_crimsite_stonecutting.json deleted file mode 100644 index 597034cc8..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_crimsite_stairs_from_crimsite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_crimsite": { - "conditions": { - "items": [ - { - "items": [ - "create:crimsite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_crimsite_stairs_from_crimsite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_crimsite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_crimsite_stairs_from_crimsite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_crimsite_wall_from_crimsite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_crimsite_wall_from_crimsite_stonecutting.json deleted file mode 100644 index efac2039e..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_crimsite_wall_from_crimsite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_crimsite": { - "conditions": { - "items": [ - { - "items": [ - "create:crimsite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_crimsite_wall_from_crimsite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_crimsite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_crimsite_wall_from_crimsite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_deepslate_from_deepslate_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_deepslate_from_deepslate_stonecutting.json deleted file mode 100644 index 34f67fde6..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_deepslate_from_deepslate_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_deepslate": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:deepslate" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_deepslate_from_deepslate_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_deepslate", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_deepslate_from_deepslate_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_deepslate_slab_from_deepslate_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_deepslate_slab_from_deepslate_stonecutting.json deleted file mode 100644 index 3d7f67dd3..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_deepslate_slab_from_deepslate_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_deepslate": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:deepslate" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_deepslate_slab_from_deepslate_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_deepslate", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_deepslate_slab_from_deepslate_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_deepslate_stairs_from_deepslate_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_deepslate_stairs_from_deepslate_stonecutting.json deleted file mode 100644 index 9a19cab9a..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_deepslate_stairs_from_deepslate_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_deepslate": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:deepslate" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_deepslate_stairs_from_deepslate_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_deepslate", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_deepslate_stairs_from_deepslate_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_deepslate_wall_from_deepslate_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_deepslate_wall_from_deepslate_stonecutting.json deleted file mode 100644 index 5dc3c4692..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_deepslate_wall_from_deepslate_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_deepslate": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:deepslate" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_deepslate_wall_from_deepslate_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_deepslate", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_deepslate_wall_from_deepslate_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_diorite_from_diorite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_diorite_from_diorite_stonecutting.json deleted file mode 100644 index e589032a8..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_diorite_from_diorite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_diorite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:diorite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_diorite_from_diorite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_diorite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_diorite_from_diorite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_diorite_slab_from_diorite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_diorite_slab_from_diorite_stonecutting.json deleted file mode 100644 index 56f8ee14c..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_diorite_slab_from_diorite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_diorite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:diorite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_diorite_slab_from_diorite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_diorite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_diorite_slab_from_diorite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_diorite_stairs_from_diorite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_diorite_stairs_from_diorite_stonecutting.json deleted file mode 100644 index 9f496b20b..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_diorite_stairs_from_diorite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_diorite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:diorite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_diorite_stairs_from_diorite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_diorite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_diorite_stairs_from_diorite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_diorite_wall_from_diorite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_diorite_wall_from_diorite_stonecutting.json deleted file mode 100644 index 42e1cee3c..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_diorite_wall_from_diorite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_diorite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:diorite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_diorite_wall_from_diorite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_diorite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_diorite_wall_from_diorite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_dripstone_from_dripstone_block_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_dripstone_from_dripstone_block_stonecutting.json deleted file mode 100644 index 6017ace41..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_dripstone_from_dripstone_block_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_dripstone_block": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:dripstone_block" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_dripstone_from_dripstone_block_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_dripstone_block", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_dripstone_from_dripstone_block_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_dripstone_slab_from_dripstone_block_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_dripstone_slab_from_dripstone_block_stonecutting.json deleted file mode 100644 index 5ef30eebf..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_dripstone_slab_from_dripstone_block_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_dripstone_block": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:dripstone_block" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_dripstone_slab_from_dripstone_block_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_dripstone_block", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_dripstone_slab_from_dripstone_block_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_dripstone_stairs_from_dripstone_block_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_dripstone_stairs_from_dripstone_block_stonecutting.json deleted file mode 100644 index 8883b04c9..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_dripstone_stairs_from_dripstone_block_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_dripstone_block": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:dripstone_block" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_dripstone_stairs_from_dripstone_block_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_dripstone_block", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_dripstone_stairs_from_dripstone_block_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_dripstone_wall_from_dripstone_block_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_dripstone_wall_from_dripstone_block_stonecutting.json deleted file mode 100644 index 3f58d3849..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_dripstone_wall_from_dripstone_block_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_dripstone_block": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:dripstone_block" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_dripstone_wall_from_dripstone_block_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_dripstone_block", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_dripstone_wall_from_dripstone_block_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_granite_from_granite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_granite_from_granite_stonecutting.json deleted file mode 100644 index 53419861c..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_granite_from_granite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_granite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:granite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_granite_from_granite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_granite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_granite_from_granite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_granite_slab_from_granite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_granite_slab_from_granite_stonecutting.json deleted file mode 100644 index c8add24d2..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_granite_slab_from_granite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_granite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:granite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_granite_slab_from_granite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_granite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_granite_slab_from_granite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_granite_stairs_from_granite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_granite_stairs_from_granite_stonecutting.json deleted file mode 100644 index 09d08aab1..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_granite_stairs_from_granite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_granite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:granite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_granite_stairs_from_granite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_granite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_granite_stairs_from_granite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_granite_wall_from_granite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_granite_wall_from_granite_stonecutting.json deleted file mode 100644 index e59e9c982..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_granite_wall_from_granite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_granite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:granite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_granite_wall_from_granite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_granite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_granite_wall_from_granite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_limestone_from_limestone_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_limestone_from_limestone_stonecutting.json deleted file mode 100644 index 880d8e943..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_limestone_from_limestone_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_limestone": { - "conditions": { - "items": [ - { - "items": [ - "create:limestone" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_limestone_from_limestone_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_limestone", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_limestone_from_limestone_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_limestone_slab_from_limestone_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_limestone_slab_from_limestone_stonecutting.json deleted file mode 100644 index b45300341..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_limestone_slab_from_limestone_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_limestone": { - "conditions": { - "items": [ - { - "items": [ - "create:limestone" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_limestone_slab_from_limestone_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_limestone", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_limestone_slab_from_limestone_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_limestone_stairs_from_limestone_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_limestone_stairs_from_limestone_stonecutting.json deleted file mode 100644 index 1bdc92350..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_limestone_stairs_from_limestone_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_limestone": { - "conditions": { - "items": [ - { - "items": [ - "create:limestone" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_limestone_stairs_from_limestone_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_limestone", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_limestone_stairs_from_limestone_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_limestone_wall_from_limestone_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_limestone_wall_from_limestone_stonecutting.json deleted file mode 100644 index 3e1fac8b4..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_limestone_wall_from_limestone_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_limestone": { - "conditions": { - "items": [ - { - "items": [ - "create:limestone" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_limestone_wall_from_limestone_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_limestone", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_limestone_wall_from_limestone_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_ochrum_from_ochrum_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_ochrum_from_ochrum_stonecutting.json deleted file mode 100644 index 2dd3502d0..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_ochrum_from_ochrum_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_ochrum": { - "conditions": { - "items": [ - { - "items": [ - "create:ochrum" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_ochrum_from_ochrum_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_ochrum", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_ochrum_from_ochrum_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_ochrum_slab_from_ochrum_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_ochrum_slab_from_ochrum_stonecutting.json deleted file mode 100644 index f3235509a..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_ochrum_slab_from_ochrum_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_ochrum": { - "conditions": { - "items": [ - { - "items": [ - "create:ochrum" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_ochrum_slab_from_ochrum_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_ochrum", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_ochrum_slab_from_ochrum_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_ochrum_stairs_from_ochrum_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_ochrum_stairs_from_ochrum_stonecutting.json deleted file mode 100644 index 40d5b3b84..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_ochrum_stairs_from_ochrum_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_ochrum": { - "conditions": { - "items": [ - { - "items": [ - "create:ochrum" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_ochrum_stairs_from_ochrum_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_ochrum", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_ochrum_stairs_from_ochrum_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_ochrum_wall_from_ochrum_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_ochrum_wall_from_ochrum_stonecutting.json deleted file mode 100644 index ebaf1750f..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_ochrum_wall_from_ochrum_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_ochrum": { - "conditions": { - "items": [ - { - "items": [ - "create:ochrum" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_ochrum_wall_from_ochrum_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_ochrum", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_ochrum_wall_from_ochrum_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_scorchia_from_scorchia_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_scorchia_from_scorchia_stonecutting.json deleted file mode 100644 index efde3437c..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_scorchia_from_scorchia_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_scorchia": { - "conditions": { - "items": [ - { - "items": [ - "create:scorchia" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_scorchia_from_scorchia_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_scorchia", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_scorchia_from_scorchia_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_scorchia_slab_from_scorchia_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_scorchia_slab_from_scorchia_stonecutting.json deleted file mode 100644 index 8987606ab..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_scorchia_slab_from_scorchia_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_scorchia": { - "conditions": { - "items": [ - { - "items": [ - "create:scorchia" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_scorchia_slab_from_scorchia_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_scorchia", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_scorchia_slab_from_scorchia_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_scorchia_stairs_from_scorchia_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_scorchia_stairs_from_scorchia_stonecutting.json deleted file mode 100644 index 2d8229dd4..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_scorchia_stairs_from_scorchia_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_scorchia": { - "conditions": { - "items": [ - { - "items": [ - "create:scorchia" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_scorchia_stairs_from_scorchia_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_scorchia", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_scorchia_stairs_from_scorchia_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_scorchia_wall_from_scorchia_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_scorchia_wall_from_scorchia_stonecutting.json deleted file mode 100644 index 05979247f..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_scorchia_wall_from_scorchia_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_scorchia": { - "conditions": { - "items": [ - { - "items": [ - "create:scorchia" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_scorchia_wall_from_scorchia_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_scorchia", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_scorchia_wall_from_scorchia_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_scoria_from_scoria_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_scoria_from_scoria_stonecutting.json deleted file mode 100644 index ed881d3da..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_scoria_from_scoria_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_scoria": { - "conditions": { - "items": [ - { - "items": [ - "create:scoria" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_scoria_from_scoria_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_scoria", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_scoria_from_scoria_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_scoria_slab_from_scoria_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_scoria_slab_from_scoria_stonecutting.json deleted file mode 100644 index 561932857..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_scoria_slab_from_scoria_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_scoria": { - "conditions": { - "items": [ - { - "items": [ - "create:scoria" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_scoria_slab_from_scoria_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_scoria", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_scoria_slab_from_scoria_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_scoria_stairs_from_scoria_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_scoria_stairs_from_scoria_stonecutting.json deleted file mode 100644 index c34bf47d3..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_scoria_stairs_from_scoria_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_scoria": { - "conditions": { - "items": [ - { - "items": [ - "create:scoria" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_scoria_stairs_from_scoria_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_scoria", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_scoria_stairs_from_scoria_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_scoria_wall_from_scoria_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_scoria_wall_from_scoria_stonecutting.json deleted file mode 100644 index 6de05d350..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_scoria_wall_from_scoria_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_scoria": { - "conditions": { - "items": [ - { - "items": [ - "create:scoria" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_scoria_wall_from_scoria_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_scoria", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_scoria_wall_from_scoria_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_tuff_from_tuff_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_tuff_from_tuff_stonecutting.json deleted file mode 100644 index 0b2cc6ae7..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_tuff_from_tuff_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_tuff_from_tuff_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - }, - "has_tuff": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:tuff" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "requirements": [ - [ - "has_tuff", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_tuff_from_tuff_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_tuff_slab_from_tuff_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_tuff_slab_from_tuff_stonecutting.json deleted file mode 100644 index 49f64afaa..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_tuff_slab_from_tuff_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_tuff_slab_from_tuff_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - }, - "has_tuff": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:tuff" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "requirements": [ - [ - "has_tuff", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_tuff_slab_from_tuff_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_tuff_stairs_from_tuff_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_tuff_stairs_from_tuff_stonecutting.json deleted file mode 100644 index 85705b0e8..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_tuff_stairs_from_tuff_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_tuff_stairs_from_tuff_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - }, - "has_tuff": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:tuff" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "requirements": [ - [ - "has_tuff", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_tuff_stairs_from_tuff_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_tuff_wall_from_tuff_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_tuff_wall_from_tuff_stonecutting.json deleted file mode 100644 index 0e6a91fb8..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_tuff_wall_from_tuff_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_tuff_wall_from_tuff_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - }, - "has_tuff": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:tuff" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "requirements": [ - [ - "has_tuff", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_tuff_wall_from_tuff_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_veridium_from_veridium_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_veridium_from_veridium_stonecutting.json deleted file mode 100644 index 2a51165f2..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_veridium_from_veridium_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_veridium_from_veridium_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - }, - "has_veridium": { - "conditions": { - "items": [ - { - "items": [ - "create:veridium" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "requirements": [ - [ - "has_veridium", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_veridium_from_veridium_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_veridium_slab_from_veridium_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_veridium_slab_from_veridium_stonecutting.json deleted file mode 100644 index 1763a887c..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_veridium_slab_from_veridium_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_veridium_slab_from_veridium_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - }, - "has_veridium": { - "conditions": { - "items": [ - { - "items": [ - "create:veridium" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "requirements": [ - [ - "has_veridium", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_veridium_slab_from_veridium_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_veridium_stairs_from_veridium_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_veridium_stairs_from_veridium_stonecutting.json deleted file mode 100644 index 90156ccf1..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_veridium_stairs_from_veridium_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_veridium_stairs_from_veridium_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - }, - "has_veridium": { - "conditions": { - "items": [ - { - "items": [ - "create:veridium" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "requirements": [ - [ - "has_veridium", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_veridium_stairs_from_veridium_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_veridium_wall_from_veridium_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_veridium_wall_from_veridium_stonecutting.json deleted file mode 100644 index 71dc4e971..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/polished_cut_veridium_wall_from_veridium_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_the_recipe": { - "conditions": { - "recipe": "create:polished_cut_veridium_wall_from_veridium_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - }, - "has_veridium": { - "conditions": { - "items": [ - { - "items": [ - "create:veridium" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "requirements": [ - [ - "has_veridium", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:polished_cut_veridium_wall_from_veridium_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/scorchia_from_stone_types_scorchia_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/scorchia_from_stone_types_scorchia_stonecutting.json new file mode 100644 index 000000000..11ff87dd8 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/scorchia_from_stone_types_scorchia_stonecutting.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_stone_types_scorchia": { + "conditions": { + "items": [ + { + "tag": "create:stone_types/scorchia" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:scorchia_from_stone_types_scorchia_stonecutting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_stone_types_scorchia", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:scorchia_from_stone_types_scorchia_stonecutting" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/scorchia_pillar_from_scorchia_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/scorchia_pillar_from_scorchia_stonecutting.json deleted file mode 100644 index f892ea0b7..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/scorchia_pillar_from_scorchia_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_scorchia": { - "conditions": { - "items": [ - { - "items": [ - "create:scorchia" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:scorchia_pillar_from_scorchia_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_scorchia", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:scorchia_pillar_from_scorchia_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/scoria_from_stone_types_scoria_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/scoria_from_stone_types_scoria_stonecutting.json new file mode 100644 index 000000000..44dedca93 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/scoria_from_stone_types_scoria_stonecutting.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_stone_types_scoria": { + "conditions": { + "items": [ + { + "tag": "create:stone_types/scoria" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:scoria_from_stone_types_scoria_stonecutting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_stone_types_scoria", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:scoria_from_stone_types_scoria_stonecutting" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/scoria_pillar_from_scoria_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/scoria_pillar_from_scoria_stonecutting.json deleted file mode 100644 index 10bbbf72c..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/scoria_pillar_from_scoria_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_scoria": { - "conditions": { - "items": [ - { - "items": [ - "create:scoria" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:scoria_pillar_from_scoria_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_scoria", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:scoria_pillar_from_scoria_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_andesite_brick_slab_from_andesite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_andesite_brick_slab_from_andesite_stonecutting.json deleted file mode 100644 index 5efeabbe4..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_andesite_brick_slab_from_andesite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_andesite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:andesite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_andesite_brick_slab_from_andesite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_andesite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_andesite_brick_slab_from_andesite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_andesite_brick_stairs_from_andesite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_andesite_brick_stairs_from_andesite_stonecutting.json deleted file mode 100644 index fbc273b42..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_andesite_brick_stairs_from_andesite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_andesite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:andesite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_andesite_brick_stairs_from_andesite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_andesite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_andesite_brick_stairs_from_andesite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_andesite_brick_wall_from_andesite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_andesite_brick_wall_from_andesite_stonecutting.json deleted file mode 100644 index f55705145..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_andesite_brick_wall_from_andesite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_andesite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:andesite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_andesite_brick_wall_from_andesite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_andesite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_andesite_brick_wall_from_andesite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_andesite_bricks_from_andesite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_andesite_bricks_from_andesite_stonecutting.json deleted file mode 100644 index 0465d8fbb..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_andesite_bricks_from_andesite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_andesite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:andesite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_andesite_bricks_from_andesite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_andesite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_andesite_bricks_from_andesite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_asurine_brick_slab_from_asurine_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_asurine_brick_slab_from_asurine_stonecutting.json deleted file mode 100644 index c70ad72b0..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_asurine_brick_slab_from_asurine_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_asurine": { - "conditions": { - "items": [ - { - "items": [ - "create:asurine" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_asurine_brick_slab_from_asurine_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_asurine", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_asurine_brick_slab_from_asurine_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_asurine_brick_stairs_from_asurine_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_asurine_brick_stairs_from_asurine_stonecutting.json deleted file mode 100644 index fb01f5f6e..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_asurine_brick_stairs_from_asurine_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_asurine": { - "conditions": { - "items": [ - { - "items": [ - "create:asurine" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_asurine_brick_stairs_from_asurine_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_asurine", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_asurine_brick_stairs_from_asurine_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_asurine_brick_wall_from_asurine_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_asurine_brick_wall_from_asurine_stonecutting.json deleted file mode 100644 index 507f78693..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_asurine_brick_wall_from_asurine_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_asurine": { - "conditions": { - "items": [ - { - "items": [ - "create:asurine" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_asurine_brick_wall_from_asurine_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_asurine", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_asurine_brick_wall_from_asurine_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_asurine_bricks_from_asurine_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_asurine_bricks_from_asurine_stonecutting.json deleted file mode 100644 index 7f45f631b..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_asurine_bricks_from_asurine_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_asurine": { - "conditions": { - "items": [ - { - "items": [ - "create:asurine" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_asurine_bricks_from_asurine_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_asurine", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_asurine_bricks_from_asurine_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_calcite_brick_slab_from_calcite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_calcite_brick_slab_from_calcite_stonecutting.json deleted file mode 100644 index 2bf42e20a..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_calcite_brick_slab_from_calcite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_calcite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:calcite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_calcite_brick_slab_from_calcite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_calcite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_calcite_brick_slab_from_calcite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_calcite_brick_stairs_from_calcite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_calcite_brick_stairs_from_calcite_stonecutting.json deleted file mode 100644 index cae1a9c35..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_calcite_brick_stairs_from_calcite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_calcite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:calcite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_calcite_brick_stairs_from_calcite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_calcite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_calcite_brick_stairs_from_calcite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_calcite_brick_wall_from_calcite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_calcite_brick_wall_from_calcite_stonecutting.json deleted file mode 100644 index 2c4907e14..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_calcite_brick_wall_from_calcite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_calcite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:calcite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_calcite_brick_wall_from_calcite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_calcite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_calcite_brick_wall_from_calcite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_calcite_bricks_from_calcite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_calcite_bricks_from_calcite_stonecutting.json deleted file mode 100644 index 030b4011d..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_calcite_bricks_from_calcite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_calcite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:calcite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_calcite_bricks_from_calcite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_calcite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_calcite_bricks_from_calcite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_crimsite_brick_slab_from_crimsite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_crimsite_brick_slab_from_crimsite_stonecutting.json deleted file mode 100644 index 560eac16d..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_crimsite_brick_slab_from_crimsite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_crimsite": { - "conditions": { - "items": [ - { - "items": [ - "create:crimsite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_crimsite_brick_slab_from_crimsite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_crimsite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_crimsite_brick_slab_from_crimsite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_crimsite_brick_stairs_from_crimsite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_crimsite_brick_stairs_from_crimsite_stonecutting.json deleted file mode 100644 index 16a0d66f8..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_crimsite_brick_stairs_from_crimsite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_crimsite": { - "conditions": { - "items": [ - { - "items": [ - "create:crimsite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_crimsite_brick_stairs_from_crimsite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_crimsite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_crimsite_brick_stairs_from_crimsite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_crimsite_brick_wall_from_crimsite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_crimsite_brick_wall_from_crimsite_stonecutting.json deleted file mode 100644 index 81ad8388d..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_crimsite_brick_wall_from_crimsite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_crimsite": { - "conditions": { - "items": [ - { - "items": [ - "create:crimsite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_crimsite_brick_wall_from_crimsite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_crimsite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_crimsite_brick_wall_from_crimsite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_crimsite_bricks_from_crimsite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_crimsite_bricks_from_crimsite_stonecutting.json deleted file mode 100644 index d01340551..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_crimsite_bricks_from_crimsite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_crimsite": { - "conditions": { - "items": [ - { - "items": [ - "create:crimsite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_crimsite_bricks_from_crimsite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_crimsite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_crimsite_bricks_from_crimsite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_deepslate_brick_slab_from_deepslate_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_deepslate_brick_slab_from_deepslate_stonecutting.json deleted file mode 100644 index 26d751030..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_deepslate_brick_slab_from_deepslate_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_deepslate": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:deepslate" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_deepslate_brick_slab_from_deepslate_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_deepslate", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_deepslate_brick_slab_from_deepslate_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_deepslate_brick_stairs_from_deepslate_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_deepslate_brick_stairs_from_deepslate_stonecutting.json deleted file mode 100644 index 95758cc19..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_deepslate_brick_stairs_from_deepslate_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_deepslate": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:deepslate" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_deepslate_brick_stairs_from_deepslate_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_deepslate", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_deepslate_brick_stairs_from_deepslate_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_deepslate_brick_wall_from_deepslate_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_deepslate_brick_wall_from_deepslate_stonecutting.json deleted file mode 100644 index cb936ede7..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_deepslate_brick_wall_from_deepslate_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_deepslate": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:deepslate" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_deepslate_brick_wall_from_deepslate_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_deepslate", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_deepslate_brick_wall_from_deepslate_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_deepslate_bricks_from_deepslate_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_deepslate_bricks_from_deepslate_stonecutting.json deleted file mode 100644 index eb9f24ab9..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_deepslate_bricks_from_deepslate_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_deepslate": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:deepslate" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_deepslate_bricks_from_deepslate_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_deepslate", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_deepslate_bricks_from_deepslate_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_diorite_brick_slab_from_diorite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_diorite_brick_slab_from_diorite_stonecutting.json deleted file mode 100644 index c6db6debc..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_diorite_brick_slab_from_diorite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_diorite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:diorite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_diorite_brick_slab_from_diorite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_diorite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_diorite_brick_slab_from_diorite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_diorite_brick_stairs_from_diorite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_diorite_brick_stairs_from_diorite_stonecutting.json deleted file mode 100644 index 09c9f549f..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_diorite_brick_stairs_from_diorite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_diorite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:diorite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_diorite_brick_stairs_from_diorite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_diorite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_diorite_brick_stairs_from_diorite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_diorite_brick_wall_from_diorite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_diorite_brick_wall_from_diorite_stonecutting.json deleted file mode 100644 index b741602a2..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_diorite_brick_wall_from_diorite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_diorite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:diorite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_diorite_brick_wall_from_diorite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_diorite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_diorite_brick_wall_from_diorite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_diorite_bricks_from_diorite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_diorite_bricks_from_diorite_stonecutting.json deleted file mode 100644 index b3ada642f..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_diorite_bricks_from_diorite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_diorite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:diorite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_diorite_bricks_from_diorite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_diorite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_diorite_bricks_from_diorite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_dripstone_brick_slab_from_dripstone_block_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_dripstone_brick_slab_from_dripstone_block_stonecutting.json deleted file mode 100644 index 9e758373d..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_dripstone_brick_slab_from_dripstone_block_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_dripstone_block": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:dripstone_block" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_dripstone_brick_slab_from_dripstone_block_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_dripstone_block", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_dripstone_brick_slab_from_dripstone_block_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_dripstone_brick_stairs_from_dripstone_block_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_dripstone_brick_stairs_from_dripstone_block_stonecutting.json deleted file mode 100644 index cf816bca7..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_dripstone_brick_stairs_from_dripstone_block_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_dripstone_block": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:dripstone_block" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_dripstone_brick_stairs_from_dripstone_block_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_dripstone_block", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_dripstone_brick_stairs_from_dripstone_block_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_dripstone_brick_wall_from_dripstone_block_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_dripstone_brick_wall_from_dripstone_block_stonecutting.json deleted file mode 100644 index 9749ad09e..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_dripstone_brick_wall_from_dripstone_block_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_dripstone_block": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:dripstone_block" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_dripstone_brick_wall_from_dripstone_block_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_dripstone_block", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_dripstone_brick_wall_from_dripstone_block_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_dripstone_bricks_from_dripstone_block_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_dripstone_bricks_from_dripstone_block_stonecutting.json deleted file mode 100644 index f25ffe126..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_dripstone_bricks_from_dripstone_block_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_dripstone_block": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:dripstone_block" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_dripstone_bricks_from_dripstone_block_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_dripstone_block", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_dripstone_bricks_from_dripstone_block_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_granite_brick_slab_from_granite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_granite_brick_slab_from_granite_stonecutting.json deleted file mode 100644 index 323d7a7de..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_granite_brick_slab_from_granite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_granite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:granite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_granite_brick_slab_from_granite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_granite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_granite_brick_slab_from_granite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_granite_brick_stairs_from_granite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_granite_brick_stairs_from_granite_stonecutting.json deleted file mode 100644 index 9fd4d1b7e..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_granite_brick_stairs_from_granite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_granite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:granite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_granite_brick_stairs_from_granite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_granite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_granite_brick_stairs_from_granite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_granite_brick_wall_from_granite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_granite_brick_wall_from_granite_stonecutting.json deleted file mode 100644 index 8e0c02df8..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_granite_brick_wall_from_granite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_granite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:granite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_granite_brick_wall_from_granite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_granite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_granite_brick_wall_from_granite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_granite_bricks_from_granite_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_granite_bricks_from_granite_stonecutting.json deleted file mode 100644 index 9ce6ad898..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_granite_bricks_from_granite_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_granite": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:granite" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_granite_bricks_from_granite_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_granite", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_granite_bricks_from_granite_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_limestone_brick_slab_from_limestone_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_limestone_brick_slab_from_limestone_stonecutting.json deleted file mode 100644 index d7874f219..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_limestone_brick_slab_from_limestone_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_limestone": { - "conditions": { - "items": [ - { - "items": [ - "create:limestone" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_limestone_brick_slab_from_limestone_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_limestone", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_limestone_brick_slab_from_limestone_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_limestone_brick_stairs_from_limestone_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_limestone_brick_stairs_from_limestone_stonecutting.json deleted file mode 100644 index 5019e15ab..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_limestone_brick_stairs_from_limestone_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_limestone": { - "conditions": { - "items": [ - { - "items": [ - "create:limestone" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_limestone_brick_stairs_from_limestone_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_limestone", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_limestone_brick_stairs_from_limestone_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_limestone_brick_wall_from_limestone_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_limestone_brick_wall_from_limestone_stonecutting.json deleted file mode 100644 index b22ef09c7..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_limestone_brick_wall_from_limestone_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_limestone": { - "conditions": { - "items": [ - { - "items": [ - "create:limestone" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_limestone_brick_wall_from_limestone_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_limestone", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_limestone_brick_wall_from_limestone_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_limestone_bricks_from_limestone_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_limestone_bricks_from_limestone_stonecutting.json deleted file mode 100644 index f27fe5959..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_limestone_bricks_from_limestone_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_limestone": { - "conditions": { - "items": [ - { - "items": [ - "create:limestone" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_limestone_bricks_from_limestone_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_limestone", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_limestone_bricks_from_limestone_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_ochrum_brick_slab_from_ochrum_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_ochrum_brick_slab_from_ochrum_stonecutting.json deleted file mode 100644 index 0b5609a78..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_ochrum_brick_slab_from_ochrum_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_ochrum": { - "conditions": { - "items": [ - { - "items": [ - "create:ochrum" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_ochrum_brick_slab_from_ochrum_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_ochrum", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_ochrum_brick_slab_from_ochrum_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_ochrum_brick_stairs_from_ochrum_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_ochrum_brick_stairs_from_ochrum_stonecutting.json deleted file mode 100644 index d55c11c34..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_ochrum_brick_stairs_from_ochrum_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_ochrum": { - "conditions": { - "items": [ - { - "items": [ - "create:ochrum" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_ochrum_brick_stairs_from_ochrum_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_ochrum", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_ochrum_brick_stairs_from_ochrum_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_ochrum_brick_wall_from_ochrum_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_ochrum_brick_wall_from_ochrum_stonecutting.json deleted file mode 100644 index 6cd1a26cc..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_ochrum_brick_wall_from_ochrum_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_ochrum": { - "conditions": { - "items": [ - { - "items": [ - "create:ochrum" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_ochrum_brick_wall_from_ochrum_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_ochrum", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_ochrum_brick_wall_from_ochrum_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_ochrum_bricks_from_ochrum_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_ochrum_bricks_from_ochrum_stonecutting.json deleted file mode 100644 index 7625e8907..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_ochrum_bricks_from_ochrum_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_ochrum": { - "conditions": { - "items": [ - { - "items": [ - "create:ochrum" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_ochrum_bricks_from_ochrum_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_ochrum", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_ochrum_bricks_from_ochrum_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_scorchia_brick_slab_from_scorchia_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_scorchia_brick_slab_from_scorchia_stonecutting.json deleted file mode 100644 index 6021a7000..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_scorchia_brick_slab_from_scorchia_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_scorchia": { - "conditions": { - "items": [ - { - "items": [ - "create:scorchia" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_scorchia_brick_slab_from_scorchia_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_scorchia", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_scorchia_brick_slab_from_scorchia_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_scorchia_brick_stairs_from_scorchia_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_scorchia_brick_stairs_from_scorchia_stonecutting.json deleted file mode 100644 index 34c8439e2..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_scorchia_brick_stairs_from_scorchia_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_scorchia": { - "conditions": { - "items": [ - { - "items": [ - "create:scorchia" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_scorchia_brick_stairs_from_scorchia_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_scorchia", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_scorchia_brick_stairs_from_scorchia_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_scorchia_brick_wall_from_scorchia_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_scorchia_brick_wall_from_scorchia_stonecutting.json deleted file mode 100644 index dcb0ae523..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_scorchia_brick_wall_from_scorchia_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_scorchia": { - "conditions": { - "items": [ - { - "items": [ - "create:scorchia" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_scorchia_brick_wall_from_scorchia_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_scorchia", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_scorchia_brick_wall_from_scorchia_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_scorchia_bricks_from_scorchia_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_scorchia_bricks_from_scorchia_stonecutting.json deleted file mode 100644 index 2ae176d62..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_scorchia_bricks_from_scorchia_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_scorchia": { - "conditions": { - "items": [ - { - "items": [ - "create:scorchia" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_scorchia_bricks_from_scorchia_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_scorchia", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_scorchia_bricks_from_scorchia_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_scoria_brick_slab_from_scoria_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_scoria_brick_slab_from_scoria_stonecutting.json deleted file mode 100644 index 59dd43c39..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_scoria_brick_slab_from_scoria_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_scoria": { - "conditions": { - "items": [ - { - "items": [ - "create:scoria" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_scoria_brick_slab_from_scoria_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_scoria", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_scoria_brick_slab_from_scoria_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_scoria_brick_stairs_from_scoria_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_scoria_brick_stairs_from_scoria_stonecutting.json deleted file mode 100644 index 971f9a211..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_scoria_brick_stairs_from_scoria_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_scoria": { - "conditions": { - "items": [ - { - "items": [ - "create:scoria" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_scoria_brick_stairs_from_scoria_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_scoria", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_scoria_brick_stairs_from_scoria_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_scoria_brick_wall_from_scoria_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_scoria_brick_wall_from_scoria_stonecutting.json deleted file mode 100644 index 11124ec35..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_scoria_brick_wall_from_scoria_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_scoria": { - "conditions": { - "items": [ - { - "items": [ - "create:scoria" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_scoria_brick_wall_from_scoria_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_scoria", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_scoria_brick_wall_from_scoria_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_scoria_bricks_from_scoria_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_scoria_bricks_from_scoria_stonecutting.json deleted file mode 100644 index ef46b578f..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_scoria_bricks_from_scoria_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_scoria": { - "conditions": { - "items": [ - { - "items": [ - "create:scoria" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:small_scoria_bricks_from_scoria_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_scoria", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_scoria_bricks_from_scoria_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_tuff_brick_slab_from_tuff_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_tuff_brick_slab_from_tuff_stonecutting.json deleted file mode 100644 index f835dd723..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_tuff_brick_slab_from_tuff_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_the_recipe": { - "conditions": { - "recipe": "create:small_tuff_brick_slab_from_tuff_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - }, - "has_tuff": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:tuff" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "requirements": [ - [ - "has_tuff", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_tuff_brick_slab_from_tuff_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_tuff_brick_stairs_from_tuff_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_tuff_brick_stairs_from_tuff_stonecutting.json deleted file mode 100644 index f31120ad4..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_tuff_brick_stairs_from_tuff_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_the_recipe": { - "conditions": { - "recipe": "create:small_tuff_brick_stairs_from_tuff_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - }, - "has_tuff": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:tuff" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "requirements": [ - [ - "has_tuff", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_tuff_brick_stairs_from_tuff_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_tuff_brick_wall_from_tuff_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_tuff_brick_wall_from_tuff_stonecutting.json deleted file mode 100644 index bc631f06f..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_tuff_brick_wall_from_tuff_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_the_recipe": { - "conditions": { - "recipe": "create:small_tuff_brick_wall_from_tuff_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - }, - "has_tuff": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:tuff" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "requirements": [ - [ - "has_tuff", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_tuff_brick_wall_from_tuff_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_tuff_bricks_from_tuff_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_tuff_bricks_from_tuff_stonecutting.json deleted file mode 100644 index 4210a71f9..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_tuff_bricks_from_tuff_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_the_recipe": { - "conditions": { - "recipe": "create:small_tuff_bricks_from_tuff_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - }, - "has_tuff": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:tuff" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "requirements": [ - [ - "has_tuff", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_tuff_bricks_from_tuff_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_veridium_brick_slab_from_veridium_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_veridium_brick_slab_from_veridium_stonecutting.json deleted file mode 100644 index 93ab7110f..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_veridium_brick_slab_from_veridium_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_the_recipe": { - "conditions": { - "recipe": "create:small_veridium_brick_slab_from_veridium_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - }, - "has_veridium": { - "conditions": { - "items": [ - { - "items": [ - "create:veridium" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "requirements": [ - [ - "has_veridium", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_veridium_brick_slab_from_veridium_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_veridium_brick_stairs_from_veridium_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_veridium_brick_stairs_from_veridium_stonecutting.json deleted file mode 100644 index 59b1b99b0..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_veridium_brick_stairs_from_veridium_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_the_recipe": { - "conditions": { - "recipe": "create:small_veridium_brick_stairs_from_veridium_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - }, - "has_veridium": { - "conditions": { - "items": [ - { - "items": [ - "create:veridium" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "requirements": [ - [ - "has_veridium", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_veridium_brick_stairs_from_veridium_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_veridium_brick_wall_from_veridium_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_veridium_brick_wall_from_veridium_stonecutting.json deleted file mode 100644 index 6a550a2df..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_veridium_brick_wall_from_veridium_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_the_recipe": { - "conditions": { - "recipe": "create:small_veridium_brick_wall_from_veridium_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - }, - "has_veridium": { - "conditions": { - "items": [ - { - "items": [ - "create:veridium" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "requirements": [ - [ - "has_veridium", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_veridium_brick_wall_from_veridium_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_veridium_bricks_from_veridium_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/small_veridium_bricks_from_veridium_stonecutting.json deleted file mode 100644 index aef29f137..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/small_veridium_bricks_from_veridium_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_the_recipe": { - "conditions": { - "recipe": "create:small_veridium_bricks_from_veridium_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - }, - "has_veridium": { - "conditions": { - "items": [ - { - "items": [ - "create:veridium" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "requirements": [ - [ - "has_veridium", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:small_veridium_bricks_from_veridium_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/tuff_from_stone_types_tuff_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/tuff_from_stone_types_tuff_stonecutting.json new file mode 100644 index 000000000..049b22090 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/tuff_from_stone_types_tuff_stonecutting.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_stone_types_tuff": { + "conditions": { + "items": [ + { + "tag": "create:stone_types/tuff" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:tuff_from_stone_types_tuff_stonecutting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_stone_types_tuff", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:tuff_from_stone_types_tuff_stonecutting" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/tuff_pillar_from_tuff_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/tuff_pillar_from_tuff_stonecutting.json deleted file mode 100644 index 92db9d0d9..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/tuff_pillar_from_tuff_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_the_recipe": { - "conditions": { - "recipe": "create:tuff_pillar_from_tuff_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - }, - "has_tuff": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:tuff" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "requirements": [ - [ - "has_tuff", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:tuff_pillar_from_tuff_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/veridium_from_stone_types_veridium_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/veridium_from_stone_types_veridium_stonecutting.json new file mode 100644 index 000000000..ea3a1a657 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/veridium_from_stone_types_veridium_stonecutting.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_stone_types_veridium": { + "conditions": { + "items": [ + { + "tag": "create:stone_types/veridium" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:veridium_from_stone_types_veridium_stonecutting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_stone_types_veridium", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:veridium_from_stone_types_veridium_stonecutting" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/veridium_pillar_from_veridium_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/veridium_pillar_from_veridium_stonecutting.json deleted file mode 100644 index 079491e2b..000000000 --- a/src/generated/resources/data/create/advancements/recipes/building_blocks/veridium_pillar_from_veridium_stonecutting.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_the_recipe": { - "conditions": { - "recipe": "create:veridium_pillar_from_veridium_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - }, - "has_veridium": { - "conditions": { - "items": [ - { - "items": [ - "create:veridium" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - } - }, - "requirements": [ - [ - "has_veridium", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:veridium_pillar_from_veridium_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/combat/crafting/appliances/netherite_backtank.json b/src/generated/resources/data/create/advancements/recipes/combat/crafting/appliances/netherite_backtank.json new file mode 100644 index 000000000..a28c6f7ae --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/combat/crafting/appliances/netherite_backtank.json @@ -0,0 +1,34 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:copper_backtank" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/appliances/netherite_backtank" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/appliances/netherite_backtank" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/combat/crafting/appliances/netherite_backtank_from_netherite.json b/src/generated/resources/data/create/advancements/recipes/combat/crafting/appliances/netherite_backtank_from_netherite.json new file mode 100644 index 000000000..5316b4c1e --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/combat/crafting/appliances/netherite_backtank_from_netherite.json @@ -0,0 +1,34 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "minecraft:netherite_chestplate" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/appliances/netherite_backtank_from_netherite" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/appliances/netherite_backtank_from_netherite" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/combat/crafting/appliances/netherite_diving_boots.json b/src/generated/resources/data/create/advancements/recipes/combat/crafting/appliances/netherite_diving_boots.json new file mode 100644 index 000000000..d524c7a52 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/combat/crafting/appliances/netherite_diving_boots.json @@ -0,0 +1,34 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:copper_diving_boots" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/appliances/netherite_diving_boots" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/appliances/netherite_diving_boots" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/combat/crafting/appliances/netherite_diving_boots_from_netherite.json b/src/generated/resources/data/create/advancements/recipes/combat/crafting/appliances/netherite_diving_boots_from_netherite.json new file mode 100644 index 000000000..807cc60d6 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/combat/crafting/appliances/netherite_diving_boots_from_netherite.json @@ -0,0 +1,34 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "minecraft:netherite_boots" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/appliances/netherite_diving_boots_from_netherite" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/appliances/netherite_diving_boots_from_netherite" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/combat/crafting/appliances/netherite_diving_helmet.json b/src/generated/resources/data/create/advancements/recipes/combat/crafting/appliances/netherite_diving_helmet.json new file mode 100644 index 000000000..fe8c9e0c1 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/combat/crafting/appliances/netherite_diving_helmet.json @@ -0,0 +1,34 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:copper_diving_helmet" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/appliances/netherite_diving_helmet" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/appliances/netherite_diving_helmet" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/combat/crafting/appliances/netherite_diving_helmet_from_netherite.json b/src/generated/resources/data/create/advancements/recipes/combat/crafting/appliances/netherite_diving_helmet_from_netherite.json new file mode 100644 index 000000000..3195f2ce6 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/combat/crafting/appliances/netherite_diving_helmet_from_netherite.json @@ -0,0 +1,34 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "minecraft:netherite_helmet" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/appliances/netherite_diving_helmet_from_netherite" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/appliances/netherite_diving_helmet_from_netherite" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/decorations/andesite_bars_from_andesite_alloy_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/decorations/andesite_bars_from_andesite_alloy_stonecutting.json new file mode 100644 index 000000000..05c3fa4ea --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/decorations/andesite_bars_from_andesite_alloy_stonecutting.json @@ -0,0 +1,34 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_andesite_alloy": { + "conditions": { + "items": [ + { + "items": [ + "create:andesite_alloy" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:andesite_bars_from_andesite_alloy_stonecutting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_andesite_alloy", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:andesite_bars_from_andesite_alloy_stonecutting" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/decorations/andesite_ladder_from_andesite_alloy_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/decorations/andesite_ladder_from_andesite_alloy_stonecutting.json new file mode 100644 index 000000000..54be084ef --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/decorations/andesite_ladder_from_andesite_alloy_stonecutting.json @@ -0,0 +1,34 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_andesite_alloy": { + "conditions": { + "items": [ + { + "items": [ + "create:andesite_alloy" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:andesite_ladder_from_andesite_alloy_stonecutting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_andesite_alloy", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:andesite_ladder_from_andesite_alloy_stonecutting" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/decorations/andesite_scaffolding_from_andesite_alloy_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/decorations/andesite_scaffolding_from_andesite_alloy_stonecutting.json new file mode 100644 index 000000000..f3b4f7d4b --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/decorations/andesite_scaffolding_from_andesite_alloy_stonecutting.json @@ -0,0 +1,34 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_andesite_alloy": { + "conditions": { + "items": [ + { + "items": [ + "create:andesite_alloy" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:andesite_scaffolding_from_andesite_alloy_stonecutting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_andesite_alloy", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:andesite_scaffolding_from_andesite_alloy_stonecutting" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/decorations/brass_bars_from_ingots_brass_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/decorations/brass_bars_from_ingots_brass_stonecutting.json new file mode 100644 index 000000000..09aa0f779 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/decorations/brass_bars_from_ingots_brass_stonecutting.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_ingots_brass": { + "conditions": { + "items": [ + { + "tag": "forge:ingots/brass" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:brass_bars_from_ingots_brass_stonecutting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_ingots_brass", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:brass_bars_from_ingots_brass_stonecutting" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/decorations/brass_ladder_from_ingots_brass_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/decorations/brass_ladder_from_ingots_brass_stonecutting.json new file mode 100644 index 000000000..8014a7986 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/decorations/brass_ladder_from_ingots_brass_stonecutting.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_ingots_brass": { + "conditions": { + "items": [ + { + "tag": "forge:ingots/brass" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:brass_ladder_from_ingots_brass_stonecutting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_ingots_brass", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:brass_ladder_from_ingots_brass_stonecutting" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/decorations/brass_ladder_from_plates_brass_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/decorations/brass_ladder_from_plates_brass_stonecutting.json deleted file mode 100644 index 7caceca52..000000000 --- a/src/generated/resources/data/create/advancements/recipes/decorations/brass_ladder_from_plates_brass_stonecutting.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_plates_brass": { - "conditions": { - "items": [ - { - "tag": "forge:plates/brass" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:brass_ladder_from_plates_brass_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_plates_brass", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:brass_ladder_from_plates_brass_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/decorations/brass_scaffolding_from_ingots_brass_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/decorations/brass_scaffolding_from_ingots_brass_stonecutting.json new file mode 100644 index 000000000..cf4ac7df7 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/decorations/brass_scaffolding_from_ingots_brass_stonecutting.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_ingots_brass": { + "conditions": { + "items": [ + { + "tag": "forge:ingots/brass" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:brass_scaffolding_from_ingots_brass_stonecutting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_ingots_brass", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:brass_scaffolding_from_ingots_brass_stonecutting" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/decorations/copper_bars_from_ingots_copper_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/decorations/copper_bars_from_ingots_copper_stonecutting.json new file mode 100644 index 000000000..1dcef3b8b --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/decorations/copper_bars_from_ingots_copper_stonecutting.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_ingots_copper": { + "conditions": { + "items": [ + { + "tag": "forge:ingots/copper" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:copper_bars_from_ingots_copper_stonecutting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_ingots_copper", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:copper_bars_from_ingots_copper_stonecutting" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/decorations/copper_ladder_from_ingots_copper_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/decorations/copper_ladder_from_ingots_copper_stonecutting.json new file mode 100644 index 000000000..00d2da06b --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/decorations/copper_ladder_from_ingots_copper_stonecutting.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_ingots_copper": { + "conditions": { + "items": [ + { + "tag": "forge:ingots/copper" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:copper_ladder_from_ingots_copper_stonecutting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_ingots_copper", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:copper_ladder_from_ingots_copper_stonecutting" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/decorations/copper_ladder_from_plates_copper_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/decorations/copper_ladder_from_plates_copper_stonecutting.json deleted file mode 100644 index e59a0a4d3..000000000 --- a/src/generated/resources/data/create/advancements/recipes/decorations/copper_ladder_from_plates_copper_stonecutting.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_plates_copper": { - "conditions": { - "items": [ - { - "tag": "forge:plates/copper" - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:copper_ladder_from_plates_copper_stonecutting" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_plates_copper", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:copper_ladder_from_plates_copper_stonecutting" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/decorations/copper_scaffolding_from_ingots_copper_stonecutting.json b/src/generated/resources/data/create/advancements/recipes/decorations/copper_scaffolding_from_ingots_copper_stonecutting.json new file mode 100644 index 000000000..6e231d21f --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/decorations/copper_scaffolding_from_ingots_copper_stonecutting.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_ingots_copper": { + "conditions": { + "items": [ + { + "tag": "forge:ingots/copper" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:copper_scaffolding_from_ingots_copper_stonecutting" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_ingots_copper", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:copper_scaffolding_from_ingots_copper_stonecutting" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/blasting/copper_ingot_from_crushed.json b/src/generated/resources/data/create/advancements/recipes/misc/blasting/copper_ingot_from_crushed.json index 356dded7a..fc70776a1 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/blasting/copper_ingot_from_crushed.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/blasting/copper_ingot_from_crushed.json @@ -6,7 +6,7 @@ "items": [ { "items": [ - "create:crushed_copper_ore" + "create:crushed_raw_copper" ] } ] diff --git a/src/generated/resources/data/create/advancements/recipes/misc/blasting/gold_ingot_from_crushed.json b/src/generated/resources/data/create/advancements/recipes/misc/blasting/gold_ingot_from_crushed.json index fdefe8a46..fe72e4c9e 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/blasting/gold_ingot_from_crushed.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/blasting/gold_ingot_from_crushed.json @@ -6,7 +6,7 @@ "items": [ { "items": [ - "create:crushed_gold_ore" + "create:crushed_raw_gold" ] } ] diff --git a/src/generated/resources/data/create/advancements/recipes/misc/blasting/ingot_aluminum_compat_immersiveengineering.json b/src/generated/resources/data/create/advancements/recipes/misc/blasting/ingot_aluminum_compat_immersiveengineering.json index 5fe37eca2..e54fe1dd4 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/blasting/ingot_aluminum_compat_immersiveengineering.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/blasting/ingot_aluminum_compat_immersiveengineering.json @@ -6,7 +6,7 @@ "items": [ { "items": [ - "create:crushed_aluminum_ore" + "create:crushed_raw_aluminum" ] } ] diff --git a/src/generated/resources/data/create/advancements/recipes/misc/blasting/ingot_lead_compat_immersiveengineering.json b/src/generated/resources/data/create/advancements/recipes/misc/blasting/ingot_lead_compat_immersiveengineering.json index 62b8f453c..bae49c78d 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/blasting/ingot_lead_compat_immersiveengineering.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/blasting/ingot_lead_compat_immersiveengineering.json @@ -6,7 +6,7 @@ "items": [ { "items": [ - "create:crushed_lead_ore" + "create:crushed_raw_lead" ] } ] diff --git a/src/generated/resources/data/create/advancements/recipes/misc/blasting/ingot_lead_compat_mekanism.json b/src/generated/resources/data/create/advancements/recipes/misc/blasting/ingot_lead_compat_mekanism.json index 1f48792df..6ac8d24a4 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/blasting/ingot_lead_compat_mekanism.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/blasting/ingot_lead_compat_mekanism.json @@ -6,7 +6,7 @@ "items": [ { "items": [ - "create:crushed_lead_ore" + "create:crushed_raw_lead" ] } ] diff --git a/src/generated/resources/data/create/advancements/recipes/misc/blasting/ingot_nickel_compat_immersiveengineering.json b/src/generated/resources/data/create/advancements/recipes/misc/blasting/ingot_nickel_compat_immersiveengineering.json index ef424f870..c6b9420eb 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/blasting/ingot_nickel_compat_immersiveengineering.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/blasting/ingot_nickel_compat_immersiveengineering.json @@ -6,7 +6,7 @@ "items": [ { "items": [ - "create:crushed_nickel_ore" + "create:crushed_raw_nickel" ] } ] diff --git a/src/generated/resources/data/create/advancements/recipes/misc/blasting/ingot_osmium_compat_mekanism.json b/src/generated/resources/data/create/advancements/recipes/misc/blasting/ingot_osmium_compat_mekanism.json index c283cd0b9..dbb8d3c58 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/blasting/ingot_osmium_compat_mekanism.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/blasting/ingot_osmium_compat_mekanism.json @@ -6,7 +6,7 @@ "items": [ { "items": [ - "create:crushed_osmium_ore" + "create:crushed_raw_osmium" ] } ] diff --git a/src/generated/resources/data/create/advancements/recipes/misc/blasting/ingot_silver_compat_immersiveengineering.json b/src/generated/resources/data/create/advancements/recipes/misc/blasting/ingot_silver_compat_immersiveengineering.json index 828401ba9..b5fea367b 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/blasting/ingot_silver_compat_immersiveengineering.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/blasting/ingot_silver_compat_immersiveengineering.json @@ -6,7 +6,7 @@ "items": [ { "items": [ - "create:crushed_silver_ore" + "create:crushed_raw_silver" ] } ] diff --git a/src/generated/resources/data/create/advancements/recipes/misc/blasting/ingot_tin_compat_mekanism.json b/src/generated/resources/data/create/advancements/recipes/misc/blasting/ingot_tin_compat_mekanism.json index ba97e5bcf..cea17350c 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/blasting/ingot_tin_compat_mekanism.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/blasting/ingot_tin_compat_mekanism.json @@ -6,7 +6,7 @@ "items": [ { "items": [ - "create:crushed_tin_ore" + "create:crushed_raw_tin" ] } ] diff --git a/src/generated/resources/data/create/advancements/recipes/misc/blasting/ingot_uranium_compat_immersiveengineering.json b/src/generated/resources/data/create/advancements/recipes/misc/blasting/ingot_uranium_compat_immersiveengineering.json index 68dd4ebe3..fbec5ca60 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/blasting/ingot_uranium_compat_immersiveengineering.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/blasting/ingot_uranium_compat_immersiveengineering.json @@ -6,7 +6,7 @@ "items": [ { "items": [ - "create:crushed_uranium_ore" + "create:crushed_raw_uranium" ] } ] diff --git a/src/generated/resources/data/create/advancements/recipes/misc/blasting/ingot_uranium_compat_mekanism.json b/src/generated/resources/data/create/advancements/recipes/misc/blasting/ingot_uranium_compat_mekanism.json index 13a55fb5e..21f2daa29 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/blasting/ingot_uranium_compat_mekanism.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/blasting/ingot_uranium_compat_mekanism.json @@ -6,7 +6,7 @@ "items": [ { "items": [ - "create:crushed_uranium_ore" + "create:crushed_raw_uranium" ] } ] diff --git a/src/generated/resources/data/create/advancements/recipes/misc/blasting/iron_ingot_from_crushed.json b/src/generated/resources/data/create/advancements/recipes/misc/blasting/iron_ingot_from_crushed.json index 084a55110..5203b2d51 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/blasting/iron_ingot_from_crushed.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/blasting/iron_ingot_from_crushed.json @@ -6,7 +6,7 @@ "items": [ { "items": [ - "create:crushed_iron_ore" + "create:crushed_raw_iron" ] } ] diff --git a/src/generated/resources/data/create/advancements/recipes/misc/blasting/lead_ingot_compat_thermal.json b/src/generated/resources/data/create/advancements/recipes/misc/blasting/lead_ingot_compat_thermal.json index 5bbb2a61e..7ca0d1fba 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/blasting/lead_ingot_compat_thermal.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/blasting/lead_ingot_compat_thermal.json @@ -6,7 +6,7 @@ "items": [ { "items": [ - "create:crushed_lead_ore" + "create:crushed_raw_lead" ] } ] diff --git a/src/generated/resources/data/create/advancements/recipes/misc/blasting/nickel_ingot_compat_thermal.json b/src/generated/resources/data/create/advancements/recipes/misc/blasting/nickel_ingot_compat_thermal.json index 95abf64c0..5779d78db 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/blasting/nickel_ingot_compat_thermal.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/blasting/nickel_ingot_compat_thermal.json @@ -6,7 +6,7 @@ "items": [ { "items": [ - "create:crushed_nickel_ore" + "create:crushed_raw_nickel" ] } ] diff --git a/src/generated/resources/data/create/advancements/recipes/misc/blasting/silver_ingot_compat_thermal.json b/src/generated/resources/data/create/advancements/recipes/misc/blasting/silver_ingot_compat_thermal.json index 30387da02..326062057 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/blasting/silver_ingot_compat_thermal.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/blasting/silver_ingot_compat_thermal.json @@ -6,7 +6,7 @@ "items": [ { "items": [ - "create:crushed_silver_ore" + "create:crushed_raw_silver" ] } ] diff --git a/src/generated/resources/data/create/advancements/recipes/misc/blasting/tin_ingot_compat_thermal.json b/src/generated/resources/data/create/advancements/recipes/misc/blasting/tin_ingot_compat_thermal.json index bc95145ae..36028208f 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/blasting/tin_ingot_compat_thermal.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/blasting/tin_ingot_compat_thermal.json @@ -6,7 +6,7 @@ "items": [ { "items": [ - "create:crushed_tin_ore" + "create:crushed_raw_tin" ] } ] diff --git a/src/generated/resources/data/create/advancements/recipes/misc/blasting/zinc_ingot_from_crushed.json b/src/generated/resources/data/create/advancements/recipes/misc/blasting/zinc_ingot_from_crushed.json index 75e4b604d..ed984e936 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/blasting/zinc_ingot_from_crushed.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/blasting/zinc_ingot_from_crushed.json @@ -6,7 +6,7 @@ "items": [ { "items": [ - "create:crushed_zinc_ore" + "create:crushed_raw_zinc" ] } ] diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/attribute_filter_clear.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/attribute_filter_clear.json new file mode 100644 index 000000000..df34ef788 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/attribute_filter_clear.json @@ -0,0 +1,34 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:attribute_filter" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/appliances/attribute_filter_clear" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/appliances/attribute_filter_clear" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/clipboard.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/clipboard.json new file mode 100644 index 000000000..736de1c09 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/clipboard.json @@ -0,0 +1,34 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:andesite_alloy" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/appliances/clipboard" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/appliances/clipboard" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/clipboard_clear.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/clipboard_clear.json new file mode 100644 index 000000000..e1bea76a7 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/clipboard_clear.json @@ -0,0 +1,34 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:clipboard" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/appliances/clipboard_clear" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/appliances/clipboard_clear" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/copper_diving_boots.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/copper_diving_boots.json new file mode 100644 index 000000000..2c2f238c8 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/copper_diving_boots.json @@ -0,0 +1,34 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "minecraft:copper_ingot" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/appliances/copper_diving_boots" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/appliances/copper_diving_boots" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/copper_diving_helmet.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/copper_diving_helmet.json new file mode 100644 index 000000000..b34e34917 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/copper_diving_helmet.json @@ -0,0 +1,34 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "minecraft:copper_ingot" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/appliances/copper_diving_helmet" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/appliances/copper_diving_helmet" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/diving_boots.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/diving_boots.json deleted file mode 100644 index fdbd9087b..000000000 --- a/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/diving_boots.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_item": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:copper_ingot" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:crafting/appliances/diving_boots" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_item", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:crafting/appliances/diving_boots" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/diving_helmet.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/diving_helmet.json deleted file mode 100644 index d9b9401c4..000000000 --- a/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/diving_helmet.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_item": { - "conditions": { - "items": [ - { - "items": [ - "minecraft:copper_ingot" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:crafting/appliances/diving_helmet" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_item", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:crafting/appliances/diving_helmet" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/filter_clear.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/filter_clear.json new file mode 100644 index 000000000..c04c9ea41 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/filter_clear.json @@ -0,0 +1,34 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:filter" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/appliances/filter_clear" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/appliances/filter_clear" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/schedule_clear.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/schedule_clear.json new file mode 100644 index 000000000..97aacb6a0 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/appliances/schedule_clear.json @@ -0,0 +1,34 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:schedule" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/appliances/schedule_clear" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/appliances/schedule_clear" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/andesite_door.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/andesite_door.json new file mode 100644 index 000000000..d84057d0e --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/andesite_door.json @@ -0,0 +1,34 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:andesite_casing" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/kinetics/andesite_door" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/kinetics/andesite_door" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/andesite_ladder.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/andesite_ladder.json deleted file mode 100644 index 7a0524120..000000000 --- a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/andesite_ladder.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_item": { - "conditions": { - "items": [ - { - "items": [ - "create:andesite_alloy" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:crafting/kinetics/andesite_ladder" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_item", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:crafting/kinetics/andesite_ladder" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/brass_door.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/brass_door.json new file mode 100644 index 000000000..ce6f865e3 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/brass_door.json @@ -0,0 +1,34 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:brass_casing" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/kinetics/brass_door" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/kinetics/brass_door" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/contraption_controls.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/contraption_controls.json new file mode 100644 index 000000000..3c7541ba7 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/contraption_controls.json @@ -0,0 +1,34 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:andesite_alloy" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/kinetics/contraption_controls" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/kinetics/contraption_controls" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/copper_door.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/copper_door.json new file mode 100644 index 000000000..d3e83ec42 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/copper_door.json @@ -0,0 +1,34 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:copper_casing" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/kinetics/copper_door" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/kinetics/copper_door" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/elevator_pulley.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/elevator_pulley.json new file mode 100644 index 000000000..590d1e163 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/elevator_pulley.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "tag": "forge:ingots/brass" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/kinetics/elevator_pulley" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/kinetics/elevator_pulley" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/large_cogwheel_from_little.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/large_cogwheel_from_little.json new file mode 100644 index 000000000..6f5e73c74 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/large_cogwheel_from_little.json @@ -0,0 +1,34 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:andesite_alloy" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/kinetics/large_cogwheel_from_little" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/kinetics/large_cogwheel_from_little" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/large_cogwheelfrom_little.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/large_cogwheelfrom_little.json deleted file mode 100644 index 89c1ee1fb..000000000 --- a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/large_cogwheelfrom_little.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_item": { - "conditions": { - "items": [ - { - "items": [ - "create:andesite_alloy" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:crafting/kinetics/large_cogwheelfrom_little" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_item", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:crafting/kinetics/large_cogwheelfrom_little" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/large_water_wheel.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/large_water_wheel.json new file mode 100644 index 000000000..78d860398 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/large_water_wheel.json @@ -0,0 +1,34 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:water_wheel" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/kinetics/large_water_wheel" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/kinetics/large_water_wheel" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/mechanical_roller.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/mechanical_roller.json new file mode 100644 index 000000000..3be97a0b2 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/mechanical_roller.json @@ -0,0 +1,34 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:andesite_casing" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/kinetics/mechanical_roller" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/kinetics/mechanical_roller" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/train_door.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/train_door.json index 222004675..0aa56dd1e 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/train_door.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/train_door.json @@ -5,7 +5,9 @@ "conditions": { "items": [ { - "tag": "forge:ingots/brass" + "items": [ + "create:railway_casing" + ] } ] }, diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/train_trapdoor.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/train_trapdoor.json index b316713f3..ce4c799a6 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/train_trapdoor.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/kinetics/train_trapdoor.json @@ -5,7 +5,9 @@ "conditions": { "items": [ { - "tag": "forge:ingots/brass" + "items": [ + "create:railway_casing" + ] } ] }, diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/content_observer.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/content_observer.json index 75966c8b5..e4b712096 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/content_observer.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/content_observer.json @@ -6,7 +6,7 @@ "items": [ { "items": [ - "create:belt_connector" + "create:brass_casing" ] } ] diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/content_observerfrom_conversion.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/content_observerfrom_conversion.json deleted file mode 100644 index 0302d87b8..000000000 --- a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/content_observerfrom_conversion.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_item": { - "conditions": { - "items": [ - { - "items": [ - "create:stockpile_switch" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:crafting/logistics/content_observerfrom_conversion" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_item", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:crafting/logistics/content_observerfrom_conversion" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/stockpile_switch.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/stockpile_switch.json new file mode 100644 index 000000000..5cc7df6a9 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/stockpile_switch.json @@ -0,0 +1,34 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:brass_casing" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/logistics/stockpile_switch" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/logistics/stockpile_switch" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/stockpile_switchfrom_conversion.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/stockpile_switchfrom_conversion.json deleted file mode 100644 index b7f0ea406..000000000 --- a/src/generated/resources/data/create/advancements/recipes/misc/crafting/logistics/stockpile_switchfrom_conversion.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "criteria": { - "has_item": { - "conditions": { - "items": [ - { - "items": [ - "create:content_observer" - ] - } - ] - }, - "trigger": "minecraft:inventory_changed" - }, - "has_the_recipe": { - "conditions": { - "recipe": "create:crafting/logistics/stockpile_switchfrom_conversion" - }, - "trigger": "minecraft:recipe_unlocked" - } - }, - "requirements": [ - [ - "has_item", - "has_the_recipe" - ] - ], - "rewards": { - "recipes": [ - "create:crafting/logistics/stockpile_switchfrom_conversion" - ] - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/andesite_alloy_block.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/andesite_alloy_block.json new file mode 100644 index 000000000..398447637 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/andesite_alloy_block.json @@ -0,0 +1,34 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:andesite_alloy" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/materials/andesite_alloy_block" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/materials/andesite_alloy_block" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/andesite_alloy_from_block.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/andesite_alloy_from_block.json new file mode 100644 index 000000000..d7f852c14 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/andesite_alloy_from_block.json @@ -0,0 +1,34 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:andesite_alloy" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/materials/andesite_alloy_from_block" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/materials/andesite_alloy_from_block" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/experience_block.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/experience_block.json new file mode 100644 index 000000000..a2e7b0fcd --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/experience_block.json @@ -0,0 +1,34 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:experience_nugget" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/materials/experience_block" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/materials/experience_block" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/experience_nugget_from_block.json b/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/experience_nugget_from_block.json new file mode 100644 index 000000000..6b1f24785 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/misc/crafting/materials/experience_nugget_from_block.json @@ -0,0 +1,34 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:experience_nugget" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "create:crafting/materials/experience_nugget_from_block" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "create:crafting/materials/experience_nugget_from_block" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/misc/smelting/copper_ingot_from_crushed.json b/src/generated/resources/data/create/advancements/recipes/misc/smelting/copper_ingot_from_crushed.json index 9590f4d98..23289d726 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/smelting/copper_ingot_from_crushed.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/smelting/copper_ingot_from_crushed.json @@ -6,7 +6,7 @@ "items": [ { "items": [ - "create:crushed_copper_ore" + "create:crushed_raw_copper" ] } ] diff --git a/src/generated/resources/data/create/advancements/recipes/misc/smelting/gold_ingot_from_crushed.json b/src/generated/resources/data/create/advancements/recipes/misc/smelting/gold_ingot_from_crushed.json index 528df67cc..6540e69b3 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/smelting/gold_ingot_from_crushed.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/smelting/gold_ingot_from_crushed.json @@ -6,7 +6,7 @@ "items": [ { "items": [ - "create:crushed_gold_ore" + "create:crushed_raw_gold" ] } ] diff --git a/src/generated/resources/data/create/advancements/recipes/misc/smelting/ingot_aluminum_compat_immersiveengineering.json b/src/generated/resources/data/create/advancements/recipes/misc/smelting/ingot_aluminum_compat_immersiveengineering.json index f825bd691..17e3fbf7f 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/smelting/ingot_aluminum_compat_immersiveengineering.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/smelting/ingot_aluminum_compat_immersiveengineering.json @@ -6,7 +6,7 @@ "items": [ { "items": [ - "create:crushed_aluminum_ore" + "create:crushed_raw_aluminum" ] } ] diff --git a/src/generated/resources/data/create/advancements/recipes/misc/smelting/ingot_lead_compat_immersiveengineering.json b/src/generated/resources/data/create/advancements/recipes/misc/smelting/ingot_lead_compat_immersiveengineering.json index ae0ae92a4..5aee1f149 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/smelting/ingot_lead_compat_immersiveengineering.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/smelting/ingot_lead_compat_immersiveengineering.json @@ -6,7 +6,7 @@ "items": [ { "items": [ - "create:crushed_lead_ore" + "create:crushed_raw_lead" ] } ] diff --git a/src/generated/resources/data/create/advancements/recipes/misc/smelting/ingot_lead_compat_mekanism.json b/src/generated/resources/data/create/advancements/recipes/misc/smelting/ingot_lead_compat_mekanism.json index 26a60a074..7c5fcfac7 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/smelting/ingot_lead_compat_mekanism.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/smelting/ingot_lead_compat_mekanism.json @@ -6,7 +6,7 @@ "items": [ { "items": [ - "create:crushed_lead_ore" + "create:crushed_raw_lead" ] } ] diff --git a/src/generated/resources/data/create/advancements/recipes/misc/smelting/ingot_nickel_compat_immersiveengineering.json b/src/generated/resources/data/create/advancements/recipes/misc/smelting/ingot_nickel_compat_immersiveengineering.json index 9369b3688..436c43fda 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/smelting/ingot_nickel_compat_immersiveengineering.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/smelting/ingot_nickel_compat_immersiveengineering.json @@ -6,7 +6,7 @@ "items": [ { "items": [ - "create:crushed_nickel_ore" + "create:crushed_raw_nickel" ] } ] diff --git a/src/generated/resources/data/create/advancements/recipes/misc/smelting/ingot_osmium_compat_mekanism.json b/src/generated/resources/data/create/advancements/recipes/misc/smelting/ingot_osmium_compat_mekanism.json index 9254a4838..bd9a8862b 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/smelting/ingot_osmium_compat_mekanism.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/smelting/ingot_osmium_compat_mekanism.json @@ -6,7 +6,7 @@ "items": [ { "items": [ - "create:crushed_osmium_ore" + "create:crushed_raw_osmium" ] } ] diff --git a/src/generated/resources/data/create/advancements/recipes/misc/smelting/ingot_silver_compat_immersiveengineering.json b/src/generated/resources/data/create/advancements/recipes/misc/smelting/ingot_silver_compat_immersiveengineering.json index efa5e1c8d..f248b7331 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/smelting/ingot_silver_compat_immersiveengineering.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/smelting/ingot_silver_compat_immersiveengineering.json @@ -6,7 +6,7 @@ "items": [ { "items": [ - "create:crushed_silver_ore" + "create:crushed_raw_silver" ] } ] diff --git a/src/generated/resources/data/create/advancements/recipes/misc/smelting/ingot_tin_compat_mekanism.json b/src/generated/resources/data/create/advancements/recipes/misc/smelting/ingot_tin_compat_mekanism.json index 58312b58a..cbd5f6309 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/smelting/ingot_tin_compat_mekanism.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/smelting/ingot_tin_compat_mekanism.json @@ -6,7 +6,7 @@ "items": [ { "items": [ - "create:crushed_tin_ore" + "create:crushed_raw_tin" ] } ] diff --git a/src/generated/resources/data/create/advancements/recipes/misc/smelting/ingot_uranium_compat_immersiveengineering.json b/src/generated/resources/data/create/advancements/recipes/misc/smelting/ingot_uranium_compat_immersiveengineering.json index 54014a9ae..3322935be 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/smelting/ingot_uranium_compat_immersiveengineering.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/smelting/ingot_uranium_compat_immersiveengineering.json @@ -6,7 +6,7 @@ "items": [ { "items": [ - "create:crushed_uranium_ore" + "create:crushed_raw_uranium" ] } ] diff --git a/src/generated/resources/data/create/advancements/recipes/misc/smelting/ingot_uranium_compat_mekanism.json b/src/generated/resources/data/create/advancements/recipes/misc/smelting/ingot_uranium_compat_mekanism.json index 585d06f07..67b73862a 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/smelting/ingot_uranium_compat_mekanism.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/smelting/ingot_uranium_compat_mekanism.json @@ -6,7 +6,7 @@ "items": [ { "items": [ - "create:crushed_uranium_ore" + "create:crushed_raw_uranium" ] } ] diff --git a/src/generated/resources/data/create/advancements/recipes/misc/smelting/iron_ingot_from_crushed.json b/src/generated/resources/data/create/advancements/recipes/misc/smelting/iron_ingot_from_crushed.json index c5c7ac2d5..63ed3feb2 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/smelting/iron_ingot_from_crushed.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/smelting/iron_ingot_from_crushed.json @@ -6,7 +6,7 @@ "items": [ { "items": [ - "create:crushed_iron_ore" + "create:crushed_raw_iron" ] } ] diff --git a/src/generated/resources/data/create/advancements/recipes/misc/smelting/lead_ingot_compat_thermal.json b/src/generated/resources/data/create/advancements/recipes/misc/smelting/lead_ingot_compat_thermal.json index 9513518e0..7c24b32f3 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/smelting/lead_ingot_compat_thermal.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/smelting/lead_ingot_compat_thermal.json @@ -6,7 +6,7 @@ "items": [ { "items": [ - "create:crushed_lead_ore" + "create:crushed_raw_lead" ] } ] diff --git a/src/generated/resources/data/create/advancements/recipes/misc/smelting/nickel_ingot_compat_thermal.json b/src/generated/resources/data/create/advancements/recipes/misc/smelting/nickel_ingot_compat_thermal.json index d3889529e..1d442d1a2 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/smelting/nickel_ingot_compat_thermal.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/smelting/nickel_ingot_compat_thermal.json @@ -6,7 +6,7 @@ "items": [ { "items": [ - "create:crushed_nickel_ore" + "create:crushed_raw_nickel" ] } ] diff --git a/src/generated/resources/data/create/advancements/recipes/misc/smelting/silver_ingot_compat_thermal.json b/src/generated/resources/data/create/advancements/recipes/misc/smelting/silver_ingot_compat_thermal.json index f9b0d9d17..77ca02140 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/smelting/silver_ingot_compat_thermal.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/smelting/silver_ingot_compat_thermal.json @@ -6,7 +6,7 @@ "items": [ { "items": [ - "create:crushed_silver_ore" + "create:crushed_raw_silver" ] } ] diff --git a/src/generated/resources/data/create/advancements/recipes/misc/smelting/tin_ingot_compat_thermal.json b/src/generated/resources/data/create/advancements/recipes/misc/smelting/tin_ingot_compat_thermal.json index ebbb5d3fd..cc154d1e5 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/smelting/tin_ingot_compat_thermal.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/smelting/tin_ingot_compat_thermal.json @@ -6,7 +6,7 @@ "items": [ { "items": [ - "create:crushed_tin_ore" + "create:crushed_raw_tin" ] } ] diff --git a/src/generated/resources/data/create/advancements/recipes/misc/smelting/zinc_ingot_from_crushed.json b/src/generated/resources/data/create/advancements/recipes/misc/smelting/zinc_ingot_from_crushed.json index 0880d87dd..568157356 100644 --- a/src/generated/resources/data/create/advancements/recipes/misc/smelting/zinc_ingot_from_crushed.json +++ b/src/generated/resources/data/create/advancements/recipes/misc/smelting/zinc_ingot_from_crushed.json @@ -6,7 +6,7 @@ "items": [ { "items": [ - "create:crushed_zinc_ore" + "create:crushed_raw_zinc" ] } ] diff --git a/src/generated/resources/data/create/loot_tables/blocks/andesite_alloy_block.json b/src/generated/resources/data/create/loot_tables/blocks/andesite_alloy_block.json new file mode 100644 index 000000000..b22614cd5 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/andesite_alloy_block.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:andesite_alloy_block" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/andesite_bars.json b/src/generated/resources/data/create/loot_tables/blocks/andesite_bars.json new file mode 100644 index 000000000..2bc75f3b3 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/andesite_bars.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:andesite_bars" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/andesite_door.json b/src/generated/resources/data/create/loot_tables/blocks/andesite_door.json new file mode 100644 index 000000000..f452c3132 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/andesite_door.json @@ -0,0 +1,29 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "conditions": [ + { + "block": "create:andesite_door", + "condition": "minecraft:block_state_property", + "properties": { + "half": "lower" + } + } + ], + "name": "create:andesite_door" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/andesite_scaffolding.json b/src/generated/resources/data/create/loot_tables/blocks/andesite_scaffolding.json new file mode 100644 index 000000000..70f62d0dc --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/andesite_scaffolding.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:andesite_scaffolding" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/brass_bars.json b/src/generated/resources/data/create/loot_tables/blocks/brass_bars.json new file mode 100644 index 000000000..737ae5569 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/brass_bars.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:brass_bars" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/brass_door.json b/src/generated/resources/data/create/loot_tables/blocks/brass_door.json new file mode 100644 index 000000000..81a679f5c --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/brass_door.json @@ -0,0 +1,29 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "conditions": [ + { + "block": "create:brass_door", + "condition": "minecraft:block_state_property", + "properties": { + "half": "lower" + } + } + ], + "name": "create:brass_door" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/brass_scaffolding.json b/src/generated/resources/data/create/loot_tables/blocks/brass_scaffolding.json new file mode 100644 index 000000000..8e781fa89 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/brass_scaffolding.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:brass_scaffolding" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/clipboard.json b/src/generated/resources/data/create/loot_tables/blocks/clipboard.json new file mode 100644 index 000000000..68701f9f6 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/clipboard.json @@ -0,0 +1,3 @@ +{ + "type": "minecraft:block" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/contraption_controls.json b/src/generated/resources/data/create/loot_tables/blocks/contraption_controls.json new file mode 100644 index 000000000..56429a7df --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/contraption_controls.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:contraption_controls" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/copper_bars.json b/src/generated/resources/data/create/loot_tables/blocks/copper_bars.json new file mode 100644 index 000000000..4dec04ca5 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/copper_bars.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:copper_bars" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/copper_door.json b/src/generated/resources/data/create/loot_tables/blocks/copper_door.json new file mode 100644 index 000000000..d1981762d --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/copper_door.json @@ -0,0 +1,29 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "conditions": [ + { + "block": "create:copper_door", + "condition": "minecraft:block_state_property", + "properties": { + "half": "lower" + } + } + ], + "name": "create:copper_door" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/copper_scaffolding.json b/src/generated/resources/data/create/loot_tables/blocks/copper_scaffolding.json new file mode 100644 index 000000000..bfbcad3f9 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/copper_scaffolding.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:copper_scaffolding" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/copycat_bars.json b/src/generated/resources/data/create/loot_tables/blocks/copycat_bars.json new file mode 100644 index 000000000..38fe9914a --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/copycat_bars.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "minecraft:air" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/copycat_base.json b/src/generated/resources/data/create/loot_tables/blocks/copycat_base.json new file mode 100644 index 000000000..38fe9914a --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/copycat_base.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "minecraft:air" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/copycat_panel.json b/src/generated/resources/data/create/loot_tables/blocks/copycat_panel.json new file mode 100644 index 000000000..69e4906af --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/copycat_panel.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:copycat_panel" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/copycat_step.json b/src/generated/resources/data/create/loot_tables/blocks/copycat_step.json new file mode 100644 index 000000000..244ba65ca --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/copycat_step.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:copycat_step" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/elevator_contact.json b/src/generated/resources/data/create/loot_tables/blocks/elevator_contact.json new file mode 100644 index 000000000..e6e5a5f99 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/elevator_contact.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:redstone_contact" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/elevator_pulley.json b/src/generated/resources/data/create/loot_tables/blocks/elevator_pulley.json new file mode 100644 index 000000000..3ef60c4ac --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/elevator_pulley.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:elevator_pulley" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/experience_block.json b/src/generated/resources/data/create/loot_tables/blocks/experience_block.json new file mode 100644 index 000000000..40231da41 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/experience_block.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:experience_block" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/industrial_iron_block.json b/src/generated/resources/data/create/loot_tables/blocks/industrial_iron_block.json new file mode 100644 index 000000000..1ac94eada --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/industrial_iron_block.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:industrial_iron_block" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/large_water_wheel.json b/src/generated/resources/data/create/loot_tables/blocks/large_water_wheel.json new file mode 100644 index 000000000..8fdefec60 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/large_water_wheel.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:large_water_wheel" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/mangrove_window.json b/src/generated/resources/data/create/loot_tables/blocks/mangrove_window.json new file mode 100644 index 000000000..fbffc276e --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/mangrove_window.json @@ -0,0 +1,30 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:match_tool", + "predicate": { + "enchantments": [ + { + "enchantment": "minecraft:silk_touch", + "levels": { + "min": 1 + } + } + ] + } + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:mangrove_window" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/mangrove_window_pane.json b/src/generated/resources/data/create/loot_tables/blocks/mangrove_window_pane.json new file mode 100644 index 000000000..9cd224a49 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/mangrove_window_pane.json @@ -0,0 +1,30 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:match_tool", + "predicate": { + "enchantments": [ + { + "enchantment": "minecraft:silk_touch", + "levels": { + "min": 1 + } + } + ] + } + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:mangrove_window_pane" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/mechanical_roller.json b/src/generated/resources/data/create/loot_tables/blocks/mechanical_roller.json new file mode 100644 index 000000000..0632837b4 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/mechanical_roller.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "create:mechanical_roller" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/netherite_backtank.json b/src/generated/resources/data/create/loot_tables/blocks/netherite_backtank.json new file mode 100644 index 000000000..5ccb82ad0 --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/netherite_backtank.json @@ -0,0 +1,48 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:copy_name", + "source": "block_entity" + }, + { + "function": "minecraft:copy_nbt", + "ops": [ + { + "op": "replace", + "source": "Air", + "target": "Air" + } + ], + "source": "block_entity" + }, + { + "function": "minecraft:copy_nbt", + "ops": [ + { + "op": "replace", + "source": "Enchantments", + "target": "Enchantments" + } + ], + "source": "block_entity" + } + ], + "name": "create:netherite_backtank" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/loot_tables/blocks/water_wheel_structure.json b/src/generated/resources/data/create/loot_tables/blocks/water_wheel_structure.json new file mode 100644 index 000000000..38fe9914a --- /dev/null +++ b/src/generated/resources/data/create/loot_tables/blocks/water_wheel_structure.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "minecraft:air" + } + ], + "rolls": 1.0 + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/andesite_bars_from_andesite_alloy_stonecutting.json b/src/generated/resources/data/create/recipes/andesite_bars_from_andesite_alloy_stonecutting.json new file mode 100644 index 000000000..31814ee34 --- /dev/null +++ b/src/generated/resources/data/create/recipes/andesite_bars_from_andesite_alloy_stonecutting.json @@ -0,0 +1,8 @@ +{ + "type": "minecraft:stonecutting", + "count": 4, + "ingredient": { + "item": "create:andesite_alloy" + }, + "result": "create:andesite_bars" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/andesite_from_stone_types_andesite_stonecutting.json b/src/generated/resources/data/create/recipes/andesite_from_stone_types_andesite_stonecutting.json new file mode 100644 index 000000000..8183a5d85 --- /dev/null +++ b/src/generated/resources/data/create/recipes/andesite_from_stone_types_andesite_stonecutting.json @@ -0,0 +1,8 @@ +{ + "type": "minecraft:stonecutting", + "count": 1, + "ingredient": { + "tag": "create:stone_types/andesite" + }, + "result": "minecraft:andesite" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/andesite_ladder_from_andesite_alloy_stonecutting.json b/src/generated/resources/data/create/recipes/andesite_ladder_from_andesite_alloy_stonecutting.json new file mode 100644 index 000000000..31e929496 --- /dev/null +++ b/src/generated/resources/data/create/recipes/andesite_ladder_from_andesite_alloy_stonecutting.json @@ -0,0 +1,8 @@ +{ + "type": "minecraft:stonecutting", + "count": 2, + "ingredient": { + "item": "create:andesite_alloy" + }, + "result": "create:andesite_ladder" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/andesite_pillar_from_andesite_stonecutting.json b/src/generated/resources/data/create/recipes/andesite_pillar_from_andesite_stonecutting.json deleted file mode 100644 index 8b4f2e2ca..000000000 --- a/src/generated/resources/data/create/recipes/andesite_pillar_from_andesite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:andesite" - }, - "result": "create:andesite_pillar" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/andesite_scaffolding_from_andesite_alloy_stonecutting.json b/src/generated/resources/data/create/recipes/andesite_scaffolding_from_andesite_alloy_stonecutting.json new file mode 100644 index 000000000..04bd6b21f --- /dev/null +++ b/src/generated/resources/data/create/recipes/andesite_scaffolding_from_andesite_alloy_stonecutting.json @@ -0,0 +1,8 @@ +{ + "type": "minecraft:stonecutting", + "count": 2, + "ingredient": { + "item": "create:andesite_alloy" + }, + "result": "create:andesite_scaffolding" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/asurine_from_stone_types_asurine_stonecutting.json b/src/generated/resources/data/create/recipes/asurine_from_stone_types_asurine_stonecutting.json new file mode 100644 index 000000000..76c1cdba2 --- /dev/null +++ b/src/generated/resources/data/create/recipes/asurine_from_stone_types_asurine_stonecutting.json @@ -0,0 +1,8 @@ +{ + "type": "minecraft:stonecutting", + "count": 1, + "ingredient": { + "tag": "create:stone_types/asurine" + }, + "result": "create:asurine" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/asurine_pillar_from_asurine_stonecutting.json b/src/generated/resources/data/create/recipes/asurine_pillar_from_asurine_stonecutting.json deleted file mode 100644 index 79f97bddc..000000000 --- a/src/generated/resources/data/create/recipes/asurine_pillar_from_asurine_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:asurine" - }, - "result": "create:asurine_pillar" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/blasting/copper_ingot_from_crushed.json b/src/generated/resources/data/create/recipes/blasting/copper_ingot_from_crushed.json index 667874e3a..0ec95f7e3 100644 --- a/src/generated/resources/data/create/recipes/blasting/copper_ingot_from_crushed.json +++ b/src/generated/resources/data/create/recipes/blasting/copper_ingot_from_crushed.json @@ -4,7 +4,7 @@ "cookingtime": 100, "experience": 0.1, "ingredient": { - "item": "create:crushed_copper_ore" + "item": "create:crushed_raw_copper" }, "result": "minecraft:copper_ingot" } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/blasting/gold_ingot_from_crushed.json b/src/generated/resources/data/create/recipes/blasting/gold_ingot_from_crushed.json index ef914169f..5deb38209 100644 --- a/src/generated/resources/data/create/recipes/blasting/gold_ingot_from_crushed.json +++ b/src/generated/resources/data/create/recipes/blasting/gold_ingot_from_crushed.json @@ -4,7 +4,7 @@ "cookingtime": 100, "experience": 0.1, "ingredient": { - "item": "create:crushed_gold_ore" + "item": "create:crushed_raw_gold" }, "result": "minecraft:gold_ingot" } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/blasting/ingot_aluminum_compat_immersiveengineering.json b/src/generated/resources/data/create/recipes/blasting/ingot_aluminum_compat_immersiveengineering.json index 952d2c6ef..c6f469a0b 100644 --- a/src/generated/resources/data/create/recipes/blasting/ingot_aluminum_compat_immersiveengineering.json +++ b/src/generated/resources/data/create/recipes/blasting/ingot_aluminum_compat_immersiveengineering.json @@ -10,7 +10,7 @@ "cookingtime": 100, "experience": 0.1, "ingredient": { - "item": "create:crushed_aluminum_ore" + "item": "create:crushed_raw_aluminum" }, "result": "immersiveengineering:ingot_aluminum" } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/blasting/ingot_lead_compat_immersiveengineering.json b/src/generated/resources/data/create/recipes/blasting/ingot_lead_compat_immersiveengineering.json index 910ca3abc..60b0320ab 100644 --- a/src/generated/resources/data/create/recipes/blasting/ingot_lead_compat_immersiveengineering.json +++ b/src/generated/resources/data/create/recipes/blasting/ingot_lead_compat_immersiveengineering.json @@ -10,7 +10,7 @@ "cookingtime": 100, "experience": 0.1, "ingredient": { - "item": "create:crushed_lead_ore" + "item": "create:crushed_raw_lead" }, "result": "immersiveengineering:ingot_lead" } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/blasting/ingot_lead_compat_mekanism.json b/src/generated/resources/data/create/recipes/blasting/ingot_lead_compat_mekanism.json index d21553af9..cfe7188a1 100644 --- a/src/generated/resources/data/create/recipes/blasting/ingot_lead_compat_mekanism.json +++ b/src/generated/resources/data/create/recipes/blasting/ingot_lead_compat_mekanism.json @@ -10,7 +10,7 @@ "cookingtime": 100, "experience": 0.1, "ingredient": { - "item": "create:crushed_lead_ore" + "item": "create:crushed_raw_lead" }, "result": "mekanism:ingot_lead" } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/blasting/ingot_nickel_compat_immersiveengineering.json b/src/generated/resources/data/create/recipes/blasting/ingot_nickel_compat_immersiveengineering.json index 6c03f87a0..0be5a5ba2 100644 --- a/src/generated/resources/data/create/recipes/blasting/ingot_nickel_compat_immersiveengineering.json +++ b/src/generated/resources/data/create/recipes/blasting/ingot_nickel_compat_immersiveengineering.json @@ -10,7 +10,7 @@ "cookingtime": 100, "experience": 0.1, "ingredient": { - "item": "create:crushed_nickel_ore" + "item": "create:crushed_raw_nickel" }, "result": "immersiveengineering:ingot_nickel" } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/blasting/ingot_osmium_compat_mekanism.json b/src/generated/resources/data/create/recipes/blasting/ingot_osmium_compat_mekanism.json index 571c1eb90..df416aeca 100644 --- a/src/generated/resources/data/create/recipes/blasting/ingot_osmium_compat_mekanism.json +++ b/src/generated/resources/data/create/recipes/blasting/ingot_osmium_compat_mekanism.json @@ -10,7 +10,7 @@ "cookingtime": 100, "experience": 0.1, "ingredient": { - "item": "create:crushed_osmium_ore" + "item": "create:crushed_raw_osmium" }, "result": "mekanism:ingot_osmium" } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/blasting/ingot_silver_compat_immersiveengineering.json b/src/generated/resources/data/create/recipes/blasting/ingot_silver_compat_immersiveengineering.json index bf0c86ded..b159d0839 100644 --- a/src/generated/resources/data/create/recipes/blasting/ingot_silver_compat_immersiveengineering.json +++ b/src/generated/resources/data/create/recipes/blasting/ingot_silver_compat_immersiveengineering.json @@ -10,7 +10,7 @@ "cookingtime": 100, "experience": 0.1, "ingredient": { - "item": "create:crushed_silver_ore" + "item": "create:crushed_raw_silver" }, "result": "immersiveengineering:ingot_silver" } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/blasting/ingot_tin_compat_mekanism.json b/src/generated/resources/data/create/recipes/blasting/ingot_tin_compat_mekanism.json index b30ff13e7..9869f5bd8 100644 --- a/src/generated/resources/data/create/recipes/blasting/ingot_tin_compat_mekanism.json +++ b/src/generated/resources/data/create/recipes/blasting/ingot_tin_compat_mekanism.json @@ -10,7 +10,7 @@ "cookingtime": 100, "experience": 0.1, "ingredient": { - "item": "create:crushed_tin_ore" + "item": "create:crushed_raw_tin" }, "result": "mekanism:ingot_tin" } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/blasting/ingot_uranium_compat_immersiveengineering.json b/src/generated/resources/data/create/recipes/blasting/ingot_uranium_compat_immersiveengineering.json index a59e8a03a..f46f32a09 100644 --- a/src/generated/resources/data/create/recipes/blasting/ingot_uranium_compat_immersiveengineering.json +++ b/src/generated/resources/data/create/recipes/blasting/ingot_uranium_compat_immersiveengineering.json @@ -10,7 +10,7 @@ "cookingtime": 100, "experience": 0.1, "ingredient": { - "item": "create:crushed_uranium_ore" + "item": "create:crushed_raw_uranium" }, "result": "immersiveengineering:ingot_uranium" } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/blasting/ingot_uranium_compat_mekanism.json b/src/generated/resources/data/create/recipes/blasting/ingot_uranium_compat_mekanism.json index f48fa4257..51c759646 100644 --- a/src/generated/resources/data/create/recipes/blasting/ingot_uranium_compat_mekanism.json +++ b/src/generated/resources/data/create/recipes/blasting/ingot_uranium_compat_mekanism.json @@ -10,7 +10,7 @@ "cookingtime": 100, "experience": 0.1, "ingredient": { - "item": "create:crushed_uranium_ore" + "item": "create:crushed_raw_uranium" }, "result": "mekanism:ingot_uranium" } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/blasting/iron_ingot_from_crushed.json b/src/generated/resources/data/create/recipes/blasting/iron_ingot_from_crushed.json index d5be06cba..9fa35f105 100644 --- a/src/generated/resources/data/create/recipes/blasting/iron_ingot_from_crushed.json +++ b/src/generated/resources/data/create/recipes/blasting/iron_ingot_from_crushed.json @@ -4,7 +4,7 @@ "cookingtime": 100, "experience": 0.1, "ingredient": { - "item": "create:crushed_iron_ore" + "item": "create:crushed_raw_iron" }, "result": "minecraft:iron_ingot" } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/blasting/lead_ingot_compat_thermal.json b/src/generated/resources/data/create/recipes/blasting/lead_ingot_compat_thermal.json index 7b4b053ba..319ab038b 100644 --- a/src/generated/resources/data/create/recipes/blasting/lead_ingot_compat_thermal.json +++ b/src/generated/resources/data/create/recipes/blasting/lead_ingot_compat_thermal.json @@ -10,7 +10,7 @@ "cookingtime": 100, "experience": 0.1, "ingredient": { - "item": "create:crushed_lead_ore" + "item": "create:crushed_raw_lead" }, "result": "thermal:lead_ingot" } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/blasting/nickel_ingot_compat_thermal.json b/src/generated/resources/data/create/recipes/blasting/nickel_ingot_compat_thermal.json index 662153193..f15096fc6 100644 --- a/src/generated/resources/data/create/recipes/blasting/nickel_ingot_compat_thermal.json +++ b/src/generated/resources/data/create/recipes/blasting/nickel_ingot_compat_thermal.json @@ -10,7 +10,7 @@ "cookingtime": 100, "experience": 0.1, "ingredient": { - "item": "create:crushed_nickel_ore" + "item": "create:crushed_raw_nickel" }, "result": "thermal:nickel_ingot" } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/blasting/silver_ingot_compat_thermal.json b/src/generated/resources/data/create/recipes/blasting/silver_ingot_compat_thermal.json index d9ff2067e..5cd35a888 100644 --- a/src/generated/resources/data/create/recipes/blasting/silver_ingot_compat_thermal.json +++ b/src/generated/resources/data/create/recipes/blasting/silver_ingot_compat_thermal.json @@ -10,7 +10,7 @@ "cookingtime": 100, "experience": 0.1, "ingredient": { - "item": "create:crushed_silver_ore" + "item": "create:crushed_raw_silver" }, "result": "thermal:silver_ingot" } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/blasting/tin_ingot_compat_thermal.json b/src/generated/resources/data/create/recipes/blasting/tin_ingot_compat_thermal.json index da39dc84c..b976189ea 100644 --- a/src/generated/resources/data/create/recipes/blasting/tin_ingot_compat_thermal.json +++ b/src/generated/resources/data/create/recipes/blasting/tin_ingot_compat_thermal.json @@ -10,7 +10,7 @@ "cookingtime": 100, "experience": 0.1, "ingredient": { - "item": "create:crushed_tin_ore" + "item": "create:crushed_raw_tin" }, "result": "thermal:tin_ingot" } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/blasting/zinc_ingot_from_crushed.json b/src/generated/resources/data/create/recipes/blasting/zinc_ingot_from_crushed.json index f2784b83c..e77a846d4 100644 --- a/src/generated/resources/data/create/recipes/blasting/zinc_ingot_from_crushed.json +++ b/src/generated/resources/data/create/recipes/blasting/zinc_ingot_from_crushed.json @@ -4,7 +4,7 @@ "cookingtime": 100, "experience": 0.1, "ingredient": { - "item": "create:crushed_zinc_ore" + "item": "create:crushed_raw_zinc" }, "result": "create:zinc_ingot" } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/brass_bars_from_ingots_brass_stonecutting.json b/src/generated/resources/data/create/recipes/brass_bars_from_ingots_brass_stonecutting.json new file mode 100644 index 000000000..ce62220e7 --- /dev/null +++ b/src/generated/resources/data/create/recipes/brass_bars_from_ingots_brass_stonecutting.json @@ -0,0 +1,8 @@ +{ + "type": "minecraft:stonecutting", + "count": 4, + "ingredient": { + "tag": "forge:ingots/brass" + }, + "result": "create:brass_bars" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/brass_ladder_from_ingots_brass_stonecutting.json b/src/generated/resources/data/create/recipes/brass_ladder_from_ingots_brass_stonecutting.json new file mode 100644 index 000000000..0d81937f0 --- /dev/null +++ b/src/generated/resources/data/create/recipes/brass_ladder_from_ingots_brass_stonecutting.json @@ -0,0 +1,8 @@ +{ + "type": "minecraft:stonecutting", + "count": 2, + "ingredient": { + "tag": "forge:ingots/brass" + }, + "result": "create:brass_ladder" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/brass_ladder_from_plates_brass_stonecutting.json b/src/generated/resources/data/create/recipes/brass_ladder_from_plates_brass_stonecutting.json deleted file mode 100644 index 17cd1c26f..000000000 --- a/src/generated/resources/data/create/recipes/brass_ladder_from_plates_brass_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "tag": "forge:plates/brass" - }, - "result": "create:brass_ladder" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/brass_scaffolding_from_ingots_brass_stonecutting.json b/src/generated/resources/data/create/recipes/brass_scaffolding_from_ingots_brass_stonecutting.json new file mode 100644 index 000000000..901543231 --- /dev/null +++ b/src/generated/resources/data/create/recipes/brass_scaffolding_from_ingots_brass_stonecutting.json @@ -0,0 +1,8 @@ +{ + "type": "minecraft:stonecutting", + "count": 2, + "ingredient": { + "tag": "forge:ingots/brass" + }, + "result": "create:brass_scaffolding" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/calcite_from_stone_types_calcite_stonecutting.json b/src/generated/resources/data/create/recipes/calcite_from_stone_types_calcite_stonecutting.json new file mode 100644 index 000000000..e4f0283c3 --- /dev/null +++ b/src/generated/resources/data/create/recipes/calcite_from_stone_types_calcite_stonecutting.json @@ -0,0 +1,8 @@ +{ + "type": "minecraft:stonecutting", + "count": 1, + "ingredient": { + "tag": "create:stone_types/calcite" + }, + "result": "minecraft:calcite" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/calcite_pillar_from_calcite_stonecutting.json b/src/generated/resources/data/create/recipes/calcite_pillar_from_calcite_stonecutting.json deleted file mode 100644 index b8a94fa18..000000000 --- a/src/generated/resources/data/create/recipes/calcite_pillar_from_calcite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:calcite" - }, - "result": "create:calcite_pillar" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/copper_bars_from_ingots_copper_stonecutting.json b/src/generated/resources/data/create/recipes/copper_bars_from_ingots_copper_stonecutting.json new file mode 100644 index 000000000..49b0aad61 --- /dev/null +++ b/src/generated/resources/data/create/recipes/copper_bars_from_ingots_copper_stonecutting.json @@ -0,0 +1,8 @@ +{ + "type": "minecraft:stonecutting", + "count": 4, + "ingredient": { + "tag": "forge:ingots/copper" + }, + "result": "create:copper_bars" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/copper_ladder_from_ingots_copper_stonecutting.json b/src/generated/resources/data/create/recipes/copper_ladder_from_ingots_copper_stonecutting.json new file mode 100644 index 000000000..046aed0b3 --- /dev/null +++ b/src/generated/resources/data/create/recipes/copper_ladder_from_ingots_copper_stonecutting.json @@ -0,0 +1,8 @@ +{ + "type": "minecraft:stonecutting", + "count": 2, + "ingredient": { + "tag": "forge:ingots/copper" + }, + "result": "create:copper_ladder" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/copper_ladder_from_plates_copper_stonecutting.json b/src/generated/resources/data/create/recipes/copper_ladder_from_plates_copper_stonecutting.json deleted file mode 100644 index 86e34acf5..000000000 --- a/src/generated/resources/data/create/recipes/copper_ladder_from_plates_copper_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "tag": "forge:plates/copper" - }, - "result": "create:copper_ladder" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/copper_scaffolding_from_ingots_copper_stonecutting.json b/src/generated/resources/data/create/recipes/copper_scaffolding_from_ingots_copper_stonecutting.json new file mode 100644 index 000000000..93a993149 --- /dev/null +++ b/src/generated/resources/data/create/recipes/copper_scaffolding_from_ingots_copper_stonecutting.json @@ -0,0 +1,8 @@ +{ + "type": "minecraft:stonecutting", + "count": 2, + "ingredient": { + "tag": "forge:ingots/copper" + }, + "result": "create:copper_scaffolding" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/copper_shingles_from_ingots_copper_stonecutting.json b/src/generated/resources/data/create/recipes/copper_shingles_from_ingots_copper_stonecutting.json new file mode 100644 index 000000000..7cbf53c1d --- /dev/null +++ b/src/generated/resources/data/create/recipes/copper_shingles_from_ingots_copper_stonecutting.json @@ -0,0 +1,8 @@ +{ + "type": "minecraft:stonecutting", + "count": 2, + "ingredient": { + "tag": "forge:ingots/copper" + }, + "result": "create:copper_shingles" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/copper_shingles_from_plates_copper_stonecutting.json b/src/generated/resources/data/create/recipes/copper_shingles_from_plates_copper_stonecutting.json deleted file mode 100644 index 93953a4d2..000000000 --- a/src/generated/resources/data/create/recipes/copper_shingles_from_plates_copper_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "tag": "forge:plates/copper" - }, - "result": "create:copper_shingles" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/copper_tiles_from_ingots_copper_stonecutting.json b/src/generated/resources/data/create/recipes/copper_tiles_from_ingots_copper_stonecutting.json new file mode 100644 index 000000000..10cd247b3 --- /dev/null +++ b/src/generated/resources/data/create/recipes/copper_tiles_from_ingots_copper_stonecutting.json @@ -0,0 +1,8 @@ +{ + "type": "minecraft:stonecutting", + "count": 2, + "ingredient": { + "tag": "forge:ingots/copper" + }, + "result": "create:copper_tiles" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/copper_tiles_from_plates_copper_stonecutting.json b/src/generated/resources/data/create/recipes/copper_tiles_from_plates_copper_stonecutting.json deleted file mode 100644 index 85e3b85d7..000000000 --- a/src/generated/resources/data/create/recipes/copper_tiles_from_plates_copper_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "tag": "forge:plates/copper" - }, - "result": "create:copper_tiles" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/copycat_panel_from_ingots_zinc_stonecutting.json b/src/generated/resources/data/create/recipes/copycat_panel_from_ingots_zinc_stonecutting.json new file mode 100644 index 000000000..30c78b204 --- /dev/null +++ b/src/generated/resources/data/create/recipes/copycat_panel_from_ingots_zinc_stonecutting.json @@ -0,0 +1,8 @@ +{ + "type": "minecraft:stonecutting", + "count": 4, + "ingredient": { + "tag": "forge:ingots/zinc" + }, + "result": "create:copycat_panel" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/copycat_step_from_ingots_zinc_stonecutting.json b/src/generated/resources/data/create/recipes/copycat_step_from_ingots_zinc_stonecutting.json new file mode 100644 index 000000000..9f02e272f --- /dev/null +++ b/src/generated/resources/data/create/recipes/copycat_step_from_ingots_zinc_stonecutting.json @@ -0,0 +1,8 @@ +{ + "type": "minecraft:stonecutting", + "count": 4, + "ingredient": { + "tag": "forge:ingots/zinc" + }, + "result": "create:copycat_step" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/appliances/attribute_filter_clear.json b/src/generated/resources/data/create/recipes/crafting/appliances/attribute_filter_clear.json new file mode 100644 index 000000000..acce3d930 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/appliances/attribute_filter_clear.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:attribute_filter" + } + ], + "result": { + "item": "create:attribute_filter" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/appliances/clipboard.json b/src/generated/resources/data/create/recipes/crafting/appliances/clipboard.json new file mode 100644 index 000000000..f5b312361 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/appliances/clipboard.json @@ -0,0 +1,23 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "A": { + "item": "create:andesite_alloy" + }, + "G": { + "tag": "minecraft:planks" + }, + "P": { + "item": "minecraft:paper" + } + }, + "pattern": [ + "A", + "P", + "G" + ], + "result": { + "item": "create:clipboard" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/appliances/clipboard_clear.json b/src/generated/resources/data/create/recipes/crafting/appliances/clipboard_clear.json new file mode 100644 index 000000000..2f19bb096 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/appliances/clipboard_clear.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:clipboard" + } + ], + "result": { + "item": "create:clipboard" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/appliances/copper_diving_boots.json b/src/generated/resources/data/create/recipes/crafting/appliances/copper_diving_boots.json new file mode 100644 index 000000000..7480d3d78 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/appliances/copper_diving_boots.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "G": { + "item": "create:andesite_alloy" + }, + "P": { + "item": "minecraft:copper_ingot" + } + }, + "pattern": [ + "P P", + "P P", + "G G" + ], + "result": { + "item": "create:copper_diving_boots" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/appliances/copper_diving_helmet.json b/src/generated/resources/data/create/recipes/crafting/appliances/copper_diving_helmet.json new file mode 100644 index 000000000..63ac703c2 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/appliances/copper_diving_helmet.json @@ -0,0 +1,19 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "G": { + "tag": "forge:glass" + }, + "P": { + "item": "minecraft:copper_ingot" + } + }, + "pattern": [ + "PPP", + "PGP" + ], + "result": { + "item": "create:copper_diving_helmet" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/appliances/diving_boots.json b/src/generated/resources/data/create/recipes/crafting/appliances/diving_boots.json deleted file mode 100644 index d685cee94..000000000 --- a/src/generated/resources/data/create/recipes/crafting/appliances/diving_boots.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "misc", - "key": { - "G": { - "item": "create:andesite_alloy" - }, - "P": { - "item": "minecraft:copper_ingot" - } - }, - "pattern": [ - "P P", - "P P", - "G G" - ], - "result": { - "item": "create:diving_boots" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/appliances/diving_helmet.json b/src/generated/resources/data/create/recipes/crafting/appliances/diving_helmet.json deleted file mode 100644 index 83951d054..000000000 --- a/src/generated/resources/data/create/recipes/crafting/appliances/diving_helmet.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "misc", - "key": { - "G": { - "tag": "forge:glass" - }, - "P": { - "item": "minecraft:copper_ingot" - } - }, - "pattern": [ - "PPP", - "PGP" - ], - "result": { - "item": "create:diving_helmet" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/appliances/filter_clear.json b/src/generated/resources/data/create/recipes/crafting/appliances/filter_clear.json new file mode 100644 index 000000000..2b31b094a --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/appliances/filter_clear.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:filter" + } + ], + "result": { + "item": "create:filter" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/appliances/netherite_backtank.json b/src/generated/resources/data/create/recipes/crafting/appliances/netherite_backtank.json new file mode 100644 index 000000000..953fa491b --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/appliances/netherite_backtank.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:smithing", + "addition": { + "tag": "forge:ingots/netherite" + }, + "base": { + "item": "create:copper_backtank" + }, + "result": { + "item": "create:netherite_backtank" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/appliances/netherite_backtank_from_netherite.json b/src/generated/resources/data/create/recipes/crafting/appliances/netherite_backtank_from_netherite.json new file mode 100644 index 000000000..46e4143ca --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/appliances/netherite_backtank_from_netherite.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:smithing", + "addition": { + "item": "create:copper_backtank" + }, + "base": { + "item": "minecraft:netherite_chestplate" + }, + "result": { + "item": "create:netherite_backtank" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/appliances/netherite_diving_boots.json b/src/generated/resources/data/create/recipes/crafting/appliances/netherite_diving_boots.json new file mode 100644 index 000000000..05e7f4238 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/appliances/netherite_diving_boots.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:smithing", + "addition": { + "tag": "forge:ingots/netherite" + }, + "base": { + "item": "create:copper_diving_boots" + }, + "result": { + "item": "create:netherite_diving_boots" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/appliances/netherite_diving_boots_from_netherite.json b/src/generated/resources/data/create/recipes/crafting/appliances/netherite_diving_boots_from_netherite.json new file mode 100644 index 000000000..3b47e1129 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/appliances/netherite_diving_boots_from_netherite.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:smithing", + "addition": { + "item": "create:copper_diving_boots" + }, + "base": { + "item": "minecraft:netherite_boots" + }, + "result": { + "item": "create:netherite_diving_boots" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/appliances/netherite_diving_helmet.json b/src/generated/resources/data/create/recipes/crafting/appliances/netherite_diving_helmet.json new file mode 100644 index 000000000..33b59881d --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/appliances/netherite_diving_helmet.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:smithing", + "addition": { + "tag": "forge:ingots/netherite" + }, + "base": { + "item": "create:copper_diving_helmet" + }, + "result": { + "item": "create:netherite_diving_helmet" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/appliances/netherite_diving_helmet_from_netherite.json b/src/generated/resources/data/create/recipes/crafting/appliances/netherite_diving_helmet_from_netherite.json new file mode 100644 index 000000000..f7a2c0c90 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/appliances/netherite_diving_helmet_from_netherite.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:smithing", + "addition": { + "item": "create:copper_diving_helmet" + }, + "base": { + "item": "minecraft:netherite_helmet" + }, + "result": { + "item": "create:netherite_diving_helmet" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/appliances/schedule_clear.json b/src/generated/resources/data/create/recipes/crafting/appliances/schedule_clear.json new file mode 100644 index 000000000..9e08bf2cf --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/appliances/schedule_clear.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:schedule" + } + ], + "result": { + "item": "create:schedule" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/andesite_door.json b/src/generated/resources/data/create/recipes/crafting/kinetics/andesite_door.json new file mode 100644 index 000000000..94129c11c --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/andesite_door.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "tag": "minecraft:wooden_doors" + }, + { + "item": "create:andesite_casing" + } + ], + "result": { + "item": "create:andesite_door" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/andesite_ladder.json b/src/generated/resources/data/create/recipes/crafting/kinetics/andesite_ladder.json deleted file mode 100644 index da599e63c..000000000 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/andesite_ladder.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "category": "misc", - "key": { - "A": { - "item": "create:andesite_alloy" - } - }, - "pattern": [ - "A A", - "AAA", - "A A" - ], - "result": { - "count": 4, - "item": "create:andesite_ladder" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/black_seat.json b/src/generated/resources/data/create/recipes/crafting/kinetics/black_seat.json index 7190703d8..8bb127510 100644 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/black_seat.json +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/black_seat.json @@ -1,6 +1,6 @@ { "type": "minecraft:crafting_shapeless", - "category": "misc", + "category": "building", "ingredients": [ { "item": "minecraft:black_wool" diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/black_seat_from_other_seat.json b/src/generated/resources/data/create/recipes/crafting/kinetics/black_seat_from_other_seat.json index ab3a642dc..de3102dcc 100644 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/black_seat_from_other_seat.json +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/black_seat_from_other_seat.json @@ -1,6 +1,6 @@ { "type": "minecraft:crafting_shapeless", - "category": "misc", + "category": "building", "ingredients": [ { "tag": "forge:dyes/black" diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/blue_seat.json b/src/generated/resources/data/create/recipes/crafting/kinetics/blue_seat.json index c9d371788..9abc84c3d 100644 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/blue_seat.json +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/blue_seat.json @@ -1,6 +1,6 @@ { "type": "minecraft:crafting_shapeless", - "category": "misc", + "category": "building", "ingredients": [ { "item": "minecraft:blue_wool" diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/blue_seat_from_other_seat.json b/src/generated/resources/data/create/recipes/crafting/kinetics/blue_seat_from_other_seat.json index 402020a04..871805762 100644 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/blue_seat_from_other_seat.json +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/blue_seat_from_other_seat.json @@ -1,6 +1,6 @@ { "type": "minecraft:crafting_shapeless", - "category": "misc", + "category": "building", "ingredients": [ { "tag": "forge:dyes/blue" diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/brass_door.json b/src/generated/resources/data/create/recipes/crafting/kinetics/brass_door.json new file mode 100644 index 000000000..4d9b706b7 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/brass_door.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "tag": "minecraft:wooden_doors" + }, + { + "item": "create:brass_casing" + } + ], + "result": { + "item": "create:brass_door" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/brown_seat.json b/src/generated/resources/data/create/recipes/crafting/kinetics/brown_seat.json index 375640a4b..965992d7d 100644 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/brown_seat.json +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/brown_seat.json @@ -1,6 +1,6 @@ { "type": "minecraft:crafting_shapeless", - "category": "misc", + "category": "building", "ingredients": [ { "item": "minecraft:brown_wool" diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/brown_seat_from_other_seat.json b/src/generated/resources/data/create/recipes/crafting/kinetics/brown_seat_from_other_seat.json index 092236b8a..62542746a 100644 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/brown_seat_from_other_seat.json +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/brown_seat_from_other_seat.json @@ -1,6 +1,6 @@ { "type": "minecraft:crafting_shapeless", - "category": "misc", + "category": "building", "ingredients": [ { "tag": "forge:dyes/brown" diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/contraption_controls.json b/src/generated/resources/data/create/recipes/crafting/kinetics/contraption_controls.json new file mode 100644 index 000000000..8a701f8a0 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/contraption_controls.json @@ -0,0 +1,23 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "B": { + "tag": "minecraft:buttons" + }, + "C": { + "item": "create:andesite_casing" + }, + "I": { + "item": "create:electron_tube" + } + }, + "pattern": [ + "B", + "C", + "I" + ], + "result": { + "item": "create:contraption_controls" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/copper_door.json b/src/generated/resources/data/create/recipes/crafting/kinetics/copper_door.json new file mode 100644 index 000000000..3e83762cb --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/copper_door.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "tag": "minecraft:wooden_doors" + }, + { + "item": "create:copper_casing" + } + ], + "result": { + "item": "create:copper_door" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/cyan_seat.json b/src/generated/resources/data/create/recipes/crafting/kinetics/cyan_seat.json index ada6955ee..94495e1cc 100644 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/cyan_seat.json +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/cyan_seat.json @@ -1,6 +1,6 @@ { "type": "minecraft:crafting_shapeless", - "category": "misc", + "category": "building", "ingredients": [ { "item": "minecraft:cyan_wool" diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/cyan_seat_from_other_seat.json b/src/generated/resources/data/create/recipes/crafting/kinetics/cyan_seat_from_other_seat.json index 60d4117c3..bff05e3b0 100644 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/cyan_seat_from_other_seat.json +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/cyan_seat_from_other_seat.json @@ -1,6 +1,6 @@ { "type": "minecraft:crafting_shapeless", - "category": "misc", + "category": "building", "ingredients": [ { "tag": "forge:dyes/cyan" diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/elevator_pulley.json b/src/generated/resources/data/create/recipes/crafting/kinetics/elevator_pulley.json new file mode 100644 index 000000000..1c51e8b95 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/elevator_pulley.json @@ -0,0 +1,23 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "B": { + "item": "create:brass_casing" + }, + "C": { + "item": "minecraft:dried_kelp_block" + }, + "I": { + "tag": "forge:plates/iron" + } + }, + "pattern": [ + "B", + "C", + "I" + ], + "result": { + "item": "create:elevator_pulley" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/gray_seat.json b/src/generated/resources/data/create/recipes/crafting/kinetics/gray_seat.json index aacbf7e40..05d356e41 100644 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/gray_seat.json +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/gray_seat.json @@ -1,6 +1,6 @@ { "type": "minecraft:crafting_shapeless", - "category": "misc", + "category": "building", "ingredients": [ { "item": "minecraft:gray_wool" diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/gray_seat_from_other_seat.json b/src/generated/resources/data/create/recipes/crafting/kinetics/gray_seat_from_other_seat.json index 2559dbd46..ff1814642 100644 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/gray_seat_from_other_seat.json +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/gray_seat_from_other_seat.json @@ -1,6 +1,6 @@ { "type": "minecraft:crafting_shapeless", - "category": "misc", + "category": "building", "ingredients": [ { "tag": "forge:dyes/gray" diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/green_seat.json b/src/generated/resources/data/create/recipes/crafting/kinetics/green_seat.json index 56dcd811a..4e724fdaa 100644 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/green_seat.json +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/green_seat.json @@ -1,6 +1,6 @@ { "type": "minecraft:crafting_shapeless", - "category": "misc", + "category": "building", "ingredients": [ { "item": "minecraft:green_wool" diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/green_seat_from_other_seat.json b/src/generated/resources/data/create/recipes/crafting/kinetics/green_seat_from_other_seat.json index 4ad3f581c..842f11855 100644 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/green_seat_from_other_seat.json +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/green_seat_from_other_seat.json @@ -1,6 +1,6 @@ { "type": "minecraft:crafting_shapeless", - "category": "misc", + "category": "building", "ingredients": [ { "tag": "forge:dyes/green" diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/large_cogwheelfrom_little.json b/src/generated/resources/data/create/recipes/crafting/kinetics/large_cogwheel_from_little.json similarity index 100% rename from src/generated/resources/data/create/recipes/crafting/kinetics/large_cogwheelfrom_little.json rename to src/generated/resources/data/create/recipes/crafting/kinetics/large_cogwheel_from_little.json diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/large_water_wheel.json b/src/generated/resources/data/create/recipes/crafting/kinetics/large_water_wheel.json new file mode 100644 index 000000000..85b279f81 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/large_water_wheel.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "C": { + "item": "create:water_wheel" + }, + "S": { + "tag": "minecraft:planks" + } + }, + "pattern": [ + "SSS", + "SCS", + "SSS" + ], + "result": { + "item": "create:large_water_wheel" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/light_blue_seat.json b/src/generated/resources/data/create/recipes/crafting/kinetics/light_blue_seat.json index 3feef0a32..a2a30858d 100644 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/light_blue_seat.json +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/light_blue_seat.json @@ -1,6 +1,6 @@ { "type": "minecraft:crafting_shapeless", - "category": "misc", + "category": "building", "ingredients": [ { "item": "minecraft:light_blue_wool" diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/light_blue_seat_from_other_seat.json b/src/generated/resources/data/create/recipes/crafting/kinetics/light_blue_seat_from_other_seat.json index 3b85a07b6..57f64ada1 100644 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/light_blue_seat_from_other_seat.json +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/light_blue_seat_from_other_seat.json @@ -1,6 +1,6 @@ { "type": "minecraft:crafting_shapeless", - "category": "misc", + "category": "building", "ingredients": [ { "tag": "forge:dyes/light_blue" diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/light_gray_seat.json b/src/generated/resources/data/create/recipes/crafting/kinetics/light_gray_seat.json index 32a9cd262..3290863b1 100644 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/light_gray_seat.json +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/light_gray_seat.json @@ -1,6 +1,6 @@ { "type": "minecraft:crafting_shapeless", - "category": "misc", + "category": "building", "ingredients": [ { "item": "minecraft:light_gray_wool" diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/light_gray_seat_from_other_seat.json b/src/generated/resources/data/create/recipes/crafting/kinetics/light_gray_seat_from_other_seat.json index a8dc69255..32a230f8d 100644 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/light_gray_seat_from_other_seat.json +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/light_gray_seat_from_other_seat.json @@ -1,6 +1,6 @@ { "type": "minecraft:crafting_shapeless", - "category": "misc", + "category": "building", "ingredients": [ { "tag": "forge:dyes/light_gray" diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/lime_seat.json b/src/generated/resources/data/create/recipes/crafting/kinetics/lime_seat.json index 1695e84e6..7ce964507 100644 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/lime_seat.json +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/lime_seat.json @@ -1,6 +1,6 @@ { "type": "minecraft:crafting_shapeless", - "category": "misc", + "category": "building", "ingredients": [ { "item": "minecraft:lime_wool" diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/lime_seat_from_other_seat.json b/src/generated/resources/data/create/recipes/crafting/kinetics/lime_seat_from_other_seat.json index 2501ae6a9..cc792d9ff 100644 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/lime_seat_from_other_seat.json +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/lime_seat_from_other_seat.json @@ -1,6 +1,6 @@ { "type": "minecraft:crafting_shapeless", - "category": "misc", + "category": "building", "ingredients": [ { "tag": "forge:dyes/lime" diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/magenta_seat.json b/src/generated/resources/data/create/recipes/crafting/kinetics/magenta_seat.json index ae80f0b12..4d048c575 100644 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/magenta_seat.json +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/magenta_seat.json @@ -1,6 +1,6 @@ { "type": "minecraft:crafting_shapeless", - "category": "misc", + "category": "building", "ingredients": [ { "item": "minecraft:magenta_wool" diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/magenta_seat_from_other_seat.json b/src/generated/resources/data/create/recipes/crafting/kinetics/magenta_seat_from_other_seat.json index 2032db5ee..23a383a72 100644 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/magenta_seat_from_other_seat.json +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/magenta_seat_from_other_seat.json @@ -1,6 +1,6 @@ { "type": "minecraft:crafting_shapeless", - "category": "misc", + "category": "building", "ingredients": [ { "tag": "forge:dyes/magenta" diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/mechanical_roller.json b/src/generated/resources/data/create/recipes/crafting/kinetics/mechanical_roller.json new file mode 100644 index 000000000..f789c271f --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/mechanical_roller.json @@ -0,0 +1,23 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "A": { + "item": "create:electron_tube" + }, + "C": { + "item": "create:andesite_casing" + }, + "I": { + "item": "create:crushing_wheel" + } + }, + "pattern": [ + "A", + "C", + "I" + ], + "result": { + "item": "create:mechanical_roller" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/orange_seat.json b/src/generated/resources/data/create/recipes/crafting/kinetics/orange_seat.json index fee38dda8..3dc46de48 100644 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/orange_seat.json +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/orange_seat.json @@ -1,6 +1,6 @@ { "type": "minecraft:crafting_shapeless", - "category": "misc", + "category": "building", "ingredients": [ { "item": "minecraft:orange_wool" diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/orange_seat_from_other_seat.json b/src/generated/resources/data/create/recipes/crafting/kinetics/orange_seat_from_other_seat.json index da7721b4b..fecc29fdb 100644 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/orange_seat_from_other_seat.json +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/orange_seat_from_other_seat.json @@ -1,6 +1,6 @@ { "type": "minecraft:crafting_shapeless", - "category": "misc", + "category": "building", "ingredients": [ { "tag": "forge:dyes/orange" diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/pink_seat.json b/src/generated/resources/data/create/recipes/crafting/kinetics/pink_seat.json index 7e1ae3e43..d7622d6fe 100644 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/pink_seat.json +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/pink_seat.json @@ -1,6 +1,6 @@ { "type": "minecraft:crafting_shapeless", - "category": "misc", + "category": "building", "ingredients": [ { "item": "minecraft:pink_wool" diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/pink_seat_from_other_seat.json b/src/generated/resources/data/create/recipes/crafting/kinetics/pink_seat_from_other_seat.json index 2d8888861..1f50f964d 100644 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/pink_seat_from_other_seat.json +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/pink_seat_from_other_seat.json @@ -1,6 +1,6 @@ { "type": "minecraft:crafting_shapeless", - "category": "misc", + "category": "building", "ingredients": [ { "tag": "forge:dyes/pink" diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/purple_seat.json b/src/generated/resources/data/create/recipes/crafting/kinetics/purple_seat.json index 1798de571..e5559476c 100644 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/purple_seat.json +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/purple_seat.json @@ -1,6 +1,6 @@ { "type": "minecraft:crafting_shapeless", - "category": "misc", + "category": "building", "ingredients": [ { "item": "minecraft:purple_wool" diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/purple_seat_from_other_seat.json b/src/generated/resources/data/create/recipes/crafting/kinetics/purple_seat_from_other_seat.json index cb543661e..0c02f7cfe 100644 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/purple_seat_from_other_seat.json +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/purple_seat_from_other_seat.json @@ -1,6 +1,6 @@ { "type": "minecraft:crafting_shapeless", - "category": "misc", + "category": "building", "ingredients": [ { "tag": "forge:dyes/purple" diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/red_seat.json b/src/generated/resources/data/create/recipes/crafting/kinetics/red_seat.json index 380a1a6f0..16723ff4c 100644 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/red_seat.json +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/red_seat.json @@ -1,6 +1,6 @@ { "type": "minecraft:crafting_shapeless", - "category": "misc", + "category": "building", "ingredients": [ { "item": "minecraft:red_wool" diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/red_seat_from_other_seat.json b/src/generated/resources/data/create/recipes/crafting/kinetics/red_seat_from_other_seat.json index 689cac6ef..8477a2531 100644 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/red_seat_from_other_seat.json +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/red_seat_from_other_seat.json @@ -1,6 +1,6 @@ { "type": "minecraft:crafting_shapeless", - "category": "misc", + "category": "building", "ingredients": [ { "tag": "forge:dyes/red" diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/train_door.json b/src/generated/resources/data/create/recipes/crafting/kinetics/train_door.json index 272a7e979..12cdf53fa 100644 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/train_door.json +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/train_door.json @@ -6,7 +6,7 @@ "tag": "minecraft:wooden_doors" }, { - "tag": "forge:plates/brass" + "item": "create:railway_casing" } ], "result": { diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/train_trapdoor.json b/src/generated/resources/data/create/recipes/crafting/kinetics/train_trapdoor.json index 3c2ddbe7b..b5dbd0765 100644 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/train_trapdoor.json +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/train_trapdoor.json @@ -6,7 +6,7 @@ "tag": "minecraft:wooden_trapdoors" }, { - "tag": "forge:plates/brass" + "item": "create:railway_casing" } ], "result": { diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/water_wheel.json b/src/generated/resources/data/create/recipes/crafting/kinetics/water_wheel.json index 57b4e4872..2fb033d36 100644 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/water_wheel.json +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/water_wheel.json @@ -3,10 +3,10 @@ "category": "misc", "key": { "C": { - "item": "create:large_cogwheel" + "item": "create:shaft" }, "S": { - "tag": "minecraft:wooden_slabs" + "tag": "minecraft:planks" } }, "pattern": [ diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/white_seat.json b/src/generated/resources/data/create/recipes/crafting/kinetics/white_seat.json index 5d107475d..967b400e8 100644 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/white_seat.json +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/white_seat.json @@ -1,6 +1,6 @@ { "type": "minecraft:crafting_shapeless", - "category": "misc", + "category": "building", "ingredients": [ { "item": "minecraft:white_wool" diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/white_seat_from_other_seat.json b/src/generated/resources/data/create/recipes/crafting/kinetics/white_seat_from_other_seat.json index 165c30736..146b5bcea 100644 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/white_seat_from_other_seat.json +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/white_seat_from_other_seat.json @@ -1,6 +1,6 @@ { "type": "minecraft:crafting_shapeless", - "category": "misc", + "category": "building", "ingredients": [ { "tag": "forge:dyes/white" diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/yellow_seat.json b/src/generated/resources/data/create/recipes/crafting/kinetics/yellow_seat.json index fd4829b3e..692236fd3 100644 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/yellow_seat.json +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/yellow_seat.json @@ -1,6 +1,6 @@ { "type": "minecraft:crafting_shapeless", - "category": "misc", + "category": "building", "ingredients": [ { "item": "minecraft:yellow_wool" diff --git a/src/generated/resources/data/create/recipes/crafting/kinetics/yellow_seat_from_other_seat.json b/src/generated/resources/data/create/recipes/crafting/kinetics/yellow_seat_from_other_seat.json index 94df16514..11e47c42a 100644 --- a/src/generated/resources/data/create/recipes/crafting/kinetics/yellow_seat_from_other_seat.json +++ b/src/generated/resources/data/create/recipes/crafting/kinetics/yellow_seat_from_other_seat.json @@ -1,6 +1,6 @@ { "type": "minecraft:crafting_shapeless", - "category": "misc", + "category": "building", "ingredients": [ { "tag": "forge:dyes/yellow" diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/content_observer.json b/src/generated/resources/data/create/recipes/crafting/logistics/content_observer.json index bb7702f59..0ad718a0b 100644 --- a/src/generated/resources/data/create/recipes/crafting/logistics/content_observer.json +++ b/src/generated/resources/data/create/recipes/crafting/logistics/content_observer.json @@ -6,16 +6,16 @@ "item": "create:brass_casing" }, "I": { - "item": "minecraft:comparator" + "item": "minecraft:observer" }, "R": { "item": "create:electron_tube" } }, "pattern": [ - "I", + "R", "B", - "R" + "I" ], "result": { "item": "create:content_observer" diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/content_observerfrom_conversion.json b/src/generated/resources/data/create/recipes/crafting/logistics/content_observerfrom_conversion.json deleted file mode 100644 index 8069646f6..000000000 --- a/src/generated/resources/data/create/recipes/crafting/logistics/content_observerfrom_conversion.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "type": "minecraft:crafting_shapeless", - "category": "misc", - "ingredients": [ - { - "item": "create:stockpile_switch" - } - ], - "result": { - "item": "create:content_observer" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/stockpile_switch.json b/src/generated/resources/data/create/recipes/crafting/logistics/stockpile_switch.json new file mode 100644 index 000000000..e8d523376 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/logistics/stockpile_switch.json @@ -0,0 +1,23 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "B": { + "item": "create:brass_casing" + }, + "I": { + "item": "minecraft:comparator" + }, + "R": { + "item": "create:electron_tube" + } + }, + "pattern": [ + "R", + "B", + "I" + ], + "result": { + "item": "create:stockpile_switch" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/logistics/stockpile_switchfrom_conversion.json b/src/generated/resources/data/create/recipes/crafting/logistics/stockpile_switchfrom_conversion.json deleted file mode 100644 index cb20acc0b..000000000 --- a/src/generated/resources/data/create/recipes/crafting/logistics/stockpile_switchfrom_conversion.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "type": "minecraft:crafting_shapeless", - "category": "misc", - "ingredients": [ - { - "item": "create:content_observer" - } - ], - "result": { - "item": "create:stockpile_switch" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/materials/andesite_alloy_block.json b/src/generated/resources/data/create/recipes/crafting/materials/andesite_alloy_block.json new file mode 100644 index 000000000..d9e91870d --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/materials/andesite_alloy_block.json @@ -0,0 +1,17 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "C": { + "item": "create:andesite_alloy" + } + }, + "pattern": [ + "CCC", + "CCC", + "CCC" + ], + "result": { + "item": "create:andesite_alloy_block" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/materials/andesite_alloy_from_block.json b/src/generated/resources/data/create/recipes/crafting/materials/andesite_alloy_from_block.json new file mode 100644 index 000000000..055760e4c --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/materials/andesite_alloy_from_block.json @@ -0,0 +1,13 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:andesite_alloy_block" + } + ], + "result": { + "count": 9, + "item": "create:andesite_alloy" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/materials/experience_block.json b/src/generated/resources/data/create/recipes/crafting/materials/experience_block.json new file mode 100644 index 000000000..0b80d5916 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/materials/experience_block.json @@ -0,0 +1,17 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "C": { + "item": "create:experience_nugget" + } + }, + "pattern": [ + "CCC", + "CCC", + "CCC" + ], + "result": { + "item": "create:experience_block" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/materials/experience_nugget_from_block.json b/src/generated/resources/data/create/recipes/crafting/materials/experience_nugget_from_block.json new file mode 100644 index 000000000..a6eb7d0fa --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/materials/experience_nugget_from_block.json @@ -0,0 +1,13 @@ +{ + "type": "minecraft:crafting_shapeless", + "category": "misc", + "ingredients": [ + { + "item": "create:experience_block" + } + ], + "result": { + "count": 9, + "item": "create:experience_nugget" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crimsite_from_stone_types_crimsite_stonecutting.json b/src/generated/resources/data/create/recipes/crimsite_from_stone_types_crimsite_stonecutting.json new file mode 100644 index 000000000..7733c710f --- /dev/null +++ b/src/generated/resources/data/create/recipes/crimsite_from_stone_types_crimsite_stonecutting.json @@ -0,0 +1,8 @@ +{ + "type": "minecraft:stonecutting", + "count": 1, + "ingredient": { + "tag": "create:stone_types/crimsite" + }, + "result": "create:crimsite" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crimsite_pillar_from_crimsite_stonecutting.json b/src/generated/resources/data/create/recipes/crimsite_pillar_from_crimsite_stonecutting.json deleted file mode 100644 index dcbd3ea6b..000000000 --- a/src/generated/resources/data/create/recipes/crimsite_pillar_from_crimsite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:crimsite" - }, - "result": "create:crimsite_pillar" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crushing/aluminum_ore.json b/src/generated/resources/data/create/recipes/crushing/aluminum_ore.json index 813f3744a..143c9a043 100644 --- a/src/generated/resources/data/create/recipes/crushing/aluminum_ore.json +++ b/src/generated/resources/data/create/recipes/crushing/aluminum_ore.json @@ -17,11 +17,11 @@ "processingTime": 400, "results": [ { - "item": "create:crushed_aluminum_ore" + "item": "create:crushed_raw_aluminum" }, { "chance": 0.75, - "item": "create:crushed_aluminum_ore" + "item": "create:crushed_raw_aluminum" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/asurine.json b/src/generated/resources/data/create/recipes/crushing/asurine.json index c25ab2297..91f334678 100644 --- a/src/generated/resources/data/create/recipes/crushing/asurine.json +++ b/src/generated/resources/data/create/recipes/crushing/asurine.json @@ -9,7 +9,7 @@ "results": [ { "chance": 0.3, - "item": "create:crushed_zinc_ore" + "item": "create:crushed_raw_zinc" }, { "chance": 0.3, diff --git a/src/generated/resources/data/create/recipes/crushing/asurine_recycling.json b/src/generated/resources/data/create/recipes/crushing/asurine_recycling.json index 588f84c71..bbedfed29 100644 --- a/src/generated/resources/data/create/recipes/crushing/asurine_recycling.json +++ b/src/generated/resources/data/create/recipes/crushing/asurine_recycling.json @@ -9,7 +9,7 @@ "results": [ { "chance": 0.3, - "item": "create:crushed_zinc_ore" + "item": "create:crushed_raw_zinc" }, { "chance": 0.3, diff --git a/src/generated/resources/data/create/recipes/crushing/copper_ore.json b/src/generated/resources/data/create/recipes/crushing/copper_ore.json index 9e06a17eb..2a35feaf8 100644 --- a/src/generated/resources/data/create/recipes/crushing/copper_ore.json +++ b/src/generated/resources/data/create/recipes/crushing/copper_ore.json @@ -9,11 +9,11 @@ "results": [ { "count": 5, - "item": "create:crushed_copper_ore" + "item": "create:crushed_raw_copper" }, { "chance": 0.25, - "item": "create:crushed_copper_ore" + "item": "create:crushed_raw_copper" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/crimsite.json b/src/generated/resources/data/create/recipes/crushing/crimsite.json index 63d5a0a2d..f725dd6b9 100644 --- a/src/generated/resources/data/create/recipes/crushing/crimsite.json +++ b/src/generated/resources/data/create/recipes/crushing/crimsite.json @@ -9,7 +9,7 @@ "results": [ { "chance": 0.4, - "item": "create:crushed_iron_ore" + "item": "create:crushed_raw_iron" }, { "chance": 0.4, diff --git a/src/generated/resources/data/create/recipes/crushing/crimsite_recycling.json b/src/generated/resources/data/create/recipes/crushing/crimsite_recycling.json index 6d61990bd..78c3dc6e5 100644 --- a/src/generated/resources/data/create/recipes/crushing/crimsite_recycling.json +++ b/src/generated/resources/data/create/recipes/crushing/crimsite_recycling.json @@ -9,7 +9,7 @@ "results": [ { "chance": 0.4, - "item": "create:crushed_iron_ore" + "item": "create:crushed_raw_iron" }, { "chance": 0.4, diff --git a/src/generated/resources/data/create/recipes/crushing/deepslate_copper_ore.json b/src/generated/resources/data/create/recipes/crushing/deepslate_copper_ore.json index 0b4dbfdb1..3bad3d985 100644 --- a/src/generated/resources/data/create/recipes/crushing/deepslate_copper_ore.json +++ b/src/generated/resources/data/create/recipes/crushing/deepslate_copper_ore.json @@ -9,11 +9,11 @@ "results": [ { "count": 7, - "item": "create:crushed_copper_ore" + "item": "create:crushed_raw_copper" }, { "chance": 0.25, - "item": "create:crushed_copper_ore" + "item": "create:crushed_raw_copper" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/deepslate_gold_ore.json b/src/generated/resources/data/create/recipes/crushing/deepslate_gold_ore.json index 1c213d1a0..1467bbbaf 100644 --- a/src/generated/resources/data/create/recipes/crushing/deepslate_gold_ore.json +++ b/src/generated/resources/data/create/recipes/crushing/deepslate_gold_ore.json @@ -9,14 +9,15 @@ "results": [ { "count": 2, - "item": "create:crushed_gold_ore" + "item": "create:crushed_raw_gold" }, { "chance": 0.25, - "item": "create:crushed_gold_ore" + "item": "create:crushed_raw_gold" }, { "chance": 0.75, + "count": 2, "item": "create:experience_nugget" }, { diff --git a/src/generated/resources/data/create/recipes/crushing/deepslate_iron_ore.json b/src/generated/resources/data/create/recipes/crushing/deepslate_iron_ore.json index 7dc20a450..a12e491c1 100644 --- a/src/generated/resources/data/create/recipes/crushing/deepslate_iron_ore.json +++ b/src/generated/resources/data/create/recipes/crushing/deepslate_iron_ore.json @@ -9,11 +9,11 @@ "results": [ { "count": 2, - "item": "create:crushed_iron_ore" + "item": "create:crushed_raw_iron" }, { "chance": 0.25, - "item": "create:crushed_iron_ore" + "item": "create:crushed_raw_iron" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/deepslate_zinc_ore.json b/src/generated/resources/data/create/recipes/crushing/deepslate_zinc_ore.json index 75673fadc..450c786fe 100644 --- a/src/generated/resources/data/create/recipes/crushing/deepslate_zinc_ore.json +++ b/src/generated/resources/data/create/recipes/crushing/deepslate_zinc_ore.json @@ -9,11 +9,11 @@ "results": [ { "count": 2, - "item": "create:crushed_zinc_ore" + "item": "create:crushed_raw_zinc" }, { "chance": 0.25, - "item": "create:crushed_zinc_ore" + "item": "create:crushed_raw_zinc" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/gold_ore.json b/src/generated/resources/data/create/recipes/crushing/gold_ore.json index b1a02450b..b5e49e36d 100644 --- a/src/generated/resources/data/create/recipes/crushing/gold_ore.json +++ b/src/generated/resources/data/create/recipes/crushing/gold_ore.json @@ -8,14 +8,15 @@ "processingTime": 250, "results": [ { - "item": "create:crushed_gold_ore" + "item": "create:crushed_raw_gold" }, { "chance": 0.75, - "item": "create:crushed_gold_ore" + "item": "create:crushed_raw_gold" }, { "chance": 0.75, + "count": 2, "item": "create:experience_nugget" }, { diff --git a/src/generated/resources/data/create/recipes/crushing/iron_ore.json b/src/generated/resources/data/create/recipes/crushing/iron_ore.json index 25411ca07..4b08b4274 100644 --- a/src/generated/resources/data/create/recipes/crushing/iron_ore.json +++ b/src/generated/resources/data/create/recipes/crushing/iron_ore.json @@ -8,11 +8,11 @@ "processingTime": 250, "results": [ { - "item": "create:crushed_iron_ore" + "item": "create:crushed_raw_iron" }, { "chance": 0.75, - "item": "create:crushed_iron_ore" + "item": "create:crushed_raw_iron" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/lead_ore.json b/src/generated/resources/data/create/recipes/crushing/lead_ore.json index d431e754a..4f9d82ec5 100644 --- a/src/generated/resources/data/create/recipes/crushing/lead_ore.json +++ b/src/generated/resources/data/create/recipes/crushing/lead_ore.json @@ -17,11 +17,11 @@ "processingTime": 400, "results": [ { - "item": "create:crushed_lead_ore" + "item": "create:crushed_raw_lead" }, { "chance": 0.75, - "item": "create:crushed_lead_ore" + "item": "create:crushed_raw_lead" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/nickel_ore.json b/src/generated/resources/data/create/recipes/crushing/nickel_ore.json index cd85d2c1a..f815ec8a6 100644 --- a/src/generated/resources/data/create/recipes/crushing/nickel_ore.json +++ b/src/generated/resources/data/create/recipes/crushing/nickel_ore.json @@ -17,11 +17,11 @@ "processingTime": 400, "results": [ { - "item": "create:crushed_nickel_ore" + "item": "create:crushed_raw_nickel" }, { "chance": 0.75, - "item": "create:crushed_nickel_ore" + "item": "create:crushed_raw_nickel" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/ochrum.json b/src/generated/resources/data/create/recipes/crushing/ochrum.json index 738f1eb2e..00832373e 100644 --- a/src/generated/resources/data/create/recipes/crushing/ochrum.json +++ b/src/generated/resources/data/create/recipes/crushing/ochrum.json @@ -9,7 +9,7 @@ "results": [ { "chance": 0.2, - "item": "create:crushed_gold_ore" + "item": "create:crushed_raw_gold" }, { "chance": 0.2, diff --git a/src/generated/resources/data/create/recipes/crushing/ochrum_recycling.json b/src/generated/resources/data/create/recipes/crushing/ochrum_recycling.json index 95510608b..283c2a889 100644 --- a/src/generated/resources/data/create/recipes/crushing/ochrum_recycling.json +++ b/src/generated/resources/data/create/recipes/crushing/ochrum_recycling.json @@ -9,7 +9,7 @@ "results": [ { "chance": 0.2, - "item": "create:crushed_gold_ore" + "item": "create:crushed_raw_gold" }, { "chance": 0.2, diff --git a/src/generated/resources/data/create/recipes/crushing/osmium_ore.json b/src/generated/resources/data/create/recipes/crushing/osmium_ore.json index 6cba4b5d4..afc4aa5f1 100644 --- a/src/generated/resources/data/create/recipes/crushing/osmium_ore.json +++ b/src/generated/resources/data/create/recipes/crushing/osmium_ore.json @@ -17,11 +17,11 @@ "processingTime": 400, "results": [ { - "item": "create:crushed_osmium_ore" + "item": "create:crushed_raw_osmium" }, { "chance": 0.75, - "item": "create:crushed_osmium_ore" + "item": "create:crushed_raw_osmium" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/platinum_ore.json b/src/generated/resources/data/create/recipes/crushing/platinum_ore.json index bf126bce5..ad92ae87b 100644 --- a/src/generated/resources/data/create/recipes/crushing/platinum_ore.json +++ b/src/generated/resources/data/create/recipes/crushing/platinum_ore.json @@ -17,11 +17,11 @@ "processingTime": 400, "results": [ { - "item": "create:crushed_platinum_ore" + "item": "create:crushed_raw_platinum" }, { "chance": 0.75, - "item": "create:crushed_platinum_ore" + "item": "create:crushed_raw_platinum" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/quicksilver_ore.json b/src/generated/resources/data/create/recipes/crushing/quicksilver_ore.json index 9dc640550..4e60a1478 100644 --- a/src/generated/resources/data/create/recipes/crushing/quicksilver_ore.json +++ b/src/generated/resources/data/create/recipes/crushing/quicksilver_ore.json @@ -17,11 +17,11 @@ "processingTime": 400, "results": [ { - "item": "create:crushed_quicksilver_ore" + "item": "create:crushed_raw_quicksilver" }, { "chance": 0.75, - "item": "create:crushed_quicksilver_ore" + "item": "create:crushed_raw_quicksilver" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/raw_aluminum_block.json b/src/generated/resources/data/create/recipes/crushing/raw_aluminum_block.json index 10e11e3de..29c7765d3 100644 --- a/src/generated/resources/data/create/recipes/crushing/raw_aluminum_block.json +++ b/src/generated/resources/data/create/recipes/crushing/raw_aluminum_block.json @@ -18,7 +18,7 @@ "results": [ { "count": 9, - "item": "create:crushed_aluminum_ore" + "item": "create:crushed_raw_aluminum" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/raw_aluminum_ore.json b/src/generated/resources/data/create/recipes/crushing/raw_aluminum_ore.json index cb20a6dfe..0dce77235 100644 --- a/src/generated/resources/data/create/recipes/crushing/raw_aluminum_ore.json +++ b/src/generated/resources/data/create/recipes/crushing/raw_aluminum_ore.json @@ -17,7 +17,7 @@ "processingTime": 400, "results": [ { - "item": "create:crushed_aluminum_ore" + "item": "create:crushed_raw_aluminum" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/raw_copper.json b/src/generated/resources/data/create/recipes/crushing/raw_copper.json index 4a7f00571..60dd3d6fc 100644 --- a/src/generated/resources/data/create/recipes/crushing/raw_copper.json +++ b/src/generated/resources/data/create/recipes/crushing/raw_copper.json @@ -8,7 +8,7 @@ "processingTime": 400, "results": [ { - "item": "create:crushed_copper_ore" + "item": "create:crushed_raw_copper" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/raw_copper_block.json b/src/generated/resources/data/create/recipes/crushing/raw_copper_block.json index a1f4260cd..426699923 100644 --- a/src/generated/resources/data/create/recipes/crushing/raw_copper_block.json +++ b/src/generated/resources/data/create/recipes/crushing/raw_copper_block.json @@ -9,7 +9,7 @@ "results": [ { "count": 9, - "item": "create:crushed_copper_ore" + "item": "create:crushed_raw_copper" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/raw_gold.json b/src/generated/resources/data/create/recipes/crushing/raw_gold.json index 9c9f4fff2..3ba415681 100644 --- a/src/generated/resources/data/create/recipes/crushing/raw_gold.json +++ b/src/generated/resources/data/create/recipes/crushing/raw_gold.json @@ -8,10 +8,11 @@ "processingTime": 400, "results": [ { - "item": "create:crushed_gold_ore" + "item": "create:crushed_raw_gold" }, { "chance": 0.75, + "count": 2, "item": "create:experience_nugget" } ] diff --git a/src/generated/resources/data/create/recipes/crushing/raw_gold_block.json b/src/generated/resources/data/create/recipes/crushing/raw_gold_block.json index 141c08e58..bcb1e19c6 100644 --- a/src/generated/resources/data/create/recipes/crushing/raw_gold_block.json +++ b/src/generated/resources/data/create/recipes/crushing/raw_gold_block.json @@ -9,11 +9,11 @@ "results": [ { "count": 9, - "item": "create:crushed_gold_ore" + "item": "create:crushed_raw_gold" }, { "chance": 0.75, - "count": 9, + "count": 18, "item": "create:experience_nugget" } ] diff --git a/src/generated/resources/data/create/recipes/crushing/raw_iron.json b/src/generated/resources/data/create/recipes/crushing/raw_iron.json index 1e595a8f9..5177512a7 100644 --- a/src/generated/resources/data/create/recipes/crushing/raw_iron.json +++ b/src/generated/resources/data/create/recipes/crushing/raw_iron.json @@ -8,7 +8,7 @@ "processingTime": 400, "results": [ { - "item": "create:crushed_iron_ore" + "item": "create:crushed_raw_iron" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/raw_iron_block.json b/src/generated/resources/data/create/recipes/crushing/raw_iron_block.json index 805f85b54..7a3299a0b 100644 --- a/src/generated/resources/data/create/recipes/crushing/raw_iron_block.json +++ b/src/generated/resources/data/create/recipes/crushing/raw_iron_block.json @@ -9,7 +9,7 @@ "results": [ { "count": 9, - "item": "create:crushed_iron_ore" + "item": "create:crushed_raw_iron" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/raw_lead_block.json b/src/generated/resources/data/create/recipes/crushing/raw_lead_block.json index 99f7eb9bf..b099468b5 100644 --- a/src/generated/resources/data/create/recipes/crushing/raw_lead_block.json +++ b/src/generated/resources/data/create/recipes/crushing/raw_lead_block.json @@ -18,7 +18,7 @@ "results": [ { "count": 9, - "item": "create:crushed_lead_ore" + "item": "create:crushed_raw_lead" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/raw_lead_ore.json b/src/generated/resources/data/create/recipes/crushing/raw_lead_ore.json index a12b4b479..30f9986b5 100644 --- a/src/generated/resources/data/create/recipes/crushing/raw_lead_ore.json +++ b/src/generated/resources/data/create/recipes/crushing/raw_lead_ore.json @@ -17,7 +17,7 @@ "processingTime": 400, "results": [ { - "item": "create:crushed_lead_ore" + "item": "create:crushed_raw_lead" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/raw_nickel_block.json b/src/generated/resources/data/create/recipes/crushing/raw_nickel_block.json index f1b8cd54e..185a91e98 100644 --- a/src/generated/resources/data/create/recipes/crushing/raw_nickel_block.json +++ b/src/generated/resources/data/create/recipes/crushing/raw_nickel_block.json @@ -18,7 +18,7 @@ "results": [ { "count": 9, - "item": "create:crushed_nickel_ore" + "item": "create:crushed_raw_nickel" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/raw_nickel_ore.json b/src/generated/resources/data/create/recipes/crushing/raw_nickel_ore.json index 6eac61ef9..103784704 100644 --- a/src/generated/resources/data/create/recipes/crushing/raw_nickel_ore.json +++ b/src/generated/resources/data/create/recipes/crushing/raw_nickel_ore.json @@ -17,7 +17,7 @@ "processingTime": 400, "results": [ { - "item": "create:crushed_nickel_ore" + "item": "create:crushed_raw_nickel" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/raw_osmium_block.json b/src/generated/resources/data/create/recipes/crushing/raw_osmium_block.json index 15e2645ef..a816c41bd 100644 --- a/src/generated/resources/data/create/recipes/crushing/raw_osmium_block.json +++ b/src/generated/resources/data/create/recipes/crushing/raw_osmium_block.json @@ -18,7 +18,7 @@ "results": [ { "count": 9, - "item": "create:crushed_osmium_ore" + "item": "create:crushed_raw_osmium" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/raw_osmium_ore.json b/src/generated/resources/data/create/recipes/crushing/raw_osmium_ore.json index 898c3a843..5a40dbc1a 100644 --- a/src/generated/resources/data/create/recipes/crushing/raw_osmium_ore.json +++ b/src/generated/resources/data/create/recipes/crushing/raw_osmium_ore.json @@ -17,7 +17,7 @@ "processingTime": 400, "results": [ { - "item": "create:crushed_osmium_ore" + "item": "create:crushed_raw_osmium" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/raw_platinum_block.json b/src/generated/resources/data/create/recipes/crushing/raw_platinum_block.json index c0c56177b..916a9f904 100644 --- a/src/generated/resources/data/create/recipes/crushing/raw_platinum_block.json +++ b/src/generated/resources/data/create/recipes/crushing/raw_platinum_block.json @@ -18,7 +18,7 @@ "results": [ { "count": 9, - "item": "create:crushed_platinum_ore" + "item": "create:crushed_raw_platinum" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/raw_platinum_ore.json b/src/generated/resources/data/create/recipes/crushing/raw_platinum_ore.json index da99df7cf..f3f12a188 100644 --- a/src/generated/resources/data/create/recipes/crushing/raw_platinum_ore.json +++ b/src/generated/resources/data/create/recipes/crushing/raw_platinum_ore.json @@ -17,7 +17,7 @@ "processingTime": 400, "results": [ { - "item": "create:crushed_platinum_ore" + "item": "create:crushed_raw_platinum" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/raw_quicksilver_block.json b/src/generated/resources/data/create/recipes/crushing/raw_quicksilver_block.json index f51cf1165..b674f5dfa 100644 --- a/src/generated/resources/data/create/recipes/crushing/raw_quicksilver_block.json +++ b/src/generated/resources/data/create/recipes/crushing/raw_quicksilver_block.json @@ -18,7 +18,7 @@ "results": [ { "count": 9, - "item": "create:crushed_quicksilver_ore" + "item": "create:crushed_raw_quicksilver" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/raw_quicksilver_ore.json b/src/generated/resources/data/create/recipes/crushing/raw_quicksilver_ore.json index 818ca0dd6..2828b5ce1 100644 --- a/src/generated/resources/data/create/recipes/crushing/raw_quicksilver_ore.json +++ b/src/generated/resources/data/create/recipes/crushing/raw_quicksilver_ore.json @@ -17,7 +17,7 @@ "processingTime": 400, "results": [ { - "item": "create:crushed_quicksilver_ore" + "item": "create:crushed_raw_quicksilver" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/raw_silver_block.json b/src/generated/resources/data/create/recipes/crushing/raw_silver_block.json index 224a47a31..9b1e5bf50 100644 --- a/src/generated/resources/data/create/recipes/crushing/raw_silver_block.json +++ b/src/generated/resources/data/create/recipes/crushing/raw_silver_block.json @@ -18,7 +18,7 @@ "results": [ { "count": 9, - "item": "create:crushed_silver_ore" + "item": "create:crushed_raw_silver" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/raw_silver_ore.json b/src/generated/resources/data/create/recipes/crushing/raw_silver_ore.json index ab3a0e201..9ca490108 100644 --- a/src/generated/resources/data/create/recipes/crushing/raw_silver_ore.json +++ b/src/generated/resources/data/create/recipes/crushing/raw_silver_ore.json @@ -17,7 +17,7 @@ "processingTime": 400, "results": [ { - "item": "create:crushed_silver_ore" + "item": "create:crushed_raw_silver" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/raw_tin_block.json b/src/generated/resources/data/create/recipes/crushing/raw_tin_block.json index 2c5a37734..96354a091 100644 --- a/src/generated/resources/data/create/recipes/crushing/raw_tin_block.json +++ b/src/generated/resources/data/create/recipes/crushing/raw_tin_block.json @@ -18,7 +18,7 @@ "results": [ { "count": 9, - "item": "create:crushed_tin_ore" + "item": "create:crushed_raw_tin" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/raw_tin_ore.json b/src/generated/resources/data/create/recipes/crushing/raw_tin_ore.json index 9a57c327a..290fede6d 100644 --- a/src/generated/resources/data/create/recipes/crushing/raw_tin_ore.json +++ b/src/generated/resources/data/create/recipes/crushing/raw_tin_ore.json @@ -17,7 +17,7 @@ "processingTime": 400, "results": [ { - "item": "create:crushed_tin_ore" + "item": "create:crushed_raw_tin" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/raw_uranium_block.json b/src/generated/resources/data/create/recipes/crushing/raw_uranium_block.json index 6f3c1f6e8..8393f8e8b 100644 --- a/src/generated/resources/data/create/recipes/crushing/raw_uranium_block.json +++ b/src/generated/resources/data/create/recipes/crushing/raw_uranium_block.json @@ -18,7 +18,7 @@ "results": [ { "count": 9, - "item": "create:crushed_uranium_ore" + "item": "create:crushed_raw_uranium" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/raw_uranium_ore.json b/src/generated/resources/data/create/recipes/crushing/raw_uranium_ore.json index 562198822..ee551326f 100644 --- a/src/generated/resources/data/create/recipes/crushing/raw_uranium_ore.json +++ b/src/generated/resources/data/create/recipes/crushing/raw_uranium_ore.json @@ -17,7 +17,7 @@ "processingTime": 400, "results": [ { - "item": "create:crushed_uranium_ore" + "item": "create:crushed_raw_uranium" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/raw_zinc.json b/src/generated/resources/data/create/recipes/crushing/raw_zinc.json index 18c35d563..e0acd0ec1 100644 --- a/src/generated/resources/data/create/recipes/crushing/raw_zinc.json +++ b/src/generated/resources/data/create/recipes/crushing/raw_zinc.json @@ -8,7 +8,7 @@ "processingTime": 400, "results": [ { - "item": "create:crushed_zinc_ore" + "item": "create:crushed_raw_zinc" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/raw_zinc_block.json b/src/generated/resources/data/create/recipes/crushing/raw_zinc_block.json index 551dd2bcb..804660ca0 100644 --- a/src/generated/resources/data/create/recipes/crushing/raw_zinc_block.json +++ b/src/generated/resources/data/create/recipes/crushing/raw_zinc_block.json @@ -9,7 +9,7 @@ "results": [ { "count": 9, - "item": "create:crushed_zinc_ore" + "item": "create:crushed_raw_zinc" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/silver_ore.json b/src/generated/resources/data/create/recipes/crushing/silver_ore.json index e63f4ac09..2dfaa8085 100644 --- a/src/generated/resources/data/create/recipes/crushing/silver_ore.json +++ b/src/generated/resources/data/create/recipes/crushing/silver_ore.json @@ -17,11 +17,11 @@ "processingTime": 400, "results": [ { - "item": "create:crushed_silver_ore" + "item": "create:crushed_raw_silver" }, { "chance": 0.75, - "item": "create:crushed_silver_ore" + "item": "create:crushed_raw_silver" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/tin_ore.json b/src/generated/resources/data/create/recipes/crushing/tin_ore.json index 95ec06c1a..6544cb903 100644 --- a/src/generated/resources/data/create/recipes/crushing/tin_ore.json +++ b/src/generated/resources/data/create/recipes/crushing/tin_ore.json @@ -17,11 +17,11 @@ "processingTime": 400, "results": [ { - "item": "create:crushed_tin_ore" + "item": "create:crushed_raw_tin" }, { "chance": 0.75, - "item": "create:crushed_tin_ore" + "item": "create:crushed_raw_tin" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/uranium_ore.json b/src/generated/resources/data/create/recipes/crushing/uranium_ore.json index f7177af0c..34cbbfc66 100644 --- a/src/generated/resources/data/create/recipes/crushing/uranium_ore.json +++ b/src/generated/resources/data/create/recipes/crushing/uranium_ore.json @@ -17,11 +17,11 @@ "processingTime": 400, "results": [ { - "item": "create:crushed_uranium_ore" + "item": "create:crushed_raw_uranium" }, { "chance": 0.75, - "item": "create:crushed_uranium_ore" + "item": "create:crushed_raw_uranium" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/crushing/veridium.json b/src/generated/resources/data/create/recipes/crushing/veridium.json index 432c90515..7b1940b50 100644 --- a/src/generated/resources/data/create/recipes/crushing/veridium.json +++ b/src/generated/resources/data/create/recipes/crushing/veridium.json @@ -9,7 +9,7 @@ "results": [ { "chance": 0.8, - "item": "create:crushed_copper_ore" + "item": "create:crushed_raw_copper" }, { "chance": 0.8, diff --git a/src/generated/resources/data/create/recipes/crushing/veridium_recycling.json b/src/generated/resources/data/create/recipes/crushing/veridium_recycling.json index 61f678183..08d1b72c7 100644 --- a/src/generated/resources/data/create/recipes/crushing/veridium_recycling.json +++ b/src/generated/resources/data/create/recipes/crushing/veridium_recycling.json @@ -9,7 +9,7 @@ "results": [ { "chance": 0.8, - "item": "create:crushed_copper_ore" + "item": "create:crushed_raw_copper" }, { "chance": 0.8, diff --git a/src/generated/resources/data/create/recipes/crushing/zinc_ore.json b/src/generated/resources/data/create/recipes/crushing/zinc_ore.json index b21bc3c6e..86029b154 100644 --- a/src/generated/resources/data/create/recipes/crushing/zinc_ore.json +++ b/src/generated/resources/data/create/recipes/crushing/zinc_ore.json @@ -8,11 +8,11 @@ "processingTime": 250, "results": [ { - "item": "create:crushed_zinc_ore" + "item": "create:crushed_raw_zinc" }, { "chance": 0.75, - "item": "create:crushed_zinc_ore" + "item": "create:crushed_raw_zinc" }, { "chance": 0.75, diff --git a/src/generated/resources/data/create/recipes/cut_andesite_brick_slab_from_andesite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_andesite_brick_slab_from_andesite_stonecutting.json deleted file mode 100644 index 3d3a0281d..000000000 --- a/src/generated/resources/data/create/recipes/cut_andesite_brick_slab_from_andesite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "minecraft:andesite" - }, - "result": "create:cut_andesite_brick_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_andesite_brick_stairs_from_andesite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_andesite_brick_stairs_from_andesite_stonecutting.json deleted file mode 100644 index b10fb91e9..000000000 --- a/src/generated/resources/data/create/recipes/cut_andesite_brick_stairs_from_andesite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:andesite" - }, - "result": "create:cut_andesite_brick_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_andesite_brick_wall_from_andesite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_andesite_brick_wall_from_andesite_stonecutting.json deleted file mode 100644 index b7dadbb6a..000000000 --- a/src/generated/resources/data/create/recipes/cut_andesite_brick_wall_from_andesite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:andesite" - }, - "result": "create:cut_andesite_brick_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_andesite_bricks_from_andesite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_andesite_bricks_from_andesite_stonecutting.json deleted file mode 100644 index 03e8bd9cf..000000000 --- a/src/generated/resources/data/create/recipes/cut_andesite_bricks_from_andesite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:andesite" - }, - "result": "create:cut_andesite_bricks" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_andesite_from_andesite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_andesite_from_andesite_stonecutting.json deleted file mode 100644 index 90a89863e..000000000 --- a/src/generated/resources/data/create/recipes/cut_andesite_from_andesite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:andesite" - }, - "result": "create:cut_andesite" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_andesite_slab_from_andesite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_andesite_slab_from_andesite_stonecutting.json deleted file mode 100644 index ca1708344..000000000 --- a/src/generated/resources/data/create/recipes/cut_andesite_slab_from_andesite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "minecraft:andesite" - }, - "result": "create:cut_andesite_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_andesite_stairs_from_andesite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_andesite_stairs_from_andesite_stonecutting.json deleted file mode 100644 index 66cbe64f1..000000000 --- a/src/generated/resources/data/create/recipes/cut_andesite_stairs_from_andesite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:andesite" - }, - "result": "create:cut_andesite_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_andesite_wall_from_andesite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_andesite_wall_from_andesite_stonecutting.json deleted file mode 100644 index 31917ce6b..000000000 --- a/src/generated/resources/data/create/recipes/cut_andesite_wall_from_andesite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:andesite" - }, - "result": "create:cut_andesite_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_asurine_brick_slab_from_asurine_stonecutting.json b/src/generated/resources/data/create/recipes/cut_asurine_brick_slab_from_asurine_stonecutting.json deleted file mode 100644 index cc5bfd20e..000000000 --- a/src/generated/resources/data/create/recipes/cut_asurine_brick_slab_from_asurine_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "create:asurine" - }, - "result": "create:cut_asurine_brick_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_asurine_brick_stairs_from_asurine_stonecutting.json b/src/generated/resources/data/create/recipes/cut_asurine_brick_stairs_from_asurine_stonecutting.json deleted file mode 100644 index fac60c9e2..000000000 --- a/src/generated/resources/data/create/recipes/cut_asurine_brick_stairs_from_asurine_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:asurine" - }, - "result": "create:cut_asurine_brick_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_asurine_brick_wall_from_asurine_stonecutting.json b/src/generated/resources/data/create/recipes/cut_asurine_brick_wall_from_asurine_stonecutting.json deleted file mode 100644 index c400ffbae..000000000 --- a/src/generated/resources/data/create/recipes/cut_asurine_brick_wall_from_asurine_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:asurine" - }, - "result": "create:cut_asurine_brick_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_asurine_bricks_from_asurine_stonecutting.json b/src/generated/resources/data/create/recipes/cut_asurine_bricks_from_asurine_stonecutting.json deleted file mode 100644 index dc981ca0d..000000000 --- a/src/generated/resources/data/create/recipes/cut_asurine_bricks_from_asurine_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:asurine" - }, - "result": "create:cut_asurine_bricks" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_asurine_from_asurine_stonecutting.json b/src/generated/resources/data/create/recipes/cut_asurine_from_asurine_stonecutting.json deleted file mode 100644 index 713ff72a5..000000000 --- a/src/generated/resources/data/create/recipes/cut_asurine_from_asurine_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:asurine" - }, - "result": "create:cut_asurine" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_asurine_slab_from_asurine_stonecutting.json b/src/generated/resources/data/create/recipes/cut_asurine_slab_from_asurine_stonecutting.json deleted file mode 100644 index 4f491d0c4..000000000 --- a/src/generated/resources/data/create/recipes/cut_asurine_slab_from_asurine_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "create:asurine" - }, - "result": "create:cut_asurine_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_asurine_stairs_from_asurine_stonecutting.json b/src/generated/resources/data/create/recipes/cut_asurine_stairs_from_asurine_stonecutting.json deleted file mode 100644 index 30460a4e7..000000000 --- a/src/generated/resources/data/create/recipes/cut_asurine_stairs_from_asurine_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:asurine" - }, - "result": "create:cut_asurine_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_asurine_wall_from_asurine_stonecutting.json b/src/generated/resources/data/create/recipes/cut_asurine_wall_from_asurine_stonecutting.json deleted file mode 100644 index 743d3d9f4..000000000 --- a/src/generated/resources/data/create/recipes/cut_asurine_wall_from_asurine_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:asurine" - }, - "result": "create:cut_asurine_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_calcite_brick_slab_from_calcite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_calcite_brick_slab_from_calcite_stonecutting.json deleted file mode 100644 index 36adb99eb..000000000 --- a/src/generated/resources/data/create/recipes/cut_calcite_brick_slab_from_calcite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "minecraft:calcite" - }, - "result": "create:cut_calcite_brick_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_calcite_brick_stairs_from_calcite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_calcite_brick_stairs_from_calcite_stonecutting.json deleted file mode 100644 index 8635dc9cf..000000000 --- a/src/generated/resources/data/create/recipes/cut_calcite_brick_stairs_from_calcite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:calcite" - }, - "result": "create:cut_calcite_brick_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_calcite_brick_wall_from_calcite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_calcite_brick_wall_from_calcite_stonecutting.json deleted file mode 100644 index 1be2976c1..000000000 --- a/src/generated/resources/data/create/recipes/cut_calcite_brick_wall_from_calcite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:calcite" - }, - "result": "create:cut_calcite_brick_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_calcite_bricks_from_calcite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_calcite_bricks_from_calcite_stonecutting.json deleted file mode 100644 index c46a4e73a..000000000 --- a/src/generated/resources/data/create/recipes/cut_calcite_bricks_from_calcite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:calcite" - }, - "result": "create:cut_calcite_bricks" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_calcite_from_calcite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_calcite_from_calcite_stonecutting.json deleted file mode 100644 index dd54750b9..000000000 --- a/src/generated/resources/data/create/recipes/cut_calcite_from_calcite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:calcite" - }, - "result": "create:cut_calcite" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_calcite_slab_from_calcite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_calcite_slab_from_calcite_stonecutting.json deleted file mode 100644 index 19b03550b..000000000 --- a/src/generated/resources/data/create/recipes/cut_calcite_slab_from_calcite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "minecraft:calcite" - }, - "result": "create:cut_calcite_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_calcite_stairs_from_calcite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_calcite_stairs_from_calcite_stonecutting.json deleted file mode 100644 index db1e06779..000000000 --- a/src/generated/resources/data/create/recipes/cut_calcite_stairs_from_calcite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:calcite" - }, - "result": "create:cut_calcite_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_calcite_wall_from_calcite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_calcite_wall_from_calcite_stonecutting.json deleted file mode 100644 index e12c1ea00..000000000 --- a/src/generated/resources/data/create/recipes/cut_calcite_wall_from_calcite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:calcite" - }, - "result": "create:cut_calcite_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_crimsite_brick_slab_from_crimsite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_crimsite_brick_slab_from_crimsite_stonecutting.json deleted file mode 100644 index f9d20565a..000000000 --- a/src/generated/resources/data/create/recipes/cut_crimsite_brick_slab_from_crimsite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "create:crimsite" - }, - "result": "create:cut_crimsite_brick_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_crimsite_brick_stairs_from_crimsite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_crimsite_brick_stairs_from_crimsite_stonecutting.json deleted file mode 100644 index 61b9d455d..000000000 --- a/src/generated/resources/data/create/recipes/cut_crimsite_brick_stairs_from_crimsite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:crimsite" - }, - "result": "create:cut_crimsite_brick_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_crimsite_brick_wall_from_crimsite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_crimsite_brick_wall_from_crimsite_stonecutting.json deleted file mode 100644 index 0f7ed8e84..000000000 --- a/src/generated/resources/data/create/recipes/cut_crimsite_brick_wall_from_crimsite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:crimsite" - }, - "result": "create:cut_crimsite_brick_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_crimsite_bricks_from_crimsite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_crimsite_bricks_from_crimsite_stonecutting.json deleted file mode 100644 index 19c269cec..000000000 --- a/src/generated/resources/data/create/recipes/cut_crimsite_bricks_from_crimsite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:crimsite" - }, - "result": "create:cut_crimsite_bricks" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_crimsite_from_crimsite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_crimsite_from_crimsite_stonecutting.json deleted file mode 100644 index 98ee42c88..000000000 --- a/src/generated/resources/data/create/recipes/cut_crimsite_from_crimsite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:crimsite" - }, - "result": "create:cut_crimsite" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_crimsite_slab_from_crimsite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_crimsite_slab_from_crimsite_stonecutting.json deleted file mode 100644 index aca61443e..000000000 --- a/src/generated/resources/data/create/recipes/cut_crimsite_slab_from_crimsite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "create:crimsite" - }, - "result": "create:cut_crimsite_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_crimsite_stairs_from_crimsite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_crimsite_stairs_from_crimsite_stonecutting.json deleted file mode 100644 index 29bd4f5db..000000000 --- a/src/generated/resources/data/create/recipes/cut_crimsite_stairs_from_crimsite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:crimsite" - }, - "result": "create:cut_crimsite_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_crimsite_wall_from_crimsite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_crimsite_wall_from_crimsite_stonecutting.json deleted file mode 100644 index 454da3b42..000000000 --- a/src/generated/resources/data/create/recipes/cut_crimsite_wall_from_crimsite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:crimsite" - }, - "result": "create:cut_crimsite_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_deepslate_brick_slab_from_deepslate_stonecutting.json b/src/generated/resources/data/create/recipes/cut_deepslate_brick_slab_from_deepslate_stonecutting.json deleted file mode 100644 index de3db962a..000000000 --- a/src/generated/resources/data/create/recipes/cut_deepslate_brick_slab_from_deepslate_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "minecraft:deepslate" - }, - "result": "create:cut_deepslate_brick_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_deepslate_brick_stairs_from_deepslate_stonecutting.json b/src/generated/resources/data/create/recipes/cut_deepslate_brick_stairs_from_deepslate_stonecutting.json deleted file mode 100644 index 87eeedd73..000000000 --- a/src/generated/resources/data/create/recipes/cut_deepslate_brick_stairs_from_deepslate_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:deepslate" - }, - "result": "create:cut_deepslate_brick_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_deepslate_brick_wall_from_deepslate_stonecutting.json b/src/generated/resources/data/create/recipes/cut_deepslate_brick_wall_from_deepslate_stonecutting.json deleted file mode 100644 index a52ebc728..000000000 --- a/src/generated/resources/data/create/recipes/cut_deepslate_brick_wall_from_deepslate_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:deepslate" - }, - "result": "create:cut_deepslate_brick_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_deepslate_bricks_from_deepslate_stonecutting.json b/src/generated/resources/data/create/recipes/cut_deepslate_bricks_from_deepslate_stonecutting.json deleted file mode 100644 index 439b721f9..000000000 --- a/src/generated/resources/data/create/recipes/cut_deepslate_bricks_from_deepslate_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:deepslate" - }, - "result": "create:cut_deepslate_bricks" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_deepslate_from_deepslate_stonecutting.json b/src/generated/resources/data/create/recipes/cut_deepslate_from_deepslate_stonecutting.json deleted file mode 100644 index e7d23ce6b..000000000 --- a/src/generated/resources/data/create/recipes/cut_deepslate_from_deepslate_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:deepslate" - }, - "result": "create:cut_deepslate" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_deepslate_slab_from_deepslate_stonecutting.json b/src/generated/resources/data/create/recipes/cut_deepslate_slab_from_deepslate_stonecutting.json deleted file mode 100644 index d152a14b6..000000000 --- a/src/generated/resources/data/create/recipes/cut_deepslate_slab_from_deepslate_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "minecraft:deepslate" - }, - "result": "create:cut_deepslate_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_deepslate_stairs_from_deepslate_stonecutting.json b/src/generated/resources/data/create/recipes/cut_deepslate_stairs_from_deepslate_stonecutting.json deleted file mode 100644 index b1b1c037e..000000000 --- a/src/generated/resources/data/create/recipes/cut_deepslate_stairs_from_deepslate_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:deepslate" - }, - "result": "create:cut_deepslate_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_deepslate_wall_from_deepslate_stonecutting.json b/src/generated/resources/data/create/recipes/cut_deepslate_wall_from_deepslate_stonecutting.json deleted file mode 100644 index c9134f221..000000000 --- a/src/generated/resources/data/create/recipes/cut_deepslate_wall_from_deepslate_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:deepslate" - }, - "result": "create:cut_deepslate_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_diorite_brick_slab_from_diorite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_diorite_brick_slab_from_diorite_stonecutting.json deleted file mode 100644 index bdb640fa5..000000000 --- a/src/generated/resources/data/create/recipes/cut_diorite_brick_slab_from_diorite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "minecraft:diorite" - }, - "result": "create:cut_diorite_brick_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_diorite_brick_stairs_from_diorite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_diorite_brick_stairs_from_diorite_stonecutting.json deleted file mode 100644 index 8b26dfddc..000000000 --- a/src/generated/resources/data/create/recipes/cut_diorite_brick_stairs_from_diorite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:diorite" - }, - "result": "create:cut_diorite_brick_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_diorite_brick_wall_from_diorite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_diorite_brick_wall_from_diorite_stonecutting.json deleted file mode 100644 index 4169a2127..000000000 --- a/src/generated/resources/data/create/recipes/cut_diorite_brick_wall_from_diorite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:diorite" - }, - "result": "create:cut_diorite_brick_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_diorite_bricks_from_diorite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_diorite_bricks_from_diorite_stonecutting.json deleted file mode 100644 index de2b640f6..000000000 --- a/src/generated/resources/data/create/recipes/cut_diorite_bricks_from_diorite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:diorite" - }, - "result": "create:cut_diorite_bricks" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_diorite_from_diorite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_diorite_from_diorite_stonecutting.json deleted file mode 100644 index dfd894367..000000000 --- a/src/generated/resources/data/create/recipes/cut_diorite_from_diorite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:diorite" - }, - "result": "create:cut_diorite" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_diorite_slab_from_diorite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_diorite_slab_from_diorite_stonecutting.json deleted file mode 100644 index 952b4ad88..000000000 --- a/src/generated/resources/data/create/recipes/cut_diorite_slab_from_diorite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "minecraft:diorite" - }, - "result": "create:cut_diorite_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_diorite_stairs_from_diorite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_diorite_stairs_from_diorite_stonecutting.json deleted file mode 100644 index 90fb03d20..000000000 --- a/src/generated/resources/data/create/recipes/cut_diorite_stairs_from_diorite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:diorite" - }, - "result": "create:cut_diorite_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_diorite_wall_from_diorite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_diorite_wall_from_diorite_stonecutting.json deleted file mode 100644 index 9aaf13c64..000000000 --- a/src/generated/resources/data/create/recipes/cut_diorite_wall_from_diorite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:diorite" - }, - "result": "create:cut_diorite_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_dripstone_brick_slab_from_dripstone_block_stonecutting.json b/src/generated/resources/data/create/recipes/cut_dripstone_brick_slab_from_dripstone_block_stonecutting.json deleted file mode 100644 index 07555cb00..000000000 --- a/src/generated/resources/data/create/recipes/cut_dripstone_brick_slab_from_dripstone_block_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "minecraft:dripstone_block" - }, - "result": "create:cut_dripstone_brick_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_dripstone_brick_stairs_from_dripstone_block_stonecutting.json b/src/generated/resources/data/create/recipes/cut_dripstone_brick_stairs_from_dripstone_block_stonecutting.json deleted file mode 100644 index 153dc0089..000000000 --- a/src/generated/resources/data/create/recipes/cut_dripstone_brick_stairs_from_dripstone_block_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:dripstone_block" - }, - "result": "create:cut_dripstone_brick_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_dripstone_brick_wall_from_dripstone_block_stonecutting.json b/src/generated/resources/data/create/recipes/cut_dripstone_brick_wall_from_dripstone_block_stonecutting.json deleted file mode 100644 index b5bea1ac8..000000000 --- a/src/generated/resources/data/create/recipes/cut_dripstone_brick_wall_from_dripstone_block_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:dripstone_block" - }, - "result": "create:cut_dripstone_brick_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_dripstone_bricks_from_dripstone_block_stonecutting.json b/src/generated/resources/data/create/recipes/cut_dripstone_bricks_from_dripstone_block_stonecutting.json deleted file mode 100644 index 897dc836b..000000000 --- a/src/generated/resources/data/create/recipes/cut_dripstone_bricks_from_dripstone_block_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:dripstone_block" - }, - "result": "create:cut_dripstone_bricks" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_dripstone_from_dripstone_block_stonecutting.json b/src/generated/resources/data/create/recipes/cut_dripstone_from_dripstone_block_stonecutting.json deleted file mode 100644 index 411d69849..000000000 --- a/src/generated/resources/data/create/recipes/cut_dripstone_from_dripstone_block_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:dripstone_block" - }, - "result": "create:cut_dripstone" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_dripstone_slab_from_dripstone_block_stonecutting.json b/src/generated/resources/data/create/recipes/cut_dripstone_slab_from_dripstone_block_stonecutting.json deleted file mode 100644 index a75417ea8..000000000 --- a/src/generated/resources/data/create/recipes/cut_dripstone_slab_from_dripstone_block_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "minecraft:dripstone_block" - }, - "result": "create:cut_dripstone_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_dripstone_stairs_from_dripstone_block_stonecutting.json b/src/generated/resources/data/create/recipes/cut_dripstone_stairs_from_dripstone_block_stonecutting.json deleted file mode 100644 index 28b045d1e..000000000 --- a/src/generated/resources/data/create/recipes/cut_dripstone_stairs_from_dripstone_block_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:dripstone_block" - }, - "result": "create:cut_dripstone_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_dripstone_wall_from_dripstone_block_stonecutting.json b/src/generated/resources/data/create/recipes/cut_dripstone_wall_from_dripstone_block_stonecutting.json deleted file mode 100644 index 3670f4ee4..000000000 --- a/src/generated/resources/data/create/recipes/cut_dripstone_wall_from_dripstone_block_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:dripstone_block" - }, - "result": "create:cut_dripstone_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_granite_brick_slab_from_granite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_granite_brick_slab_from_granite_stonecutting.json deleted file mode 100644 index 257dbc1c2..000000000 --- a/src/generated/resources/data/create/recipes/cut_granite_brick_slab_from_granite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "minecraft:granite" - }, - "result": "create:cut_granite_brick_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_granite_brick_stairs_from_granite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_granite_brick_stairs_from_granite_stonecutting.json deleted file mode 100644 index f7a826b70..000000000 --- a/src/generated/resources/data/create/recipes/cut_granite_brick_stairs_from_granite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:granite" - }, - "result": "create:cut_granite_brick_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_granite_brick_wall_from_granite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_granite_brick_wall_from_granite_stonecutting.json deleted file mode 100644 index 0a6eecfb9..000000000 --- a/src/generated/resources/data/create/recipes/cut_granite_brick_wall_from_granite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:granite" - }, - "result": "create:cut_granite_brick_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_granite_bricks_from_granite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_granite_bricks_from_granite_stonecutting.json deleted file mode 100644 index 350d996d1..000000000 --- a/src/generated/resources/data/create/recipes/cut_granite_bricks_from_granite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:granite" - }, - "result": "create:cut_granite_bricks" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_granite_from_granite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_granite_from_granite_stonecutting.json deleted file mode 100644 index eefa36ac8..000000000 --- a/src/generated/resources/data/create/recipes/cut_granite_from_granite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:granite" - }, - "result": "create:cut_granite" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_granite_slab_from_granite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_granite_slab_from_granite_stonecutting.json deleted file mode 100644 index cb7b88842..000000000 --- a/src/generated/resources/data/create/recipes/cut_granite_slab_from_granite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "minecraft:granite" - }, - "result": "create:cut_granite_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_granite_stairs_from_granite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_granite_stairs_from_granite_stonecutting.json deleted file mode 100644 index 7cec092f2..000000000 --- a/src/generated/resources/data/create/recipes/cut_granite_stairs_from_granite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:granite" - }, - "result": "create:cut_granite_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_granite_wall_from_granite_stonecutting.json b/src/generated/resources/data/create/recipes/cut_granite_wall_from_granite_stonecutting.json deleted file mode 100644 index 8eb8fcc0c..000000000 --- a/src/generated/resources/data/create/recipes/cut_granite_wall_from_granite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:granite" - }, - "result": "create:cut_granite_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_limestone_brick_slab_from_limestone_stonecutting.json b/src/generated/resources/data/create/recipes/cut_limestone_brick_slab_from_limestone_stonecutting.json deleted file mode 100644 index 56ab575d6..000000000 --- a/src/generated/resources/data/create/recipes/cut_limestone_brick_slab_from_limestone_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "create:limestone" - }, - "result": "create:cut_limestone_brick_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_limestone_brick_stairs_from_limestone_stonecutting.json b/src/generated/resources/data/create/recipes/cut_limestone_brick_stairs_from_limestone_stonecutting.json deleted file mode 100644 index a17f2e566..000000000 --- a/src/generated/resources/data/create/recipes/cut_limestone_brick_stairs_from_limestone_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:limestone" - }, - "result": "create:cut_limestone_brick_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_limestone_brick_wall_from_limestone_stonecutting.json b/src/generated/resources/data/create/recipes/cut_limestone_brick_wall_from_limestone_stonecutting.json deleted file mode 100644 index 3ab1540fb..000000000 --- a/src/generated/resources/data/create/recipes/cut_limestone_brick_wall_from_limestone_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:limestone" - }, - "result": "create:cut_limestone_brick_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_limestone_bricks_from_limestone_stonecutting.json b/src/generated/resources/data/create/recipes/cut_limestone_bricks_from_limestone_stonecutting.json deleted file mode 100644 index 0e19ce62a..000000000 --- a/src/generated/resources/data/create/recipes/cut_limestone_bricks_from_limestone_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:limestone" - }, - "result": "create:cut_limestone_bricks" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_limestone_from_limestone_stonecutting.json b/src/generated/resources/data/create/recipes/cut_limestone_from_limestone_stonecutting.json deleted file mode 100644 index 799f1e2e8..000000000 --- a/src/generated/resources/data/create/recipes/cut_limestone_from_limestone_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:limestone" - }, - "result": "create:cut_limestone" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_limestone_slab_from_limestone_stonecutting.json b/src/generated/resources/data/create/recipes/cut_limestone_slab_from_limestone_stonecutting.json deleted file mode 100644 index f1a0abf23..000000000 --- a/src/generated/resources/data/create/recipes/cut_limestone_slab_from_limestone_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "create:limestone" - }, - "result": "create:cut_limestone_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_limestone_stairs_from_limestone_stonecutting.json b/src/generated/resources/data/create/recipes/cut_limestone_stairs_from_limestone_stonecutting.json deleted file mode 100644 index ab70cbd38..000000000 --- a/src/generated/resources/data/create/recipes/cut_limestone_stairs_from_limestone_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:limestone" - }, - "result": "create:cut_limestone_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_limestone_wall_from_limestone_stonecutting.json b/src/generated/resources/data/create/recipes/cut_limestone_wall_from_limestone_stonecutting.json deleted file mode 100644 index 3a283db11..000000000 --- a/src/generated/resources/data/create/recipes/cut_limestone_wall_from_limestone_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:limestone" - }, - "result": "create:cut_limestone_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_ochrum_brick_slab_from_ochrum_stonecutting.json b/src/generated/resources/data/create/recipes/cut_ochrum_brick_slab_from_ochrum_stonecutting.json deleted file mode 100644 index 084b2bff3..000000000 --- a/src/generated/resources/data/create/recipes/cut_ochrum_brick_slab_from_ochrum_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "create:ochrum" - }, - "result": "create:cut_ochrum_brick_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_ochrum_brick_stairs_from_ochrum_stonecutting.json b/src/generated/resources/data/create/recipes/cut_ochrum_brick_stairs_from_ochrum_stonecutting.json deleted file mode 100644 index 7e202eb39..000000000 --- a/src/generated/resources/data/create/recipes/cut_ochrum_brick_stairs_from_ochrum_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:ochrum" - }, - "result": "create:cut_ochrum_brick_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_ochrum_brick_wall_from_ochrum_stonecutting.json b/src/generated/resources/data/create/recipes/cut_ochrum_brick_wall_from_ochrum_stonecutting.json deleted file mode 100644 index 56c816660..000000000 --- a/src/generated/resources/data/create/recipes/cut_ochrum_brick_wall_from_ochrum_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:ochrum" - }, - "result": "create:cut_ochrum_brick_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_ochrum_bricks_from_ochrum_stonecutting.json b/src/generated/resources/data/create/recipes/cut_ochrum_bricks_from_ochrum_stonecutting.json deleted file mode 100644 index db34dfd88..000000000 --- a/src/generated/resources/data/create/recipes/cut_ochrum_bricks_from_ochrum_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:ochrum" - }, - "result": "create:cut_ochrum_bricks" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_ochrum_from_ochrum_stonecutting.json b/src/generated/resources/data/create/recipes/cut_ochrum_from_ochrum_stonecutting.json deleted file mode 100644 index 5b5a4be97..000000000 --- a/src/generated/resources/data/create/recipes/cut_ochrum_from_ochrum_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:ochrum" - }, - "result": "create:cut_ochrum" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_ochrum_slab_from_ochrum_stonecutting.json b/src/generated/resources/data/create/recipes/cut_ochrum_slab_from_ochrum_stonecutting.json deleted file mode 100644 index a35cd2d1f..000000000 --- a/src/generated/resources/data/create/recipes/cut_ochrum_slab_from_ochrum_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "create:ochrum" - }, - "result": "create:cut_ochrum_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_ochrum_stairs_from_ochrum_stonecutting.json b/src/generated/resources/data/create/recipes/cut_ochrum_stairs_from_ochrum_stonecutting.json deleted file mode 100644 index 237448d7f..000000000 --- a/src/generated/resources/data/create/recipes/cut_ochrum_stairs_from_ochrum_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:ochrum" - }, - "result": "create:cut_ochrum_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_ochrum_wall_from_ochrum_stonecutting.json b/src/generated/resources/data/create/recipes/cut_ochrum_wall_from_ochrum_stonecutting.json deleted file mode 100644 index d5325ccdc..000000000 --- a/src/generated/resources/data/create/recipes/cut_ochrum_wall_from_ochrum_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:ochrum" - }, - "result": "create:cut_ochrum_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_scorchia_brick_slab_from_scorchia_stonecutting.json b/src/generated/resources/data/create/recipes/cut_scorchia_brick_slab_from_scorchia_stonecutting.json deleted file mode 100644 index 87ccc9248..000000000 --- a/src/generated/resources/data/create/recipes/cut_scorchia_brick_slab_from_scorchia_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "create:scorchia" - }, - "result": "create:cut_scorchia_brick_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_scorchia_brick_stairs_from_scorchia_stonecutting.json b/src/generated/resources/data/create/recipes/cut_scorchia_brick_stairs_from_scorchia_stonecutting.json deleted file mode 100644 index 80784d07a..000000000 --- a/src/generated/resources/data/create/recipes/cut_scorchia_brick_stairs_from_scorchia_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:scorchia" - }, - "result": "create:cut_scorchia_brick_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_scorchia_brick_wall_from_scorchia_stonecutting.json b/src/generated/resources/data/create/recipes/cut_scorchia_brick_wall_from_scorchia_stonecutting.json deleted file mode 100644 index 104cfa2f9..000000000 --- a/src/generated/resources/data/create/recipes/cut_scorchia_brick_wall_from_scorchia_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:scorchia" - }, - "result": "create:cut_scorchia_brick_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_scorchia_bricks_from_scorchia_stonecutting.json b/src/generated/resources/data/create/recipes/cut_scorchia_bricks_from_scorchia_stonecutting.json deleted file mode 100644 index a857f221f..000000000 --- a/src/generated/resources/data/create/recipes/cut_scorchia_bricks_from_scorchia_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:scorchia" - }, - "result": "create:cut_scorchia_bricks" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_scorchia_from_scorchia_stonecutting.json b/src/generated/resources/data/create/recipes/cut_scorchia_from_scorchia_stonecutting.json deleted file mode 100644 index 677e0138c..000000000 --- a/src/generated/resources/data/create/recipes/cut_scorchia_from_scorchia_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:scorchia" - }, - "result": "create:cut_scorchia" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_scorchia_slab_from_scorchia_stonecutting.json b/src/generated/resources/data/create/recipes/cut_scorchia_slab_from_scorchia_stonecutting.json deleted file mode 100644 index 0c54c04c8..000000000 --- a/src/generated/resources/data/create/recipes/cut_scorchia_slab_from_scorchia_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "create:scorchia" - }, - "result": "create:cut_scorchia_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_scorchia_stairs_from_scorchia_stonecutting.json b/src/generated/resources/data/create/recipes/cut_scorchia_stairs_from_scorchia_stonecutting.json deleted file mode 100644 index d81115f56..000000000 --- a/src/generated/resources/data/create/recipes/cut_scorchia_stairs_from_scorchia_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:scorchia" - }, - "result": "create:cut_scorchia_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_scorchia_wall_from_scorchia_stonecutting.json b/src/generated/resources/data/create/recipes/cut_scorchia_wall_from_scorchia_stonecutting.json deleted file mode 100644 index c75e03d2d..000000000 --- a/src/generated/resources/data/create/recipes/cut_scorchia_wall_from_scorchia_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:scorchia" - }, - "result": "create:cut_scorchia_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_scoria_brick_slab_from_scoria_stonecutting.json b/src/generated/resources/data/create/recipes/cut_scoria_brick_slab_from_scoria_stonecutting.json deleted file mode 100644 index d7f07c8b5..000000000 --- a/src/generated/resources/data/create/recipes/cut_scoria_brick_slab_from_scoria_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "create:scoria" - }, - "result": "create:cut_scoria_brick_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_scoria_brick_stairs_from_scoria_stonecutting.json b/src/generated/resources/data/create/recipes/cut_scoria_brick_stairs_from_scoria_stonecutting.json deleted file mode 100644 index 0cec52dd0..000000000 --- a/src/generated/resources/data/create/recipes/cut_scoria_brick_stairs_from_scoria_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:scoria" - }, - "result": "create:cut_scoria_brick_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_scoria_brick_wall_from_scoria_stonecutting.json b/src/generated/resources/data/create/recipes/cut_scoria_brick_wall_from_scoria_stonecutting.json deleted file mode 100644 index 90334fb6a..000000000 --- a/src/generated/resources/data/create/recipes/cut_scoria_brick_wall_from_scoria_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:scoria" - }, - "result": "create:cut_scoria_brick_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_scoria_bricks_from_scoria_stonecutting.json b/src/generated/resources/data/create/recipes/cut_scoria_bricks_from_scoria_stonecutting.json deleted file mode 100644 index 75f17a978..000000000 --- a/src/generated/resources/data/create/recipes/cut_scoria_bricks_from_scoria_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:scoria" - }, - "result": "create:cut_scoria_bricks" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_scoria_from_scoria_stonecutting.json b/src/generated/resources/data/create/recipes/cut_scoria_from_scoria_stonecutting.json deleted file mode 100644 index a234de235..000000000 --- a/src/generated/resources/data/create/recipes/cut_scoria_from_scoria_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:scoria" - }, - "result": "create:cut_scoria" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_scoria_slab_from_scoria_stonecutting.json b/src/generated/resources/data/create/recipes/cut_scoria_slab_from_scoria_stonecutting.json deleted file mode 100644 index ac3778fcd..000000000 --- a/src/generated/resources/data/create/recipes/cut_scoria_slab_from_scoria_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "create:scoria" - }, - "result": "create:cut_scoria_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_scoria_stairs_from_scoria_stonecutting.json b/src/generated/resources/data/create/recipes/cut_scoria_stairs_from_scoria_stonecutting.json deleted file mode 100644 index e3c25837c..000000000 --- a/src/generated/resources/data/create/recipes/cut_scoria_stairs_from_scoria_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:scoria" - }, - "result": "create:cut_scoria_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_scoria_wall_from_scoria_stonecutting.json b/src/generated/resources/data/create/recipes/cut_scoria_wall_from_scoria_stonecutting.json deleted file mode 100644 index 6bfc7eb5f..000000000 --- a/src/generated/resources/data/create/recipes/cut_scoria_wall_from_scoria_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:scoria" - }, - "result": "create:cut_scoria_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_tuff_brick_slab_from_tuff_stonecutting.json b/src/generated/resources/data/create/recipes/cut_tuff_brick_slab_from_tuff_stonecutting.json deleted file mode 100644 index 44ff9be7e..000000000 --- a/src/generated/resources/data/create/recipes/cut_tuff_brick_slab_from_tuff_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "minecraft:tuff" - }, - "result": "create:cut_tuff_brick_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_tuff_brick_stairs_from_tuff_stonecutting.json b/src/generated/resources/data/create/recipes/cut_tuff_brick_stairs_from_tuff_stonecutting.json deleted file mode 100644 index 984e9e862..000000000 --- a/src/generated/resources/data/create/recipes/cut_tuff_brick_stairs_from_tuff_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:tuff" - }, - "result": "create:cut_tuff_brick_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_tuff_brick_wall_from_tuff_stonecutting.json b/src/generated/resources/data/create/recipes/cut_tuff_brick_wall_from_tuff_stonecutting.json deleted file mode 100644 index 41085ab7a..000000000 --- a/src/generated/resources/data/create/recipes/cut_tuff_brick_wall_from_tuff_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:tuff" - }, - "result": "create:cut_tuff_brick_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_tuff_bricks_from_tuff_stonecutting.json b/src/generated/resources/data/create/recipes/cut_tuff_bricks_from_tuff_stonecutting.json deleted file mode 100644 index 63573d9a2..000000000 --- a/src/generated/resources/data/create/recipes/cut_tuff_bricks_from_tuff_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:tuff" - }, - "result": "create:cut_tuff_bricks" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_tuff_from_tuff_stonecutting.json b/src/generated/resources/data/create/recipes/cut_tuff_from_tuff_stonecutting.json deleted file mode 100644 index 7b283bca4..000000000 --- a/src/generated/resources/data/create/recipes/cut_tuff_from_tuff_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:tuff" - }, - "result": "create:cut_tuff" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_tuff_slab_from_tuff_stonecutting.json b/src/generated/resources/data/create/recipes/cut_tuff_slab_from_tuff_stonecutting.json deleted file mode 100644 index 5659f310b..000000000 --- a/src/generated/resources/data/create/recipes/cut_tuff_slab_from_tuff_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "minecraft:tuff" - }, - "result": "create:cut_tuff_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_tuff_stairs_from_tuff_stonecutting.json b/src/generated/resources/data/create/recipes/cut_tuff_stairs_from_tuff_stonecutting.json deleted file mode 100644 index 9fae6e540..000000000 --- a/src/generated/resources/data/create/recipes/cut_tuff_stairs_from_tuff_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:tuff" - }, - "result": "create:cut_tuff_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_tuff_wall_from_tuff_stonecutting.json b/src/generated/resources/data/create/recipes/cut_tuff_wall_from_tuff_stonecutting.json deleted file mode 100644 index 0c7d24b67..000000000 --- a/src/generated/resources/data/create/recipes/cut_tuff_wall_from_tuff_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:tuff" - }, - "result": "create:cut_tuff_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_veridium_brick_slab_from_veridium_stonecutting.json b/src/generated/resources/data/create/recipes/cut_veridium_brick_slab_from_veridium_stonecutting.json deleted file mode 100644 index e11c98b8d..000000000 --- a/src/generated/resources/data/create/recipes/cut_veridium_brick_slab_from_veridium_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "create:veridium" - }, - "result": "create:cut_veridium_brick_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_veridium_brick_stairs_from_veridium_stonecutting.json b/src/generated/resources/data/create/recipes/cut_veridium_brick_stairs_from_veridium_stonecutting.json deleted file mode 100644 index 085e58b58..000000000 --- a/src/generated/resources/data/create/recipes/cut_veridium_brick_stairs_from_veridium_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:veridium" - }, - "result": "create:cut_veridium_brick_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_veridium_brick_wall_from_veridium_stonecutting.json b/src/generated/resources/data/create/recipes/cut_veridium_brick_wall_from_veridium_stonecutting.json deleted file mode 100644 index 86d1bfa5c..000000000 --- a/src/generated/resources/data/create/recipes/cut_veridium_brick_wall_from_veridium_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:veridium" - }, - "result": "create:cut_veridium_brick_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_veridium_bricks_from_veridium_stonecutting.json b/src/generated/resources/data/create/recipes/cut_veridium_bricks_from_veridium_stonecutting.json deleted file mode 100644 index 7a68d7c4c..000000000 --- a/src/generated/resources/data/create/recipes/cut_veridium_bricks_from_veridium_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:veridium" - }, - "result": "create:cut_veridium_bricks" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_veridium_from_veridium_stonecutting.json b/src/generated/resources/data/create/recipes/cut_veridium_from_veridium_stonecutting.json deleted file mode 100644 index ee7e46926..000000000 --- a/src/generated/resources/data/create/recipes/cut_veridium_from_veridium_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:veridium" - }, - "result": "create:cut_veridium" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_veridium_slab_from_veridium_stonecutting.json b/src/generated/resources/data/create/recipes/cut_veridium_slab_from_veridium_stonecutting.json deleted file mode 100644 index 7db3bc28d..000000000 --- a/src/generated/resources/data/create/recipes/cut_veridium_slab_from_veridium_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "create:veridium" - }, - "result": "create:cut_veridium_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_veridium_stairs_from_veridium_stonecutting.json b/src/generated/resources/data/create/recipes/cut_veridium_stairs_from_veridium_stonecutting.json deleted file mode 100644 index e531a3444..000000000 --- a/src/generated/resources/data/create/recipes/cut_veridium_stairs_from_veridium_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:veridium" - }, - "result": "create:cut_veridium_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cut_veridium_wall_from_veridium_stonecutting.json b/src/generated/resources/data/create/recipes/cut_veridium_wall_from_veridium_stonecutting.json deleted file mode 100644 index 119d64321..000000000 --- a/src/generated/resources/data/create/recipes/cut_veridium_wall_from_veridium_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:veridium" - }, - "result": "create:cut_veridium_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/mangrove_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/mangrove_log.json deleted file mode 100644 index 0f4b24e33..000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/mangrove_log.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:mangrove_log" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_mangrove_log" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/mangrove_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/mangrove_wood.json deleted file mode 100644 index bc78983cc..000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/mangrove_wood.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:mangrove_wood" - } - ], - "processingTime": 50, - "results": [ - { - "item": "byg:stripped_mangrove_wood" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_mangrove_log.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_mangrove_log.json deleted file mode 100644 index 901ef74a7..000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_mangrove_log.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_mangrove_log" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:mangrove_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_mangrove_wood.json b/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_mangrove_wood.json deleted file mode 100644 index dea6c7065..000000000 --- a/src/generated/resources/data/create/recipes/cutting/compat/byg/stripped_mangrove_wood.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type": "create:cutting", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "byg" - } - ], - "ingredients": [ - { - "item": "byg:stripped_mangrove_wood" - } - ], - "processingTime": 50, - "results": [ - { - "count": 6, - "item": "byg:mangrove_planks" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deepslate_from_stone_types_deepslate_stonecutting.json b/src/generated/resources/data/create/recipes/deepslate_from_stone_types_deepslate_stonecutting.json new file mode 100644 index 000000000..1da82f5f7 --- /dev/null +++ b/src/generated/resources/data/create/recipes/deepslate_from_stone_types_deepslate_stonecutting.json @@ -0,0 +1,8 @@ +{ + "type": "minecraft:stonecutting", + "count": 1, + "ingredient": { + "tag": "create:stone_types/deepslate" + }, + "result": "minecraft:deepslate" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/deepslate_pillar_from_deepslate_stonecutting.json b/src/generated/resources/data/create/recipes/deepslate_pillar_from_deepslate_stonecutting.json deleted file mode 100644 index 91d6a6a04..000000000 --- a/src/generated/resources/data/create/recipes/deepslate_pillar_from_deepslate_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:deepslate" - }, - "result": "create:deepslate_pillar" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/diorite_from_stone_types_diorite_stonecutting.json b/src/generated/resources/data/create/recipes/diorite_from_stone_types_diorite_stonecutting.json new file mode 100644 index 000000000..0ecd1bfda --- /dev/null +++ b/src/generated/resources/data/create/recipes/diorite_from_stone_types_diorite_stonecutting.json @@ -0,0 +1,8 @@ +{ + "type": "minecraft:stonecutting", + "count": 1, + "ingredient": { + "tag": "create:stone_types/diorite" + }, + "result": "minecraft:diorite" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/diorite_pillar_from_diorite_stonecutting.json b/src/generated/resources/data/create/recipes/diorite_pillar_from_diorite_stonecutting.json deleted file mode 100644 index f7b08fd68..000000000 --- a/src/generated/resources/data/create/recipes/diorite_pillar_from_diorite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:diorite" - }, - "result": "create:diorite_pillar" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/dripstone_block_from_stone_types_dripstone_stonecutting.json b/src/generated/resources/data/create/recipes/dripstone_block_from_stone_types_dripstone_stonecutting.json new file mode 100644 index 000000000..9bd2396ca --- /dev/null +++ b/src/generated/resources/data/create/recipes/dripstone_block_from_stone_types_dripstone_stonecutting.json @@ -0,0 +1,8 @@ +{ + "type": "minecraft:stonecutting", + "count": 1, + "ingredient": { + "tag": "create:stone_types/dripstone" + }, + "result": "minecraft:dripstone_block" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/dripstone_pillar_from_dripstone_block_stonecutting.json b/src/generated/resources/data/create/recipes/dripstone_pillar_from_dripstone_block_stonecutting.json deleted file mode 100644 index ed4ecfebc..000000000 --- a/src/generated/resources/data/create/recipes/dripstone_pillar_from_dripstone_block_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:dripstone_block" - }, - "result": "create:dripstone_pillar" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/granite_from_stone_types_granite_stonecutting.json b/src/generated/resources/data/create/recipes/granite_from_stone_types_granite_stonecutting.json new file mode 100644 index 000000000..dbe5ada30 --- /dev/null +++ b/src/generated/resources/data/create/recipes/granite_from_stone_types_granite_stonecutting.json @@ -0,0 +1,8 @@ +{ + "type": "minecraft:stonecutting", + "count": 1, + "ingredient": { + "tag": "create:stone_types/granite" + }, + "result": "minecraft:granite" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/granite_pillar_from_granite_stonecutting.json b/src/generated/resources/data/create/recipes/granite_pillar_from_granite_stonecutting.json deleted file mode 100644 index 20866a93f..000000000 --- a/src/generated/resources/data/create/recipes/granite_pillar_from_granite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:granite" - }, - "result": "create:granite_pillar" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/industrial_iron_block_from_ingots_iron_stonecutting.json b/src/generated/resources/data/create/recipes/industrial_iron_block_from_ingots_iron_stonecutting.json new file mode 100644 index 000000000..e4c394306 --- /dev/null +++ b/src/generated/resources/data/create/recipes/industrial_iron_block_from_ingots_iron_stonecutting.json @@ -0,0 +1,8 @@ +{ + "type": "minecraft:stonecutting", + "count": 2, + "ingredient": { + "tag": "forge:ingots/iron" + }, + "result": "create:industrial_iron_block" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/layered_andesite_from_andesite_stonecutting.json b/src/generated/resources/data/create/recipes/layered_andesite_from_andesite_stonecutting.json deleted file mode 100644 index 42c17a7b8..000000000 --- a/src/generated/resources/data/create/recipes/layered_andesite_from_andesite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:andesite" - }, - "result": "create:layered_andesite" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/layered_asurine_from_asurine_stonecutting.json b/src/generated/resources/data/create/recipes/layered_asurine_from_asurine_stonecutting.json deleted file mode 100644 index ab73d0a6d..000000000 --- a/src/generated/resources/data/create/recipes/layered_asurine_from_asurine_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:asurine" - }, - "result": "create:layered_asurine" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/layered_calcite_from_calcite_stonecutting.json b/src/generated/resources/data/create/recipes/layered_calcite_from_calcite_stonecutting.json deleted file mode 100644 index fd07345f4..000000000 --- a/src/generated/resources/data/create/recipes/layered_calcite_from_calcite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:calcite" - }, - "result": "create:layered_calcite" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/layered_crimsite_from_crimsite_stonecutting.json b/src/generated/resources/data/create/recipes/layered_crimsite_from_crimsite_stonecutting.json deleted file mode 100644 index 3e1a13feb..000000000 --- a/src/generated/resources/data/create/recipes/layered_crimsite_from_crimsite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:crimsite" - }, - "result": "create:layered_crimsite" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/layered_deepslate_from_deepslate_stonecutting.json b/src/generated/resources/data/create/recipes/layered_deepslate_from_deepslate_stonecutting.json deleted file mode 100644 index b9f4191ba..000000000 --- a/src/generated/resources/data/create/recipes/layered_deepslate_from_deepslate_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:deepslate" - }, - "result": "create:layered_deepslate" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/layered_diorite_from_diorite_stonecutting.json b/src/generated/resources/data/create/recipes/layered_diorite_from_diorite_stonecutting.json deleted file mode 100644 index 5fdf13adb..000000000 --- a/src/generated/resources/data/create/recipes/layered_diorite_from_diorite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:diorite" - }, - "result": "create:layered_diorite" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/layered_dripstone_from_dripstone_block_stonecutting.json b/src/generated/resources/data/create/recipes/layered_dripstone_from_dripstone_block_stonecutting.json deleted file mode 100644 index 6c1e84519..000000000 --- a/src/generated/resources/data/create/recipes/layered_dripstone_from_dripstone_block_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:dripstone_block" - }, - "result": "create:layered_dripstone" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/layered_granite_from_granite_stonecutting.json b/src/generated/resources/data/create/recipes/layered_granite_from_granite_stonecutting.json deleted file mode 100644 index 5849245e5..000000000 --- a/src/generated/resources/data/create/recipes/layered_granite_from_granite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:granite" - }, - "result": "create:layered_granite" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/layered_limestone_from_limestone_stonecutting.json b/src/generated/resources/data/create/recipes/layered_limestone_from_limestone_stonecutting.json deleted file mode 100644 index d1a3218b1..000000000 --- a/src/generated/resources/data/create/recipes/layered_limestone_from_limestone_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:limestone" - }, - "result": "create:layered_limestone" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/layered_ochrum_from_ochrum_stonecutting.json b/src/generated/resources/data/create/recipes/layered_ochrum_from_ochrum_stonecutting.json deleted file mode 100644 index d092f56b2..000000000 --- a/src/generated/resources/data/create/recipes/layered_ochrum_from_ochrum_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:ochrum" - }, - "result": "create:layered_ochrum" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/layered_scorchia_from_scorchia_stonecutting.json b/src/generated/resources/data/create/recipes/layered_scorchia_from_scorchia_stonecutting.json deleted file mode 100644 index 4104e97a8..000000000 --- a/src/generated/resources/data/create/recipes/layered_scorchia_from_scorchia_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:scorchia" - }, - "result": "create:layered_scorchia" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/layered_scoria_from_scoria_stonecutting.json b/src/generated/resources/data/create/recipes/layered_scoria_from_scoria_stonecutting.json deleted file mode 100644 index 6feb1e9a0..000000000 --- a/src/generated/resources/data/create/recipes/layered_scoria_from_scoria_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:scoria" - }, - "result": "create:layered_scoria" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/layered_tuff_from_tuff_stonecutting.json b/src/generated/resources/data/create/recipes/layered_tuff_from_tuff_stonecutting.json deleted file mode 100644 index 76f49d0fb..000000000 --- a/src/generated/resources/data/create/recipes/layered_tuff_from_tuff_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:tuff" - }, - "result": "create:layered_tuff" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/layered_veridium_from_veridium_stonecutting.json b/src/generated/resources/data/create/recipes/layered_veridium_from_veridium_stonecutting.json deleted file mode 100644 index d25be2709..000000000 --- a/src/generated/resources/data/create/recipes/layered_veridium_from_veridium_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:veridium" - }, - "result": "create:layered_veridium" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/limestone_from_stone_types_limestone_stonecutting.json b/src/generated/resources/data/create/recipes/limestone_from_stone_types_limestone_stonecutting.json new file mode 100644 index 000000000..e0dbccc60 --- /dev/null +++ b/src/generated/resources/data/create/recipes/limestone_from_stone_types_limestone_stonecutting.json @@ -0,0 +1,8 @@ +{ + "type": "minecraft:stonecutting", + "count": 1, + "ingredient": { + "tag": "create:stone_types/limestone" + }, + "result": "create:limestone" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/limestone_pillar_from_limestone_stonecutting.json b/src/generated/resources/data/create/recipes/limestone_pillar_from_limestone_stonecutting.json deleted file mode 100644 index cfb9c8b2d..000000000 --- a/src/generated/resources/data/create/recipes/limestone_pillar_from_limestone_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:limestone" - }, - "result": "create:limestone_pillar" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/mangrove_window.json b/src/generated/resources/data/create/recipes/mangrove_window.json new file mode 100644 index 000000000..20c34e146 --- /dev/null +++ b/src/generated/resources/data/create/recipes/mangrove_window.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "building", + "key": { + "#": { + "item": "minecraft:mangrove_planks" + }, + "X": { + "tag": "forge:glass/colorless" + } + }, + "pattern": [ + " # ", + "#X#" + ], + "result": { + "count": 2, + "item": "create:mangrove_window" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/mangrove_window_pane.json b/src/generated/resources/data/create/recipes/mangrove_window_pane.json new file mode 100644 index 000000000..76a80f364 --- /dev/null +++ b/src/generated/resources/data/create/recipes/mangrove_window_pane.json @@ -0,0 +1,17 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "building", + "key": { + "#": { + "item": "create:mangrove_window" + } + }, + "pattern": [ + "###", + "###" + ], + "result": { + "count": 16, + "item": "create:mangrove_window_pane" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/ochrum_from_stone_types_ochrum_stonecutting.json b/src/generated/resources/data/create/recipes/ochrum_from_stone_types_ochrum_stonecutting.json new file mode 100644 index 000000000..d1f098eca --- /dev/null +++ b/src/generated/resources/data/create/recipes/ochrum_from_stone_types_ochrum_stonecutting.json @@ -0,0 +1,8 @@ +{ + "type": "minecraft:stonecutting", + "count": 1, + "ingredient": { + "tag": "create:stone_types/ochrum" + }, + "result": "create:ochrum" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/ochrum_pillar_from_ochrum_stonecutting.json b/src/generated/resources/data/create/recipes/ochrum_pillar_from_ochrum_stonecutting.json deleted file mode 100644 index 41fe79e3c..000000000 --- a/src/generated/resources/data/create/recipes/ochrum_pillar_from_ochrum_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:ochrum" - }, - "result": "create:ochrum_pillar" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_andesite_from_andesite_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_andesite_from_andesite_stonecutting.json deleted file mode 100644 index 5bfb9f83e..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_andesite_from_andesite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:andesite" - }, - "result": "create:polished_cut_andesite" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_andesite_slab_from_andesite_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_andesite_slab_from_andesite_stonecutting.json deleted file mode 100644 index 58b80d2fb..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_andesite_slab_from_andesite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "minecraft:andesite" - }, - "result": "create:polished_cut_andesite_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_andesite_stairs_from_andesite_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_andesite_stairs_from_andesite_stonecutting.json deleted file mode 100644 index 4fd3ee0b2..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_andesite_stairs_from_andesite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:andesite" - }, - "result": "create:polished_cut_andesite_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_andesite_wall_from_andesite_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_andesite_wall_from_andesite_stonecutting.json deleted file mode 100644 index f5dd5efc4..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_andesite_wall_from_andesite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:andesite" - }, - "result": "create:polished_cut_andesite_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_asurine_from_asurine_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_asurine_from_asurine_stonecutting.json deleted file mode 100644 index dcc8c94b4..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_asurine_from_asurine_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:asurine" - }, - "result": "create:polished_cut_asurine" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_asurine_slab_from_asurine_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_asurine_slab_from_asurine_stonecutting.json deleted file mode 100644 index bcbdef5cb..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_asurine_slab_from_asurine_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "create:asurine" - }, - "result": "create:polished_cut_asurine_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_asurine_stairs_from_asurine_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_asurine_stairs_from_asurine_stonecutting.json deleted file mode 100644 index 91d4048bf..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_asurine_stairs_from_asurine_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:asurine" - }, - "result": "create:polished_cut_asurine_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_asurine_wall_from_asurine_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_asurine_wall_from_asurine_stonecutting.json deleted file mode 100644 index e032256c8..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_asurine_wall_from_asurine_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:asurine" - }, - "result": "create:polished_cut_asurine_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_calcite_from_calcite_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_calcite_from_calcite_stonecutting.json deleted file mode 100644 index bff6ad416..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_calcite_from_calcite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:calcite" - }, - "result": "create:polished_cut_calcite" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_calcite_slab_from_calcite_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_calcite_slab_from_calcite_stonecutting.json deleted file mode 100644 index 0544b9be0..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_calcite_slab_from_calcite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "minecraft:calcite" - }, - "result": "create:polished_cut_calcite_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_calcite_stairs_from_calcite_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_calcite_stairs_from_calcite_stonecutting.json deleted file mode 100644 index f30030818..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_calcite_stairs_from_calcite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:calcite" - }, - "result": "create:polished_cut_calcite_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_calcite_wall_from_calcite_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_calcite_wall_from_calcite_stonecutting.json deleted file mode 100644 index d3533124a..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_calcite_wall_from_calcite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:calcite" - }, - "result": "create:polished_cut_calcite_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_crimsite_from_crimsite_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_crimsite_from_crimsite_stonecutting.json deleted file mode 100644 index 67b1235ca..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_crimsite_from_crimsite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:crimsite" - }, - "result": "create:polished_cut_crimsite" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_crimsite_slab_from_crimsite_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_crimsite_slab_from_crimsite_stonecutting.json deleted file mode 100644 index 5605fee22..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_crimsite_slab_from_crimsite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "create:crimsite" - }, - "result": "create:polished_cut_crimsite_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_crimsite_stairs_from_crimsite_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_crimsite_stairs_from_crimsite_stonecutting.json deleted file mode 100644 index e6bc5361e..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_crimsite_stairs_from_crimsite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:crimsite" - }, - "result": "create:polished_cut_crimsite_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_crimsite_wall_from_crimsite_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_crimsite_wall_from_crimsite_stonecutting.json deleted file mode 100644 index 4fd72c497..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_crimsite_wall_from_crimsite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:crimsite" - }, - "result": "create:polished_cut_crimsite_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_deepslate_from_deepslate_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_deepslate_from_deepslate_stonecutting.json deleted file mode 100644 index c3bbc5477..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_deepslate_from_deepslate_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:deepslate" - }, - "result": "create:polished_cut_deepslate" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_deepslate_slab_from_deepslate_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_deepslate_slab_from_deepslate_stonecutting.json deleted file mode 100644 index 2b77ddcca..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_deepslate_slab_from_deepslate_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "minecraft:deepslate" - }, - "result": "create:polished_cut_deepslate_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_deepslate_stairs_from_deepslate_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_deepslate_stairs_from_deepslate_stonecutting.json deleted file mode 100644 index 38941ff5d..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_deepslate_stairs_from_deepslate_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:deepslate" - }, - "result": "create:polished_cut_deepslate_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_deepslate_wall_from_deepslate_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_deepslate_wall_from_deepslate_stonecutting.json deleted file mode 100644 index 3e17caf54..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_deepslate_wall_from_deepslate_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:deepslate" - }, - "result": "create:polished_cut_deepslate_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_diorite_from_diorite_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_diorite_from_diorite_stonecutting.json deleted file mode 100644 index 2fdbb6a19..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_diorite_from_diorite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:diorite" - }, - "result": "create:polished_cut_diorite" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_diorite_slab_from_diorite_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_diorite_slab_from_diorite_stonecutting.json deleted file mode 100644 index 19b18fa87..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_diorite_slab_from_diorite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "minecraft:diorite" - }, - "result": "create:polished_cut_diorite_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_diorite_stairs_from_diorite_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_diorite_stairs_from_diorite_stonecutting.json deleted file mode 100644 index 288872bd3..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_diorite_stairs_from_diorite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:diorite" - }, - "result": "create:polished_cut_diorite_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_diorite_wall_from_diorite_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_diorite_wall_from_diorite_stonecutting.json deleted file mode 100644 index a658b5c72..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_diorite_wall_from_diorite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:diorite" - }, - "result": "create:polished_cut_diorite_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_dripstone_from_dripstone_block_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_dripstone_from_dripstone_block_stonecutting.json deleted file mode 100644 index ab6d8575f..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_dripstone_from_dripstone_block_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:dripstone_block" - }, - "result": "create:polished_cut_dripstone" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_dripstone_slab_from_dripstone_block_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_dripstone_slab_from_dripstone_block_stonecutting.json deleted file mode 100644 index 078667baa..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_dripstone_slab_from_dripstone_block_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "minecraft:dripstone_block" - }, - "result": "create:polished_cut_dripstone_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_dripstone_stairs_from_dripstone_block_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_dripstone_stairs_from_dripstone_block_stonecutting.json deleted file mode 100644 index 24bb4d59e..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_dripstone_stairs_from_dripstone_block_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:dripstone_block" - }, - "result": "create:polished_cut_dripstone_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_dripstone_wall_from_dripstone_block_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_dripstone_wall_from_dripstone_block_stonecutting.json deleted file mode 100644 index ba991de0c..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_dripstone_wall_from_dripstone_block_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:dripstone_block" - }, - "result": "create:polished_cut_dripstone_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_granite_from_granite_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_granite_from_granite_stonecutting.json deleted file mode 100644 index 20a3de5d0..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_granite_from_granite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:granite" - }, - "result": "create:polished_cut_granite" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_granite_slab_from_granite_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_granite_slab_from_granite_stonecutting.json deleted file mode 100644 index 507628855..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_granite_slab_from_granite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "minecraft:granite" - }, - "result": "create:polished_cut_granite_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_granite_stairs_from_granite_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_granite_stairs_from_granite_stonecutting.json deleted file mode 100644 index 333cca6f5..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_granite_stairs_from_granite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:granite" - }, - "result": "create:polished_cut_granite_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_granite_wall_from_granite_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_granite_wall_from_granite_stonecutting.json deleted file mode 100644 index 2659d2cfa..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_granite_wall_from_granite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:granite" - }, - "result": "create:polished_cut_granite_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_limestone_from_limestone_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_limestone_from_limestone_stonecutting.json deleted file mode 100644 index 85f06a8c6..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_limestone_from_limestone_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:limestone" - }, - "result": "create:polished_cut_limestone" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_limestone_slab_from_limestone_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_limestone_slab_from_limestone_stonecutting.json deleted file mode 100644 index 55977a942..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_limestone_slab_from_limestone_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "create:limestone" - }, - "result": "create:polished_cut_limestone_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_limestone_stairs_from_limestone_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_limestone_stairs_from_limestone_stonecutting.json deleted file mode 100644 index 8e80b2226..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_limestone_stairs_from_limestone_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:limestone" - }, - "result": "create:polished_cut_limestone_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_limestone_wall_from_limestone_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_limestone_wall_from_limestone_stonecutting.json deleted file mode 100644 index a4cad05ca..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_limestone_wall_from_limestone_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:limestone" - }, - "result": "create:polished_cut_limestone_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_ochrum_from_ochrum_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_ochrum_from_ochrum_stonecutting.json deleted file mode 100644 index 143bea292..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_ochrum_from_ochrum_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:ochrum" - }, - "result": "create:polished_cut_ochrum" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_ochrum_slab_from_ochrum_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_ochrum_slab_from_ochrum_stonecutting.json deleted file mode 100644 index 90c8f363c..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_ochrum_slab_from_ochrum_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "create:ochrum" - }, - "result": "create:polished_cut_ochrum_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_ochrum_stairs_from_ochrum_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_ochrum_stairs_from_ochrum_stonecutting.json deleted file mode 100644 index 1a72a5c4e..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_ochrum_stairs_from_ochrum_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:ochrum" - }, - "result": "create:polished_cut_ochrum_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_ochrum_wall_from_ochrum_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_ochrum_wall_from_ochrum_stonecutting.json deleted file mode 100644 index d3a4a00ba..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_ochrum_wall_from_ochrum_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:ochrum" - }, - "result": "create:polished_cut_ochrum_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_scorchia_from_scorchia_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_scorchia_from_scorchia_stonecutting.json deleted file mode 100644 index 6b1f8572f..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_scorchia_from_scorchia_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:scorchia" - }, - "result": "create:polished_cut_scorchia" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_scorchia_slab_from_scorchia_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_scorchia_slab_from_scorchia_stonecutting.json deleted file mode 100644 index 2d447cfad..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_scorchia_slab_from_scorchia_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "create:scorchia" - }, - "result": "create:polished_cut_scorchia_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_scorchia_stairs_from_scorchia_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_scorchia_stairs_from_scorchia_stonecutting.json deleted file mode 100644 index 1dfb5bf28..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_scorchia_stairs_from_scorchia_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:scorchia" - }, - "result": "create:polished_cut_scorchia_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_scorchia_wall_from_scorchia_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_scorchia_wall_from_scorchia_stonecutting.json deleted file mode 100644 index 6d18419e9..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_scorchia_wall_from_scorchia_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:scorchia" - }, - "result": "create:polished_cut_scorchia_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_scoria_from_scoria_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_scoria_from_scoria_stonecutting.json deleted file mode 100644 index 06eb78cff..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_scoria_from_scoria_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:scoria" - }, - "result": "create:polished_cut_scoria" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_scoria_slab_from_scoria_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_scoria_slab_from_scoria_stonecutting.json deleted file mode 100644 index fa4cadbc1..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_scoria_slab_from_scoria_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "create:scoria" - }, - "result": "create:polished_cut_scoria_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_scoria_stairs_from_scoria_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_scoria_stairs_from_scoria_stonecutting.json deleted file mode 100644 index 22193fa2f..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_scoria_stairs_from_scoria_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:scoria" - }, - "result": "create:polished_cut_scoria_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_scoria_wall_from_scoria_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_scoria_wall_from_scoria_stonecutting.json deleted file mode 100644 index 942f305ad..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_scoria_wall_from_scoria_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:scoria" - }, - "result": "create:polished_cut_scoria_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_tuff_from_tuff_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_tuff_from_tuff_stonecutting.json deleted file mode 100644 index 7a211bead..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_tuff_from_tuff_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:tuff" - }, - "result": "create:polished_cut_tuff" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_tuff_slab_from_tuff_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_tuff_slab_from_tuff_stonecutting.json deleted file mode 100644 index 8b4ed778c..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_tuff_slab_from_tuff_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "minecraft:tuff" - }, - "result": "create:polished_cut_tuff_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_tuff_stairs_from_tuff_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_tuff_stairs_from_tuff_stonecutting.json deleted file mode 100644 index c25eccbf1..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_tuff_stairs_from_tuff_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:tuff" - }, - "result": "create:polished_cut_tuff_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_tuff_wall_from_tuff_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_tuff_wall_from_tuff_stonecutting.json deleted file mode 100644 index eabed71f4..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_tuff_wall_from_tuff_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:tuff" - }, - "result": "create:polished_cut_tuff_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_veridium_from_veridium_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_veridium_from_veridium_stonecutting.json deleted file mode 100644 index 95be05b93..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_veridium_from_veridium_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:veridium" - }, - "result": "create:polished_cut_veridium" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_veridium_slab_from_veridium_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_veridium_slab_from_veridium_stonecutting.json deleted file mode 100644 index bd2f8246d..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_veridium_slab_from_veridium_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "create:veridium" - }, - "result": "create:polished_cut_veridium_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_veridium_stairs_from_veridium_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_veridium_stairs_from_veridium_stonecutting.json deleted file mode 100644 index 20287b0d3..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_veridium_stairs_from_veridium_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:veridium" - }, - "result": "create:polished_cut_veridium_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_cut_veridium_wall_from_veridium_stonecutting.json b/src/generated/resources/data/create/recipes/polished_cut_veridium_wall_from_veridium_stonecutting.json deleted file mode 100644 index aeb15fd62..000000000 --- a/src/generated/resources/data/create/recipes/polished_cut_veridium_wall_from_veridium_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:veridium" - }, - "result": "create:polished_cut_veridium_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/scorchia_from_stone_types_scorchia_stonecutting.json b/src/generated/resources/data/create/recipes/scorchia_from_stone_types_scorchia_stonecutting.json new file mode 100644 index 000000000..a56383349 --- /dev/null +++ b/src/generated/resources/data/create/recipes/scorchia_from_stone_types_scorchia_stonecutting.json @@ -0,0 +1,8 @@ +{ + "type": "minecraft:stonecutting", + "count": 1, + "ingredient": { + "tag": "create:stone_types/scorchia" + }, + "result": "create:scorchia" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/scorchia_pillar_from_scorchia_stonecutting.json b/src/generated/resources/data/create/recipes/scorchia_pillar_from_scorchia_stonecutting.json deleted file mode 100644 index 76e7ef273..000000000 --- a/src/generated/resources/data/create/recipes/scorchia_pillar_from_scorchia_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:scorchia" - }, - "result": "create:scorchia_pillar" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/scoria_from_stone_types_scoria_stonecutting.json b/src/generated/resources/data/create/recipes/scoria_from_stone_types_scoria_stonecutting.json new file mode 100644 index 000000000..fd04c17bd --- /dev/null +++ b/src/generated/resources/data/create/recipes/scoria_from_stone_types_scoria_stonecutting.json @@ -0,0 +1,8 @@ +{ + "type": "minecraft:stonecutting", + "count": 1, + "ingredient": { + "tag": "create:stone_types/scoria" + }, + "result": "create:scoria" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/scoria_pillar_from_scoria_stonecutting.json b/src/generated/resources/data/create/recipes/scoria_pillar_from_scoria_stonecutting.json deleted file mode 100644 index 530a67eba..000000000 --- a/src/generated/resources/data/create/recipes/scoria_pillar_from_scoria_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:scoria" - }, - "result": "create:scoria_pillar" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/sequenced_assembly/precision_mechanism.json b/src/generated/resources/data/create/recipes/sequenced_assembly/precision_mechanism.json index 7a258e05a..c288ad371 100644 --- a/src/generated/resources/data/create/recipes/sequenced_assembly/precision_mechanism.json +++ b/src/generated/resources/data/create/recipes/sequenced_assembly/precision_mechanism.json @@ -31,7 +31,7 @@ }, { "chance": 2.0, - "item": "create:crushed_gold_ore" + "item": "create:crushed_raw_gold" }, { "item": "minecraft:iron_ingot" diff --git a/src/generated/resources/data/create/recipes/small_andesite_brick_slab_from_andesite_stonecutting.json b/src/generated/resources/data/create/recipes/small_andesite_brick_slab_from_andesite_stonecutting.json deleted file mode 100644 index 21e81d58d..000000000 --- a/src/generated/resources/data/create/recipes/small_andesite_brick_slab_from_andesite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "minecraft:andesite" - }, - "result": "create:small_andesite_brick_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_andesite_brick_stairs_from_andesite_stonecutting.json b/src/generated/resources/data/create/recipes/small_andesite_brick_stairs_from_andesite_stonecutting.json deleted file mode 100644 index 94dd05233..000000000 --- a/src/generated/resources/data/create/recipes/small_andesite_brick_stairs_from_andesite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:andesite" - }, - "result": "create:small_andesite_brick_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_andesite_brick_wall_from_andesite_stonecutting.json b/src/generated/resources/data/create/recipes/small_andesite_brick_wall_from_andesite_stonecutting.json deleted file mode 100644 index b5f5ff0f6..000000000 --- a/src/generated/resources/data/create/recipes/small_andesite_brick_wall_from_andesite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:andesite" - }, - "result": "create:small_andesite_brick_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_andesite_bricks_from_andesite_stonecutting.json b/src/generated/resources/data/create/recipes/small_andesite_bricks_from_andesite_stonecutting.json deleted file mode 100644 index 60a144d67..000000000 --- a/src/generated/resources/data/create/recipes/small_andesite_bricks_from_andesite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:andesite" - }, - "result": "create:small_andesite_bricks" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_asurine_brick_slab_from_asurine_stonecutting.json b/src/generated/resources/data/create/recipes/small_asurine_brick_slab_from_asurine_stonecutting.json deleted file mode 100644 index 5d544e773..000000000 --- a/src/generated/resources/data/create/recipes/small_asurine_brick_slab_from_asurine_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "create:asurine" - }, - "result": "create:small_asurine_brick_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_asurine_brick_stairs_from_asurine_stonecutting.json b/src/generated/resources/data/create/recipes/small_asurine_brick_stairs_from_asurine_stonecutting.json deleted file mode 100644 index b62283315..000000000 --- a/src/generated/resources/data/create/recipes/small_asurine_brick_stairs_from_asurine_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:asurine" - }, - "result": "create:small_asurine_brick_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_asurine_brick_wall_from_asurine_stonecutting.json b/src/generated/resources/data/create/recipes/small_asurine_brick_wall_from_asurine_stonecutting.json deleted file mode 100644 index f5cb549fd..000000000 --- a/src/generated/resources/data/create/recipes/small_asurine_brick_wall_from_asurine_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:asurine" - }, - "result": "create:small_asurine_brick_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_asurine_bricks_from_asurine_stonecutting.json b/src/generated/resources/data/create/recipes/small_asurine_bricks_from_asurine_stonecutting.json deleted file mode 100644 index 762f13d48..000000000 --- a/src/generated/resources/data/create/recipes/small_asurine_bricks_from_asurine_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:asurine" - }, - "result": "create:small_asurine_bricks" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_calcite_brick_slab_from_calcite_stonecutting.json b/src/generated/resources/data/create/recipes/small_calcite_brick_slab_from_calcite_stonecutting.json deleted file mode 100644 index 7f3ff870c..000000000 --- a/src/generated/resources/data/create/recipes/small_calcite_brick_slab_from_calcite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "minecraft:calcite" - }, - "result": "create:small_calcite_brick_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_calcite_brick_stairs_from_calcite_stonecutting.json b/src/generated/resources/data/create/recipes/small_calcite_brick_stairs_from_calcite_stonecutting.json deleted file mode 100644 index e8fc940cb..000000000 --- a/src/generated/resources/data/create/recipes/small_calcite_brick_stairs_from_calcite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:calcite" - }, - "result": "create:small_calcite_brick_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_calcite_brick_wall_from_calcite_stonecutting.json b/src/generated/resources/data/create/recipes/small_calcite_brick_wall_from_calcite_stonecutting.json deleted file mode 100644 index a3e0ebeb3..000000000 --- a/src/generated/resources/data/create/recipes/small_calcite_brick_wall_from_calcite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:calcite" - }, - "result": "create:small_calcite_brick_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_calcite_bricks_from_calcite_stonecutting.json b/src/generated/resources/data/create/recipes/small_calcite_bricks_from_calcite_stonecutting.json deleted file mode 100644 index 5fcd0010e..000000000 --- a/src/generated/resources/data/create/recipes/small_calcite_bricks_from_calcite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:calcite" - }, - "result": "create:small_calcite_bricks" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_crimsite_brick_slab_from_crimsite_stonecutting.json b/src/generated/resources/data/create/recipes/small_crimsite_brick_slab_from_crimsite_stonecutting.json deleted file mode 100644 index abfd05525..000000000 --- a/src/generated/resources/data/create/recipes/small_crimsite_brick_slab_from_crimsite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "create:crimsite" - }, - "result": "create:small_crimsite_brick_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_crimsite_brick_stairs_from_crimsite_stonecutting.json b/src/generated/resources/data/create/recipes/small_crimsite_brick_stairs_from_crimsite_stonecutting.json deleted file mode 100644 index 9f79796de..000000000 --- a/src/generated/resources/data/create/recipes/small_crimsite_brick_stairs_from_crimsite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:crimsite" - }, - "result": "create:small_crimsite_brick_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_crimsite_brick_wall_from_crimsite_stonecutting.json b/src/generated/resources/data/create/recipes/small_crimsite_brick_wall_from_crimsite_stonecutting.json deleted file mode 100644 index 3abb33c3f..000000000 --- a/src/generated/resources/data/create/recipes/small_crimsite_brick_wall_from_crimsite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:crimsite" - }, - "result": "create:small_crimsite_brick_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_crimsite_bricks_from_crimsite_stonecutting.json b/src/generated/resources/data/create/recipes/small_crimsite_bricks_from_crimsite_stonecutting.json deleted file mode 100644 index 7cbefe795..000000000 --- a/src/generated/resources/data/create/recipes/small_crimsite_bricks_from_crimsite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:crimsite" - }, - "result": "create:small_crimsite_bricks" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_deepslate_brick_slab_from_deepslate_stonecutting.json b/src/generated/resources/data/create/recipes/small_deepslate_brick_slab_from_deepslate_stonecutting.json deleted file mode 100644 index a8601015e..000000000 --- a/src/generated/resources/data/create/recipes/small_deepslate_brick_slab_from_deepslate_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "minecraft:deepslate" - }, - "result": "create:small_deepslate_brick_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_deepslate_brick_stairs_from_deepslate_stonecutting.json b/src/generated/resources/data/create/recipes/small_deepslate_brick_stairs_from_deepslate_stonecutting.json deleted file mode 100644 index 63d99f297..000000000 --- a/src/generated/resources/data/create/recipes/small_deepslate_brick_stairs_from_deepslate_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:deepslate" - }, - "result": "create:small_deepslate_brick_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_deepslate_brick_wall_from_deepslate_stonecutting.json b/src/generated/resources/data/create/recipes/small_deepslate_brick_wall_from_deepslate_stonecutting.json deleted file mode 100644 index e5ea0570d..000000000 --- a/src/generated/resources/data/create/recipes/small_deepslate_brick_wall_from_deepslate_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:deepslate" - }, - "result": "create:small_deepslate_brick_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_deepslate_bricks_from_deepslate_stonecutting.json b/src/generated/resources/data/create/recipes/small_deepslate_bricks_from_deepslate_stonecutting.json deleted file mode 100644 index 97b264a53..000000000 --- a/src/generated/resources/data/create/recipes/small_deepslate_bricks_from_deepslate_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:deepslate" - }, - "result": "create:small_deepslate_bricks" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_diorite_brick_slab_from_diorite_stonecutting.json b/src/generated/resources/data/create/recipes/small_diorite_brick_slab_from_diorite_stonecutting.json deleted file mode 100644 index b850be40e..000000000 --- a/src/generated/resources/data/create/recipes/small_diorite_brick_slab_from_diorite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "minecraft:diorite" - }, - "result": "create:small_diorite_brick_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_diorite_brick_stairs_from_diorite_stonecutting.json b/src/generated/resources/data/create/recipes/small_diorite_brick_stairs_from_diorite_stonecutting.json deleted file mode 100644 index cf491ccdc..000000000 --- a/src/generated/resources/data/create/recipes/small_diorite_brick_stairs_from_diorite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:diorite" - }, - "result": "create:small_diorite_brick_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_diorite_brick_wall_from_diorite_stonecutting.json b/src/generated/resources/data/create/recipes/small_diorite_brick_wall_from_diorite_stonecutting.json deleted file mode 100644 index 73b7265ef..000000000 --- a/src/generated/resources/data/create/recipes/small_diorite_brick_wall_from_diorite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:diorite" - }, - "result": "create:small_diorite_brick_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_diorite_bricks_from_diorite_stonecutting.json b/src/generated/resources/data/create/recipes/small_diorite_bricks_from_diorite_stonecutting.json deleted file mode 100644 index 739a4b93a..000000000 --- a/src/generated/resources/data/create/recipes/small_diorite_bricks_from_diorite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:diorite" - }, - "result": "create:small_diorite_bricks" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_dripstone_brick_slab_from_dripstone_block_stonecutting.json b/src/generated/resources/data/create/recipes/small_dripstone_brick_slab_from_dripstone_block_stonecutting.json deleted file mode 100644 index c693a9998..000000000 --- a/src/generated/resources/data/create/recipes/small_dripstone_brick_slab_from_dripstone_block_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "minecraft:dripstone_block" - }, - "result": "create:small_dripstone_brick_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_dripstone_brick_stairs_from_dripstone_block_stonecutting.json b/src/generated/resources/data/create/recipes/small_dripstone_brick_stairs_from_dripstone_block_stonecutting.json deleted file mode 100644 index 104db1d1f..000000000 --- a/src/generated/resources/data/create/recipes/small_dripstone_brick_stairs_from_dripstone_block_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:dripstone_block" - }, - "result": "create:small_dripstone_brick_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_dripstone_brick_wall_from_dripstone_block_stonecutting.json b/src/generated/resources/data/create/recipes/small_dripstone_brick_wall_from_dripstone_block_stonecutting.json deleted file mode 100644 index 47fdf4ff7..000000000 --- a/src/generated/resources/data/create/recipes/small_dripstone_brick_wall_from_dripstone_block_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:dripstone_block" - }, - "result": "create:small_dripstone_brick_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_dripstone_bricks_from_dripstone_block_stonecutting.json b/src/generated/resources/data/create/recipes/small_dripstone_bricks_from_dripstone_block_stonecutting.json deleted file mode 100644 index bdd922d20..000000000 --- a/src/generated/resources/data/create/recipes/small_dripstone_bricks_from_dripstone_block_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:dripstone_block" - }, - "result": "create:small_dripstone_bricks" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_granite_brick_slab_from_granite_stonecutting.json b/src/generated/resources/data/create/recipes/small_granite_brick_slab_from_granite_stonecutting.json deleted file mode 100644 index 07328382a..000000000 --- a/src/generated/resources/data/create/recipes/small_granite_brick_slab_from_granite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "minecraft:granite" - }, - "result": "create:small_granite_brick_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_granite_brick_stairs_from_granite_stonecutting.json b/src/generated/resources/data/create/recipes/small_granite_brick_stairs_from_granite_stonecutting.json deleted file mode 100644 index 96c8a8aa8..000000000 --- a/src/generated/resources/data/create/recipes/small_granite_brick_stairs_from_granite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:granite" - }, - "result": "create:small_granite_brick_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_granite_brick_wall_from_granite_stonecutting.json b/src/generated/resources/data/create/recipes/small_granite_brick_wall_from_granite_stonecutting.json deleted file mode 100644 index 75e031717..000000000 --- a/src/generated/resources/data/create/recipes/small_granite_brick_wall_from_granite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:granite" - }, - "result": "create:small_granite_brick_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_granite_bricks_from_granite_stonecutting.json b/src/generated/resources/data/create/recipes/small_granite_bricks_from_granite_stonecutting.json deleted file mode 100644 index 7f30d75e1..000000000 --- a/src/generated/resources/data/create/recipes/small_granite_bricks_from_granite_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:granite" - }, - "result": "create:small_granite_bricks" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_limestone_brick_slab_from_limestone_stonecutting.json b/src/generated/resources/data/create/recipes/small_limestone_brick_slab_from_limestone_stonecutting.json deleted file mode 100644 index e6b19c2c7..000000000 --- a/src/generated/resources/data/create/recipes/small_limestone_brick_slab_from_limestone_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "create:limestone" - }, - "result": "create:small_limestone_brick_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_limestone_brick_stairs_from_limestone_stonecutting.json b/src/generated/resources/data/create/recipes/small_limestone_brick_stairs_from_limestone_stonecutting.json deleted file mode 100644 index 00910367a..000000000 --- a/src/generated/resources/data/create/recipes/small_limestone_brick_stairs_from_limestone_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:limestone" - }, - "result": "create:small_limestone_brick_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_limestone_brick_wall_from_limestone_stonecutting.json b/src/generated/resources/data/create/recipes/small_limestone_brick_wall_from_limestone_stonecutting.json deleted file mode 100644 index 783e9868a..000000000 --- a/src/generated/resources/data/create/recipes/small_limestone_brick_wall_from_limestone_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:limestone" - }, - "result": "create:small_limestone_brick_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_limestone_bricks_from_limestone_stonecutting.json b/src/generated/resources/data/create/recipes/small_limestone_bricks_from_limestone_stonecutting.json deleted file mode 100644 index 200843a5a..000000000 --- a/src/generated/resources/data/create/recipes/small_limestone_bricks_from_limestone_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:limestone" - }, - "result": "create:small_limestone_bricks" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_ochrum_brick_slab_from_ochrum_stonecutting.json b/src/generated/resources/data/create/recipes/small_ochrum_brick_slab_from_ochrum_stonecutting.json deleted file mode 100644 index 5eb55f30f..000000000 --- a/src/generated/resources/data/create/recipes/small_ochrum_brick_slab_from_ochrum_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "create:ochrum" - }, - "result": "create:small_ochrum_brick_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_ochrum_brick_stairs_from_ochrum_stonecutting.json b/src/generated/resources/data/create/recipes/small_ochrum_brick_stairs_from_ochrum_stonecutting.json deleted file mode 100644 index c2d46ab9a..000000000 --- a/src/generated/resources/data/create/recipes/small_ochrum_brick_stairs_from_ochrum_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:ochrum" - }, - "result": "create:small_ochrum_brick_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_ochrum_brick_wall_from_ochrum_stonecutting.json b/src/generated/resources/data/create/recipes/small_ochrum_brick_wall_from_ochrum_stonecutting.json deleted file mode 100644 index cc608e3b1..000000000 --- a/src/generated/resources/data/create/recipes/small_ochrum_brick_wall_from_ochrum_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:ochrum" - }, - "result": "create:small_ochrum_brick_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_ochrum_bricks_from_ochrum_stonecutting.json b/src/generated/resources/data/create/recipes/small_ochrum_bricks_from_ochrum_stonecutting.json deleted file mode 100644 index 4e8ba1aba..000000000 --- a/src/generated/resources/data/create/recipes/small_ochrum_bricks_from_ochrum_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:ochrum" - }, - "result": "create:small_ochrum_bricks" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_scorchia_brick_slab_from_scorchia_stonecutting.json b/src/generated/resources/data/create/recipes/small_scorchia_brick_slab_from_scorchia_stonecutting.json deleted file mode 100644 index d827a29b5..000000000 --- a/src/generated/resources/data/create/recipes/small_scorchia_brick_slab_from_scorchia_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "create:scorchia" - }, - "result": "create:small_scorchia_brick_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_scorchia_brick_stairs_from_scorchia_stonecutting.json b/src/generated/resources/data/create/recipes/small_scorchia_brick_stairs_from_scorchia_stonecutting.json deleted file mode 100644 index 4f1bb841d..000000000 --- a/src/generated/resources/data/create/recipes/small_scorchia_brick_stairs_from_scorchia_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:scorchia" - }, - "result": "create:small_scorchia_brick_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_scorchia_brick_wall_from_scorchia_stonecutting.json b/src/generated/resources/data/create/recipes/small_scorchia_brick_wall_from_scorchia_stonecutting.json deleted file mode 100644 index cc9ffcd95..000000000 --- a/src/generated/resources/data/create/recipes/small_scorchia_brick_wall_from_scorchia_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:scorchia" - }, - "result": "create:small_scorchia_brick_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_scorchia_bricks_from_scorchia_stonecutting.json b/src/generated/resources/data/create/recipes/small_scorchia_bricks_from_scorchia_stonecutting.json deleted file mode 100644 index b0b49ba60..000000000 --- a/src/generated/resources/data/create/recipes/small_scorchia_bricks_from_scorchia_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:scorchia" - }, - "result": "create:small_scorchia_bricks" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_scoria_brick_slab_from_scoria_stonecutting.json b/src/generated/resources/data/create/recipes/small_scoria_brick_slab_from_scoria_stonecutting.json deleted file mode 100644 index a9a6e4a55..000000000 --- a/src/generated/resources/data/create/recipes/small_scoria_brick_slab_from_scoria_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "create:scoria" - }, - "result": "create:small_scoria_brick_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_scoria_brick_stairs_from_scoria_stonecutting.json b/src/generated/resources/data/create/recipes/small_scoria_brick_stairs_from_scoria_stonecutting.json deleted file mode 100644 index b41bfca35..000000000 --- a/src/generated/resources/data/create/recipes/small_scoria_brick_stairs_from_scoria_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:scoria" - }, - "result": "create:small_scoria_brick_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_scoria_brick_wall_from_scoria_stonecutting.json b/src/generated/resources/data/create/recipes/small_scoria_brick_wall_from_scoria_stonecutting.json deleted file mode 100644 index fa2c6f200..000000000 --- a/src/generated/resources/data/create/recipes/small_scoria_brick_wall_from_scoria_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:scoria" - }, - "result": "create:small_scoria_brick_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_scoria_bricks_from_scoria_stonecutting.json b/src/generated/resources/data/create/recipes/small_scoria_bricks_from_scoria_stonecutting.json deleted file mode 100644 index 5441d8041..000000000 --- a/src/generated/resources/data/create/recipes/small_scoria_bricks_from_scoria_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:scoria" - }, - "result": "create:small_scoria_bricks" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_tuff_brick_slab_from_tuff_stonecutting.json b/src/generated/resources/data/create/recipes/small_tuff_brick_slab_from_tuff_stonecutting.json deleted file mode 100644 index 869386a1d..000000000 --- a/src/generated/resources/data/create/recipes/small_tuff_brick_slab_from_tuff_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "minecraft:tuff" - }, - "result": "create:small_tuff_brick_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_tuff_brick_stairs_from_tuff_stonecutting.json b/src/generated/resources/data/create/recipes/small_tuff_brick_stairs_from_tuff_stonecutting.json deleted file mode 100644 index 646363a0d..000000000 --- a/src/generated/resources/data/create/recipes/small_tuff_brick_stairs_from_tuff_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:tuff" - }, - "result": "create:small_tuff_brick_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_tuff_brick_wall_from_tuff_stonecutting.json b/src/generated/resources/data/create/recipes/small_tuff_brick_wall_from_tuff_stonecutting.json deleted file mode 100644 index a80990822..000000000 --- a/src/generated/resources/data/create/recipes/small_tuff_brick_wall_from_tuff_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:tuff" - }, - "result": "create:small_tuff_brick_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_tuff_bricks_from_tuff_stonecutting.json b/src/generated/resources/data/create/recipes/small_tuff_bricks_from_tuff_stonecutting.json deleted file mode 100644 index 5f5ea3e5e..000000000 --- a/src/generated/resources/data/create/recipes/small_tuff_bricks_from_tuff_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:tuff" - }, - "result": "create:small_tuff_bricks" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_veridium_brick_slab_from_veridium_stonecutting.json b/src/generated/resources/data/create/recipes/small_veridium_brick_slab_from_veridium_stonecutting.json deleted file mode 100644 index 3f76f18d5..000000000 --- a/src/generated/resources/data/create/recipes/small_veridium_brick_slab_from_veridium_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 2, - "ingredient": { - "item": "create:veridium" - }, - "result": "create:small_veridium_brick_slab" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_veridium_brick_stairs_from_veridium_stonecutting.json b/src/generated/resources/data/create/recipes/small_veridium_brick_stairs_from_veridium_stonecutting.json deleted file mode 100644 index 4343cfc7a..000000000 --- a/src/generated/resources/data/create/recipes/small_veridium_brick_stairs_from_veridium_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:veridium" - }, - "result": "create:small_veridium_brick_stairs" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_veridium_brick_wall_from_veridium_stonecutting.json b/src/generated/resources/data/create/recipes/small_veridium_brick_wall_from_veridium_stonecutting.json deleted file mode 100644 index 1e87f7ec7..000000000 --- a/src/generated/resources/data/create/recipes/small_veridium_brick_wall_from_veridium_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:veridium" - }, - "result": "create:small_veridium_brick_wall" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/small_veridium_bricks_from_veridium_stonecutting.json b/src/generated/resources/data/create/recipes/small_veridium_bricks_from_veridium_stonecutting.json deleted file mode 100644 index d7cbbbbaf..000000000 --- a/src/generated/resources/data/create/recipes/small_veridium_bricks_from_veridium_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:veridium" - }, - "result": "create:small_veridium_bricks" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/smelting/copper_ingot_from_crushed.json b/src/generated/resources/data/create/recipes/smelting/copper_ingot_from_crushed.json index 279e3ae2f..2f002df86 100644 --- a/src/generated/resources/data/create/recipes/smelting/copper_ingot_from_crushed.json +++ b/src/generated/resources/data/create/recipes/smelting/copper_ingot_from_crushed.json @@ -4,7 +4,7 @@ "cookingtime": 200, "experience": 0.1, "ingredient": { - "item": "create:crushed_copper_ore" + "item": "create:crushed_raw_copper" }, "result": "minecraft:copper_ingot" } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/smelting/gold_ingot_from_crushed.json b/src/generated/resources/data/create/recipes/smelting/gold_ingot_from_crushed.json index 4b7adb262..6088cab52 100644 --- a/src/generated/resources/data/create/recipes/smelting/gold_ingot_from_crushed.json +++ b/src/generated/resources/data/create/recipes/smelting/gold_ingot_from_crushed.json @@ -4,7 +4,7 @@ "cookingtime": 200, "experience": 0.1, "ingredient": { - "item": "create:crushed_gold_ore" + "item": "create:crushed_raw_gold" }, "result": "minecraft:gold_ingot" } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/smelting/ingot_aluminum_compat_immersiveengineering.json b/src/generated/resources/data/create/recipes/smelting/ingot_aluminum_compat_immersiveengineering.json index 65ffb6703..500ad74df 100644 --- a/src/generated/resources/data/create/recipes/smelting/ingot_aluminum_compat_immersiveengineering.json +++ b/src/generated/resources/data/create/recipes/smelting/ingot_aluminum_compat_immersiveengineering.json @@ -10,7 +10,7 @@ "cookingtime": 200, "experience": 0.1, "ingredient": { - "item": "create:crushed_aluminum_ore" + "item": "create:crushed_raw_aluminum" }, "result": "immersiveengineering:ingot_aluminum" } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/smelting/ingot_lead_compat_immersiveengineering.json b/src/generated/resources/data/create/recipes/smelting/ingot_lead_compat_immersiveengineering.json index 34c3449ca..dd4721a32 100644 --- a/src/generated/resources/data/create/recipes/smelting/ingot_lead_compat_immersiveengineering.json +++ b/src/generated/resources/data/create/recipes/smelting/ingot_lead_compat_immersiveengineering.json @@ -10,7 +10,7 @@ "cookingtime": 200, "experience": 0.1, "ingredient": { - "item": "create:crushed_lead_ore" + "item": "create:crushed_raw_lead" }, "result": "immersiveengineering:ingot_lead" } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/smelting/ingot_lead_compat_mekanism.json b/src/generated/resources/data/create/recipes/smelting/ingot_lead_compat_mekanism.json index 2efbeffe3..c9676e08a 100644 --- a/src/generated/resources/data/create/recipes/smelting/ingot_lead_compat_mekanism.json +++ b/src/generated/resources/data/create/recipes/smelting/ingot_lead_compat_mekanism.json @@ -10,7 +10,7 @@ "cookingtime": 200, "experience": 0.1, "ingredient": { - "item": "create:crushed_lead_ore" + "item": "create:crushed_raw_lead" }, "result": "mekanism:ingot_lead" } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/smelting/ingot_nickel_compat_immersiveengineering.json b/src/generated/resources/data/create/recipes/smelting/ingot_nickel_compat_immersiveengineering.json index a3bf1ef3a..007610f4e 100644 --- a/src/generated/resources/data/create/recipes/smelting/ingot_nickel_compat_immersiveengineering.json +++ b/src/generated/resources/data/create/recipes/smelting/ingot_nickel_compat_immersiveengineering.json @@ -10,7 +10,7 @@ "cookingtime": 200, "experience": 0.1, "ingredient": { - "item": "create:crushed_nickel_ore" + "item": "create:crushed_raw_nickel" }, "result": "immersiveengineering:ingot_nickel" } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/smelting/ingot_osmium_compat_mekanism.json b/src/generated/resources/data/create/recipes/smelting/ingot_osmium_compat_mekanism.json index 9fa827394..d1c70fb1f 100644 --- a/src/generated/resources/data/create/recipes/smelting/ingot_osmium_compat_mekanism.json +++ b/src/generated/resources/data/create/recipes/smelting/ingot_osmium_compat_mekanism.json @@ -10,7 +10,7 @@ "cookingtime": 200, "experience": 0.1, "ingredient": { - "item": "create:crushed_osmium_ore" + "item": "create:crushed_raw_osmium" }, "result": "mekanism:ingot_osmium" } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/smelting/ingot_silver_compat_immersiveengineering.json b/src/generated/resources/data/create/recipes/smelting/ingot_silver_compat_immersiveengineering.json index 5d1fe4f6f..4d4d0f31a 100644 --- a/src/generated/resources/data/create/recipes/smelting/ingot_silver_compat_immersiveengineering.json +++ b/src/generated/resources/data/create/recipes/smelting/ingot_silver_compat_immersiveengineering.json @@ -10,7 +10,7 @@ "cookingtime": 200, "experience": 0.1, "ingredient": { - "item": "create:crushed_silver_ore" + "item": "create:crushed_raw_silver" }, "result": "immersiveengineering:ingot_silver" } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/smelting/ingot_tin_compat_mekanism.json b/src/generated/resources/data/create/recipes/smelting/ingot_tin_compat_mekanism.json index 856180bb6..5d218c434 100644 --- a/src/generated/resources/data/create/recipes/smelting/ingot_tin_compat_mekanism.json +++ b/src/generated/resources/data/create/recipes/smelting/ingot_tin_compat_mekanism.json @@ -10,7 +10,7 @@ "cookingtime": 200, "experience": 0.1, "ingredient": { - "item": "create:crushed_tin_ore" + "item": "create:crushed_raw_tin" }, "result": "mekanism:ingot_tin" } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/smelting/ingot_uranium_compat_immersiveengineering.json b/src/generated/resources/data/create/recipes/smelting/ingot_uranium_compat_immersiveengineering.json index 1f675b3ba..f58201736 100644 --- a/src/generated/resources/data/create/recipes/smelting/ingot_uranium_compat_immersiveengineering.json +++ b/src/generated/resources/data/create/recipes/smelting/ingot_uranium_compat_immersiveengineering.json @@ -10,7 +10,7 @@ "cookingtime": 200, "experience": 0.1, "ingredient": { - "item": "create:crushed_uranium_ore" + "item": "create:crushed_raw_uranium" }, "result": "immersiveengineering:ingot_uranium" } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/smelting/ingot_uranium_compat_mekanism.json b/src/generated/resources/data/create/recipes/smelting/ingot_uranium_compat_mekanism.json index 7d598cdae..b18dee6a3 100644 --- a/src/generated/resources/data/create/recipes/smelting/ingot_uranium_compat_mekanism.json +++ b/src/generated/resources/data/create/recipes/smelting/ingot_uranium_compat_mekanism.json @@ -10,7 +10,7 @@ "cookingtime": 200, "experience": 0.1, "ingredient": { - "item": "create:crushed_uranium_ore" + "item": "create:crushed_raw_uranium" }, "result": "mekanism:ingot_uranium" } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/smelting/iron_ingot_from_crushed.json b/src/generated/resources/data/create/recipes/smelting/iron_ingot_from_crushed.json index 15f3dd286..78a8a2c24 100644 --- a/src/generated/resources/data/create/recipes/smelting/iron_ingot_from_crushed.json +++ b/src/generated/resources/data/create/recipes/smelting/iron_ingot_from_crushed.json @@ -4,7 +4,7 @@ "cookingtime": 200, "experience": 0.1, "ingredient": { - "item": "create:crushed_iron_ore" + "item": "create:crushed_raw_iron" }, "result": "minecraft:iron_ingot" } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/smelting/lead_ingot_compat_thermal.json b/src/generated/resources/data/create/recipes/smelting/lead_ingot_compat_thermal.json index fe6819601..317d72290 100644 --- a/src/generated/resources/data/create/recipes/smelting/lead_ingot_compat_thermal.json +++ b/src/generated/resources/data/create/recipes/smelting/lead_ingot_compat_thermal.json @@ -10,7 +10,7 @@ "cookingtime": 200, "experience": 0.1, "ingredient": { - "item": "create:crushed_lead_ore" + "item": "create:crushed_raw_lead" }, "result": "thermal:lead_ingot" } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/smelting/nickel_ingot_compat_thermal.json b/src/generated/resources/data/create/recipes/smelting/nickel_ingot_compat_thermal.json index 3ffb83a43..3ffbfec2c 100644 --- a/src/generated/resources/data/create/recipes/smelting/nickel_ingot_compat_thermal.json +++ b/src/generated/resources/data/create/recipes/smelting/nickel_ingot_compat_thermal.json @@ -10,7 +10,7 @@ "cookingtime": 200, "experience": 0.1, "ingredient": { - "item": "create:crushed_nickel_ore" + "item": "create:crushed_raw_nickel" }, "result": "thermal:nickel_ingot" } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/smelting/silver_ingot_compat_thermal.json b/src/generated/resources/data/create/recipes/smelting/silver_ingot_compat_thermal.json index 13378a242..9d84ed502 100644 --- a/src/generated/resources/data/create/recipes/smelting/silver_ingot_compat_thermal.json +++ b/src/generated/resources/data/create/recipes/smelting/silver_ingot_compat_thermal.json @@ -10,7 +10,7 @@ "cookingtime": 200, "experience": 0.1, "ingredient": { - "item": "create:crushed_silver_ore" + "item": "create:crushed_raw_silver" }, "result": "thermal:silver_ingot" } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/smelting/tin_ingot_compat_thermal.json b/src/generated/resources/data/create/recipes/smelting/tin_ingot_compat_thermal.json index 7fe77d7fd..f56c3f1ec 100644 --- a/src/generated/resources/data/create/recipes/smelting/tin_ingot_compat_thermal.json +++ b/src/generated/resources/data/create/recipes/smelting/tin_ingot_compat_thermal.json @@ -10,7 +10,7 @@ "cookingtime": 200, "experience": 0.1, "ingredient": { - "item": "create:crushed_tin_ore" + "item": "create:crushed_raw_tin" }, "result": "thermal:tin_ingot" } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/smelting/zinc_ingot_from_crushed.json b/src/generated/resources/data/create/recipes/smelting/zinc_ingot_from_crushed.json index 9700cac67..0b254868a 100644 --- a/src/generated/resources/data/create/recipes/smelting/zinc_ingot_from_crushed.json +++ b/src/generated/resources/data/create/recipes/smelting/zinc_ingot_from_crushed.json @@ -4,7 +4,7 @@ "cookingtime": 200, "experience": 0.1, "ingredient": { - "item": "create:crushed_zinc_ore" + "item": "create:crushed_raw_zinc" }, "result": "create:zinc_ingot" } \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/splashing/crushed_copper_ore.json b/src/generated/resources/data/create/recipes/splashing/crushed_copper_ore.json deleted file mode 100644 index 292700422..000000000 --- a/src/generated/resources/data/create/recipes/splashing/crushed_copper_ore.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "type": "create:splashing", - "ingredients": [ - { - "item": "create:crushed_copper_ore" - } - ], - "results": [ - { - "count": 9, - "item": "create:copper_nugget" - }, - { - "chance": 0.5, - "item": "minecraft:clay_ball" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/splashing/crushed_gold_ore.json b/src/generated/resources/data/create/recipes/splashing/crushed_gold_ore.json deleted file mode 100644 index 11cb27911..000000000 --- a/src/generated/resources/data/create/recipes/splashing/crushed_gold_ore.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "type": "create:splashing", - "ingredients": [ - { - "item": "create:crushed_gold_ore" - } - ], - "results": [ - { - "count": 9, - "item": "minecraft:gold_nugget" - }, - { - "chance": 0.5, - "item": "minecraft:quartz" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/splashing/crushed_iron_ore.json b/src/generated/resources/data/create/recipes/splashing/crushed_iron_ore.json deleted file mode 100644 index 4edd73302..000000000 --- a/src/generated/resources/data/create/recipes/splashing/crushed_iron_ore.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "type": "create:splashing", - "ingredients": [ - { - "item": "create:crushed_iron_ore" - } - ], - "results": [ - { - "count": 9, - "item": "minecraft:iron_nugget" - }, - { - "chance": 0.75, - "item": "minecraft:redstone" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/splashing/crushed_raw_copper.json b/src/generated/resources/data/create/recipes/splashing/crushed_raw_copper.json new file mode 100644 index 000000000..aeb0b173d --- /dev/null +++ b/src/generated/resources/data/create/recipes/splashing/crushed_raw_copper.json @@ -0,0 +1,18 @@ +{ + "type": "create:splashing", + "ingredients": [ + { + "item": "create:crushed_raw_copper" + } + ], + "results": [ + { + "count": 9, + "item": "create:copper_nugget" + }, + { + "chance": 0.5, + "item": "minecraft:clay_ball" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/splashing/crushed_raw_gold.json b/src/generated/resources/data/create/recipes/splashing/crushed_raw_gold.json new file mode 100644 index 000000000..05f1f9332 --- /dev/null +++ b/src/generated/resources/data/create/recipes/splashing/crushed_raw_gold.json @@ -0,0 +1,18 @@ +{ + "type": "create:splashing", + "ingredients": [ + { + "item": "create:crushed_raw_gold" + } + ], + "results": [ + { + "count": 9, + "item": "minecraft:gold_nugget" + }, + { + "chance": 0.5, + "item": "minecraft:quartz" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/splashing/crushed_raw_iron.json b/src/generated/resources/data/create/recipes/splashing/crushed_raw_iron.json new file mode 100644 index 000000000..c588186e1 --- /dev/null +++ b/src/generated/resources/data/create/recipes/splashing/crushed_raw_iron.json @@ -0,0 +1,18 @@ +{ + "type": "create:splashing", + "ingredients": [ + { + "item": "create:crushed_raw_iron" + } + ], + "results": [ + { + "count": 9, + "item": "minecraft:iron_nugget" + }, + { + "chance": 0.75, + "item": "minecraft:redstone" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/splashing/crushed_raw_zinc.json b/src/generated/resources/data/create/recipes/splashing/crushed_raw_zinc.json new file mode 100644 index 000000000..9715918fc --- /dev/null +++ b/src/generated/resources/data/create/recipes/splashing/crushed_raw_zinc.json @@ -0,0 +1,18 @@ +{ + "type": "create:splashing", + "ingredients": [ + { + "item": "create:crushed_raw_zinc" + } + ], + "results": [ + { + "count": 9, + "item": "create:zinc_nugget" + }, + { + "chance": 0.25, + "item": "minecraft:gunpowder" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/splashing/crushed_zinc_ore.json b/src/generated/resources/data/create/recipes/splashing/crushed_zinc_ore.json deleted file mode 100644 index 500398ec1..000000000 --- a/src/generated/resources/data/create/recipes/splashing/crushed_zinc_ore.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "type": "create:splashing", - "ingredients": [ - { - "item": "create:crushed_zinc_ore" - } - ], - "results": [ - { - "count": 9, - "item": "create:zinc_nugget" - }, - { - "chance": 0.25, - "item": "minecraft:gunpowder" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/splashing/immersiveengineering/crushed_aluminum_ore.json b/src/generated/resources/data/create/recipes/splashing/immersiveengineering/crushed_aluminum_ore.json deleted file mode 100644 index 0de64e7f2..000000000 --- a/src/generated/resources/data/create/recipes/splashing/immersiveengineering/crushed_aluminum_ore.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:splashing", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "immersiveengineering" - } - ], - "ingredients": [ - { - "item": "create:crushed_aluminum_ore" - } - ], - "results": [ - { - "count": 9, - "item": "immersiveengineering:nugget_aluminum" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/splashing/immersiveengineering/crushed_lead_ore.json b/src/generated/resources/data/create/recipes/splashing/immersiveengineering/crushed_lead_ore.json deleted file mode 100644 index c46081a77..000000000 --- a/src/generated/resources/data/create/recipes/splashing/immersiveengineering/crushed_lead_ore.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:splashing", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "immersiveengineering" - } - ], - "ingredients": [ - { - "item": "create:crushed_lead_ore" - } - ], - "results": [ - { - "count": 9, - "item": "immersiveengineering:nugget_lead" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/splashing/immersiveengineering/crushed_nickel_ore.json b/src/generated/resources/data/create/recipes/splashing/immersiveengineering/crushed_nickel_ore.json deleted file mode 100644 index e6d8eb77f..000000000 --- a/src/generated/resources/data/create/recipes/splashing/immersiveengineering/crushed_nickel_ore.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:splashing", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "immersiveengineering" - } - ], - "ingredients": [ - { - "item": "create:crushed_nickel_ore" - } - ], - "results": [ - { - "count": 9, - "item": "immersiveengineering:nugget_nickel" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/splashing/immersiveengineering/crushed_raw_aluminum.json b/src/generated/resources/data/create/recipes/splashing/immersiveengineering/crushed_raw_aluminum.json new file mode 100644 index 000000000..d9a579ee3 --- /dev/null +++ b/src/generated/resources/data/create/recipes/splashing/immersiveengineering/crushed_raw_aluminum.json @@ -0,0 +1,20 @@ +{ + "type": "create:splashing", + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "immersiveengineering" + } + ], + "ingredients": [ + { + "item": "create:crushed_raw_aluminum" + } + ], + "results": [ + { + "count": 9, + "item": "immersiveengineering:nugget_aluminum" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/splashing/immersiveengineering/crushed_raw_lead.json b/src/generated/resources/data/create/recipes/splashing/immersiveengineering/crushed_raw_lead.json new file mode 100644 index 000000000..4dcccf7ec --- /dev/null +++ b/src/generated/resources/data/create/recipes/splashing/immersiveengineering/crushed_raw_lead.json @@ -0,0 +1,20 @@ +{ + "type": "create:splashing", + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "immersiveengineering" + } + ], + "ingredients": [ + { + "item": "create:crushed_raw_lead" + } + ], + "results": [ + { + "count": 9, + "item": "immersiveengineering:nugget_lead" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/splashing/immersiveengineering/crushed_raw_nickel.json b/src/generated/resources/data/create/recipes/splashing/immersiveengineering/crushed_raw_nickel.json new file mode 100644 index 000000000..c57a8a6b1 --- /dev/null +++ b/src/generated/resources/data/create/recipes/splashing/immersiveengineering/crushed_raw_nickel.json @@ -0,0 +1,20 @@ +{ + "type": "create:splashing", + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "immersiveengineering" + } + ], + "ingredients": [ + { + "item": "create:crushed_raw_nickel" + } + ], + "results": [ + { + "count": 9, + "item": "immersiveengineering:nugget_nickel" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/splashing/immersiveengineering/crushed_raw_silver.json b/src/generated/resources/data/create/recipes/splashing/immersiveengineering/crushed_raw_silver.json new file mode 100644 index 000000000..e8b6e2cf1 --- /dev/null +++ b/src/generated/resources/data/create/recipes/splashing/immersiveengineering/crushed_raw_silver.json @@ -0,0 +1,20 @@ +{ + "type": "create:splashing", + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "immersiveengineering" + } + ], + "ingredients": [ + { + "item": "create:crushed_raw_silver" + } + ], + "results": [ + { + "count": 9, + "item": "immersiveengineering:nugget_silver" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/splashing/immersiveengineering/crushed_raw_uranium.json b/src/generated/resources/data/create/recipes/splashing/immersiveengineering/crushed_raw_uranium.json new file mode 100644 index 000000000..73f714066 --- /dev/null +++ b/src/generated/resources/data/create/recipes/splashing/immersiveengineering/crushed_raw_uranium.json @@ -0,0 +1,20 @@ +{ + "type": "create:splashing", + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "immersiveengineering" + } + ], + "ingredients": [ + { + "item": "create:crushed_raw_uranium" + } + ], + "results": [ + { + "count": 9, + "item": "immersiveengineering:nugget_uranium" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/splashing/immersiveengineering/crushed_silver_ore.json b/src/generated/resources/data/create/recipes/splashing/immersiveengineering/crushed_silver_ore.json deleted file mode 100644 index 23828e45d..000000000 --- a/src/generated/resources/data/create/recipes/splashing/immersiveengineering/crushed_silver_ore.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:splashing", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "immersiveengineering" - } - ], - "ingredients": [ - { - "item": "create:crushed_silver_ore" - } - ], - "results": [ - { - "count": 9, - "item": "immersiveengineering:nugget_silver" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/splashing/immersiveengineering/crushed_uranium_ore.json b/src/generated/resources/data/create/recipes/splashing/immersiveengineering/crushed_uranium_ore.json deleted file mode 100644 index 2e83536fb..000000000 --- a/src/generated/resources/data/create/recipes/splashing/immersiveengineering/crushed_uranium_ore.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:splashing", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "immersiveengineering" - } - ], - "ingredients": [ - { - "item": "create:crushed_uranium_ore" - } - ], - "results": [ - { - "count": 9, - "item": "immersiveengineering:nugget_uranium" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/splashing/mekanism/crushed_lead_ore.json b/src/generated/resources/data/create/recipes/splashing/mekanism/crushed_lead_ore.json deleted file mode 100644 index a5588d8f9..000000000 --- a/src/generated/resources/data/create/recipes/splashing/mekanism/crushed_lead_ore.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:splashing", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "mekanism" - } - ], - "ingredients": [ - { - "item": "create:crushed_lead_ore" - } - ], - "results": [ - { - "count": 9, - "item": "mekanism:nugget_lead" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/splashing/mekanism/crushed_osmium_ore.json b/src/generated/resources/data/create/recipes/splashing/mekanism/crushed_osmium_ore.json deleted file mode 100644 index 87dc5af82..000000000 --- a/src/generated/resources/data/create/recipes/splashing/mekanism/crushed_osmium_ore.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:splashing", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "mekanism" - } - ], - "ingredients": [ - { - "item": "create:crushed_osmium_ore" - } - ], - "results": [ - { - "count": 9, - "item": "mekanism:nugget_osmium" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/splashing/mekanism/crushed_raw_lead.json b/src/generated/resources/data/create/recipes/splashing/mekanism/crushed_raw_lead.json new file mode 100644 index 000000000..c85200a8d --- /dev/null +++ b/src/generated/resources/data/create/recipes/splashing/mekanism/crushed_raw_lead.json @@ -0,0 +1,20 @@ +{ + "type": "create:splashing", + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "mekanism" + } + ], + "ingredients": [ + { + "item": "create:crushed_raw_lead" + } + ], + "results": [ + { + "count": 9, + "item": "mekanism:nugget_lead" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/splashing/mekanism/crushed_raw_osmium.json b/src/generated/resources/data/create/recipes/splashing/mekanism/crushed_raw_osmium.json new file mode 100644 index 000000000..639ef777c --- /dev/null +++ b/src/generated/resources/data/create/recipes/splashing/mekanism/crushed_raw_osmium.json @@ -0,0 +1,20 @@ +{ + "type": "create:splashing", + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "mekanism" + } + ], + "ingredients": [ + { + "item": "create:crushed_raw_osmium" + } + ], + "results": [ + { + "count": 9, + "item": "mekanism:nugget_osmium" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/splashing/mekanism/crushed_raw_tin.json b/src/generated/resources/data/create/recipes/splashing/mekanism/crushed_raw_tin.json new file mode 100644 index 000000000..56afae0a6 --- /dev/null +++ b/src/generated/resources/data/create/recipes/splashing/mekanism/crushed_raw_tin.json @@ -0,0 +1,20 @@ +{ + "type": "create:splashing", + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "mekanism" + } + ], + "ingredients": [ + { + "item": "create:crushed_raw_tin" + } + ], + "results": [ + { + "count": 9, + "item": "mekanism:nugget_tin" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/splashing/mekanism/crushed_raw_uranium.json b/src/generated/resources/data/create/recipes/splashing/mekanism/crushed_raw_uranium.json new file mode 100644 index 000000000..a323e4629 --- /dev/null +++ b/src/generated/resources/data/create/recipes/splashing/mekanism/crushed_raw_uranium.json @@ -0,0 +1,20 @@ +{ + "type": "create:splashing", + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "mekanism" + } + ], + "ingredients": [ + { + "item": "create:crushed_raw_uranium" + } + ], + "results": [ + { + "count": 9, + "item": "mekanism:nugget_uranium" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/splashing/mekanism/crushed_tin_ore.json b/src/generated/resources/data/create/recipes/splashing/mekanism/crushed_tin_ore.json deleted file mode 100644 index 4ae97cde5..000000000 --- a/src/generated/resources/data/create/recipes/splashing/mekanism/crushed_tin_ore.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:splashing", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "mekanism" - } - ], - "ingredients": [ - { - "item": "create:crushed_tin_ore" - } - ], - "results": [ - { - "count": 9, - "item": "mekanism:nugget_tin" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/splashing/mekanism/crushed_uranium_ore.json b/src/generated/resources/data/create/recipes/splashing/mekanism/crushed_uranium_ore.json deleted file mode 100644 index 3659c8c10..000000000 --- a/src/generated/resources/data/create/recipes/splashing/mekanism/crushed_uranium_ore.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:splashing", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "mekanism" - } - ], - "ingredients": [ - { - "item": "create:crushed_uranium_ore" - } - ], - "results": [ - { - "count": 9, - "item": "mekanism:nugget_uranium" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/splashing/thermal/crushed_lead_ore.json b/src/generated/resources/data/create/recipes/splashing/thermal/crushed_lead_ore.json deleted file mode 100644 index b08880adf..000000000 --- a/src/generated/resources/data/create/recipes/splashing/thermal/crushed_lead_ore.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:splashing", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "thermal" - } - ], - "ingredients": [ - { - "item": "create:crushed_lead_ore" - } - ], - "results": [ - { - "count": 9, - "item": "thermal:lead_nugget" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/splashing/thermal/crushed_nickel_ore.json b/src/generated/resources/data/create/recipes/splashing/thermal/crushed_nickel_ore.json deleted file mode 100644 index 739bac5e3..000000000 --- a/src/generated/resources/data/create/recipes/splashing/thermal/crushed_nickel_ore.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:splashing", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "thermal" - } - ], - "ingredients": [ - { - "item": "create:crushed_nickel_ore" - } - ], - "results": [ - { - "count": 9, - "item": "thermal:nickel_nugget" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/splashing/thermal/crushed_raw_lead.json b/src/generated/resources/data/create/recipes/splashing/thermal/crushed_raw_lead.json new file mode 100644 index 000000000..188e94c8b --- /dev/null +++ b/src/generated/resources/data/create/recipes/splashing/thermal/crushed_raw_lead.json @@ -0,0 +1,20 @@ +{ + "type": "create:splashing", + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "thermal" + } + ], + "ingredients": [ + { + "item": "create:crushed_raw_lead" + } + ], + "results": [ + { + "count": 9, + "item": "thermal:lead_nugget" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/splashing/thermal/crushed_raw_nickel.json b/src/generated/resources/data/create/recipes/splashing/thermal/crushed_raw_nickel.json new file mode 100644 index 000000000..856c4a8a2 --- /dev/null +++ b/src/generated/resources/data/create/recipes/splashing/thermal/crushed_raw_nickel.json @@ -0,0 +1,20 @@ +{ + "type": "create:splashing", + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "thermal" + } + ], + "ingredients": [ + { + "item": "create:crushed_raw_nickel" + } + ], + "results": [ + { + "count": 9, + "item": "thermal:nickel_nugget" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/splashing/thermal/crushed_raw_silver.json b/src/generated/resources/data/create/recipes/splashing/thermal/crushed_raw_silver.json new file mode 100644 index 000000000..3c429a31e --- /dev/null +++ b/src/generated/resources/data/create/recipes/splashing/thermal/crushed_raw_silver.json @@ -0,0 +1,20 @@ +{ + "type": "create:splashing", + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "thermal" + } + ], + "ingredients": [ + { + "item": "create:crushed_raw_silver" + } + ], + "results": [ + { + "count": 9, + "item": "thermal:silver_nugget" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/splashing/thermal/crushed_raw_tin.json b/src/generated/resources/data/create/recipes/splashing/thermal/crushed_raw_tin.json new file mode 100644 index 000000000..363b3efd0 --- /dev/null +++ b/src/generated/resources/data/create/recipes/splashing/thermal/crushed_raw_tin.json @@ -0,0 +1,20 @@ +{ + "type": "create:splashing", + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "thermal" + } + ], + "ingredients": [ + { + "item": "create:crushed_raw_tin" + } + ], + "results": [ + { + "count": 9, + "item": "thermal:tin_nugget" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/splashing/thermal/crushed_silver_ore.json b/src/generated/resources/data/create/recipes/splashing/thermal/crushed_silver_ore.json deleted file mode 100644 index daacf4f6f..000000000 --- a/src/generated/resources/data/create/recipes/splashing/thermal/crushed_silver_ore.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:splashing", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "thermal" - } - ], - "ingredients": [ - { - "item": "create:crushed_silver_ore" - } - ], - "results": [ - { - "count": 9, - "item": "thermal:silver_nugget" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/splashing/thermal/crushed_tin_ore.json b/src/generated/resources/data/create/recipes/splashing/thermal/crushed_tin_ore.json deleted file mode 100644 index 14dcec5c8..000000000 --- a/src/generated/resources/data/create/recipes/splashing/thermal/crushed_tin_ore.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "type": "create:splashing", - "conditions": [ - { - "type": "forge:mod_loaded", - "modid": "thermal" - } - ], - "ingredients": [ - { - "item": "create:crushed_tin_ore" - } - ], - "results": [ - { - "count": 9, - "item": "thermal:tin_nugget" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/tuff_from_stone_types_tuff_stonecutting.json b/src/generated/resources/data/create/recipes/tuff_from_stone_types_tuff_stonecutting.json new file mode 100644 index 000000000..4288fb7ea --- /dev/null +++ b/src/generated/resources/data/create/recipes/tuff_from_stone_types_tuff_stonecutting.json @@ -0,0 +1,8 @@ +{ + "type": "minecraft:stonecutting", + "count": 1, + "ingredient": { + "tag": "create:stone_types/tuff" + }, + "result": "minecraft:tuff" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/tuff_pillar_from_tuff_stonecutting.json b/src/generated/resources/data/create/recipes/tuff_pillar_from_tuff_stonecutting.json deleted file mode 100644 index 8bdaba744..000000000 --- a/src/generated/resources/data/create/recipes/tuff_pillar_from_tuff_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "minecraft:tuff" - }, - "result": "create:tuff_pillar" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/veridium_from_stone_types_veridium_stonecutting.json b/src/generated/resources/data/create/recipes/veridium_from_stone_types_veridium_stonecutting.json new file mode 100644 index 000000000..aebd8457e --- /dev/null +++ b/src/generated/resources/data/create/recipes/veridium_from_stone_types_veridium_stonecutting.json @@ -0,0 +1,8 @@ +{ + "type": "minecraft:stonecutting", + "count": 1, + "ingredient": { + "tag": "create:stone_types/veridium" + }, + "result": "create:veridium" +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/veridium_pillar_from_veridium_stonecutting.json b/src/generated/resources/data/create/recipes/veridium_pillar_from_veridium_stonecutting.json deleted file mode 100644 index 2d50d0a6d..000000000 --- a/src/generated/resources/data/create/recipes/veridium_pillar_from_veridium_stonecutting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "minecraft:stonecutting", - "count": 1, - "ingredient": { - "item": "create:veridium" - }, - "result": "create:veridium_pillar" -} \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/blocks/contraption_inventory_deny.json b/src/generated/resources/data/create/tags/blocks/contraption_inventory_deny.json new file mode 100644 index 000000000..f72d209df --- /dev/null +++ b/src/generated/resources/data/create/tags/blocks/contraption_inventory_deny.json @@ -0,0 +1,3 @@ +{ + "values": [] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/blocks/copycat_allow.json b/src/generated/resources/data/create/tags/blocks/copycat_allow.json new file mode 100644 index 000000000..b07daae1c --- /dev/null +++ b/src/generated/resources/data/create/tags/blocks/copycat_allow.json @@ -0,0 +1,5 @@ +{ + "values": [ + "minecraft:barrel" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/blocks/copycat_deny.json b/src/generated/resources/data/create/tags/blocks/copycat_deny.json new file mode 100644 index 000000000..2f852ffe6 --- /dev/null +++ b/src/generated/resources/data/create/tags/blocks/copycat_deny.json @@ -0,0 +1,7 @@ +{ + "values": [ + "#minecraft:cauldrons", + "#minecraft:saplings", + "#minecraft:climbable" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/blocks/fan_transparent.json b/src/generated/resources/data/create/tags/blocks/fan_transparent.json index cae6b1811..6dcdc1df9 100644 --- a/src/generated/resources/data/create/tags/blocks/fan_transparent.json +++ b/src/generated/resources/data/create/tags/blocks/fan_transparent.json @@ -3,6 +3,10 @@ "create:blaze_burner", "create:lit_blaze_burner", "create:sail_frame", + "create:andesite_bars", + "create:brass_bars", + "create:copper_bars", + "create:copycat_base", "minecraft:iron_bars", "minecraft:mangrove_roots", "#minecraft:campfires", diff --git a/src/generated/resources/data/create/tags/blocks/girdable_tracks.json b/src/generated/resources/data/create/tags/blocks/girdable_tracks.json new file mode 100644 index 000000000..259661af4 --- /dev/null +++ b/src/generated/resources/data/create/tags/blocks/girdable_tracks.json @@ -0,0 +1,5 @@ +{ + "values": [ + "create:track" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/blocks/movable_empty_collider.json b/src/generated/resources/data/create/tags/blocks/movable_empty_collider.json index 996f70065..2ebcea708 100644 --- a/src/generated/resources/data/create/tags/blocks/movable_empty_collider.json +++ b/src/generated/resources/data/create/tags/blocks/movable_empty_collider.json @@ -2,6 +2,8 @@ "values": [ "minecraft:cobweb", "minecraft:powder_snow", + "minecraft:tripwire", + "minecraft:tripwire_hook", "#minecraft:fence_gates" ] } \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/blocks/safe_nbt.json b/src/generated/resources/data/create/tags/blocks/safe_nbt.json index cc8a8a80d..3db7d7024 100644 --- a/src/generated/resources/data/create/tags/blocks/safe_nbt.json +++ b/src/generated/resources/data/create/tags/blocks/safe_nbt.json @@ -18,12 +18,11 @@ "create:andesite_belt_funnel", "create:brass_funnel", "create:brass_belt_funnel", - "create:creative_crate", "create:redstone_link", "create:analog_lever", - "create:placard", "create:pulse_repeater", "create:pulse_extender", + "create:clipboard", "#minecraft:banners", "#minecraft:signs" ] diff --git a/src/generated/resources/data/create/tags/blocks/tracks.json b/src/generated/resources/data/create/tags/blocks/tracks.json new file mode 100644 index 000000000..259661af4 --- /dev/null +++ b/src/generated/resources/data/create/tags/blocks/tracks.json @@ -0,0 +1,5 @@ +{ + "values": [ + "create:track" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/blocks/wrench_pickup.json b/src/generated/resources/data/create/tags/blocks/wrench_pickup.json index ca8f1e5ac..603735926 100644 --- a/src/generated/resources/data/create/tags/blocks/wrench_pickup.json +++ b/src/generated/resources/data/create/tags/blocks/wrench_pickup.json @@ -1,5 +1,9 @@ { "values": [ + "create:andesite_bars", + "create:brass_bars", + "create:copper_bars", + "create:industrial_iron_block", "minecraft:redstone_wire", "minecraft:redstone_torch", "minecraft:repeater", diff --git a/src/generated/resources/data/create/tags/items/contraption_controlled.json b/src/generated/resources/data/create/tags/items/contraption_controlled.json new file mode 100644 index 000000000..038d6b608 --- /dev/null +++ b/src/generated/resources/data/create/tags/items/contraption_controlled.json @@ -0,0 +1,27 @@ +{ + "values": [ + "create:portable_fluid_interface", + "create:mechanical_drill", + "create:mechanical_saw", + "create:deployer", + "create:portable_storage_interface", + "create:redstone_contact", + "create:mechanical_harvester", + "create:mechanical_plough", + "create:mechanical_roller", + "create:andesite_funnel", + "create:brass_funnel", + "create:peculiar_bell", + "create:haunted_bell", + "create:andesite_door", + "create:brass_door", + "create:copper_door", + "create:train_door", + "create:framed_glass_door", + "minecraft:bell", + "minecraft:campfire", + "minecraft:soul_campfire", + "minecraft:dispenser", + "minecraft:dropper" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/items/crushed_ores.json b/src/generated/resources/data/create/tags/items/crushed_ores.json deleted file mode 100644 index b3bb6f727..000000000 --- a/src/generated/resources/data/create/tags/items/crushed_ores.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "values": [ - "create:crushed_iron_ore", - "create:crushed_gold_ore", - "create:crushed_copper_ore", - "create:crushed_zinc_ore", - "create:crushed_osmium_ore", - "create:crushed_platinum_ore", - "create:crushed_silver_ore", - "create:crushed_tin_ore", - "create:crushed_lead_ore", - "create:crushed_quicksilver_ore", - "create:crushed_aluminum_ore", - "create:crushed_uranium_ore", - "create:crushed_nickel_ore" - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/items/crushed_raw_materials.json b/src/generated/resources/data/create/tags/items/crushed_raw_materials.json new file mode 100644 index 000000000..405bf381e --- /dev/null +++ b/src/generated/resources/data/create/tags/items/crushed_raw_materials.json @@ -0,0 +1,17 @@ +{ + "values": [ + "create:crushed_raw_iron", + "create:crushed_raw_gold", + "create:crushed_raw_copper", + "create:crushed_raw_zinc", + "create:crushed_raw_osmium", + "create:crushed_raw_platinum", + "create:crushed_raw_silver", + "create:crushed_raw_tin", + "create:crushed_raw_lead", + "create:crushed_raw_quicksilver", + "create:crushed_raw_aluminum", + "create:crushed_raw_uranium", + "create:crushed_raw_nickel" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/items/pressurized_air_sources.json b/src/generated/resources/data/create/tags/items/pressurized_air_sources.json index 56c3cf6c8..f930557b8 100644 --- a/src/generated/resources/data/create/tags/items/pressurized_air_sources.json +++ b/src/generated/resources/data/create/tags/items/pressurized_air_sources.json @@ -1,5 +1,6 @@ { "values": [ - "create:copper_backtank" + "create:copper_backtank", + "create:netherite_backtank" ] } \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/items/stone_types/andesite.json b/src/generated/resources/data/create/tags/items/stone_types/andesite.json index 01ddbc163..d651d4174 100644 --- a/src/generated/resources/data/create/tags/items/stone_types/andesite.json +++ b/src/generated/resources/data/create/tags/items/stone_types/andesite.json @@ -13,6 +13,7 @@ "create:small_andesite_brick_stairs", "create:small_andesite_brick_wall", "create:layered_andesite", - "create:andesite_pillar" + "create:andesite_pillar", + "minecraft:andesite" ] } \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/items/stone_types/asurine.json b/src/generated/resources/data/create/tags/items/stone_types/asurine.json index 6c74f1dd7..744ab9292 100644 --- a/src/generated/resources/data/create/tags/items/stone_types/asurine.json +++ b/src/generated/resources/data/create/tags/items/stone_types/asurine.json @@ -13,6 +13,7 @@ "create:small_asurine_brick_stairs", "create:small_asurine_brick_wall", "create:layered_asurine", - "create:asurine_pillar" + "create:asurine_pillar", + "create:asurine" ] } \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/items/stone_types/calcite.json b/src/generated/resources/data/create/tags/items/stone_types/calcite.json index c51cd6103..d1f9d8499 100644 --- a/src/generated/resources/data/create/tags/items/stone_types/calcite.json +++ b/src/generated/resources/data/create/tags/items/stone_types/calcite.json @@ -13,6 +13,7 @@ "create:small_calcite_brick_stairs", "create:small_calcite_brick_wall", "create:layered_calcite", - "create:calcite_pillar" + "create:calcite_pillar", + "minecraft:calcite" ] } \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/items/stone_types/crimsite.json b/src/generated/resources/data/create/tags/items/stone_types/crimsite.json index c7fd52879..736e79590 100644 --- a/src/generated/resources/data/create/tags/items/stone_types/crimsite.json +++ b/src/generated/resources/data/create/tags/items/stone_types/crimsite.json @@ -13,6 +13,7 @@ "create:small_crimsite_brick_stairs", "create:small_crimsite_brick_wall", "create:layered_crimsite", - "create:crimsite_pillar" + "create:crimsite_pillar", + "create:crimsite" ] } \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/items/stone_types/deepslate.json b/src/generated/resources/data/create/tags/items/stone_types/deepslate.json index d3f7ecdf6..5ceef9ec4 100644 --- a/src/generated/resources/data/create/tags/items/stone_types/deepslate.json +++ b/src/generated/resources/data/create/tags/items/stone_types/deepslate.json @@ -13,6 +13,7 @@ "create:small_deepslate_brick_stairs", "create:small_deepslate_brick_wall", "create:layered_deepslate", - "create:deepslate_pillar" + "create:deepslate_pillar", + "minecraft:deepslate" ] } \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/items/stone_types/diorite.json b/src/generated/resources/data/create/tags/items/stone_types/diorite.json index 7fc0e4a86..4562a5837 100644 --- a/src/generated/resources/data/create/tags/items/stone_types/diorite.json +++ b/src/generated/resources/data/create/tags/items/stone_types/diorite.json @@ -13,6 +13,7 @@ "create:small_diorite_brick_stairs", "create:small_diorite_brick_wall", "create:layered_diorite", - "create:diorite_pillar" + "create:diorite_pillar", + "minecraft:diorite" ] } \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/items/stone_types/dripstone.json b/src/generated/resources/data/create/tags/items/stone_types/dripstone.json index bcdd5850c..64d445fee 100644 --- a/src/generated/resources/data/create/tags/items/stone_types/dripstone.json +++ b/src/generated/resources/data/create/tags/items/stone_types/dripstone.json @@ -13,6 +13,7 @@ "create:small_dripstone_brick_stairs", "create:small_dripstone_brick_wall", "create:layered_dripstone", - "create:dripstone_pillar" + "create:dripstone_pillar", + "minecraft:dripstone_block" ] } \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/items/stone_types/granite.json b/src/generated/resources/data/create/tags/items/stone_types/granite.json index a216687e9..cf2be0bdd 100644 --- a/src/generated/resources/data/create/tags/items/stone_types/granite.json +++ b/src/generated/resources/data/create/tags/items/stone_types/granite.json @@ -13,6 +13,7 @@ "create:small_granite_brick_stairs", "create:small_granite_brick_wall", "create:layered_granite", - "create:granite_pillar" + "create:granite_pillar", + "minecraft:granite" ] } \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/items/stone_types/limestone.json b/src/generated/resources/data/create/tags/items/stone_types/limestone.json index 3de74d034..921c8556d 100644 --- a/src/generated/resources/data/create/tags/items/stone_types/limestone.json +++ b/src/generated/resources/data/create/tags/items/stone_types/limestone.json @@ -13,6 +13,7 @@ "create:small_limestone_brick_stairs", "create:small_limestone_brick_wall", "create:layered_limestone", - "create:limestone_pillar" + "create:limestone_pillar", + "create:limestone" ] } \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/items/stone_types/ochrum.json b/src/generated/resources/data/create/tags/items/stone_types/ochrum.json index 2cd31771f..aa6bdd235 100644 --- a/src/generated/resources/data/create/tags/items/stone_types/ochrum.json +++ b/src/generated/resources/data/create/tags/items/stone_types/ochrum.json @@ -13,6 +13,7 @@ "create:small_ochrum_brick_stairs", "create:small_ochrum_brick_wall", "create:layered_ochrum", - "create:ochrum_pillar" + "create:ochrum_pillar", + "create:ochrum" ] } \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/items/stone_types/scorchia.json b/src/generated/resources/data/create/tags/items/stone_types/scorchia.json index 2f1f85a4a..6d4689156 100644 --- a/src/generated/resources/data/create/tags/items/stone_types/scorchia.json +++ b/src/generated/resources/data/create/tags/items/stone_types/scorchia.json @@ -13,6 +13,7 @@ "create:small_scorchia_brick_stairs", "create:small_scorchia_brick_wall", "create:layered_scorchia", - "create:scorchia_pillar" + "create:scorchia_pillar", + "create:scorchia" ] } \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/items/stone_types/scoria.json b/src/generated/resources/data/create/tags/items/stone_types/scoria.json index 751ffb6e6..33bf7aedb 100644 --- a/src/generated/resources/data/create/tags/items/stone_types/scoria.json +++ b/src/generated/resources/data/create/tags/items/stone_types/scoria.json @@ -13,6 +13,7 @@ "create:small_scoria_brick_stairs", "create:small_scoria_brick_wall", "create:layered_scoria", - "create:scoria_pillar" + "create:scoria_pillar", + "create:scoria" ] } \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/items/stone_types/tuff.json b/src/generated/resources/data/create/tags/items/stone_types/tuff.json index 2ec0e2537..5e5ef2ee7 100644 --- a/src/generated/resources/data/create/tags/items/stone_types/tuff.json +++ b/src/generated/resources/data/create/tags/items/stone_types/tuff.json @@ -13,6 +13,7 @@ "create:small_tuff_brick_stairs", "create:small_tuff_brick_wall", "create:layered_tuff", - "create:tuff_pillar" + "create:tuff_pillar", + "minecraft:tuff" ] } \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/items/stone_types/veridium.json b/src/generated/resources/data/create/tags/items/stone_types/veridium.json index 756c945ae..ddb0ddc29 100644 --- a/src/generated/resources/data/create/tags/items/stone_types/veridium.json +++ b/src/generated/resources/data/create/tags/items/stone_types/veridium.json @@ -13,6 +13,7 @@ "create:small_veridium_brick_stairs", "create:small_veridium_brick_wall", "create:layered_veridium", - "create:veridium_pillar" + "create:veridium_pillar", + "create:veridium" ] } \ No newline at end of file diff --git a/src/generated/resources/data/create/worldgen/configured_feature/striated_ores_nether.json b/src/generated/resources/data/create/worldgen/configured_feature/striated_ores_nether.json index 7e0bca285..6b66f0198 100644 --- a/src/generated/resources/data/create/worldgen/configured_feature/striated_ores_nether.json +++ b/src/generated/resources/data/create/worldgen/configured_feature/striated_ores_nether.json @@ -35,8 +35,8 @@ "weight": 1 }, { - "max_size": 4, - "min_size": 1, + "max_size": 5, + "min_size": 2, "targets": [ [ { @@ -53,7 +53,7 @@ "weight": 2 }, { - "max_size": 3, + "max_size": 2, "min_size": 1, "targets": [ [ @@ -71,8 +71,8 @@ "weight": 1 }, { - "max_size": 1, - "min_size": 1, + "max_size": 3, + "min_size": 2, "targets": [ [ { @@ -132,11 +132,11 @@ } ] ], - "weight": 2 + "weight": 4 }, { - "max_size": 4, - "min_size": 1, + "max_size": 5, + "min_size": 2, "targets": [ [ { @@ -150,7 +150,7 @@ } ] ], - "weight": 4 + "weight": 8 }, { "max_size": 3, @@ -179,7 +179,7 @@ } ] ], - "weight": 2 + "weight": 4 }, { "max_size": 1, @@ -200,8 +200,8 @@ "weight": 1 }, { - "max_size": 1, - "min_size": 1, + "max_size": 3, + "min_size": 2, "targets": [ [ { @@ -229,7 +229,7 @@ } ] ], - "weight": 2 + "weight": 4 } ] ], diff --git a/src/generated/resources/data/create/worldgen/configured_feature/striated_ores_overworld.json b/src/generated/resources/data/create/worldgen/configured_feature/striated_ores_overworld.json index 9f1c111b3..ec99a2828 100644 --- a/src/generated/resources/data/create/worldgen/configured_feature/striated_ores_overworld.json +++ b/src/generated/resources/data/create/worldgen/configured_feature/striated_ores_overworld.json @@ -5,38 +5,8 @@ "layer_patterns": [ [ { - "max_size": 1, - "min_size": 1, - "targets": [ - [ - { - "state": { - "Name": "minecraft:stone" - }, - "target": { - "predicate_type": "minecraft:tag_match", - "tag": "minecraft:stone_ore_replaceables" - } - }, - { - "state": { - "Name": "minecraft:deepslate", - "Properties": { - "axis": "y" - } - }, - "target": { - "predicate_type": "minecraft:tag_match", - "tag": "minecraft:deepslate_ore_replaceables" - } - } - ] - ], - "weight": 1 - }, - { - "max_size": 3, - "min_size": 1, + "max_size": 5, + "min_size": 2, "targets": [ [ { @@ -62,8 +32,8 @@ "weight": 2 }, { - "max_size": 2, - "min_size": 1, + "max_size": 3, + "min_size": 2, "targets": [ [ { @@ -109,8 +79,8 @@ "weight": 2 }, { - "max_size": 1, - "min_size": 1, + "max_size": 2, + "min_size": 2, "targets": [ [ { @@ -136,7 +106,7 @@ "weight": 1 }, { - "max_size": 1, + "max_size": 2, "min_size": 1, "targets": [ [ @@ -165,38 +135,8 @@ ], [ { - "max_size": 1, - "min_size": 1, - "targets": [ - [ - { - "state": { - "Name": "minecraft:stone" - }, - "target": { - "predicate_type": "minecraft:tag_match", - "tag": "minecraft:stone_ore_replaceables" - } - }, - { - "state": { - "Name": "minecraft:deepslate", - "Properties": { - "axis": "y" - } - }, - "target": { - "predicate_type": "minecraft:tag_match", - "tag": "minecraft:deepslate_ore_replaceables" - } - } - ] - ], - "weight": 1 - }, - { - "max_size": 3, - "min_size": 1, + "max_size": 5, + "min_size": 2, "targets": [ [ { @@ -222,7 +162,7 @@ "weight": 2 }, { - "max_size": 2, + "max_size": 3, "min_size": 2, "targets": [ [ @@ -275,8 +215,8 @@ "weight": 1 }, { - "max_size": 1, - "min_size": 1, + "max_size": 2, + "min_size": 2, "targets": [ [ { @@ -305,7 +245,7 @@ "weight": 1 }, { - "max_size": 1, + "max_size": 2, "min_size": 1, "targets": [ [ @@ -334,38 +274,8 @@ ], [ { - "max_size": 1, - "min_size": 1, - "targets": [ - [ - { - "state": { - "Name": "minecraft:stone" - }, - "target": { - "predicate_type": "minecraft:tag_match", - "tag": "minecraft:stone_ore_replaceables" - } - }, - { - "state": { - "Name": "minecraft:deepslate", - "Properties": { - "axis": "y" - } - }, - "target": { - "predicate_type": "minecraft:tag_match", - "tag": "minecraft:deepslate_ore_replaceables" - } - } - ] - ], - "weight": 1 - }, - { - "max_size": 3, - "min_size": 1, + "max_size": 5, + "min_size": 2, "targets": [ [ { @@ -391,8 +301,8 @@ "weight": 2 }, { - "max_size": 2, - "min_size": 1, + "max_size": 3, + "min_size": 2, "targets": [ [ { @@ -444,8 +354,8 @@ "weight": 1 }, { - "max_size": 1, - "min_size": 1, + "max_size": 2, + "min_size": 2, "targets": [ [ { @@ -474,7 +384,7 @@ "weight": 1 }, { - "max_size": 1, + "max_size": 2, "min_size": 1, "targets": [ [ @@ -503,38 +413,8 @@ ], [ { - "max_size": 1, - "min_size": 1, - "targets": [ - [ - { - "state": { - "Name": "minecraft:stone" - }, - "target": { - "predicate_type": "minecraft:tag_match", - "tag": "minecraft:stone_ore_replaceables" - } - }, - { - "state": { - "Name": "minecraft:deepslate", - "Properties": { - "axis": "y" - } - }, - "target": { - "predicate_type": "minecraft:tag_match", - "tag": "minecraft:deepslate_ore_replaceables" - } - } - ] - ], - "weight": 2 - }, - { - "max_size": 3, - "min_size": 1, + "max_size": 5, + "min_size": 2, "targets": [ [ { @@ -560,8 +440,8 @@ "weight": 4 }, { - "max_size": 2, - "min_size": 1, + "max_size": 3, + "min_size": 2, "targets": [ [ { @@ -607,8 +487,8 @@ "weight": 2 }, { - "max_size": 1, - "min_size": 1, + "max_size": 2, + "min_size": 2, "targets": [ [ { @@ -634,7 +514,7 @@ "weight": 2 }, { - "max_size": 1, + "max_size": 2, "min_size": 1, "targets": [ [ @@ -748,7 +628,7 @@ }, { "max_size": 4, - "min_size": 1, + "min_size": 2, "targets": [ [ { @@ -776,38 +656,8 @@ ], [ { - "max_size": 1, - "min_size": 1, - "targets": [ - [ - { - "state": { - "Name": "minecraft:stone" - }, - "target": { - "predicate_type": "minecraft:tag_match", - "tag": "minecraft:stone_ore_replaceables" - } - }, - { - "state": { - "Name": "minecraft:deepslate", - "Properties": { - "axis": "y" - } - }, - "target": { - "predicate_type": "minecraft:tag_match", - "tag": "minecraft:deepslate_ore_replaceables" - } - } - ] - ], - "weight": 1 - }, - { - "max_size": 3, - "min_size": 1, + "max_size": 5, + "min_size": 2, "targets": [ [ { @@ -833,8 +683,8 @@ "weight": 2 }, { - "max_size": 2, - "min_size": 1, + "max_size": 3, + "min_size": 2, "targets": [ [ { diff --git a/src/generated/resources/data/create/worldgen/placed_feature/striated_ores_nether.json b/src/generated/resources/data/create/worldgen/placed_feature/striated_ores_nether.json index 0cf84f8ef..5a99334f4 100644 --- a/src/generated/resources/data/create/worldgen/placed_feature/striated_ores_nether.json +++ b/src/generated/resources/data/create/worldgen/placed_feature/striated_ores_nether.json @@ -3,7 +3,7 @@ "placement": [ { "type": "minecraft:rarity_filter", - "chance": 12 + "chance": 18 }, { "type": "minecraft:in_square" diff --git a/src/generated/resources/data/create/worldgen/placed_feature/striated_ores_overworld.json b/src/generated/resources/data/create/worldgen/placed_feature/striated_ores_overworld.json index a75637fd5..0fcaa996a 100644 --- a/src/generated/resources/data/create/worldgen/placed_feature/striated_ores_overworld.json +++ b/src/generated/resources/data/create/worldgen/placed_feature/striated_ores_overworld.json @@ -3,7 +3,7 @@ "placement": [ { "type": "minecraft:rarity_filter", - "chance": 12 + "chance": 18 }, { "type": "minecraft:in_square" diff --git a/src/generated/resources/data/forge/tags/blocks/glass_panes.json b/src/generated/resources/data/forge/tags/blocks/glass_panes.json index 1e77aae5c..ec99a30f5 100644 --- a/src/generated/resources/data/forge/tags/blocks/glass_panes.json +++ b/src/generated/resources/data/forge/tags/blocks/glass_panes.json @@ -10,6 +10,7 @@ "create:jungle_window_pane", "create:acacia_window_pane", "create:dark_oak_window_pane", + "create:mangrove_window_pane", "create:crimson_window_pane", "create:warped_window_pane", "create:ornate_iron_window_pane" diff --git a/src/generated/resources/data/forge/tags/blocks/storage_blocks.json b/src/generated/resources/data/forge/tags/blocks/storage_blocks.json index 86d8e457a..14641f451 100644 --- a/src/generated/resources/data/forge/tags/blocks/storage_blocks.json +++ b/src/generated/resources/data/forge/tags/blocks/storage_blocks.json @@ -2,6 +2,8 @@ "values": [ "create:raw_zinc_block", "create:zinc_block", - "create:brass_block" + "create:andesite_alloy_block", + "create:brass_block", + "create:experience_block" ] } \ No newline at end of file diff --git a/src/generated/resources/data/forge/tags/blocks/storage_blocks/andesite_alloy.json b/src/generated/resources/data/forge/tags/blocks/storage_blocks/andesite_alloy.json new file mode 100644 index 000000000..f3331f5df --- /dev/null +++ b/src/generated/resources/data/forge/tags/blocks/storage_blocks/andesite_alloy.json @@ -0,0 +1,5 @@ +{ + "values": [ + "create:andesite_alloy_block" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/forge/tags/items/armors/boots.json b/src/generated/resources/data/forge/tags/items/armors/boots.json new file mode 100644 index 000000000..892f0dd35 --- /dev/null +++ b/src/generated/resources/data/forge/tags/items/armors/boots.json @@ -0,0 +1,6 @@ +{ + "values": [ + "create:copper_diving_boots", + "create:netherite_diving_boots" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/forge/tags/items/armors/chestplates.json b/src/generated/resources/data/forge/tags/items/armors/chestplates.json new file mode 100644 index 000000000..f930557b8 --- /dev/null +++ b/src/generated/resources/data/forge/tags/items/armors/chestplates.json @@ -0,0 +1,6 @@ +{ + "values": [ + "create:copper_backtank", + "create:netherite_backtank" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/forge/tags/items/armors/helmets.json b/src/generated/resources/data/forge/tags/items/armors/helmets.json new file mode 100644 index 000000000..b8690643e --- /dev/null +++ b/src/generated/resources/data/forge/tags/items/armors/helmets.json @@ -0,0 +1,6 @@ +{ + "values": [ + "create:copper_diving_helmet", + "create:netherite_diving_helmet" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/forge/tags/items/glass_panes.json b/src/generated/resources/data/forge/tags/items/glass_panes.json index 1e77aae5c..ec99a30f5 100644 --- a/src/generated/resources/data/forge/tags/items/glass_panes.json +++ b/src/generated/resources/data/forge/tags/items/glass_panes.json @@ -10,6 +10,7 @@ "create:jungle_window_pane", "create:acacia_window_pane", "create:dark_oak_window_pane", + "create:mangrove_window_pane", "create:crimson_window_pane", "create:warped_window_pane", "create:ornate_iron_window_pane" diff --git a/src/generated/resources/data/forge/tags/items/storage_blocks.json b/src/generated/resources/data/forge/tags/items/storage_blocks.json index 86d8e457a..14641f451 100644 --- a/src/generated/resources/data/forge/tags/items/storage_blocks.json +++ b/src/generated/resources/data/forge/tags/items/storage_blocks.json @@ -2,6 +2,8 @@ "values": [ "create:raw_zinc_block", "create:zinc_block", - "create:brass_block" + "create:andesite_alloy_block", + "create:brass_block", + "create:experience_block" ] } \ No newline at end of file diff --git a/src/generated/resources/data/forge/tags/items/storage_blocks/andesite_alloy.json b/src/generated/resources/data/forge/tags/items/storage_blocks/andesite_alloy.json new file mode 100644 index 000000000..f3331f5df --- /dev/null +++ b/src/generated/resources/data/forge/tags/items/storage_blocks/andesite_alloy.json @@ -0,0 +1,5 @@ +{ + "values": [ + "create:andesite_alloy_block" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/tags/blocks/beacon_base_blocks.json b/src/generated/resources/data/minecraft/tags/blocks/beacon_base_blocks.json index 5642e46d2..a4d31b28a 100644 --- a/src/generated/resources/data/minecraft/tags/blocks/beacon_base_blocks.json +++ b/src/generated/resources/data/minecraft/tags/blocks/beacon_base_blocks.json @@ -1,6 +1,7 @@ { "values": [ "create:zinc_block", - "create:brass_block" + "create:brass_block", + "create:experience_block" ] } \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/tags/blocks/climbable.json b/src/generated/resources/data/minecraft/tags/blocks/climbable.json index 93a0a9a09..4052c24c4 100644 --- a/src/generated/resources/data/minecraft/tags/blocks/climbable.json +++ b/src/generated/resources/data/minecraft/tags/blocks/climbable.json @@ -1,7 +1,12 @@ { "values": [ + "create:rope", + "create:pulley_magnet", "create:andesite_ladder", "create:brass_ladder", - "create:copper_ladder" + "create:copper_ladder", + "create:andesite_scaffolding", + "create:brass_scaffolding", + "create:copper_scaffolding" ] } \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/tags/blocks/doors.json b/src/generated/resources/data/minecraft/tags/blocks/doors.json index 060700c4e..a1f766933 100644 --- a/src/generated/resources/data/minecraft/tags/blocks/doors.json +++ b/src/generated/resources/data/minecraft/tags/blocks/doors.json @@ -1,5 +1,8 @@ { "values": [ + "create:andesite_door", + "create:brass_door", + "create:copper_door", "create:train_door", "create:framed_glass_door" ] diff --git a/src/generated/resources/data/minecraft/tags/blocks/impermeable.json b/src/generated/resources/data/minecraft/tags/blocks/impermeable.json index 5cbfb7ca6..f6c6369fb 100644 --- a/src/generated/resources/data/minecraft/tags/blocks/impermeable.json +++ b/src/generated/resources/data/minecraft/tags/blocks/impermeable.json @@ -10,6 +10,7 @@ "create:jungle_window", "create:acacia_window", "create:dark_oak_window", + "create:mangrove_window", "create:crimson_window", "create:warped_window", "create:ornate_iron_window" diff --git a/src/generated/resources/data/minecraft/tags/blocks/mineable/axe.json b/src/generated/resources/data/minecraft/tags/blocks/mineable/axe.json index 008241891..488344a68 100644 --- a/src/generated/resources/data/minecraft/tags/blocks/mineable/axe.json +++ b/src/generated/resources/data/minecraft/tags/blocks/mineable/axe.json @@ -16,6 +16,8 @@ "create:adjustable_chain_gearshift", "create:belt", "create:water_wheel", + "create:large_water_wheel", + "create:water_wheel_structure", "create:encased_fan", "create:nozzle", "create:turntable", @@ -41,33 +43,21 @@ "create:mechanical_bearing", "create:clockwork_bearing", "create:rope_pulley", + "create:elevator_pulley", "create:cart_assembler", "create:linear_chassis", "create:secondary_linear_chassis", "create:radial_chassis", + "create:contraption_controls", "create:mechanical_drill", "create:mechanical_saw", "create:deployer", "create:portable_storage_interface", "create:redstone_contact", + "create:elevator_contact", "create:mechanical_harvester", "create:mechanical_plough", - "create:white_seat", - "create:orange_seat", - "create:magenta_seat", - "create:light_blue_seat", - "create:yellow_seat", - "create:lime_seat", - "create:pink_seat", - "create:gray_seat", - "create:light_gray_seat", - "create:cyan_seat", - "create:purple_seat", - "create:blue_seat", - "create:brown_seat", - "create:green_seat", - "create:red_seat", - "create:black_seat", + "create:mechanical_roller", "create:sail_frame", "create:white_sail", "create:orange_sail", @@ -102,6 +92,25 @@ "create:display_link", "create:redstone_link", "create:analog_lever", - "create:lectern_controller" + "create:lectern_controller", + "create:clipboard", + "create:copycat_step", + "create:copycat_panel", + "create:white_seat", + "create:orange_seat", + "create:magenta_seat", + "create:light_blue_seat", + "create:yellow_seat", + "create:lime_seat", + "create:pink_seat", + "create:gray_seat", + "create:light_gray_seat", + "create:cyan_seat", + "create:purple_seat", + "create:blue_seat", + "create:brown_seat", + "create:green_seat", + "create:red_seat", + "create:black_seat" ] } \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/tags/blocks/mineable/pickaxe.json b/src/generated/resources/data/minecraft/tags/blocks/mineable/pickaxe.json index df62ba9e5..82f9abcb2 100644 --- a/src/generated/resources/data/minecraft/tags/blocks/mineable/pickaxe.json +++ b/src/generated/resources/data/minecraft/tags/blocks/mineable/pickaxe.json @@ -19,6 +19,8 @@ "create:belt", "create:creative_motor", "create:water_wheel", + "create:large_water_wheel", + "create:water_wheel_structure", "create:encased_fan", "create:nozzle", "create:turntable", @@ -40,11 +42,6 @@ "create:stressometer", "create:wooden_bracket", "create:metal_bracket", - "create:metal_girder", - "create:metal_girder_encased_shaft", - "create:andesite_ladder", - "create:brass_ladder", - "create:copper_ladder", "create:fluid_pipe", "create:encased_fluid_pipe", "create:glass_fluid_pipe", @@ -88,19 +85,23 @@ "create:mechanical_bearing", "create:clockwork_bearing", "create:rope_pulley", + "create:elevator_pulley", "create:cart_assembler", "create:controller_rail", "create:linear_chassis", "create:secondary_linear_chassis", "create:radial_chassis", "create:sticker", + "create:contraption_controls", "create:mechanical_drill", "create:mechanical_saw", "create:deployer", "create:portable_storage_interface", "create:redstone_contact", + "create:elevator_contact", "create:mechanical_harvester", "create:mechanical_plough", + "create:mechanical_roller", "create:andesite_casing", "create:brass_casing", "create:copper_casing", @@ -119,10 +120,6 @@ "create:small_bogey", "create:large_bogey", "create:controls", - "create:train_door", - "create:train_trapdoor", - "create:framed_glass_door", - "create:framed_glass_trapdoor", "create:item_vault", "create:andesite_funnel", "create:andesite_belt_funnel", @@ -156,13 +153,39 @@ "create:analog_lever", "create:placard", "create:copper_backtank", + "create:netherite_backtank", "create:peculiar_bell", "create:haunted_bell", + "create:clipboard", + "create:andesite_ladder", + "create:brass_ladder", + "create:copper_ladder", + "create:andesite_bars", + "create:brass_bars", + "create:copper_bars", + "create:andesite_scaffolding", + "create:brass_scaffolding", + "create:copper_scaffolding", + "create:metal_girder", + "create:metal_girder_encased_shaft", + "create:copycat_base", + "create:copycat_step", + "create:copycat_panel", + "create:andesite_door", + "create:brass_door", + "create:copper_door", + "create:train_door", + "create:train_trapdoor", + "create:framed_glass_door", + "create:framed_glass_trapdoor", "create:zinc_ore", "create:deepslate_zinc_ore", "create:raw_zinc_block", "create:zinc_block", + "create:andesite_alloy_block", + "create:industrial_iron_block", "create:brass_block", + "create:experience_block", "create:rose_quartz_block", "create:rose_quartz_tiles", "create:small_rose_quartz_tiles", diff --git a/src/generated/resources/data/minecraft/tags/blocks/wooden_doors.json b/src/generated/resources/data/minecraft/tags/blocks/wooden_doors.json index 060700c4e..a1f766933 100644 --- a/src/generated/resources/data/minecraft/tags/blocks/wooden_doors.json +++ b/src/generated/resources/data/minecraft/tags/blocks/wooden_doors.json @@ -1,5 +1,8 @@ { "values": [ + "create:andesite_door", + "create:brass_door", + "create:copper_door", "create:train_door", "create:framed_glass_door" ] diff --git a/src/generated/resources/data/minecraft/tags/items/doors.json b/src/generated/resources/data/minecraft/tags/items/doors.json index 060700c4e..a1f766933 100644 --- a/src/generated/resources/data/minecraft/tags/items/doors.json +++ b/src/generated/resources/data/minecraft/tags/items/doors.json @@ -1,5 +1,8 @@ { "values": [ + "create:andesite_door", + "create:brass_door", + "create:copper_door", "create:train_door", "create:framed_glass_door" ] diff --git a/src/generated/resources/data/minecraft/tags/items/piglin_loved.json b/src/generated/resources/data/minecraft/tags/items/piglin_loved.json index 46e769ef0..5c84f1c61 100644 --- a/src/generated/resources/data/minecraft/tags/items/piglin_loved.json +++ b/src/generated/resources/data/minecraft/tags/items/piglin_loved.json @@ -1,6 +1,6 @@ { "values": [ "create:golden_sheet", - "create:crushed_gold_ore" + "create:crushed_raw_gold" ] } \ No newline at end of file diff --git a/src/generated/resources/data/quark/tags/blocks/non_double_door.json b/src/generated/resources/data/quark/tags/blocks/non_double_door.json index 060700c4e..a1f766933 100644 --- a/src/generated/resources/data/quark/tags/blocks/non_double_door.json +++ b/src/generated/resources/data/quark/tags/blocks/non_double_door.json @@ -1,5 +1,8 @@ { "values": [ + "create:andesite_door", + "create:brass_door", + "create:copper_door", "create:train_door", "create:framed_glass_door" ] diff --git a/src/main/java/com/simibubi/create/AllBlockEntityTypes.java b/src/main/java/com/simibubi/create/AllBlockEntityTypes.java new file mode 100644 index 000000000..8ff7849e6 --- /dev/null +++ b/src/main/java/com/simibubi/create/AllBlockEntityTypes.java @@ -0,0 +1,893 @@ +package com.simibubi.create; + +import static com.simibubi.create.Create.REGISTRATE; +import static com.simibubi.create.content.redstone.displayLink.AllDisplayBehaviours.assignDataBehaviourBE; + +import com.simibubi.create.content.contraptions.actors.contraptionControls.ContraptionControlsBlockEntity; +import com.simibubi.create.content.contraptions.actors.contraptionControls.ContraptionControlsRenderer; +import com.simibubi.create.content.contraptions.actors.harvester.HarvesterBlockEntity; +import com.simibubi.create.content.contraptions.actors.harvester.HarvesterRenderer; +import com.simibubi.create.content.contraptions.actors.psi.PSIInstance; +import com.simibubi.create.content.contraptions.actors.psi.PortableFluidInterfaceBlockEntity; +import com.simibubi.create.content.contraptions.actors.psi.PortableItemInterfaceBlockEntity; +import com.simibubi.create.content.contraptions.actors.psi.PortableStorageInterfaceRenderer; +import com.simibubi.create.content.contraptions.actors.roller.RollerBlockEntity; +import com.simibubi.create.content.contraptions.actors.roller.RollerRenderer; +import com.simibubi.create.content.contraptions.bearing.BearingInstance; +import com.simibubi.create.content.contraptions.bearing.BearingRenderer; +import com.simibubi.create.content.contraptions.bearing.ClockworkBearingBlockEntity; +import com.simibubi.create.content.contraptions.bearing.MechanicalBearingBlockEntity; +import com.simibubi.create.content.contraptions.bearing.WindmillBearingBlockEntity; +import com.simibubi.create.content.contraptions.chassis.ChassisBlockEntity; +import com.simibubi.create.content.contraptions.chassis.StickerBlockEntity; +import com.simibubi.create.content.contraptions.chassis.StickerInstance; +import com.simibubi.create.content.contraptions.chassis.StickerRenderer; +import com.simibubi.create.content.contraptions.elevator.ElevatorContactBlockEntity; +import com.simibubi.create.content.contraptions.elevator.ElevatorPulleyBlockEntity; +import com.simibubi.create.content.contraptions.elevator.ElevatorPulleyRenderer; +import com.simibubi.create.content.contraptions.gantry.GantryCarriageBlockEntity; +import com.simibubi.create.content.contraptions.gantry.GantryCarriageInstance; +import com.simibubi.create.content.contraptions.gantry.GantryCarriageRenderer; +import com.simibubi.create.content.contraptions.mounted.CartAssemblerBlockEntity; +import com.simibubi.create.content.contraptions.piston.MechanicalPistonBlockEntity; +import com.simibubi.create.content.contraptions.piston.MechanicalPistonRenderer; +import com.simibubi.create.content.contraptions.pulley.HosePulleyInstance; +import com.simibubi.create.content.contraptions.pulley.PulleyBlockEntity; +import com.simibubi.create.content.contraptions.pulley.PulleyRenderer; +import com.simibubi.create.content.contraptions.pulley.RopePulleyInstance; +import com.simibubi.create.content.decoration.copycat.CopycatBlockEntity; +import com.simibubi.create.content.decoration.placard.PlacardBlockEntity; +import com.simibubi.create.content.decoration.placard.PlacardRenderer; +import com.simibubi.create.content.decoration.slidingDoor.SlidingDoorBlockEntity; +import com.simibubi.create.content.decoration.slidingDoor.SlidingDoorRenderer; +import com.simibubi.create.content.decoration.steamWhistle.WhistleBlockEntity; +import com.simibubi.create.content.decoration.steamWhistle.WhistleRenderer; +import com.simibubi.create.content.equipment.armor.BacktankBlockEntity; +import com.simibubi.create.content.equipment.armor.BacktankInstance; +import com.simibubi.create.content.equipment.armor.BacktankRenderer; +import com.simibubi.create.content.equipment.bell.BellRenderer; +import com.simibubi.create.content.equipment.bell.HauntedBellBlockEntity; +import com.simibubi.create.content.equipment.bell.PeculiarBellBlockEntity; +import com.simibubi.create.content.equipment.clipboard.ClipboardBlockEntity; +import com.simibubi.create.content.equipment.toolbox.ToolBoxInstance; +import com.simibubi.create.content.equipment.toolbox.ToolboxBlockEntity; +import com.simibubi.create.content.equipment.toolbox.ToolboxRenderer; +import com.simibubi.create.content.fluids.drain.ItemDrainBlockEntity; +import com.simibubi.create.content.fluids.drain.ItemDrainRenderer; +import com.simibubi.create.content.fluids.hosePulley.HosePulleyBlockEntity; +import com.simibubi.create.content.fluids.hosePulley.HosePulleyRenderer; +import com.simibubi.create.content.fluids.pipes.FluidPipeBlockEntity; +import com.simibubi.create.content.fluids.pipes.SmartFluidPipeBlockEntity; +import com.simibubi.create.content.fluids.pipes.StraightPipeBlockEntity; +import com.simibubi.create.content.fluids.pipes.TransparentStraightPipeRenderer; +import com.simibubi.create.content.fluids.pipes.valve.FluidValveBlockEntity; +import com.simibubi.create.content.fluids.pipes.valve.FluidValveInstance; +import com.simibubi.create.content.fluids.pipes.valve.FluidValveRenderer; +import com.simibubi.create.content.fluids.pump.PumpBlockEntity; +import com.simibubi.create.content.fluids.pump.PumpCogInstance; +import com.simibubi.create.content.fluids.pump.PumpRenderer; +import com.simibubi.create.content.fluids.spout.SpoutBlockEntity; +import com.simibubi.create.content.fluids.spout.SpoutRenderer; +import com.simibubi.create.content.fluids.tank.CreativeFluidTankBlockEntity; +import com.simibubi.create.content.fluids.tank.FluidTankBlockEntity; +import com.simibubi.create.content.fluids.tank.FluidTankRenderer; +import com.simibubi.create.content.kinetics.base.CutoutRotatingInstance; +import com.simibubi.create.content.kinetics.base.HalfShaftInstance; +import com.simibubi.create.content.kinetics.base.HorizontalHalfShaftInstance; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.content.kinetics.base.ShaftInstance; +import com.simibubi.create.content.kinetics.base.ShaftRenderer; +import com.simibubi.create.content.kinetics.base.SingleRotatingInstance; +import com.simibubi.create.content.kinetics.belt.BeltBlockEntity; +import com.simibubi.create.content.kinetics.belt.BeltInstance; +import com.simibubi.create.content.kinetics.belt.BeltRenderer; +import com.simibubi.create.content.kinetics.chainDrive.ChainGearshiftBlockEntity; +import com.simibubi.create.content.kinetics.clock.CuckooClockBlockEntity; +import com.simibubi.create.content.kinetics.clock.CuckooClockRenderer; +import com.simibubi.create.content.kinetics.crafter.MechanicalCrafterBlockEntity; +import com.simibubi.create.content.kinetics.crafter.MechanicalCrafterRenderer; +import com.simibubi.create.content.kinetics.crafter.ShaftlessCogwheelInstance; +import com.simibubi.create.content.kinetics.crank.HandCrankBlockEntity; +import com.simibubi.create.content.kinetics.crank.HandCrankInstance; +import com.simibubi.create.content.kinetics.crank.HandCrankRenderer; +import com.simibubi.create.content.kinetics.crank.ValveHandleBlockEntity; +import com.simibubi.create.content.kinetics.crusher.CrushingWheelBlockEntity; +import com.simibubi.create.content.kinetics.crusher.CrushingWheelControllerBlockEntity; +import com.simibubi.create.content.kinetics.deployer.DeployerBlockEntity; +import com.simibubi.create.content.kinetics.deployer.DeployerInstance; +import com.simibubi.create.content.kinetics.deployer.DeployerRenderer; +import com.simibubi.create.content.kinetics.drill.DrillBlockEntity; +import com.simibubi.create.content.kinetics.drill.DrillInstance; +import com.simibubi.create.content.kinetics.drill.DrillRenderer; +import com.simibubi.create.content.kinetics.fan.EncasedFanBlockEntity; +import com.simibubi.create.content.kinetics.fan.EncasedFanRenderer; +import com.simibubi.create.content.kinetics.fan.FanInstance; +import com.simibubi.create.content.kinetics.fan.NozzleBlockEntity; +import com.simibubi.create.content.kinetics.flywheel.FlywheelBlockEntity; +import com.simibubi.create.content.kinetics.flywheel.FlywheelInstance; +import com.simibubi.create.content.kinetics.flywheel.FlywheelRenderer; +import com.simibubi.create.content.kinetics.gantry.GantryShaftBlockEntity; +import com.simibubi.create.content.kinetics.gauge.GaugeInstance; +import com.simibubi.create.content.kinetics.gauge.GaugeRenderer; +import com.simibubi.create.content.kinetics.gauge.SpeedGaugeBlockEntity; +import com.simibubi.create.content.kinetics.gauge.StressGaugeBlockEntity; +import com.simibubi.create.content.kinetics.gearbox.GearboxBlockEntity; +import com.simibubi.create.content.kinetics.gearbox.GearboxInstance; +import com.simibubi.create.content.kinetics.gearbox.GearboxRenderer; +import com.simibubi.create.content.kinetics.mechanicalArm.ArmBlockEntity; +import com.simibubi.create.content.kinetics.mechanicalArm.ArmInstance; +import com.simibubi.create.content.kinetics.mechanicalArm.ArmRenderer; +import com.simibubi.create.content.kinetics.millstone.MillstoneBlockEntity; +import com.simibubi.create.content.kinetics.millstone.MillstoneCogInstance; +import com.simibubi.create.content.kinetics.millstone.MillstoneRenderer; +import com.simibubi.create.content.kinetics.mixer.MechanicalMixerBlockEntity; +import com.simibubi.create.content.kinetics.mixer.MechanicalMixerRenderer; +import com.simibubi.create.content.kinetics.mixer.MixerInstance; +import com.simibubi.create.content.kinetics.motor.CreativeMotorBlockEntity; +import com.simibubi.create.content.kinetics.motor.CreativeMotorRenderer; +import com.simibubi.create.content.kinetics.press.MechanicalPressBlockEntity; +import com.simibubi.create.content.kinetics.press.MechanicalPressRenderer; +import com.simibubi.create.content.kinetics.press.PressInstance; +import com.simibubi.create.content.kinetics.saw.SawBlockEntity; +import com.simibubi.create.content.kinetics.saw.SawInstance; +import com.simibubi.create.content.kinetics.saw.SawRenderer; +import com.simibubi.create.content.kinetics.simpleRelays.BracketedKineticBlockEntity; +import com.simibubi.create.content.kinetics.simpleRelays.BracketedKineticBlockEntityInstance; +import com.simibubi.create.content.kinetics.simpleRelays.BracketedKineticBlockEntityRenderer; +import com.simibubi.create.content.kinetics.simpleRelays.SimpleKineticBlockEntity; +import com.simibubi.create.content.kinetics.simpleRelays.encased.EncasedCogInstance; +import com.simibubi.create.content.kinetics.simpleRelays.encased.EncasedCogRenderer; +import com.simibubi.create.content.kinetics.speedController.SpeedControllerBlockEntity; +import com.simibubi.create.content.kinetics.speedController.SpeedControllerRenderer; +import com.simibubi.create.content.kinetics.steamEngine.PoweredShaftBlockEntity; +import com.simibubi.create.content.kinetics.steamEngine.SteamEngineBlockEntity; +import com.simibubi.create.content.kinetics.steamEngine.SteamEngineInstance; +import com.simibubi.create.content.kinetics.steamEngine.SteamEngineRenderer; +import com.simibubi.create.content.kinetics.transmission.ClutchBlockEntity; +import com.simibubi.create.content.kinetics.transmission.GearshiftBlockEntity; +import com.simibubi.create.content.kinetics.transmission.SplitShaftInstance; +import com.simibubi.create.content.kinetics.transmission.SplitShaftRenderer; +import com.simibubi.create.content.kinetics.transmission.sequencer.SequencedGearshiftBlockEntity; +import com.simibubi.create.content.kinetics.turntable.TurntableBlockEntity; +import com.simibubi.create.content.kinetics.waterwheel.LargeWaterWheelBlockEntity; +import com.simibubi.create.content.kinetics.waterwheel.WaterWheelBlockEntity; +import com.simibubi.create.content.kinetics.waterwheel.WaterWheelInstance; +import com.simibubi.create.content.kinetics.waterwheel.WaterWheelRenderer; +import com.simibubi.create.content.logistics.chute.ChuteBlockEntity; +import com.simibubi.create.content.logistics.chute.ChuteRenderer; +import com.simibubi.create.content.logistics.chute.SmartChuteBlockEntity; +import com.simibubi.create.content.logistics.chute.SmartChuteRenderer; +import com.simibubi.create.content.logistics.crate.CreativeCrateBlockEntity; +import com.simibubi.create.content.logistics.depot.DepotBlockEntity; +import com.simibubi.create.content.logistics.depot.DepotRenderer; +import com.simibubi.create.content.logistics.depot.EjectorBlockEntity; +import com.simibubi.create.content.logistics.depot.EjectorInstance; +import com.simibubi.create.content.logistics.depot.EjectorRenderer; +import com.simibubi.create.content.logistics.funnel.FunnelBlockEntity; +import com.simibubi.create.content.logistics.funnel.FunnelInstance; +import com.simibubi.create.content.logistics.funnel.FunnelRenderer; +import com.simibubi.create.content.logistics.tunnel.BeltTunnelBlockEntity; +import com.simibubi.create.content.logistics.tunnel.BeltTunnelInstance; +import com.simibubi.create.content.logistics.tunnel.BeltTunnelRenderer; +import com.simibubi.create.content.logistics.tunnel.BrassTunnelBlockEntity; +import com.simibubi.create.content.logistics.vault.ItemVaultBlockEntity; +import com.simibubi.create.content.processing.basin.BasinBlockEntity; +import com.simibubi.create.content.processing.basin.BasinRenderer; +import com.simibubi.create.content.processing.burner.BlazeBurnerBlockEntity; +import com.simibubi.create.content.processing.burner.BlazeBurnerRenderer; +import com.simibubi.create.content.redstone.analogLever.AnalogLeverBlockEntity; +import com.simibubi.create.content.redstone.analogLever.AnalogLeverInstance; +import com.simibubi.create.content.redstone.analogLever.AnalogLeverRenderer; +import com.simibubi.create.content.redstone.diodes.BrassDiodeInstance; +import com.simibubi.create.content.redstone.diodes.BrassDiodeRenderer; +import com.simibubi.create.content.redstone.diodes.PulseExtenderBlockEntity; +import com.simibubi.create.content.redstone.diodes.PulseRepeaterBlockEntity; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkBlockEntity; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkRenderer; +import com.simibubi.create.content.redstone.displayLink.source.NixieTubeDisplaySource; +import com.simibubi.create.content.redstone.displayLink.target.NixieTubeDisplayTarget; +import com.simibubi.create.content.redstone.link.RedstoneLinkBlockEntity; +import com.simibubi.create.content.redstone.link.controller.LecternControllerBlockEntity; +import com.simibubi.create.content.redstone.link.controller.LecternControllerRenderer; +import com.simibubi.create.content.redstone.nixieTube.NixieTubeBlockEntity; +import com.simibubi.create.content.redstone.nixieTube.NixieTubeRenderer; +import com.simibubi.create.content.redstone.smartObserver.SmartObserverBlockEntity; +import com.simibubi.create.content.redstone.thresholdSwitch.ThresholdSwitchBlockEntity; +import com.simibubi.create.content.schematics.cannon.SchematicannonBlockEntity; +import com.simibubi.create.content.schematics.cannon.SchematicannonInstance; +import com.simibubi.create.content.schematics.cannon.SchematicannonRenderer; +import com.simibubi.create.content.schematics.table.SchematicTableBlockEntity; +import com.simibubi.create.content.trains.bogey.BogeyBlockEntityRenderer; +import com.simibubi.create.content.trains.bogey.StandardBogeyBlockEntity; +import com.simibubi.create.content.trains.display.FlapDisplayBlockEntity; +import com.simibubi.create.content.trains.display.FlapDisplayRenderer; +import com.simibubi.create.content.trains.observer.TrackObserverBlockEntity; +import com.simibubi.create.content.trains.observer.TrackObserverRenderer; +import com.simibubi.create.content.trains.signal.SignalBlockEntity; +import com.simibubi.create.content.trains.signal.SignalRenderer; +import com.simibubi.create.content.trains.station.StationBlockEntity; +import com.simibubi.create.content.trains.station.StationRenderer; +import com.simibubi.create.content.trains.track.FakeTrackBlockEntity; +import com.simibubi.create.content.trains.track.TrackBlockEntity; +import com.simibubi.create.content.trains.track.TrackInstance; +import com.simibubi.create.content.trains.track.TrackMaterial; +import com.simibubi.create.content.trains.track.TrackRenderer; +import com.simibubi.create.foundation.blockEntity.renderer.SmartBlockEntityRenderer; +import com.tterrag.registrate.util.entry.BlockEntityEntry; + +public class AllBlockEntityTypes { + + // Schematics + public static final BlockEntityEntry SCHEMATICANNON = REGISTRATE + .blockEntity("schematicannon", SchematicannonBlockEntity::new) + .instance(() -> SchematicannonInstance::new) + .validBlocks(AllBlocks.SCHEMATICANNON) + .renderer(() -> SchematicannonRenderer::new) + .register(); + + public static final BlockEntityEntry SCHEMATIC_TABLE = REGISTRATE + .blockEntity("schematic_table", SchematicTableBlockEntity::new) + .validBlocks(AllBlocks.SCHEMATIC_TABLE) + .register(); + + // Kinetics + public static final BlockEntityEntry BRACKETED_KINETIC = REGISTRATE + .blockEntity("simple_kinetic", BracketedKineticBlockEntity::new) + .instance(() -> BracketedKineticBlockEntityInstance::new, false) + .validBlocks(AllBlocks.SHAFT, AllBlocks.COGWHEEL, AllBlocks.LARGE_COGWHEEL) + .renderer(() -> BracketedKineticBlockEntityRenderer::new) + .register(); + + public static final BlockEntityEntry MOTOR = REGISTRATE + .blockEntity("motor", CreativeMotorBlockEntity::new) + .instance(() -> HalfShaftInstance::new, false) + .validBlocks(AllBlocks.CREATIVE_MOTOR) + .renderer(() -> CreativeMotorRenderer::new) + .register(); + + public static final BlockEntityEntry GEARBOX = REGISTRATE + .blockEntity("gearbox", GearboxBlockEntity::new) + .instance(() -> GearboxInstance::new, false) + .validBlocks(AllBlocks.GEARBOX) + .renderer(() -> GearboxRenderer::new) + .register(); + + public static final BlockEntityEntry ENCASED_SHAFT = REGISTRATE + .blockEntity("encased_shaft", KineticBlockEntity::new) + .instance(() -> ShaftInstance::new, false) + .validBlocks(AllBlocks.ANDESITE_ENCASED_SHAFT, AllBlocks.BRASS_ENCASED_SHAFT, AllBlocks.ENCASED_CHAIN_DRIVE, + AllBlocks.METAL_GIRDER_ENCASED_SHAFT) + .renderer(() -> ShaftRenderer::new) + .register(); + + public static final BlockEntityEntry ENCASED_COGWHEEL = REGISTRATE + .blockEntity("encased_cogwheel", SimpleKineticBlockEntity::new) + .instance(() -> EncasedCogInstance::small, false) + .validBlocks(AllBlocks.ANDESITE_ENCASED_COGWHEEL, AllBlocks.BRASS_ENCASED_COGWHEEL) + .renderer(() -> EncasedCogRenderer::small) + .register(); + + public static final BlockEntityEntry ENCASED_LARGE_COGWHEEL = REGISTRATE + .blockEntity("encased_large_cogwheel", SimpleKineticBlockEntity::new) + .instance(() -> EncasedCogInstance::large, false) + .validBlocks(AllBlocks.ANDESITE_ENCASED_LARGE_COGWHEEL, AllBlocks.BRASS_ENCASED_LARGE_COGWHEEL) + .renderer(() -> EncasedCogRenderer::large) + .register(); + + public static final BlockEntityEntry ADJUSTABLE_CHAIN_GEARSHIFT = REGISTRATE + .blockEntity("adjustable_chain_gearshift", ChainGearshiftBlockEntity::new) + .instance(() -> ShaftInstance::new, false) + .validBlocks(AllBlocks.ADJUSTABLE_CHAIN_GEARSHIFT) + .renderer(() -> ShaftRenderer::new) + .register(); + + public static final BlockEntityEntry ENCASED_FAN = REGISTRATE + .blockEntity("encased_fan", EncasedFanBlockEntity::new) + .instance(() -> FanInstance::new, false) + .validBlocks(AllBlocks.ENCASED_FAN) + .renderer(() -> EncasedFanRenderer::new) + .register(); + + public static final BlockEntityEntry NOZZLE = REGISTRATE + .blockEntity("nozzle", NozzleBlockEntity::new) + .validBlocks(AllBlocks.NOZZLE) + // .renderer(() -> renderer) + .register(); + + public static final BlockEntityEntry CLUTCH = REGISTRATE + .blockEntity("clutch", ClutchBlockEntity::new) + .instance(() -> SplitShaftInstance::new, false) + .validBlocks(AllBlocks.CLUTCH) + .renderer(() -> SplitShaftRenderer::new) + .register(); + + public static final BlockEntityEntry GEARSHIFT = REGISTRATE + .blockEntity("gearshift", GearshiftBlockEntity::new) + .instance(() -> SplitShaftInstance::new, false) + .validBlocks(AllBlocks.GEARSHIFT) + .renderer(() -> SplitShaftRenderer::new) + .register(); + + public static final BlockEntityEntry TURNTABLE = REGISTRATE + .blockEntity("turntable", TurntableBlockEntity::new) + .instance(() -> SingleRotatingInstance::new, false) + .validBlocks(AllBlocks.TURNTABLE) + .renderer(() -> KineticBlockEntityRenderer::new) + .register(); + + public static final BlockEntityEntry HAND_CRANK = REGISTRATE + .blockEntity("hand_crank", HandCrankBlockEntity::new) + .instance(() -> HandCrankInstance::new) + .validBlocks(AllBlocks.HAND_CRANK) + .renderer(() -> HandCrankRenderer::new) + .register(); + + public static final BlockEntityEntry VALVE_HANDLE = REGISTRATE + .blockEntity("valve_handle", ValveHandleBlockEntity::new) + .instance(() -> HandCrankInstance::new) + .validBlocks(AllBlocks.COPPER_VALVE_HANDLE) + .validBlocks(AllBlocks.DYED_VALVE_HANDLES.toArray()) + .renderer(() -> HandCrankRenderer::new) + .register(); + + public static final BlockEntityEntry CUCKOO_CLOCK = REGISTRATE + .blockEntity("cuckoo_clock", CuckooClockBlockEntity::new) + .instance(() -> HorizontalHalfShaftInstance::new) + .validBlocks(AllBlocks.CUCKOO_CLOCK, AllBlocks.MYSTERIOUS_CUCKOO_CLOCK) + .renderer(() -> CuckooClockRenderer::new) + .register(); + + public static final BlockEntityEntry GANTRY_SHAFT = REGISTRATE + .blockEntity("gantry_shaft", GantryShaftBlockEntity::new) + .instance(() -> SingleRotatingInstance::new, false) + .validBlocks(AllBlocks.GANTRY_SHAFT) + .renderer(() -> KineticBlockEntityRenderer::new) + .register(); + + public static final BlockEntityEntry GANTRY_PINION = REGISTRATE + .blockEntity("gantry_pinion", GantryCarriageBlockEntity::new) + .instance(() -> GantryCarriageInstance::new) + .validBlocks(AllBlocks.GANTRY_CARRIAGE) + .renderer(() -> GantryCarriageRenderer::new) + .register(); + + public static final BlockEntityEntry MECHANICAL_PUMP = REGISTRATE + .blockEntity("mechanical_pump", PumpBlockEntity::new) + .instance(() -> PumpCogInstance::new) + .validBlocks(AllBlocks.MECHANICAL_PUMP) + .renderer(() -> PumpRenderer::new) + .register(); + + public static final BlockEntityEntry SMART_FLUID_PIPE = REGISTRATE + .blockEntity("smart_fluid_pipe", SmartFluidPipeBlockEntity::new) + .validBlocks(AllBlocks.SMART_FLUID_PIPE) + .renderer(() -> SmartBlockEntityRenderer::new) + .register(); + + public static final BlockEntityEntry FLUID_PIPE = REGISTRATE + .blockEntity("fluid_pipe", FluidPipeBlockEntity::new) + .validBlocks(AllBlocks.FLUID_PIPE) + .register(); + + public static final BlockEntityEntry ENCASED_FLUID_PIPE = REGISTRATE + .blockEntity("encased_fluid_pipe", FluidPipeBlockEntity::new) + .validBlocks(AllBlocks.ENCASED_FLUID_PIPE) + .register(); + + public static final BlockEntityEntry GLASS_FLUID_PIPE = REGISTRATE + .blockEntity("glass_fluid_pipe", StraightPipeBlockEntity::new) + .validBlocks(AllBlocks.GLASS_FLUID_PIPE) + .renderer(() -> TransparentStraightPipeRenderer::new) + .register(); + + public static final BlockEntityEntry FLUID_VALVE = REGISTRATE + .blockEntity("fluid_valve", FluidValveBlockEntity::new) + .instance(() -> FluidValveInstance::new) + .validBlocks(AllBlocks.FLUID_VALVE) + .renderer(() -> FluidValveRenderer::new) + .register(); + + public static final BlockEntityEntry FLUID_TANK = REGISTRATE + .blockEntity("fluid_tank", FluidTankBlockEntity::new) + .validBlocks(AllBlocks.FLUID_TANK) + .renderer(() -> FluidTankRenderer::new) + .register(); + + public static final BlockEntityEntry CREATIVE_FLUID_TANK = REGISTRATE + .blockEntity("creative_fluid_tank", CreativeFluidTankBlockEntity::new) + .validBlocks(AllBlocks.CREATIVE_FLUID_TANK) + .renderer(() -> FluidTankRenderer::new) + .register(); + + public static final BlockEntityEntry HOSE_PULLEY = REGISTRATE + .blockEntity("hose_pulley", HosePulleyBlockEntity::new) + .instance(() -> HosePulleyInstance::new) + .validBlocks(AllBlocks.HOSE_PULLEY) + .renderer(() -> HosePulleyRenderer::new) + .register(); + + public static final BlockEntityEntry SPOUT = REGISTRATE + .blockEntity("spout", SpoutBlockEntity::new) + .validBlocks(AllBlocks.SPOUT) + .renderer(() -> SpoutRenderer::new) + .register(); + + public static final BlockEntityEntry ITEM_DRAIN = REGISTRATE + .blockEntity("item_drain", ItemDrainBlockEntity::new) + .validBlocks(AllBlocks.ITEM_DRAIN) + .renderer(() -> ItemDrainRenderer::new) + .register(); + + public static final BlockEntityEntry BELT = REGISTRATE + .blockEntity("belt", BeltBlockEntity::new) + .instance(() -> BeltInstance::new, BeltBlockEntity::shouldRenderNormally) + .validBlocks(AllBlocks.BELT) + .renderer(() -> BeltRenderer::new) + .register(); + + public static final BlockEntityEntry CHUTE = REGISTRATE + .blockEntity("chute", ChuteBlockEntity::new) + .validBlocks(AllBlocks.CHUTE) + .renderer(() -> ChuteRenderer::new) + .register(); + + public static final BlockEntityEntry SMART_CHUTE = REGISTRATE + .blockEntity("smart_chute", SmartChuteBlockEntity::new) + .validBlocks(AllBlocks.SMART_CHUTE) + .renderer(() -> SmartChuteRenderer::new) + .register(); + + public static final BlockEntityEntry ANDESITE_TUNNEL = REGISTRATE + .blockEntity("andesite_tunnel", BeltTunnelBlockEntity::new) + .instance(() -> BeltTunnelInstance::new) + .validBlocks(AllBlocks.ANDESITE_TUNNEL) + .renderer(() -> BeltTunnelRenderer::new) + .register(); + + public static final BlockEntityEntry BRASS_TUNNEL = REGISTRATE + .blockEntity("brass_tunnel", BrassTunnelBlockEntity::new) + .instance(() -> BeltTunnelInstance::new) + .validBlocks(AllBlocks.BRASS_TUNNEL) + .renderer(() -> BeltTunnelRenderer::new) + .register(); + + public static final BlockEntityEntry MECHANICAL_ARM = REGISTRATE + .blockEntity("mechanical_arm", ArmBlockEntity::new) + .instance(() -> ArmInstance::new) + .validBlocks(AllBlocks.MECHANICAL_ARM) + .renderer(() -> ArmRenderer::new) + .register(); + + public static final BlockEntityEntry ITEM_VAULT = REGISTRATE + .blockEntity("item_vault", ItemVaultBlockEntity::new) + .validBlocks(AllBlocks.ITEM_VAULT) + .register(); + + public static final BlockEntityEntry MECHANICAL_PISTON = REGISTRATE + .blockEntity("mechanical_piston", MechanicalPistonBlockEntity::new) + .instance(() -> ShaftInstance::new, false) + .validBlocks(AllBlocks.MECHANICAL_PISTON, AllBlocks.STICKY_MECHANICAL_PISTON) + .renderer(() -> MechanicalPistonRenderer::new) + .register(); + + public static final BlockEntityEntry WINDMILL_BEARING = REGISTRATE + .blockEntity("windmill_bearing", WindmillBearingBlockEntity::new) + .instance(() -> BearingInstance::new) + .validBlocks(AllBlocks.WINDMILL_BEARING) + .renderer(() -> BearingRenderer::new) + .register(); + + public static final BlockEntityEntry MECHANICAL_BEARING = REGISTRATE + .blockEntity("mechanical_bearing", MechanicalBearingBlockEntity::new) + .instance(() -> BearingInstance::new) + .validBlocks(AllBlocks.MECHANICAL_BEARING) + .renderer(() -> BearingRenderer::new) + .register(); + + public static final BlockEntityEntry CLOCKWORK_BEARING = REGISTRATE + .blockEntity("clockwork_bearing", ClockworkBearingBlockEntity::new) + .instance(() -> BearingInstance::new) + .validBlocks(AllBlocks.CLOCKWORK_BEARING) + .renderer(() -> BearingRenderer::new) + .register(); + + public static final BlockEntityEntry ROPE_PULLEY = REGISTRATE + .blockEntity("rope_pulley", PulleyBlockEntity::new) + .instance(() -> RopePulleyInstance::new, false) + .validBlocks(AllBlocks.ROPE_PULLEY) + .renderer(() -> PulleyRenderer::new) + .register(); + + public static final BlockEntityEntry ELEVATOR_PULLEY = + REGISTRATE.blockEntity("elevator_pulley", ElevatorPulleyBlockEntity::new) +// .instance(() -> ElevatorPulleyInstance::new, false) + .validBlocks(AllBlocks.ELEVATOR_PULLEY) + .renderer(() -> ElevatorPulleyRenderer::new) + .register(); + + public static final BlockEntityEntry ELEVATOR_CONTACT = + REGISTRATE.blockEntity("elevator_contact", ElevatorContactBlockEntity::new) + .validBlocks(AllBlocks.ELEVATOR_CONTACT) + .register(); + + public static final BlockEntityEntry CHASSIS = REGISTRATE + .blockEntity("chassis", ChassisBlockEntity::new) + .validBlocks(AllBlocks.RADIAL_CHASSIS, AllBlocks.LINEAR_CHASSIS, AllBlocks.SECONDARY_LINEAR_CHASSIS) + // .renderer(() -> renderer) + .register(); + + public static final BlockEntityEntry STICKER = REGISTRATE + .blockEntity("sticker", StickerBlockEntity::new) + .instance(() -> StickerInstance::new, false) + .validBlocks(AllBlocks.STICKER) + .renderer(() -> StickerRenderer::new) + .register(); + + public static final BlockEntityEntry CONTRAPTION_CONTROLS = + REGISTRATE.blockEntity("contraption_controls", ContraptionControlsBlockEntity::new) + .validBlocks(AllBlocks.CONTRAPTION_CONTROLS) + .renderer(() -> ContraptionControlsRenderer::new) + .register(); + + public static final BlockEntityEntry DRILL = REGISTRATE + .blockEntity("drill", DrillBlockEntity::new) + .instance(() -> DrillInstance::new, false) + .validBlocks(AllBlocks.MECHANICAL_DRILL) + .renderer(() -> DrillRenderer::new) + .register(); + + public static final BlockEntityEntry SAW = REGISTRATE + .blockEntity("saw", SawBlockEntity::new) + .instance(() -> SawInstance::new) + .validBlocks(AllBlocks.MECHANICAL_SAW) + .renderer(() -> SawRenderer::new) + .register(); + + public static final BlockEntityEntry HARVESTER = REGISTRATE + .blockEntity("harvester", HarvesterBlockEntity::new) + .validBlocks(AllBlocks.MECHANICAL_HARVESTER) + .renderer(() -> HarvesterRenderer::new) + .register(); + + public static final BlockEntityEntry MECHANICAL_ROLLER = + REGISTRATE.blockEntity("mechanical_roller", RollerBlockEntity::new) + .validBlocks(AllBlocks.MECHANICAL_ROLLER) + .renderer(() -> RollerRenderer::new) + .register(); + + public static final BlockEntityEntry PORTABLE_STORAGE_INTERFACE = + REGISTRATE + .blockEntity("portable_storage_interface", PortableItemInterfaceBlockEntity::new) + .instance(() -> PSIInstance::new) + .validBlocks(AllBlocks.PORTABLE_STORAGE_INTERFACE) + .renderer(() -> PortableStorageInterfaceRenderer::new) + .register(); + + public static final BlockEntityEntry PORTABLE_FLUID_INTERFACE = + REGISTRATE + .blockEntity("portable_fluid_interface", PortableFluidInterfaceBlockEntity::new) + .instance(() -> PSIInstance::new) + .validBlocks(AllBlocks.PORTABLE_FLUID_INTERFACE) + .renderer(() -> PortableStorageInterfaceRenderer::new) + .register(); + + public static final BlockEntityEntry STEAM_ENGINE = REGISTRATE + .blockEntity("steam_engine", SteamEngineBlockEntity::new) + .instance(() -> SteamEngineInstance::new, false) + .validBlocks(AllBlocks.STEAM_ENGINE) + .renderer(() -> SteamEngineRenderer::new) + .register(); + + public static final BlockEntityEntry STEAM_WHISTLE = REGISTRATE + .blockEntity("steam_whistle", WhistleBlockEntity::new) + .validBlocks(AllBlocks.STEAM_WHISTLE) + .renderer(() -> WhistleRenderer::new) + .register(); + + public static final BlockEntityEntry POWERED_SHAFT = REGISTRATE + .blockEntity("powered_shaft", PoweredShaftBlockEntity::new) + .instance(() -> SingleRotatingInstance::new, false) + .validBlocks(AllBlocks.POWERED_SHAFT) + .renderer(() -> KineticBlockEntityRenderer::new) + .register(); + + public static final BlockEntityEntry FLYWHEEL = REGISTRATE + .blockEntity("flywheel", FlywheelBlockEntity::new) + .instance(() -> FlywheelInstance::new, false) + .validBlocks(AllBlocks.FLYWHEEL) + .renderer(() -> FlywheelRenderer::new) + .register(); + + public static final BlockEntityEntry MILLSTONE = REGISTRATE + .blockEntity("millstone", MillstoneBlockEntity::new) + .instance(() -> MillstoneCogInstance::new, false) + .validBlocks(AllBlocks.MILLSTONE) + .renderer(() -> MillstoneRenderer::new) + .register(); + + public static final BlockEntityEntry CRUSHING_WHEEL = REGISTRATE + .blockEntity("crushing_wheel", CrushingWheelBlockEntity::new) + .instance(() -> CutoutRotatingInstance::new, false) + .validBlocks(AllBlocks.CRUSHING_WHEEL) + .renderer(() -> KineticBlockEntityRenderer::new) + .register(); + + public static final BlockEntityEntry CRUSHING_WHEEL_CONTROLLER = + REGISTRATE + .blockEntity("crushing_wheel_controller", CrushingWheelControllerBlockEntity::new) + .validBlocks(AllBlocks.CRUSHING_WHEEL_CONTROLLER) + // .renderer(() -> renderer) + .register(); + + public static final BlockEntityEntry WATER_WHEEL = REGISTRATE + .blockEntity("water_wheel", WaterWheelBlockEntity::new) + .instance(() -> WaterWheelInstance::standard, false) + .validBlocks(AllBlocks.WATER_WHEEL) + .renderer(() -> WaterWheelRenderer::standard) + .register(); + + public static final BlockEntityEntry LARGE_WATER_WHEEL = REGISTRATE + .blockEntity("large_water_wheel", LargeWaterWheelBlockEntity::new) + .instance(() -> WaterWheelInstance::large, false) + .validBlocks(AllBlocks.LARGE_WATER_WHEEL) + .renderer(() -> WaterWheelRenderer::large) + .register(); + + public static final BlockEntityEntry MECHANICAL_PRESS = REGISTRATE + .blockEntity("mechanical_press", MechanicalPressBlockEntity::new) + .instance(() -> PressInstance::new) + .validBlocks(AllBlocks.MECHANICAL_PRESS) + .renderer(() -> MechanicalPressRenderer::new) + .register(); + + public static final BlockEntityEntry MECHANICAL_MIXER = REGISTRATE + .blockEntity("mechanical_mixer", MechanicalMixerBlockEntity::new) + .instance(() -> MixerInstance::new) + .validBlocks(AllBlocks.MECHANICAL_MIXER) + .renderer(() -> MechanicalMixerRenderer::new) + .register(); + + public static final BlockEntityEntry DEPLOYER = REGISTRATE + .blockEntity("deployer", DeployerBlockEntity::new) + .instance(() -> DeployerInstance::new) + .validBlocks(AllBlocks.DEPLOYER) + .renderer(() -> DeployerRenderer::new) + .register(); + + public static final BlockEntityEntry BASIN = REGISTRATE + .blockEntity("basin", BasinBlockEntity::new) + .validBlocks(AllBlocks.BASIN) + .renderer(() -> BasinRenderer::new) + .register(); + + public static final BlockEntityEntry HEATER = REGISTRATE + .blockEntity("blaze_heater", BlazeBurnerBlockEntity::new) + .validBlocks(AllBlocks.BLAZE_BURNER) + .renderer(() -> BlazeBurnerRenderer::new) + .register(); + + public static final BlockEntityEntry MECHANICAL_CRAFTER = REGISTRATE + .blockEntity("mechanical_crafter", MechanicalCrafterBlockEntity::new) + .instance(() -> ShaftlessCogwheelInstance::new) + .validBlocks(AllBlocks.MECHANICAL_CRAFTER) + .renderer(() -> MechanicalCrafterRenderer::new) + .register(); + + public static final BlockEntityEntry SEQUENCED_GEARSHIFT = REGISTRATE + .blockEntity("sequenced_gearshift", SequencedGearshiftBlockEntity::new) + .instance(() -> SplitShaftInstance::new, false) + .validBlocks(AllBlocks.SEQUENCED_GEARSHIFT) + .renderer(() -> SplitShaftRenderer::new) + .register(); + + public static final BlockEntityEntry ROTATION_SPEED_CONTROLLER = REGISTRATE + .blockEntity("rotation_speed_controller", SpeedControllerBlockEntity::new) + .instance(() -> ShaftInstance::new) + .validBlocks(AllBlocks.ROTATION_SPEED_CONTROLLER) + .renderer(() -> SpeedControllerRenderer::new) + .register(); + + public static final BlockEntityEntry SPEEDOMETER = REGISTRATE + .blockEntity("speedometer", SpeedGaugeBlockEntity::new) + .instance(() -> GaugeInstance.Speed::new) + .validBlocks(AllBlocks.SPEEDOMETER) + .renderer(() -> GaugeRenderer::speed) + .register(); + + public static final BlockEntityEntry STRESSOMETER = REGISTRATE + .blockEntity("stressometer", StressGaugeBlockEntity::new) + .instance(() -> GaugeInstance.Stress::new) + .validBlocks(AllBlocks.STRESSOMETER) + .renderer(() -> GaugeRenderer::stress) + .register(); + + public static final BlockEntityEntry ANALOG_LEVER = REGISTRATE + .blockEntity("analog_lever", AnalogLeverBlockEntity::new) + .instance(() -> AnalogLeverInstance::new, false) + .validBlocks(AllBlocks.ANALOG_LEVER) + .renderer(() -> AnalogLeverRenderer::new) + .register(); + + public static final BlockEntityEntry PLACARD = REGISTRATE + .blockEntity("placard", PlacardBlockEntity::new) + .validBlocks(AllBlocks.PLACARD) + .renderer(() -> PlacardRenderer::new) + .register(); + + public static final BlockEntityEntry CART_ASSEMBLER = REGISTRATE + .blockEntity("cart_assembler", CartAssemblerBlockEntity::new) + .validBlocks(AllBlocks.CART_ASSEMBLER) + // .renderer(() -> renderer) + .register(); + + // Logistics + public static final BlockEntityEntry REDSTONE_LINK = REGISTRATE + .blockEntity("redstone_link", RedstoneLinkBlockEntity::new) + .validBlocks(AllBlocks.REDSTONE_LINK) + .renderer(() -> SmartBlockEntityRenderer::new) + .register(); + + public static final BlockEntityEntry NIXIE_TUBE = REGISTRATE + .blockEntity("nixie_tube", NixieTubeBlockEntity::new) + .validBlocks(AllBlocks.ORANGE_NIXIE_TUBE) + .validBlocks(AllBlocks.NIXIE_TUBES.toArray()) + .renderer(() -> NixieTubeRenderer::new) + .onRegister(assignDataBehaviourBE(new NixieTubeDisplayTarget())) + .onRegister(assignDataBehaviourBE(new NixieTubeDisplaySource())) + .register(); + + public static final BlockEntityEntry DISPLAY_LINK = REGISTRATE + .blockEntity("display_link", DisplayLinkBlockEntity::new) + .validBlocks(AllBlocks.DISPLAY_LINK) + .renderer(() -> DisplayLinkRenderer::new) + .register(); + + public static final BlockEntityEntry THRESHOLD_SWITCH = REGISTRATE + .blockEntity("stockpile_switch", ThresholdSwitchBlockEntity::new) + .validBlocks(AllBlocks.THRESHOLD_SWITCH) + .renderer(() -> SmartBlockEntityRenderer::new) + .register(); + + public static final BlockEntityEntry CREATIVE_CRATE = REGISTRATE + .blockEntity("creative_crate", CreativeCrateBlockEntity::new) + .validBlocks(AllBlocks.CREATIVE_CRATE) + .renderer(() -> SmartBlockEntityRenderer::new) + .register(); + + public static final BlockEntityEntry DEPOT = REGISTRATE + .blockEntity("depot", DepotBlockEntity::new) + .validBlocks(AllBlocks.DEPOT) + .renderer(() -> DepotRenderer::new) + .register(); + + public static final BlockEntityEntry WEIGHTED_EJECTOR = REGISTRATE + .blockEntity("weighted_ejector", EjectorBlockEntity::new) + .instance(() -> EjectorInstance::new) + .validBlocks(AllBlocks.WEIGHTED_EJECTOR) + .renderer(() -> EjectorRenderer::new) + .register(); + + public static final BlockEntityEntry FUNNEL = REGISTRATE + .blockEntity("funnel", FunnelBlockEntity::new) + .instance(() -> FunnelInstance::new) + .validBlocks(AllBlocks.BRASS_FUNNEL, AllBlocks.BRASS_BELT_FUNNEL, AllBlocks.ANDESITE_FUNNEL, + AllBlocks.ANDESITE_BELT_FUNNEL) + .renderer(() -> FunnelRenderer::new) + .register(); + + public static final BlockEntityEntry SMART_OBSERVER = REGISTRATE + .blockEntity("content_observer", SmartObserverBlockEntity::new) + .validBlocks(AllBlocks.SMART_OBSERVER) + .renderer(() -> SmartBlockEntityRenderer::new) + .register(); + + public static final BlockEntityEntry PULSE_EXTENDER = REGISTRATE + .blockEntity("pulse_extender", PulseExtenderBlockEntity::new) + .instance(() -> BrassDiodeInstance::new, false) + .validBlocks(AllBlocks.PULSE_EXTENDER) + .renderer(() -> BrassDiodeRenderer::new) + .register(); + + public static final BlockEntityEntry PULSE_REPEATER = REGISTRATE + .blockEntity("pulse_repeater", PulseRepeaterBlockEntity::new) + .instance(() -> BrassDiodeInstance::new, false) + .validBlocks(AllBlocks.PULSE_REPEATER) + .renderer(() -> BrassDiodeRenderer::new) + .register(); + + public static final BlockEntityEntry LECTERN_CONTROLLER = REGISTRATE + .blockEntity("lectern_controller", LecternControllerBlockEntity::new) + .validBlocks(AllBlocks.LECTERN_CONTROLLER) + .renderer(() -> LecternControllerRenderer::new) + .register(); + + // Curiosities + public static final BlockEntityEntry BACKTANK = REGISTRATE + .blockEntity("backtank", BacktankBlockEntity::new) + .instance(() -> BacktankInstance::new) + .validBlocks(AllBlocks.COPPER_BACKTANK, AllBlocks.NETHERITE_BACKTANK) + .renderer(() -> BacktankRenderer::new) + .register(); + + public static final BlockEntityEntry PECULIAR_BELL = REGISTRATE + .blockEntity("peculiar_bell", PeculiarBellBlockEntity::new) + .validBlocks(AllBlocks.PECULIAR_BELL) + .renderer(() -> BellRenderer::new) + .register(); + + public static final BlockEntityEntry HAUNTED_BELL = REGISTRATE + .blockEntity("cursed_bell", HauntedBellBlockEntity::new) + .validBlocks(AllBlocks.HAUNTED_BELL) + .renderer(() -> BellRenderer::new) + .register(); + + public static final BlockEntityEntry TOOLBOX = REGISTRATE + .blockEntity("toolbox", ToolboxBlockEntity::new) + .instance(() -> ToolBoxInstance::new, false) + .validBlocks(AllBlocks.TOOLBOXES.toArray()) + .renderer(() -> ToolboxRenderer::new) + .register(); + + public static final BlockEntityEntry TRACK = REGISTRATE + .blockEntity("track", TrackBlockEntity::new) + .instance(() -> TrackInstance::new) + .validBlocksDeferred(TrackMaterial::allBlocks) + .renderer(() -> TrackRenderer::new) + .register(); + + public static final BlockEntityEntry FAKE_TRACK = REGISTRATE + .blockEntity("fake_track", FakeTrackBlockEntity::new) + .validBlocks(AllBlocks.FAKE_TRACK) + .register(); + + public static final BlockEntityEntry BOGEY = REGISTRATE + .blockEntity("bogey", StandardBogeyBlockEntity::new) + .renderer(() -> BogeyBlockEntityRenderer::new) + .validBlocks(AllBlocks.SMALL_BOGEY, AllBlocks.LARGE_BOGEY) + .register(); + + public static final BlockEntityEntry TRACK_STATION = REGISTRATE + .blockEntity("track_station", StationBlockEntity::new) + .renderer(() -> StationRenderer::new) + .validBlocks(AllBlocks.TRACK_STATION) + .register(); + + public static final BlockEntityEntry SLIDING_DOOR = + REGISTRATE.blockEntity("sliding_door", SlidingDoorBlockEntity::new) + .renderer(() -> SlidingDoorRenderer::new) + .validBlocks(AllBlocks.TRAIN_DOOR, AllBlocks.FRAMED_GLASS_DOOR, AllBlocks.ANDESITE_DOOR, + AllBlocks.BRASS_DOOR, AllBlocks.COPPER_DOOR) + .register(); + + public static final BlockEntityEntry COPYCAT = + REGISTRATE.blockEntity("copycat", CopycatBlockEntity::new) + .validBlocks(AllBlocks.COPYCAT_PANEL, AllBlocks.COPYCAT_STEP) + .register(); + + public static final BlockEntityEntry FLAP_DISPLAY = REGISTRATE + .blockEntity("flap_display", FlapDisplayBlockEntity::new) + .instance(() -> ShaftlessCogwheelInstance::new) + .renderer(() -> FlapDisplayRenderer::new) + .validBlocks(AllBlocks.DISPLAY_BOARD) + .register(); + + public static final BlockEntityEntry TRACK_SIGNAL = REGISTRATE + .blockEntity("track_signal", SignalBlockEntity::new) + .renderer(() -> SignalRenderer::new) + .validBlocks(AllBlocks.TRACK_SIGNAL) + .register(); + + public static final BlockEntityEntry TRACK_OBSERVER = REGISTRATE + .blockEntity("track_observer", TrackObserverBlockEntity::new) + .renderer(() -> TrackObserverRenderer::new) + .validBlocks(AllBlocks.TRACK_OBSERVER) + .register(); + + public static final BlockEntityEntry CLIPBOARD = REGISTRATE + .blockEntity("clipboard", ClipboardBlockEntity::new) + .validBlocks(AllBlocks.CLIPBOARD) + .register(); + + public static void register() {} +} diff --git a/src/main/java/com/simibubi/create/AllBlockPartials.java b/src/main/java/com/simibubi/create/AllBlockPartials.java deleted file mode 100644 index 88443bdc2..000000000 --- a/src/main/java/com/simibubi/create/AllBlockPartials.java +++ /dev/null @@ -1,197 +0,0 @@ -package com.simibubi.create; - -import java.util.EnumMap; -import java.util.HashMap; -import java.util.Map; - -import com.jozufozu.flywheel.core.PartialModel; -import com.simibubi.create.content.contraptions.fluids.FluidTransportBehaviour; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Lang; - -import net.minecraft.core.Direction; -import net.minecraft.world.item.DyeColor; - -public class AllBlockPartials { - - public static final PartialModel - - SCHEMATICANNON_CONNECTOR = block("schematicannon/connector"), SCHEMATICANNON_PIPE = block("schematicannon/pipe"), - - SHAFTLESS_COGWHEEL = block("cogwheel_shaftless"), SHAFTLESS_LARGE_COGWHEEL = block("large_cogwheel_shaftless"), - COGWHEEL_SHAFT = block("cogwheel_shaft"), SHAFT_HALF = block("shaft_half"), - - BELT_PULLEY = block("belt_pulley"), BELT_START = block("belt/start"), BELT_MIDDLE = block("belt/middle"), - BELT_END = block("belt/end"), BELT_START_BOTTOM = block("belt/start_bottom"), - BELT_MIDDLE_BOTTOM = block("belt/middle_bottom"), BELT_END_BOTTOM = block("belt/end_bottom"), - BELT_DIAGONAL_START = block("belt/diagonal_start"), BELT_DIAGONAL_MIDDLE = block("belt/diagonal_middle"), - BELT_DIAGONAL_END = block("belt/diagonal_end"), - - ENCASED_FAN_INNER = block("encased_fan/propeller"), HAND_CRANK_HANDLE = block("hand_crank/handle"), - MECHANICAL_PRESS_HEAD = block("mechanical_press/head"), MECHANICAL_MIXER_POLE = block("mechanical_mixer/pole"), - MECHANICAL_MIXER_HEAD = block("mechanical_mixer/head"), - MECHANICAL_CRAFTER_LID = block("mechanical_crafter/lid"), - MECHANICAL_CRAFTER_ARROW = block("mechanical_crafter/arrow"), - MECHANICAL_CRAFTER_BELT_FRAME = block("mechanical_crafter/belt"), - MECHANICAL_CRAFTER_BELT = block("mechanical_crafter/belt_animated"), - SAW_BLADE_HORIZONTAL_ACTIVE = block("mechanical_saw/blade_horizontal_active"), - SAW_BLADE_HORIZONTAL_INACTIVE = block("mechanical_saw/blade_horizontal_inactive"), - SAW_BLADE_HORIZONTAL_REVERSED = block("mechanical_saw/blade_horizontal_reversed"), - SAW_BLADE_VERTICAL_ACTIVE = block("mechanical_saw/blade_vertical_active"), - SAW_BLADE_VERTICAL_INACTIVE = block("mechanical_saw/blade_vertical_inactive"), - SAW_BLADE_VERTICAL_REVERSED = block("mechanical_saw/blade_vertical_reversed"), GAUGE_DIAL = block("gauge/dial"), - GAUGE_INDICATOR = block("gauge/indicator"), GAUGE_HEAD_SPEED = block("gauge/speedometer/head"), - GAUGE_HEAD_STRESS = block("gauge/stressometer/head"), BEARING_TOP = block("bearing/top"), - BEARING_TOP_WOODEN = block("bearing/top_wooden"), DRILL_HEAD = block("mechanical_drill/head"), - HARVESTER_BLADE = block("mechanical_harvester/blade"), DEPLOYER_POLE = block("deployer/pole"), - DEPLOYER_HAND_POINTING = block("deployer/hand_pointing"), - DEPLOYER_HAND_PUNCHING = block("deployer/hand_punching"), - DEPLOYER_HAND_HOLDING = block("deployer/hand_holding"), ANALOG_LEVER_HANDLE = block("analog_lever/handle"), - ANALOG_LEVER_INDICATOR = block("analog_lever/indicator"), FUNNEL_FLAP = block("funnel/flap"), - BELT_FUNNEL_FLAP = block("belt_funnel/flap"), BELT_TUNNEL_FLAP = block("belt_tunnel/flap"), - FLEXPEATER_INDICATOR = block("diodes/indicator"), - - CUCKOO_MINUTE_HAND = block("cuckoo_clock/minute_hand"), CUCKOO_HOUR_HAND = block("cuckoo_clock/hour_hand"), - CUCKOO_LEFT_DOOR = block("cuckoo_clock/left_door"), CUCKOO_RIGHT_DOOR = block("cuckoo_clock/right_door"), - CUCKOO_PIG = block("cuckoo_clock/pig"), CUCKOO_CREEPER = block("cuckoo_clock/creeper"), - - GANTRY_COGS = block("gantry_carriage/wheels"), - - ROPE_COIL = block("rope_pulley/rope_coil"), ROPE_HALF = block("rope_pulley/rope_half"), - ROPE_HALF_MAGNET = block("rope_pulley/rope_half_magnet"), - - HOSE_COIL = block("hose_pulley/rope_coil"), HOSE = block("hose_pulley/rope"), - HOSE_MAGNET = block("hose_pulley/pulley_magnet"), HOSE_HALF = block("hose_pulley/rope_half"), - HOSE_HALF_MAGNET = block("hose_pulley/rope_half_magnet"), - - MILLSTONE_COG = block("millstone/inner"), - - SYMMETRY_PLANE = block("symmetry_effect/plane"), SYMMETRY_CROSSPLANE = block("symmetry_effect/crossplane"), - SYMMETRY_TRIPLEPLANE = block("symmetry_effect/tripleplane"), - - STICKER_HEAD = block("sticker/head"), - - PORTABLE_STORAGE_INTERFACE_MIDDLE = block("portable_storage_interface/block_middle"), - PORTABLE_STORAGE_INTERFACE_MIDDLE_POWERED = block("portable_storage_interface/block_middle_powered"), - PORTABLE_STORAGE_INTERFACE_TOP = block("portable_storage_interface/block_top"), - - PORTABLE_FLUID_INTERFACE_MIDDLE = block("portable_fluid_interface/block_middle"), - PORTABLE_FLUID_INTERFACE_MIDDLE_POWERED = block("portable_fluid_interface/block_middle_powered"), - PORTABLE_FLUID_INTERFACE_TOP = block("portable_fluid_interface/block_top"), - - ARM_COG = block("mechanical_arm/cog"), ARM_BASE = block("mechanical_arm/base"), - ARM_LOWER_BODY = block("mechanical_arm/lower_body"), ARM_UPPER_BODY = block("mechanical_arm/upper_body"), - ARM_HEAD = block("mechanical_arm/head"), ARM_CLAW_BASE = block("mechanical_arm/claw_base"), - ARM_CLAW_GRIP = block("mechanical_arm/claw_grip"), - - MECHANICAL_PUMP_ARROW = block("mechanical_pump/arrow"), MECHANICAL_PUMP_COG = block("mechanical_pump/cog"), - FLUID_PIPE_CASING = block("fluid_pipe/casing"), FLUID_VALVE_POINTER = block("fluid_valve/pointer"), - - SPOUT_TOP = block("spout/top"), SPOUT_MIDDLE = block("spout/middle"), SPOUT_BOTTOM = block("spout/bottom"), - - PECULIAR_BELL = block("peculiar_bell"), HAUNTED_BELL = block("haunted_bell"), - - TOOLBOX_DRAWER = block("toolbox/drawer"), - - SPEED_CONTROLLER_BRACKET = block("rotation_speed_controller/bracket"), - - GOGGLES = block("goggles"), - - EJECTOR_TOP = block("weighted_ejector/top"), - - COPPER_BACKTANK_SHAFT = block("copper_backtank/block_shaft_input"), - COPPER_BACKTANK_COGS = block("copper_backtank/block_cogs"), - - TRACK_SEGMENT_LEFT = block("track/segment_left"), TRACK_SEGMENT_RIGHT = block("track/segment_right"), - TRACK_TIE = block("track/tie"), GIRDER_SEGMENT_TOP = block("metal_girder/segment_top"), - GIRDER_SEGMENT_MIDDLE = block("metal_girder/segment_middle"), - GIRDER_SEGMENT_BOTTOM = block("metal_girder/segment_bottom"), - - TRACK_STATION_OVERLAY = block("track_overlay/station"), TRACK_SIGNAL_OVERLAY = block("track_overlay/signal"), - TRACK_ASSEMBLING_OVERLAY = block("track_overlay/assembling"), - TRACK_SIGNAL_DUAL_OVERLAY = block("track_overlay/signal_dual"), - TRACK_OBSERVER_OVERLAY = block("track_overlay/observer"), - - BOGEY_FRAME = block("track/bogey/bogey_frame"), SMALL_BOGEY_WHEELS = block("track/bogey/bogey_wheel"), - BOGEY_PIN = block("track/bogey/bogey_drive_wheel_pin"), BOGEY_PISTON = block("track/bogey/bogey_drive_piston"), - BOGEY_DRIVE = block("track/bogey/bogey_drive"), LARGE_BOGEY_WHEELS = block("track/bogey/bogey_drive_wheel"), - - TRAIN_COUPLING_HEAD = block("track/bogey/coupling_head"), - TRAIN_COUPLING_CABLE = block("track/bogey/coupling_cable"), - - TRAIN_CONTROLS_COVER = block("controls/train/cover"), TRAIN_CONTROLS_LEVER = block("controls/train/lever"), - - ENGINE_PISTON = block("steam_engine/piston"), ENGINE_LINKAGE = block("steam_engine/linkage"), - ENGINE_CONNECTOR = block("steam_engine/shaft_connector"), BOILER_GAUGE = block("steam_engine/gauge"), - BOILER_GAUGE_DIAL = block("steam_engine/gauge_dial"), - - SIGNAL_ON = block("track_signal/indicator_on"), SIGNAL_OFF = block("track_signal/indicator_off"), - DISPLAY_LINK_TUBE = block("display_link/tube"), DISPLAY_LINK_GLOW = block("display_link/glow"), - - STATION_ON = block("track_station/flag_on"), STATION_OFF = block("track_station/flag_off"), - STATION_ASSEMBLE = block("track_station/flag_assemble"), - - SIGNAL_PANEL = block("track_signal/panel"), SIGNAL_WHITE_CUBE = block("track_signal/white_cube"), - SIGNAL_WHITE_GLOW = block("track_signal/white_glow"), SIGNAL_WHITE = block("track_signal/white_tube"), - SIGNAL_RED_CUBE = block("track_signal/red_cube"), SIGNAL_RED_GLOW = block("track_signal/red_glow"), - SIGNAL_RED = block("track_signal/red_tube"), SIGNAL_YELLOW_CUBE = block("track_signal/yellow_cube"), - SIGNAL_YELLOW_GLOW = block("track_signal/yellow_glow"), SIGNAL_YELLOW = block("track_signal/yellow_tube"), - - BLAZE_INERT = block("blaze_burner/blaze/inert"), BLAZE_SUPER_ACTIVE = block("blaze_burner/blaze/super_active"), - BLAZE_GOGGLES = block("blaze_burner/goggles"), BLAZE_GOGGLES_SMALL = block("blaze_burner/goggles_small"), - BLAZE_IDLE = block("blaze_burner/blaze/idle"), BLAZE_ACTIVE = block("blaze_burner/blaze/active"), - BLAZE_SUPER = block("blaze_burner/blaze/super"), BLAZE_BURNER_FLAME = block("blaze_burner/flame"), - BLAZE_BURNER_RODS = block("blaze_burner/rods_small"), - BLAZE_BURNER_RODS_2 = block("blaze_burner/rods_large"), - BLAZE_BURNER_SUPER_RODS = block("blaze_burner/superheated_rods_small"), - BLAZE_BURNER_SUPER_RODS_2 = block("blaze_burner/superheated_rods_large"), - - WHISTLE_MOUTH_LARGE = block("steam_whistle/large_mouth"), - WHISTLE_MOUTH_MEDIUM = block("steam_whistle/medium_mouth"), - WHISTLE_MOUTH_SMALL = block("steam_whistle/small_mouth"), - - CRAFTING_BLUEPRINT_1x1 = entity("crafting_blueprint_small"), - CRAFTING_BLUEPRINT_2x2 = entity("crafting_blueprint_medium"), - CRAFTING_BLUEPRINT_3x3 = entity("crafting_blueprint_large"), - - TRAIN_HAT = entity("train_hat"), - - COUPLING_ATTACHMENT = entity("minecart_coupling/attachment"), COUPLING_RING = entity("minecart_coupling/ring"), - COUPLING_CONNECTOR = entity("minecart_coupling/connector") - - ; - - public static final Map> PIPE_ATTACHMENTS = - new EnumMap<>(FluidTransportBehaviour.AttachmentTypes.ComponentPartials.class); - - public static final Map METAL_GIRDER_BRACKETS = new EnumMap<>(Direction.class); - public static final Map TOOLBOX_LIDS = new EnumMap<>(DyeColor.class); - - static { - for (FluidTransportBehaviour.AttachmentTypes.ComponentPartials type : FluidTransportBehaviour.AttachmentTypes.ComponentPartials.values()) { - Map map = new HashMap<>(); - for (Direction d : Iterate.directions) { - String asId = Lang.asId(type.name()); - map.put(d, block("fluid_pipe/" + asId + "/" + Lang.asId(d.getSerializedName()))); - } - PIPE_ATTACHMENTS.put(type, map); - } - for (DyeColor color : DyeColor.values()) - TOOLBOX_LIDS.put(color, block("toolbox/lid/" + Lang.asId(color.name()))); - for (Direction d : Iterate.horizontalDirections) - METAL_GIRDER_BRACKETS.put(d, block("metal_girder/bracket_" + Lang.asId(d.name()))); - } - - private static PartialModel block(String path) { - return new PartialModel(Create.asResource("block/" + path)); - } - - private static PartialModel entity(String path) { - return new PartialModel(Create.asResource("entity/" + path)); - } - - public static void init() { - // init static fields - } - -} diff --git a/src/main/java/com/simibubi/create/AllBlocks.java b/src/main/java/com/simibubi/create/AllBlocks.java index 75becdcbd..8906813e0 100644 --- a/src/main/java/com/simibubi/create/AllBlocks.java +++ b/src/main/java/com/simibubi/create/AllBlocks.java @@ -3,8 +3,7 @@ package com.simibubi.create; import static com.simibubi.create.AllInteractionBehaviours.interactionBehaviour; import static com.simibubi.create.AllMovementBehaviours.movementBehaviour; import static com.simibubi.create.Create.REGISTRATE; -import static com.simibubi.create.content.AllSections.SCHEMATICS; -import static com.simibubi.create.content.logistics.block.display.AllDisplayBehaviours.assignDataBehaviour; +import static com.simibubi.create.content.redstone.displayLink.AllDisplayBehaviours.assignDataBehaviour; import static com.simibubi.create.foundation.data.BlockStateGen.axisBlock; import static com.simibubi.create.foundation.data.BlockStateGen.simpleCubeAll; import static com.simibubi.create.foundation.data.CreateRegistrate.connectedTextures; @@ -16,221 +15,251 @@ import static com.simibubi.create.foundation.data.TagGen.tagBlockAndItem; import com.simibubi.create.AllTags.AllBlockTags; import com.simibubi.create.AllTags.AllItemTags; -import com.simibubi.create.content.AllSections; -import com.simibubi.create.content.contraptions.base.CasingBlock; -import com.simibubi.create.content.contraptions.components.AssemblyOperatorBlockItem; -import com.simibubi.create.content.contraptions.components.actors.BellMovementBehaviour; -import com.simibubi.create.content.contraptions.components.actors.DrillBlock; -import com.simibubi.create.content.contraptions.components.actors.DrillMovementBehaviour; -import com.simibubi.create.content.contraptions.components.actors.HarvesterBlock; -import com.simibubi.create.content.contraptions.components.actors.HarvesterMovementBehaviour; -import com.simibubi.create.content.contraptions.components.actors.PloughBlock; -import com.simibubi.create.content.contraptions.components.actors.PloughMovementBehaviour; -import com.simibubi.create.content.contraptions.components.actors.PortableStorageInterfaceBlock; -import com.simibubi.create.content.contraptions.components.actors.PortableStorageInterfaceMovement; -import com.simibubi.create.content.contraptions.components.actors.SawMovementBehaviour; -import com.simibubi.create.content.contraptions.components.actors.SeatBlock; -import com.simibubi.create.content.contraptions.components.actors.SeatInteractionBehaviour; -import com.simibubi.create.content.contraptions.components.actors.SeatMovementBehaviour; -import com.simibubi.create.content.contraptions.components.clock.CuckooClockBlock; -import com.simibubi.create.content.contraptions.components.crafter.CrafterCTBehaviour; -import com.simibubi.create.content.contraptions.components.crafter.MechanicalCrafterBlock; -import com.simibubi.create.content.contraptions.components.crank.HandCrankBlock; -import com.simibubi.create.content.contraptions.components.crank.ValveHandleBlock; -import com.simibubi.create.content.contraptions.components.crusher.CrushingWheelBlock; -import com.simibubi.create.content.contraptions.components.crusher.CrushingWheelControllerBlock; -import com.simibubi.create.content.contraptions.components.deployer.DeployerBlock; -import com.simibubi.create.content.contraptions.components.deployer.DeployerMovementBehaviour; -import com.simibubi.create.content.contraptions.components.deployer.DeployerMovingInteraction; -import com.simibubi.create.content.contraptions.components.fan.EncasedFanBlock; -import com.simibubi.create.content.contraptions.components.fan.NozzleBlock; -import com.simibubi.create.content.contraptions.components.flywheel.FlywheelBlock; -import com.simibubi.create.content.contraptions.components.millstone.MillstoneBlock; -import com.simibubi.create.content.contraptions.components.mixer.MechanicalMixerBlock; -import com.simibubi.create.content.contraptions.components.motor.CreativeMotorBlock; -import com.simibubi.create.content.contraptions.components.motor.CreativeMotorGenerator; -import com.simibubi.create.content.contraptions.components.press.MechanicalPressBlock; -import com.simibubi.create.content.contraptions.components.saw.SawBlock; -import com.simibubi.create.content.contraptions.components.saw.SawGenerator; -import com.simibubi.create.content.contraptions.components.steam.PoweredShaftBlock; -import com.simibubi.create.content.contraptions.components.steam.SteamEngineBlock; -import com.simibubi.create.content.contraptions.components.steam.whistle.WhistleBlock; -import com.simibubi.create.content.contraptions.components.steam.whistle.WhistleExtenderBlock; -import com.simibubi.create.content.contraptions.components.steam.whistle.WhistleGenerator; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.BlankSailBlockItem; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.ClockworkBearingBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.MechanicalBearingBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.SailBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.StabilizedBearingMovementBehaviour; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.WindmillBearingBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.chassis.LinearChassisBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.chassis.LinearChassisBlock.ChassisCTBehaviour; -import com.simibubi.create.content.contraptions.components.structureMovement.chassis.RadialChassisBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.chassis.StickerBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.gantry.GantryCarriageBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsInteractionBehaviour; -import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsMovementBehaviour; -import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerBlock.MinecartAnchorBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerBlockItem; -import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonHeadBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.piston.PistonExtensionPoleBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyBlock; -import com.simibubi.create.content.contraptions.components.tracks.ControllerRailBlock; -import com.simibubi.create.content.contraptions.components.tracks.ControllerRailGenerator; -import com.simibubi.create.content.contraptions.components.turntable.TurntableBlock; -import com.simibubi.create.content.contraptions.components.waterwheel.WaterWheelBlock; -import com.simibubi.create.content.contraptions.fluids.PipeAttachmentModel; -import com.simibubi.create.content.contraptions.fluids.PumpBlock; -import com.simibubi.create.content.contraptions.fluids.actors.HosePulleyBlock; -import com.simibubi.create.content.contraptions.fluids.actors.ItemDrainBlock; -import com.simibubi.create.content.contraptions.fluids.actors.SpoutBlock; -import com.simibubi.create.content.contraptions.fluids.pipes.BracketBlock; -import com.simibubi.create.content.contraptions.fluids.pipes.BracketBlockItem; -import com.simibubi.create.content.contraptions.fluids.pipes.BracketGenerator; -import com.simibubi.create.content.contraptions.fluids.pipes.EncasedPipeBlock; -import com.simibubi.create.content.contraptions.fluids.pipes.FluidPipeBlock; -import com.simibubi.create.content.contraptions.fluids.pipes.FluidValveBlock; -import com.simibubi.create.content.contraptions.fluids.pipes.GlassFluidPipeBlock; -import com.simibubi.create.content.contraptions.fluids.pipes.SmartFluidPipeBlock; -import com.simibubi.create.content.contraptions.fluids.pipes.SmartFluidPipeGenerator; -import com.simibubi.create.content.contraptions.fluids.tank.FluidTankBlock; -import com.simibubi.create.content.contraptions.fluids.tank.FluidTankGenerator; -import com.simibubi.create.content.contraptions.fluids.tank.FluidTankItem; -import com.simibubi.create.content.contraptions.fluids.tank.FluidTankModel; -import com.simibubi.create.content.contraptions.processing.BasinBlock; -import com.simibubi.create.content.contraptions.processing.BasinGenerator; -import com.simibubi.create.content.contraptions.processing.BasinMovementBehaviour; -import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock; -import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlockItem; -import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerInteractionBehaviour; -import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerMovementBehaviour; -import com.simibubi.create.content.contraptions.processing.burner.LitBlazeBurnerBlock; -import com.simibubi.create.content.contraptions.relays.advanced.GantryShaftBlock; -import com.simibubi.create.content.contraptions.relays.advanced.SpeedControllerBlock; -import com.simibubi.create.content.contraptions.relays.advanced.sequencer.SequencedGearshiftBlock; -import com.simibubi.create.content.contraptions.relays.advanced.sequencer.SequencedGearshiftGenerator; -import com.simibubi.create.content.contraptions.relays.belt.BeltBlock; -import com.simibubi.create.content.contraptions.relays.belt.BeltGenerator; -import com.simibubi.create.content.contraptions.relays.belt.BeltModel; -import com.simibubi.create.content.contraptions.relays.elementary.BracketedKineticBlockModel; -import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock; -import com.simibubi.create.content.contraptions.relays.elementary.CogwheelBlockItem; -import com.simibubi.create.content.contraptions.relays.elementary.EncasingRegistry; -import com.simibubi.create.content.contraptions.relays.elementary.ShaftBlock; -import com.simibubi.create.content.contraptions.relays.encased.AdjustablePulleyBlock; -import com.simibubi.create.content.contraptions.relays.encased.ClutchBlock; -import com.simibubi.create.content.contraptions.relays.encased.EncasedBeltBlock; -import com.simibubi.create.content.contraptions.relays.encased.EncasedBeltGenerator; -import com.simibubi.create.content.contraptions.relays.encased.EncasedCTBehaviour; -import com.simibubi.create.content.contraptions.relays.encased.EncasedCogCTBehaviour; -import com.simibubi.create.content.contraptions.relays.encased.EncasedCogwheelBlock; -import com.simibubi.create.content.contraptions.relays.encased.EncasedShaftBlock; -import com.simibubi.create.content.contraptions.relays.encased.GearshiftBlock; -import com.simibubi.create.content.contraptions.relays.gauge.GaugeBlock; -import com.simibubi.create.content.contraptions.relays.gauge.GaugeGenerator; -import com.simibubi.create.content.contraptions.relays.gearbox.GearboxBlock; -import com.simibubi.create.content.curiosities.armor.CopperBacktankBlock; -import com.simibubi.create.content.curiosities.bell.HauntedBellBlock; -import com.simibubi.create.content.curiosities.bell.HauntedBellMovementBehaviour; -import com.simibubi.create.content.curiosities.bell.PeculiarBellBlock; -import com.simibubi.create.content.curiosities.deco.MetalLadderBlock; -import com.simibubi.create.content.curiosities.deco.PlacardBlock; -import com.simibubi.create.content.curiosities.deco.SlidingDoorBlock; -import com.simibubi.create.content.curiosities.deco.TrainTrapdoorBlock; -import com.simibubi.create.content.curiosities.deco.TrapdoorCTBehaviour; -import com.simibubi.create.content.curiosities.girder.ConnectedGirderModel; -import com.simibubi.create.content.curiosities.girder.GirderBlock; -import com.simibubi.create.content.curiosities.girder.GirderBlockStateGenerator; -import com.simibubi.create.content.curiosities.girder.GirderEncasedShaftBlock; -import com.simibubi.create.content.curiosities.toolbox.ToolboxBlock; -import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelBlock; -import com.simibubi.create.content.logistics.block.belts.tunnel.BrassTunnelBlock; -import com.simibubi.create.content.logistics.block.belts.tunnel.BrassTunnelCTBehaviour; -import com.simibubi.create.content.logistics.block.chute.ChuteBlock; -import com.simibubi.create.content.logistics.block.chute.ChuteGenerator; -import com.simibubi.create.content.logistics.block.chute.ChuteItem; -import com.simibubi.create.content.logistics.block.chute.SmartChuteBlock; -import com.simibubi.create.content.logistics.block.depot.DepotBlock; -import com.simibubi.create.content.logistics.block.depot.EjectorBlock; -import com.simibubi.create.content.logistics.block.depot.EjectorItem; -import com.simibubi.create.content.logistics.block.diodes.AbstractDiodeGenerator; -import com.simibubi.create.content.logistics.block.diodes.BrassDiodeBlock; -import com.simibubi.create.content.logistics.block.diodes.BrassDiodeGenerator; -import com.simibubi.create.content.logistics.block.diodes.PoweredLatchBlock; -import com.simibubi.create.content.logistics.block.diodes.PoweredLatchGenerator; -import com.simibubi.create.content.logistics.block.diodes.ToggleLatchBlock; -import com.simibubi.create.content.logistics.block.diodes.ToggleLatchGenerator; -import com.simibubi.create.content.logistics.block.display.DisplayLinkBlock; -import com.simibubi.create.content.logistics.block.display.DisplayLinkBlockItem; -import com.simibubi.create.content.logistics.block.display.source.AccumulatedItemCountDisplaySource; -import com.simibubi.create.content.logistics.block.display.source.BoilerDisplaySource; -import com.simibubi.create.content.logistics.block.display.source.EntityNameDisplaySource; -import com.simibubi.create.content.logistics.block.display.source.FillLevelDisplaySource; -import com.simibubi.create.content.logistics.block.display.source.FluidAmountDisplaySource; -import com.simibubi.create.content.logistics.block.display.source.FluidListDisplaySource; -import com.simibubi.create.content.logistics.block.display.source.ItemCountDisplaySource; -import com.simibubi.create.content.logistics.block.display.source.ItemListDisplaySource; -import com.simibubi.create.content.logistics.block.display.source.ItemNameDisplaySource; -import com.simibubi.create.content.logistics.block.display.source.ItemThroughputDisplaySource; -import com.simibubi.create.content.logistics.block.display.source.KineticSpeedDisplaySource; -import com.simibubi.create.content.logistics.block.display.source.KineticStressDisplaySource; -import com.simibubi.create.content.logistics.block.display.source.ObservedTrainNameSource; -import com.simibubi.create.content.logistics.block.display.source.StationSummaryDisplaySource; -import com.simibubi.create.content.logistics.block.display.source.StopWatchDisplaySource; -import com.simibubi.create.content.logistics.block.display.source.TimeOfDayDisplaySource; -import com.simibubi.create.content.logistics.block.display.source.TrainStatusDisplaySource; -import com.simibubi.create.content.logistics.block.display.target.DisplayBoardTarget; -import com.simibubi.create.content.logistics.block.funnel.AndesiteFunnelBlock; -import com.simibubi.create.content.logistics.block.funnel.BeltFunnelBlock; -import com.simibubi.create.content.logistics.block.funnel.BeltFunnelGenerator; -import com.simibubi.create.content.logistics.block.funnel.BrassFunnelBlock; -import com.simibubi.create.content.logistics.block.funnel.FunnelGenerator; -import com.simibubi.create.content.logistics.block.funnel.FunnelItem; -import com.simibubi.create.content.logistics.block.funnel.FunnelMovementBehaviour; -import com.simibubi.create.content.logistics.block.inventories.CreativeCrateBlock; -import com.simibubi.create.content.logistics.block.mechanicalArm.ArmBlock; -import com.simibubi.create.content.logistics.block.mechanicalArm.ArmItem; -import com.simibubi.create.content.logistics.block.redstone.AnalogLeverBlock; -import com.simibubi.create.content.logistics.block.redstone.ContactMovementBehaviour; -import com.simibubi.create.content.logistics.block.redstone.ContentObserverBlock; -import com.simibubi.create.content.logistics.block.redstone.NixieTubeBlock; -import com.simibubi.create.content.logistics.block.redstone.NixieTubeGenerator; -import com.simibubi.create.content.logistics.block.redstone.RedstoneContactBlock; -import com.simibubi.create.content.logistics.block.redstone.RedstoneLinkBlock; -import com.simibubi.create.content.logistics.block.redstone.RedstoneLinkGenerator; -import com.simibubi.create.content.logistics.block.redstone.RoseQuartzLampBlock; -import com.simibubi.create.content.logistics.block.redstone.StockpileSwitchBlock; -import com.simibubi.create.content.logistics.block.vault.ItemVaultBlock; -import com.simibubi.create.content.logistics.block.vault.ItemVaultCTBehaviour; -import com.simibubi.create.content.logistics.block.vault.ItemVaultItem; -import com.simibubi.create.content.logistics.item.LecternControllerBlock; -import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayBlock; -import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType; -import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBlockItem; -import com.simibubi.create.content.logistics.trains.management.edgePoint.observer.TrackObserverBlock; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalBlock; -import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationBlock; -import com.simibubi.create.content.logistics.trains.track.FakeTrackBlock; -import com.simibubi.create.content.logistics.trains.track.StandardBogeyBlock; -import com.simibubi.create.content.logistics.trains.track.TrackBlock; -import com.simibubi.create.content.logistics.trains.track.TrackBlockItem; -import com.simibubi.create.content.logistics.trains.track.TrackBlockStateGenerator; -import com.simibubi.create.content.schematics.block.SchematicTableBlock; -import com.simibubi.create.content.schematics.block.SchematicannonBlock; -import com.simibubi.create.foundation.block.BlockStressDefaults; +import com.simibubi.create.content.contraptions.actors.contraptionControls.ContraptionControlsBlock; +import com.simibubi.create.content.contraptions.actors.contraptionControls.ContraptionControlsMovement; +import com.simibubi.create.content.contraptions.actors.contraptionControls.ContraptionControlsMovingInteraction; +import com.simibubi.create.content.contraptions.actors.harvester.HarvesterBlock; +import com.simibubi.create.content.contraptions.actors.harvester.HarvesterMovementBehaviour; +import com.simibubi.create.content.contraptions.actors.plough.PloughBlock; +import com.simibubi.create.content.contraptions.actors.plough.PloughMovementBehaviour; +import com.simibubi.create.content.contraptions.actors.psi.PortableStorageInterfaceBlock; +import com.simibubi.create.content.contraptions.actors.psi.PortableStorageInterfaceMovement; +import com.simibubi.create.content.contraptions.actors.roller.RollerBlock; +import com.simibubi.create.content.contraptions.actors.roller.RollerBlockItem; +import com.simibubi.create.content.contraptions.actors.roller.RollerMovementBehaviour; +import com.simibubi.create.content.contraptions.actors.seat.SeatBlock; +import com.simibubi.create.content.contraptions.actors.seat.SeatInteractionBehaviour; +import com.simibubi.create.content.contraptions.actors.seat.SeatMovementBehaviour; +import com.simibubi.create.content.contraptions.actors.trainControls.ControlsBlock; +import com.simibubi.create.content.contraptions.actors.trainControls.ControlsInteractionBehaviour; +import com.simibubi.create.content.contraptions.actors.trainControls.ControlsMovementBehaviour; +import com.simibubi.create.content.contraptions.bearing.BlankSailBlockItem; +import com.simibubi.create.content.contraptions.bearing.ClockworkBearingBlock; +import com.simibubi.create.content.contraptions.bearing.MechanicalBearingBlock; +import com.simibubi.create.content.contraptions.bearing.SailBlock; +import com.simibubi.create.content.contraptions.bearing.StabilizedBearingMovementBehaviour; +import com.simibubi.create.content.contraptions.bearing.WindmillBearingBlock; +import com.simibubi.create.content.contraptions.behaviour.BellMovementBehaviour; +import com.simibubi.create.content.contraptions.chassis.LinearChassisBlock; +import com.simibubi.create.content.contraptions.chassis.LinearChassisBlock.ChassisCTBehaviour; +import com.simibubi.create.content.contraptions.chassis.RadialChassisBlock; +import com.simibubi.create.content.contraptions.chassis.StickerBlock; +import com.simibubi.create.content.contraptions.elevator.ElevatorContactBlock; +import com.simibubi.create.content.contraptions.elevator.ElevatorPulleyBlock; +import com.simibubi.create.content.contraptions.gantry.GantryCarriageBlock; +import com.simibubi.create.content.contraptions.mounted.CartAssemblerBlock; +import com.simibubi.create.content.contraptions.mounted.CartAssemblerBlock.MinecartAnchorBlock; +import com.simibubi.create.content.contraptions.mounted.CartAssemblerBlockItem; +import com.simibubi.create.content.contraptions.piston.MechanicalPistonBlock; +import com.simibubi.create.content.contraptions.piston.MechanicalPistonHeadBlock; +import com.simibubi.create.content.contraptions.piston.PistonExtensionPoleBlock; +import com.simibubi.create.content.contraptions.pulley.PulleyBlock; +import com.simibubi.create.content.decoration.MetalLadderBlock; +import com.simibubi.create.content.decoration.MetalScaffoldingBlock; +import com.simibubi.create.content.decoration.TrainTrapdoorBlock; +import com.simibubi.create.content.decoration.TrapdoorCTBehaviour; +import com.simibubi.create.content.decoration.bracket.BracketBlock; +import com.simibubi.create.content.decoration.bracket.BracketBlockItem; +import com.simibubi.create.content.decoration.bracket.BracketGenerator; +import com.simibubi.create.content.decoration.copycat.CopycatBarsModel; +import com.simibubi.create.content.decoration.copycat.CopycatPanelBlock; +import com.simibubi.create.content.decoration.copycat.CopycatPanelModel; +import com.simibubi.create.content.decoration.copycat.CopycatStepBlock; +import com.simibubi.create.content.decoration.copycat.CopycatStepModel; +import com.simibubi.create.content.decoration.copycat.SpecialCopycatPanelBlockState; +import com.simibubi.create.content.decoration.encasing.CasingBlock; +import com.simibubi.create.content.decoration.encasing.EncasedCTBehaviour; +import com.simibubi.create.content.decoration.encasing.EncasingRegistry; +import com.simibubi.create.content.decoration.girder.ConnectedGirderModel; +import com.simibubi.create.content.decoration.girder.GirderBlock; +import com.simibubi.create.content.decoration.girder.GirderBlockStateGenerator; +import com.simibubi.create.content.decoration.girder.GirderEncasedShaftBlock; +import com.simibubi.create.content.decoration.placard.PlacardBlock; +import com.simibubi.create.content.decoration.slidingDoor.SlidingDoorBlock; +import com.simibubi.create.content.decoration.steamWhistle.WhistleBlock; +import com.simibubi.create.content.decoration.steamWhistle.WhistleExtenderBlock; +import com.simibubi.create.content.decoration.steamWhistle.WhistleGenerator; +import com.simibubi.create.content.equipment.armor.BacktankBlock; +import com.simibubi.create.content.equipment.bell.HauntedBellBlock; +import com.simibubi.create.content.equipment.bell.HauntedBellMovementBehaviour; +import com.simibubi.create.content.equipment.bell.PeculiarBellBlock; +import com.simibubi.create.content.equipment.clipboard.ClipboardBlock; +import com.simibubi.create.content.equipment.clipboard.ClipboardBlockItem; +import com.simibubi.create.content.equipment.clipboard.ClipboardOverrides; +import com.simibubi.create.content.equipment.toolbox.ToolboxBlock; +import com.simibubi.create.content.fluids.PipeAttachmentModel; +import com.simibubi.create.content.fluids.drain.ItemDrainBlock; +import com.simibubi.create.content.fluids.hosePulley.HosePulleyBlock; +import com.simibubi.create.content.fluids.pipes.EncasedPipeBlock; +import com.simibubi.create.content.fluids.pipes.FluidPipeBlock; +import com.simibubi.create.content.fluids.pipes.GlassFluidPipeBlock; +import com.simibubi.create.content.fluids.pipes.SmartFluidPipeBlock; +import com.simibubi.create.content.fluids.pipes.SmartFluidPipeGenerator; +import com.simibubi.create.content.fluids.pipes.valve.FluidValveBlock; +import com.simibubi.create.content.fluids.pump.PumpBlock; +import com.simibubi.create.content.fluids.spout.SpoutBlock; +import com.simibubi.create.content.fluids.tank.FluidTankBlock; +import com.simibubi.create.content.fluids.tank.FluidTankGenerator; +import com.simibubi.create.content.fluids.tank.FluidTankItem; +import com.simibubi.create.content.fluids.tank.FluidTankModel; +import com.simibubi.create.content.kinetics.BlockStressDefaults; +import com.simibubi.create.content.kinetics.belt.BeltBlock; +import com.simibubi.create.content.kinetics.belt.BeltGenerator; +import com.simibubi.create.content.kinetics.belt.BeltModel; +import com.simibubi.create.content.kinetics.chainDrive.ChainDriveBlock; +import com.simibubi.create.content.kinetics.chainDrive.ChainDriveGenerator; +import com.simibubi.create.content.kinetics.chainDrive.ChainGearshiftBlock; +import com.simibubi.create.content.kinetics.clock.CuckooClockBlock; +import com.simibubi.create.content.kinetics.crafter.CrafterCTBehaviour; +import com.simibubi.create.content.kinetics.crafter.MechanicalCrafterBlock; +import com.simibubi.create.content.kinetics.crank.HandCrankBlock; +import com.simibubi.create.content.kinetics.crank.ValveHandleBlock; +import com.simibubi.create.content.kinetics.crusher.CrushingWheelBlock; +import com.simibubi.create.content.kinetics.crusher.CrushingWheelControllerBlock; +import com.simibubi.create.content.kinetics.deployer.DeployerBlock; +import com.simibubi.create.content.kinetics.deployer.DeployerMovementBehaviour; +import com.simibubi.create.content.kinetics.deployer.DeployerMovingInteraction; +import com.simibubi.create.content.kinetics.drill.DrillBlock; +import com.simibubi.create.content.kinetics.drill.DrillMovementBehaviour; +import com.simibubi.create.content.kinetics.fan.EncasedFanBlock; +import com.simibubi.create.content.kinetics.fan.NozzleBlock; +import com.simibubi.create.content.kinetics.flywheel.FlywheelBlock; +import com.simibubi.create.content.kinetics.gantry.GantryShaftBlock; +import com.simibubi.create.content.kinetics.gauge.GaugeBlock; +import com.simibubi.create.content.kinetics.gauge.GaugeGenerator; +import com.simibubi.create.content.kinetics.gearbox.GearboxBlock; +import com.simibubi.create.content.kinetics.mechanicalArm.ArmBlock; +import com.simibubi.create.content.kinetics.mechanicalArm.ArmItem; +import com.simibubi.create.content.kinetics.millstone.MillstoneBlock; +import com.simibubi.create.content.kinetics.mixer.MechanicalMixerBlock; +import com.simibubi.create.content.kinetics.motor.CreativeMotorBlock; +import com.simibubi.create.content.kinetics.motor.CreativeMotorGenerator; +import com.simibubi.create.content.kinetics.press.MechanicalPressBlock; +import com.simibubi.create.content.kinetics.saw.SawBlock; +import com.simibubi.create.content.kinetics.saw.SawGenerator; +import com.simibubi.create.content.kinetics.saw.SawMovementBehaviour; +import com.simibubi.create.content.kinetics.simpleRelays.BracketedKineticBlockModel; +import com.simibubi.create.content.kinetics.simpleRelays.CogWheelBlock; +import com.simibubi.create.content.kinetics.simpleRelays.CogwheelBlockItem; +import com.simibubi.create.content.kinetics.simpleRelays.ShaftBlock; +import com.simibubi.create.content.kinetics.simpleRelays.encased.EncasedCogCTBehaviour; +import com.simibubi.create.content.kinetics.simpleRelays.encased.EncasedCogwheelBlock; +import com.simibubi.create.content.kinetics.simpleRelays.encased.EncasedShaftBlock; +import com.simibubi.create.content.kinetics.speedController.SpeedControllerBlock; +import com.simibubi.create.content.kinetics.steamEngine.PoweredShaftBlock; +import com.simibubi.create.content.kinetics.steamEngine.SteamEngineBlock; +import com.simibubi.create.content.kinetics.transmission.ClutchBlock; +import com.simibubi.create.content.kinetics.transmission.GearshiftBlock; +import com.simibubi.create.content.kinetics.transmission.sequencer.SequencedGearshiftBlock; +import com.simibubi.create.content.kinetics.transmission.sequencer.SequencedGearshiftGenerator; +import com.simibubi.create.content.kinetics.turntable.TurntableBlock; +import com.simibubi.create.content.kinetics.waterwheel.LargeWaterWheelBlock; +import com.simibubi.create.content.kinetics.waterwheel.LargeWaterWheelBlockItem; +import com.simibubi.create.content.kinetics.waterwheel.WaterWheelBlock; +import com.simibubi.create.content.kinetics.waterwheel.WaterWheelStructuralBlock; +import com.simibubi.create.content.logistics.chute.ChuteBlock; +import com.simibubi.create.content.logistics.chute.ChuteGenerator; +import com.simibubi.create.content.logistics.chute.ChuteItem; +import com.simibubi.create.content.logistics.chute.SmartChuteBlock; +import com.simibubi.create.content.logistics.crate.CreativeCrateBlock; +import com.simibubi.create.content.logistics.depot.DepotBlock; +import com.simibubi.create.content.logistics.depot.EjectorBlock; +import com.simibubi.create.content.logistics.depot.EjectorItem; +import com.simibubi.create.content.logistics.funnel.AndesiteFunnelBlock; +import com.simibubi.create.content.logistics.funnel.BeltFunnelBlock; +import com.simibubi.create.content.logistics.funnel.BeltFunnelGenerator; +import com.simibubi.create.content.logistics.funnel.BrassFunnelBlock; +import com.simibubi.create.content.logistics.funnel.FunnelGenerator; +import com.simibubi.create.content.logistics.funnel.FunnelItem; +import com.simibubi.create.content.logistics.funnel.FunnelMovementBehaviour; +import com.simibubi.create.content.logistics.tunnel.BeltTunnelBlock; +import com.simibubi.create.content.logistics.tunnel.BrassTunnelBlock; +import com.simibubi.create.content.logistics.tunnel.BrassTunnelCTBehaviour; +import com.simibubi.create.content.logistics.vault.ItemVaultBlock; +import com.simibubi.create.content.logistics.vault.ItemVaultCTBehaviour; +import com.simibubi.create.content.logistics.vault.ItemVaultItem; +import com.simibubi.create.content.materials.ExperienceBlock; +import com.simibubi.create.content.processing.AssemblyOperatorBlockItem; +import com.simibubi.create.content.processing.basin.BasinBlock; +import com.simibubi.create.content.processing.basin.BasinGenerator; +import com.simibubi.create.content.processing.basin.BasinMovementBehaviour; +import com.simibubi.create.content.processing.burner.BlazeBurnerBlock; +import com.simibubi.create.content.processing.burner.BlazeBurnerBlockItem; +import com.simibubi.create.content.processing.burner.BlazeBurnerInteractionBehaviour; +import com.simibubi.create.content.processing.burner.BlazeBurnerMovementBehaviour; +import com.simibubi.create.content.processing.burner.LitBlazeBurnerBlock; +import com.simibubi.create.content.redstone.RoseQuartzLampBlock; +import com.simibubi.create.content.redstone.analogLever.AnalogLeverBlock; +import com.simibubi.create.content.redstone.contact.ContactMovementBehaviour; +import com.simibubi.create.content.redstone.contact.RedstoneContactBlock; +import com.simibubi.create.content.redstone.contact.RedstoneContactItem; +import com.simibubi.create.content.redstone.diodes.AbstractDiodeGenerator; +import com.simibubi.create.content.redstone.diodes.BrassDiodeBlock; +import com.simibubi.create.content.redstone.diodes.BrassDiodeGenerator; +import com.simibubi.create.content.redstone.diodes.PoweredLatchBlock; +import com.simibubi.create.content.redstone.diodes.PoweredLatchGenerator; +import com.simibubi.create.content.redstone.diodes.ToggleLatchBlock; +import com.simibubi.create.content.redstone.diodes.ToggleLatchGenerator; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkBlock; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkBlockItem; +import com.simibubi.create.content.redstone.displayLink.source.AccumulatedItemCountDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.BoilerDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.CurrentFloorDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.EntityNameDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.FillLevelDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.FluidAmountDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.FluidListDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.ItemCountDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.ItemListDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.ItemNameDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.ItemThroughputDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.KineticSpeedDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.KineticStressDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.ObservedTrainNameSource; +import com.simibubi.create.content.redstone.displayLink.source.StationSummaryDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.StopWatchDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.TimeOfDayDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.TrainStatusDisplaySource; +import com.simibubi.create.content.redstone.displayLink.target.DisplayBoardTarget; +import com.simibubi.create.content.redstone.link.RedstoneLinkBlock; +import com.simibubi.create.content.redstone.link.RedstoneLinkGenerator; +import com.simibubi.create.content.redstone.link.controller.LecternControllerBlock; +import com.simibubi.create.content.redstone.nixieTube.NixieTubeBlock; +import com.simibubi.create.content.redstone.nixieTube.NixieTubeGenerator; +import com.simibubi.create.content.redstone.rail.ControllerRailBlock; +import com.simibubi.create.content.redstone.rail.ControllerRailGenerator; +import com.simibubi.create.content.redstone.smartObserver.SmartObserverBlock; +import com.simibubi.create.content.redstone.smartObserver.SmartObserverGenerator; +import com.simibubi.create.content.redstone.thresholdSwitch.ThresholdSwitchBlock; +import com.simibubi.create.content.redstone.thresholdSwitch.ThresholdSwitchGenerator; +import com.simibubi.create.content.schematics.cannon.SchematicannonBlock; +import com.simibubi.create.content.schematics.table.SchematicTableBlock; +import com.simibubi.create.content.trains.bogey.BogeySizes; +import com.simibubi.create.content.trains.bogey.StandardBogeyBlock; +import com.simibubi.create.content.trains.display.FlapDisplayBlock; +import com.simibubi.create.content.trains.graph.EdgePointType; +import com.simibubi.create.content.trains.observer.TrackObserverBlock; +import com.simibubi.create.content.trains.signal.SignalBlock; +import com.simibubi.create.content.trains.station.StationBlock; +import com.simibubi.create.content.trains.track.FakeTrackBlock; +import com.simibubi.create.content.trains.track.TrackBlock; +import com.simibubi.create.content.trains.track.TrackBlockItem; +import com.simibubi.create.content.trains.track.TrackBlockStateGenerator; +import com.simibubi.create.content.trains.track.TrackMaterial; +import com.simibubi.create.content.trains.track.TrackModel; +import com.simibubi.create.content.trains.track.TrackTargetingBlockItem; import com.simibubi.create.foundation.block.CopperBlockSet; import com.simibubi.create.foundation.block.DyedBlockList; import com.simibubi.create.foundation.block.ItemUseOverrides; +import com.simibubi.create.foundation.block.WrenchableDirectionalBlock; import com.simibubi.create.foundation.data.AssetLookup; import com.simibubi.create.foundation.data.BlockStateGen; import com.simibubi.create.foundation.data.BuilderTransformers; import com.simibubi.create.foundation.data.CreateRegistrate; +import com.simibubi.create.foundation.data.MetalBarsGen; import com.simibubi.create.foundation.data.ModelGen; import com.simibubi.create.foundation.data.SharedProperties; -import com.simibubi.create.foundation.item.TooltipHelper; +import com.simibubi.create.foundation.item.ItemDescription; import com.simibubi.create.foundation.item.UncontainableBlockItem; import com.simibubi.create.foundation.utility.ColorHandlers; import com.simibubi.create.foundation.utility.Couple; @@ -244,9 +273,11 @@ import net.minecraft.client.renderer.RenderType; import net.minecraft.core.Direction.Axis; import net.minecraft.core.Direction.AxisDirection; import net.minecraft.core.registries.Registries; +import net.minecraft.data.loot.BlockLootSubProvider; import net.minecraft.data.recipes.RecipeCategory; import net.minecraft.data.recipes.ShapelessRecipeBuilder; import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundEvents; import net.minecraft.tags.BlockTags; import net.minecraft.tags.ItemTags; import net.minecraft.world.item.DyeColor; @@ -254,6 +285,7 @@ import net.minecraft.world.item.Rarity; import net.minecraft.world.item.enchantment.Enchantments; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.IronBarsBlock; import net.minecraft.world.level.block.RotatedPillarBlock; import net.minecraft.world.level.block.SoundType; import net.minecraft.world.level.block.state.BlockBehaviour; @@ -275,15 +307,12 @@ import net.minecraft.world.level.storage.loot.providers.number.ConstantValue; import net.minecraftforge.client.model.generators.ConfiguredModel; import net.minecraftforge.client.model.generators.ModelFile; import net.minecraftforge.common.Tags; +import net.minecraftforge.common.util.ForgeSoundType; public class AllBlocks { // Schematics - static { - REGISTRATE.startSection(SCHEMATICS); - } - public static final BlockEntry SCHEMATICANNON = REGISTRATE.block("schematicannon", SchematicannonBlock::new) .initialProperties(() -> Blocks.DISPENSER) @@ -317,10 +346,6 @@ public class AllBlocks { // Kinetics - static { - REGISTRATE.startSection(AllSections.KINETICS); - } - public static final BlockEntry SHAFT = REGISTRATE.block("shaft", ShaftBlock::new) .initialProperties(SharedProperties::stone) .properties(p -> p.color(MaterialColor.METAL)) @@ -394,21 +419,22 @@ public class AllBlocks { .transform(axeOrPickaxe()) .register(); - public static final BlockEntry ANDESITE_ENCASED_LARGE_COGWHEEL = - REGISTRATE.block("andesite_encased_large_cogwheel", p -> new EncasedCogwheelBlock(p, true, AllBlocks.ANDESITE_CASING::get)) - .properties(p -> p.color(MaterialColor.PODZOL)) - .transform(BuilderTransformers.encasedLargeCogwheel("andesite", () -> AllSpriteShifts.ANDESITE_CASING)) - .transform(EncasingRegistry.addVariantTo(AllBlocks.LARGE_COGWHEEL)) - .transform(axeOrPickaxe()) - .register(); + public static final BlockEntry ANDESITE_ENCASED_LARGE_COGWHEEL = REGISTRATE + .block("andesite_encased_large_cogwheel", + p -> new EncasedCogwheelBlock(p, true, AllBlocks.ANDESITE_CASING::get)) + .properties(p -> p.color(MaterialColor.PODZOL)) + .transform(BuilderTransformers.encasedLargeCogwheel("andesite", () -> AllSpriteShifts.ANDESITE_CASING)) + .transform(EncasingRegistry.addVariantTo(AllBlocks.LARGE_COGWHEEL)) + .transform(axeOrPickaxe()) + .register(); - public static final BlockEntry BRASS_ENCASED_LARGE_COGWHEEL = - REGISTRATE.block("brass_encased_large_cogwheel", p -> new EncasedCogwheelBlock(p, true, AllBlocks.BRASS_CASING::get)) - .properties(p -> p.color(MaterialColor.TERRACOTTA_BROWN)) - .transform(BuilderTransformers.encasedLargeCogwheel("brass", () -> AllSpriteShifts.BRASS_CASING)) - .transform(EncasingRegistry.addVariantTo(AllBlocks.LARGE_COGWHEEL)) - .transform(axeOrPickaxe()) - .register(); + public static final BlockEntry BRASS_ENCASED_LARGE_COGWHEEL = REGISTRATE + .block("brass_encased_large_cogwheel", p -> new EncasedCogwheelBlock(p, true, AllBlocks.BRASS_CASING::get)) + .properties(p -> p.color(MaterialColor.TERRACOTTA_BROWN)) + .transform(BuilderTransformers.encasedLargeCogwheel("brass", () -> AllSpriteShifts.BRASS_CASING)) + .transform(EncasingRegistry.addVariantTo(AllBlocks.LARGE_COGWHEEL)) + .transform(axeOrPickaxe()) + .register(); public static final BlockEntry GEARBOX = REGISTRATE.block("gearbox", GearboxBlock::new) .initialProperties(SharedProperties::stone) @@ -428,6 +454,7 @@ public class AllBlocks { .initialProperties(SharedProperties::stone) .properties(BlockBehaviour.Properties::noOcclusion) .properties(p -> p.color(MaterialColor.PODZOL)) + .addLayer(() -> RenderType::cutoutMipped) .transform(BlockStressDefaults.setNoImpact()) .transform(axeOrPickaxe()) .blockstate((c, p) -> BlockStateGen.axisBlock(c, p, AssetLookup.forPowered(c, p))) @@ -439,6 +466,7 @@ public class AllBlocks { .initialProperties(SharedProperties::stone) .properties(BlockBehaviour.Properties::noOcclusion) .properties(p -> p.color(MaterialColor.PODZOL)) + .addLayer(() -> RenderType::cutoutMipped) .transform(BlockStressDefaults.setNoImpact()) .transform(axeOrPickaxe()) .blockstate((c, p) -> BlockStateGen.axisBlock(c, p, AssetLookup.forPowered(c, p))) @@ -446,28 +474,28 @@ public class AllBlocks { .transform(customItemModel()) .register(); - public static final BlockEntry ENCASED_CHAIN_DRIVE = - REGISTRATE.block("encased_chain_drive", EncasedBeltBlock::new) + public static final BlockEntry ENCASED_CHAIN_DRIVE = + REGISTRATE.block("encased_chain_drive", ChainDriveBlock::new) .initialProperties(SharedProperties::stone) .properties(BlockBehaviour.Properties::noOcclusion) .properties(p -> p.color(MaterialColor.PODZOL)) .transform(BlockStressDefaults.setNoImpact()) .transform(axeOrPickaxe()) - .blockstate((c, p) -> new EncasedBeltGenerator((state, suffix) -> p.models() + .blockstate((c, p) -> new ChainDriveGenerator((state, suffix) -> p.models() .getExistingFile(p.modLoc("block/" + c.getName() + "/" + suffix))).generate(c, p)) .item() .transform(customItemModel()) .register(); - public static final BlockEntry ADJUSTABLE_CHAIN_GEARSHIFT = - REGISTRATE.block("adjustable_chain_gearshift", AdjustablePulleyBlock::new) + public static final BlockEntry ADJUSTABLE_CHAIN_GEARSHIFT = + REGISTRATE.block("adjustable_chain_gearshift", ChainGearshiftBlock::new) .initialProperties(SharedProperties::stone) .properties(BlockBehaviour.Properties::noOcclusion) .properties(p -> p.color(MaterialColor.NETHER)) .transform(BlockStressDefaults.setNoImpact()) .transform(axeOrPickaxe()) - .blockstate((c, p) -> new EncasedBeltGenerator((state, suffix) -> { - String powered = state.getValue(AdjustablePulleyBlock.POWERED) ? "_powered" : ""; + .blockstate((c, p) -> new ChainDriveGenerator((state, suffix) -> { + String powered = state.getValue(ChainGearshiftBlock.POWERED) ? "_powered" : ""; return p.models() .withExistingParent(c.getName() + "_" + suffix + powered, p.modLoc("block/encased_chain_drive/" + suffix)) @@ -481,6 +509,7 @@ public class AllBlocks { public static final BlockEntry BELT = REGISTRATE.block("belt", BeltBlock::new) .initialProperties(SharedProperties.BELT_MATERIAL, MaterialColor.COLOR_GRAY) + .addLayer(() -> RenderType::cutoutMipped) .properties(p -> p.sound(SoundType.WOOL)) .properties(p -> p.strength(0.8F)) .properties(p -> p.color(MaterialColor.COLOR_GRAY)) @@ -510,13 +539,41 @@ public class AllBlocks { .properties(p -> p.color(MaterialColor.DIRT)) .properties(BlockBehaviour.Properties::noOcclusion) .transform(axeOrPickaxe()) - .blockstate(BlockStateGen.directionalBlockProviderIgnoresWaterlogged(false)) + .blockstate( + (c, p) -> BlockStateGen.directionalBlockIgnoresWaterlogged(c, p, s -> AssetLookup.partialBaseModel(c, p))) .addLayer(() -> RenderType::cutoutMipped) - .transform(BlockStressDefaults.setCapacity(16.0)) + .transform(BlockStressDefaults.setCapacity(32.0)) .transform(BlockStressDefaults.setGeneratorSpeed(WaterWheelBlock::getSpeedRange)) - .simpleItem() + .item() + .transform(customItemModel()) .register(); + public static final BlockEntry LARGE_WATER_WHEEL = + REGISTRATE.block("large_water_wheel", LargeWaterWheelBlock::new) + .initialProperties(SharedProperties::wooden) + .properties(p -> p.color(MaterialColor.DIRT)) + .properties(BlockBehaviour.Properties::noOcclusion) + .transform(axeOrPickaxe()) + .blockstate((c, p) -> axisBlock(c, p, + s -> s.getValue(LargeWaterWheelBlock.EXTENSION) ? AssetLookup.partialBaseModel(c, p, "extension") + : AssetLookup.partialBaseModel(c, p))) + .transform(BlockStressDefaults.setCapacity(128.0)) + .transform(BlockStressDefaults.setGeneratorSpeed(LargeWaterWheelBlock::getSpeedRange)) + .item(LargeWaterWheelBlockItem::new) + .transform(customItemModel()) + .register(); + + public static final BlockEntry WATER_WHEEL_STRUCTURAL = + REGISTRATE.block("water_wheel_structure", WaterWheelStructuralBlock::new) + .initialProperties(SharedProperties::wooden) + .blockstate((c, p) -> p.getVariantBuilder(c.get()) + .forAllStatesExcept(BlockStateGen.mapToAir(p), WaterWheelStructuralBlock.FACING)) + .properties(p -> p.color(MaterialColor.DIRT)) + .properties(BlockBehaviour.Properties::noOcclusion) + .transform(axeOrPickaxe()) + .lang("Large Water Wheel") + .register(); + public static final BlockEntry ENCASED_FAN = REGISTRATE.block("encased_fan", EncasedFanBlock::new) .initialProperties(SharedProperties::stone) .properties(p -> p.color(MaterialColor.PODZOL)) @@ -576,7 +633,7 @@ public class AllBlocks { .transform(axeOrPickaxe()) .transform(BuilderTransformers.cuckooClock()) .lang("Cuckoo Clock") - .onRegisterAfter(Registries.ITEM, c -> TooltipHelper.referTo(c, CUCKOO_CLOCK)) + .onRegisterAfter(Registries.ITEM, c -> ItemDescription.referKey(c, CUCKOO_CLOCK)) .register(); public static final BlockEntry MILLSTONE = REGISTRATE.block("millstone", MillstoneBlock::new) @@ -595,10 +652,11 @@ public class AllBlocks { .initialProperties(SharedProperties::stone) .properties(BlockBehaviour.Properties::noOcclusion) .transform(pickaxeOnly()) - .blockstate(BlockStateGen.axisBlockProvider(false)) + .blockstate((c, p) -> BlockStateGen.axisBlock(c, p, s -> AssetLookup.partialBaseModel(c, p))) .addLayer(() -> RenderType::cutoutMipped) .transform(BlockStressDefaults.setImpact(8.0)) - .simpleItem() + .item() + .transform(customItemModel()) .register(); public static final BlockEntry CRUSHING_WHEEL_CONTROLLER = @@ -609,10 +667,7 @@ public class AllBlocks { .noLootTable() .air()) .blockstate((c, p) -> p.getVariantBuilder(c.get()) - .forAllStatesExcept(state -> ConfiguredModel.builder() - .modelFile(p.models() - .getExistingFile(p.mcLoc("block/air"))) - .build(), CrushingWheelControllerBlock.FACING)) + .forAllStatesExcept(BlockStateGen.mapToAir(p), CrushingWheelControllerBlock.FACING)) .register(); public static final BlockEntry MECHANICAL_PRESS = @@ -646,6 +701,7 @@ public class AllBlocks { .properties(p -> p.sound(SoundType.NETHERITE_BLOCK)) .transform(pickaxeOnly()) .blockstate(new BasinGenerator()::generate) + .addLayer(() -> RenderType::cutoutMipped) .onRegister(movementBehaviour(new BasinMovementBehaviour())) .item() .transform(customItemModel("_", "block")) @@ -664,7 +720,7 @@ public class AllBlocks { .onRegister(movementBehaviour(new BlazeBurnerMovementBehaviour())) .onRegister(interactionBehaviour(new BlazeBurnerInteractionBehaviour())) .item(BlazeBurnerBlockItem::withBlaze) - .model(AssetLookup.customBlockItemModel("blaze_burner", "block_with_blaze")) + .model(AssetLookup.customBlockItemModel("blaze_burner", "block_with_blaze")) .build() .register(); @@ -711,6 +767,7 @@ public class AllBlocks { .register(); public static final BlockEntry CHUTE = REGISTRATE.block("chute", ChuteBlock::new) + .addLayer(() -> RenderType::cutoutMipped) .initialProperties(SharedProperties::softMetal) .properties(p -> p.color(MaterialColor.COLOR_GRAY)) .properties(p -> p.sound(SoundType.NETHERITE_BLOCK)) @@ -722,9 +779,12 @@ public class AllBlocks { .register(); public static final BlockEntry SMART_CHUTE = REGISTRATE.block("smart_chute", SmartChuteBlock::new) + .addLayer(() -> RenderType::cutoutMipped) .initialProperties(SharedProperties::softMetal) .properties(p -> p.color(MaterialColor.COLOR_GRAY)) .properties(p -> p.sound(SoundType.NETHERITE_BLOCK)) + .properties(p -> p.noOcclusion()) + .properties(p -> p.isRedstoneConductor((level, pos, state) -> false)) .transform(pickaxeOnly()) .blockstate((c, p) -> BlockStateGen.simpleBlock(c, p, AssetLookup.forPowered(c, p))) .item() @@ -769,49 +829,6 @@ public class AllBlocks { .transform(BracketGenerator.itemModel("metal")) .register(); - public static final BlockEntry METAL_GIRDER = REGISTRATE.block("metal_girder", GirderBlock::new) - .initialProperties(SharedProperties::softMetal) - .blockstate(GirderBlockStateGenerator::blockState) - .properties(p -> p.color(MaterialColor.COLOR_GRAY)) - .properties(p -> p.sound(SoundType.NETHERITE_BLOCK)) - .transform(pickaxeOnly()) - .onRegister(CreateRegistrate.blockModel(() -> ConnectedGirderModel::new)) - .item() - .transform(customItemModel()) - .register(); - - public static final BlockEntry METAL_GIRDER_ENCASED_SHAFT = - REGISTRATE.block("metal_girder_encased_shaft", GirderEncasedShaftBlock::new) - .initialProperties(SharedProperties::softMetal) - .blockstate(GirderBlockStateGenerator::blockStateWithShaft) - .properties(p -> p.color(MaterialColor.COLOR_GRAY)) - .properties(p -> p.sound(SoundType.NETHERITE_BLOCK)) - .transform(pickaxeOnly()) - .loot((p, b) -> p.add(b, p.createSingleItemTable(METAL_GIRDER.get()) - .withPool(p.applyExplosionCondition(SHAFT.get(), LootPool.lootPool() - .setRolls(ConstantValue.exactly(1.0F)) - .add(LootItem.lootTableItem(SHAFT.get())))))) - .onRegister(CreateRegistrate.blockModel(() -> ConnectedGirderModel::new)) - .register(); - - public static final BlockEntry ANDESITE_LADDER = - REGISTRATE.block("andesite_ladder", MetalLadderBlock::new) - .transform( - BuilderTransformers.ladder("andesite", () -> DataIngredient.items(AllItems.ANDESITE_ALLOY.get()))) - .register(); - - public static final BlockEntry BRASS_LADDER = - REGISTRATE.block("brass_ladder", MetalLadderBlock::new) - .transform( - BuilderTransformers.ladder("brass", () -> DataIngredient.tag(AllTags.forgeItemTag("plates/brass")))) - .register(); - - public static final BlockEntry COPPER_LADDER = - REGISTRATE.block("copper_ladder", MetalLadderBlock::new) - .transform( - BuilderTransformers.ladder("copper", () -> DataIngredient.tag(AllTags.forgeItemTag("plates/copper")))) - .register(); - // Fluids public static final BlockEntry FLUID_PIPE = REGISTRATE.block("fluid_pipe", FluidPipeBlock::new) @@ -897,6 +914,7 @@ public class AllBlocks { REGISTRATE.block("copper_valve_handle", ValveHandleBlock::copper) .transform(pickaxeOnly()) .transform(BuilderTransformers.valveHandle(null)) + .transform(BlockStressDefaults.setCapacity(8.0)) .register(); public static final DyedBlockList DYED_VALVE_HANDLES = new DyedBlockList<>(colour -> { @@ -923,7 +941,7 @@ public class AllBlocks { .onRegister(assignDataBehaviour(new BoilerDisplaySource(), "boiler_status")) .addLayer(() -> RenderType::cutoutMipped) .item(FluidTankItem::new) - .model(AssetLookup.customBlockItemModel("_", "block_single_window")) + .model(AssetLookup.customBlockItemModel("_", "block_single_window")) .build() .register(); @@ -983,6 +1001,7 @@ public class AllBlocks { .blockstate((c, p) -> p.directionalBlock(c.get(), AssetLookup.partialBaseModel(c, p))) .onRegister(movementBehaviour(new PortableStorageInterfaceMovement())) .item() + .tag(AllItemTags.CONTRAPTION_CONTROLLED.tag) .transform(customItemModel()) .register(); @@ -1103,7 +1122,7 @@ public class AllBlocks { REGISTRATE.block("windmill_bearing", WindmillBearingBlock::new) .transform(axeOrPickaxe()) .properties(p -> p.color(MaterialColor.PODZOL)) - .transform(BuilderTransformers.bearing("windmill", "gearbox", true)) + .transform(BuilderTransformers.bearing("windmill", "gearbox")) .transform(BlockStressDefaults.setCapacity(512.0)) .transform(BlockStressDefaults.setGeneratorSpeed(WindmillBearingBlock::getSpeedRange)) .tag(AllBlockTags.SAFE_NBT.tag) @@ -1113,7 +1132,7 @@ public class AllBlocks { REGISTRATE.block("mechanical_bearing", MechanicalBearingBlock::new) .properties(p -> p.color(MaterialColor.PODZOL)) .transform(axeOrPickaxe()) - .transform(BuilderTransformers.bearing("mechanical", "gearbox", false)) + .transform(BuilderTransformers.bearing("mechanical", "gearbox")) .transform(BlockStressDefaults.setImpact(4.0)) .tag(AllBlockTags.SAFE_NBT.tag) .onRegister(movementBehaviour(new StabilizedBearingMovementBehaviour())) @@ -1123,7 +1142,7 @@ public class AllBlocks { REGISTRATE.block("clockwork_bearing", ClockworkBearingBlock::new) .properties(p -> p.color(MaterialColor.TERRACOTTA_BROWN)) .transform(axeOrPickaxe()) - .transform(BuilderTransformers.bearing("clockwork", "brass_gearbox", false)) + .transform(BuilderTransformers.bearing("clockwork", "brass_gearbox")) .transform(BlockStressDefaults.setImpact(4.0)) .tag(AllBlockTags.SAFE_NBT.tag) .register(); @@ -1142,6 +1161,7 @@ public class AllBlocks { public static final BlockEntry ROPE = REGISTRATE.block("rope", PulleyBlock.RopeBlock::new) .initialProperties(SharedProperties.BELT_MATERIAL, MaterialColor.COLOR_BROWN) .tag(AllBlockTags.BRITTLE.tag) + .tag(BlockTags.CLIMBABLE) .properties(p -> p.sound(SoundType.WOOL)) .blockstate((c, p) -> p.simpleBlock(c.get(), p.models() .getExistingFile(p.modLoc("block/rope_pulley/" + c.getName())))) @@ -1151,10 +1171,22 @@ public class AllBlocks { REGISTRATE.block("pulley_magnet", PulleyBlock.MagnetBlock::new) .initialProperties(SharedProperties::stone) .tag(AllBlockTags.BRITTLE.tag) + .tag(BlockTags.CLIMBABLE) .blockstate((c, p) -> p.simpleBlock(c.get(), p.models() .getExistingFile(p.modLoc("block/rope_pulley/" + c.getName())))) .register(); + public static final BlockEntry ELEVATOR_PULLEY = + REGISTRATE.block("elevator_pulley", ElevatorPulleyBlock::new) + .initialProperties(SharedProperties::softMetal) + .properties(p -> p.color(MaterialColor.TERRACOTTA_BROWN)) + .transform(axeOrPickaxe()) + .blockstate(BlockStateGen.horizontalBlockProvider(true)) + .transform(BlockStressDefaults.setImpact(4.0)) + .item() + .transform(customItemModel()) + .register(); + public static final BlockEntry CART_ASSEMBLER = REGISTRATE.block("cart_assembler", CartAssemblerBlock::new) .initialProperties(SharedProperties::stone) @@ -1236,6 +1268,19 @@ public class AllBlocks { .transform(customItemModel()) .register(); + public static final BlockEntry CONTRAPTION_CONTROLS = + REGISTRATE.block("contraption_controls", ContraptionControlsBlock::new) + .initialProperties(SharedProperties::stone) + .properties(p -> p.color(MaterialColor.PODZOL)) + .addLayer(() -> RenderType::cutoutMipped) + .transform(axeOrPickaxe()) + .blockstate((c, p) -> p.horizontalBlock(c.get(), s -> AssetLookup.partialBaseModel(c, p))) + .onRegister(movementBehaviour(new ContraptionControlsMovement())) + .onRegister(interactionBehaviour(new ContraptionControlsMovingInteraction())) + .item() + .transform(customItemModel()) + .register(); + public static final BlockEntry MECHANICAL_DRILL = REGISTRATE.block("mechanical_drill", DrillBlock::new) .initialProperties(SharedProperties::stone) .properties(p -> p.color(MaterialColor.PODZOL)) @@ -1244,11 +1289,13 @@ public class AllBlocks { .transform(BlockStressDefaults.setImpact(4.0)) .onRegister(movementBehaviour(new DrillMovementBehaviour())) .item() + .tag(AllItemTags.CONTRAPTION_CONTROLLED.tag) .transform(customItemModel()) .register(); public static final BlockEntry MECHANICAL_SAW = REGISTRATE.block("mechanical_saw", SawBlock::new) .initialProperties(SharedProperties::stone) + .addLayer(() -> RenderType::cutoutMipped) .properties(p -> p.color(MaterialColor.PODZOL)) .transform(axeOrPickaxe()) .blockstate(new SawGenerator()::generate) @@ -1256,6 +1303,7 @@ public class AllBlocks { .onRegister(movementBehaviour(new SawMovementBehaviour())) .addLayer(() -> RenderType::cutoutMipped) .item() + .tag(AllItemTags.CONTRAPTION_CONTROLLED.tag) .transform(customItemModel()) .register(); @@ -1268,6 +1316,7 @@ public class AllBlocks { .onRegister(movementBehaviour(new DeployerMovementBehaviour())) .onRegister(interactionBehaviour(new DeployerMovingInteraction())) .item(AssemblyOperatorBlockItem::new) + .tag(AllItemTags.CONTRAPTION_CONTROLLED.tag) .transform(customItemModel()) .register(); @@ -1279,6 +1328,7 @@ public class AllBlocks { .blockstate((c, p) -> p.directionalBlock(c.get(), AssetLookup.partialBaseModel(c, p))) .onRegister(movementBehaviour(new PortableStorageInterfaceMovement())) .item() + .tag(AllItemTags.CONTRAPTION_CONTROLLED.tag) .transform(customItemModel()) .register(); @@ -1289,6 +1339,25 @@ public class AllBlocks { .transform(axeOrPickaxe()) .onRegister(movementBehaviour(new ContactMovementBehaviour())) .blockstate((c, p) -> p.directionalBlock(c.get(), AssetLookup.forPowered(c, p))) + .item(RedstoneContactItem::new) + .tag(AllItemTags.CONTRAPTION_CONTROLLED.tag) + .transform(customItemModel("_", "block")) + .register(); + + public static final BlockEntry ELEVATOR_CONTACT = + REGISTRATE.block("elevator_contact", ElevatorContactBlock::new) + .initialProperties(SharedProperties::softMetal) + .properties(p -> p.color(MaterialColor.TERRACOTTA_YELLOW)) + .properties(p -> p.lightLevel(ElevatorContactBlock::getLight)) + .transform(axeOrPickaxe()) + .blockstate((c, p) -> p.directionalBlock(c.get(), state -> { + Boolean calling = state.getValue(ElevatorContactBlock.CALLING); + Boolean powering = state.getValue(ElevatorContactBlock.POWERING); + return powering ? AssetLookup.partialBaseModel(c, p, "powered") + : calling ? AssetLookup.partialBaseModel(c, p, "dim") : AssetLookup.partialBaseModel(c, p); + })) + .loot((p, b) -> p.dropOther(b, REDSTONE_CONTACT.get())) + .onRegister(assignDataBehaviour(new CurrentFloorDisplaySource(), "current_floor")) .item() .transform(customItemModel("_", "block")) .register(); @@ -1302,6 +1371,7 @@ public class AllBlocks { .blockstate(BlockStateGen.horizontalBlockProvider(true)) .addLayer(() -> RenderType::cutoutMipped) .item() + .tag(AllItemTags.CONTRAPTION_CONTROLLED.tag) .transform(customItemModel()) .register(); @@ -1312,45 +1382,24 @@ public class AllBlocks { .transform(axeOrPickaxe()) .onRegister(movementBehaviour(new PloughMovementBehaviour())) .blockstate(BlockStateGen.horizontalBlockProvider(false)) - .simpleItem() - .register(); - - public static final DyedBlockList SEATS = new DyedBlockList<>(colour -> { - String colourName = colour.getSerializedName(); - SeatMovementBehaviour movementBehaviour = new SeatMovementBehaviour(); - SeatInteractionBehaviour interactionBehaviour = new SeatInteractionBehaviour(); - return REGISTRATE.block(colourName + "_seat", p -> new SeatBlock(p, colour)) - .initialProperties(SharedProperties::wooden) - .properties(p -> p.color(colour.getMaterialColor())) - .transform(axeOnly()) - .onRegister(movementBehaviour(movementBehaviour)) - .onRegister(interactionBehaviour(interactionBehaviour)) - .onRegister(assignDataBehaviour(new EntityNameDisplaySource(), "entity_name")) - .blockstate((c, p) -> { - p.simpleBlock(c.get(), p.models() - .withExistingParent(colourName + "_seat", p.modLoc("block/seat")) - .texture("1", p.modLoc("block/seat/top_" + colourName)) - .texture("2", p.modLoc("block/seat/side_" + colourName))); - }) - .recipe((c, p) -> { - ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, c.get()) - .requires(DyeHelper.getWoolOfDye(colour)) - .requires(ItemTags.WOODEN_SLABS) - .unlockedBy("has_wool", RegistrateRecipeProvider.has(ItemTags.WOOL)) - .save(p, Create.asResource("crafting/kinetics/" + c.getName())); - ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, c.get()) - .requires(colour.getTag()) - .requires(AllItemTags.SEATS.tag) - .unlockedBy("has_seat", RegistrateRecipeProvider.has(AllItemTags.SEATS.tag)) - .save(p, Create.asResource("crafting/kinetics/" + c.getName() + "_from_other_seat")); - }) - .onRegisterAfter(Registries.ITEM, v -> TooltipHelper.referTo(v, "block.create.brown_seat")) - .tag(AllBlockTags.SEATS.tag) .item() - .tag(AllItemTags.SEATS.tag) + .tag(AllItemTags.CONTRAPTION_CONTROLLED.tag) .build() .register(); - }); + + public static final BlockEntry MECHANICAL_ROLLER = + REGISTRATE.block("mechanical_roller", RollerBlock::new) + .initialProperties(SharedProperties::stone) + .properties(p -> p.color(MaterialColor.COLOR_GRAY) + .noOcclusion()) + .transform(axeOrPickaxe()) + .onRegister(movementBehaviour(new RollerMovementBehaviour())) + .blockstate(BlockStateGen.horizontalBlockProvider(true)) + .addLayer(() -> RenderType::cutoutMipped) + .item(RollerBlockItem::new) + .tag(AllItemTags.CONTRAPTION_CONTROLLED.tag) + .transform(customItemModel()) + .register(); public static final BlockEntry SAIL_FRAME = REGISTRATE.block("sail_frame", p -> SailBlock.frame(p)) .initialProperties(SharedProperties::wooden) @@ -1359,6 +1408,7 @@ public class AllBlocks { .noOcclusion()) .transform(axeOnly()) .blockstate(BlockStateGen.directionalBlockProvider(false)) + .lang("Windmill Sail Frame") .tag(AllBlockTags.WINDMILL_SAILS.tag) .tag(AllBlockTags.FAN_TRANSPARENT.tag) .simpleItem() @@ -1372,6 +1422,7 @@ public class AllBlocks { .noOcclusion()) .transform(axeOnly()) .blockstate(BlockStateGen.directionalBlockProvider(false)) + .lang("Windmill Sail") .tag(AllBlockTags.WINDMILL_SAILS.tag) .item(BlankSailBlockItem::new) .build() @@ -1479,10 +1530,6 @@ public class AllBlocks { // Logistics - static { - REGISTRATE.startSection(AllSections.LOGISTICS); - } - public static final BlockEntry MECHANICAL_ARM = REGISTRATE.block("mechanical_arm", ArmBlock::new) .initialProperties(SharedProperties::softMetal) .properties(p -> p.color(MaterialColor.TERRACOTTA_YELLOW)) @@ -1497,7 +1544,7 @@ public class AllBlocks { .transform(customItemModel()) .register(); - public static final BlockEntry TRACK = REGISTRATE.block("track", TrackBlock::new) + public static final BlockEntry TRACK = REGISTRATE.block("track", TrackMaterial.ANDESITE::createBlock) .initialProperties(Material.STONE) .properties(p -> p.color(MaterialColor.METAL) .strength(0.8F) @@ -1505,8 +1552,11 @@ public class AllBlocks { .noOcclusion()) .addLayer(() -> RenderType::cutoutMipped) .transform(pickaxeOnly()) + .onRegister(CreateRegistrate.blockModel(() -> TrackModel::new)) .blockstate(new TrackBlockStateGenerator()::generate) .tag(AllBlockTags.RELOCATION_NOT_SUPPORTED.tag) + .tag(AllBlockTags.TRACKS.tag) + .tag(AllBlockTags.GIRDABLE_TRACKS.tag) .lang("Train Track") .item(TrackBlockItem::new) .model((c, p) -> p.generated(c, Create.asResource("item/" + c.getName()))) @@ -1575,18 +1625,18 @@ public class AllBlocks { .register(); public static final BlockEntry SMALL_BOGEY = - REGISTRATE.block("small_bogey", p -> new StandardBogeyBlock(p, false)) + REGISTRATE.block("small_bogey", p -> new StandardBogeyBlock(p, BogeySizes.SMALL)) .properties(p -> p.color(MaterialColor.PODZOL)) .transform(BuilderTransformers.bogey()) .register(); public static final BlockEntry LARGE_BOGEY = - REGISTRATE.block("large_bogey", p -> new StandardBogeyBlock(p, true)) + REGISTRATE.block("large_bogey", p -> new StandardBogeyBlock(p, BogeySizes.LARGE)) .properties(p -> p.color(MaterialColor.PODZOL)) .transform(BuilderTransformers.bogey()) .register(); - public static final BlockEntry CONTROLS = REGISTRATE.block("controls", ControlsBlock::new) + public static final BlockEntry TRAIN_CONTROLS = REGISTRATE.block("controls", ControlsBlock::new) .initialProperties(SharedProperties::softMetal) .properties(p -> p.color(MaterialColor.TERRACOTTA_BROWN)) .properties(p -> p.sound(SoundType.NETHERITE_BLOCK)) @@ -1602,40 +1652,6 @@ public class AllBlocks { .transform(customItemModel()) .register(); - public static final BlockEntry TRAIN_DOOR = REGISTRATE.block("train_door", SlidingDoorBlock::new) - .transform(BuilderTransformers.slidingDoor("train")) - .properties(p -> p.color(MaterialColor.TERRACOTTA_CYAN) - .sound(SoundType.NETHERITE_BLOCK) - .noOcclusion()) - .register(); - - public static final BlockEntry TRAIN_TRAPDOOR = - REGISTRATE.block("train_trapdoor", TrainTrapdoorBlock::new) - .initialProperties(SharedProperties::softMetal) - .properties(p -> p.color(MaterialColor.TERRACOTTA_CYAN) - .sound(SoundType.NETHERITE_BLOCK)) - .transform(BuilderTransformers.trapdoor(true)) - .register(); - - public static final BlockEntry FRAMED_GLASS_DOOR = - REGISTRATE.block("framed_glass_door", SlidingDoorBlock::new) - .transform(BuilderTransformers.slidingDoor("glass")) - .properties(p -> p.color(MaterialColor.NONE) - .sound(SoundType.GLASS) - .noOcclusion()) - .register(); - - public static final BlockEntry FRAMED_GLASS_TRAPDOOR = - REGISTRATE.block("framed_glass_trapdoor", TrainTrapdoorBlock::new) - .initialProperties(SharedProperties::softMetal) - .transform(BuilderTransformers.trapdoor(false)) - .properties(p -> p.color(MaterialColor.NONE) - .sound(SoundType.GLASS) - .noOcclusion()) - .onRegister(connectedTextures(TrapdoorCTBehaviour::new)) - .addLayer(() -> RenderType::cutoutMipped) - .register(); - public static final BlockEntry ITEM_VAULT = REGISTRATE.block("item_vault", ItemVaultBlock::new) .initialProperties(SharedProperties::softMetal) .properties(p -> p.color(MaterialColor.TERRACOTTA_BLUE)) @@ -1654,6 +1670,7 @@ public class AllBlocks { public static final BlockEntry ANDESITE_FUNNEL = REGISTRATE.block("andesite_funnel", AndesiteFunnelBlock::new) + .addLayer(() -> RenderType::cutoutMipped) .initialProperties(SharedProperties::stone) .properties(p -> p.color(MaterialColor.STONE)) .transform(pickaxeOnly()) @@ -1661,22 +1678,25 @@ public class AllBlocks { .onRegister(movementBehaviour(FunnelMovementBehaviour.andesite())) .blockstate(new FunnelGenerator("andesite", false)::generate) .item(FunnelItem::new) + .tag(AllItemTags.CONTRAPTION_CONTROLLED.tag) .model(FunnelGenerator.itemModel("andesite")) .build() .register(); public static final BlockEntry ANDESITE_BELT_FUNNEL = REGISTRATE.block("andesite_belt_funnel", p -> new BeltFunnelBlock(AllBlocks.ANDESITE_FUNNEL, p)) + .addLayer(() -> RenderType::cutoutMipped) .initialProperties(SharedProperties::stone) .properties(p -> p.color(MaterialColor.STONE)) .transform(pickaxeOnly()) .tag(AllBlockTags.SAFE_NBT.tag) - .blockstate(new BeltFunnelGenerator("andesite", new ResourceLocation("block/polished_andesite"))::generate) + .blockstate(new BeltFunnelGenerator("andesite")::generate) .loot((p, b) -> p.dropOther(b, ANDESITE_FUNNEL.get())) .register(); public static final BlockEntry BRASS_FUNNEL = REGISTRATE.block("brass_funnel", BrassFunnelBlock::new) + .addLayer(() -> RenderType::cutoutMipped) .initialProperties(SharedProperties::softMetal) .properties(p -> p.color(MaterialColor.TERRACOTTA_YELLOW)) .transform(pickaxeOnly()) @@ -1684,17 +1704,19 @@ public class AllBlocks { .onRegister(movementBehaviour(FunnelMovementBehaviour.brass())) .blockstate(new FunnelGenerator("brass", true)::generate) .item(FunnelItem::new) + .tag(AllItemTags.CONTRAPTION_CONTROLLED.tag) .model(FunnelGenerator.itemModel("brass")) .build() .register(); public static final BlockEntry BRASS_BELT_FUNNEL = REGISTRATE.block("brass_belt_funnel", p -> new BeltFunnelBlock(AllBlocks.BRASS_FUNNEL, p)) + .addLayer(() -> RenderType::cutoutMipped) .initialProperties(SharedProperties::softMetal) .properties(p -> p.color(MaterialColor.TERRACOTTA_YELLOW)) .transform(pickaxeOnly()) .tag(AllBlockTags.SAFE_NBT.tag) - .blockstate(new BeltFunnelGenerator("brass", Create.asResource("block/brass_block"))::generate) + .blockstate(new BeltFunnelGenerator("brass")::generate) .loot((p, b) -> p.dropOther(b, BRASS_FUNNEL.get())) .register(); @@ -1715,36 +1737,39 @@ public class AllBlocks { .onRegister(connectedTextures(BrassTunnelCTBehaviour::new)) .register(); - public static final BlockEntry CONTENT_OBSERVER = - REGISTRATE.block("content_observer", ContentObserverBlock::new) + public static final BlockEntry SMART_OBSERVER = + REGISTRATE.block("content_observer", SmartObserverBlock::new) .initialProperties(SharedProperties::stone) .properties(p -> p.color(MaterialColor.TERRACOTTA_BROWN)) + .properties(p -> p.noOcclusion()) .transform(axeOrPickaxe()) - .blockstate((c, p) -> p.horizontalBlock(c.get(), AssetLookup.forPowered(c, p))) + .blockstate(new SmartObserverGenerator()::generate) .onRegister(assignDataBehaviour(new ItemCountDisplaySource(), "count_items")) .onRegister(assignDataBehaviour(new ItemListDisplaySource(), "list_items")) .onRegister(assignDataBehaviour(new FluidAmountDisplaySource(), "count_fluids")) .onRegister(assignDataBehaviour(new FluidListDisplaySource(), "list_fluids")) + .lang("Smart Observer") .item() .transform(customItemModel("_", "block")) .register(); - public static final BlockEntry STOCKPILE_SWITCH = - REGISTRATE.block("stockpile_switch", StockpileSwitchBlock::new) + public static final BlockEntry THRESHOLD_SWITCH = + REGISTRATE.block("stockpile_switch", ThresholdSwitchBlock::new) .initialProperties(SharedProperties::stone) .properties(p -> p.color(MaterialColor.TERRACOTTA_BROWN)) + .properties(p -> p.noOcclusion()) .transform(axeOrPickaxe()) - .blockstate((c, p) -> p.horizontalBlock(c.get(), - AssetLookup.withIndicator(c, p, $ -> AssetLookup.standardModel(c, p), StockpileSwitchBlock.INDICATOR))) + .blockstate(new ThresholdSwitchGenerator()::generate) .onRegister(assignDataBehaviour(new FillLevelDisplaySource(), "fill_level")) - .simpleItem() + .lang("Threshold Switch") + .item() + .transform(customItemModel("threshold_switch", "block_wall")) .register(); public static final BlockEntry CREATIVE_CRATE = REGISTRATE.block("creative_crate", CreativeCrateBlock::new) .transform(BuilderTransformers.crate("creative")) .properties(p -> p.color(MaterialColor.COLOR_PURPLE)) - .tag(AllBlockTags.SAFE_NBT.tag) .register(); public static final BlockEntry DISPLAY_LINK = @@ -1840,7 +1865,6 @@ public class AllBlocks { public static final BlockEntry PLACARD = REGISTRATE.block("placard", PlacardBlock::new) .initialProperties(SharedProperties::copperMetal) .transform(pickaxeOnly()) - .tag(AllBlockTags.SAFE_NBT.tag) .blockstate((c, p) -> p.horizontalFaceBlock(c.get(), AssetLookup.standardModel(c, p))) .simpleItem() .register(); @@ -1895,30 +1919,16 @@ public class AllBlocks { // Curiosities - static { - REGISTRATE.startSection(AllSections.CURIOSITIES); - } - - public static final BlockEntry COPPER_BACKTANK = - REGISTRATE.block("copper_backtank", CopperBacktankBlock::new) + public static final BlockEntry COPPER_BACKTANK = + REGISTRATE.block("copper_backtank", BacktankBlock::new) .initialProperties(SharedProperties::copperMetal) - .blockstate((c, p) -> p.horizontalBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p))) - .transform(pickaxeOnly()) - .addLayer(() -> RenderType::cutoutMipped) - .transform(BlockStressDefaults.setImpact(4.0)) - .loot((lt, block) -> { - Builder builder = LootTable.lootTable(); - LootItemCondition.Builder survivesExplosion = ExplosionCondition.survivesExplosion(); - lt.add(block, builder.withPool(LootPool.lootPool() - .when(survivesExplosion) - .setRolls(ConstantValue.exactly(1)) - .add(LootItem.lootTableItem(AllItems.COPPER_BACKTANK.get()) - .apply(CopyNameFunction.copyName(CopyNameFunction.NameSource.BLOCK_ENTITY)) - .apply(CopyNbtFunction.copyData(ContextNbtProvider.BLOCK_ENTITY) - .copy("Air", "Air")) - .apply(CopyNbtFunction.copyData(ContextNbtProvider.BLOCK_ENTITY) - .copy("Enchantments", "Enchantments"))))); - }) + .transform(BuilderTransformers.backtank(AllItems.COPPER_BACKTANK::get)) + .register(); + + public static final BlockEntry NETHERITE_BACKTANK = + REGISTRATE.block("netherite_backtank", BacktankBlock::new) + .initialProperties(SharedProperties::netheriteMetal) + .transform(BuilderTransformers.backtank(AllItems.NETHERITE_BACKTANK::get)) .register(); public static final BlockEntry PECULIAR_BELL = @@ -1960,7 +1970,7 @@ public class AllBlocks { .withExistingParent(colourName + "_toolbox", p.modLoc("block/toolbox/block")) .texture("0", p.modLoc("block/toolbox/" + colourName))); }) - .onRegisterAfter(Registries.ITEM, v -> TooltipHelper.referTo(v, "block.create.toolbox")) + .onRegisterAfter(Registries.ITEM, v -> ItemDescription.useKey(v, "block.create.toolbox")) .tag(AllBlockTags.TOOLBOXES.tag) .item(UncontainableBlockItem::new) .model((c, p) -> p.withExistingParent(colourName + "_toolbox", p.modLoc("block/toolbox/item")) @@ -1970,11 +1980,222 @@ public class AllBlocks { .register(); }); + public static final BlockEntry CLIPBOARD = REGISTRATE.block("clipboard", ClipboardBlock::new) + .initialProperties(SharedProperties::wooden) + .transform(axeOrPickaxe()) + .tag(AllBlockTags.SAFE_NBT.tag) + .blockstate((c, p) -> p.horizontalFaceBlock(c.get(), + s -> AssetLookup.partialBaseModel(c, p, s.getValue(ClipboardBlock.WRITTEN) ? "written" : "empty"))) + .loot((lt, b) -> lt.add(b, BlockLootSubProvider.noDrop())) + .item(ClipboardBlockItem::new) + .onRegister(ClipboardBlockItem::registerModelOverrides) + .model((c, p) -> ClipboardOverrides.addOverrideModels(c, p)) + .build() + .register(); + // Materials - static { - REGISTRATE.startSection(AllSections.PALETTES); - } + public static final BlockEntry ANDESITE_LADDER = + REGISTRATE.block("andesite_ladder", MetalLadderBlock::new) + .transform(BuilderTransformers.ladder("andesite", () -> DataIngredient.items(AllItems.ANDESITE_ALLOY.get()), + MaterialColor.STONE)) + .register(); + + public static final BlockEntry BRASS_LADDER = + REGISTRATE.block("brass_ladder", MetalLadderBlock::new) + .transform(BuilderTransformers.ladder("brass", + () -> DataIngredient.tag(AllTags.forgeItemTag("ingots/brass")), MaterialColor.TERRACOTTA_YELLOW)) + .register(); + + public static final BlockEntry COPPER_LADDER = + REGISTRATE.block("copper_ladder", MetalLadderBlock::new) + .transform(BuilderTransformers.ladder("copper", + () -> DataIngredient.tag(AllTags.forgeItemTag("ingots/copper")), MaterialColor.COLOR_ORANGE)) + .register(); + + public static final BlockEntry ANDESITE_BARS = MetalBarsGen.createBars("andesite", true, + () -> DataIngredient.items(AllItems.ANDESITE_ALLOY.get()), MaterialColor.STONE); + public static final BlockEntry BRASS_BARS = MetalBarsGen.createBars("brass", true, + () -> DataIngredient.tag(AllTags.forgeItemTag("ingots/brass")), MaterialColor.TERRACOTTA_YELLOW); + public static final BlockEntry COPPER_BARS = MetalBarsGen.createBars("copper", true, + () -> DataIngredient.tag(AllTags.forgeItemTag("ingots/copper")), MaterialColor.COLOR_ORANGE); + + public static final BlockEntry ANDESITE_SCAFFOLD = REGISTRATE + .block("andesite_scaffolding", MetalScaffoldingBlock::new) + .transform(BuilderTransformers.scaffold("andesite", () -> DataIngredient.items(AllItems.ANDESITE_ALLOY.get()), + MaterialColor.STONE, AllSpriteShifts.ANDESITE_SCAFFOLD, AllSpriteShifts.ANDESITE_SCAFFOLD_INSIDE, + AllSpriteShifts.ANDESITE_CASING)) + .register(); + + public static final BlockEntry BRASS_SCAFFOLD = + REGISTRATE.block("brass_scaffolding", MetalScaffoldingBlock::new) + .transform(BuilderTransformers.scaffold("brass", + () -> DataIngredient.tag(AllTags.forgeItemTag("ingots/brass")), MaterialColor.TERRACOTTA_YELLOW, + AllSpriteShifts.BRASS_SCAFFOLD, AllSpriteShifts.BRASS_SCAFFOLD_INSIDE, AllSpriteShifts.BRASS_CASING)) + .register(); + + public static final BlockEntry COPPER_SCAFFOLD = + REGISTRATE.block("copper_scaffolding", MetalScaffoldingBlock::new) + .transform(BuilderTransformers.scaffold("copper", + () -> DataIngredient.tag(AllTags.forgeItemTag("ingots/copper")), MaterialColor.COLOR_ORANGE, + AllSpriteShifts.COPPER_SCAFFOLD, AllSpriteShifts.COPPER_SCAFFOLD_INSIDE, AllSpriteShifts.COPPER_CASING)) + .register(); + + public static final BlockEntry METAL_GIRDER = REGISTRATE.block("metal_girder", GirderBlock::new) + .initialProperties(SharedProperties::softMetal) + .blockstate(GirderBlockStateGenerator::blockState) + .properties(p -> p.color(MaterialColor.COLOR_GRAY)) + .properties(p -> p.sound(SoundType.NETHERITE_BLOCK)) + .transform(pickaxeOnly()) + .onRegister(CreateRegistrate.blockModel(() -> ConnectedGirderModel::new)) + .item() + .transform(customItemModel()) + .register(); + + public static final BlockEntry METAL_GIRDER_ENCASED_SHAFT = + REGISTRATE.block("metal_girder_encased_shaft", GirderEncasedShaftBlock::new) + .initialProperties(SharedProperties::softMetal) + .blockstate(GirderBlockStateGenerator::blockStateWithShaft) + .properties(p -> p.color(MaterialColor.COLOR_GRAY)) + .properties(p -> p.sound(SoundType.NETHERITE_BLOCK)) + .transform(pickaxeOnly()) + .loot((p, b) -> p.add(b, p.createSingleItemTable(METAL_GIRDER.get()) + .withPool(p.applyExplosionCondition(SHAFT.get(), LootPool.lootPool() + .setRolls(ConstantValue.exactly(1.0F)) + .add(LootItem.lootTableItem(SHAFT.get())))))) + .onRegister(CreateRegistrate.blockModel(() -> ConnectedGirderModel::new)) + .register(); + + public static final BlockEntry COPYCAT_BASE = REGISTRATE.block("copycat_base", Block::new) + .initialProperties(SharedProperties::softMetal) + .properties(p -> p.color(MaterialColor.GLOW_LICHEN)) + .addLayer(() -> RenderType::cutoutMipped) + .tag(AllBlockTags.FAN_TRANSPARENT.tag) + .transform(pickaxeOnly()) + .blockstate((c, p) -> p.simpleBlock(c.get(), AssetLookup.partialBaseModel(c, p))) + .register(); + + public static final BlockEntry COPYCAT_STEP = + REGISTRATE.block("copycat_step", CopycatStepBlock::new) + .transform(BuilderTransformers.copycat()) + .onRegister(CreateRegistrate.blockModel(() -> CopycatStepModel::new)) + .item() + .recipe((c, p) -> p.stonecutting(DataIngredient.tag(AllTags.forgeItemTag("ingots/zinc")), + RecipeCategory.BUILDING_BLOCKS, c::get, 4)) + .transform(customItemModel("copycat_base", "step")) + .register(); + + public static final BlockEntry COPYCAT_PANEL = + REGISTRATE.block("copycat_panel", CopycatPanelBlock::new) + .transform(BuilderTransformers.copycat()) + .onRegister(CreateRegistrate.blockModel(() -> CopycatPanelModel::new)) + .item() + .recipe((c, p) -> p.stonecutting(DataIngredient.tag(AllTags.forgeItemTag("ingots/zinc")), + RecipeCategory.BUILDING_BLOCKS, c::get, 4)) + .transform(customItemModel("copycat_base", "panel")) + .register(); + + public static final BlockEntry COPYCAT_BARS = + REGISTRATE.block("copycat_bars", WrenchableDirectionalBlock::new) + .blockstate(new SpecialCopycatPanelBlockState("bars")::generate) + .onRegister(CreateRegistrate.blockModel(() -> CopycatBarsModel::new)) + .register(); + + public static final DyedBlockList SEATS = new DyedBlockList<>(colour -> { + String colourName = colour.getSerializedName(); + SeatMovementBehaviour movementBehaviour = new SeatMovementBehaviour(); + SeatInteractionBehaviour interactionBehaviour = new SeatInteractionBehaviour(); + return REGISTRATE.block(colourName + "_seat", p -> new SeatBlock(p, colour)) + .initialProperties(SharedProperties::wooden) + .properties(p -> p.color(colour.getMaterialColor())) + .transform(axeOnly()) + .onRegister(movementBehaviour(movementBehaviour)) + .onRegister(interactionBehaviour(interactionBehaviour)) + .onRegister(assignDataBehaviour(new EntityNameDisplaySource(), "entity_name")) + .blockstate((c, p) -> { + p.simpleBlock(c.get(), p.models() + .withExistingParent(colourName + "_seat", p.modLoc("block/seat")) + .texture("1", p.modLoc("block/seat/top_" + colourName)) + .texture("2", p.modLoc("block/seat/side_" + colourName))); + }) + .recipe((c, p) -> { + ShapelessRecipeBuilder.shapeless(RecipeCategory.BUILDING_BLOCKS, c.get()) + .requires(DyeHelper.getWoolOfDye(colour)) + .requires(ItemTags.WOODEN_SLABS) + .unlockedBy("has_wool", RegistrateRecipeProvider.has(ItemTags.WOOL)) + .save(p, Create.asResource("crafting/kinetics/" + c.getName())); + ShapelessRecipeBuilder.shapeless(RecipeCategory.BUILDING_BLOCKS, c.get()) + .requires(colour.getTag()) + .requires(AllItemTags.SEATS.tag) + .unlockedBy("has_seat", RegistrateRecipeProvider.has(AllItemTags.SEATS.tag)) + .save(p, Create.asResource("crafting/kinetics/" + c.getName() + "_from_other_seat")); + }) + .onRegisterAfter(Registries.ITEM, v -> ItemDescription.useKey(v, "block.create.seat")) + .tag(AllBlockTags.SEATS.tag) + .item() + .tag(AllItemTags.SEATS.tag) + .build() + .register(); + }); + + public static final BlockEntry ANDESITE_DOOR = + REGISTRATE.block("andesite_door", p -> new SlidingDoorBlock(p, true)) + .transform(BuilderTransformers.slidingDoor("andesite")) + .properties(p -> p.color(MaterialColor.STONE) + .sound(SoundType.STONE) + .noOcclusion()) + .register(); + + public static final BlockEntry BRASS_DOOR = + REGISTRATE.block("brass_door", p -> new SlidingDoorBlock(p, false)) + .transform(BuilderTransformers.slidingDoor("brass")) + .properties(p -> p.color(MaterialColor.TERRACOTTA_YELLOW) + .sound(SoundType.STONE) + .noOcclusion()) + .register(); + + public static final BlockEntry COPPER_DOOR = + REGISTRATE.block("copper_door", p -> new SlidingDoorBlock(p, true)) + .transform(BuilderTransformers.slidingDoor("copper")) + .properties(p -> p.color(MaterialColor.COLOR_ORANGE) + .sound(SoundType.STONE) + .noOcclusion()) + .register(); + + public static final BlockEntry TRAIN_DOOR = + REGISTRATE.block("train_door", p -> new SlidingDoorBlock(p, false)) + .transform(BuilderTransformers.slidingDoor("train")) + .properties(p -> p.color(MaterialColor.TERRACOTTA_CYAN) + .sound(SoundType.NETHERITE_BLOCK) + .noOcclusion()) + .register(); + + public static final BlockEntry TRAIN_TRAPDOOR = + REGISTRATE.block("train_trapdoor", TrainTrapdoorBlock::new) + .initialProperties(SharedProperties::softMetal) + .properties(p -> p.color(MaterialColor.TERRACOTTA_CYAN) + .sound(SoundType.NETHERITE_BLOCK)) + .transform(BuilderTransformers.trapdoor(true)) + .register(); + + public static final BlockEntry FRAMED_GLASS_DOOR = + REGISTRATE.block("framed_glass_door", p -> new SlidingDoorBlock(p, false)) + .transform(BuilderTransformers.slidingDoor("glass")) + .properties(p -> p.color(MaterialColor.NONE) + .sound(SoundType.GLASS) + .noOcclusion()) + .register(); + + public static final BlockEntry FRAMED_GLASS_TRAPDOOR = + REGISTRATE.block("framed_glass_trapdoor", TrainTrapdoorBlock::new) + .initialProperties(SharedProperties::softMetal) + .transform(BuilderTransformers.trapdoor(false)) + .properties(p -> p.color(MaterialColor.NONE) + .sound(SoundType.GLASS) + .noOcclusion()) + .onRegister(connectedTextures(TrapdoorCTBehaviour::new)) + .addLayer(() -> RenderType::cutoutMipped) + .register(); public static final BlockEntry ZINC_ORE = REGISTRATE.block("zinc_ore", Block::new) .initialProperties(() -> Blocks.GOLD_ORE) @@ -2023,7 +2244,7 @@ public class AllBlocks { .build() .register(); - public static final BlockEntry ZINC_BLOCK = REGISTRATE.block("zinc_block", p -> new Block(p)) + public static final BlockEntry ZINC_BLOCK = REGISTRATE.block("zinc_block", Block::new) .initialProperties(() -> Blocks.IRON_BLOCK) .properties(p -> p.color(MaterialColor.GLOW_LICHEN)) .properties(p -> p.requiresCorrectToolForDrops()) @@ -2037,12 +2258,41 @@ public class AllBlocks { .lang("Block of Zinc") .register(); + public static final BlockEntry ANDESITE_ALLOY_BLOCK = REGISTRATE.block("andesite_alloy_block", Block::new) + .initialProperties(() -> Blocks.ANDESITE) + .properties(p -> p.color(MaterialColor.STONE)) + .properties(p -> p.requiresCorrectToolForDrops()) + .transform(pickaxeOnly()) + .blockstate(simpleCubeAll("andesite_block")) + .tag(Tags.Blocks.STORAGE_BLOCKS) + .transform(tagBlockAndItem("storage_blocks/andesite_alloy")) + .tag(Tags.Items.STORAGE_BLOCKS) + .build() + .lang("Block of Andesite Alloy") + .register(); + + public static final BlockEntry INDUSTRIAL_IRON_BLOCK = REGISTRATE.block("industrial_iron_block", Block::new) + .initialProperties(SharedProperties::softMetal) + .properties(p -> p.color(MaterialColor.COLOR_GRAY)) + .properties(p -> p.sound(SoundType.NETHERITE_BLOCK)) + .properties(p -> p.requiresCorrectToolForDrops()) + .transform(pickaxeOnly()) + .blockstate((c, p) -> p.simpleBlock(c.get(), p.models() + .cubeColumn(c.getName(), p.modLoc("block/industrial_iron_block"), + p.modLoc("block/industrial_iron_block_top")))) + .tag(AllBlockTags.WRENCH_PICKUP.tag) + .lang("Block of Industrial Iron") + .recipe((c, p) -> p.stonecutting(DataIngredient.tag(Tags.Items.INGOTS_IRON), RecipeCategory.BUILDING_BLOCKS, + c::get, 2)) + .simpleItem() + .register(); + public static final BlockEntry BRASS_BLOCK = REGISTRATE.block("brass_block", Block::new) .initialProperties(() -> Blocks.IRON_BLOCK) .properties(p -> p.color(MaterialColor.TERRACOTTA_YELLOW)) .properties(p -> p.requiresCorrectToolForDrops()) .transform(pickaxeOnly()) - .blockstate(simpleCubeAll("brass_storage_block")) + .blockstate(simpleCubeAll("brass_block")) .tag(BlockTags.NEEDS_IRON_TOOL) .tag(Tags.Blocks.STORAGE_BLOCKS) .tag(BlockTags.BEACON_BASE_BLOCKS) @@ -2052,6 +2302,26 @@ public class AllBlocks { .lang("Block of Brass") .register(); + public static final BlockEntry EXPERIENCE_BLOCK = + REGISTRATE.block("experience_block", ExperienceBlock::new) + .initialProperties(SharedProperties::softMetal) + .properties(p -> p.color(MaterialColor.PLANT)) + .properties(p -> p.sound(new ForgeSoundType(1, .5f, () -> SoundEvents.AMETHYST_BLOCK_BREAK, + () -> SoundEvents.AMETHYST_BLOCK_STEP, () -> SoundEvents.AMETHYST_BLOCK_PLACE, + () -> SoundEvents.AMETHYST_BLOCK_HIT, () -> SoundEvents.AMETHYST_BLOCK_FALL))) + .properties(p -> p.requiresCorrectToolForDrops()) + .properties(p -> p.lightLevel(s -> 15)) + .blockstate((c, p) -> p.simpleBlock(c.get(), AssetLookup.standardModel(c, p))) + .transform(pickaxeOnly()) + .lang("Block of Experience") + .tag(Tags.Blocks.STORAGE_BLOCKS) + .tag(BlockTags.BEACON_BASE_BLOCKS) + .item() + .properties(p -> p.rarity(Rarity.UNCOMMON)) + .tag(Tags.Items.STORAGE_BLOCKS) + .build() + .register(); + public static final BlockEntry ROSE_QUARTZ_BLOCK = REGISTRATE.block("rose_quartz_block", RotatedPillarBlock::new) .initialProperties(() -> Blocks.AMETHYST_BLOCK) @@ -2092,13 +2362,13 @@ public class AllBlocks { public static final CopperBlockSet COPPER_SHINGLES = new CopperBlockSet(REGISTRATE, "copper_shingles", "copper_roof_top", CopperBlockSet.DEFAULT_VARIANTS, (c, p) -> { - p.stonecutting(DataIngredient.tag(AllTags.forgeItemTag("plates/copper")), RecipeCategory.BUILDING_BLOCKS, + p.stonecutting(DataIngredient.tag(AllTags.forgeItemTag("ingots/copper")), RecipeCategory.BUILDING_BLOCKS, c::get, 2); }); public static final CopperBlockSet COPPER_TILES = new CopperBlockSet(REGISTRATE, "copper_tiles", "copper_roof_top", CopperBlockSet.DEFAULT_VARIANTS, (c, p) -> { - p.stonecutting(DataIngredient.tag(AllTags.forgeItemTag("plates/copper")), RecipeCategory.BUILDING_BLOCKS, + p.stonecutting(DataIngredient.tag(AllTags.forgeItemTag("ingots/copper")), RecipeCategory.BUILDING_BLOCKS, c::get, 2); }); diff --git a/src/main/java/com/simibubi/create/AllBogeyStyles.java b/src/main/java/com/simibubi/create/AllBogeyStyles.java new file mode 100644 index 000000000..96b5c1568 --- /dev/null +++ b/src/main/java/com/simibubi/create/AllBogeyStyles.java @@ -0,0 +1,132 @@ +package com.simibubi.create; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.function.Supplier; + +import com.google.common.collect.ImmutableMap; +import com.simibubi.create.content.trains.bogey.AbstractBogeyBlock; +import com.simibubi.create.content.trains.bogey.BogeyRenderer; +import com.simibubi.create.content.trains.bogey.BogeyRenderer.CommonRenderer; +import com.simibubi.create.content.trains.bogey.BogeySizes; +import com.simibubi.create.content.trains.bogey.BogeyStyle; +import com.simibubi.create.content.trains.bogey.StandardBogeyRenderer.CommonStandardBogeyRenderer; +import com.simibubi.create.content.trains.bogey.StandardBogeyRenderer.LargeStandardBogeyRenderer; +import com.simibubi.create.content.trains.bogey.StandardBogeyRenderer.SmallStandardBogeyRenderer; +import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.Lang; +import com.tterrag.registrate.util.entry.BlockEntry; + +import net.minecraft.core.particles.ParticleOptions; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; + +public class AllBogeyStyles { + public static final Map BOGEY_STYLES = new HashMap<>(); + public static final Map> CYCLE_GROUPS = new HashMap<>(); + private static final Map EMPTY_GROUP = ImmutableMap.of(); + + public static Map getCycleGroup(ResourceLocation cycleGroup) { + return CYCLE_GROUPS.getOrDefault(cycleGroup, EMPTY_GROUP); + } + + public static final String STANDARD_CYCLE_GROUP = "standard"; + + public static final BogeyStyle STANDARD = + create("standard", STANDARD_CYCLE_GROUP).commonRenderer(() -> CommonStandardBogeyRenderer::new) + .displayName(Components.translatable("create.bogey.style.standard")) + .size(BogeySizes.SMALL, () -> SmallStandardBogeyRenderer::new, AllBlocks.SMALL_BOGEY) + .size(BogeySizes.LARGE, () -> LargeStandardBogeyRenderer::new, AllBlocks.LARGE_BOGEY) + .build(); + + private static BogeyStyleBuilder create(String name, String cycleGroup) { + return create(Create.asResource(name), Create.asResource(cycleGroup)); + } + + public static BogeyStyleBuilder create(ResourceLocation name, ResourceLocation cycleGroup) { + return new BogeyStyleBuilder(name, cycleGroup); + } + + public static void register() {} + + public static class BogeyStyleBuilder { + protected final Map> sizeRenderers = new HashMap<>(); + protected final Map sizes = new HashMap<>(); + protected final ResourceLocation name; + protected final ResourceLocation cycleGroup; + + protected Component displayName = Lang.translateDirect("bogey.style.invalid"); + protected ResourceLocation soundType = AllSoundEvents.TRAIN2.getId(); + protected CompoundTag defaultData = new CompoundTag(); + protected ParticleOptions contactParticle = ParticleTypes.CRIT; + protected ParticleOptions smokeParticle = ParticleTypes.POOF; + protected Optional> commonRenderer = Optional.empty(); + + public BogeyStyleBuilder(ResourceLocation name, ResourceLocation cycleGroup) { + this.name = name; + this.cycleGroup = cycleGroup; + } + + public BogeyStyleBuilder displayName(Component displayName) { + this.displayName = displayName; + return this; + } + + public BogeyStyleBuilder soundType(ResourceLocation soundType) { + this.soundType = soundType; + return this; + } + + public BogeyStyleBuilder defaultData(CompoundTag defaultData) { + this.defaultData = defaultData; + return this; + } + + public BogeyStyleBuilder size(BogeySizes.BogeySize size, Supplier> renderer, + BlockEntry> blockEntry) { + this.size(size, renderer, blockEntry.getId()); + return this; + } + + public BogeyStyleBuilder size(BogeySizes.BogeySize size, Supplier> renderer, + ResourceLocation location) { + this.sizes.put(size, location); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { + this.sizeRenderers.put(size, () -> new BogeyStyle.SizeRenderData(renderer.get(), renderer.get() + .get())); + }); + return this; + } + + public BogeyStyleBuilder contactParticle(ParticleOptions contactParticle) { + this.contactParticle = contactParticle; + return this; + } + + public BogeyStyleBuilder smokeParticle(ParticleOptions smokeParticle) { + this.smokeParticle = smokeParticle; + return this; + } + + public BogeyStyleBuilder commonRenderer(Supplier> commonRenderer) { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { + this.commonRenderer = Optional.of(commonRenderer.get()); + }); + return this; + } + + public BogeyStyle build() { + BogeyStyle entry = new BogeyStyle(name, cycleGroup, displayName, soundType, contactParticle, smokeParticle, + defaultData, sizes, sizeRenderers, commonRenderer); + BOGEY_STYLES.put(name, entry); + CYCLE_GROUPS.computeIfAbsent(cycleGroup, l -> new HashMap<>()) + .put(name, entry); + return entry; + } + } +} diff --git a/src/main/java/com/simibubi/create/AllContainerTypes.java b/src/main/java/com/simibubi/create/AllContainerTypes.java deleted file mode 100644 index a5da0970f..000000000 --- a/src/main/java/com/simibubi/create/AllContainerTypes.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.simibubi.create; - -import com.simibubi.create.content.curiosities.toolbox.ToolboxContainer; -import com.simibubi.create.content.curiosities.toolbox.ToolboxScreen; -import com.simibubi.create.content.curiosities.tools.BlueprintContainer; -import com.simibubi.create.content.curiosities.tools.BlueprintScreen; -import com.simibubi.create.content.logistics.item.LinkedControllerContainer; -import com.simibubi.create.content.logistics.item.LinkedControllerScreen; -import com.simibubi.create.content.logistics.item.filter.AttributeFilterContainer; -import com.simibubi.create.content.logistics.item.filter.AttributeFilterScreen; -import com.simibubi.create.content.logistics.item.filter.FilterContainer; -import com.simibubi.create.content.logistics.item.filter.FilterScreen; -import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleContainer; -import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleScreen; -import com.simibubi.create.content.schematics.block.SchematicTableContainer; -import com.simibubi.create.content.schematics.block.SchematicTableScreen; -import com.simibubi.create.content.schematics.block.SchematicannonContainer; -import com.simibubi.create.content.schematics.block.SchematicannonScreen; -import com.tterrag.registrate.builders.MenuBuilder.ForgeMenuFactory; -import com.tterrag.registrate.builders.MenuBuilder.ScreenFactory; -import com.tterrag.registrate.util.entry.MenuEntry; -import com.tterrag.registrate.util.nullness.NonNullSupplier; - -import net.minecraft.client.gui.screens.Screen; -import net.minecraft.client.gui.screens.inventory.MenuAccess; -import net.minecraft.world.inventory.AbstractContainerMenu; - -public class AllContainerTypes { - - public static final MenuEntry SCHEMATIC_TABLE = - register("schematic_table", SchematicTableContainer::new, () -> SchematicTableScreen::new); - - public static final MenuEntry SCHEMATICANNON = - register("schematicannon", SchematicannonContainer::new, () -> SchematicannonScreen::new); - - public static final MenuEntry FILTER = - register("filter", FilterContainer::new, () -> FilterScreen::new); - - public static final MenuEntry ATTRIBUTE_FILTER = - register("attribute_filter", AttributeFilterContainer::new, () -> AttributeFilterScreen::new); - - public static final MenuEntry CRAFTING_BLUEPRINT = - register("crafting_blueprint", BlueprintContainer::new, () -> BlueprintScreen::new); - - public static final MenuEntry LINKED_CONTROLLER = - register("linked_controller", LinkedControllerContainer::new, () -> LinkedControllerScreen::new); - - public static final MenuEntry TOOLBOX = - register("toolbox", ToolboxContainer::new, () -> ToolboxScreen::new); - - public static final MenuEntry SCHEDULE = - register("schedule", ScheduleContainer::new, () -> ScheduleScreen::new); - - private static > MenuEntry register( - String name, ForgeMenuFactory factory, NonNullSupplier> screenFactory) { - return Create.REGISTRATE - .menu(name, factory, screenFactory) - .register(); - } - - public static void register() {} - -} diff --git a/src/main/java/com/simibubi/create/AllCreativeModeTabs.java b/src/main/java/com/simibubi/create/AllCreativeModeTabs.java index f5cd01592..8741c4ec7 100644 --- a/src/main/java/com/simibubi/create/AllCreativeModeTabs.java +++ b/src/main/java/com/simibubi/create/AllCreativeModeTabs.java @@ -1,6 +1,5 @@ package com.simibubi.create; -import java.util.EnumSet; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -8,12 +7,11 @@ import java.util.Set; import java.util.function.Function; import java.util.function.Predicate; -import com.simibubi.create.content.AllSections; -import com.simibubi.create.content.contraptions.components.actors.SeatBlock; -import com.simibubi.create.content.contraptions.components.crank.ValveHandleBlock; -import com.simibubi.create.content.curiosities.armor.BackTankUtil; -import com.simibubi.create.content.curiosities.toolbox.ToolboxBlock; -import com.simibubi.create.content.palettes.AllPaletteBlocks; +import com.simibubi.create.content.contraptions.actors.seat.SeatBlock; +import com.simibubi.create.content.decoration.palettes.AllPaletteBlocks; +import com.simibubi.create.content.equipment.armor.BacktankUtil; +import com.simibubi.create.content.equipment.toolbox.ToolboxBlock; +import com.simibubi.create.content.kinetics.crank.ValveHandleBlock; import com.simibubi.create.foundation.item.TagDependentIngredientItem; import com.tterrag.registrate.util.entry.BlockEntry; import com.tterrag.registrate.util.entry.ItemEntry; @@ -34,10 +32,10 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.world.flag.FeatureFlagSet; import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.CreativeModeTab; -import net.minecraft.world.item.CreativeModeTabs; import net.minecraft.world.item.CreativeModeTab.DisplayItemsGenerator; import net.minecraft.world.item.CreativeModeTab.Output; import net.minecraft.world.item.CreativeModeTab.TabVisibility; +import net.minecraft.world.item.CreativeModeTabs; import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; @@ -58,16 +56,17 @@ public class AllCreativeModeTabs { @SubscribeEvent public static void onCreativeModeTabRegister(CreativeModeTabEvent.Register event) { + // FIXME: 1.19.3 this used to filter by AllSections.PALETTES baseTab = event.registerCreativeModeTab(BASE_TAB_ID, List.of(PALETTES_TAB_ID), List.of(CreativeModeTabs.SPAWN_EGGS), builder -> { builder.title(Component.translatable("itemGroup.create.base")) .icon(() -> AllBlocks.COGWHEEL.asStack()) - .displayItems(new RegistrateDisplayItemsGenerator(EnumSet.complementOf(EnumSet.of(AllSections.PALETTES)), true)); + .displayItems(new RegistrateDisplayItemsGenerator(true)); }); palettesTab = event.registerCreativeModeTab(PALETTES_TAB_ID, List.of(), List.of(CreativeModeTabs.SPAWN_EGGS, BASE_TAB_ID), builder -> { builder.title(Component.translatable("itemGroup.create.palettes")) .icon(() -> AllPaletteBlocks.ORNATE_IRON_WINDOW.asStack()) - .displayItems(new RegistrateDisplayItemsGenerator(EnumSet.of(AllSections.PALETTES), false)); + .displayItems(new RegistrateDisplayItemsGenerator(false)); }); } @@ -80,11 +79,11 @@ public class AllCreativeModeTabs { } private static class RegistrateDisplayItemsGenerator implements DisplayItemsGenerator { - private final EnumSet sections; +// private final EnumSet sections; private final boolean addItems; - public RegistrateDisplayItemsGenerator(EnumSet sections, boolean addItems) { - this.sections = sections; + public RegistrateDisplayItemsGenerator(boolean addItems) { +// this.sections = sections; this.addItems = addItems; } private static Predicate makeExclusionPredicate() { @@ -168,7 +167,7 @@ public class AllCreativeModeTabs { Map, Function> simpleFactories = Map.of( AllItems.COPPER_BACKTANK, item -> { ItemStack stack = new ItemStack(item); - stack.getOrCreateTag().putInt("Air", BackTankUtil.maxAirWithoutEnchants()); + stack.getOrCreateTag().putInt("Air", BacktankUtil.maxAirWithoutEnchants()); return stack; } ); @@ -250,8 +249,8 @@ public class AllCreativeModeTabs { private List collectBlocks(Predicate exclusionPredicate) { List items = new ReferenceArrayList<>(); - for (AllSections section : sections) { - for (RegistryEntry entry : Create.REGISTRATE.getAll(section, Registries.BLOCK)) { +// for (AllSections section : sections) { + for (RegistryEntry entry : Create.REGISTRATE.getAll(Registries.BLOCK)) { Item item = entry.get().asItem(); if (item != Items.AIR) { if (!exclusionPredicate.test(item)) { @@ -259,15 +258,15 @@ public class AllCreativeModeTabs { } } } - } +// } items = new ReferenceArrayList<>(new ReferenceLinkedOpenHashSet<>(items)); return items; } private List collectItems(ItemRenderer itemRenderer, boolean special, Predicate exclusionPredicate) { List items = new ReferenceArrayList<>(); - for (AllSections section : sections) { - for (RegistryEntry entry : Create.REGISTRATE.getAll(section, Registries.ITEM)) { +// for (AllSections section : sections) { + for (RegistryEntry entry : Create.REGISTRATE.getAll(Registries.ITEM)) { Item item = entry.get(); if (!(item instanceof BlockItem)) { BakedModel model = itemRenderer.getModel(new ItemStack(item), null, null, 0); @@ -278,7 +277,7 @@ public class AllCreativeModeTabs { } } } - } +// } return items; } @@ -324,4 +323,4 @@ public class AllCreativeModeTabs { } } } -} +} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/AllEnchantments.java b/src/main/java/com/simibubi/create/AllEnchantments.java index 135933ab8..3f0a3f863 100644 --- a/src/main/java/com/simibubi/create/AllEnchantments.java +++ b/src/main/java/com/simibubi/create/AllEnchantments.java @@ -2,8 +2,8 @@ package com.simibubi.create; import static com.simibubi.create.Create.REGISTRATE; -import com.simibubi.create.content.curiosities.armor.CapacityEnchantment; -import com.simibubi.create.content.curiosities.weapons.PotatoRecoveryEnchantment; +import com.simibubi.create.content.equipment.armor.CapacityEnchantment; +import com.simibubi.create.content.equipment.potatoCannon.PotatoRecoveryEnchantment; import com.tterrag.registrate.util.entry.RegistryEntry; import net.minecraft.world.entity.EquipmentSlot; diff --git a/src/main/java/com/simibubi/create/AllEntityDataSerializers.java b/src/main/java/com/simibubi/create/AllEntityDataSerializers.java index 6227bea7d..ad3932e90 100644 --- a/src/main/java/com/simibubi/create/AllEntityDataSerializers.java +++ b/src/main/java/com/simibubi/create/AllEntityDataSerializers.java @@ -1,6 +1,6 @@ package com.simibubi.create; -import com.simibubi.create.content.logistics.trains.entity.CarriageSyncDataSerializer; +import com.simibubi.create.content.trains.entity.CarriageSyncDataSerializer; import net.minecraft.network.syncher.EntityDataSerializer; import net.minecraftforge.eventbus.api.IEventBus; diff --git a/src/main/java/com/simibubi/create/AllEntityTypes.java b/src/main/java/com/simibubi/create/AllEntityTypes.java index 2b4161e76..5d6b70220 100644 --- a/src/main/java/com/simibubi/create/AllEntityTypes.java +++ b/src/main/java/com/simibubi/create/AllEntityTypes.java @@ -1,21 +1,21 @@ package com.simibubi.create; -import com.simibubi.create.content.contraptions.components.actors.SeatEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntityRenderer; -import com.simibubi.create.content.contraptions.components.structureMovement.gantry.GantryContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueRenderer; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionEntityRenderer; -import com.simibubi.create.content.curiosities.tools.BlueprintEntity; -import com.simibubi.create.content.curiosities.tools.BlueprintRenderer; -import com.simibubi.create.content.curiosities.weapons.PotatoProjectileEntity; -import com.simibubi.create.content.curiosities.weapons.PotatoProjectileRenderer; -import com.simibubi.create.content.logistics.trains.entity.CarriageContraptionEntity; -import com.simibubi.create.content.logistics.trains.entity.CarriageContraptionEntityRenderer; -import com.simibubi.create.content.logistics.trains.entity.CarriageContraptionInstance; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.ControlledContraptionEntity; +import com.simibubi.create.content.contraptions.OrientedContraptionEntity; +import com.simibubi.create.content.contraptions.actors.seat.SeatEntity; +import com.simibubi.create.content.contraptions.gantry.GantryContraptionEntity; +import com.simibubi.create.content.contraptions.glue.SuperGlueEntity; +import com.simibubi.create.content.contraptions.glue.SuperGlueRenderer; +import com.simibubi.create.content.contraptions.render.ContraptionEntityRenderer; +import com.simibubi.create.content.contraptions.render.OrientedContraptionEntityRenderer; +import com.simibubi.create.content.equipment.blueprint.BlueprintEntity; +import com.simibubi.create.content.equipment.blueprint.BlueprintRenderer; +import com.simibubi.create.content.equipment.potatoCannon.PotatoProjectileEntity; +import com.simibubi.create.content.equipment.potatoCannon.PotatoProjectileRenderer; +import com.simibubi.create.content.trains.entity.CarriageContraptionEntity; +import com.simibubi.create.content.trains.entity.CarriageContraptionEntityRenderer; +import com.simibubi.create.content.trains.entity.CarriageContraptionInstance; import com.simibubi.create.foundation.data.CreateEntityBuilder; import com.simibubi.create.foundation.utility.Lang; import com.tterrag.registrate.util.entry.EntityEntry; diff --git a/src/main/java/com/simibubi/create/AllFluids.java b/src/main/java/com/simibubi/create/AllFluids.java index e3ec85004..3a5765df5 100644 --- a/src/main/java/com/simibubi/create/AllFluids.java +++ b/src/main/java/com/simibubi/create/AllFluids.java @@ -7,10 +7,10 @@ import java.util.function.Consumer; import javax.annotation.Nullable; import com.simibubi.create.AllTags.AllFluidTags; -import com.simibubi.create.content.contraptions.fluids.VirtualFluid; -import com.simibubi.create.content.contraptions.fluids.potion.PotionFluid; -import com.simibubi.create.content.contraptions.fluids.potion.PotionFluid.PotionFluidType; -import com.simibubi.create.content.palettes.AllPaletteStoneTypes; +import com.simibubi.create.content.decoration.palettes.AllPaletteStoneTypes; +import com.simibubi.create.content.fluids.VirtualFluid; +import com.simibubi.create.content.fluids.potion.PotionFluid; +import com.simibubi.create.content.fluids.potion.PotionFluid.PotionFluidType; import com.tterrag.registrate.util.entry.FluidEntry; import net.minecraft.core.BlockPos; diff --git a/src/main/java/com/simibubi/create/AllInteractionBehaviours.java b/src/main/java/com/simibubi/create/AllInteractionBehaviours.java index e953871cc..31c518c5f 100644 --- a/src/main/java/com/simibubi/create/AllInteractionBehaviours.java +++ b/src/main/java/com/simibubi/create/AllInteractionBehaviours.java @@ -5,11 +5,11 @@ import java.util.List; import org.jetbrains.annotations.Nullable; -import com.simibubi.create.content.contraptions.components.structureMovement.MovingInteractionBehaviour; -import com.simibubi.create.content.contraptions.components.structureMovement.interaction.DoorMovingInteraction; -import com.simibubi.create.content.contraptions.components.structureMovement.interaction.LeverMovingInteraction; -import com.simibubi.create.content.contraptions.components.structureMovement.interaction.TrapdoorMovingInteraction; -import com.simibubi.create.foundation.utility.CreateRegistry; +import com.simibubi.create.content.contraptions.behaviour.DoorMovingInteraction; +import com.simibubi.create.content.contraptions.behaviour.LeverMovingInteraction; +import com.simibubi.create.content.contraptions.behaviour.MovingInteractionBehaviour; +import com.simibubi.create.content.contraptions.behaviour.TrapdoorMovingInteraction; +import com.simibubi.create.foundation.utility.AttachedRegistry; import com.tterrag.registrate.util.nullness.NonNullConsumer; import net.minecraft.resources.ResourceLocation; @@ -20,7 +20,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraftforge.registries.ForgeRegistries; public class AllInteractionBehaviours { - private static final CreateRegistry BLOCK_BEHAVIOURS = new CreateRegistry<>(ForgeRegistries.BLOCKS); + private static final AttachedRegistry BLOCK_BEHAVIOURS = new AttachedRegistry<>(ForgeRegistries.BLOCKS); private static final List GLOBAL_BEHAVIOURS = new ArrayList<>(); public static void registerBehaviour(ResourceLocation block, MovingInteractionBehaviour provider) { diff --git a/src/main/java/com/simibubi/create/AllItems.java b/src/main/java/com/simibubi/create/AllItems.java index 28675b261..40fcefb7c 100644 --- a/src/main/java/com/simibubi/create/AllItems.java +++ b/src/main/java/com/simibubi/create/AllItems.java @@ -2,14 +2,9 @@ package com.simibubi.create; import static com.simibubi.create.AllTags.forgeItemTag; import static com.simibubi.create.AllTags.AllItemTags.CREATE_INGOTS; -import static com.simibubi.create.AllTags.AllItemTags.CRUSHED_ORES; +import static com.simibubi.create.AllTags.AllItemTags.CRUSHED_RAW_MATERIALS; import static com.simibubi.create.AllTags.AllItemTags.PLATES; import static com.simibubi.create.Create.REGISTRATE; -import static com.simibubi.create.content.AllSections.CURIOSITIES; -import static com.simibubi.create.content.AllSections.KINETICS; -import static com.simibubi.create.content.AllSections.LOGISTICS; -import static com.simibubi.create.content.AllSections.MATERIALS; -import static com.simibubi.create.content.AllSections.SCHEMATICS; import static com.simibubi.create.foundation.data.recipe.CompatMetals.ALUMINUM; import static com.simibubi.create.foundation.data.recipe.CompatMetals.LEAD; import static com.simibubi.create.foundation.data.recipe.CompatMetals.NICKEL; @@ -21,62 +16,57 @@ import static com.simibubi.create.foundation.data.recipe.CompatMetals.TIN; import static com.simibubi.create.foundation.data.recipe.CompatMetals.URANIUM; import com.simibubi.create.AllTags.AllItemTags; -import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueItem; -import com.simibubi.create.content.contraptions.components.structureMovement.mounted.MinecartContraptionItem; -import com.simibubi.create.content.contraptions.components.structureMovement.train.MinecartCouplingItem; -import com.simibubi.create.content.contraptions.goggles.GogglesItem; -import com.simibubi.create.content.contraptions.goggles.GogglesModel; -import com.simibubi.create.content.contraptions.itemAssembly.SequencedAssemblyItem; -import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlockItem; -import com.simibubi.create.content.contraptions.relays.belt.item.BeltConnectorItem; -import com.simibubi.create.content.contraptions.relays.gearbox.VerticalGearboxItem; -import com.simibubi.create.content.contraptions.wrench.WrenchItem; -import com.simibubi.create.content.curiosities.BuildersTeaItem; -import com.simibubi.create.content.curiosities.ChromaticCompoundColor; -import com.simibubi.create.content.curiosities.ChromaticCompoundItem; -import com.simibubi.create.content.curiosities.CombustibleItem; -import com.simibubi.create.content.curiosities.ExperienceNuggetItem; -import com.simibubi.create.content.curiosities.RefinedRadianceItem; -import com.simibubi.create.content.curiosities.ShadowSteelItem; -import com.simibubi.create.content.curiosities.TreeFertilizerItem; -import com.simibubi.create.content.curiosities.armor.CopperArmorItem; -import com.simibubi.create.content.curiosities.armor.CopperBacktankItem; -import com.simibubi.create.content.curiosities.armor.CopperBacktankItem.CopperBacktankBlockItem; -import com.simibubi.create.content.curiosities.armor.DivingBootsItem; -import com.simibubi.create.content.curiosities.armor.DivingHelmetItem; -import com.simibubi.create.content.curiosities.symmetry.SymmetryWandItem; -import com.simibubi.create.content.curiosities.tools.BlueprintItem; -import com.simibubi.create.content.curiosities.tools.ExtendoGripItem; -import com.simibubi.create.content.curiosities.tools.SandPaperItem; -import com.simibubi.create.content.curiosities.weapons.PotatoCannonItem; -import com.simibubi.create.content.curiosities.zapper.terrainzapper.WorldshaperItem; -import com.simibubi.create.content.logistics.item.LinkedControllerItem; -import com.simibubi.create.content.logistics.item.filter.FilterItem; -import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleItem; -import com.simibubi.create.content.schematics.item.SchematicAndQuillItem; -import com.simibubi.create.content.schematics.item.SchematicItem; +import com.simibubi.create.content.contraptions.glue.SuperGlueItem; +import com.simibubi.create.content.contraptions.minecart.MinecartCouplingItem; +import com.simibubi.create.content.contraptions.mounted.MinecartContraptionItem; +import com.simibubi.create.content.equipment.BuildersTeaItem; +import com.simibubi.create.content.equipment.TreeFertilizerItem; +import com.simibubi.create.content.equipment.armor.AllArmorMaterials; +import com.simibubi.create.content.equipment.armor.BacktankItem; +import com.simibubi.create.content.equipment.armor.BacktankItem.BacktankBlockItem; +import com.simibubi.create.content.equipment.armor.DivingBootsItem; +import com.simibubi.create.content.equipment.armor.DivingHelmetItem; +import com.simibubi.create.content.equipment.blueprint.BlueprintItem; +import com.simibubi.create.content.equipment.extendoGrip.ExtendoGripItem; +import com.simibubi.create.content.equipment.goggles.GogglesItem; +import com.simibubi.create.content.equipment.goggles.GogglesModel; +import com.simibubi.create.content.equipment.potatoCannon.PotatoCannonItem; +import com.simibubi.create.content.equipment.sandPaper.SandPaperItem; +import com.simibubi.create.content.equipment.symmetryWand.SymmetryWandItem; +import com.simibubi.create.content.equipment.wrench.WrenchItem; +import com.simibubi.create.content.equipment.zapper.terrainzapper.WorldshaperItem; +import com.simibubi.create.content.kinetics.belt.item.BeltConnectorItem; +import com.simibubi.create.content.kinetics.gearbox.VerticalGearboxItem; +import com.simibubi.create.content.legacy.ChromaticCompoundColor; +import com.simibubi.create.content.legacy.ChromaticCompoundItem; +import com.simibubi.create.content.legacy.RefinedRadianceItem; +import com.simibubi.create.content.legacy.ShadowSteelItem; +import com.simibubi.create.content.logistics.filter.FilterItem; +import com.simibubi.create.content.materials.ExperienceNuggetItem; +import com.simibubi.create.content.processing.burner.BlazeBurnerBlockItem; +import com.simibubi.create.content.processing.sequenced.SequencedAssemblyItem; +import com.simibubi.create.content.redstone.link.controller.LinkedControllerItem; +import com.simibubi.create.content.schematics.SchematicAndQuillItem; +import com.simibubi.create.content.schematics.SchematicItem; +import com.simibubi.create.content.trains.schedule.ScheduleItem; import com.simibubi.create.foundation.data.AssetLookup; import com.simibubi.create.foundation.data.CreateRegistrate; import com.simibubi.create.foundation.data.recipe.CompatMetals; +import com.simibubi.create.foundation.item.CombustibleItem; +import com.simibubi.create.foundation.item.ItemDescription; import com.simibubi.create.foundation.item.TagDependentIngredientItem; -import com.simibubi.create.foundation.item.TooltipHelper; import com.tterrag.registrate.util.entry.ItemEntry; import net.minecraft.tags.ItemTags; import net.minecraft.tags.TagKey; import net.minecraft.world.food.FoodProperties; +import net.minecraft.world.item.ArmorMaterials; import net.minecraft.world.item.Item; import net.minecraft.world.item.Rarity; import net.minecraftforge.common.Tags; public class AllItems { - // Schematics - - static { - REGISTRATE.startSection(MATERIALS); - } - public static final ItemEntry WHEAT_FLOUR = taggedIngredient("wheat_flour", forgeItemTag("flour/wheat"), forgeItemTag("flour")), DOUGH = taggedIngredient("dough", forgeItemTag("dough"), forgeItemTag("dough/wheat")), @@ -183,10 +173,10 @@ public class AllItems { IRON_SHEET = taggedIngredient("iron_sheet", forgeItemTag("plates/iron"), PLATES.tag), GOLDEN_SHEET = taggedIngredient("golden_sheet", forgeItemTag("plates/gold"), PLATES.tag, ItemTags.PIGLIN_LOVED), - CRUSHED_IRON = taggedIngredient("crushed_iron_ore", CRUSHED_ORES.tag), - CRUSHED_GOLD = taggedIngredient("crushed_gold_ore", CRUSHED_ORES.tag, ItemTags.PIGLIN_LOVED), - CRUSHED_COPPER = taggedIngredient("crushed_copper_ore", CRUSHED_ORES.tag), - CRUSHED_ZINC = taggedIngredient("crushed_zinc_ore", CRUSHED_ORES.tag); + CRUSHED_IRON = taggedIngredient("crushed_raw_iron", CRUSHED_RAW_MATERIALS.tag), + CRUSHED_GOLD = taggedIngredient("crushed_raw_gold", CRUSHED_RAW_MATERIALS.tag, ItemTags.PIGLIN_LOVED), + CRUSHED_COPPER = taggedIngredient("crushed_raw_copper", CRUSHED_RAW_MATERIALS.tag), + CRUSHED_ZINC = taggedIngredient("crushed_raw_zinc", CRUSHED_RAW_MATERIALS.tag); public static final ItemEntry CRUSHED_OSMIUM = compatCrushedOre(OSMIUM), CRUSHED_PLATINUM = compatCrushedOre(PLATINUM), CRUSHED_SILVER = compatCrushedOre(SILVER), @@ -196,10 +186,6 @@ public class AllItems { // Kinetics - static { - REGISTRATE.startSection(KINETICS); - } - public static final ItemEntry BELT_CONNECTOR = REGISTRATE.item("belt_connector", BeltConnectorItem::new) .lang("Mechanical Belt") @@ -236,22 +222,72 @@ public class AllItems { // wrapped by COPPER_BACKTANK for block placement uses. // must be registered as of 1.18.2 - public static final ItemEntry COPPER_BACKTANK_PLACEABLE = REGISTRATE - .item("copper_backtank_placeable", p -> new CopperBacktankBlockItem(AllBlocks.COPPER_BACKTANK.get(), p)) + public static final ItemEntry COPPER_BACKTANK_PLACEABLE = REGISTRATE + .item("copper_backtank_placeable", + p -> new BacktankBlockItem(AllBlocks.COPPER_BACKTANK.get(), AllItems.COPPER_BACKTANK::get, p)) .model((c, p) -> p.withExistingParent(c.getName(), p.mcLoc("item/barrier"))) .register(); - public static final ItemEntry + // wrapped by NETHERITE_BACKTANK for block placement uses. + // must be registered as of 1.18.2 + public static final ItemEntry NETHERITE_BACKTANK_PLACEABLE = REGISTRATE + .item("netherite_backtank_placeable", + p -> new BacktankBlockItem(AllBlocks.NETHERITE_BACKTANK.get(), AllItems.NETHERITE_BACKTANK::get, p)) + .model((c, p) -> p.withExistingParent(c.getName(), p.mcLoc("item/barrier"))) + .register(); - COPPER_BACKTANK = REGISTRATE.item("copper_backtank", p -> new CopperBacktankItem(p, COPPER_BACKTANK_PLACEABLE)) - .model(AssetLookup.customGenericItemModel("_", "item")) - .tag(AllItemTags.PRESSURIZED_AIR_SOURCES.tag) - .register(), + public static final ItemEntry - DIVING_HELMET = REGISTRATE.item("diving_helmet", DivingHelmetItem::new) + COPPER_BACKTANK = + REGISTRATE + .item("copper_backtank", + p -> new BacktankItem(AllArmorMaterials.COPPER, p, Create.asResource("copper_diving"), + COPPER_BACKTANK_PLACEABLE)) + .model(AssetLookup.customGenericItemModel("_", "item")) + .tag(AllItemTags.PRESSURIZED_AIR_SOURCES.tag) + .tag(forgeItemTag("armors/chestplates")) .register(), - DIVING_BOOTS = REGISTRATE.item("diving_boots", DivingBootsItem::new) + NETHERITE_BACKTANK = REGISTRATE + .item("netherite_backtank", + p -> new BacktankItem.Layered(ArmorMaterials.NETHERITE, p, Create.asResource("netherite_diving"), + NETHERITE_BACKTANK_PLACEABLE)) + .model(AssetLookup.customGenericItemModel("_", "item")) + .properties(p -> p.fireResistant()) + .tag(AllItemTags.PRESSURIZED_AIR_SOURCES.tag) + .tag(forgeItemTag("armors/chestplates")) + .register(); + + public static final ItemEntry + + COPPER_DIVING_HELMET = + REGISTRATE + .item("copper_diving_helmet", + p -> new DivingHelmetItem(AllArmorMaterials.COPPER, p, Create.asResource("copper_diving"))) + .tag(forgeItemTag("armors/helmets")) + .register(), + + NETHERITE_DIVING_HELMET = REGISTRATE + .item("netherite_diving_helmet", + p -> new DivingHelmetItem(ArmorMaterials.NETHERITE, p, Create.asResource("netherite_diving"))) + .properties(p -> p.fireResistant()) + .tag(forgeItemTag("armors/helmets")) + .register(); + + public static final ItemEntry + + COPPER_DIVING_BOOTS = + REGISTRATE + .item("copper_diving_boots", + p -> new DivingBootsItem(AllArmorMaterials.COPPER, p, Create.asResource("copper_diving"))) + .tag(forgeItemTag("armors/boots")) + .register(), + + NETHERITE_DIVING_BOOTS = REGISTRATE + .item("netherite_diving_boots", + p -> new DivingBootsItem(ArmorMaterials.NETHERITE, p, Create.asResource("netherite_diving"))) + .properties(p -> p.fireResistant()) + .tag(forgeItemTag("armors/boots")) .register(); public static final ItemEntry SAND_PAPER = REGISTRATE.item("sand_paper", SandPaperItem::new) @@ -260,7 +296,7 @@ public class AllItems { public static final ItemEntry RED_SAND_PAPER = REGISTRATE.item("red_sand_paper", SandPaperItem::new) .tag(AllTags.AllItemTags.SANDPAPER.tag) - .onRegister(s -> TooltipHelper.referTo(s, SAND_PAPER)) + .onRegister(s -> ItemDescription.referKey(s, SAND_PAPER)) .register(); public static final ItemEntry WRENCH = REGISTRATE.item("wrench", WrenchItem::new) @@ -283,10 +319,6 @@ public class AllItems { // Curiosities - static { - REGISTRATE.startSection(CURIOSITIES); - } - public static final ItemEntry LINKED_CONTROLLER = REGISTRATE.item("linked_controller", LinkedControllerItem::new) .properties(p -> p.stacksTo(1)) @@ -323,18 +355,11 @@ public class AllItems { // Logistics - static { - REGISTRATE.startSection(LOGISTICS); - } - public static final ItemEntry FILTER = REGISTRATE.item("filter", FilterItem::regular) - .model(AssetLookup.existingItemModel()) - .register(); - - public static final ItemEntry ATTRIBUTE_FILTER = - REGISTRATE.item("attribute_filter", FilterItem::attribute) - .model(AssetLookup.existingItemModel()) - .register(); + .lang("List Filter") + .register(), ATTRIBUTE_FILTER = + REGISTRATE.item("attribute_filter", FilterItem::attribute) + .register(); public static final ItemEntry SCHEDULE = REGISTRATE.item("schedule", ScheduleItem::new) .lang("Train Schedule") @@ -342,10 +367,6 @@ public class AllItems { // Schematics - static { - REGISTRATE.startSection(SCHEMATICS); - } - public static final ItemEntry EMPTY_SCHEMATIC = REGISTRATE.item("empty_schematic", Item::new) .properties(p -> p.stacksTo(1)) .register(); @@ -386,9 +407,9 @@ public class AllItems { private static ItemEntry compatCrushedOre(CompatMetals metal) { String metalName = metal.getName(); return REGISTRATE - .item("crushed_" + metalName + "_ore", + .item("crushed_raw_" + metalName, props -> new TagDependentIngredientItem(props, AllTags.forgeItemTag("ores/" + metalName))) - .tag(CRUSHED_ORES.tag) + .tag(CRUSHED_RAW_MATERIALS.tag) .register(); } diff --git a/src/main/java/com/simibubi/create/AllMenuTypes.java b/src/main/java/com/simibubi/create/AllMenuTypes.java new file mode 100644 index 000000000..853a9e647 --- /dev/null +++ b/src/main/java/com/simibubi/create/AllMenuTypes.java @@ -0,0 +1,63 @@ +package com.simibubi.create; + +import com.simibubi.create.content.equipment.blueprint.BlueprintMenu; +import com.simibubi.create.content.equipment.blueprint.BlueprintScreen; +import com.simibubi.create.content.equipment.toolbox.ToolboxMenu; +import com.simibubi.create.content.equipment.toolbox.ToolboxScreen; +import com.simibubi.create.content.logistics.filter.AttributeFilterMenu; +import com.simibubi.create.content.logistics.filter.AttributeFilterScreen; +import com.simibubi.create.content.logistics.filter.FilterMenu; +import com.simibubi.create.content.logistics.filter.FilterScreen; +import com.simibubi.create.content.redstone.link.controller.LinkedControllerMenu; +import com.simibubi.create.content.redstone.link.controller.LinkedControllerScreen; +import com.simibubi.create.content.schematics.cannon.SchematicannonMenu; +import com.simibubi.create.content.schematics.cannon.SchematicannonScreen; +import com.simibubi.create.content.schematics.table.SchematicTableMenu; +import com.simibubi.create.content.schematics.table.SchematicTableScreen; +import com.simibubi.create.content.trains.schedule.ScheduleMenu; +import com.simibubi.create.content.trains.schedule.ScheduleScreen; +import com.tterrag.registrate.builders.MenuBuilder.ForgeMenuFactory; +import com.tterrag.registrate.builders.MenuBuilder.ScreenFactory; +import com.tterrag.registrate.util.entry.MenuEntry; +import com.tterrag.registrate.util.nullness.NonNullSupplier; + +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.gui.screens.inventory.MenuAccess; +import net.minecraft.world.inventory.AbstractContainerMenu; + +public class AllMenuTypes { + + public static final MenuEntry SCHEMATIC_TABLE = + register("schematic_table", SchematicTableMenu::new, () -> SchematicTableScreen::new); + + public static final MenuEntry SCHEMATICANNON = + register("schematicannon", SchematicannonMenu::new, () -> SchematicannonScreen::new); + + public static final MenuEntry FILTER = + register("filter", FilterMenu::new, () -> FilterScreen::new); + + public static final MenuEntry ATTRIBUTE_FILTER = + register("attribute_filter", AttributeFilterMenu::new, () -> AttributeFilterScreen::new); + + public static final MenuEntry CRAFTING_BLUEPRINT = + register("crafting_blueprint", BlueprintMenu::new, () -> BlueprintScreen::new); + + public static final MenuEntry LINKED_CONTROLLER = + register("linked_controller", LinkedControllerMenu::new, () -> LinkedControllerScreen::new); + + public static final MenuEntry TOOLBOX = + register("toolbox", ToolboxMenu::new, () -> ToolboxScreen::new); + + public static final MenuEntry SCHEDULE = + register("schedule", ScheduleMenu::new, () -> ScheduleScreen::new); + + private static > MenuEntry register( + String name, ForgeMenuFactory factory, NonNullSupplier> screenFactory) { + return Create.REGISTRATE + .menu(name, factory, screenFactory) + .register(); + } + + public static void register() {} + +} diff --git a/src/main/java/com/simibubi/create/AllMovementBehaviours.java b/src/main/java/com/simibubi/create/AllMovementBehaviours.java index a66352285..6dde48640 100644 --- a/src/main/java/com/simibubi/create/AllMovementBehaviours.java +++ b/src/main/java/com/simibubi/create/AllMovementBehaviours.java @@ -3,14 +3,14 @@ package com.simibubi.create; import java.util.ArrayList; import java.util.List; -import org.jetbrains.annotations.Nullable; +import javax.annotation.Nullable; -import com.simibubi.create.content.contraptions.components.actors.BellMovementBehaviour; -import com.simibubi.create.content.contraptions.components.actors.CampfireMovementBehaviour; -import com.simibubi.create.content.contraptions.components.actors.dispenser.DispenserMovementBehaviour; -import com.simibubi.create.content.contraptions.components.actors.dispenser.DropperMovementBehaviour; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; -import com.simibubi.create.foundation.utility.CreateRegistry; +import com.simibubi.create.content.contraptions.behaviour.BellMovementBehaviour; +import com.simibubi.create.content.contraptions.behaviour.CampfireMovementBehaviour; +import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; +import com.simibubi.create.content.contraptions.behaviour.dispenser.DispenserMovementBehaviour; +import com.simibubi.create.content.contraptions.behaviour.dispenser.DropperMovementBehaviour; +import com.simibubi.create.foundation.utility.AttachedRegistry; import com.tterrag.registrate.util.nullness.NonNullConsumer; import net.minecraft.resources.ResourceLocation; @@ -20,7 +20,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraftforge.registries.ForgeRegistries; public class AllMovementBehaviours { - private static final CreateRegistry BLOCK_BEHAVIOURS = new CreateRegistry<>(ForgeRegistries.BLOCKS); + private static final AttachedRegistry BLOCK_BEHAVIOURS = new AttachedRegistry<>(ForgeRegistries.BLOCKS); private static final List GLOBAL_BEHAVIOURS = new ArrayList<>(); public static void registerBehaviour(ResourceLocation block, MovementBehaviour behaviour) { @@ -60,6 +60,7 @@ public class AllMovementBehaviours { static void registerDefaults() { registerBehaviour(Blocks.BELL, new BellMovementBehaviour()); registerBehaviour(Blocks.CAMPFIRE, new CampfireMovementBehaviour()); + registerBehaviour(Blocks.SOUL_CAMPFIRE, new CampfireMovementBehaviour()); DispenserMovementBehaviour.gatherMovedDispenseItemBehaviours(); registerBehaviour(Blocks.DISPENSER, new DispenserMovementBehaviour()); diff --git a/src/main/java/com/simibubi/create/AllPackets.java b/src/main/java/com/simibubi/create/AllPackets.java new file mode 100644 index 000000000..00d5b3b0a --- /dev/null +++ b/src/main/java/com/simibubi/create/AllPackets.java @@ -0,0 +1,277 @@ +package com.simibubi.create; + +import static net.minecraftforge.network.NetworkDirection.PLAY_TO_CLIENT; +import static net.minecraftforge.network.NetworkDirection.PLAY_TO_SERVER; + +import java.util.function.BiConsumer; +import java.util.function.Function; +import java.util.function.Supplier; + +import com.simibubi.create.compat.computercraft.AttachedComputerPacket; +import com.simibubi.create.content.contraptions.ContraptionBlockChangedPacket; +import com.simibubi.create.content.contraptions.ContraptionColliderLockPacket; +import com.simibubi.create.content.contraptions.ContraptionColliderLockPacket.ContraptionColliderLockPacketRequest; +import com.simibubi.create.content.contraptions.ContraptionDisassemblyPacket; +import com.simibubi.create.content.contraptions.ContraptionRelocationPacket; +import com.simibubi.create.content.contraptions.ContraptionStallPacket; +import com.simibubi.create.content.contraptions.TrainCollisionPacket; +import com.simibubi.create.content.contraptions.actors.contraptionControls.ContraptionDisableActorPacket; +import com.simibubi.create.content.contraptions.actors.trainControls.ControlsInputPacket; +import com.simibubi.create.content.contraptions.actors.trainControls.ControlsStopControllingPacket; +import com.simibubi.create.content.contraptions.elevator.ElevatorContactEditPacket; +import com.simibubi.create.content.contraptions.elevator.ElevatorFloorListPacket; +import com.simibubi.create.content.contraptions.elevator.ElevatorTargetFloorPacket; +import com.simibubi.create.content.contraptions.gantry.GantryContraptionUpdatePacket; +import com.simibubi.create.content.contraptions.glue.GlueEffectPacket; +import com.simibubi.create.content.contraptions.glue.SuperGlueRemovalPacket; +import com.simibubi.create.content.contraptions.glue.SuperGlueSelectionPacket; +import com.simibubi.create.content.contraptions.minecart.CouplingCreationPacket; +import com.simibubi.create.content.contraptions.minecart.capability.MinecartControllerUpdatePacket; +import com.simibubi.create.content.contraptions.sync.ClientMotionPacket; +import com.simibubi.create.content.contraptions.sync.ContraptionFluidPacket; +import com.simibubi.create.content.contraptions.sync.ContraptionInteractionPacket; +import com.simibubi.create.content.contraptions.sync.ContraptionSeatMappingPacket; +import com.simibubi.create.content.contraptions.sync.LimbSwingUpdatePacket; +import com.simibubi.create.content.equipment.bell.SoulPulseEffectPacket; +import com.simibubi.create.content.equipment.blueprint.BlueprintAssignCompleteRecipePacket; +import com.simibubi.create.content.equipment.clipboard.ClipboardEditPacket; +import com.simibubi.create.content.equipment.extendoGrip.ExtendoGripInteractionPacket; +import com.simibubi.create.content.equipment.potatoCannon.PotatoCannonPacket; +import com.simibubi.create.content.equipment.potatoCannon.PotatoProjectileTypeManager; +import com.simibubi.create.content.equipment.symmetryWand.ConfigureSymmetryWandPacket; +import com.simibubi.create.content.equipment.symmetryWand.SymmetryEffectPacket; +import com.simibubi.create.content.equipment.toolbox.ToolboxDisposeAllPacket; +import com.simibubi.create.content.equipment.toolbox.ToolboxEquipPacket; +import com.simibubi.create.content.equipment.zapper.ZapperBeamPacket; +import com.simibubi.create.content.equipment.zapper.terrainzapper.ConfigureWorldshaperPacket; +import com.simibubi.create.content.fluids.transfer.FluidSplashPacket; +import com.simibubi.create.content.kinetics.gauge.GaugeObservedPacket; +import com.simibubi.create.content.kinetics.mechanicalArm.ArmPlacementPacket; +import com.simibubi.create.content.kinetics.transmission.sequencer.ConfigureSequencedGearshiftPacket; +import com.simibubi.create.content.logistics.depot.EjectorAwardPacket; +import com.simibubi.create.content.logistics.depot.EjectorElytraPacket; +import com.simibubi.create.content.logistics.depot.EjectorPlacementPacket; +import com.simibubi.create.content.logistics.depot.EjectorTriggerPacket; +import com.simibubi.create.content.logistics.filter.FilterScreenPacket; +import com.simibubi.create.content.logistics.funnel.FunnelFlapPacket; +import com.simibubi.create.content.logistics.tunnel.TunnelFlapPacket; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkConfigurationPacket; +import com.simibubi.create.content.redstone.link.controller.LinkedControllerBindPacket; +import com.simibubi.create.content.redstone.link.controller.LinkedControllerInputPacket; +import com.simibubi.create.content.redstone.link.controller.LinkedControllerStopLecternPacket; +import com.simibubi.create.content.redstone.thresholdSwitch.ConfigureThresholdSwitchPacket; +import com.simibubi.create.content.schematics.cannon.ConfigureSchematicannonPacket; +import com.simibubi.create.content.schematics.packet.InstantSchematicPacket; +import com.simibubi.create.content.schematics.packet.SchematicPlacePacket; +import com.simibubi.create.content.schematics.packet.SchematicSyncPacket; +import com.simibubi.create.content.schematics.packet.SchematicUploadPacket; +import com.simibubi.create.content.trains.HonkPacket; +import com.simibubi.create.content.trains.TrainHUDUpdatePacket; +import com.simibubi.create.content.trains.entity.TrainPacket; +import com.simibubi.create.content.trains.entity.TrainPromptPacket; +import com.simibubi.create.content.trains.entity.TrainRelocationPacket; +import com.simibubi.create.content.trains.graph.TrackGraphRequestPacket; +import com.simibubi.create.content.trains.graph.TrackGraphRollCallPacket; +import com.simibubi.create.content.trains.graph.TrackGraphSyncPacket; +import com.simibubi.create.content.trains.schedule.ScheduleEditPacket; +import com.simibubi.create.content.trains.signal.SignalEdgeGroupPacket; +import com.simibubi.create.content.trains.station.StationEditPacket; +import com.simibubi.create.content.trains.station.TrainEditPacket; +import com.simibubi.create.content.trains.station.TrainEditPacket.TrainEditReturnPacket; +import com.simibubi.create.content.trains.track.CurvedTrackDestroyPacket; +import com.simibubi.create.content.trains.track.CurvedTrackSelectionPacket; +import com.simibubi.create.content.trains.track.PlaceExtendedCurvePacket; +import com.simibubi.create.foundation.blockEntity.RemoveBlockEntityPacket; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsPacket; +import com.simibubi.create.foundation.config.ui.CConfigureConfigPacket; +import com.simibubi.create.foundation.gui.menu.ClearMenuPacket; +import com.simibubi.create.foundation.gui.menu.GhostItemSubmitPacket; +import com.simibubi.create.foundation.networking.ISyncPersistentData; +import com.simibubi.create.foundation.networking.LeftClickPacket; +import com.simibubi.create.foundation.networking.SimplePacketBase; +import com.simibubi.create.foundation.utility.ServerSpeedProvider; +import com.simibubi.create.infrastructure.command.HighlightPacket; +import com.simibubi.create.infrastructure.command.SConfigureConfigPacket; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.Level; +import net.minecraftforge.network.NetworkDirection; +import net.minecraftforge.network.NetworkEvent.Context; +import net.minecraftforge.network.NetworkRegistry; +import net.minecraftforge.network.PacketDistributor; +import net.minecraftforge.network.PacketDistributor.TargetPoint; +import net.minecraftforge.network.simple.SimpleChannel; + +public enum AllPackets { + + // Client to Server + CONFIGURE_SCHEMATICANNON(ConfigureSchematicannonPacket.class, ConfigureSchematicannonPacket::new, PLAY_TO_SERVER), + CONFIGURE_STOCKSWITCH(ConfigureThresholdSwitchPacket.class, ConfigureThresholdSwitchPacket::new, PLAY_TO_SERVER), + CONFIGURE_SEQUENCER(ConfigureSequencedGearshiftPacket.class, ConfigureSequencedGearshiftPacket::new, + PLAY_TO_SERVER), + PLACE_SCHEMATIC(SchematicPlacePacket.class, SchematicPlacePacket::new, PLAY_TO_SERVER), + UPLOAD_SCHEMATIC(SchematicUploadPacket.class, SchematicUploadPacket::new, PLAY_TO_SERVER), + CLEAR_CONTAINER(ClearMenuPacket.class, ClearMenuPacket::new, PLAY_TO_SERVER), + CONFIGURE_FILTER(FilterScreenPacket.class, FilterScreenPacket::new, PLAY_TO_SERVER), + EXTENDO_INTERACT(ExtendoGripInteractionPacket.class, ExtendoGripInteractionPacket::new, PLAY_TO_SERVER), + CONTRAPTION_INTERACT(ContraptionInteractionPacket.class, ContraptionInteractionPacket::new, PLAY_TO_SERVER), + CLIENT_MOTION(ClientMotionPacket.class, ClientMotionPacket::new, PLAY_TO_SERVER), + PLACE_ARM(ArmPlacementPacket.class, ArmPlacementPacket::new, PLAY_TO_SERVER), + MINECART_COUPLING_CREATION(CouplingCreationPacket.class, CouplingCreationPacket::new, PLAY_TO_SERVER), + INSTANT_SCHEMATIC(InstantSchematicPacket.class, InstantSchematicPacket::new, PLAY_TO_SERVER), + SYNC_SCHEMATIC(SchematicSyncPacket.class, SchematicSyncPacket::new, PLAY_TO_SERVER), + LEFT_CLICK(LeftClickPacket.class, LeftClickPacket::new, PLAY_TO_SERVER), + PLACE_EJECTOR(EjectorPlacementPacket.class, EjectorPlacementPacket::new, PLAY_TO_SERVER), + TRIGGER_EJECTOR(EjectorTriggerPacket.class, EjectorTriggerPacket::new, PLAY_TO_SERVER), + EJECTOR_ELYTRA(EjectorElytraPacket.class, EjectorElytraPacket::new, PLAY_TO_SERVER), + LINKED_CONTROLLER_INPUT(LinkedControllerInputPacket.class, LinkedControllerInputPacket::new, PLAY_TO_SERVER), + LINKED_CONTROLLER_BIND(LinkedControllerBindPacket.class, LinkedControllerBindPacket::new, PLAY_TO_SERVER), + LINKED_CONTROLLER_USE_LECTERN(LinkedControllerStopLecternPacket.class, LinkedControllerStopLecternPacket::new, + PLAY_TO_SERVER), + C_CONFIGURE_CONFIG(CConfigureConfigPacket.class, CConfigureConfigPacket::new, PLAY_TO_SERVER), + SUBMIT_GHOST_ITEM(GhostItemSubmitPacket.class, GhostItemSubmitPacket::new, PLAY_TO_SERVER), + BLUEPRINT_COMPLETE_RECIPE(BlueprintAssignCompleteRecipePacket.class, BlueprintAssignCompleteRecipePacket::new, + PLAY_TO_SERVER), + CONFIGURE_SYMMETRY_WAND(ConfigureSymmetryWandPacket.class, ConfigureSymmetryWandPacket::new, PLAY_TO_SERVER), + CONFIGURE_WORLDSHAPER(ConfigureWorldshaperPacket.class, ConfigureWorldshaperPacket::new, PLAY_TO_SERVER), + TOOLBOX_EQUIP(ToolboxEquipPacket.class, ToolboxEquipPacket::new, PLAY_TO_SERVER), + TOOLBOX_DISPOSE_ALL(ToolboxDisposeAllPacket.class, ToolboxDisposeAllPacket::new, PLAY_TO_SERVER), + CONFIGURE_SCHEDULE(ScheduleEditPacket.class, ScheduleEditPacket::new, PLAY_TO_SERVER), + CONFIGURE_STATION(StationEditPacket.class, StationEditPacket::new, PLAY_TO_SERVER), + C_CONFIGURE_TRAIN(TrainEditPacket.class, TrainEditPacket::new, PLAY_TO_SERVER), + RELOCATE_TRAIN(TrainRelocationPacket.class, TrainRelocationPacket::new, PLAY_TO_SERVER), + CONTROLS_INPUT(ControlsInputPacket.class, ControlsInputPacket::new, PLAY_TO_SERVER), + CONFIGURE_DATA_GATHERER(DisplayLinkConfigurationPacket.class, DisplayLinkConfigurationPacket::new, PLAY_TO_SERVER), + DESTROY_CURVED_TRACK(CurvedTrackDestroyPacket.class, CurvedTrackDestroyPacket::new, PLAY_TO_SERVER), + SELECT_CURVED_TRACK(CurvedTrackSelectionPacket.class, CurvedTrackSelectionPacket::new, PLAY_TO_SERVER), + PLACE_CURVED_TRACK(PlaceExtendedCurvePacket.class, PlaceExtendedCurvePacket::new, PLAY_TO_SERVER), + GLUE_IN_AREA(SuperGlueSelectionPacket.class, SuperGlueSelectionPacket::new, PLAY_TO_SERVER), + GLUE_REMOVED(SuperGlueRemovalPacket.class, SuperGlueRemovalPacket::new, PLAY_TO_SERVER), + TRAIN_COLLISION(TrainCollisionPacket.class, TrainCollisionPacket::new, PLAY_TO_SERVER), + C_TRAIN_HUD(TrainHUDUpdatePacket.Serverbound.class, TrainHUDUpdatePacket.Serverbound::new, PLAY_TO_SERVER), + C_TRAIN_HONK(HonkPacket.Serverbound.class, HonkPacket.Serverbound::new, PLAY_TO_SERVER), + OBSERVER_STRESSOMETER(GaugeObservedPacket.class, GaugeObservedPacket::new, PLAY_TO_SERVER), + EJECTOR_AWARD(EjectorAwardPacket.class, EjectorAwardPacket::new, PLAY_TO_SERVER), + TRACK_GRAPH_REQUEST(TrackGraphRequestPacket.class, TrackGraphRequestPacket::new, PLAY_TO_SERVER), + CONFIGURE_ELEVATOR_CONTACT(ElevatorContactEditPacket.class, ElevatorContactEditPacket::new, PLAY_TO_SERVER), + REQUEST_FLOOR_LIST(ElevatorFloorListPacket.RequestFloorList.class, ElevatorFloorListPacket.RequestFloorList::new, + PLAY_TO_SERVER), + ELEVATOR_SET_FLOOR(ElevatorTargetFloorPacket.class, ElevatorTargetFloorPacket::new, PLAY_TO_SERVER), + VALUE_SETTINGS(ValueSettingsPacket.class, ValueSettingsPacket::new, PLAY_TO_SERVER), + CLIPBOARD_EDIT(ClipboardEditPacket.class, ClipboardEditPacket::new, PLAY_TO_SERVER), + CONTRAPTION_COLLIDER_LOCK_REQUEST(ContraptionColliderLockPacketRequest.class, + ContraptionColliderLockPacketRequest::new, PLAY_TO_SERVER), + + // Server to Client + SYMMETRY_EFFECT(SymmetryEffectPacket.class, SymmetryEffectPacket::new, PLAY_TO_CLIENT), + SERVER_SPEED(ServerSpeedProvider.Packet.class, ServerSpeedProvider.Packet::new, PLAY_TO_CLIENT), + BEAM_EFFECT(ZapperBeamPacket.class, ZapperBeamPacket::new, PLAY_TO_CLIENT), + S_CONFIGURE_CONFIG(SConfigureConfigPacket.class, SConfigureConfigPacket::new, PLAY_TO_CLIENT), + CONTRAPTION_STALL(ContraptionStallPacket.class, ContraptionStallPacket::new, PLAY_TO_CLIENT), + CONTRAPTION_DISASSEMBLE(ContraptionDisassemblyPacket.class, ContraptionDisassemblyPacket::new, PLAY_TO_CLIENT), + CONTRAPTION_BLOCK_CHANGED(ContraptionBlockChangedPacket.class, ContraptionBlockChangedPacket::new, PLAY_TO_CLIENT), + GLUE_EFFECT(GlueEffectPacket.class, GlueEffectPacket::new, PLAY_TO_CLIENT), + CONTRAPTION_SEAT_MAPPING(ContraptionSeatMappingPacket.class, ContraptionSeatMappingPacket::new, PLAY_TO_CLIENT), + LIMBSWING_UPDATE(LimbSwingUpdatePacket.class, LimbSwingUpdatePacket::new, PLAY_TO_CLIENT), + MINECART_CONTROLLER(MinecartControllerUpdatePacket.class, MinecartControllerUpdatePacket::new, PLAY_TO_CLIENT), + FLUID_SPLASH(FluidSplashPacket.class, FluidSplashPacket::new, PLAY_TO_CLIENT), + CONTRAPTION_FLUID(ContraptionFluidPacket.class, ContraptionFluidPacket::new, PLAY_TO_CLIENT), + GANTRY_UPDATE(GantryContraptionUpdatePacket.class, GantryContraptionUpdatePacket::new, PLAY_TO_CLIENT), + BLOCK_HIGHLIGHT(HighlightPacket.class, HighlightPacket::new, PLAY_TO_CLIENT), + TUNNEL_FLAP(TunnelFlapPacket.class, TunnelFlapPacket::new, PLAY_TO_CLIENT), + FUNNEL_FLAP(FunnelFlapPacket.class, FunnelFlapPacket::new, PLAY_TO_CLIENT), + POTATO_CANNON(PotatoCannonPacket.class, PotatoCannonPacket::new, PLAY_TO_CLIENT), + SOUL_PULSE(SoulPulseEffectPacket.class, SoulPulseEffectPacket::new, PLAY_TO_CLIENT), + PERSISTENT_DATA(ISyncPersistentData.PersistentDataPacket.class, ISyncPersistentData.PersistentDataPacket::new, + PLAY_TO_CLIENT), + SYNC_POTATO_PROJECTILE_TYPES(PotatoProjectileTypeManager.SyncPacket.class, + PotatoProjectileTypeManager.SyncPacket::new, PLAY_TO_CLIENT), + SYNC_RAIL_GRAPH(TrackGraphSyncPacket.class, TrackGraphSyncPacket::new, PLAY_TO_CLIENT), + SYNC_EDGE_GROUP(SignalEdgeGroupPacket.class, SignalEdgeGroupPacket::new, PLAY_TO_CLIENT), + SYNC_TRAIN(TrainPacket.class, TrainPacket::new, PLAY_TO_CLIENT), + REMOVE_TE(RemoveBlockEntityPacket.class, RemoveBlockEntityPacket::new, PLAY_TO_CLIENT), + S_CONFIGURE_TRAIN(TrainEditReturnPacket.class, TrainEditReturnPacket::new, PLAY_TO_CLIENT), + CONTROLS_ABORT(ControlsStopControllingPacket.class, ControlsStopControllingPacket::new, PLAY_TO_CLIENT), + S_TRAIN_HUD(TrainHUDUpdatePacket.class, TrainHUDUpdatePacket::new, PLAY_TO_CLIENT), + S_TRAIN_HONK(HonkPacket.class, HonkPacket::new, PLAY_TO_CLIENT), + S_TRAIN_PROMPT(TrainPromptPacket.class, TrainPromptPacket::new, PLAY_TO_CLIENT), + CONTRAPTION_RELOCATION(ContraptionRelocationPacket.class, ContraptionRelocationPacket::new, PLAY_TO_CLIENT), + TRACK_GRAPH_ROLL_CALL(TrackGraphRollCallPacket.class, TrackGraphRollCallPacket::new, PLAY_TO_CLIENT), + S_PLACE_EJECTOR(ArmPlacementPacket.ClientBoundRequest.class, ArmPlacementPacket.ClientBoundRequest::new, + PLAY_TO_CLIENT), + S_PLACE_ARM(EjectorPlacementPacket.ClientBoundRequest.class, EjectorPlacementPacket.ClientBoundRequest::new, + PLAY_TO_CLIENT), + UPDATE_ELEVATOR_FLOORS(ElevatorFloorListPacket.class, ElevatorFloorListPacket::new, PLAY_TO_CLIENT), + CONTRAPTION_ACTOR_TOGGLE(ContraptionDisableActorPacket.class, ContraptionDisableActorPacket::new, PLAY_TO_CLIENT), + CONTRAPTION_COLLIDER_LOCK(ContraptionColliderLockPacket.class, ContraptionColliderLockPacket::new, PLAY_TO_CLIENT), + ATTACHED_COMPUTER(AttachedComputerPacket.class, AttachedComputerPacket::new, PLAY_TO_CLIENT), + + ; + + public static final ResourceLocation CHANNEL_NAME = Create.asResource("main"); + public static final int NETWORK_VERSION = 3; + public static final String NETWORK_VERSION_STR = String.valueOf(NETWORK_VERSION); + private static SimpleChannel channel; + + private PacketType packetType; + + AllPackets(Class type, Function factory, + NetworkDirection direction) { + packetType = new PacketType<>(type, factory, direction); + } + + public static void registerPackets() { + channel = NetworkRegistry.ChannelBuilder.named(CHANNEL_NAME) + .serverAcceptedVersions(NETWORK_VERSION_STR::equals) + .clientAcceptedVersions(NETWORK_VERSION_STR::equals) + .networkProtocolVersion(() -> NETWORK_VERSION_STR) + .simpleChannel(); + + for (AllPackets packet : values()) + packet.packetType.register(); + } + + public static SimpleChannel getChannel() { + return channel; + } + + public static void sendToNear(Level world, BlockPos pos, int range, Object message) { + getChannel().send( + PacketDistributor.NEAR.with(TargetPoint.p(pos.getX(), pos.getY(), pos.getZ(), range, world.dimension())), + message); + } + + private static class PacketType { + private static int index = 0; + + private BiConsumer encoder; + private Function decoder; + private BiConsumer> handler; + private Class type; + private NetworkDirection direction; + + private PacketType(Class type, Function factory, NetworkDirection direction) { + encoder = T::write; + decoder = factory; + handler = (packet, contextSupplier) -> { + Context context = contextSupplier.get(); + if (packet.handle(context)) { + context.setPacketHandled(true); + } + }; + this.type = type; + this.direction = direction; + } + + private void register() { + getChannel().messageBuilder(type, index++, direction) + .encoder(encoder) + .decoder(decoder) + .consumerNetworkThread(handler) + .add(); + } + } + +} diff --git a/src/main/java/com/simibubi/create/AllPartialModels.java b/src/main/java/com/simibubi/create/AllPartialModels.java new file mode 100644 index 000000000..8fde35136 --- /dev/null +++ b/src/main/java/com/simibubi/create/AllPartialModels.java @@ -0,0 +1,233 @@ +package com.simibubi.create; + +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.jozufozu.flywheel.core.PartialModel; +import com.simibubi.create.content.fluids.FluidTransportBehaviour; +import com.simibubi.create.foundation.utility.Couple; +import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.core.Direction; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.DyeColor; + +public class AllPartialModels { + + public static final PartialModel + + SCHEMATICANNON_CONNECTOR = block("schematicannon/connector"), SCHEMATICANNON_PIPE = block("schematicannon/pipe"), + + SHAFTLESS_COGWHEEL = block("cogwheel_shaftless"), SHAFTLESS_LARGE_COGWHEEL = block("large_cogwheel_shaftless"), + COGWHEEL_SHAFT = block("cogwheel_shaft"), SHAFT_HALF = block("shaft_half"), + + BELT_PULLEY = block("belt_pulley"), BELT_START = block("belt/start"), BELT_MIDDLE = block("belt/middle"), + BELT_END = block("belt/end"), BELT_START_BOTTOM = block("belt/start_bottom"), + BELT_MIDDLE_BOTTOM = block("belt/middle_bottom"), BELT_END_BOTTOM = block("belt/end_bottom"), + BELT_DIAGONAL_START = block("belt/diagonal_start"), BELT_DIAGONAL_MIDDLE = block("belt/diagonal_middle"), + BELT_DIAGONAL_END = block("belt/diagonal_end"), + ANDESITE_BELT_COVER_X = block("belt_cover/andesite_belt_cover_x"), + BRASS_BELT_COVER_X = block("belt_cover/brass_belt_cover_x"), + ANDESITE_BELT_COVER_Z = block("belt_cover/andesite_belt_cover_z"), + BRASS_BELT_COVER_Z = block("belt_cover/brass_belt_cover_z"), + + ENCASED_FAN_INNER = block("encased_fan/propeller"), HAND_CRANK_HANDLE = block("hand_crank/handle"), + MECHANICAL_PRESS_HEAD = block("mechanical_press/head"), MECHANICAL_MIXER_POLE = block("mechanical_mixer/pole"), + MECHANICAL_MIXER_HEAD = block("mechanical_mixer/head"), + MECHANICAL_CRAFTER_LID = block("mechanical_crafter/lid"), + MECHANICAL_CRAFTER_ARROW = block("mechanical_crafter/arrow"), + MECHANICAL_CRAFTER_BELT_FRAME = block("mechanical_crafter/belt"), + MECHANICAL_CRAFTER_BELT = block("mechanical_crafter/belt_animated"), + SAW_BLADE_HORIZONTAL_ACTIVE = block("mechanical_saw/blade_horizontal_active"), + SAW_BLADE_HORIZONTAL_INACTIVE = block("mechanical_saw/blade_horizontal_inactive"), + SAW_BLADE_HORIZONTAL_REVERSED = block("mechanical_saw/blade_horizontal_reversed"), + SAW_BLADE_VERTICAL_ACTIVE = block("mechanical_saw/blade_vertical_active"), + SAW_BLADE_VERTICAL_INACTIVE = block("mechanical_saw/blade_vertical_inactive"), + SAW_BLADE_VERTICAL_REVERSED = block("mechanical_saw/blade_vertical_reversed"), GAUGE_DIAL = block("gauge/dial"), + GAUGE_INDICATOR = block("gauge/indicator"), GAUGE_HEAD_SPEED = block("gauge/speedometer/head"), + GAUGE_HEAD_STRESS = block("gauge/stressometer/head"), BEARING_TOP = block("bearing/top"), + BEARING_TOP_WOODEN = block("bearing/top_wooden"), DRILL_HEAD = block("mechanical_drill/head"), + HARVESTER_BLADE = block("mechanical_harvester/blade"), DEPLOYER_POLE = block("deployer/pole"), + DEPLOYER_HAND_POINTING = block("deployer/hand_pointing"), + DEPLOYER_HAND_PUNCHING = block("deployer/hand_punching"), + DEPLOYER_HAND_HOLDING = block("deployer/hand_holding"), ANALOG_LEVER_HANDLE = block("analog_lever/handle"), + ANALOG_LEVER_INDICATOR = block("analog_lever/indicator"), FUNNEL_FLAP = block("funnel/flap"), + BELT_FUNNEL_FLAP = block("belt_funnel/flap"), BELT_TUNNEL_FLAP = block("belt_tunnel/flap"), + FLEXPEATER_INDICATOR = block("diodes/indicator"), + + ROLLER_WHEEL = block("mechanical_roller/wheel"), + ROLLER_FRAME = block("mechanical_roller/frame"), + + CUCKOO_MINUTE_HAND = block("cuckoo_clock/minute_hand"), CUCKOO_HOUR_HAND = block("cuckoo_clock/hour_hand"), + CUCKOO_LEFT_DOOR = block("cuckoo_clock/left_door"), CUCKOO_RIGHT_DOOR = block("cuckoo_clock/right_door"), + CUCKOO_PIG = block("cuckoo_clock/pig"), CUCKOO_CREEPER = block("cuckoo_clock/creeper"), + + GANTRY_COGS = block("gantry_carriage/wheels"), + + ROPE_COIL = block("rope_pulley/rope_coil"), ROPE_HALF = block("rope_pulley/rope_half"), + ROPE_HALF_MAGNET = block("rope_pulley/rope_half_magnet"), + + HOSE_COIL = block("hose_pulley/rope_coil"), HOSE = block("hose_pulley/rope"), + HOSE_MAGNET = block("hose_pulley/pulley_magnet"), HOSE_HALF = block("hose_pulley/rope_half"), + HOSE_HALF_MAGNET = block("hose_pulley/rope_half_magnet"), + + ELEVATOR_COIL = block("elevator_pulley/rope_coil"), ELEVATOR_MAGNET = block("elevator_pulley/pulley_magnet"), + ELEVATOR_BELT = block("elevator_pulley/rope"), ELEVATOR_BELT_HALF = block("elevator_pulley/rope_half"), + + MILLSTONE_COG = block("millstone/inner"), + + SYMMETRY_PLANE = block("symmetry_effect/plane"), SYMMETRY_CROSSPLANE = block("symmetry_effect/crossplane"), + SYMMETRY_TRIPLEPLANE = block("symmetry_effect/tripleplane"), + + STICKER_HEAD = block("sticker/head"), + + PORTABLE_STORAGE_INTERFACE_MIDDLE = block("portable_storage_interface/block_middle"), + PORTABLE_STORAGE_INTERFACE_MIDDLE_POWERED = block("portable_storage_interface/block_middle_powered"), + PORTABLE_STORAGE_INTERFACE_TOP = block("portable_storage_interface/block_top"), + + PORTABLE_FLUID_INTERFACE_MIDDLE = block("portable_fluid_interface/block_middle"), + PORTABLE_FLUID_INTERFACE_MIDDLE_POWERED = block("portable_fluid_interface/block_middle_powered"), + PORTABLE_FLUID_INTERFACE_TOP = block("portable_fluid_interface/block_top"), + + ARM_COG = block("mechanical_arm/cog"), ARM_BASE = block("mechanical_arm/base"), + ARM_LOWER_BODY = block("mechanical_arm/lower_body"), ARM_UPPER_BODY = block("mechanical_arm/upper_body"), + ARM_CLAW_BASE = block("mechanical_arm/claw_base"), + ARM_CLAW_BASE_GOGGLES = block("mechanical_arm/claw_base_goggles"), + ARM_CLAW_GRIP_UPPER = block("mechanical_arm/upper_claw_grip"), + ARM_CLAW_GRIP_LOWER = block("mechanical_arm/lower_claw_grip"), + + MECHANICAL_PUMP_COG = block("mechanical_pump/cog"), + FLUID_PIPE_CASING = block("fluid_pipe/casing"), FLUID_VALVE_POINTER = block("fluid_valve/pointer"), + + SPOUT_TOP = block("spout/top"), SPOUT_MIDDLE = block("spout/middle"), SPOUT_BOTTOM = block("spout/bottom"), + + PECULIAR_BELL = block("peculiar_bell"), HAUNTED_BELL = block("haunted_bell"), + + TOOLBOX_DRAWER = block("toolbox/drawer"), + + SPEED_CONTROLLER_BRACKET = block("rotation_speed_controller/bracket"), + + GOGGLES = block("goggles"), + + EJECTOR_TOP = block("weighted_ejector/top"), + + COPPER_BACKTANK_SHAFT = block("copper_backtank/block_shaft_input"), + COPPER_BACKTANK_COGS = block("copper_backtank/block_cogs"), + + NETHERITE_BACKTANK_SHAFT = block("netherite_backtank/block_shaft_input"), + NETHERITE_BACKTANK_COGS = block("netherite_backtank/block_cogs"), + + TRACK_SEGMENT_LEFT = block("track/segment_left"), TRACK_SEGMENT_RIGHT = block("track/segment_right"), + TRACK_TIE = block("track/tie"), GIRDER_SEGMENT_TOP = block("metal_girder/segment_top"), + GIRDER_SEGMENT_MIDDLE = block("metal_girder/segment_middle"), + GIRDER_SEGMENT_BOTTOM = block("metal_girder/segment_bottom"), + + TRACK_STATION_OVERLAY = block("track_overlay/station"), TRACK_SIGNAL_OVERLAY = block("track_overlay/signal"), + TRACK_ASSEMBLING_OVERLAY = block("track_overlay/assembling"), + TRACK_SIGNAL_DUAL_OVERLAY = block("track_overlay/signal_dual"), + TRACK_OBSERVER_OVERLAY = block("track_overlay/observer"), + + BOGEY_FRAME = block("track/bogey/bogey_frame"), SMALL_BOGEY_WHEELS = block("track/bogey/bogey_wheel"), + BOGEY_PIN = block("track/bogey/bogey_drive_wheel_pin"), BOGEY_PISTON = block("track/bogey/bogey_drive_piston"), + BOGEY_DRIVE = block("track/bogey/bogey_drive"), LARGE_BOGEY_WHEELS = block("track/bogey/bogey_drive_wheel"), + + TRAIN_COUPLING_HEAD = block("track/bogey/coupling_head"), + TRAIN_COUPLING_CABLE = block("track/bogey/coupling_cable"), + + TRAIN_CONTROLS_COVER = block("controls/train/cover"), TRAIN_CONTROLS_LEVER = block("controls/train/lever"), + CONTRAPTION_CONTROLS_BUTTON = block("contraption_controls/button"), + + ENGINE_PISTON = block("steam_engine/piston"), ENGINE_LINKAGE = block("steam_engine/linkage"), + ENGINE_CONNECTOR = block("steam_engine/shaft_connector"), BOILER_GAUGE = block("steam_engine/gauge"), + BOILER_GAUGE_DIAL = block("steam_engine/gauge_dial"), + + SIGNAL_ON = block("track_signal/indicator_on"), SIGNAL_OFF = block("track_signal/indicator_off"), + DISPLAY_LINK_TUBE = block("display_link/tube"), DISPLAY_LINK_GLOW = block("display_link/glow"), + + STATION_ON = block("track_station/flag_on"), STATION_OFF = block("track_station/flag_off"), + STATION_ASSEMBLE = block("track_station/flag_assemble"), + + SIGNAL_PANEL = block("track_signal/panel"), SIGNAL_WHITE_CUBE = block("track_signal/white_cube"), + SIGNAL_WHITE_GLOW = block("track_signal/white_glow"), SIGNAL_WHITE = block("track_signal/white_tube"), + SIGNAL_RED_CUBE = block("track_signal/red_cube"), SIGNAL_RED_GLOW = block("track_signal/red_glow"), + SIGNAL_RED = block("track_signal/red_tube"), SIGNAL_YELLOW_CUBE = block("track_signal/yellow_cube"), + SIGNAL_YELLOW_GLOW = block("track_signal/yellow_glow"), SIGNAL_YELLOW = block("track_signal/yellow_tube"), + + BLAZE_INERT = block("blaze_burner/blaze/inert"), BLAZE_SUPER_ACTIVE = block("blaze_burner/blaze/super_active"), + BLAZE_GOGGLES = block("blaze_burner/goggles"), BLAZE_GOGGLES_SMALL = block("blaze_burner/goggles_small"), + BLAZE_IDLE = block("blaze_burner/blaze/idle"), BLAZE_ACTIVE = block("blaze_burner/blaze/active"), + BLAZE_SUPER = block("blaze_burner/blaze/super"), BLAZE_BURNER_FLAME = block("blaze_burner/flame"), + BLAZE_BURNER_RODS = block("blaze_burner/rods_small"), + BLAZE_BURNER_RODS_2 = block("blaze_burner/rods_large"), + BLAZE_BURNER_SUPER_RODS = block("blaze_burner/superheated_rods_small"), + BLAZE_BURNER_SUPER_RODS_2 = block("blaze_burner/superheated_rods_large"), + + WHISTLE_MOUTH_LARGE = block("steam_whistle/large_mouth"), + WHISTLE_MOUTH_MEDIUM = block("steam_whistle/medium_mouth"), + WHISTLE_MOUTH_SMALL = block("steam_whistle/small_mouth"), + + WATER_WHEEL = block("water_wheel/wheel"), + LARGE_WATER_WHEEL = block("large_water_wheel/block"), + LARGE_WATER_WHEEL_EXTENSION = block("large_water_wheel/block_extension"), + + CRAFTING_BLUEPRINT_1x1 = entity("crafting_blueprint_small"), + CRAFTING_BLUEPRINT_2x2 = entity("crafting_blueprint_medium"), + CRAFTING_BLUEPRINT_3x3 = entity("crafting_blueprint_large"), + + TRAIN_HAT = entity("train_hat"), + + COUPLING_ATTACHMENT = entity("minecart_coupling/attachment"), COUPLING_RING = entity("minecart_coupling/ring"), + COUPLING_CONNECTOR = entity("minecart_coupling/connector") + + ; + + public static final Map> PIPE_ATTACHMENTS = + new EnumMap<>(FluidTransportBehaviour.AttachmentTypes.ComponentPartials.class); + + public static final Map METAL_GIRDER_BRACKETS = new EnumMap<>(Direction.class); + public static final Map TOOLBOX_LIDS = new EnumMap<>(DyeColor.class); + public static final Map> FOLDING_DOORS = new HashMap<>(); + public static final List CONTRAPTION_CONTROLS_INDICATOR = new ArrayList<>(); + + static { + for (FluidTransportBehaviour.AttachmentTypes.ComponentPartials type : FluidTransportBehaviour.AttachmentTypes.ComponentPartials.values()) { + Map map = new HashMap<>(); + for (Direction d : Iterate.directions) { + String asId = Lang.asId(type.name()); + map.put(d, block("fluid_pipe/" + asId + "/" + Lang.asId(d.getSerializedName()))); + } + PIPE_ATTACHMENTS.put(type, map); + } + for (DyeColor color : DyeColor.values()) + TOOLBOX_LIDS.put(color, block("toolbox/lid/" + Lang.asId(color.name()))); + for (Direction d : Iterate.horizontalDirections) + METAL_GIRDER_BRACKETS.put(d, block("metal_girder/bracket_" + Lang.asId(d.name()))); + for (int i = 0; i < 8; i++) + CONTRAPTION_CONTROLS_INDICATOR.add(block("contraption_controls/indicator_" + i)); + + putFoldingDoor("andesite_door"); + putFoldingDoor("copper_door"); + } + + private static void putFoldingDoor(String path) { + FOLDING_DOORS.put(Create.asResource(path), + Couple.create(block(path + "/fold_left"), block(path + "/fold_right"))); + } + + private static PartialModel block(String path) { + return new PartialModel(Create.asResource("block/" + path)); + } + + private static PartialModel entity(String path) { + return new PartialModel(Create.asResource("entity/" + path)); + } + + public static void init() { + // init static fields + } + +} diff --git a/src/main/java/com/simibubi/create/AllParticleTypes.java b/src/main/java/com/simibubi/create/AllParticleTypes.java index eb1d938bc..31759c4a3 100644 --- a/src/main/java/com/simibubi/create/AllParticleTypes.java +++ b/src/main/java/com/simibubi/create/AllParticleTypes.java @@ -2,16 +2,15 @@ package com.simibubi.create; import java.util.function.Supplier; -import com.simibubi.create.content.contraptions.components.steam.SteamJetParticleData; -import com.simibubi.create.content.contraptions.fluids.particle.FluidParticleData; -import com.simibubi.create.content.contraptions.particle.AirFlowParticleData; -import com.simibubi.create.content.contraptions.particle.AirParticleData; -import com.simibubi.create.content.contraptions.particle.CubeParticleData; -import com.simibubi.create.content.contraptions.particle.HeaterParticleData; -import com.simibubi.create.content.contraptions.particle.ICustomParticleData; -import com.simibubi.create.content.contraptions.particle.RotationIndicatorParticleData; -import com.simibubi.create.content.curiosities.bell.SoulBaseParticle; -import com.simibubi.create.content.curiosities.bell.SoulParticle; +import com.simibubi.create.content.equipment.bell.SoulBaseParticle; +import com.simibubi.create.content.equipment.bell.SoulParticle; +import com.simibubi.create.content.fluids.particle.FluidParticleData; +import com.simibubi.create.content.kinetics.base.RotationIndicatorParticleData; +import com.simibubi.create.content.kinetics.fan.AirFlowParticleData; +import com.simibubi.create.content.kinetics.steamEngine.SteamJetParticleData; +import com.simibubi.create.content.trains.CubeParticleData; +import com.simibubi.create.foundation.particle.AirParticleData; +import com.simibubi.create.foundation.particle.ICustomParticleData; import com.simibubi.create.foundation.utility.Lang; import net.minecraft.core.particles.ParticleOptions; @@ -30,7 +29,6 @@ public enum AllParticleTypes { AIR_FLOW(AirFlowParticleData::new), AIR(AirParticleData::new), STEAM_JET(SteamJetParticleData::new), - HEATER_PARTICLE(HeaterParticleData::new), CUBE(CubeParticleData::new), FLUID_PARTICLE(FluidParticleData::new), BASIN_FLUID(FluidParticleData::new), diff --git a/src/main/java/com/simibubi/create/AllRecipeTypes.java b/src/main/java/com/simibubi/create/AllRecipeTypes.java index 67082d834..27d99896d 100644 --- a/src/main/java/com/simibubi/create/AllRecipeTypes.java +++ b/src/main/java/com/simibubi/create/AllRecipeTypes.java @@ -8,28 +8,28 @@ import org.jetbrains.annotations.Nullable; import com.google.common.collect.ImmutableSet; import com.simibubi.create.compat.jei.ConversionRecipe; -import com.simibubi.create.content.contraptions.components.crafter.MechanicalCraftingRecipe; -import com.simibubi.create.content.contraptions.components.crusher.CrushingRecipe; -import com.simibubi.create.content.contraptions.components.deployer.DeployerApplicationRecipe; -import com.simibubi.create.content.contraptions.components.deployer.ManualApplicationRecipe; -import com.simibubi.create.content.contraptions.components.fan.HauntingRecipe; -import com.simibubi.create.content.contraptions.components.fan.SplashingRecipe; -import com.simibubi.create.content.contraptions.components.millstone.MillingRecipe; -import com.simibubi.create.content.contraptions.components.mixer.CompactingRecipe; -import com.simibubi.create.content.contraptions.components.mixer.MixingRecipe; -import com.simibubi.create.content.contraptions.components.press.PressingRecipe; -import com.simibubi.create.content.contraptions.components.saw.CuttingRecipe; -import com.simibubi.create.content.contraptions.fluids.actors.FillingRecipe; -import com.simibubi.create.content.contraptions.itemAssembly.SequencedAssemblyRecipeSerializer; -import com.simibubi.create.content.contraptions.processing.BasinRecipe; -import com.simibubi.create.content.contraptions.processing.EmptyingRecipe; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder.ProcessingRecipeFactory; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipeSerializer; -import com.simibubi.create.content.curiosities.toolbox.ToolboxDyeingRecipe; -import com.simibubi.create.content.curiosities.tools.SandPaperPolishingRecipe; +import com.simibubi.create.content.equipment.sandPaper.SandPaperPolishingRecipe; +import com.simibubi.create.content.equipment.toolbox.ToolboxDyeingRecipe; +import com.simibubi.create.content.fluids.transfer.EmptyingRecipe; +import com.simibubi.create.content.fluids.transfer.FillingRecipe; +import com.simibubi.create.content.kinetics.crafter.MechanicalCraftingRecipe; +import com.simibubi.create.content.kinetics.crusher.CrushingRecipe; +import com.simibubi.create.content.kinetics.deployer.DeployerApplicationRecipe; +import com.simibubi.create.content.kinetics.deployer.ManualApplicationRecipe; +import com.simibubi.create.content.kinetics.fan.HauntingRecipe; +import com.simibubi.create.content.kinetics.fan.SplashingRecipe; +import com.simibubi.create.content.kinetics.millstone.MillingRecipe; +import com.simibubi.create.content.kinetics.mixer.CompactingRecipe; +import com.simibubi.create.content.kinetics.mixer.MixingRecipe; +import com.simibubi.create.content.kinetics.press.PressingRecipe; +import com.simibubi.create.content.kinetics.saw.CuttingRecipe; +import com.simibubi.create.content.processing.basin.BasinRecipe; +import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder.ProcessingRecipeFactory; +import com.simibubi.create.content.processing.recipe.ProcessingRecipeSerializer; +import com.simibubi.create.content.processing.sequenced.SequencedAssemblyRecipeSerializer; +import com.simibubi.create.foundation.recipe.IRecipeTypeInfo; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.RegisteredObjects; -import com.simibubi.create.foundation.utility.recipe.IRecipeTypeInfo; import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceLocation; diff --git a/src/main/java/com/simibubi/create/AllShapes.java b/src/main/java/com/simibubi/create/AllShapes.java index 57ae5e08c..8f3e06568 100644 --- a/src/main/java/com/simibubi/create/AllShapes.java +++ b/src/main/java/com/simibubi/create/AllShapes.java @@ -7,8 +7,8 @@ import static net.minecraft.core.Direction.UP; import java.util.function.BiFunction; -import com.simibubi.create.content.logistics.block.chute.ChuteShapes; -import com.simibubi.create.content.logistics.trains.track.TrackVoxelShapes; +import com.simibubi.create.content.logistics.chute.ChuteShapes; +import com.simibubi.create.content.trains.track.TrackVoxelShapes; import com.simibubi.create.foundation.utility.VoxelShaper; import net.minecraft.core.Direction; @@ -30,6 +30,8 @@ public class AllShapes { CASING_13PX = shape(0, 0, 0, 16, 13, 16).forDirectional(), CASING_12PX = shape(0, 0, 0, 16, 12, 16).forDirectional(), CASING_11PX = shape(0, 0, 0, 16, 11, 16).forDirectional(), + CASING_3PX = shape(0, 0, 0, 16, 3, 16).forDirectional(), + CASING_2PX = shape(0, 0, 0, 16, 2, 16).forDirectional(), MOTOR_BLOCK = shape(3, 0, 3, 13, 14, 13).forDirectional(), FOUR_VOXEL_POLE = shape(6, 0, 6, 10, 16, 10).forAxis(), SIX_VOXEL_POLE = shape(5, 0, 5, 11, 16, 11).forAxis(), @@ -41,15 +43,21 @@ public class AllShapes { .add(2, 13, 2, 14, 16, 14) .add(0, 0, 14, 16, 16, 16) .forHorizontalAxis(), + ELEVATOR_PULLEY = shape(0, 0, 0, 16, 16, 2).add(0, 0, 14, 16, 16, 16) + .add(2, 0, 2, 14, 14, 14) + .forHorizontal(EAST), SAIL_FRAME_COLLISION = shape(0, 5, 0, 16, 9, 16).erase(2, 0, 2, 14, 16, 14) .forDirectional(), SAIL_FRAME = shape(0, 5, 0, 16, 9, 16).forDirectional(), SAIL = shape(0, 5, 0, 16, 10, 16).forDirectional(), HARVESTER_BASE = shape(0, 2, 0, 16, 14, 3).forDirectional(SOUTH), + ROLLER_BASE = shape(0, 0, 0, 16, 16, 10).forDirectional(SOUTH), NOZZLE = shape(2, 0, 2, 14, 14, 14).add(1, 13, 1, 15, 15, 15) .erase(3, 13, 3, 13, 15, 13) .forDirectional(), CRANK = shape(5, 0, 5, 11, 6, 11).add(1, 3, 1, 15, 8, 15) .forDirectional(), + VALVE_HANDLE = shape(5, 0, 5, 11, 4, 11).add(1, 3, 1, 15, 8, 15) + .forDirectional(), CART_ASSEMBLER = shape(0, 12, 0, 16, 16, 16).add(-2, 0, 1, 18, 14, 15) .forHorizontalAxis(), CART_ASSEMBLER_PLAYER_COLLISION = shape(0, 0, 1, 16, 16, 15).forHorizontalAxis(), @@ -104,7 +112,7 @@ public class AllShapes { .add(5, -1, 6, 11, 0, 8) .forHorizontal(SOUTH), PUMP = shape(2, 0, 2, 14, 5, 14).add(4, 0, 4, 12, 16, 12) - .add(3, 12, 3, 13, 16, 13) + .add(3, 11, 3, 13, 16, 13) .forDirectional(Direction.UP), CRUSHING_WHEEL_CONTROLLER_COLLISION = shape(0, 0, 0, 16, 13, 16).forDirectional(Direction.DOWN), @@ -121,7 +129,14 @@ public class AllShapes { GIRDER_BEAM_SHAFT = shape(GIRDER_BEAM.get(Axis.X)).add(SIX_VOXEL_POLE.get(Axis.Z)) .forHorizontalAxis(), + STEP_BOTTOM = shape(0, 0, 8, 16, 8, 16).forHorizontal(SOUTH), + STEP_TOP = shape(0, 8, 8, 16, 16, 16).forHorizontal(SOUTH), + CONTROLS = shape(0, 0, 6, 16, 14, 16).forHorizontal(NORTH), + CONTRAPTION_CONTROLS = shape(0, 0, 6, 2, 14, 16).add(14, 0, 6, 16, 14, 16) + .add(0, 0, 14, 16, 14, 16) + .add(0, 0, 7, 16, 10, 16) + .forHorizontal(NORTH), NIXIE_TUBE = shape(9, 0, 5, 15, 12, 11).add(1, 0, 5, 7, 12, 11) .forHorizontalAxis(), @@ -146,12 +161,19 @@ public class AllShapes { .forHorizontal(SOUTH), PLACARD = shape(2, 0, 2, 14, 3, 14).forDirectional(UP), + + CLIPBOARD_FLOOR = shape(3, 0, 1, 13, 1, 15).forHorizontal(SOUTH), + CLIPBOARD_CEILING = shape(3, 15, 1, 13, 16, 15).forHorizontal(SOUTH), + CLIPBOARD_WALL = shape(3, 1, 0, 13, 15, 1).forHorizontal(SOUTH), TRACK_ORTHO = shape(TrackVoxelShapes.orthogonal()).forHorizontal(NORTH), TRACK_ASC = shape(TrackVoxelShapes.ascending()).forHorizontal(SOUTH), TRACK_DIAG = shape(TrackVoxelShapes.diagonal()).forHorizontal(SOUTH), TRACK_ORTHO_LONG = shape(TrackVoxelShapes.longOrthogonalZOffset()).forHorizontal(SOUTH), + DEPLOYER_INTERACTION = shape(CASING_12PX.get(UP)).add(SIX_VOXEL_POLE.get(Axis.Y)) + .forDirectional(UP), + WHISTLE_BASE = shape(1, 0, 1, 15, 3, 15).add(5, 0, 5, 11, 8, 11) .forDirectional(UP) @@ -181,9 +203,15 @@ public class AllShapes { // Static Block Shapes public static final VoxelShape - TRACK_CROSS = shape(TRACK_ORTHO.get(SOUTH)).add(TRACK_ORTHO.get(EAST)) + SCAFFOLD_HALF = shape(0, 8, 0, 16, 16, 16).build(), SCAFFOLD_FULL = shape(SCAFFOLD_HALF).add(0, 0, 0, 2, 16, 2) + .add(0, 0, 14, 2, 16, 16) + .add(14, 0, 0, 16, 16, 2) + .add(14, 0, 14, 16, 16, 16) .build(), + TRACK_CROSS = shape(TRACK_ORTHO.get(SOUTH)).add(TRACK_ORTHO.get(EAST)) + .build(), + TRACK_CROSS_DIAG = shape(TRACK_DIAG.get(SOUTH)).add(TRACK_DIAG.get(EAST)) .build(), @@ -210,7 +238,7 @@ public class AllShapes { HEATER_BLOCK_SHAPE = shape(1, 0, 1, 15, 14, 15).build(), HEATER_BLOCK_SPECIAL_COLLISION_SHAPE = shape(0, 0, 0, 16, 4, 16).build(), CRUSHING_WHEEL_COLLISION_SHAPE = cuboid(0, 0, 0, 16, 16, 16), SEAT = cuboid(0, 0, 0, 16, 8, 16), - SEAT_COLLISION = cuboid(0, 0, 0, 16, 6, 16), + SEAT_COLLISION = cuboid(0, 0, 0, 16, 6, 16), SEAT_COLLISION_PLAYERS = cuboid(0, 0, 0, 16, 3, 16), MECHANICAL_PROCESSOR_SHAPE = shape(Shapes.block()).erase(4, 0, 4, 12, 16, 12) .build(), TURNTABLE_SHAPE = shape(1, 4, 1, 15, 8, 15).add(5, 0, 5, 11, 4, 11) @@ -221,12 +249,11 @@ public class AllShapes { BELT_COLLISION_MASK = cuboid(0, 0, 0, 16, 19, 16), SCHEMATICANNON_SHAPE = shape(1, 0, 1, 15, 8, 15).add(0.5, 8, 0.5, 15.5, 11, 15.5) .build(), - PULLEY_MAGNET = shape(3, 0, 3, 13, 2, 13).add(FOUR_VOXEL_POLE.get(UP)) + PULLEY_MAGNET = shape(3, 0, 3, 13, 3, 13).add(FOUR_VOXEL_POLE.get(UP)) .build(), SPOUT = shape(1, 2, 1, 15, 14, 15).add(2, 0, 2, 14, 16, 14) .build(), - MILLSTONE = shape(0, 0, 0, 16, 6, 16).add(2, 6, 2, 14, 13, 14) - .add(3, 13, 3, 13, 16, 13) + MILLSTONE = shape(0, 0, 0, 16, 6, 16).add(2, 6, 2, 14, 16, 14) .build(), CUCKOO_CLOCK = shape(1, 0, 1, 15, 19, 15).build(), GAUGE_SHAPE_UP = shape(1, 0, 0, 15, 2, 16).add(2, 2, 1, 14, 14, 15) @@ -239,9 +266,6 @@ public class AllShapes { .build(), CHUTE = shape(1, 8, 1, 15, 16, 15).add(2, 0, 2, 14, 8, 14) .build(), - SMART_CHUTE = shape(0, 0, 0, 16, 5, 16).add(0, 9, 0, 16, 15, 16) - .add(1, 0, 1, 15, 16, 15) - .build(), TANK = shape(1, 0, 1, 15, 16, 15).build(), TANK_TOP = shape(TANK_TOP_LID).add(TANK) .build(), TANK_BOTTOM = shape(TANK_BOTTOM_LID).add(TANK) @@ -255,8 +279,6 @@ public class AllShapes { FUNNEL_CEILING = shape(2, 8, 2, 14, 18, 14).add(1, 8, 1, 15, 15, 15) .add(0, 6, 0, 16, 12, 16) .build(), - DEPOT = shape(CASING_11PX.get(Direction.UP)).add(1, 11, 1, 15, 13, 15) - .build(), STATION = shape(0, 0, 0, 16, 2, 16).add(1, 0, 1, 15, 13, 15) .build(), diff --git a/src/main/java/com/simibubi/create/AllSpriteShifts.java b/src/main/java/com/simibubi/create/AllSpriteShifts.java index 31abb134d..f79047f46 100644 --- a/src/main/java/com/simibubi/create/AllSpriteShifts.java +++ b/src/main/java/com/simibubi/create/AllSpriteShifts.java @@ -25,8 +25,15 @@ public class AllSpriteShifts { public static final SpriteShiftEntry BURNER_FLAME = get("block/blaze_burner_flame", "block/blaze_burner_flame_scroll"), - SUPER_BURNER_FLAME = - get("block/blaze_burner_flame", "block/blaze_burner_flame_superheated_scroll"); + SUPER_BURNER_FLAME = get("block/blaze_burner_flame", "block/blaze_burner_flame_superheated_scroll"); + + public static final CTSpriteShiftEntry ANDESITE_SCAFFOLD = horizontal("scaffold/andesite_scaffold"), + BRASS_SCAFFOLD = horizontal("scaffold/brass_scaffold"), + COPPER_SCAFFOLD = horizontal("scaffold/copper_scaffold"); + + public static final CTSpriteShiftEntry ANDESITE_SCAFFOLD_INSIDE = horizontal("scaffold/andesite_scaffold_inside"), + BRASS_SCAFFOLD_INSIDE = horizontal("scaffold/brass_scaffold_inside"), + COPPER_SCAFFOLD_INSIDE = horizontal("scaffold/copper_scaffold_inside"); public static final CTSpriteShiftEntry FRAMED_GLASS = getCT(AllCTTypes.OMNIDIRECTIONAL, "palettes/framed_glass", "palettes/framed_glass"), @@ -35,8 +42,8 @@ public class AllSpriteShifts { VERTICAL_FRAMED_GLASS = getCT(AllCTTypes.VERTICAL, "palettes/framed_glass", "palettes/vertical_framed_glass"), ORNATE_IRON_WINDOW = vertical("palettes/ornate_iron_window"); - public static final CTSpriteShiftEntry CRAFTER_FRONT = getCT(AllCTTypes.OMNIDIRECTIONAL, "crafter_top", "brass_casing"), - CRAFTER_SIDE = vertical("crafter_side"), CRAFTER_OTHERSIDE = horizontal("crafter_side"), + public static final CTSpriteShiftEntry CRAFTER_SIDE = vertical("crafter_side"), + CRAFTER_OTHERSIDE = horizontal("crafter_side"), ANDESITE_ENCASED_COGWHEEL_SIDE = vertical("andesite_encased_cogwheel_side"), ANDESITE_ENCASED_COGWHEEL_OTHERSIDE = horizontal("andesite_encased_cogwheel_side"), BRASS_ENCASED_COGWHEEL_SIDE = vertical("brass_encased_cogwheel_side"), @@ -47,24 +54,29 @@ public class AllSpriteShifts { BRASS_CASING = omni("brass_casing"), COPPER_CASING = omni("copper_casing"), SHADOW_STEEL_CASING = omni("shadow_steel_casing"), REFINED_RADIANCE_CASING = omni("refined_radiance_casing"), RAILWAY_CASING = omni("railway_casing"), RAILWAY_CASING_SIDE = omni("railway_casing_side"), - CREATIVE_CASING = getCT(AllCTTypes.CROSS, "creative_casing"); + CREATIVE_CASING = getCT(AllCTTypes.RECTANGLE, "creative_casing"); public static final CTSpriteShiftEntry CHASSIS_SIDE = omni("linear_chassis_side"), SECONDARY_CHASSIS_SIDE = omni("secondary_linear_chassis_side"), CHASSIS = omni("linear_chassis_end"), CHASSIS_STICKY = omni("linear_chassis_end_sticky"); - public static final CTSpriteShiftEntry BRASS_TUNNEL_TOP = vertical("brass_tunnel_top"), - FLUID_TANK = getCT(AllCTTypes.RECTANGLE, "fluid_tank"), FLUID_TANK_TOP = getCT(AllCTTypes.RECTANGLE, "fluid_tank_top"), + public static final CTSpriteShiftEntry BRASS_TUNNEL_TOP = vertical("tunnel/brass_tunnel_top"), + FLUID_TANK = getCT(AllCTTypes.RECTANGLE, "fluid_tank"), + FLUID_TANK_TOP = getCT(AllCTTypes.RECTANGLE, "fluid_tank_top"), FLUID_TANK_INNER = getCT(AllCTTypes.RECTANGLE, "fluid_tank_inner"), - CREATIVE_FLUID_TANK = getCT(AllCTTypes.CROSS, "creative_fluid_tank"); + CREATIVE_FLUID_TANK = getCT(AllCTTypes.RECTANGLE, "creative_fluid_tank"); public static final Couple VAULT_TOP = vault("top"), VAULT_FRONT = vault("front"), VAULT_SIDE = vault("side"), VAULT_BOTTOM = vault("bottom"); + public static final SpriteShiftEntry ELEVATOR_BELT = + get("block/elevator_pulley_belt", "block/elevator_pulley_belt_scroll"), + ELEVATOR_COIL = get("block/elevator_pulley_coil", "block/elevator_pulley_coil_scroll"); + public static final SpriteShiftEntry BELT = get("block/belt", "block/belt_scroll"), BELT_OFFSET = get("block/belt_offset", "block/belt_scroll"), BELT_DIAGONAL = get("block/belt_diagonal", "block/belt_diagonal_scroll"), - ANDESIDE_BELT_CASING = get("block/brass_casing_belt", "block/andesite_casing_belt"), + ANDESIDE_BELT_CASING = get("block/belt/brass_belt_casing", "block/belt/andesite_belt_casing"), CRAFTER_THINGIES = get("block/crafter_thingies", "block/crafter_thingies"); static { @@ -73,7 +85,7 @@ public class AllSpriteShifts { private static void populateMaps() { WoodType[] supportedWoodTypes = new WoodType[] { WoodType.OAK, WoodType.SPRUCE, WoodType.BIRCH, WoodType.ACACIA, - WoodType.JUNGLE, WoodType.DARK_OAK, WoodType.CRIMSON, WoodType.WARPED }; + WoodType.JUNGLE, WoodType.DARK_OAK, WoodType.MANGROVE, WoodType.CRIMSON, WoodType.WARPED }; Arrays.stream(supportedWoodTypes) .forEach(woodType -> WOODEN_WINDOWS.put(woodType, vertical("palettes/" + woodType.name() + "_window"))); @@ -81,14 +93,15 @@ public class AllSpriteShifts { String id = color.getSerializedName(); DYED_BELTS.put(color, get("block/belt", "block/belt/" + id + "_scroll")); DYED_OFFSET_BELTS.put(color, get("block/belt_offset", "block/belt/" + id + "_scroll")); - DYED_DIAGONAL_BELTS.put(color, - get("block/belt_diagonal", "block/belt/" + id + "_diagonal_scroll")); + DYED_DIAGONAL_BELTS.put(color, get("block/belt_diagonal", "block/belt/" + id + "_diagonal_scroll")); } } private static Couple vault(String name) { - final String prefixed = "vault_" + name; - return Couple.createWithContext(b -> getCT(AllCTTypes.CROSS, prefixed, b ? prefixed : prefixed + "_large")); + final String prefixed = "block/vault/vault_" + name; + return Couple.createWithContext( + medium -> CTSpriteShifter.getCT(AllCTTypes.RECTANGLE, Create.asResource(prefixed + "_small"), + Create.asResource(medium ? prefixed + "_medium" : prefixed + "_large"))); } // @@ -112,7 +125,8 @@ public class AllSpriteShifts { } private static CTSpriteShiftEntry getCT(CTType type, String blockTextureName, String connectedTextureName) { - return CTSpriteShifter.getCT(type, Create.asResource("block/" + blockTextureName), Create.asResource("block/" + connectedTextureName + "_connected")); + return CTSpriteShifter.getCT(type, Create.asResource("block/" + blockTextureName), + Create.asResource("block/" + connectedTextureName + "_connected")); } private static CTSpriteShiftEntry getCT(CTType type, String blockTextureName) { diff --git a/src/main/java/com/simibubi/create/AllTags.java b/src/main/java/com/simibubi/create/AllTags.java index fa89b748c..7dbac12e8 100644 --- a/src/main/java/com/simibubi/create/AllTags.java +++ b/src/main/java/com/simibubi/create/AllTags.java @@ -7,11 +7,7 @@ import static com.simibubi.create.AllTags.NameSpace.TIC; import java.util.Collections; -import com.simibubi.create.foundation.data.TagGen; import com.simibubi.create.foundation.utility.Lang; -import com.tterrag.registrate.builders.BlockBuilder; -import com.tterrag.registrate.builders.ItemBuilder; -import com.tterrag.registrate.util.nullness.NonNullFunction; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.BlockTags; @@ -51,27 +47,6 @@ public class AllTags { return forgeTag(ForgeRegistries.FLUIDS, path); } - @Deprecated(forRemoval = true) - public static NonNullFunction, BlockBuilder> axeOrPickaxe() { - return TagGen.axeOrPickaxe(); - } - - @Deprecated(forRemoval = true) - public static NonNullFunction, BlockBuilder> axeOnly() { - return TagGen.axeOnly(); - } - - @Deprecated(forRemoval = true) - public static NonNullFunction, BlockBuilder> pickaxeOnly() { - return TagGen.pickaxeOnly(); - } - - @Deprecated(forRemoval = true) - public static NonNullFunction, ItemBuilder>> tagBlockAndItem( - String... path) { - return TagGen.tagBlockAndItem(path); - } - public enum NameSpace { MOD(Create.ID, false, true), FORGE("forge"), @@ -106,10 +81,15 @@ public class AllTags { SAFE_NBT, SEATS, TOOLBOXES, + TRACKS, + GIRDABLE_TRACKS, TREE_ATTACHMENTS, VALVE_HANDLES, WINDMILL_SAILS, WRENCH_PICKUP, + COPYCAT_ALLOW, + COPYCAT_DENY, + CONTRAPTION_INVENTORY_DENY, RELOCATION_NOT_SUPPORTED(FORGE), WG_STONE(FORGE), @@ -154,6 +134,10 @@ public class AllTags { .is(tag); } + public boolean matches(ItemStack stack) { + return stack != null && stack.getItem() instanceof BlockItem blockItem && matches(blockItem.getBlock()); + } + public boolean matches(BlockState state) { return state.is(tag); } @@ -167,7 +151,7 @@ public class AllTags { BLAZE_BURNER_FUEL_SPECIAL(MOD, "blaze_burner_fuel/special"), CASING, CREATE_INGOTS, - CRUSHED_ORES, + CRUSHED_RAW_MATERIALS, MODDED_STRIPPED_LOGS, MODDED_STRIPPED_WOOD, PRESSURIZED_AIR_SOURCES, @@ -180,6 +164,7 @@ public class AllTags { VANILLA_STRIPPED_LOGS, VANILLA_STRIPPED_WOOD, DEPLOYABLE_DRINK, + CONTRAPTION_CONTROLLED, STRIPPED_LOGS(FORGE), STRIPPED_WOOD(FORGE), diff --git a/src/main/java/com/simibubi/create/AllTileEntities.java b/src/main/java/com/simibubi/create/AllTileEntities.java deleted file mode 100644 index 6f74119bb..000000000 --- a/src/main/java/com/simibubi/create/AllTileEntities.java +++ /dev/null @@ -1,830 +0,0 @@ -package com.simibubi.create; - -import static com.simibubi.create.Create.REGISTRATE; -import static com.simibubi.create.content.logistics.block.display.AllDisplayBehaviours.assignDataBehaviourTE; - -import com.simibubi.create.content.contraptions.base.CutoutRotatingInstance; -import com.simibubi.create.content.contraptions.base.HalfShaftInstance; -import com.simibubi.create.content.contraptions.base.HorizontalHalfShaftInstance; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.content.contraptions.base.SingleRotatingInstance; -import com.simibubi.create.content.contraptions.components.actors.DrillInstance; -import com.simibubi.create.content.contraptions.components.actors.DrillRenderer; -import com.simibubi.create.content.contraptions.components.actors.DrillTileEntity; -import com.simibubi.create.content.contraptions.components.actors.HarvesterRenderer; -import com.simibubi.create.content.contraptions.components.actors.HarvesterTileEntity; -import com.simibubi.create.content.contraptions.components.actors.PSIInstance; -import com.simibubi.create.content.contraptions.components.actors.PortableFluidInterfaceTileEntity; -import com.simibubi.create.content.contraptions.components.actors.PortableItemInterfaceTileEntity; -import com.simibubi.create.content.contraptions.components.actors.PortableStorageInterfaceRenderer; -import com.simibubi.create.content.contraptions.components.clock.CuckooClockRenderer; -import com.simibubi.create.content.contraptions.components.clock.CuckooClockTileEntity; -import com.simibubi.create.content.contraptions.components.crafter.MechanicalCrafterInstance; -import com.simibubi.create.content.contraptions.components.crafter.MechanicalCrafterRenderer; -import com.simibubi.create.content.contraptions.components.crafter.MechanicalCrafterTileEntity; -import com.simibubi.create.content.contraptions.components.crank.HandCrankInstance; -import com.simibubi.create.content.contraptions.components.crank.HandCrankRenderer; -import com.simibubi.create.content.contraptions.components.crank.HandCrankTileEntity; -import com.simibubi.create.content.contraptions.components.crusher.CrushingWheelControllerTileEntity; -import com.simibubi.create.content.contraptions.components.crusher.CrushingWheelTileEntity; -import com.simibubi.create.content.contraptions.components.deployer.DeployerInstance; -import com.simibubi.create.content.contraptions.components.deployer.DeployerRenderer; -import com.simibubi.create.content.contraptions.components.deployer.DeployerTileEntity; -import com.simibubi.create.content.contraptions.components.fan.EncasedFanRenderer; -import com.simibubi.create.content.contraptions.components.fan.EncasedFanTileEntity; -import com.simibubi.create.content.contraptions.components.fan.FanInstance; -import com.simibubi.create.content.contraptions.components.fan.NozzleTileEntity; -import com.simibubi.create.content.contraptions.components.flywheel.FlyWheelInstance; -import com.simibubi.create.content.contraptions.components.flywheel.FlywheelRenderer; -import com.simibubi.create.content.contraptions.components.flywheel.FlywheelTileEntity; -import com.simibubi.create.content.contraptions.components.millstone.MillStoneCogInstance; -import com.simibubi.create.content.contraptions.components.millstone.MillstoneRenderer; -import com.simibubi.create.content.contraptions.components.millstone.MillstoneTileEntity; -import com.simibubi.create.content.contraptions.components.mixer.MechanicalMixerRenderer; -import com.simibubi.create.content.contraptions.components.mixer.MechanicalMixerTileEntity; -import com.simibubi.create.content.contraptions.components.mixer.MixerInstance; -import com.simibubi.create.content.contraptions.components.motor.CreativeMotorRenderer; -import com.simibubi.create.content.contraptions.components.motor.CreativeMotorTileEntity; -import com.simibubi.create.content.contraptions.components.press.MechanicalPressRenderer; -import com.simibubi.create.content.contraptions.components.press.MechanicalPressTileEntity; -import com.simibubi.create.content.contraptions.components.press.PressInstance; -import com.simibubi.create.content.contraptions.components.saw.SawInstance; -import com.simibubi.create.content.contraptions.components.saw.SawRenderer; -import com.simibubi.create.content.contraptions.components.saw.SawTileEntity; -import com.simibubi.create.content.contraptions.components.steam.PoweredShaftTileEntity; -import com.simibubi.create.content.contraptions.components.steam.SteamEngineInstance; -import com.simibubi.create.content.contraptions.components.steam.SteamEngineRenderer; -import com.simibubi.create.content.contraptions.components.steam.SteamEngineTileEntity; -import com.simibubi.create.content.contraptions.components.steam.whistle.WhistleRenderer; -import com.simibubi.create.content.contraptions.components.steam.whistle.WhistleTileEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.BearingInstance; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.BearingRenderer; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.ClockworkBearingTileEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.MechanicalBearingTileEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.WindmillBearingTileEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.chassis.ChassisTileEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.chassis.StickerInstance; -import com.simibubi.create.content.contraptions.components.structureMovement.chassis.StickerRenderer; -import com.simibubi.create.content.contraptions.components.structureMovement.chassis.StickerTileEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.gantry.GantryCarriageInstance; -import com.simibubi.create.content.contraptions.components.structureMovement.gantry.GantryCarriageRenderer; -import com.simibubi.create.content.contraptions.components.structureMovement.gantry.GantryCarriageTileEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerTileEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonRenderer; -import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonTileEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.pulley.HosePulleyInstance; -import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyRenderer; -import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyTileEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.pulley.RopePulleyInstance; -import com.simibubi.create.content.contraptions.components.turntable.TurntableTileEntity; -import com.simibubi.create.content.contraptions.components.waterwheel.WaterWheelTileEntity; -import com.simibubi.create.content.contraptions.fluids.PumpCogInstance; -import com.simibubi.create.content.contraptions.fluids.PumpRenderer; -import com.simibubi.create.content.contraptions.fluids.PumpTileEntity; -import com.simibubi.create.content.contraptions.fluids.actors.HosePulleyRenderer; -import com.simibubi.create.content.contraptions.fluids.actors.HosePulleyTileEntity; -import com.simibubi.create.content.contraptions.fluids.actors.ItemDrainRenderer; -import com.simibubi.create.content.contraptions.fluids.actors.ItemDrainTileEntity; -import com.simibubi.create.content.contraptions.fluids.actors.SpoutRenderer; -import com.simibubi.create.content.contraptions.fluids.actors.SpoutTileEntity; -import com.simibubi.create.content.contraptions.fluids.pipes.FluidPipeTileEntity; -import com.simibubi.create.content.contraptions.fluids.pipes.FluidValveInstance; -import com.simibubi.create.content.contraptions.fluids.pipes.FluidValveRenderer; -import com.simibubi.create.content.contraptions.fluids.pipes.FluidValveTileEntity; -import com.simibubi.create.content.contraptions.fluids.pipes.SmartFluidPipeTileEntity; -import com.simibubi.create.content.contraptions.fluids.pipes.StraightPipeTileEntity; -import com.simibubi.create.content.contraptions.fluids.pipes.TransparentStraightPipeRenderer; -import com.simibubi.create.content.contraptions.fluids.tank.CreativeFluidTankTileEntity; -import com.simibubi.create.content.contraptions.fluids.tank.FluidTankRenderer; -import com.simibubi.create.content.contraptions.fluids.tank.FluidTankTileEntity; -import com.simibubi.create.content.contraptions.processing.BasinRenderer; -import com.simibubi.create.content.contraptions.processing.BasinTileEntity; -import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerRenderer; -import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerTileEntity; -import com.simibubi.create.content.contraptions.relays.advanced.GantryShaftTileEntity; -import com.simibubi.create.content.contraptions.relays.advanced.SpeedControllerRenderer; -import com.simibubi.create.content.contraptions.relays.advanced.SpeedControllerTileEntity; -import com.simibubi.create.content.contraptions.relays.advanced.sequencer.SequencedGearshiftTileEntity; -import com.simibubi.create.content.contraptions.relays.belt.BeltInstance; -import com.simibubi.create.content.contraptions.relays.belt.BeltRenderer; -import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity; -import com.simibubi.create.content.contraptions.relays.elementary.BracketedKineticTileEntity; -import com.simibubi.create.content.contraptions.relays.elementary.BracketedKineticTileInstance; -import com.simibubi.create.content.contraptions.relays.elementary.BracketedKineticTileRenderer; -import com.simibubi.create.content.contraptions.relays.elementary.SimpleKineticTileEntity; -import com.simibubi.create.content.contraptions.relays.encased.AdjustablePulleyTileEntity; -import com.simibubi.create.content.contraptions.relays.encased.ClutchTileEntity; -import com.simibubi.create.content.contraptions.relays.encased.EncasedCogInstance; -import com.simibubi.create.content.contraptions.relays.encased.EncasedCogRenderer; -import com.simibubi.create.content.contraptions.relays.encased.ShaftInstance; -import com.simibubi.create.content.contraptions.relays.encased.ShaftRenderer; -import com.simibubi.create.content.contraptions.relays.encased.SplitShaftInstance; -import com.simibubi.create.content.contraptions.relays.encased.SplitShaftRenderer; -import com.simibubi.create.content.contraptions.relays.gauge.GaugeInstance; -import com.simibubi.create.content.contraptions.relays.gauge.GaugeRenderer; -import com.simibubi.create.content.contraptions.relays.gauge.SpeedGaugeTileEntity; -import com.simibubi.create.content.contraptions.relays.gauge.StressGaugeTileEntity; -import com.simibubi.create.content.contraptions.relays.gearbox.GearboxInstance; -import com.simibubi.create.content.contraptions.relays.gearbox.GearboxRenderer; -import com.simibubi.create.content.contraptions.relays.gearbox.GearboxTileEntity; -import com.simibubi.create.content.contraptions.relays.gearbox.GearshiftTileEntity; -import com.simibubi.create.content.curiosities.armor.CopperBacktankInstance; -import com.simibubi.create.content.curiosities.armor.CopperBacktankRenderer; -import com.simibubi.create.content.curiosities.armor.CopperBacktankTileEntity; -import com.simibubi.create.content.curiosities.bell.BellRenderer; -import com.simibubi.create.content.curiosities.bell.HauntedBellTileEntity; -import com.simibubi.create.content.curiosities.bell.PeculiarBellTileEntity; -import com.simibubi.create.content.curiosities.deco.PlacardRenderer; -import com.simibubi.create.content.curiosities.deco.PlacardTileEntity; -import com.simibubi.create.content.curiosities.deco.SlidingDoorRenderer; -import com.simibubi.create.content.curiosities.deco.SlidingDoorTileEntity; -import com.simibubi.create.content.curiosities.toolbox.ToolBoxInstance; -import com.simibubi.create.content.curiosities.toolbox.ToolboxRenderer; -import com.simibubi.create.content.curiosities.toolbox.ToolboxTileEntity; -import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelInstance; -import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelRenderer; -import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelTileEntity; -import com.simibubi.create.content.logistics.block.belts.tunnel.BrassTunnelTileEntity; -import com.simibubi.create.content.logistics.block.chute.ChuteRenderer; -import com.simibubi.create.content.logistics.block.chute.ChuteTileEntity; -import com.simibubi.create.content.logistics.block.chute.SmartChuteRenderer; -import com.simibubi.create.content.logistics.block.chute.SmartChuteTileEntity; -import com.simibubi.create.content.logistics.block.depot.DepotRenderer; -import com.simibubi.create.content.logistics.block.depot.DepotTileEntity; -import com.simibubi.create.content.logistics.block.depot.EjectorInstance; -import com.simibubi.create.content.logistics.block.depot.EjectorRenderer; -import com.simibubi.create.content.logistics.block.depot.EjectorTileEntity; -import com.simibubi.create.content.logistics.block.diodes.BrassDiodeInstance; -import com.simibubi.create.content.logistics.block.diodes.BrassDiodeRenderer; -import com.simibubi.create.content.logistics.block.diodes.PulseExtenderTileEntity; -import com.simibubi.create.content.logistics.block.diodes.PulseRepeaterTileEntity; -import com.simibubi.create.content.logistics.block.display.DisplayLinkRenderer; -import com.simibubi.create.content.logistics.block.display.DisplayLinkTileEntity; -import com.simibubi.create.content.logistics.block.display.source.NixieTubeDisplaySource; -import com.simibubi.create.content.logistics.block.display.target.NixieTubeDisplayTarget; -import com.simibubi.create.content.logistics.block.funnel.FunnelInstance; -import com.simibubi.create.content.logistics.block.funnel.FunnelRenderer; -import com.simibubi.create.content.logistics.block.funnel.FunnelTileEntity; -import com.simibubi.create.content.logistics.block.inventories.CreativeCrateTileEntity; -import com.simibubi.create.content.logistics.block.mechanicalArm.ArmInstance; -import com.simibubi.create.content.logistics.block.mechanicalArm.ArmRenderer; -import com.simibubi.create.content.logistics.block.mechanicalArm.ArmTileEntity; -import com.simibubi.create.content.logistics.block.redstone.AnalogLeverInstance; -import com.simibubi.create.content.logistics.block.redstone.AnalogLeverRenderer; -import com.simibubi.create.content.logistics.block.redstone.AnalogLeverTileEntity; -import com.simibubi.create.content.logistics.block.redstone.ContentObserverTileEntity; -import com.simibubi.create.content.logistics.block.redstone.NixieTubeRenderer; -import com.simibubi.create.content.logistics.block.redstone.NixieTubeTileEntity; -import com.simibubi.create.content.logistics.block.redstone.RedstoneLinkTileEntity; -import com.simibubi.create.content.logistics.block.redstone.StockpileSwitchTileEntity; -import com.simibubi.create.content.logistics.block.vault.ItemVaultTileEntity; -import com.simibubi.create.content.logistics.item.LecternControllerRenderer; -import com.simibubi.create.content.logistics.item.LecternControllerTileEntity; -import com.simibubi.create.content.logistics.trains.BogeyTileEntityRenderer; -import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayRenderer; -import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayTileEntity; -import com.simibubi.create.content.logistics.trains.management.edgePoint.observer.TrackObserverRenderer; -import com.simibubi.create.content.logistics.trains.management.edgePoint.observer.TrackObserverTileEntity; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalRenderer; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalTileEntity; -import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationRenderer; -import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationTileEntity; -import com.simibubi.create.content.logistics.trains.track.FakeTrackTileEntity; -import com.simibubi.create.content.logistics.trains.track.StandardBogeyTileEntity; -import com.simibubi.create.content.logistics.trains.track.TrackInstance; -import com.simibubi.create.content.logistics.trains.track.TrackRenderer; -import com.simibubi.create.content.logistics.trains.track.TrackTileEntity; -import com.simibubi.create.content.schematics.block.SchematicTableTileEntity; -import com.simibubi.create.content.schematics.block.SchematicannonInstance; -import com.simibubi.create.content.schematics.block.SchematicannonRenderer; -import com.simibubi.create.content.schematics.block.SchematicannonTileEntity; -import com.simibubi.create.foundation.tileEntity.renderer.SmartTileEntityRenderer; -import com.tterrag.registrate.util.entry.BlockEntityEntry; - -public class AllTileEntities { - - // Schematics - public static final BlockEntityEntry SCHEMATICANNON = REGISTRATE - .tileEntity("schematicannon", SchematicannonTileEntity::new) - .instance(() -> SchematicannonInstance::new) - .validBlocks(AllBlocks.SCHEMATICANNON) - .renderer(() -> SchematicannonRenderer::new) - .register(); - - public static final BlockEntityEntry SCHEMATIC_TABLE = REGISTRATE - .tileEntity("schematic_table", SchematicTableTileEntity::new) - .validBlocks(AllBlocks.SCHEMATIC_TABLE) - .register(); - - // Kinetics - public static final BlockEntityEntry BRACKETED_KINETIC = REGISTRATE - .tileEntity("simple_kinetic", BracketedKineticTileEntity::new) - .instance(() -> BracketedKineticTileInstance::new, false) - .validBlocks(AllBlocks.SHAFT, AllBlocks.COGWHEEL, AllBlocks.LARGE_COGWHEEL) - .renderer(() -> BracketedKineticTileRenderer::new) - .register(); - - public static final BlockEntityEntry MOTOR = REGISTRATE - .tileEntity("motor", CreativeMotorTileEntity::new) - .instance(() -> HalfShaftInstance::new, false) - .validBlocks(AllBlocks.CREATIVE_MOTOR) - .renderer(() -> CreativeMotorRenderer::new) - .register(); - - public static final BlockEntityEntry GEARBOX = REGISTRATE - .tileEntity("gearbox", GearboxTileEntity::new) - .instance(() -> GearboxInstance::new, false) - .validBlocks(AllBlocks.GEARBOX) - .renderer(() -> GearboxRenderer::new) - .register(); - - public static final BlockEntityEntry ENCASED_SHAFT = REGISTRATE - .tileEntity("encased_shaft", KineticTileEntity::new) - .instance(() -> ShaftInstance::new, false) - .validBlocks(AllBlocks.ANDESITE_ENCASED_SHAFT, AllBlocks.BRASS_ENCASED_SHAFT, AllBlocks.ENCASED_CHAIN_DRIVE, - AllBlocks.METAL_GIRDER_ENCASED_SHAFT) - .renderer(() -> ShaftRenderer::new) - .register(); - - public static final BlockEntityEntry ENCASED_COGWHEEL = REGISTRATE - .tileEntity("encased_cogwheel", SimpleKineticTileEntity::new) - .instance(() -> EncasedCogInstance::small, false) - .validBlocks(AllBlocks.ANDESITE_ENCASED_COGWHEEL, AllBlocks.BRASS_ENCASED_COGWHEEL) - .renderer(() -> EncasedCogRenderer::small) - .register(); - - public static final BlockEntityEntry ENCASED_LARGE_COGWHEEL = REGISTRATE - .tileEntity("encased_large_cogwheel", SimpleKineticTileEntity::new) - .instance(() -> EncasedCogInstance::large, false) - .validBlocks(AllBlocks.ANDESITE_ENCASED_LARGE_COGWHEEL, AllBlocks.BRASS_ENCASED_LARGE_COGWHEEL) - .renderer(() -> EncasedCogRenderer::large) - .register(); - - public static final BlockEntityEntry ADJUSTABLE_PULLEY = REGISTRATE - .tileEntity("adjustable_pulley", AdjustablePulleyTileEntity::new) - .instance(() -> ShaftInstance::new, false) - .validBlocks(AllBlocks.ADJUSTABLE_CHAIN_GEARSHIFT) - .renderer(() -> ShaftRenderer::new) - .register(); - - public static final BlockEntityEntry ENCASED_FAN = REGISTRATE - .tileEntity("encased_fan", EncasedFanTileEntity::new) - .instance(() -> FanInstance::new, false) - .validBlocks(AllBlocks.ENCASED_FAN) - .renderer(() -> EncasedFanRenderer::new) - .register(); - - public static final BlockEntityEntry NOZZLE = REGISTRATE - .tileEntity("nozzle", NozzleTileEntity::new) - .validBlocks(AllBlocks.NOZZLE) - // .renderer(() -> renderer) - .register(); - - public static final BlockEntityEntry CLUTCH = REGISTRATE - .tileEntity("clutch", ClutchTileEntity::new) - .instance(() -> SplitShaftInstance::new, false) - .validBlocks(AllBlocks.CLUTCH) - .renderer(() -> SplitShaftRenderer::new) - .register(); - - public static final BlockEntityEntry GEARSHIFT = REGISTRATE - .tileEntity("gearshift", GearshiftTileEntity::new) - .instance(() -> SplitShaftInstance::new, false) - .validBlocks(AllBlocks.GEARSHIFT) - .renderer(() -> SplitShaftRenderer::new) - .register(); - - public static final BlockEntityEntry TURNTABLE = REGISTRATE - .tileEntity("turntable", TurntableTileEntity::new) - .instance(() -> SingleRotatingInstance::new, false) - .validBlocks(AllBlocks.TURNTABLE) - .renderer(() -> KineticTileEntityRenderer::new) - .register(); - - public static final BlockEntityEntry HAND_CRANK = REGISTRATE - .tileEntity("hand_crank", HandCrankTileEntity::new) - .instance(() -> HandCrankInstance::new) - .validBlocks(AllBlocks.HAND_CRANK, AllBlocks.COPPER_VALVE_HANDLE) - .validBlocks(AllBlocks.DYED_VALVE_HANDLES.toArray()) - .renderer(() -> HandCrankRenderer::new) - .register(); - - public static final BlockEntityEntry CUCKOO_CLOCK = REGISTRATE - .tileEntity("cuckoo_clock", CuckooClockTileEntity::new) - .instance(() -> HorizontalHalfShaftInstance::new) - .validBlocks(AllBlocks.CUCKOO_CLOCK, AllBlocks.MYSTERIOUS_CUCKOO_CLOCK) - .renderer(() -> CuckooClockRenderer::new) - .register(); - - public static final BlockEntityEntry GANTRY_SHAFT = REGISTRATE - .tileEntity("gantry_shaft", GantryShaftTileEntity::new) - .instance(() -> SingleRotatingInstance::new, false) - .validBlocks(AllBlocks.GANTRY_SHAFT) - .renderer(() -> KineticTileEntityRenderer::new) - .register(); - - public static final BlockEntityEntry GANTRY_PINION = REGISTRATE - .tileEntity("gantry_pinion", GantryCarriageTileEntity::new) - .instance(() -> GantryCarriageInstance::new) - .validBlocks(AllBlocks.GANTRY_CARRIAGE) - .renderer(() -> GantryCarriageRenderer::new) - .register(); - - public static final BlockEntityEntry MECHANICAL_PUMP = REGISTRATE - .tileEntity("mechanical_pump", PumpTileEntity::new) - .instance(() -> PumpCogInstance::new) - .validBlocks(AllBlocks.MECHANICAL_PUMP) - .renderer(() -> PumpRenderer::new) - .register(); - - public static final BlockEntityEntry SMART_FLUID_PIPE = REGISTRATE - .tileEntity("smart_fluid_pipe", SmartFluidPipeTileEntity::new) - .validBlocks(AllBlocks.SMART_FLUID_PIPE) - .renderer(() -> SmartTileEntityRenderer::new) - .register(); - - public static final BlockEntityEntry FLUID_PIPE = REGISTRATE - .tileEntity("fluid_pipe", FluidPipeTileEntity::new) - .validBlocks(AllBlocks.FLUID_PIPE) - .register(); - - public static final BlockEntityEntry ENCASED_FLUID_PIPE = REGISTRATE - .tileEntity("encased_fluid_pipe", FluidPipeTileEntity::new) - .validBlocks(AllBlocks.ENCASED_FLUID_PIPE) - .register(); - - public static final BlockEntityEntry GLASS_FLUID_PIPE = REGISTRATE - .tileEntity("glass_fluid_pipe", StraightPipeTileEntity::new) - .validBlocks(AllBlocks.GLASS_FLUID_PIPE) - .renderer(() -> TransparentStraightPipeRenderer::new) - .register(); - - public static final BlockEntityEntry FLUID_VALVE = REGISTRATE - .tileEntity("fluid_valve", FluidValveTileEntity::new) - .instance(() -> FluidValveInstance::new) - .validBlocks(AllBlocks.FLUID_VALVE) - .renderer(() -> FluidValveRenderer::new) - .register(); - - public static final BlockEntityEntry FLUID_TANK = REGISTRATE - .tileEntity("fluid_tank", FluidTankTileEntity::new) - .validBlocks(AllBlocks.FLUID_TANK) - .renderer(() -> FluidTankRenderer::new) - .register(); - - public static final BlockEntityEntry CREATIVE_FLUID_TANK = REGISTRATE - .tileEntity("creative_fluid_tank", CreativeFluidTankTileEntity::new) - .validBlocks(AllBlocks.CREATIVE_FLUID_TANK) - .renderer(() -> FluidTankRenderer::new) - .register(); - - public static final BlockEntityEntry HOSE_PULLEY = REGISTRATE - .tileEntity("hose_pulley", HosePulleyTileEntity::new) - .instance(() -> HosePulleyInstance::new) - .validBlocks(AllBlocks.HOSE_PULLEY) - .renderer(() -> HosePulleyRenderer::new) - .register(); - - public static final BlockEntityEntry SPOUT = REGISTRATE - .tileEntity("spout", SpoutTileEntity::new) - .validBlocks(AllBlocks.SPOUT) - .renderer(() -> SpoutRenderer::new) - .register(); - - public static final BlockEntityEntry ITEM_DRAIN = REGISTRATE - .tileEntity("item_drain", ItemDrainTileEntity::new) - .validBlocks(AllBlocks.ITEM_DRAIN) - .renderer(() -> ItemDrainRenderer::new) - .register(); - - public static final BlockEntityEntry BELT = REGISTRATE - .tileEntity("belt", BeltTileEntity::new) - .instance(() -> BeltInstance::new, BeltTileEntity::shouldRenderNormally) - .validBlocks(AllBlocks.BELT) - .renderer(() -> BeltRenderer::new) - .register(); - - public static final BlockEntityEntry CHUTE = REGISTRATE - .tileEntity("chute", ChuteTileEntity::new) - .validBlocks(AllBlocks.CHUTE) - .renderer(() -> ChuteRenderer::new) - .register(); - - public static final BlockEntityEntry SMART_CHUTE = REGISTRATE - .tileEntity("smart_chute", SmartChuteTileEntity::new) - .validBlocks(AllBlocks.SMART_CHUTE) - .renderer(() -> SmartChuteRenderer::new) - .register(); - - public static final BlockEntityEntry ANDESITE_TUNNEL = REGISTRATE - .tileEntity("andesite_tunnel", BeltTunnelTileEntity::new) - .instance(() -> BeltTunnelInstance::new) - .validBlocks(AllBlocks.ANDESITE_TUNNEL) - .renderer(() -> BeltTunnelRenderer::new) - .register(); - - public static final BlockEntityEntry BRASS_TUNNEL = REGISTRATE - .tileEntity("brass_tunnel", BrassTunnelTileEntity::new) - .instance(() -> BeltTunnelInstance::new) - .validBlocks(AllBlocks.BRASS_TUNNEL) - .renderer(() -> BeltTunnelRenderer::new) - .register(); - - public static final BlockEntityEntry MECHANICAL_ARM = REGISTRATE - .tileEntity("mechanical_arm", ArmTileEntity::new) - .instance(() -> ArmInstance::new) - .validBlocks(AllBlocks.MECHANICAL_ARM) - .renderer(() -> ArmRenderer::new) - .register(); - - public static final BlockEntityEntry ITEM_VAULT = REGISTRATE - .tileEntity("item_vault", ItemVaultTileEntity::new) - .validBlocks(AllBlocks.ITEM_VAULT) - .register(); - - public static final BlockEntityEntry MECHANICAL_PISTON = REGISTRATE - .tileEntity("mechanical_piston", MechanicalPistonTileEntity::new) - .instance(() -> ShaftInstance::new, false) - .validBlocks(AllBlocks.MECHANICAL_PISTON, AllBlocks.STICKY_MECHANICAL_PISTON) - .renderer(() -> MechanicalPistonRenderer::new) - .register(); - - public static final BlockEntityEntry WINDMILL_BEARING = REGISTRATE - .tileEntity("windmill_bearing", WindmillBearingTileEntity::new) - .instance(() -> BearingInstance::new) - .validBlocks(AllBlocks.WINDMILL_BEARING) - .renderer(() -> BearingRenderer::new) - .register(); - - public static final BlockEntityEntry MECHANICAL_BEARING = REGISTRATE - .tileEntity("mechanical_bearing", MechanicalBearingTileEntity::new) - .instance(() -> BearingInstance::new) - .validBlocks(AllBlocks.MECHANICAL_BEARING) - .renderer(() -> BearingRenderer::new) - .register(); - - public static final BlockEntityEntry CLOCKWORK_BEARING = REGISTRATE - .tileEntity("clockwork_bearing", ClockworkBearingTileEntity::new) - .instance(() -> BearingInstance::new) - .validBlocks(AllBlocks.CLOCKWORK_BEARING) - .renderer(() -> BearingRenderer::new) - .register(); - - public static final BlockEntityEntry ROPE_PULLEY = REGISTRATE - .tileEntity("rope_pulley", PulleyTileEntity::new) - .instance(() -> RopePulleyInstance::new, false) - .validBlocks(AllBlocks.ROPE_PULLEY) - .renderer(() -> PulleyRenderer::new) - .register(); - - public static final BlockEntityEntry CHASSIS = REGISTRATE - .tileEntity("chassis", ChassisTileEntity::new) - .validBlocks(AllBlocks.RADIAL_CHASSIS, AllBlocks.LINEAR_CHASSIS, AllBlocks.SECONDARY_LINEAR_CHASSIS) - // .renderer(() -> renderer) - .register(); - - public static final BlockEntityEntry STICKER = REGISTRATE - .tileEntity("sticker", StickerTileEntity::new) - .instance(() -> StickerInstance::new, false) - .validBlocks(AllBlocks.STICKER) - .renderer(() -> StickerRenderer::new) - .register(); - - public static final BlockEntityEntry DRILL = REGISTRATE - .tileEntity("drill", DrillTileEntity::new) - .instance(() -> DrillInstance::new, false) - .validBlocks(AllBlocks.MECHANICAL_DRILL) - .renderer(() -> DrillRenderer::new) - .register(); - - public static final BlockEntityEntry SAW = REGISTRATE - .tileEntity("saw", SawTileEntity::new) - .instance(() -> SawInstance::new) - .validBlocks(AllBlocks.MECHANICAL_SAW) - .renderer(() -> SawRenderer::new) - .register(); - - public static final BlockEntityEntry HARVESTER = REGISTRATE - .tileEntity("harvester", HarvesterTileEntity::new) - .validBlocks(AllBlocks.MECHANICAL_HARVESTER) - .renderer(() -> HarvesterRenderer::new) - .register(); - - public static final BlockEntityEntry PORTABLE_STORAGE_INTERFACE = - REGISTRATE - .tileEntity("portable_storage_interface", PortableItemInterfaceTileEntity::new) - .instance(() -> PSIInstance::new) - .validBlocks(AllBlocks.PORTABLE_STORAGE_INTERFACE) - .renderer(() -> PortableStorageInterfaceRenderer::new) - .register(); - - public static final BlockEntityEntry PORTABLE_FLUID_INTERFACE = - REGISTRATE - .tileEntity("portable_fluid_interface", PortableFluidInterfaceTileEntity::new) - .instance(() -> PSIInstance::new) - .validBlocks(AllBlocks.PORTABLE_FLUID_INTERFACE) - .renderer(() -> PortableStorageInterfaceRenderer::new) - .register(); - - public static final BlockEntityEntry STEAM_ENGINE = REGISTRATE - .tileEntity("steam_engine", SteamEngineTileEntity::new) - .instance(() -> SteamEngineInstance::new, false) - .validBlocks(AllBlocks.STEAM_ENGINE) - .renderer(() -> SteamEngineRenderer::new) - .register(); - - public static final BlockEntityEntry STEAM_WHISTLE = REGISTRATE - .tileEntity("steam_whistle", WhistleTileEntity::new) - .validBlocks(AllBlocks.STEAM_WHISTLE) - .renderer(() -> WhistleRenderer::new) - .register(); - - public static final BlockEntityEntry POWERED_SHAFT = REGISTRATE - .tileEntity("powered_shaft", PoweredShaftTileEntity::new) - .instance(() -> SingleRotatingInstance::new, false) - .validBlocks(AllBlocks.POWERED_SHAFT) - .renderer(() -> KineticTileEntityRenderer::new) - .register(); - - public static final BlockEntityEntry FLYWHEEL = REGISTRATE - .tileEntity("flywheel", FlywheelTileEntity::new) - .instance(() -> FlyWheelInstance::new, false) - .validBlocks(AllBlocks.FLYWHEEL) - .renderer(() -> FlywheelRenderer::new) - .register(); - - public static final BlockEntityEntry MILLSTONE = REGISTRATE - .tileEntity("millstone", MillstoneTileEntity::new) - .instance(() -> MillStoneCogInstance::new, false) - .validBlocks(AllBlocks.MILLSTONE) - .renderer(() -> MillstoneRenderer::new) - .register(); - - public static final BlockEntityEntry CRUSHING_WHEEL = REGISTRATE - .tileEntity("crushing_wheel", CrushingWheelTileEntity::new) - .instance(() -> CutoutRotatingInstance::new, false) - .validBlocks(AllBlocks.CRUSHING_WHEEL) - .renderer(() -> KineticTileEntityRenderer::new) - .register(); - - public static final BlockEntityEntry CRUSHING_WHEEL_CONTROLLER = - REGISTRATE - .tileEntity("crushing_wheel_controller", CrushingWheelControllerTileEntity::new) - .validBlocks(AllBlocks.CRUSHING_WHEEL_CONTROLLER) - // .renderer(() -> renderer) - .register(); - - public static final BlockEntityEntry WATER_WHEEL = REGISTRATE - .tileEntity("water_wheel", WaterWheelTileEntity::new) - .instance(() -> CutoutRotatingInstance::new, false) - .validBlocks(AllBlocks.WATER_WHEEL) - .renderer(() -> KineticTileEntityRenderer::new) - .register(); - - public static final BlockEntityEntry MECHANICAL_PRESS = REGISTRATE - .tileEntity("mechanical_press", MechanicalPressTileEntity::new) - .instance(() -> PressInstance::new) - .validBlocks(AllBlocks.MECHANICAL_PRESS) - .renderer(() -> MechanicalPressRenderer::new) - .register(); - - public static final BlockEntityEntry MECHANICAL_MIXER = REGISTRATE - .tileEntity("mechanical_mixer", MechanicalMixerTileEntity::new) - .instance(() -> MixerInstance::new) - .validBlocks(AllBlocks.MECHANICAL_MIXER) - .renderer(() -> MechanicalMixerRenderer::new) - .register(); - - public static final BlockEntityEntry DEPLOYER = REGISTRATE - .tileEntity("deployer", DeployerTileEntity::new) - .instance(() -> DeployerInstance::new) - .validBlocks(AllBlocks.DEPLOYER) - .renderer(() -> DeployerRenderer::new) - .register(); - - public static final BlockEntityEntry BASIN = REGISTRATE - .tileEntity("basin", BasinTileEntity::new) - .validBlocks(AllBlocks.BASIN) - .renderer(() -> BasinRenderer::new) - .register(); - - public static final BlockEntityEntry HEATER = REGISTRATE - .tileEntity("blaze_heater", BlazeBurnerTileEntity::new) - .validBlocks(AllBlocks.BLAZE_BURNER) - .renderer(() -> BlazeBurnerRenderer::new) - .register(); - - public static final BlockEntityEntry MECHANICAL_CRAFTER = REGISTRATE - .tileEntity("mechanical_crafter", MechanicalCrafterTileEntity::new) - .instance(() -> MechanicalCrafterInstance::new) - .validBlocks(AllBlocks.MECHANICAL_CRAFTER) - .renderer(() -> MechanicalCrafterRenderer::new) - .register(); - - public static final BlockEntityEntry SEQUENCED_GEARSHIFT = REGISTRATE - .tileEntity("sequenced_gearshift", SequencedGearshiftTileEntity::new) - .instance(() -> SplitShaftInstance::new, false) - .validBlocks(AllBlocks.SEQUENCED_GEARSHIFT) - .renderer(() -> SplitShaftRenderer::new) - .register(); - - public static final BlockEntityEntry ROTATION_SPEED_CONTROLLER = REGISTRATE - .tileEntity("rotation_speed_controller", SpeedControllerTileEntity::new) - .instance(() -> ShaftInstance::new) - .validBlocks(AllBlocks.ROTATION_SPEED_CONTROLLER) - .renderer(() -> SpeedControllerRenderer::new) - .register(); - - public static final BlockEntityEntry SPEEDOMETER = REGISTRATE - .tileEntity("speedometer", SpeedGaugeTileEntity::new) - .instance(() -> GaugeInstance.Speed::new) - .validBlocks(AllBlocks.SPEEDOMETER) - .renderer(() -> GaugeRenderer::speed) - .register(); - - public static final BlockEntityEntry STRESSOMETER = REGISTRATE - .tileEntity("stressometer", StressGaugeTileEntity::new) - .instance(() -> GaugeInstance.Stress::new) - .validBlocks(AllBlocks.STRESSOMETER) - .renderer(() -> GaugeRenderer::stress) - .register(); - - public static final BlockEntityEntry ANALOG_LEVER = REGISTRATE - .tileEntity("analog_lever", AnalogLeverTileEntity::new) - .instance(() -> AnalogLeverInstance::new, false) - .validBlocks(AllBlocks.ANALOG_LEVER) - .renderer(() -> AnalogLeverRenderer::new) - .register(); - - public static final BlockEntityEntry PLACARD = REGISTRATE - .tileEntity("placard", PlacardTileEntity::new) - .validBlocks(AllBlocks.PLACARD) - .renderer(() -> PlacardRenderer::new) - .register(); - - public static final BlockEntityEntry CART_ASSEMBLER = REGISTRATE - .tileEntity("cart_assembler", CartAssemblerTileEntity::new) - .validBlocks(AllBlocks.CART_ASSEMBLER) - // .renderer(() -> renderer) - .register(); - - // Logistics - public static final BlockEntityEntry REDSTONE_LINK = REGISTRATE - .tileEntity("redstone_link", RedstoneLinkTileEntity::new) - .validBlocks(AllBlocks.REDSTONE_LINK) - .renderer(() -> SmartTileEntityRenderer::new) - .register(); - - public static final BlockEntityEntry NIXIE_TUBE = REGISTRATE - .tileEntity("nixie_tube", NixieTubeTileEntity::new) - .validBlocks(AllBlocks.ORANGE_NIXIE_TUBE) - .validBlocks(AllBlocks.NIXIE_TUBES.toArray()) - .renderer(() -> NixieTubeRenderer::new) - .onRegister(assignDataBehaviourTE(new NixieTubeDisplayTarget())) - .onRegister(assignDataBehaviourTE(new NixieTubeDisplaySource())) - .register(); - - public static final BlockEntityEntry DISPLAY_LINK = REGISTRATE - .tileEntity("display_link", DisplayLinkTileEntity::new) - .validBlocks(AllBlocks.DISPLAY_LINK) - .renderer(() -> DisplayLinkRenderer::new) - .register(); - - public static final BlockEntityEntry STOCKPILE_SWITCH = REGISTRATE - .tileEntity("stockpile_switch", StockpileSwitchTileEntity::new) - .validBlocks(AllBlocks.STOCKPILE_SWITCH) - .renderer(() -> SmartTileEntityRenderer::new) - .register(); - - public static final BlockEntityEntry CREATIVE_CRATE = REGISTRATE - .tileEntity("creative_crate", CreativeCrateTileEntity::new) - .validBlocks(AllBlocks.CREATIVE_CRATE) - .renderer(() -> SmartTileEntityRenderer::new) - .register(); - - public static final BlockEntityEntry DEPOT = REGISTRATE - .tileEntity("depot", DepotTileEntity::new) - .validBlocks(AllBlocks.DEPOT) - .renderer(() -> DepotRenderer::new) - .register(); - - public static final BlockEntityEntry WEIGHTED_EJECTOR = REGISTRATE - .tileEntity("weighted_ejector", EjectorTileEntity::new) - .instance(() -> EjectorInstance::new) - .validBlocks(AllBlocks.WEIGHTED_EJECTOR) - .renderer(() -> EjectorRenderer::new) - .register(); - - public static final BlockEntityEntry FUNNEL = REGISTRATE - .tileEntity("funnel", FunnelTileEntity::new) - .instance(() -> FunnelInstance::new) - .validBlocks(AllBlocks.BRASS_FUNNEL, AllBlocks.BRASS_BELT_FUNNEL, AllBlocks.ANDESITE_FUNNEL, - AllBlocks.ANDESITE_BELT_FUNNEL) - .renderer(() -> FunnelRenderer::new) - .register(); - - public static final BlockEntityEntry CONTENT_OBSERVER = REGISTRATE - .tileEntity("content_observer", ContentObserverTileEntity::new) - .validBlocks(AllBlocks.CONTENT_OBSERVER) - .renderer(() -> SmartTileEntityRenderer::new) - .register(); - - public static final BlockEntityEntry PULSE_EXTENDER = REGISTRATE - .tileEntity("pulse_extender", PulseExtenderTileEntity::new) - .instance(() -> BrassDiodeInstance::new, false) - .validBlocks(AllBlocks.PULSE_EXTENDER) - .renderer(() -> BrassDiodeRenderer::new) - .register(); - - public static final BlockEntityEntry PULSE_REPEATER = REGISTRATE - .tileEntity("pulse_repeater", PulseRepeaterTileEntity::new) - .instance(() -> BrassDiodeInstance::new, false) - .validBlocks(AllBlocks.PULSE_REPEATER) - .renderer(() -> BrassDiodeRenderer::new) - .register(); - - public static final BlockEntityEntry LECTERN_CONTROLLER = REGISTRATE - .tileEntity("lectern_controller", LecternControllerTileEntity::new) - .validBlocks(AllBlocks.LECTERN_CONTROLLER) - .renderer(() -> LecternControllerRenderer::new) - .register(); - - // Curiosities - public static final BlockEntityEntry COPPER_BACKTANK = REGISTRATE - .tileEntity("copper_backtank", CopperBacktankTileEntity::new) - .instance(() -> CopperBacktankInstance::new) - .validBlocks(AllBlocks.COPPER_BACKTANK) - .renderer(() -> CopperBacktankRenderer::new) - .register(); - - public static final BlockEntityEntry PECULIAR_BELL = REGISTRATE - .tileEntity("peculiar_bell", PeculiarBellTileEntity::new) - .validBlocks(AllBlocks.PECULIAR_BELL) - .renderer(() -> BellRenderer::new) - .register(); - - public static final BlockEntityEntry HAUNTED_BELL = REGISTRATE - .tileEntity("cursed_bell", HauntedBellTileEntity::new) - .validBlocks(AllBlocks.HAUNTED_BELL) - .renderer(() -> BellRenderer::new) - .register(); - - public static final BlockEntityEntry TOOLBOX = REGISTRATE - .tileEntity("toolbox", ToolboxTileEntity::new) - .instance(() -> ToolBoxInstance::new, false) - .validBlocks(AllBlocks.TOOLBOXES.toArray()) - .renderer(() -> ToolboxRenderer::new) - .register(); - - public static final BlockEntityEntry TRACK = REGISTRATE - .tileEntity("track", TrackTileEntity::new) - .instance(() -> TrackInstance::new) - .renderer(() -> TrackRenderer::new) - .validBlocks(AllBlocks.TRACK) - .register(); - - public static final BlockEntityEntry FAKE_TRACK = REGISTRATE - .tileEntity("fake_track", FakeTrackTileEntity::new) - .validBlocks(AllBlocks.FAKE_TRACK) - .register(); - - public static final BlockEntityEntry BOGEY = REGISTRATE - .tileEntity("bogey", StandardBogeyTileEntity::new) - .renderer(() -> BogeyTileEntityRenderer::new) - .validBlocks(AllBlocks.SMALL_BOGEY, AllBlocks.LARGE_BOGEY) - .register(); - - public static final BlockEntityEntry TRACK_STATION = REGISTRATE - .tileEntity("track_station", StationTileEntity::new) - .renderer(() -> StationRenderer::new) - .validBlocks(AllBlocks.TRACK_STATION) - .register(); - - public static final BlockEntityEntry SLIDING_DOOR = REGISTRATE - .tileEntity("sliding_door", SlidingDoorTileEntity::new) - .renderer(() -> SlidingDoorRenderer::new) - .validBlocks(AllBlocks.TRAIN_DOOR, AllBlocks.FRAMED_GLASS_DOOR) - .register(); - - public static final BlockEntityEntry FLAP_DISPLAY = REGISTRATE - .tileEntity("flap_display", FlapDisplayTileEntity::new) - .instance(() -> MechanicalCrafterInstance::new) - .renderer(() -> FlapDisplayRenderer::new) - .validBlocks(AllBlocks.DISPLAY_BOARD) - .register(); - - public static final BlockEntityEntry TRACK_SIGNAL = REGISTRATE - .tileEntity("track_signal", SignalTileEntity::new) - .renderer(() -> SignalRenderer::new) - .validBlocks(AllBlocks.TRACK_SIGNAL) - .register(); - - public static final BlockEntityEntry TRACK_OBSERVER = REGISTRATE - .tileEntity("track_observer", TrackObserverTileEntity::new) - .renderer(() -> TrackObserverRenderer::new) - .validBlocks(AllBlocks.TRACK_OBSERVER) - .register(); - - public static void register() {} -} diff --git a/src/main/java/com/simibubi/create/Create.java b/src/main/java/com/simibubi/create/Create.java index de8ca498f..cf2f5741c 100644 --- a/src/main/java/com/simibubi/create/Create.java +++ b/src/main/java/com/simibubi/create/Create.java @@ -9,23 +9,23 @@ import com.google.gson.GsonBuilder; import com.mojang.logging.LogUtils; import com.simibubi.create.api.behaviour.BlockSpoutingBehaviour; import com.simibubi.create.compat.Mods; +import com.simibubi.create.compat.computercraft.ComputerCraftProxy; import com.simibubi.create.compat.curios.Curios; -import com.simibubi.create.content.contraptions.TorquePropagator; -import com.simibubi.create.content.contraptions.fluids.tank.BoilerHeaters; -import com.simibubi.create.content.curiosities.weapons.BuiltinPotatoProjectileTypes; -import com.simibubi.create.content.logistics.RedstoneLinkNetworkHandler; -import com.simibubi.create.content.logistics.block.display.AllDisplayBehaviours; -import com.simibubi.create.content.logistics.block.mechanicalArm.AllArmInteractionPointTypes; -import com.simibubi.create.content.logistics.trains.GlobalRailwayManager; -import com.simibubi.create.content.palettes.AllPaletteBlocks; +import com.simibubi.create.content.contraptions.ContraptionMovementSetting; +import com.simibubi.create.content.decoration.palettes.AllPaletteBlocks; +import com.simibubi.create.content.equipment.potatoCannon.BuiltinPotatoProjectileTypes; +import com.simibubi.create.content.fluids.tank.BoilerHeaters; +import com.simibubi.create.content.kinetics.TorquePropagator; +import com.simibubi.create.content.kinetics.mechanicalArm.AllArmInteractionPointTypes; +import com.simibubi.create.content.redstone.displayLink.AllDisplayBehaviours; +import com.simibubi.create.content.redstone.link.RedstoneLinkNetworkHandler; +import com.simibubi.create.content.schematics.SchematicInstances; import com.simibubi.create.content.schematics.ServerSchematicLoader; -import com.simibubi.create.content.schematics.filtering.SchematicInstances; +import com.simibubi.create.content.trains.GlobalRailwayManager; +import com.simibubi.create.content.trains.bogey.BogeySizes; import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.advancement.AllTriggers; import com.simibubi.create.foundation.block.CopperRegistries; -import com.simibubi.create.foundation.command.ServerLagger; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.config.ContraptionMovementSetting; import com.simibubi.create.foundation.data.AllLangPartials; import com.simibubi.create.foundation.data.CreateRegistrate; import com.simibubi.create.foundation.data.LangMerger; @@ -34,11 +34,16 @@ import com.simibubi.create.foundation.data.recipe.MechanicalCraftingRecipeGen; import com.simibubi.create.foundation.data.recipe.ProcessingRecipeGen; import com.simibubi.create.foundation.data.recipe.SequencedAssemblyRecipeGen; import com.simibubi.create.foundation.data.recipe.StandardRecipeGen; -import com.simibubi.create.foundation.networking.AllPackets; -import com.simibubi.create.foundation.utility.CreateRegistry; -import com.simibubi.create.foundation.worldgen.AllFeatures; -import com.simibubi.create.foundation.worldgen.AllPlacementModifiers; -import com.simibubi.create.foundation.worldgen.WorldgenDataProvider; +import com.simibubi.create.foundation.item.ItemDescription; +import com.simibubi.create.foundation.item.KineticStats; +import com.simibubi.create.foundation.item.TooltipHelper.Palette; +import com.simibubi.create.foundation.item.TooltipModifier; +import com.simibubi.create.foundation.utility.AttachedRegistry; +import com.simibubi.create.infrastructure.command.ServerLagger; +import com.simibubi.create.infrastructure.config.AllConfigs; +import com.simibubi.create.infrastructure.worldgen.AllFeatures; +import com.simibubi.create.infrastructure.worldgen.AllPlacementModifiers; +import com.simibubi.create.infrastructure.worldgen.WorldgenDataProvider; import com.tterrag.registrate.providers.ProviderType; import com.tterrag.registrate.util.nullness.NonNullConsumer; @@ -64,7 +69,7 @@ public class Create { public static final String ID = "create"; public static final String NAME = "Create"; - public static final String VERSION = "0.5j"; + public static final String VERSION = "0.5.1b"; public static final Logger LOGGER = LogUtils.getLogger(); @@ -78,6 +83,13 @@ public class Create { public static final CreateRegistrate REGISTRATE = CreateRegistrate.create(ID); + static { + REGISTRATE.setTooltipModifierFactory(item -> { + return new ItemDescription.Modifier(item, Palette.STANDARD_CREATE) + .andThen(TooltipModifier.mapNull(KineticStats.create(item))); + }); + } + public static final ServerSchematicLoader SCHEMATIC_RECEIVER = new ServerSchematicLoader(); public static final RedstoneLinkNetworkHandler REDSTONE_LINK_NETWORK_HANDLER = new RedstoneLinkNetworkHandler(); public static final TorquePropagator TORQUE_PROPAGATOR = new TorquePropagator(); @@ -103,9 +115,9 @@ public class Create { AllItems.register(); AllFluids.register(); AllPaletteBlocks.register(); - AllContainerTypes.register(); + AllMenuTypes.register(); AllEntityTypes.register(); - AllTileEntities.register(); + AllBlockEntityTypes.register(); AllEnchantments.register(); AllRecipeTypes.register(modEventBus); AllParticleTypes.register(modEventBus); @@ -113,6 +125,8 @@ public class Create { AllEntityDataSerializers.register(modEventBus); AllFeatures.register(modEventBus); AllPlacementModifiers.register(modEventBus); + BogeySizes.init(); + AllBogeyStyles.register(); AllConfigs.register(modLoadingContext); @@ -122,6 +136,7 @@ public class Create { ContraptionMovementSetting.registerDefaults(); AllArmInteractionPointTypes.register(); BlockSpoutingBehaviour.registerDefaults(); + ComputerCraftProxy.register(); ForgeMod.enableMilkFluid(); CopperRegistries.inject(); @@ -136,12 +151,12 @@ public class Create { } public static void init(final FMLCommonSetupEvent event) { - CreateRegistry.unwrapAll(); AllPackets.registerPackets(); SchematicInstances.register(); BuiltinPotatoProjectileTypes.register(); event.enqueueWork(() -> { + AttachedRegistry.unwrapAll(); AllAdvancements.register(); AllTriggers.register(); BoilerHeaters.registerDefaults(); @@ -151,7 +166,7 @@ public class Create { public static final ProviderType LANG_MERGER = ProviderType.register("lang_merger", (p, e) -> new LangMerger(e.getGenerator() - .getPackOutput(), Create.ID, "Create", AllLangPartials.values())); + .getPackOutput(), ID, NAME, AllLangPartials.values())); public static void gatherData(GatherDataEvent event) { TagGen.datagen(); diff --git a/src/main/java/com/simibubi/create/CreateClient.java b/src/main/java/com/simibubi/create/CreateClient.java index 621512bd6..0b2fe21be 100644 --- a/src/main/java/com/simibubi/create/CreateClient.java +++ b/src/main/java/com/simibubi/create/CreateClient.java @@ -1,21 +1,22 @@ package com.simibubi.create; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueSelectionHandler; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; -import com.simibubi.create.content.contraptions.components.structureMovement.render.SBBContraptionManager; -import com.simibubi.create.content.contraptions.relays.encased.CasingConnectivity; -import com.simibubi.create.content.curiosities.bell.SoulPulseEffectHandler; -import com.simibubi.create.content.curiosities.weapons.PotatoCannonRenderHandler; -import com.simibubi.create.content.curiosities.zapper.ZapperRenderHandler; -import com.simibubi.create.content.logistics.trains.GlobalRailwayManager; -import com.simibubi.create.content.schematics.ClientSchematicLoader; +import com.simibubi.create.content.contraptions.glue.SuperGlueSelectionHandler; +import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher; +import com.simibubi.create.content.contraptions.render.SBBContraptionManager; +import com.simibubi.create.content.decoration.encasing.CasingConnectivity; +import com.simibubi.create.content.equipment.bell.SoulPulseEffectHandler; +import com.simibubi.create.content.equipment.potatoCannon.PotatoCannonRenderHandler; +import com.simibubi.create.content.equipment.zapper.ZapperRenderHandler; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.content.kinetics.waterwheel.WaterWheelRenderer; +import com.simibubi.create.content.schematics.client.ClientSchematicLoader; import com.simibubi.create.content.schematics.client.SchematicAndQuillHandler; import com.simibubi.create.content.schematics.client.SchematicHandler; +import com.simibubi.create.content.trains.GlobalRailwayManager; import com.simibubi.create.foundation.ClientResourceReloadListener; -import com.simibubi.create.foundation.config.AllConfigs; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsClient; import com.simibubi.create.foundation.gui.UIRenderHelper; -import com.simibubi.create.foundation.ponder.content.PonderIndex; +import com.simibubi.create.foundation.outliner.Outliner; import com.simibubi.create.foundation.ponder.element.WorldSectionElement; import com.simibubi.create.foundation.render.CachedBufferer; import com.simibubi.create.foundation.render.CreateContexts; @@ -23,7 +24,9 @@ import com.simibubi.create.foundation.render.SuperByteBufferCache; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.ModelSwapper; import com.simibubi.create.foundation.utility.ghost.GhostBlocks; -import com.simibubi.create.foundation.utility.outliner.Outliner; +import com.simibubi.create.infrastructure.config.AllConfigs; +import com.simibubi.create.infrastructure.ponder.AllPonderTags; +import com.simibubi.create.infrastructure.ponder.PonderIndex; import net.minecraft.ChatFormatting; import net.minecraft.client.GraphicsStatus; @@ -52,6 +55,7 @@ public class CreateClient { public static final PotatoCannonRenderHandler POTATO_CANNON_RENDER_HANDLER = new PotatoCannonRenderHandler(); public static final SoulPulseEffectHandler SOUL_PULSE_EFFECT_HANDLER = new SoulPulseEffectHandler(); public static final GlobalRailwayManager RAILWAYS = new GlobalRailwayManager(); + public static final ValueSettingsClient VALUE_SETTINGS_HANDLER = new ValueSettingsClient(); public static final ClientResourceReloadListener RESOURCE_RELOAD_LISTENER = new ClientResourceReloadListener(); @@ -68,17 +72,18 @@ public class CreateClient { } public static void clientInit(final FMLClientSetupEvent event) { - BUFFER_CACHE.registerCompartment(CachedBufferer.GENERIC_TILE); + BUFFER_CACHE.registerCompartment(CachedBufferer.GENERIC_BLOCK); BUFFER_CACHE.registerCompartment(CachedBufferer.PARTIAL); BUFFER_CACHE.registerCompartment(CachedBufferer.DIRECTIONAL_PARTIAL); - BUFFER_CACHE.registerCompartment(KineticTileEntityRenderer.KINETIC_TILE); + BUFFER_CACHE.registerCompartment(KineticBlockEntityRenderer.KINETIC_BLOCK); + BUFFER_CACHE.registerCompartment(WaterWheelRenderer.WATER_WHEEL); BUFFER_CACHE.registerCompartment(SBBContraptionManager.CONTRAPTION, 20); BUFFER_CACHE.registerCompartment(WorldSectionElement.DOC_WORLD_SECTION, 20); - AllBlockPartials.init(); + AllPartialModels.init(); + AllPonderTags.register(); PonderIndex.register(); - PonderIndex.registerTags(); UIRenderHelper.init(); } @@ -98,7 +103,7 @@ public class CreateClient { if (mc.options.graphicsMode().get() != GraphicsStatus.FABULOUS) return; - if (AllConfigs.CLIENT.ignoreFabulousWarning.get()) + if (AllConfigs.client().ignoreFabulousWarning.get()) return; MutableComponent text = ComponentUtils.wrapInSquareBrackets(Components.literal("WARN")) diff --git a/src/main/java/com/simibubi/create/api/behaviour/BlockSpoutingBehaviour.java b/src/main/java/com/simibubi/create/api/behaviour/BlockSpoutingBehaviour.java index 8915492b8..9bdcf69d4 100644 --- a/src/main/java/com/simibubi/create/api/behaviour/BlockSpoutingBehaviour.java +++ b/src/main/java/com/simibubi/create/api/behaviour/BlockSpoutingBehaviour.java @@ -6,7 +6,7 @@ import java.util.function.Consumer; import com.simibubi.create.Create; import com.simibubi.create.compat.tconstruct.SpoutCasting; -import com.simibubi.create.content.contraptions.fluids.actors.SpoutTileEntity; +import com.simibubi.create.content.fluids.spout.SpoutBlockEntity; import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceLocation; @@ -43,7 +43,7 @@ public abstract class BlockSpoutingBehaviour { * @param simulate whether the spout is testing or actually performing this behaviour * @return amount filled into the block, 0 to idle/cancel */ - public abstract int fillBlock(Level world, BlockPos pos, SpoutTileEntity spout, FluidStack availableFluid, + public abstract int fillBlock(Level world, BlockPos pos, SpoutBlockEntity spout, FluidStack availableFluid, boolean simulate); public static void registerDefaults() { diff --git a/src/main/java/com/simibubi/create/api/connectivity/ConnectivityHandler.java b/src/main/java/com/simibubi/create/api/connectivity/ConnectivityHandler.java index a840bb8d8..f367df848 100644 --- a/src/main/java/com/simibubi/create/api/connectivity/ConnectivityHandler.java +++ b/src/main/java/com/simibubi/create/api/connectivity/ConnectivityHandler.java @@ -13,8 +13,8 @@ import javax.annotation.Nullable; import org.apache.commons.lang3.tuple.Pair; -import com.simibubi.create.content.contraptions.fluids.tank.CreativeFluidTankTileEntity; -import com.simibubi.create.foundation.tileEntity.IMultiTileContainer; +import com.simibubi.create.content.fluids.tank.CreativeFluidTankBlockEntity; +import com.simibubi.create.foundation.blockEntity.IMultiBlockEntityContainer; import com.simibubi.create.foundation.utility.Iterate; import net.minecraft.core.BlockPos; @@ -31,14 +31,14 @@ import net.minecraftforge.items.CapabilityItemHandler; public class ConnectivityHandler { - public static void formMulti(T be) { + public static void formMulti(T be) { SearchCache cache = new SearchCache<>(); List frontier = new ArrayList<>(); frontier.add(be); formMulti(be.getType(), be.getLevel(), cache, frontier); } - private static void formMulti(BlockEntityType type, + private static void formMulti(BlockEntityType type, BlockGetter level, SearchCache cache, List frontier) { PriorityQueue> creationQueue = makeCreationQueue(); Set visited = new HashSet<>(); @@ -110,7 +110,7 @@ public class ConnectivityHandler { } } - private static int tryToFormNewMulti(T be, SearchCache cache, + private static int tryToFormNewMulti(T be, SearchCache cache, boolean simulate) { int bestWidth = 1; int bestAmount = -1; @@ -132,7 +132,7 @@ public class ConnectivityHandler { return bestAmount; splitMultiAndInvalidate(be, cache, false); - if (be instanceof IMultiTileContainer.Fluid ifluid && ifluid.hasTank()) + if (be instanceof IMultiBlockEntityContainer.Fluid ifluid && ifluid.hasTank()) ifluid.setTankSize(0, bestAmount); tryToFormNewMultiOfWidth(be, bestWidth, cache, false); @@ -145,7 +145,7 @@ public class ConnectivityHandler { return bestAmount; } - private static int tryToFormNewMultiOfWidth(T be, int width, + private static int tryToFormNewMultiOfWidth(T be, int width, SearchCache cache, boolean simulate) { int amount = 0; int height = 0; @@ -158,7 +158,7 @@ public class ConnectivityHandler { // optional fluid handling IFluidTank beTank = null; FluidStack fluid = FluidStack.EMPTY; - if (be instanceof IMultiTileContainer.Fluid ifluid && ifluid.hasTank()) { + if (be instanceof IMultiBlockEntityContainer.Fluid ifluid && ifluid.hasTank()) { beTank = ifluid.getTank(0); fluid = beTank.getFluid(); } @@ -213,7 +213,7 @@ public class ConnectivityHandler { break Search; } } - if (controller instanceof IMultiTileContainer.Fluid ifluidCon && ifluidCon.hasTank()) { + if (controller instanceof IMultiBlockEntityContainer.Fluid ifluidCon && ifluidCon.hasTank()) { FluidStack otherFluid = ifluidCon.getFluid(0); if (!fluid.isEmpty() && !otherFluid.isEmpty() && !fluid.isFluidEqual(otherFluid)) break Search; @@ -245,17 +245,17 @@ public class ConnectivityHandler { extraData = be.modifyExtraData(extraData); - if (part instanceof IMultiTileContainer.Fluid ifluidPart && ifluidPart.hasTank()) { + if (part instanceof IMultiBlockEntityContainer.Fluid ifluidPart && ifluidPart.hasTank()) { IFluidTank tankAt = ifluidPart.getTank(0); FluidStack fluidAt = tankAt.getFluid(); if (!fluidAt.isEmpty()) { // making this generic would be a rather large mess, unfortunately if (beTank != null && fluid.isEmpty() - && beTank instanceof CreativeFluidTankTileEntity.CreativeSmartFluidTank) { - ((CreativeFluidTankTileEntity.CreativeSmartFluidTank) beTank) + && beTank instanceof CreativeFluidTankBlockEntity.CreativeSmartFluidTank) { + ((CreativeFluidTankBlockEntity.CreativeSmartFluidTank) beTank) .setContainedFluid(fluidAt); } - if (be instanceof IMultiTileContainer.Fluid ifluidBE && ifluidBE.hasTank() + if (be instanceof IMultiBlockEntityContainer.Fluid ifluidBE && ifluidBE.hasTank() && beTank != null) { beTank.fill(fluidAt, IFluidHandler.FluidAction.EXECUTE); } @@ -278,18 +278,18 @@ public class ConnectivityHandler { return amount; } - public static void splitMulti(T be) { + public static void splitMulti(T be) { splitMultiAndInvalidate(be, null, false); } // tryReconnect helps whenever only a few tanks have been removed - private static void splitMultiAndInvalidate(T be, + private static void splitMultiAndInvalidate(T be, @Nullable SearchCache cache, boolean tryReconnect) { Level level = be.getLevel(); if (level == null) return; - be = be.getControllerTE(); + be = be.getControllerBE(); if (be == null) return; @@ -305,7 +305,7 @@ public class ConnectivityHandler { // fluid handling, if present FluidStack toDistribute = FluidStack.EMPTY; int maxCapacity = 0; - if (be instanceof IMultiTileContainer.Fluid ifluidBE && ifluidBE.hasTank()) { + if (be instanceof IMultiBlockEntityContainer.Fluid ifluidBE && ifluidBE.hasTank()) { toDistribute = ifluidBE.getFluid(0); maxCapacity = ifluidBE.getTankSize(0); if (!toDistribute.isEmpty() && !be.isRemoved()) @@ -330,16 +330,16 @@ public class ConnectivityHandler { .equals(origin)) continue; - T controllerBE = partAt.getControllerTE(); + T controllerBE = partAt.getControllerBE(); partAt.setExtraData((controllerBE == null ? null : controllerBE.getExtraData())); partAt.removeController(true); if (!toDistribute.isEmpty() && partAt != be) { FluidStack copy = toDistribute.copy(); IFluidTank tank = - (partAt instanceof IMultiTileContainer.Fluid ifluidPart ? ifluidPart.getTank(0) : null); + (partAt instanceof IMultiBlockEntityContainer.Fluid ifluidPart ? ifluidPart.getTank(0) : null); // making this generic would be a rather large mess, unfortunately - if (tank instanceof CreativeFluidTankTileEntity.CreativeSmartFluidTank creativeTank) { + if (tank instanceof CreativeFluidTankBlockEntity.CreativeSmartFluidTank creativeTank) { if (creativeTank.isEmpty()) creativeTank.setContainedFluid(toDistribute); } else { @@ -360,10 +360,10 @@ public class ConnectivityHandler { } } - if (be instanceof IMultiTileContainer.Inventory iinv && iinv.hasInventory()) + if (be instanceof IMultiBlockEntityContainer.Inventory inv && inv.hasInventory()) be.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) .invalidate(); - if (be instanceof IMultiTileContainer.Fluid ifluid && ifluid.hasTank()) + if (be instanceof IMultiBlockEntityContainer.Fluid fluid && fluid.hasTank()) be.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) .invalidate(); @@ -371,12 +371,12 @@ public class ConnectivityHandler { formMulti(be.getType(), level, cache == null ? new SearchCache<>() : cache, frontier); } - private static PriorityQueue> makeCreationQueue() { + private static PriorityQueue> makeCreationQueue() { return new PriorityQueue<>((one, two) -> two.getKey() - one.getKey()); } @Nullable - public static T partAt(BlockEntityType type, BlockGetter level, + public static T partAt(BlockEntityType type, BlockGetter level, BlockPos pos) { BlockEntity be = level.getBlockEntity(pos); if (be != null && be.getType() == type && !be.isRemoved()) @@ -384,7 +384,7 @@ public class ConnectivityHandler { return null; } - public static boolean isConnected(BlockGetter level, BlockPos pos, + public static boolean isConnected(BlockGetter level, BlockPos pos, BlockPos other) { T one = checked(level.getBlockEntity(pos)); T two = checked(level.getBlockEntity(other)); @@ -396,13 +396,13 @@ public class ConnectivityHandler { @Nullable @SuppressWarnings("unchecked") - private static T checked(BlockEntity be) { - if (be instanceof IMultiTileContainer) + private static T checked(BlockEntity be) { + if (be instanceof IMultiBlockEntityContainer) return (T) be; return null; } - private static class SearchCache { + private static class SearchCache { Map> controllerMap; public SearchCache() { diff --git a/src/main/java/com/simibubi/create/api/event/BlockEntityBehaviourEvent.java b/src/main/java/com/simibubi/create/api/event/BlockEntityBehaviourEvent.java new file mode 100644 index 000000000..398783d74 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/event/BlockEntityBehaviourEvent.java @@ -0,0 +1,58 @@ +package com.simibubi.create.api.event; + +import java.lang.reflect.Type; +import java.util.Map; + +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; + +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.eventbus.api.GenericEvent; + +/** + * Event that is fired just before a SmartBlockEntity is being deserialized
+ * Also if a new one is placed
+ * Use it to attach a new {@link BlockEntityBehaviour} or replace existing ones + * (with caution)
+ *
+ * Actual setup of the behaviours internal workings and data should be done in + * BlockEntityBehaviour#read() and BlockEntityBehaviour#initialize() + * respectively.
+ *
+ * Because of the earliness of this event, the added behaviours will have access + * to the initial NBT read (unless the BE was placed, not loaded), thereby + * allowing block entities to store and retrieve data for injected behaviours. + */ +public class BlockEntityBehaviourEvent extends GenericEvent { + + private T smartBlockEntity; + private Map, BlockEntityBehaviour> behaviours; + + public BlockEntityBehaviourEvent(T blockEntity, Map, BlockEntityBehaviour> behaviours) { + smartBlockEntity = blockEntity; + this.behaviours = behaviours; + } + + @Override + public Type getGenericType() { + return smartBlockEntity.getClass(); + } + + public void attach(BlockEntityBehaviour behaviour) { + behaviours.put(behaviour.getType(), behaviour); + } + + public BlockEntityBehaviour remove(BehaviourType type) { + return behaviours.remove(type); + } + + public T getBlockEntity() { + return smartBlockEntity; + } + + public BlockState getBlockState() { + return smartBlockEntity.getBlockState(); + } + +} diff --git a/src/main/java/com/simibubi/create/api/event/TileEntityBehaviourEvent.java b/src/main/java/com/simibubi/create/api/event/TileEntityBehaviourEvent.java deleted file mode 100644 index 657d21065..000000000 --- a/src/main/java/com/simibubi/create/api/event/TileEntityBehaviourEvent.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.simibubi.create.api.event; - -import java.lang.reflect.Type; -import java.util.Map; - -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType; - -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.eventbus.api.GenericEvent; - -/** - * Event that is fired just before a SmartTileEntity is being deserialized
- * Also if a new one is placed
- * Use it to attach a new {@link TileEntityBehaviour} or replace existing ones - * (with caution)
- *
- * Actual setup of the behaviours internal workings and data should be done in - * TileEntityBehaviour#read() and TileEntityBehaviour#initialize() - * respectively.
- *
- * Because of the earliness of this event, the added behaviours will have access - * to the initial NBT read (unless the TE was placed, not loaded), thereby - * allowing tiles to store and retrieve data for injected behaviours. - */ -public class TileEntityBehaviourEvent extends GenericEvent { - - private T smartTileEntity; - private Map, TileEntityBehaviour> behaviours; - - public TileEntityBehaviourEvent(T tileEntity, Map, TileEntityBehaviour> behaviours) { - smartTileEntity = tileEntity; - this.behaviours = behaviours; - } - - @Override - public Type getGenericType() { - return smartTileEntity.getClass(); - } - - public void attach(TileEntityBehaviour behaviour) { - behaviours.put(behaviour.getType(), behaviour); - } - - public TileEntityBehaviour remove(BehaviourType type) { - return behaviours.remove(type); - } - - public T getTileEntity() { - return smartTileEntity; - } - - public BlockState getBlockState() { - return smartTileEntity.getBlockState(); - } - -} diff --git a/src/main/java/com/simibubi/create/api/event/TrackGraphMergeEvent.java b/src/main/java/com/simibubi/create/api/event/TrackGraphMergeEvent.java new file mode 100644 index 000000000..d48e2a3a7 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/event/TrackGraphMergeEvent.java @@ -0,0 +1,22 @@ +package com.simibubi.create.api.event; + +import com.simibubi.create.content.trains.graph.TrackGraph; + +import net.minecraftforge.eventbus.api.Event; + +public class TrackGraphMergeEvent extends Event{ + private TrackGraph mergedInto, mergedFrom; + + public TrackGraphMergeEvent(TrackGraph from, TrackGraph into) { + mergedInto = into; + mergedFrom = from; + } + + public TrackGraph getGraphMergedInto() { + return mergedInto; + } + + public TrackGraph getGraphMergedFrom() { + return mergedFrom; + } +} diff --git a/src/main/java/com/simibubi/create/compat/Mods.java b/src/main/java/com/simibubi/create/compat/Mods.java index 55fe10952..36bd60e52 100644 --- a/src/main/java/com/simibubi/create/compat/Mods.java +++ b/src/main/java/com/simibubi/create/compat/Mods.java @@ -5,7 +5,10 @@ import java.util.function.Supplier; import com.simibubi.create.foundation.utility.Lang; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.Block; import net.minecraftforge.fml.ModList; +import net.minecraftforge.registries.ForgeRegistries; /** * For compatibility with and without another mod present, we have to define load conditions of the specific code @@ -14,6 +17,8 @@ public enum Mods { DYNAMICTREES, TCONSTRUCT, CURIOS, + + COMPUTERCRAFT, STORAGEDRAWERS, XLPACKETS; @@ -51,4 +56,8 @@ public enum Mods { toExecute.get().run(); } } + + public Block getBlock(String id) { + return ForgeRegistries.BLOCKS.getValue(new ResourceLocation(asId(), id)); + } } diff --git a/src/main/java/com/simibubi/create/compat/computercraft/AbstractComputerBehaviour.java b/src/main/java/com/simibubi/create/compat/computercraft/AbstractComputerBehaviour.java new file mode 100644 index 000000000..956aad0b6 --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/computercraft/AbstractComputerBehaviour.java @@ -0,0 +1,57 @@ +package com.simibubi.create.compat.computercraft; + +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; + +import net.minecraft.nbt.CompoundTag; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; + +public class AbstractComputerBehaviour extends BlockEntityBehaviour { + + public static final BehaviourType TYPE = new BehaviourType<>(); + + boolean hasAttachedComputer; + + public AbstractComputerBehaviour(SmartBlockEntity te) { + super(te); + this.hasAttachedComputer = false; + } + + @Override + public void read(CompoundTag nbt, boolean clientPacket) { + hasAttachedComputer = nbt.getBoolean("HasAttachedComputer"); + super.read(nbt, clientPacket); + } + + @Override + public void write(CompoundTag nbt, boolean clientPacket) { + nbt.putBoolean("HasAttachedComputer", hasAttachedComputer); + super.write(nbt, clientPacket); + } + + public boolean isPeripheralCap(Capability cap) { + return false; + } + + public LazyOptional getPeripheralCapability() { + return LazyOptional.empty(); + } + + public void removePeripheral() {} + + public void setHasAttachedComputer(boolean hasAttachedComputer) { + this.hasAttachedComputer = hasAttachedComputer; + } + + public boolean hasAttachedComputer() { + return hasAttachedComputer; + } + + @Override + public BehaviourType getType() { + return TYPE; + } + +} diff --git a/src/main/java/com/simibubi/create/compat/computercraft/AttachedComputerPacket.java b/src/main/java/com/simibubi/create/compat/computercraft/AttachedComputerPacket.java new file mode 100644 index 000000000..0304e864b --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/computercraft/AttachedComputerPacket.java @@ -0,0 +1,37 @@ +package com.simibubi.create.compat.computercraft; + +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.SyncedBlockEntity; +import com.simibubi.create.foundation.networking.BlockEntityDataPacket; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; + +public class AttachedComputerPacket extends BlockEntityDataPacket { + + private final boolean hasAttachedComputer; + + public AttachedComputerPacket(BlockPos blockEntityPos, boolean hasAttachedComputer) { + super(blockEntityPos); + this.hasAttachedComputer = hasAttachedComputer; + } + + public AttachedComputerPacket(FriendlyByteBuf buffer) { + super(buffer); + this.hasAttachedComputer = buffer.readBoolean(); + } + + @Override + protected void writeData(FriendlyByteBuf buffer) { + buffer.writeBoolean(hasAttachedComputer); + } + + @Override + protected void handlePacket(SyncedBlockEntity blockEntity) { + if (blockEntity instanceof SmartBlockEntity sbe) { + sbe.getBehaviour(AbstractComputerBehaviour.TYPE) + .setHasAttachedComputer(hasAttachedComputer); + } + } + +} diff --git a/src/main/java/com/simibubi/create/compat/computercraft/ComputerCraftProxy.java b/src/main/java/com/simibubi/create/compat/computercraft/ComputerCraftProxy.java new file mode 100644 index 000000000..236e9695d --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/computercraft/ComputerCraftProxy.java @@ -0,0 +1,29 @@ +package com.simibubi.create.compat.computercraft; + +import java.util.function.Function; + +import com.simibubi.create.compat.Mods; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; + +public class ComputerCraftProxy { + + public static void register() { + fallbackFactory = FallbackComputerBehaviour::new; + Mods.COMPUTERCRAFT.executeIfInstalled(() -> ComputerCraftProxy::registerWithDependency); + } + + private static void registerWithDependency() { + /* Comment if computercraft.implementation is not in the source set */ + // computerFactory = ComputerBehaviour::new; + } + + private static Function fallbackFactory; + private static Function computerFactory; + + public static AbstractComputerBehaviour behaviour(SmartBlockEntity sbe) { + if (computerFactory == null) + return fallbackFactory.apply(sbe); + return computerFactory.apply(sbe); + } + +} diff --git a/src/main/java/com/simibubi/create/compat/computercraft/ComputerScreen.java b/src/main/java/com/simibubi/create/compat/computercraft/ComputerScreen.java new file mode 100644 index 000000000..2d55a2554 --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/computercraft/ComputerScreen.java @@ -0,0 +1,96 @@ +package com.simibubi.create.compat.computercraft; + +import java.util.function.Supplier; + +import javax.annotation.Nullable; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.compat.Mods; +import com.simibubi.create.foundation.gui.AbstractSimiScreen; +import com.simibubi.create.foundation.gui.AllGuiTextures; +import com.simibubi.create.foundation.gui.AllIcons; +import com.simibubi.create.foundation.gui.element.GuiGameElement; +import com.simibubi.create.foundation.gui.widget.AbstractSimiWidget; +import com.simibubi.create.foundation.gui.widget.ElementWidget; +import com.simibubi.create.foundation.gui.widget.IconButton; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; + +public class ComputerScreen extends AbstractSimiScreen { + + private final AllGuiTextures background = AllGuiTextures.COMPUTER; + + private final Supplier displayTitle; + private final RenderWindowFunction additional; + private final Screen previousScreen; + private final Supplier hasAttachedComputer; + + private AbstractSimiWidget computerWidget; + private IconButton confirmButton; + + public ComputerScreen(Component title, @Nullable RenderWindowFunction additional, Screen previousScreen, Supplier hasAttachedComputer) { + this(title, () -> title, additional, previousScreen, hasAttachedComputer); + } + + public ComputerScreen(Component title, Supplier displayTitle, @Nullable RenderWindowFunction additional, Screen previousScreen, Supplier hasAttachedComputer) { + super(title); + this.displayTitle = displayTitle; + this.additional = additional; + this.previousScreen = previousScreen; + this.hasAttachedComputer = hasAttachedComputer; + } + + @Override + public void tick() { + if (!hasAttachedComputer.get()) + minecraft.setScreen(previousScreen); + + super.tick(); + } + + @Override + protected void init() { + setWindowSize(background.width, background.height); + super.init(); + + int x = guiLeft; + int y = guiTop; + + Mods.COMPUTERCRAFT.executeIfInstalled(() -> () -> { + computerWidget = new ElementWidget(x + 33, y + 38) + .showingElement(GuiGameElement.of(Mods.COMPUTERCRAFT.getBlock("computer_advanced"))); + computerWidget.getToolTip().add(Lang.translate("gui.attached_computer.hint").component()); + addRenderableWidget(computerWidget); + }); + + confirmButton = new IconButton(x + background.width - 33, y + background.height - 24, AllIcons.I_CONFIRM); + confirmButton.withCallback(this::onClose); + addRenderableWidget(confirmButton); + } + + + + @Override + protected void renderWindow(PoseStack ms, int mouseX, int mouseY, float partialTicks) { + int x = guiLeft; + int y = guiTop; + + background.render(ms, x, y, this); + + font.draw(ms, displayTitle.get(), x + background.width / 2.0F - font.width(displayTitle.get()) / 2.0F, y + 4, 0x442000); + font.drawWordWrap(Lang.translate("gui.attached_computer.controlled").component(), x + 55, y + 32, 111, 0x7A7A7A); + + if (additional != null) + additional.render(ms, mouseX, mouseY, partialTicks, x, y, background); + } + + @FunctionalInterface + public interface RenderWindowFunction { + + void render(PoseStack ms, int mouseX, int mouseY, float partialTicks, int guiLeft, int guiTop, AllGuiTextures background); + + } + +} diff --git a/src/main/java/com/simibubi/create/compat/computercraft/FallbackComputerBehaviour.java b/src/main/java/com/simibubi/create/compat/computercraft/FallbackComputerBehaviour.java new file mode 100644 index 000000000..7e58c270d --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/computercraft/FallbackComputerBehaviour.java @@ -0,0 +1,16 @@ +package com.simibubi.create.compat.computercraft; + +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; + +public class FallbackComputerBehaviour extends AbstractComputerBehaviour { + + public FallbackComputerBehaviour(SmartBlockEntity te) { + super(te); + } + + @Override + public boolean hasAttachedComputer() { + return false; + } + +} diff --git a/src/main/java/com/simibubi/create/compat/computercraft/implementation/ComputerBehaviour.java b/src/main/java/com/simibubi/create/compat/computercraft/implementation/ComputerBehaviour.java new file mode 100644 index 000000000..25733fa87 --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/computercraft/implementation/ComputerBehaviour.java @@ -0,0 +1,75 @@ +package com.simibubi.create.compat.computercraft.implementation; + +import com.simibubi.create.compat.computercraft.AbstractComputerBehaviour; +import com.simibubi.create.compat.computercraft.implementation.peripherals.DisplayLinkPeripheral; +import com.simibubi.create.compat.computercraft.implementation.peripherals.SequencedGearshiftPeripheral; +import com.simibubi.create.compat.computercraft.implementation.peripherals.SpeedControllerPeripheral; +import com.simibubi.create.compat.computercraft.implementation.peripherals.SpeedGaugePeripheral; +import com.simibubi.create.compat.computercraft.implementation.peripherals.StationPeripheral; +import com.simibubi.create.compat.computercraft.implementation.peripherals.StressGaugePeripheral; +import com.simibubi.create.content.kinetics.gauge.SpeedGaugeBlockEntity; +import com.simibubi.create.content.kinetics.gauge.StressGaugeBlockEntity; +import com.simibubi.create.content.kinetics.speedController.SpeedControllerBlockEntity; +import com.simibubi.create.content.kinetics.transmission.sequencer.SequencedGearshiftBlockEntity; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkBlockEntity; +import com.simibubi.create.content.trains.station.StationBlockEntity; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; + +import dan200.computercraft.api.peripheral.IPeripheral; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.CapabilityManager; +import net.minecraftforge.common.capabilities.CapabilityToken; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.common.util.NonNullSupplier; +import net.minecraftforge.registries.ForgeRegistries; + +public class ComputerBehaviour extends AbstractComputerBehaviour { + + protected static final Capability PERIPHERAL_CAPABILITY = + CapabilityManager.get(new CapabilityToken<>() { + }); + LazyOptional peripheral; + NonNullSupplier peripheralSupplier; + + public ComputerBehaviour(SmartBlockEntity te) { + super(te); + this.peripheralSupplier = getPeripheralFor(te); + } + + public static NonNullSupplier getPeripheralFor(SmartBlockEntity te) { + if (te instanceof SpeedControllerBlockEntity scbe) + return () -> new SpeedControllerPeripheral(scbe, scbe.targetSpeed); + if (te instanceof DisplayLinkBlockEntity dlbe) + return () -> new DisplayLinkPeripheral(dlbe); + if (te instanceof SequencedGearshiftBlockEntity sgbe) + return () -> new SequencedGearshiftPeripheral(sgbe); + if (te instanceof SpeedGaugeBlockEntity sgbe) + return () -> new SpeedGaugePeripheral(sgbe); + if (te instanceof StressGaugeBlockEntity sgbe) + return () -> new StressGaugePeripheral(sgbe); + if (te instanceof StationBlockEntity sbe) + return () -> new StationPeripheral(sbe); + + throw new IllegalArgumentException( + "No peripheral available for " + ForgeRegistries.BLOCK_ENTITY_TYPES.getKey(te.getType())); + } + + @Override + public boolean isPeripheralCap(Capability cap) { + return cap == PERIPHERAL_CAPABILITY; + } + + @Override + public LazyOptional getPeripheralCapability() { + if (peripheral == null || !peripheral.isPresent()) + peripheral = LazyOptional.of(peripheralSupplier); + return peripheral.cast(); + } + + @Override + public void removePeripheral() { + if (peripheral != null) + peripheral.invalidate(); + } + +} diff --git a/src/main/java/com/simibubi/create/compat/computercraft/implementation/CreateLuaTable.java b/src/main/java/com/simibubi/create/compat/computercraft/implementation/CreateLuaTable.java new file mode 100644 index 000000000..3c957274e --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/computercraft/implementation/CreateLuaTable.java @@ -0,0 +1,172 @@ +package com.simibubi.create.compat.computercraft.implementation; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.lua.LuaTable; +import dan200.computercraft.api.lua.LuaValues; + +public class CreateLuaTable implements LuaTable { + + private final Map map; + + public CreateLuaTable() { + this.map = new HashMap<>(); + } + + public CreateLuaTable(Map map) { + this.map = new HashMap<>(map); + } + + public boolean getBoolean(String key) throws LuaException { + Object value = get(key); + + if (!(value instanceof Boolean)) + throw LuaValues.badField(key, "boolean", LuaValues.getType(value)); + + return (Boolean) value; + } + + public String getString(String key) throws LuaException { + Object value = get(key); + + if (!(value instanceof String)) + throw LuaValues.badField(key, "string", LuaValues.getType(value)); + + return (String) value; + } + + public CreateLuaTable getTable(String key) throws LuaException { + Object value = get(key); + + if (!(value instanceof Map)) + throw LuaValues.badField(key, "table", LuaValues.getType(value)); + + return new CreateLuaTable((Map) value); + } + + public Optional getOptBoolean(String key) throws LuaException { + Object value = get(key); + + if (value == null) + return Optional.empty(); + + if (!(value instanceof Boolean)) + throw LuaValues.badField(key, "boolean", LuaValues.getType(value)); + + return Optional.of((Boolean) value); + } + + public Set stringKeySet() throws LuaException { + Set stringSet = new HashSet<>(); + + for (Object key : keySet()) { + if (!(key instanceof String)) + throw new LuaException("key " + key + " is not string (got " + LuaValues.getType(key) + ")"); + + stringSet.add((String) key); + } + + return Collections.unmodifiableSet(stringSet); + } + + public Collection tableValues() throws LuaException { + List tables = new ArrayList<>(); + + for (int i = 1; i <= size(); i++) { + Object value = get((double) i); + + if (!(value instanceof Map)) + throw new LuaException("value " + value + " is not table (got " + LuaValues.getType(value) + ")"); + + tables.add(new CreateLuaTable((Map) value)); + } + + return Collections.unmodifiableList(tables); + } + + public Map getMap() { + return map; + } + + @Nullable + @Override + public Object put(Object key, Object value) { + return map.put(key, value); + } + + public void putBoolean(String key, boolean value) { + map.put(key, value); + } + + public void putDouble(String key, double value) { + map.put(key, value); + } + + public void putString(String key, String value) { + map.put(key, value); + } + + public void putTable(String key, CreateLuaTable value) { + map.put(key, value); + } + + public void putTable(int i, CreateLuaTable value) { + map.put(i, value); + } + + @Override + public int size() { + return map.size(); + } + + @Override + public boolean isEmpty() { + return map.isEmpty(); + } + + @Override + public boolean containsKey(Object o) { + return map.containsKey(o); + } + + @Override + public boolean containsValue(Object o) { + return map.containsValue(o); + } + + @Override + public Object get(Object o) { + return map.get(o); + } + + @NotNull + @Override + public Set keySet() { + return map.keySet(); + } + + @NotNull + @Override + public Collection values() { + return map.values(); + } + + @NotNull + @Override + public Set> entrySet() { + return map.entrySet(); + } + +} diff --git a/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/DisplayLinkPeripheral.java b/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/DisplayLinkPeripheral.java new file mode 100644 index 000000000..2d1c9d29b --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/DisplayLinkPeripheral.java @@ -0,0 +1,108 @@ +package com.simibubi.create.compat.computercraft.implementation.peripherals; + +import java.util.concurrent.atomic.AtomicInteger; + +import org.jetbrains.annotations.NotNull; + +import com.simibubi.create.content.redstone.displayLink.DisplayLinkBlockEntity; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; + +import dan200.computercraft.api.lua.LuaFunction; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.StringTag; +import net.minecraft.nbt.Tag; + +public class DisplayLinkPeripheral extends SyncedPeripheral { + + public static final String TAG_KEY = "ComputerSourceList"; + private final AtomicInteger cursorX = new AtomicInteger(); + private final AtomicInteger cursorY = new AtomicInteger(); + + public DisplayLinkPeripheral(DisplayLinkBlockEntity blockEntity) { + super(blockEntity); + } + + @LuaFunction + public final void setCursorPos(int x, int y) { + cursorX.set(x - 1); + cursorY.set(y - 1); + } + + @LuaFunction + public final Object[] getCursorPos() { + return new Object[] {cursorX.get() + 1, cursorY.get() + 1}; + } + + @LuaFunction(mainThread = true) + public final Object[] getSize() { + DisplayTargetStats stats = blockEntity.activeTarget.provideStats(new DisplayLinkContext(blockEntity.getLevel(), blockEntity)); + return new Object[]{stats.maxRows(), stats.maxColumns()}; + } + + @LuaFunction + public final boolean isColor() { + return false; + } + + @LuaFunction + public final boolean isColour() { + return false; + } + + @LuaFunction + public final void write(String text) { + ListTag tag = blockEntity.getSourceConfig().getList(TAG_KEY, Tag.TAG_STRING); + + int x = cursorX.get(); + int y = cursorY.get(); + + for (int i = tag.size(); i <= y; i++) { + tag.add(StringTag.valueOf("")); + } + + StringBuilder builder = new StringBuilder(tag.getString(y)); + + builder.append(" ".repeat(Math.max(0, x - builder.length()))); + builder.replace(x, x + text.length(), text); + + tag.set(y, StringTag.valueOf(builder.toString())); + + synchronized (blockEntity) { + blockEntity.getSourceConfig().put(TAG_KEY, tag); + } + + cursorX.set(x + text.length()); + } + + @LuaFunction + public final void clearLine() { + ListTag tag = blockEntity.getSourceConfig().getList(TAG_KEY, Tag.TAG_STRING); + + if (tag.size() > cursorY.get()) + tag.set(cursorY.get(), StringTag.valueOf("")); + + synchronized (blockEntity) { + blockEntity.getSourceConfig().put(TAG_KEY, tag); + } + } + + @LuaFunction + public final void clear() { + synchronized (blockEntity) { + blockEntity.getSourceConfig().put(TAG_KEY, new ListTag()); + } + } + + @LuaFunction(mainThread = true) + public final void update() { + blockEntity.tickSource(); + } + + @NotNull + @Override + public String getType() { + return "Create_DisplayLink"; + } + +} diff --git a/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/SequencedGearshiftPeripheral.java b/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/SequencedGearshiftPeripheral.java new file mode 100644 index 000000000..9d83359f8 --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/SequencedGearshiftPeripheral.java @@ -0,0 +1,54 @@ +package com.simibubi.create.compat.computercraft.implementation.peripherals; + +import org.jetbrains.annotations.NotNull; + +import com.simibubi.create.content.kinetics.transmission.sequencer.Instruction; +import com.simibubi.create.content.kinetics.transmission.sequencer.InstructionSpeedModifiers; +import com.simibubi.create.content.kinetics.transmission.sequencer.SequencedGearshiftBlockEntity; +import com.simibubi.create.content.kinetics.transmission.sequencer.SequencerInstructions; + +import dan200.computercraft.api.lua.IArguments; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.lua.LuaFunction; + +public class SequencedGearshiftPeripheral extends SyncedPeripheral { + + public SequencedGearshiftPeripheral(SequencedGearshiftBlockEntity blockEntity) { + super(blockEntity); + } + + @LuaFunction(mainThread = true) + public final void rotate(IArguments arguments) throws LuaException { + runInstruction(arguments, SequencerInstructions.TURN_ANGLE); + } + + @LuaFunction(mainThread = true) + public final void move(IArguments arguments) throws LuaException { + runInstruction(arguments, SequencerInstructions.TURN_DISTANCE); + } + + @LuaFunction + public final boolean isRunning() { + return !this.blockEntity.isIdle(); + } + + private void runInstruction(IArguments arguments, SequencerInstructions instructionType) throws LuaException { + int speedModifier = arguments.count() > 1 ? arguments.getInt(1) : 1; + this.blockEntity.getInstructions().clear(); + + this.blockEntity.getInstructions().add(new Instruction( + instructionType, + InstructionSpeedModifiers.getByModifier(speedModifier), + Math.abs(arguments.getInt(0)))); + this.blockEntity.getInstructions().add(new Instruction(SequencerInstructions.END)); + + this.blockEntity.run(0); + } + + @NotNull + @Override + public String getType() { + return "Create_SequencedGearshift"; + } + +} diff --git a/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/SpeedControllerPeripheral.java b/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/SpeedControllerPeripheral.java new file mode 100644 index 000000000..233a81e97 --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/SpeedControllerPeripheral.java @@ -0,0 +1,35 @@ +package com.simibubi.create.compat.computercraft.implementation.peripherals; + +import org.jetbrains.annotations.NotNull; + +import com.simibubi.create.content.kinetics.speedController.SpeedControllerBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollValueBehaviour; + +import dan200.computercraft.api.lua.LuaFunction; + +public class SpeedControllerPeripheral extends SyncedPeripheral { + + private final ScrollValueBehaviour targetSpeed; + + public SpeedControllerPeripheral(SpeedControllerBlockEntity blockEntity, ScrollValueBehaviour targetSpeed) { + super(blockEntity); + this.targetSpeed = targetSpeed; + } + + @LuaFunction(mainThread = true) + public final void setTargetSpeed(int speed) { + this.targetSpeed.setValue(speed); + } + + @LuaFunction + public final float getTargetSpeed() { + return this.targetSpeed.getValue(); + } + + @NotNull + @Override + public String getType() { + return "Create_RotationSpeedController"; + } + +} diff --git a/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/SpeedGaugePeripheral.java b/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/SpeedGaugePeripheral.java new file mode 100644 index 000000000..d6ff9d20b --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/SpeedGaugePeripheral.java @@ -0,0 +1,26 @@ +package com.simibubi.create.compat.computercraft.implementation.peripherals; + +import org.jetbrains.annotations.NotNull; + +import com.simibubi.create.content.kinetics.gauge.SpeedGaugeBlockEntity; + +import dan200.computercraft.api.lua.LuaFunction; + +public class SpeedGaugePeripheral extends SyncedPeripheral { + + public SpeedGaugePeripheral(SpeedGaugeBlockEntity blockEntity) { + super(blockEntity); + } + + @LuaFunction + public final float getSpeed() { + return this.blockEntity.getSpeed(); + } + + @NotNull + @Override + public String getType() { + return "Create_Speedometer"; + } + +} diff --git a/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/StationPeripheral.java b/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/StationPeripheral.java new file mode 100644 index 000000000..230ade2a6 --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/StationPeripheral.java @@ -0,0 +1,269 @@ +package com.simibubi.create.compat.computercraft.implementation.peripherals; + +import java.util.Map; + +import javax.annotation.Nullable; + +import org.jetbrains.annotations.NotNull; + +import com.simibubi.create.AllPackets; +import com.simibubi.create.compat.computercraft.implementation.CreateLuaTable; +import com.simibubi.create.content.trains.entity.Train; +import com.simibubi.create.content.trains.schedule.Schedule; +import com.simibubi.create.content.trains.station.GlobalStation; +import com.simibubi.create.content.trains.station.StationBlockEntity; +import com.simibubi.create.content.trains.station.TrainEditPacket; +import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.StringHelper; + +import dan200.computercraft.api.lua.IArguments; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.lua.LuaFunction; +import net.minecraft.nbt.ByteTag; +import net.minecraft.nbt.CollectionTag; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.DoubleTag; +import net.minecraft.nbt.IntTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.NumericTag; +import net.minecraft.nbt.StringTag; +import net.minecraft.nbt.Tag; +import net.minecraftforge.network.PacketDistributor; + +public class StationPeripheral extends SyncedPeripheral { + + public StationPeripheral(StationBlockEntity blockEntity) { + super(blockEntity); + } + + @LuaFunction(mainThread = true) + public final void assemble() throws LuaException { + if (!blockEntity.isAssembling()) + throw new LuaException("station must be in assembly mode"); + + blockEntity.assemble(null); + + if (blockEntity.getStation() == null || blockEntity.getStation().getPresentTrain() == null) + throw new LuaException("failed to assemble train"); + + if (!blockEntity.exitAssemblyMode()) + throw new LuaException("failed to exit assembly mode"); + } + + @LuaFunction(mainThread = true) + public final void disassemble() throws LuaException { + if (blockEntity.isAssembling()) + throw new LuaException("station must not be in assembly mode"); + + getTrainOrThrow(); + + if (!blockEntity.enterAssemblyMode(null)) + throw new LuaException("could not disassemble train"); + } + + @LuaFunction(mainThread = true) + public final void setAssemblyMode(boolean assemblyMode) throws LuaException { + if (assemblyMode) { + if (!blockEntity.enterAssemblyMode(null)) + throw new LuaException("failed to enter assembly mode"); + } else { + if (!blockEntity.exitAssemblyMode()) + throw new LuaException("failed to exit assembly mode"); + } + } + + @LuaFunction + public final boolean isInAssemblyMode() { + return blockEntity.isAssembling(); + } + + @LuaFunction + public final String getStationName() throws LuaException { + GlobalStation station = blockEntity.getStation(); + if (station == null) + throw new LuaException("station is not connected to a track"); + + return station.name; + } + + @LuaFunction(mainThread = true) + public final void setStationName(String name) throws LuaException { + if (!blockEntity.updateName(name)) + throw new LuaException("could not set station name"); + } + + @LuaFunction + public final boolean isTrainPresent() throws LuaException { + GlobalStation station = blockEntity.getStation(); + if (station == null) + throw new LuaException("station is not connected to a track"); + + return station.getPresentTrain() != null; + } + + @LuaFunction + public final boolean isTrainImminent() throws LuaException { + GlobalStation station = blockEntity.getStation(); + if (station == null) + throw new LuaException("station is not connected to a track"); + + return station.getImminentTrain() != null; + } + + @LuaFunction + public final boolean isTrainEnroute() throws LuaException { + GlobalStation station = blockEntity.getStation(); + if (station == null) + throw new LuaException("station is not connected to a track"); + + return station.getNearestTrain() != null; + } + + @LuaFunction + public final String getTrainName() throws LuaException { + Train train = getTrainOrThrow(); + return train.name.getString(); + } + + @LuaFunction(mainThread = true) + public final void setTrainName(String name) throws LuaException { + Train train = getTrainOrThrow(); + train.name = Components.literal(name); + AllPackets.getChannel().send(PacketDistributor.ALL.noArg(), new TrainEditPacket.TrainEditReturnPacket(train.id, name, train.icon.getId())); + } + + @LuaFunction + public final boolean hasSchedule() throws LuaException { + Train train = getTrainOrThrow(); + return train.runtime.getSchedule() != null; + } + + @LuaFunction + public final CreateLuaTable getSchedule() throws LuaException { + Train train = getTrainOrThrow(); + + Schedule schedule = train.runtime.getSchedule(); + if (schedule == null) + throw new LuaException("train doesn't have a schedule"); + + return fromCompoundTag(schedule.write()); + } + + @LuaFunction(mainThread = true) + public final void setSchedule(IArguments arguments) throws LuaException { + Train train = getTrainOrThrow(); + Schedule schedule = Schedule.fromTag(toCompoundTag(new CreateLuaTable(arguments.getTable(0)))); + boolean autoSchedule = train.runtime.getSchedule() == null || train.runtime.isAutoSchedule; + train.runtime.setSchedule(schedule, autoSchedule); + } + + private @NotNull Train getTrainOrThrow() throws LuaException { + GlobalStation station = blockEntity.getStation(); + if (station == null) + throw new LuaException("station is not connected to a track"); + + Train train = station.getPresentTrain(); + if (train == null) + throw new LuaException("there is no train present"); + + return train; + } + + private static @NotNull CreateLuaTable fromCompoundTag(CompoundTag tag) throws LuaException { + return (CreateLuaTable) fromNBTTag(null, tag); + } + + private static @NotNull Object fromNBTTag(@Nullable String key, Tag tag) throws LuaException { + byte type = tag.getId(); + + if (type == Tag.TAG_BYTE && key != null && key.equals("Count")) + return ((NumericTag) tag).getAsByte(); + else if (type == Tag.TAG_BYTE) + return ((NumericTag) tag).getAsByte() != 0; + else if (type == Tag.TAG_SHORT || type == Tag.TAG_INT || type == Tag.TAG_LONG) + return ((NumericTag) tag).getAsLong(); + else if (type == Tag.TAG_FLOAT || type == Tag.TAG_DOUBLE) + return ((NumericTag) tag).getAsDouble(); + else if (type == Tag.TAG_STRING) + return tag.getAsString(); + else if (type == Tag.TAG_LIST || type == Tag.TAG_BYTE_ARRAY || type == Tag.TAG_INT_ARRAY || type == Tag.TAG_LONG_ARRAY) { + CreateLuaTable list = new CreateLuaTable(); + CollectionTag listTag = (CollectionTag) tag; + + for (int i = 0; i < listTag.size(); i++) { + list.put(i + 1, fromNBTTag(null, listTag.get(i))); + } + + return list; + + } else if (type == Tag.TAG_COMPOUND) { + CreateLuaTable table = new CreateLuaTable(); + CompoundTag compoundTag = (CompoundTag) tag; + + for (String compoundKey : compoundTag.getAllKeys()) { + table.put( + StringHelper.camelCaseToSnakeCase(compoundKey), + fromNBTTag(compoundKey, compoundTag.get(compoundKey)) + ); + } + + return table; + } + + throw new LuaException("unknown tag type " + tag.getType().getName()); + } + + private static @NotNull CompoundTag toCompoundTag(CreateLuaTable table) throws LuaException { + return (CompoundTag) toNBTTag(null, table.getMap()); + } + + private static @NotNull Tag toNBTTag(@Nullable String key, Object value) throws LuaException { + if (value instanceof Boolean v) + return ByteTag.valueOf(v); + else if (value instanceof Byte || (key != null && key.equals("count"))) + return ByteTag.valueOf(((Number) value).byteValue()); + else if (value instanceof Number v) { + // If number is numerical integer + if (v.intValue() == v.doubleValue()) + return IntTag.valueOf(v.intValue()); + else + return DoubleTag.valueOf(v.doubleValue()); + + } else if (value instanceof String v) + return StringTag.valueOf(v); + else if (value instanceof Map v && v.containsKey(1.0)) { // List + ListTag list = new ListTag(); + for (Object o : v.values()) { + list.add(toNBTTag(null, o)); + } + + return list; + + } else if (value instanceof Map v) { // Table/Map + CompoundTag compound = new CompoundTag(); + for (Object objectKey : v.keySet()) { + if (!(objectKey instanceof String compoundKey)) + throw new LuaException("table key is not of type string"); + + compound.put( + // Items serialize their resource location as "id" and not as "Id". + // This check is needed to see if the 'i' should be left lowercase or not. + // Items store "count" in the same compound tag, so we can check for its presence to see if this is a serialized item + compoundKey.equals("id") && v.containsKey("count") ? "id" : StringHelper.snakeCaseToCamelCase(compoundKey), + toNBTTag(compoundKey, v.get(compoundKey)) + ); + } + + return compound; + } + + throw new LuaException("unknown object type " + value.getClass().getName()); + } + + @NotNull + @Override + public String getType() { + return "Create_Station"; + } + +} diff --git a/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/StressGaugePeripheral.java b/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/StressGaugePeripheral.java new file mode 100644 index 000000000..19c45a162 --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/StressGaugePeripheral.java @@ -0,0 +1,31 @@ +package com.simibubi.create.compat.computercraft.implementation.peripherals; + +import org.jetbrains.annotations.NotNull; + +import com.simibubi.create.content.kinetics.gauge.StressGaugeBlockEntity; + +import dan200.computercraft.api.lua.LuaFunction; + +public class StressGaugePeripheral extends SyncedPeripheral { + + public StressGaugePeripheral(StressGaugeBlockEntity blockEntity) { + super(blockEntity); + } + + @LuaFunction + public final float getStress() { + return this.blockEntity.getNetworkStress(); + } + + @LuaFunction + public final float getStressCapacity() { + return this.blockEntity.getNetworkCapacity(); + } + + @NotNull + @Override + public String getType() { + return "Create_Stressometer"; + } + +} diff --git a/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/SyncedPeripheral.java b/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/SyncedPeripheral.java new file mode 100644 index 000000000..7c0b1f7b1 --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/computercraft/implementation/peripherals/SyncedPeripheral.java @@ -0,0 +1,50 @@ +package com.simibubi.create.compat.computercraft.implementation.peripherals; + +import java.util.concurrent.atomic.AtomicInteger; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.AllPackets; +import com.simibubi.create.compat.computercraft.AttachedComputerPacket; +import com.simibubi.create.compat.computercraft.implementation.ComputerBehaviour; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; + +import dan200.computercraft.api.peripheral.IComputerAccess; +import dan200.computercraft.api.peripheral.IPeripheral; +import net.minecraftforge.network.PacketDistributor; + +public abstract class SyncedPeripheral implements IPeripheral { + + protected final T blockEntity; + private final AtomicInteger computers = new AtomicInteger(); + + public SyncedPeripheral(T blockEntity) { + this.blockEntity = blockEntity; + } + + @Override + public void attach(@NotNull IComputerAccess computer) { + computers.incrementAndGet(); + updateBlockEntity(); + } + + @Override + public void detach(@NotNull IComputerAccess computer) { + computers.decrementAndGet(); + updateBlockEntity(); + } + + private void updateBlockEntity() { + boolean hasAttachedComputer = computers.get() > 0; + + blockEntity.getBehaviour(ComputerBehaviour.TYPE).setHasAttachedComputer(hasAttachedComputer); + AllPackets.getChannel().send(PacketDistributor.ALL.noArg(), new AttachedComputerPacket(blockEntity.getBlockPos(), hasAttachedComputer)); + } + + @Override + public boolean equals(@Nullable IPeripheral other) { + return this == other; + } + +} diff --git a/src/main/java/com/simibubi/create/compat/curios/Curios.java b/src/main/java/com/simibubi/create/compat/curios/Curios.java index 1b85d2f26..9545dcc2d 100644 --- a/src/main/java/com/simibubi/create/compat/curios/Curios.java +++ b/src/main/java/com/simibubi/create/compat/curios/Curios.java @@ -1,7 +1,7 @@ package com.simibubi.create.compat.curios; import com.simibubi.create.AllItems; -import com.simibubi.create.content.contraptions.goggles.GogglesItem; +import com.simibubi.create.content.equipment.goggles.GogglesItem; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.eventbus.api.IEventBus; diff --git a/src/main/java/com/simibubi/create/compat/jei/BlueprintTransferHandler.java b/src/main/java/com/simibubi/create/compat/jei/BlueprintTransferHandler.java index dc7281731..7356a422f 100644 --- a/src/main/java/com/simibubi/create/compat/jei/BlueprintTransferHandler.java +++ b/src/main/java/com/simibubi/create/compat/jei/BlueprintTransferHandler.java @@ -6,9 +6,9 @@ import javax.annotation.ParametersAreNonnullByDefault; import org.jetbrains.annotations.Nullable; -import com.simibubi.create.content.curiosities.tools.BlueprintAssignCompleteRecipePacket; -import com.simibubi.create.content.curiosities.tools.BlueprintContainer; -import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.AllPackets; +import com.simibubi.create.content.equipment.blueprint.BlueprintAssignCompleteRecipePacket; +import com.simibubi.create.content.equipment.blueprint.BlueprintMenu; import mezz.jei.api.constants.RecipeTypes; import mezz.jei.api.gui.ingredient.IRecipeSlotsView; @@ -22,15 +22,15 @@ import net.minecraft.world.item.crafting.CraftingRecipe; @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault -public class BlueprintTransferHandler implements IRecipeTransferHandler { +public class BlueprintTransferHandler implements IRecipeTransferHandler { @Override - public Class getContainerClass() { - return BlueprintContainer.class; + public Class getContainerClass() { + return BlueprintMenu.class; } @Override - public Optional> getMenuType() { + public Optional> getMenuType() { return Optional.empty(); } @@ -40,11 +40,11 @@ public class BlueprintTransferHandler implements IRecipeTransferHandler r instanceof CraftingRecipe && !(r instanceof IShapedRecipe) && r.getIngredients() .size() > 1 - && !MechanicalPressTileEntity.canCompress(r) && !AllRecipeTypes.shouldIgnoreInAutomation(r), + && !MechanicalPressBlockEntity.canCompress(r) && !AllRecipeTypes.shouldIgnoreInAutomation(r), BasinRecipe::convertShapeless) .catalyst(AllBlocks.MECHANICAL_MIXER::get) .catalyst(AllBlocks.BASIN::get) @@ -207,7 +207,7 @@ public class CreateJEI implements IModPlugin { .enableWhen(c -> c.allowShapedSquareInPress) .addAllRecipesIf( r -> (r instanceof CraftingRecipe) && !(r instanceof MechanicalCraftingRecipe) - && MechanicalPressTileEntity.canCompress(r) && !AllRecipeTypes.shouldIgnoreInAutomation(r), + && MechanicalPressBlockEntity.canCompress(r) && !AllRecipeTypes.shouldIgnoreInAutomation(r), BasinRecipe::convertShapeless) .catalyst(AllBlocks.MECHANICAL_PRESS::get) .catalyst(AllBlocks.BASIN::get) @@ -233,7 +233,7 @@ public class CreateJEI implements IModPlugin { woodCutting = builder(CondensedBlockCuttingRecipe.class) .enableIf(c -> c.allowWoodcuttingOnSaw.get() && ModList.get() .isLoaded("druidcraft")) - .addRecipes(() -> CondensedBlockCuttingRecipe.condenseRecipes(getTypedRecipesExcluding(SawTileEntity.woodcuttingRecipeType.get(), AllRecipeTypes::shouldIgnoreInAutomation))) + .addRecipes(() -> CondensedBlockCuttingRecipe.condenseRecipes(getTypedRecipesExcluding(SawBlockEntity.woodcuttingRecipeType.get(), AllRecipeTypes::shouldIgnoreInAutomation))) .catalyst(AllBlocks.MECHANICAL_SAW::get) .doubleItemIcon(AllBlocks.MECHANICAL_SAW.get(), Items.OAK_STAIRS) .emptyBackground(177, 70) @@ -457,11 +457,9 @@ public class CreateJEI implements IModPlugin { return addRecipeListConsumer(recipes -> { List> excludedRecipes = getTypedRecipes(recipeType.get()); recipes.removeIf(recipe -> { - for (Recipe excludedRecipe : excludedRecipes) { - if (doInputsMatch(recipe, excludedRecipe)) { + for (Recipe excludedRecipe : excludedRecipes) + if (doInputsMatch(recipe, excludedRecipe) && doOutputsMatch(recipe, excludedRecipe)) return true; - } - } return false; }); }); @@ -504,7 +502,7 @@ public class CreateJEI implements IModPlugin { public CreateRecipeCategory build(String name, CreateRecipeCategory.Factory factory) { Supplier> recipesSupplier; - if (predicate.test(AllConfigs.SERVER.recipes)) { + if (predicate.test(AllConfigs.server().recipes)) { recipesSupplier = () -> { List recipes = new ArrayList<>(); for (Consumer> consumer : recipeListConsumers) @@ -571,4 +569,8 @@ public class CreateJEI implements IModPlugin { .test(matchingStacks[0]); } + public static boolean doOutputsMatch(Recipe recipe1, Recipe recipe2) { + return ItemStack.isSame(recipe1.getResultItem(), recipe2.getResultItem()); + } + } diff --git a/src/main/java/com/simibubi/create/compat/jei/GhostIngredientHandler.java b/src/main/java/com/simibubi/create/compat/jei/GhostIngredientHandler.java index 6dc404182..9f3db72c9 100644 --- a/src/main/java/com/simibubi/create/compat/jei/GhostIngredientHandler.java +++ b/src/main/java/com/simibubi/create/compat/jei/GhostIngredientHandler.java @@ -5,11 +5,11 @@ import java.util.List; import javax.annotation.ParametersAreNonnullByDefault; -import com.simibubi.create.content.logistics.item.filter.AttributeFilterScreen; -import com.simibubi.create.foundation.gui.container.AbstractSimiContainerScreen; -import com.simibubi.create.foundation.gui.container.GhostItemContainer; -import com.simibubi.create.foundation.gui.container.GhostItemSubmitPacket; -import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.AllPackets; +import com.simibubi.create.content.logistics.filter.AttributeFilterScreen; +import com.simibubi.create.foundation.gui.menu.AbstractSimiContainerScreen; +import com.simibubi.create.foundation.gui.menu.GhostItemMenu; +import com.simibubi.create.foundation.gui.menu.GhostItemSubmitPacket; import mezz.jei.api.gui.handlers.IGhostIngredientHandler; import net.minecraft.MethodsReturnNonnullByDefault; @@ -19,7 +19,7 @@ import net.minecraft.world.item.ItemStack; @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault -public class GhostIngredientHandler> +public class GhostIngredientHandler> implements IGhostIngredientHandler> { @Override @@ -52,7 +52,7 @@ public class GhostIngredientHandler> return true; } - private static class GhostTarget> implements Target { + private static class GhostTarget> implements Target { private final Rect2i area; private final AbstractSimiContainerScreen gui; @@ -82,7 +82,7 @@ public class GhostIngredientHandler> return; // sync new filter contents with server - AllPackets.channel.sendToServer(new GhostItemSubmitPacket(stack, slotIndex)); + AllPackets.getChannel().sendToServer(new GhostItemSubmitPacket(stack, slotIndex)); } } } diff --git a/src/main/java/com/simibubi/create/compat/jei/PotionFluidSubtypeInterpreter.java b/src/main/java/com/simibubi/create/compat/jei/PotionFluidSubtypeInterpreter.java index ee5d05a6c..68b6d6151 100644 --- a/src/main/java/com/simibubi/create/compat/jei/PotionFluidSubtypeInterpreter.java +++ b/src/main/java/com/simibubi/create/compat/jei/PotionFluidSubtypeInterpreter.java @@ -2,7 +2,7 @@ package com.simibubi.create.compat.jei; import java.util.List; -import com.simibubi.create.content.contraptions.fluids.potion.PotionFluid.BottleType; +import com.simibubi.create.content.fluids.potion.PotionFluid.BottleType; import com.simibubi.create.foundation.utility.NBTHelper; import mezz.jei.api.ingredients.subtypes.IIngredientSubtypeInterpreter; diff --git a/src/main/java/com/simibubi/create/compat/jei/SlotMover.java b/src/main/java/com/simibubi/create/compat/jei/SlotMover.java index 0198d562c..711668054 100644 --- a/src/main/java/com/simibubi/create/compat/jei/SlotMover.java +++ b/src/main/java/com/simibubi/create/compat/jei/SlotMover.java @@ -2,7 +2,7 @@ package com.simibubi.create.compat.jei; import java.util.List; -import com.simibubi.create.foundation.gui.container.AbstractSimiContainerScreen; +import com.simibubi.create.foundation.gui.menu.AbstractSimiContainerScreen; import mezz.jei.api.gui.handlers.IGuiContainerHandler; import net.minecraft.client.renderer.Rect2i; diff --git a/src/main/java/com/simibubi/create/compat/jei/category/BasinCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/BasinCategory.java index 737a1101b..294dac022 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/BasinCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/BasinCategory.java @@ -10,10 +10,10 @@ import org.apache.commons.lang3.mutable.MutableInt; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; -import com.simibubi.create.content.contraptions.processing.BasinRecipe; -import com.simibubi.create.content.contraptions.processing.HeatCondition; -import com.simibubi.create.content.contraptions.processing.ProcessingOutput; -import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.HeatLevel; +import com.simibubi.create.content.processing.basin.BasinRecipe; +import com.simibubi.create.content.processing.burner.BlazeBurnerBlock.HeatLevel; +import com.simibubi.create.content.processing.recipe.HeatCondition; +import com.simibubi.create.content.processing.recipe.ProcessingOutput; import com.simibubi.create.foundation.fluid.FluidIngredient; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.item.ItemHelper; diff --git a/src/main/java/com/simibubi/create/compat/jei/category/CreateRecipeCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/CreateRecipeCategory.java index 480fc3e70..b626810db 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/CreateRecipeCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/CreateRecipeCategory.java @@ -12,8 +12,8 @@ import org.jetbrains.annotations.NotNull; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllFluids; -import com.simibubi.create.content.contraptions.fluids.potion.PotionFluidHandler; -import com.simibubi.create.content.contraptions.processing.ProcessingOutput; +import com.simibubi.create.content.fluids.potion.PotionFluidHandler; +import com.simibubi.create.content.processing.recipe.ProcessingOutput; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Lang; diff --git a/src/main/java/com/simibubi/create/compat/jei/category/CrushingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/CrushingCategory.java index 6d5f3b3eb..fb891a99b 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/CrushingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/CrushingCategory.java @@ -7,9 +7,9 @@ import javax.annotation.ParametersAreNonnullByDefault; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.compat.jei.category.animations.AnimatedCrushingWheels; -import com.simibubi.create.content.contraptions.components.crusher.AbstractCrushingRecipe; -import com.simibubi.create.content.contraptions.processing.ProcessingOutput; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipe; +import com.simibubi.create.content.kinetics.crusher.AbstractCrushingRecipe; +import com.simibubi.create.content.processing.recipe.ProcessingOutput; +import com.simibubi.create.content.processing.recipe.ProcessingRecipe; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.ponder.ui.LayoutHelper; diff --git a/src/main/java/com/simibubi/create/compat/jei/category/DeployingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/DeployingCategory.java index 9631e36b6..8e8465be5 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/DeployingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/DeployingCategory.java @@ -6,8 +6,8 @@ import javax.annotation.ParametersAreNonnullByDefault; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.compat.jei.category.animations.AnimatedDeployer; -import com.simibubi.create.content.contraptions.components.deployer.DeployerApplicationRecipe; -import com.simibubi.create.content.contraptions.processing.ProcessingOutput; +import com.simibubi.create.content.kinetics.deployer.DeployerApplicationRecipe; +import com.simibubi.create.content.processing.recipe.ProcessingOutput; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.utility.Lang; diff --git a/src/main/java/com/simibubi/create/compat/jei/category/FanHauntingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/FanHauntingCategory.java index b76ac4982..c574a5922 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/FanHauntingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/FanHauntingCategory.java @@ -4,7 +4,7 @@ import org.jetbrains.annotations.NotNull; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.compat.jei.category.animations.AnimatedKinetics; -import com.simibubi.create.content.contraptions.components.fan.HauntingRecipe; +import com.simibubi.create.content.kinetics.fan.HauntingRecipe; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.element.GuiGameElement; diff --git a/src/main/java/com/simibubi/create/compat/jei/category/FanWashingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/FanWashingCategory.java index d0064ed4d..aa41ec84f 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/FanWashingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/FanWashingCategory.java @@ -4,7 +4,7 @@ import org.jetbrains.annotations.NotNull; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.compat.jei.category.animations.AnimatedKinetics; -import com.simibubi.create.content.contraptions.components.fan.SplashingRecipe; +import com.simibubi.create.content.kinetics.fan.SplashingRecipe; import com.simibubi.create.foundation.gui.element.GuiGameElement; import net.minecraft.world.level.material.Fluids; diff --git a/src/main/java/com/simibubi/create/compat/jei/category/ItemApplicationCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/ItemApplicationCategory.java index c68bdeb79..c5c5a5e7e 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/ItemApplicationCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/ItemApplicationCategory.java @@ -8,8 +8,8 @@ import javax.annotation.ParametersAreNonnullByDefault; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Axis; import com.simibubi.create.compat.jei.category.animations.AnimatedKinetics; -import com.simibubi.create.content.contraptions.processing.ItemApplicationRecipe; -import com.simibubi.create.content.contraptions.processing.ProcessingOutput; +import com.simibubi.create.content.kinetics.deployer.ItemApplicationRecipe; +import com.simibubi.create.content.processing.recipe.ProcessingOutput; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.element.GuiGameElement; import com.simibubi.create.foundation.utility.Lang; diff --git a/src/main/java/com/simibubi/create/compat/jei/category/ItemDrainCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/ItemDrainCategory.java index 63f1779c0..b40b8beb3 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/ItemDrainCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/ItemDrainCategory.java @@ -7,9 +7,9 @@ import javax.annotation.ParametersAreNonnullByDefault; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.Create; import com.simibubi.create.compat.jei.category.animations.AnimatedItemDrain; -import com.simibubi.create.content.contraptions.fluids.potion.PotionFluidHandler; -import com.simibubi.create.content.contraptions.processing.EmptyingRecipe; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder; +import com.simibubi.create.content.fluids.potion.PotionFluidHandler; +import com.simibubi.create.content.fluids.transfer.EmptyingRecipe; +import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.utility.RegisteredObjects; diff --git a/src/main/java/com/simibubi/create/compat/jei/category/MillingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/MillingCategory.java index 9fc0945fe..f9943a976 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/MillingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/MillingCategory.java @@ -6,8 +6,8 @@ import javax.annotation.ParametersAreNonnullByDefault; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.compat.jei.category.animations.AnimatedMillstone; -import com.simibubi.create.content.contraptions.components.crusher.AbstractCrushingRecipe; -import com.simibubi.create.content.contraptions.processing.ProcessingOutput; +import com.simibubi.create.content.kinetics.crusher.AbstractCrushingRecipe; +import com.simibubi.create.content.processing.recipe.ProcessingOutput; import com.simibubi.create.foundation.gui.AllGuiTextures; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; diff --git a/src/main/java/com/simibubi/create/compat/jei/category/MixingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/MixingCategory.java index ad0bade4d..4cd7c7015 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/MixingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/MixingCategory.java @@ -5,8 +5,8 @@ import javax.annotation.ParametersAreNonnullByDefault; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.compat.jei.category.animations.AnimatedBlazeBurner; import com.simibubi.create.compat.jei.category.animations.AnimatedMixer; -import com.simibubi.create.content.contraptions.processing.BasinRecipe; -import com.simibubi.create.content.contraptions.processing.HeatCondition; +import com.simibubi.create.content.processing.basin.BasinRecipe; +import com.simibubi.create.content.processing.recipe.HeatCondition; import mezz.jei.api.gui.ingredient.IRecipeSlotsView; diff --git a/src/main/java/com/simibubi/create/compat/jei/category/PackingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/PackingCategory.java index 7cb7773d9..c7618096c 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/PackingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/PackingCategory.java @@ -5,8 +5,8 @@ import javax.annotation.ParametersAreNonnullByDefault; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.compat.jei.category.animations.AnimatedBlazeBurner; import com.simibubi.create.compat.jei.category.animations.AnimatedPress; -import com.simibubi.create.content.contraptions.processing.BasinRecipe; -import com.simibubi.create.content.contraptions.processing.HeatCondition; +import com.simibubi.create.content.processing.basin.BasinRecipe; +import com.simibubi.create.content.processing.recipe.HeatCondition; import com.simibubi.create.foundation.gui.AllGuiTextures; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; diff --git a/src/main/java/com/simibubi/create/compat/jei/category/PolishingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/PolishingCategory.java index 00fe2378e..eeae17b3f 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/PolishingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/PolishingCategory.java @@ -4,8 +4,8 @@ import javax.annotation.ParametersAreNonnullByDefault; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllItems; -import com.simibubi.create.content.contraptions.processing.ProcessingOutput; -import com.simibubi.create.content.curiosities.tools.SandPaperPolishingRecipe; +import com.simibubi.create.content.equipment.sandPaper.SandPaperPolishingRecipe; +import com.simibubi.create.content.processing.recipe.ProcessingOutput; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.element.GuiGameElement; diff --git a/src/main/java/com/simibubi/create/compat/jei/category/PressingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/PressingCategory.java index b0bffa08c..ba3084c88 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/PressingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/PressingCategory.java @@ -6,8 +6,8 @@ import javax.annotation.ParametersAreNonnullByDefault; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.compat.jei.category.animations.AnimatedPress; -import com.simibubi.create.content.contraptions.components.press.PressingRecipe; -import com.simibubi.create.content.contraptions.processing.ProcessingOutput; +import com.simibubi.create.content.kinetics.press.PressingRecipe; +import com.simibubi.create.content.processing.recipe.ProcessingOutput; import com.simibubi.create.foundation.gui.AllGuiTextures; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; diff --git a/src/main/java/com/simibubi/create/compat/jei/category/ProcessingViaFanCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/ProcessingViaFanCategory.java index 09e40037b..b7084afc4 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/ProcessingViaFanCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/ProcessingViaFanCategory.java @@ -7,11 +7,11 @@ import javax.annotation.ParametersAreNonnullByDefault; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Axis; -import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPartialModels; import com.simibubi.create.compat.jei.category.animations.AnimatedKinetics; -import com.simibubi.create.content.contraptions.processing.ProcessingOutput; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipe; +import com.simibubi.create.content.processing.recipe.ProcessingOutput; +import com.simibubi.create.content.processing.recipe.ProcessingRecipe; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.utility.Lang; @@ -57,7 +57,7 @@ public abstract class ProcessingViaFanCategory> extends Crea matrixStack.mulPose(Axis.XP.rotationDegrees(-12.5f)); matrixStack.mulPose(Axis.YP.rotationDegrees(22.5f)); - AnimatedKinetics.defaultBlockElement(AllBlockPartials.ENCASED_FAN_INNER) + AnimatedKinetics.defaultBlockElement(AllPartialModels.ENCASED_FAN_INNER) .rotateBlock(180, 0, AnimatedKinetics.getCurrentAngle() * 16) .scale(SCALE) .render(matrixStack); diff --git a/src/main/java/com/simibubi/create/compat/jei/category/SawingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/SawingCategory.java index 4db6a713d..b852d7e9c 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/SawingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/SawingCategory.java @@ -6,8 +6,8 @@ import javax.annotation.ParametersAreNonnullByDefault; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.compat.jei.category.animations.AnimatedSaw; -import com.simibubi.create.content.contraptions.components.saw.CuttingRecipe; -import com.simibubi.create.content.contraptions.processing.ProcessingOutput; +import com.simibubi.create.content.kinetics.saw.CuttingRecipe; +import com.simibubi.create.content.processing.recipe.ProcessingOutput; import com.simibubi.create.foundation.gui.AllGuiTextures; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; diff --git a/src/main/java/com/simibubi/create/compat/jei/category/SequencedAssemblyCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/SequencedAssemblyCategory.java index 1dbcd15ad..4a89ea1af 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/SequencedAssemblyCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/SequencedAssemblyCategory.java @@ -11,8 +11,8 @@ import org.jetbrains.annotations.NotNull; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.compat.jei.category.sequencedAssembly.SequencedAssemblySubCategory; -import com.simibubi.create.content.contraptions.itemAssembly.SequencedAssemblyRecipe; -import com.simibubi.create.content.contraptions.itemAssembly.SequencedRecipe; +import com.simibubi.create.content.processing.sequenced.SequencedAssemblyRecipe; +import com.simibubi.create.content.processing.sequenced.SequencedRecipe; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.utility.Components; diff --git a/src/main/java/com/simibubi/create/compat/jei/category/SpoutCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/SpoutCategory.java index 5f4f43160..58940cb79 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/SpoutCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/SpoutCategory.java @@ -8,10 +8,10 @@ import javax.annotation.ParametersAreNonnullByDefault; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.Create; import com.simibubi.create.compat.jei.category.animations.AnimatedSpout; -import com.simibubi.create.content.contraptions.fluids.actors.FillingRecipe; -import com.simibubi.create.content.contraptions.fluids.actors.GenericItemFilling; -import com.simibubi.create.content.contraptions.fluids.potion.PotionFluidHandler; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder; +import com.simibubi.create.content.fluids.potion.PotionFluidHandler; +import com.simibubi.create.content.fluids.transfer.FillingRecipe; +import com.simibubi.create.content.fluids.transfer.GenericItemFilling; +import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder; import com.simibubi.create.foundation.fluid.FluidIngredient; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.utility.RegisteredObjects; diff --git a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedBlazeBurner.java b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedBlazeBurner.java index a15702e24..a3e783fef 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedBlazeBurner.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedBlazeBurner.java @@ -4,10 +4,10 @@ import com.jozufozu.flywheel.core.PartialModel; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import com.mojang.math.Axis; -import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPartialModels; import com.simibubi.create.AllSpriteShifts; -import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.HeatLevel; +import com.simibubi.create.content.processing.burner.BlazeBurnerBlock.HeatLevel; import com.simibubi.create.foundation.block.render.SpriteShiftEntry; import com.simibubi.create.foundation.render.CachedBufferer; import com.simibubi.create.foundation.utility.AnimationTickHolder; @@ -42,9 +42,9 @@ public class AnimatedBlazeBurner extends AnimatedKinetics { .render(matrixStack); PartialModel blaze = - heatLevel == HeatLevel.SEETHING ? AllBlockPartials.BLAZE_SUPER : AllBlockPartials.BLAZE_ACTIVE; - PartialModel rods2 = heatLevel == HeatLevel.SEETHING ? AllBlockPartials.BLAZE_BURNER_SUPER_RODS_2 - : AllBlockPartials.BLAZE_BURNER_RODS_2; + heatLevel == HeatLevel.SEETHING ? AllPartialModels.BLAZE_SUPER : AllPartialModels.BLAZE_ACTIVE; + PartialModel rods2 = heatLevel == HeatLevel.SEETHING ? AllPartialModels.BLAZE_BURNER_SUPER_RODS_2 + : AllPartialModels.BLAZE_BURNER_RODS_2; blockElement(blaze).atLocal(1, 1.8, 1) .rotate(0, 180, 0) @@ -86,7 +86,7 @@ public class AnimatedBlazeBurner extends AnimatedKinetics { MultiBufferSource.BufferSource buffer = mc.renderBuffers() .bufferSource(); VertexConsumer vb = buffer.getBuffer(RenderType.cutoutMipped()); - CachedBufferer.partial(AllBlockPartials.BLAZE_BURNER_FLAME, Blocks.AIR.defaultBlockState()) + CachedBufferer.partial(AllPartialModels.BLAZE_BURNER_FLAME, Blocks.AIR.defaultBlockState()) .shiftUVScrolling(spriteShift, (float) uScroll, (float) vScroll) .light(LightTexture.FULL_BRIGHT) .renderInto(matrixStack, vb); diff --git a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedDeployer.java b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedDeployer.java index b82b78bf9..97462f47f 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedDeployer.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedDeployer.java @@ -2,9 +2,9 @@ package com.simibubi.create.compat.jei.category.animations; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Axis; -import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.components.deployer.DeployerBlock; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.deployer.DeployerBlock; import com.simibubi.create.foundation.utility.AnimationTickHolder; import net.minecraft.core.Direction; @@ -36,11 +36,11 @@ public class AnimatedDeployer extends AnimatedKinetics { matrixStack.pushPose(); matrixStack.translate(0, offset * 17, 0); - blockElement(AllBlockPartials.DEPLOYER_POLE) + blockElement(AllPartialModels.DEPLOYER_POLE) .rotateBlock(90, 0, 0) .scale(scale) .render(matrixStack); - blockElement(AllBlockPartials.DEPLOYER_HAND_HOLDING) + blockElement(AllPartialModels.DEPLOYER_HAND_HOLDING) .rotateBlock(90, 0, 0) .scale(scale) .render(matrixStack); diff --git a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedKinetics.java b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedKinetics.java index b78a6672a..3b7d9ce1d 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedKinetics.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedKinetics.java @@ -1,8 +1,8 @@ package com.simibubi.create.compat.jei.category.animations; import com.jozufozu.flywheel.core.PartialModel; -import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPartialModels; import com.simibubi.create.foundation.gui.CustomLightingSettings; import com.simibubi.create.foundation.gui.ILightingSettings; import com.simibubi.create.foundation.gui.element.GuiGameElement; @@ -49,7 +49,7 @@ public abstract class AnimatedKinetics implements IDrawable { } protected PartialModel cogwheel() { - return AllBlockPartials.SHAFTLESS_COGWHEEL; + return AllPartialModels.SHAFTLESS_COGWHEEL; } protected GuiGameElement.GuiRenderBuilder blockElement(BlockState state) { diff --git a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedMillstone.java b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedMillstone.java index 85ee7970c..33c1fce6b 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedMillstone.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedMillstone.java @@ -1,8 +1,8 @@ package com.simibubi.create.compat.jei.category.animations; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPartialModels; import com.simibubi.create.foundation.gui.AllGuiTextures; public class AnimatedMillstone extends AnimatedKinetics { @@ -15,7 +15,7 @@ public class AnimatedMillstone extends AnimatedKinetics { matrixStack.translate(-2, 18, 0); int scale = 22; - blockElement(AllBlockPartials.MILLSTONE_COG) + blockElement(AllPartialModels.MILLSTONE_COG) .rotateBlock(22.5, getCurrentAngle() * 2, 0) .scale(scale) .render(matrixStack); diff --git a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedMixer.java b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedMixer.java index 9c820e01f..6814a86ef 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedMixer.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedMixer.java @@ -2,8 +2,8 @@ package com.simibubi.create.compat.jei.category.animations; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Axis; -import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPartialModels; import com.simibubi.create.foundation.utility.AnimationTickHolder; import net.minecraft.util.Mth; @@ -31,12 +31,12 @@ public class AnimatedMixer extends AnimatedKinetics { float animation = ((Mth.sin(AnimationTickHolder.getRenderTime() / 32f) + 1) / 5) + .5f; - blockElement(AllBlockPartials.MECHANICAL_MIXER_POLE) + blockElement(AllPartialModels.MECHANICAL_MIXER_POLE) .atLocal(0, animation, 0) .scale(scale) .render(matrixStack); - blockElement(AllBlockPartials.MECHANICAL_MIXER_HEAD) + blockElement(AllPartialModels.MECHANICAL_MIXER_HEAD) .rotateBlock(0, getCurrentAngle() * 4, 0) .atLocal(0, animation, 0) .scale(scale) diff --git a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedPress.java b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedPress.java index a3c0dc589..f44511ffd 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedPress.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedPress.java @@ -2,8 +2,8 @@ package com.simibubi.create.compat.jei.category.animations; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Axis; -import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPartialModels; import com.simibubi.create.foundation.utility.AnimationTickHolder; import net.minecraft.core.Direction; @@ -33,7 +33,7 @@ public class AnimatedPress extends AnimatedKinetics { .scale(scale) .render(matrixStack); - blockElement(AllBlockPartials.MECHANICAL_PRESS_HEAD) + blockElement(AllPartialModels.MECHANICAL_PRESS_HEAD) .atLocal(0, -getAnimatedHeadOffset(), 0) .scale(scale) .render(matrixStack); diff --git a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedSaw.java b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedSaw.java index 45c91b8ce..f3ec25bb9 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedSaw.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedSaw.java @@ -2,9 +2,9 @@ package com.simibubi.create.compat.jei.category.animations; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Axis; -import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.components.saw.SawBlock; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.saw.SawBlock; import net.minecraft.core.Direction; @@ -31,7 +31,7 @@ public class AnimatedSaw extends AnimatedKinetics { .scale(scale) .render(matrixStack); - blockElement(AllBlockPartials.SAW_BLADE_VERTICAL_ACTIVE) + blockElement(AllPartialModels.SAW_BLADE_VERTICAL_ACTIVE) .rotateBlock(0, -90, -90) .scale(scale) .render(matrixStack); diff --git a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedSpout.java b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedSpout.java index cd227210a..49198f21c 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedSpout.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedSpout.java @@ -6,8 +6,8 @@ import com.mojang.blaze3d.platform.Lighting; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.Tesselator; import com.mojang.math.Axis; -import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPartialModels; import com.simibubi.create.foundation.fluid.FluidRenderer; import com.simibubi.create.foundation.gui.UIRenderHelper; import com.simibubi.create.foundation.utility.AnimationTickHolder; @@ -45,15 +45,15 @@ public class AnimatedSpout extends AnimatedKinetics { matrixStack.pushPose(); - blockElement(AllBlockPartials.SPOUT_TOP) + blockElement(AllPartialModels.SPOUT_TOP) .scale(scale) .render(matrixStack); matrixStack.translate(0, -3 * squeeze / 32f, 0); - blockElement(AllBlockPartials.SPOUT_MIDDLE) + blockElement(AllPartialModels.SPOUT_MIDDLE) .scale(scale) .render(matrixStack); matrixStack.translate(0, -3 * squeeze / 32f, 0); - blockElement(AllBlockPartials.SPOUT_BOTTOM) + blockElement(AllPartialModels.SPOUT_BOTTOM) .scale(scale) .render(matrixStack); matrixStack.translate(0, -3 * squeeze / 32f, 0); diff --git a/src/main/java/com/simibubi/create/compat/jei/category/sequencedAssembly/SequencedAssemblySubCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/sequencedAssembly/SequencedAssemblySubCategory.java index 26d76a540..b7682ce65 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/sequencedAssembly/SequencedAssemblySubCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/sequencedAssembly/SequencedAssemblySubCategory.java @@ -6,8 +6,8 @@ import com.simibubi.create.compat.jei.category.animations.AnimatedDeployer; import com.simibubi.create.compat.jei.category.animations.AnimatedPress; import com.simibubi.create.compat.jei.category.animations.AnimatedSaw; import com.simibubi.create.compat.jei.category.animations.AnimatedSpout; -import com.simibubi.create.content.contraptions.components.deployer.DeployerApplicationRecipe; -import com.simibubi.create.content.contraptions.itemAssembly.SequencedRecipe; +import com.simibubi.create.content.kinetics.deployer.DeployerApplicationRecipe; +import com.simibubi.create.content.processing.sequenced.SequencedRecipe; import com.simibubi.create.foundation.fluid.FluidIngredient; import com.simibubi.create.foundation.utility.Lang; diff --git a/src/main/java/com/simibubi/create/compat/storageDrawers/StorageDrawers.java b/src/main/java/com/simibubi/create/compat/storageDrawers/StorageDrawers.java index cfe11969f..5f4731aee 100644 --- a/src/main/java/com/simibubi/create/compat/storageDrawers/StorageDrawers.java +++ b/src/main/java/com/simibubi/create/compat/storageDrawers/StorageDrawers.java @@ -1,7 +1,7 @@ package com.simibubi.create.compat.storageDrawers; import com.simibubi.create.compat.Mods; -import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.entity.BlockEntity; @@ -10,9 +10,9 @@ import net.minecraftforge.items.IItemHandler; public class StorageDrawers { - public static boolean isDrawer(BlockEntity tile) { - return tile != null && Mods.STORAGEDRAWERS.asId() - .equals(BlockEntityType.getKey(tile.getType()) + public static boolean isDrawer(BlockEntity be) { + return be != null && Mods.STORAGEDRAWERS.asId() + .equals(BlockEntityType.getKey(be.getType()) .getNamespace()); } diff --git a/src/main/java/com/simibubi/create/compat/tconstruct/SpoutCasting.java b/src/main/java/com/simibubi/create/compat/tconstruct/SpoutCasting.java index ccf2a8bac..65e26042f 100644 --- a/src/main/java/com/simibubi/create/compat/tconstruct/SpoutCasting.java +++ b/src/main/java/com/simibubi/create/compat/tconstruct/SpoutCasting.java @@ -2,10 +2,10 @@ package com.simibubi.create.compat.tconstruct; import com.simibubi.create.api.behaviour.BlockSpoutingBehaviour; import com.simibubi.create.compat.Mods; -import com.simibubi.create.content.contraptions.fluids.actors.SpoutTileEntity; -import com.simibubi.create.foundation.config.AllConfigs; +import com.simibubi.create.content.fluids.spout.SpoutBlockEntity; import com.simibubi.create.foundation.fluid.FluidHelper; import com.simibubi.create.foundation.utility.RegisteredObjects; +import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -25,23 +25,23 @@ public class SpoutCasting extends BlockSpoutingBehaviour { ResourceLocation BASIN = new ResourceLocation("tconstruct", "basin"); @Override - public int fillBlock(Level level, BlockPos pos, SpoutTileEntity spout, FluidStack availableFluid, + public int fillBlock(Level level, BlockPos pos, SpoutBlockEntity spout, FluidStack availableFluid, boolean simulate) { if (!enabled()) return 0; - BlockEntity te = level.getBlockEntity(pos); - if (te == null) + BlockEntity blockEntity = level.getBlockEntity(pos); + if (blockEntity == null) return 0; - IFluidHandler handler = te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, Direction.UP) + IFluidHandler handler = blockEntity.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, Direction.UP) .orElse(null); if (handler == null) return 0; if (handler.getTanks() != 1) return 0; - ResourceLocation registryName = RegisteredObjects.getKeyOrThrow(te.getType()); + ResourceLocation registryName = RegisteredObjects.getKeyOrThrow(blockEntity.getType()); if (!registryName.equals(TABLE) && !registryName.equals(BASIN)) return 0; if (!handler.isFluidValid(0, availableFluid)) @@ -66,7 +66,7 @@ public class SpoutCasting extends BlockSpoutingBehaviour { TICON_PRESENT = Mods.TCONSTRUCT.isLoaded(); if (!TICON_PRESENT) return false; - return AllConfigs.SERVER.recipes.allowCastingBySpout.get(); + return AllConfigs.server().recipes.allowCastingBySpout.get(); } } diff --git a/src/main/java/com/simibubi/create/content/AllSections.java b/src/main/java/com/simibubi/create/content/AllSections.java deleted file mode 100644 index 628b98b3e..000000000 --- a/src/main/java/com/simibubi/create/content/AllSections.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.simibubi.create.content; - -import com.simibubi.create.Create; -import com.simibubi.create.foundation.item.ItemDescription.Palette; - -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.Block; - -public enum AllSections { - - /** Create's kinetic mechanisms */ - KINETICS(Palette.Red), - - /** Item transport and other Utility */ - LOGISTICS(Palette.Yellow), - - /** Tools for structure movement and replication */ - SCHEMATICS(Palette.Blue), - - /** Decorative blocks */ - PALETTES(Palette.Green), - - /** Helpful gadgets and other shenanigans */ - CURIOSITIES(Palette.Purple), - - /** Base materials, ingredients and tools */ - MATERIALS(Palette.Green), - - /** Fallback section */ - UNASSIGNED(Palette.Gray) - - ; - - private final Palette tooltipPalette; - - private AllSections(Palette tooltipPalette) { - this.tooltipPalette = tooltipPalette; - } - - public Palette getTooltipPalette() { - return tooltipPalette; - } - - public static AllSections of(ItemStack stack) { - Item item = stack.getItem(); - if (item instanceof BlockItem) - return ofBlock(((BlockItem) item).getBlock()); - return ofItem(item); - } - - static AllSections ofItem(Item item) { - return Create.REGISTRATE - .getSection(item); - } - - static AllSections ofBlock(Block block) { - return Create.REGISTRATE - .getSection(block); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java b/src/main/java/com/simibubi/create/content/contraptions/AbstractContraptionEntity.java similarity index 92% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java rename to src/main/java/com/simibubi/create/content/contraptions/AbstractContraptionEntity.java index b84fa3cf1..72d222792 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/AbstractContraptionEntity.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.structureMovement; +package com.simibubi.create.content.contraptions; import java.util.Collection; import java.util.IdentityHashMap; @@ -16,26 +16,28 @@ import org.apache.commons.lang3.tuple.MutablePair; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllItems; import com.simibubi.create.AllMovementBehaviours; +import com.simibubi.create.AllPackets; import com.simibubi.create.AllSoundEvents; import com.simibubi.create.Create; -import com.simibubi.create.content.contraptions.components.actors.PortableStorageInterfaceMovement; -import com.simibubi.create.content.contraptions.components.actors.SeatBlock; -import com.simibubi.create.content.contraptions.components.actors.SeatEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsStopControllingPacket; -import com.simibubi.create.content.contraptions.components.structureMovement.mounted.MountedContraption; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; -import com.simibubi.create.content.contraptions.components.structureMovement.sync.ContraptionSeatMappingPacket; -import com.simibubi.create.content.curiosities.deco.SlidingDoorBlock; -import com.simibubi.create.content.logistics.trains.entity.CarriageContraption; -import com.simibubi.create.content.logistics.trains.entity.CarriageContraptionEntity; -import com.simibubi.create.content.logistics.trains.entity.Train; +import com.simibubi.create.content.contraptions.actors.psi.PortableStorageInterfaceMovement; +import com.simibubi.create.content.contraptions.actors.seat.SeatBlock; +import com.simibubi.create.content.contraptions.actors.seat.SeatEntity; +import com.simibubi.create.content.contraptions.actors.trainControls.ControlsStopControllingPacket; +import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.contraptions.elevator.ElevatorContraption; +import com.simibubi.create.content.contraptions.glue.SuperGlueEntity; +import com.simibubi.create.content.contraptions.mounted.MountedContraption; +import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher; +import com.simibubi.create.content.contraptions.sync.ContraptionSeatMappingPacket; +import com.simibubi.create.content.decoration.slidingDoor.SlidingDoorBlock; +import com.simibubi.create.content.trains.entity.CarriageContraption; +import com.simibubi.create.content.trains.entity.CarriageContraptionEntity; +import com.simibubi.create.content.trains.entity.Train; import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.collision.Matrix3d; import com.simibubi.create.foundation.mixin.accessor.ServerLevelAccessor; -import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.ContraptionData; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.client.Minecraft; @@ -127,7 +129,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit } public boolean supportsTerrainCollision() { - return contraption instanceof TranslatingContraption; + return contraption instanceof TranslatingContraption && !(contraption instanceof ElevatorContraption); } protected void contraptionInitialize() { @@ -162,7 +164,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit return; contraption.getSeatMapping() .put(passenger.getUUID(), seatIndex); - AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this), + AllPackets.getChannel().send(PacketDistributor.TRACKING_ENTITY.with(() -> this), new ContraptionSeatMappingPacket(getId(), contraption.getSeatMapping())); } @@ -179,7 +181,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit .put("ContraptionDismountLocation", VecHelper.writeNBT(transformedVector)); contraption.getSeatMapping() .remove(passenger.getUUID()); - AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this), + AllPackets.getChannel().send(PacketDistributor.TRACKING_ENTITY.with(() -> this), new ContraptionSeatMappingPacket(getId(), contraption.getSeatMapping(), passenger.getId())); } @@ -269,7 +271,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit public void stopControlling(BlockPos controlsLocalPos) { getControllingPlayer().map(level::getPlayerByUUID) .map(p -> (p instanceof ServerPlayer) ? ((ServerPlayer) p) : null) - .ifPresent(p -> AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> p), + .ifPresent(p -> AllPackets.getChannel().send(PacketDistributor.PLAYER.with(() -> p), new ControlsStopControllingPacket())); setControllingPlayer(null); } @@ -278,9 +280,12 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit InteractionHand interactionHand) { int indexOfSeat = contraption.getSeats() .indexOf(localPos); - if (indexOfSeat == -1 || AllItems.WRENCH.isIn(player.getItemInHand(interactionHand))) - return contraption.interactors.containsKey(localPos) && contraption.interactors.get(localPos) - .handlePlayerInteraction(player, interactionHand, localPos, this); + if (indexOfSeat == -1 || AllItems.WRENCH.isIn(player.getItemInHand(interactionHand))) { + if (contraption.interactors.containsKey(localPos)) + return contraption.interactors.get(localPos) + .handlePlayerInteraction(player, interactionHand, localPos, this); + return contraption.storage.handlePlayerStorageInteraction(contraption, player, localPos); + } if (player.isPassenger()) return false; @@ -412,7 +417,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit public void setBlock(BlockPos localPos, StructureBlockInfo newInfo) { contraption.blocks.put(localPos, newInfo); - AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this), + AllPackets.getChannel().send(PacketDistributor.TRACKING_ENTITY.with(() -> this), new ContraptionBlockChangedPacket(getId(), localPos, newInfo.state)); } @@ -446,7 +451,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit context.rotation = v -> applyRotation(v, 1); context.position = actorPosition; - if (!isActorActive(context, actor)) + if (!isActorActive(context, actor) && !actor.mustTickWhileDisabled()) continue; if (newPosVisited && !context.stall) { actor.visitNewPosition(context, gridPosition); @@ -508,7 +513,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit } protected void onContraptionStalled() { - AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this), + AllPackets.getChannel().send(PacketDistributor.TRACKING_ENTITY.with(() -> this), new ContraptionStallPacket(getId(), getX(), getY(), getZ(), getStalledAngle())); } @@ -649,7 +654,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit StructureTransform transform = makeStructureTransform(); contraption.stop(level); - AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this), + AllPackets.getChannel().send(PacketDistributor.TRACKING_ENTITY.with(() -> this), new ContraptionDisassemblyPacket(this.getId(), transform)); contraption.addBlocksToWorld(level, transform); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AssemblyException.java b/src/main/java/com/simibubi/create/content/contraptions/AssemblyException.java similarity index 88% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AssemblyException.java rename to src/main/java/com/simibubi/create/content/contraptions/AssemblyException.java index 630d563b1..8bb1675d4 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AssemblyException.java +++ b/src/main/java/com/simibubi/create/content/contraptions/AssemblyException.java @@ -1,7 +1,7 @@ -package com.simibubi.create.content.contraptions.components.structureMovement; +package com.simibubi.create.content.contraptions; -import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; @@ -62,11 +62,11 @@ public class AssemblyException extends Exception { } public static AssemblyException structureTooLarge() { - return new AssemblyException("structureTooLarge", AllConfigs.SERVER.kinetics.maxBlocksMoved.get()); + return new AssemblyException("structureTooLarge", AllConfigs.server().kinetics.maxBlocksMoved.get()); } public static AssemblyException tooManyPistonPoles() { - return new AssemblyException("tooManyPistonPoles", AllConfigs.SERVER.kinetics.maxPistonPoles.get()); + return new AssemblyException("tooManyPistonPoles", AllConfigs.server().kinetics.maxPistonPoles.get()); } public static AssemblyException noPistonPoles() { @@ -74,7 +74,7 @@ public class AssemblyException extends Exception { } public static AssemblyException notEnoughSails(int sails) { - return new AssemblyException("not_enough_sails", sails, AllConfigs.SERVER.kinetics.minimumWindmillSails.get()); + return new AssemblyException("not_enough_sails", sails, AllConfigs.server().kinetics.minimumWindmillSails.get()); } public boolean hasPosition() { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/BlockMovementChecks.java b/src/main/java/com/simibubi/create/content/contraptions/BlockMovementChecks.java similarity index 80% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/BlockMovementChecks.java rename to src/main/java/com/simibubi/create/content/contraptions/BlockMovementChecks.java index ce06099e4..0a223944d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/BlockMovementChecks.java +++ b/src/main/java/com/simibubi/create/content/contraptions/BlockMovementChecks.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.structureMovement; +package com.simibubi.create.content.contraptions; import java.util.ArrayList; import java.util.List; @@ -6,34 +6,32 @@ import java.util.List; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllTags.AllBlockTags; import com.simibubi.create.api.connectivity.ConnectivityHandler; -import com.simibubi.create.content.contraptions.components.actors.AttachedActorBlock; -import com.simibubi.create.content.contraptions.components.actors.HarvesterBlock; -import com.simibubi.create.content.contraptions.components.actors.PloughBlock; -import com.simibubi.create.content.contraptions.components.actors.PortableStorageInterfaceBlock; -import com.simibubi.create.content.contraptions.components.crank.HandCrankBlock; -import com.simibubi.create.content.contraptions.components.fan.NozzleBlock; -import com.simibubi.create.content.contraptions.components.steam.whistle.WhistleBlock; -import com.simibubi.create.content.contraptions.components.steam.whistle.WhistleExtenderBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.ClockworkBearingBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.ClockworkBearingTileEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.MechanicalBearingBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.MechanicalBearingTileEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.SailBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.chassis.AbstractChassisBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.chassis.StickerBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.PistonState; -import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyTileEntity; -import com.simibubi.create.content.contraptions.fluids.tank.FluidTankBlock; -import com.simibubi.create.content.curiosities.deco.SlidingDoorBlock; -import com.simibubi.create.content.logistics.block.redstone.RedstoneLinkBlock; -import com.simibubi.create.content.logistics.block.vault.ItemVaultBlock; -import com.simibubi.create.content.logistics.trains.IBogeyBlock; -import com.simibubi.create.content.logistics.trains.ITrackBlock; -import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationBlock; -import com.simibubi.create.foundation.config.ContraptionMovementSetting; +import com.simibubi.create.content.contraptions.actors.AttachedActorBlock; +import com.simibubi.create.content.contraptions.actors.harvester.HarvesterBlock; +import com.simibubi.create.content.contraptions.actors.psi.PortableStorageInterfaceBlock; +import com.simibubi.create.content.contraptions.bearing.ClockworkBearingBlock; +import com.simibubi.create.content.contraptions.bearing.ClockworkBearingBlockEntity; +import com.simibubi.create.content.contraptions.bearing.MechanicalBearingBlock; +import com.simibubi.create.content.contraptions.bearing.MechanicalBearingBlockEntity; +import com.simibubi.create.content.contraptions.bearing.SailBlock; +import com.simibubi.create.content.contraptions.chassis.AbstractChassisBlock; +import com.simibubi.create.content.contraptions.chassis.StickerBlock; +import com.simibubi.create.content.contraptions.mounted.CartAssemblerBlock; +import com.simibubi.create.content.contraptions.piston.MechanicalPistonBlock; +import com.simibubi.create.content.contraptions.piston.MechanicalPistonBlock.PistonState; +import com.simibubi.create.content.contraptions.pulley.PulleyBlock; +import com.simibubi.create.content.contraptions.pulley.PulleyBlockEntity; +import com.simibubi.create.content.decoration.slidingDoor.SlidingDoorBlock; +import com.simibubi.create.content.decoration.steamWhistle.WhistleBlock; +import com.simibubi.create.content.decoration.steamWhistle.WhistleExtenderBlock; +import com.simibubi.create.content.fluids.tank.FluidTankBlock; +import com.simibubi.create.content.kinetics.crank.HandCrankBlock; +import com.simibubi.create.content.kinetics.fan.NozzleBlock; +import com.simibubi.create.content.logistics.vault.ItemVaultBlock; +import com.simibubi.create.content.redstone.link.RedstoneLinkBlock; +import com.simibubi.create.content.trains.bogey.AbstractBogeyBlock; +import com.simibubi.create.content.trains.station.StationBlock; +import com.simibubi.create.content.trains.track.ITrackBlock; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -174,13 +172,15 @@ public class BlockMovementChecks { private static boolean isMovementNecessaryFallback(BlockState state, Level world, BlockPos pos) { if (isBrittle(state)) return true; - if (!state.getMaterial() - .isReplaceable()) + if (AllBlockTags.MOVABLE_EMPTY_COLLIDER.matches(state)) return true; - if (!state.getCollisionShape(world, pos) + if (state.getCollisionShape(world, pos) .isEmpty()) - return true; - return AllBlockTags.MOVABLE_EMPTY_COLLIDER.matches(state); + return false; + if (state.getMaterial() + .isReplaceable()) + return false; + return true; } private static boolean isMovementAllowedFallback(BlockState state, Level world, BlockPos pos) { @@ -200,19 +200,19 @@ public class BlockMovementChecks { if (block instanceof MechanicalPistonBlock && state.getValue(MechanicalPistonBlock.STATE) != PistonState.MOVING) return true; if (block instanceof MechanicalBearingBlock) { - BlockEntity te = world.getBlockEntity(pos); - if (te instanceof MechanicalBearingTileEntity) - return !((MechanicalBearingTileEntity) te).isRunning(); + BlockEntity be = world.getBlockEntity(pos); + if (be instanceof MechanicalBearingBlockEntity) + return !((MechanicalBearingBlockEntity) be).isRunning(); } if (block instanceof ClockworkBearingBlock) { - BlockEntity te = world.getBlockEntity(pos); - if (te instanceof ClockworkBearingTileEntity) - return !((ClockworkBearingTileEntity) te).isRunning(); + BlockEntity be = world.getBlockEntity(pos); + if (be instanceof ClockworkBearingBlockEntity) + return !((ClockworkBearingBlockEntity) be).isRunning(); } if (block instanceof PulleyBlock) { - BlockEntity te = world.getBlockEntity(pos); - if (te instanceof PulleyTileEntity) - return !((PulleyTileEntity) te).running; + BlockEntity be = world.getBlockEntity(pos); + if (be instanceof PulleyBlockEntity) + return !((PulleyBlockEntity) be).running; } if (AllBlocks.BELT.has(state)) @@ -337,7 +337,7 @@ public class BlockMovementChecks { return direction == state.getValue(StickerBlock.FACING) && !isNotSupportive(world.getBlockState(pos.relative(direction)), direction.getOpposite()); } - if (block instanceof IBogeyBlock bogey) + if (block instanceof AbstractBogeyBlock bogey) return bogey.getStickySurfaces(world, pos, state) .contains(direction); if (block instanceof WhistleBlock) @@ -353,10 +353,6 @@ public class BlockMovementChecks { return state.getValue(BlockStateProperties.FACING) == facing; if (AllBlocks.MECHANICAL_BEARING.has(state)) return state.getValue(BlockStateProperties.FACING) == facing; - if (AllBlocks.MECHANICAL_HARVESTER.has(state)) - return state.getValue(HarvesterBlock.FACING) == facing; - if (AllBlocks.MECHANICAL_PLOUGH.has(state)) - return state.getValue(PloughBlock.FACING) == facing; if (AllBlocks.CART_ASSEMBLER.has(state)) return Direction.DOWN == facing; @@ -364,7 +360,7 @@ public class BlockMovementChecks { return state.getValue(BlockStateProperties.FACING) == facing; if (AllBlocks.PORTABLE_STORAGE_INTERFACE.has(state)) return state.getValue(PortableStorageInterfaceBlock.FACING) == facing; - if (state.getBlock() instanceof AttachedActorBlock) + if (state.getBlock() instanceof AttachedActorBlock && !AllBlocks.MECHANICAL_ROLLER.has(state)) return state.getValue(BlockStateProperties.HORIZONTAL_FACING) == facing; if (AllBlocks.ROPE_PULLEY.has(state)) return facing == Direction.DOWN; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/Contraption.java b/src/main/java/com/simibubi/create/content/contraptions/Contraption.java similarity index 83% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/Contraption.java rename to src/main/java/com/simibubi/create/content/contraptions/Contraption.java index da57caced..7e9805f66 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/Contraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/Contraption.java @@ -1,7 +1,7 @@ -package com.simibubi.create.content.contraptions.components.structureMovement; +package com.simibubi.create.content.contraptions; -import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isExtensionPole; -import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isPistonHead; +import static com.simibubi.create.content.contraptions.piston.MechanicalPistonBlock.isExtensionPole; +import static com.simibubi.create.content.contraptions.piston.MechanicalPistonBlock.isPistonHead; import java.util.ArrayList; import java.util.Collection; @@ -24,49 +24,52 @@ import javax.annotation.Nullable; import org.apache.commons.lang3.tuple.MutablePair; import org.apache.commons.lang3.tuple.Pair; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllInteractionBehaviours; import com.simibubi.create.AllMovementBehaviours; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.IRotate; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.components.actors.BlockBreakingMovementBehaviour; -import com.simibubi.create.content.contraptions.components.actors.HarvesterMovementBehaviour; -import com.simibubi.create.content.contraptions.components.actors.SeatBlock; -import com.simibubi.create.content.contraptions.components.actors.SeatEntity; -import com.simibubi.create.content.contraptions.components.steam.PoweredShaftTileEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.MechanicalBearingBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.StabilizedContraption; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.WindmillBearingBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.WindmillBearingTileEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.chassis.AbstractChassisBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.chassis.ChassisTileEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.chassis.StickerBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.gantry.GantryCarriageBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.PistonState; -import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonHeadBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.piston.PistonExtensionPoleBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyBlock.MagnetBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyBlock.RopeBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyTileEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionLighter; -import com.simibubi.create.content.contraptions.components.structureMovement.render.EmptyLighter; -import com.simibubi.create.content.contraptions.fluids.tank.FluidTankTileEntity; -import com.simibubi.create.content.contraptions.relays.advanced.GantryShaftBlock; -import com.simibubi.create.content.contraptions.relays.belt.BeltBlock; -import com.simibubi.create.content.contraptions.relays.elementary.ShaftBlock; -import com.simibubi.create.content.curiosities.deco.SlidingDoorBlock; -import com.simibubi.create.content.logistics.block.inventories.CreativeCrateTileEntity; -import com.simibubi.create.content.logistics.block.redstone.RedstoneContactBlock; -import com.simibubi.create.content.logistics.block.vault.ItemVaultTileEntity; -import com.simibubi.create.content.logistics.trains.IBogeyBlock; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.tileEntity.IMultiTileContainer; -import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.content.contraptions.actors.contraptionControls.ContraptionControlsMovement; +import com.simibubi.create.content.contraptions.actors.harvester.HarvesterMovementBehaviour; +import com.simibubi.create.content.contraptions.actors.seat.SeatBlock; +import com.simibubi.create.content.contraptions.actors.seat.SeatEntity; +import com.simibubi.create.content.contraptions.actors.trainControls.ControlsBlock; +import com.simibubi.create.content.contraptions.bearing.MechanicalBearingBlock; +import com.simibubi.create.content.contraptions.bearing.StabilizedContraption; +import com.simibubi.create.content.contraptions.bearing.WindmillBearingBlock; +import com.simibubi.create.content.contraptions.bearing.WindmillBearingBlockEntity; +import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.contraptions.behaviour.MovingInteractionBehaviour; +import com.simibubi.create.content.contraptions.chassis.AbstractChassisBlock; +import com.simibubi.create.content.contraptions.chassis.ChassisBlockEntity; +import com.simibubi.create.content.contraptions.chassis.StickerBlock; +import com.simibubi.create.content.contraptions.gantry.GantryCarriageBlock; +import com.simibubi.create.content.contraptions.glue.SuperGlueEntity; +import com.simibubi.create.content.contraptions.piston.MechanicalPistonBlock; +import com.simibubi.create.content.contraptions.piston.MechanicalPistonBlock.PistonState; +import com.simibubi.create.content.contraptions.piston.MechanicalPistonHeadBlock; +import com.simibubi.create.content.contraptions.piston.PistonExtensionPoleBlock; +import com.simibubi.create.content.contraptions.pulley.PulleyBlock; +import com.simibubi.create.content.contraptions.pulley.PulleyBlock.MagnetBlock; +import com.simibubi.create.content.contraptions.pulley.PulleyBlock.RopeBlock; +import com.simibubi.create.content.contraptions.pulley.PulleyBlockEntity; +import com.simibubi.create.content.contraptions.render.ContraptionLighter; +import com.simibubi.create.content.contraptions.render.EmptyLighter; +import com.simibubi.create.content.decoration.slidingDoor.SlidingDoorBlock; +import com.simibubi.create.content.fluids.tank.FluidTankBlockEntity; +import com.simibubi.create.content.kinetics.base.BlockBreakingMovementBehaviour; +import com.simibubi.create.content.kinetics.base.IRotate; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.belt.BeltBlock; +import com.simibubi.create.content.kinetics.gantry.GantryShaftBlock; +import com.simibubi.create.content.kinetics.simpleRelays.ShaftBlock; +import com.simibubi.create.content.kinetics.steamEngine.PoweredShaftBlockEntity; +import com.simibubi.create.content.logistics.crate.CreativeCrateBlockEntity; +import com.simibubi.create.content.logistics.vault.ItemVaultBlockEntity; +import com.simibubi.create.content.redstone.contact.RedstoneContactBlock; +import com.simibubi.create.content.trains.bogey.AbstractBogeyBlock; +import com.simibubi.create.foundation.blockEntity.IMultiBlockEntityContainer; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; import com.simibubi.create.foundation.utility.BBHelper; import com.simibubi.create.foundation.utility.BlockFace; import com.simibubi.create.foundation.utility.BlockHelper; @@ -75,6 +78,7 @@ import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.NBTProcessors; import com.simibubi.create.foundation.utility.UniqueLinkedList; +import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -89,6 +93,7 @@ import net.minecraft.network.protocol.game.DebugPackets; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.ai.village.poi.PoiTypes; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.Block; @@ -139,6 +144,8 @@ public abstract class Contraption { protected Map blocks; protected List> actors; protected Map interactors; + protected List disabledActors; + protected List superglue; protected List seats; protected Map seatMapping; @@ -153,9 +160,9 @@ public abstract class Contraption { // Client public Map modelData; - public Map presentTileEntities; - public List maybeInstancedTileEntities; - public List specialRenderedTileEntities; + public Map presentBlockEntities; + public List maybeInstancedBlockEntities; + public List specialRenderedBlockEntities; protected ContraptionWorld world; public boolean deferInvalidate; @@ -164,15 +171,16 @@ public abstract class Contraption { blocks = new HashMap<>(); seats = new ArrayList<>(); actors = new ArrayList<>(); + disabledActors = new ArrayList<>(); modelData = new HashMap<>(); interactors = new HashMap<>(); superglue = new ArrayList<>(); seatMapping = new HashMap<>(); glueToRemove = new HashSet<>(); initialPassengers = new HashMap<>(); - presentTileEntities = new HashMap<>(); - maybeInstancedTileEntities = new ArrayList<>(); - specialRenderedTileEntities = new ArrayList<>(); + presentBlockEntities = new HashMap<>(); + maybeInstancedBlockEntities = new ArrayList<>(); + specialRenderedBlockEntities = new ArrayList<>(); pendingSubContraptions = new ArrayList<>(); stabilizedSubContraptions = new HashMap<>(); simplifiedEntityColliders = Optional.empty(); @@ -189,7 +197,7 @@ public abstract class Contraption { public abstract boolean canBeStabilized(Direction facing, BlockPos localPos); - protected abstract ContraptionType getType(); + public abstract ContraptionType getType(); protected boolean customBlockPlacement(LevelAccessor world, BlockPos pos, BlockState state) { return false; @@ -317,8 +325,8 @@ public abstract class Contraption { if (AllBlocks.BELT.has(state)) moveBelt(pos, frontier, visited, state); - if (AllBlocks.WINDMILL_BEARING.has(state) && world.getBlockEntity(pos)instanceof WindmillBearingTileEntity wbte) - wbte.disassembleForMovement(); + if (AllBlocks.WINDMILL_BEARING.has(state) && world.getBlockEntity(pos)instanceof WindmillBearingBlockEntity wbbe) + wbbe.disassembleForMovement(); if (AllBlocks.GANTRY_CARRIAGE.has(state)) moveGantryPinion(world, pos, frontier, visited, state); @@ -344,7 +352,7 @@ public abstract class Contraption { } // Bogeys tend to have sticky sides - if (state.getBlock()instanceof IBogeyBlock bogey) + if (state.getBlock()instanceof AbstractBogeyBlock bogey) for (Direction d : bogey.getStickySurfaces(world, pos, state)) if (!visited.contains(pos.relative(d))) frontier.add(pos.relative(d)); @@ -417,7 +425,7 @@ public abstract class Contraption { } addBlock(pos, capture(world, pos)); - if (blocks.size() <= AllConfigs.SERVER.kinetics.maxBlocksMoved.get()) + if (blocks.size() <= AllConfigs.server().kinetics.maxBlocksMoved.get()) return true; else throw AssemblyException.structureTooLarge(); @@ -542,7 +550,7 @@ public abstract class Contraption { } private void movePulley(Level world, BlockPos pos, Queue frontier, Set visited) { - int limit = AllConfigs.SERVER.kinetics.maxRopeLength.get(); + int limit = AllConfigs.server().kinetics.maxRopeLength.get(); BlockPos ropePos = pos; while (limit-- >= 0) { ropePos = ropePos.below(); @@ -585,10 +593,10 @@ public abstract class Contraption { private boolean moveChassis(Level world, BlockPos pos, Direction movementDirection, Queue frontier, Set visited) { - BlockEntity te = world.getBlockEntity(pos); - if (!(te instanceof ChassisTileEntity)) + BlockEntity be = world.getBlockEntity(pos); + if (!(be instanceof ChassisBlockEntity)) return false; - ChassisTileEntity chassis = (ChassisTileEntity) te; + ChassisBlockEntity chassis = (ChassisBlockEntity) be; chassis.addAttachedChasses(frontier, visited); List includedBlockPositions = chassis.getIncludedBlockPositions(movementDirection, false); if (includedBlockPositions == null) @@ -605,7 +613,7 @@ public abstract class Contraption { blockstate = blockstate.setValue(RedstoneContactBlock.POWERED, true); if (AllBlocks.POWERED_SHAFT.has(blockstate)) blockstate = BlockHelper.copyProperties(blockstate, AllBlocks.SHAFT.getDefaultState()); - if (AllBlocks.CONTROLS.has(blockstate)) + if (blockstate.getBlock() instanceof ControlsBlock && getType() == ContraptionType.CARRIAGE) blockstate = blockstate.setValue(ControlsBlock.OPEN, true); if (blockstate.hasProperty(SlidingDoorBlock.VISIBLE)) blockstate = blockstate.setValue(SlidingDoorBlock.VISIBLE, false); @@ -617,11 +625,11 @@ public abstract class Contraption { blockstate = blockstate.setValue(PressurePlateBlock.POWERED, false); world.scheduleTick(pos, blockstate.getBlock(), -1); } - CompoundTag compoundnbt = getTileEntityNBT(world, pos); - BlockEntity tileentity = world.getBlockEntity(pos); - if (tileentity instanceof PoweredShaftTileEntity) - tileentity = AllTileEntities.BRACKETED_KINETIC.create(pos, blockstate); - return Pair.of(new StructureBlockInfo(pos, blockstate, compoundnbt), tileentity); + CompoundTag compoundnbt = getBlockEntityNBT(world, pos); + BlockEntity blockEntity = world.getBlockEntity(pos); + if (blockEntity instanceof PoweredShaftBlockEntity) + blockEntity = AllBlockEntityTypes.BRACKETED_KINETIC.create(pos, blockstate); + return Pair.of(new StructureBlockInfo(pos, blockstate, compoundnbt), blockEntity); } protected void addBlock(BlockPos pos, Pair pair) { @@ -633,8 +641,8 @@ public abstract class Contraption { return; bounds = bounds.minmax(new AABB(localPos)); - BlockEntity te = pair.getValue(); - storage.addBlock(localPos, te); + BlockEntity be = pair.getValue(); + storage.addBlock(localPos, be); if (AllMovementBehaviours.getBehaviour(captured.state) != null) actors.add(MutablePair.of(structureBlockInfo, null)); @@ -643,24 +651,24 @@ public abstract class Contraption { if (interactionBehaviour != null) interactors.put(localPos, interactionBehaviour); - if (te instanceof CreativeCrateTileEntity - && ((CreativeCrateTileEntity) te).getBehaviour(FilteringBehaviour.TYPE) + if (be instanceof CreativeCrateBlockEntity + && ((CreativeCrateBlockEntity) be).getBehaviour(FilteringBehaviour.TYPE) .getFilter() .isEmpty()) hasUniversalCreativeCrate = true; } @Nullable - protected CompoundTag getTileEntityNBT(Level world, BlockPos pos) { - BlockEntity tileentity = world.getBlockEntity(pos); - if (tileentity == null) + protected CompoundTag getBlockEntityNBT(Level world, BlockPos pos) { + BlockEntity blockEntity = world.getBlockEntity(pos); + if (blockEntity == null) return null; - CompoundTag nbt = tileentity.saveWithFullMetadata(); + CompoundTag nbt = blockEntity.saveWithFullMetadata(); nbt.remove("x"); nbt.remove("y"); nbt.remove("z"); - if ((tileentity instanceof FluidTankTileEntity || tileentity instanceof ItemVaultTileEntity) + if ((blockEntity instanceof FluidTankBlockEntity || blockEntity instanceof ItemVaultBlockEntity) && nbt.contains("Controller")) nbt.put("Controller", NbtUtils.writeBlockPos(toLocalPos(NbtUtils.readBlockPos(nbt.getCompound("Controller"))))); @@ -682,8 +690,8 @@ public abstract class Contraption { public void readNBT(Level world, CompoundTag nbt, boolean spawnData) { blocks.clear(); - presentTileEntities.clear(); - specialRenderedTileEntities.clear(); + presentBlockEntities.clear(); + specialRenderedBlockEntities.clear(); Tag blocks = nbt.get("Blocks"); // used to differentiate between the 'old' and the paletted serialization @@ -702,6 +710,10 @@ public abstract class Contraption { getActors().add(MutablePair.of(info, context)); }); + disabledActors = NBTHelper.readItemList(nbt.getList("DisabledActors", Tag.TAG_COMPOUND)); + for (ItemStack stack : disabledActors) + setActorsActive(stack, false); + superglue.clear(); NBTHelper.iterateCompoundList(nbt.getList("Superglue", Tag.TAG_COMPOUND), c -> superglue.add(SuperGlueEntity.readBoundingBox(c))); @@ -728,7 +740,7 @@ public abstract class Contraption { interactors.put(pos, behaviour); }); - storage.read(nbt, presentTileEntities, spawnData); + storage.read(nbt, presentBlockEntities, spawnData); if (nbt.contains("BoundsFront")) bounds = NBTHelper.readAABB(nbt.getList("BoundsFront", 5)); @@ -756,6 +768,8 @@ public abstract class Contraption { actorsNBT.add(compound); } + ListTag disabledActorsNBT = NBTHelper.writeItemList(disabledActors); + ListTag superglueNBT = new ListTag(); if (!spawnPacket) { for (AABB glueEntry : superglue) { @@ -792,6 +806,7 @@ public abstract class Contraption { nbt.put("Blocks", blocksNBT); nbt.put("Actors", actorsNBT); + nbt.put("DisabledActors", disabledActorsNBT); nbt.put("Interactors", interactorNBT); nbt.put("Superglue", superglueNBT); nbt.put("Anchor", NbtUtils.writeBlockPos(anchor)); @@ -877,24 +892,24 @@ public abstract class Contraption { tag.putInt("y", info.pos.getY()); tag.putInt("z", info.pos.getZ()); - BlockEntity te = BlockEntity.loadStatic(info.pos, info.state, tag); - if (te == null) + BlockEntity be = BlockEntity.loadStatic(info.pos, info.state, tag); + if (be == null) return; - te.setLevel(world); - modelData.put(info.pos, te.getModelData()); - if (te instanceof KineticTileEntity kte) - kte.setSpeed(0); - te.getBlockState(); + be.setLevel(world); + modelData.put(info.pos, be.getModelData()); + if (be instanceof KineticBlockEntity kbe) + kbe.setSpeed(0); + be.getBlockState(); MovementBehaviour movementBehaviour = AllMovementBehaviours.getBehaviour(info.state); if (movementBehaviour == null || !movementBehaviour.hasSpecialInstancedRendering()) - maybeInstancedTileEntities.add(te); + maybeInstancedBlockEntities.add(be); - if (movementBehaviour != null && !movementBehaviour.renderAsNormalTileEntity()) + if (movementBehaviour != null && !movementBehaviour.renderAsNormalBlockEntity()) return; - presentTileEntities.put(info.pos, te); - specialRenderedTileEntities.add(te); + presentBlockEntities.put(info.pos, be); + specialRenderedBlockEntities.add(be); }); } @@ -1009,7 +1024,7 @@ public abstract class Contraption { if (disassembled) return; disassembled = true; - + for (boolean nonBrittles : Iterate.trueAndFalse) { for (StructureBlockInfo block : blocks.values()) { if (nonBrittles == BlockMovementChecks.isBrittle(block.state)) @@ -1050,39 +1065,49 @@ public abstract class Contraption { if (state.hasProperty(SlidingDoorBlock.VISIBLE)) state = state.setValue(SlidingDoorBlock.VISIBLE, !state.getValue(SlidingDoorBlock.OPEN)) .setValue(SlidingDoorBlock.POWERED, false); + // Stop Sculk shriekers from getting "stuck" if moved mid-shriek. + if(state.is(Blocks.SCULK_SHRIEKER)){ + state = Blocks.SCULK_SHRIEKER.defaultBlockState(); + } world.setBlock(targetPos, state, Block.UPDATE_MOVE_BY_PISTON | Block.UPDATE_ALL); boolean verticalRotation = transform.rotationAxis == null || transform.rotationAxis.isHorizontal(); verticalRotation = verticalRotation && transform.rotation != Rotation.NONE; if (verticalRotation) { - if (state.getBlock() instanceof RopeBlock || state.getBlock() instanceof MagnetBlock || state.getBlock() instanceof DoorBlock) + if (state.getBlock() instanceof RopeBlock || state.getBlock() instanceof MagnetBlock + || state.getBlock() instanceof DoorBlock) world.destroyBlock(targetPos, true); } - BlockEntity tileEntity = world.getBlockEntity(targetPos); + BlockEntity blockEntity = world.getBlockEntity(targetPos); CompoundTag tag = block.nbt; - if (tileEntity != null) - tag = NBTProcessors.process(tileEntity, tag, false); - if (tileEntity != null && tag != null) { + + // Temporary fix: Calling load(CompoundTag tag) on a Sculk sensor causes it to not react to vibrations. + if(state.is(Blocks.SCULK_SENSOR) || state.is(Blocks.SCULK_SHRIEKER)) + tag = null; + + if (blockEntity != null) + tag = NBTProcessors.process(blockEntity, tag, false); + if (blockEntity != null && tag != null) { tag.putInt("x", targetPos.getX()); tag.putInt("y", targetPos.getY()); tag.putInt("z", targetPos.getZ()); - if (verticalRotation && tileEntity instanceof PulleyTileEntity) { + if (verticalRotation && blockEntity instanceof PulleyBlockEntity) { tag.remove("Offset"); tag.remove("InitialOffset"); } - if (tileEntity instanceof IMultiTileContainer && tag.contains("LastKnownPos")) + if (blockEntity instanceof IMultiBlockEntityContainer && tag.contains("LastKnownPos")) tag.put("LastKnownPos", NbtUtils.writeBlockPos(BlockPos.ZERO.below(Integer.MAX_VALUE - 1))); - tileEntity.load(tag); - storage.addStorageToWorld(block, tileEntity); + blockEntity.load(tag); + storage.addStorageToWorld(block, blockEntity); } - transform.apply(tileEntity); + transform.apply(blockEntity); } } @@ -1123,13 +1148,56 @@ public abstract class Contraption { } public void startMoving(Level world) { + disabledActors.clear(); + for (MutablePair pair : actors) { MovementContext context = new MovementContext(world, pair.left, this); MovementBehaviour behaviour = AllMovementBehaviours.getBehaviour(pair.left.state); if (behaviour != null) behaviour.startMoving(context); pair.setRight(context); + if (behaviour instanceof ContraptionControlsMovement) + disableActorOnStart(context); } + + for (ItemStack stack : disabledActors) + setActorsActive(stack, false); + } + + protected void disableActorOnStart(MovementContext context) { + if (!ContraptionControlsMovement.isDisabledInitially(context)) + return; + ItemStack filter = ContraptionControlsMovement.getFilter(context); + if (filter == null) + return; + if (isActorTypeDisabled(filter)) + return; + disabledActors.add(filter); + } + + public boolean isActorTypeDisabled(ItemStack filter) { + return disabledActors.stream() + .anyMatch(i -> ContraptionControlsMovement.isSameFilter(i, filter)); + } + + public void setActorsActive(ItemStack referenceStack, boolean enable) { + for (MutablePair pair : actors) { + MovementBehaviour behaviour = AllMovementBehaviours.getBehaviour(pair.left.state); + if (behaviour == null) + continue; + ItemStack behaviourStack = behaviour.canBeDisabledVia(pair.right); + if (behaviourStack == null) + continue; + if (!referenceStack.isEmpty() && !ContraptionControlsMovement.isSameFilter(referenceStack, behaviourStack)) + continue; + pair.right.disabled = !enable; + if (!enable) + behaviour.onDisabledByControls(pair.right); + } + } + + public List getDisabledActors() { + return disabledActors; } public void stop(Level world) { @@ -1222,6 +1290,14 @@ public abstract class Contraption { return actors; } + @Nullable + public MutablePair getActorAt(BlockPos localPos) { + for (MutablePair pair : actors) + if (localPos.equals(pair.left.pos)) + return pair; + return null; + } + public Map getInteractors() { return interactors; } @@ -1304,7 +1380,7 @@ public abstract class Contraption { } public Collection getSpecialRenderedTEs() { - return specialRenderedTileEntities; + return specialRenderedBlockEntities; } public boolean isHiddenInPortal(BlockPos localPos) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionBlockChangedPacket.java b/src/main/java/com/simibubi/create/content/contraptions/ContraptionBlockChangedPacket.java similarity index 76% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionBlockChangedPacket.java rename to src/main/java/com/simibubi/create/content/contraptions/ContraptionBlockChangedPacket.java index 2302fb687..b28ccfd4e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionBlockChangedPacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/ContraptionBlockChangedPacket.java @@ -1,6 +1,4 @@ -package com.simibubi.create.content.contraptions.components.structureMovement; - -import java.util.function.Supplier; +package com.simibubi.create.content.contraptions; import com.simibubi.create.foundation.networking.SimplePacketBase; @@ -40,12 +38,10 @@ public class ContraptionBlockChangedPacket extends SimplePacketBase { } @Override - public void handle(Supplier context) { - context.get() - .enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, - () -> () -> AbstractContraptionEntity.handleBlockChangedPacket(this))); - context.get() - .setPacketHandled(true); + public boolean handle(Context context) { + context.enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, + () -> () -> AbstractContraptionEntity.handleBlockChangedPacket(this))); + return true; } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionCollider.java b/src/main/java/com/simibubi/create/content/contraptions/ContraptionCollider.java similarity index 76% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionCollider.java rename to src/main/java/com/simibubi/create/content/contraptions/ContraptionCollider.java index 970d6ea30..245107612 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionCollider.java +++ b/src/main/java/com/simibubi/create/content/contraptions/ContraptionCollider.java @@ -1,33 +1,45 @@ -package com.simibubi.create.content.contraptions.components.structureMovement; +package com.simibubi.create.content.contraptions; import static net.minecraft.world.entity.Entity.collideBoundingBox; +import java.lang.ref.WeakReference; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.WeakHashMap; import org.apache.commons.lang3.mutable.MutableBoolean; import org.apache.commons.lang3.mutable.MutableFloat; import org.apache.commons.lang3.mutable.MutableObject; +import org.apache.commons.lang3.tuple.MutablePair; import com.google.common.base.Predicates; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllMovementBehaviours; -import com.simibubi.create.content.contraptions.components.actors.BlockBreakingMovementBehaviour; -import com.simibubi.create.content.contraptions.components.actors.HarvesterMovementBehaviour; -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity.ContraptionRotationState; -import com.simibubi.create.content.contraptions.components.structureMovement.sync.ClientMotionPacket; -import com.simibubi.create.content.logistics.trains.entity.CarriageContraptionEntity; +import com.simibubi.create.AllPackets; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity.ContraptionRotationState; +import com.simibubi.create.content.contraptions.ContraptionColliderLockPacket.ContraptionColliderLockPacketRequest; +import com.simibubi.create.content.contraptions.actors.harvester.HarvesterMovementBehaviour; +import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; +import com.simibubi.create.content.contraptions.behaviour.MovingInteractionBehaviour; +import com.simibubi.create.content.contraptions.sync.ClientMotionPacket; +import com.simibubi.create.content.kinetics.base.BlockBreakingMovementBehaviour; +import com.simibubi.create.content.trains.entity.CarriageContraptionEntity; import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.collision.ContinuousOBBCollider.ContinuousSeparationManifold; import com.simibubi.create.foundation.collision.Matrix3d; import com.simibubi.create.foundation.collision.OrientedBB; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.utility.BlockHelper; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.infrastructure.config.AllConfigs; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.multiplayer.ClientPacketListener; import net.minecraft.client.player.LocalPlayer; +import net.minecraft.client.player.RemotePlayer; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -48,6 +60,7 @@ import net.minecraft.world.level.block.CocoaBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraftforge.api.distmarker.Dist; @@ -60,6 +73,9 @@ public class ContraptionCollider { NONE, CLIENT, REMOTE, SERVER } + private static MutablePair, Double> safetyLock = new MutablePair<>(); + private static Map> remoteSafetyLocks = new WeakHashMap<>(); + static void collideEntities(AbstractContraptionEntity contraptionEntity) { Level world = contraptionEntity.getCommandSenderWorld(); Contraption contraption = contraptionEntity.getContraption(); @@ -75,6 +91,10 @@ public class ContraptionCollider { Vec3 anchorVec = contraptionEntity.getAnchorVec(); ContraptionRotationState rotation = null; + if (world.isClientSide() && safetyLock.left != null && safetyLock.left.get() == contraptionEntity) + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, + () -> () -> saveClientPlayerFromClipping(contraptionEntity, contraptionMotion)); + // After death, multiple refs to the client player may show up in the area boolean skipClientPlayer = false; @@ -85,8 +105,13 @@ public class ContraptionCollider { continue; PlayerType playerType = getPlayerType(entity); - if (playerType == PlayerType.REMOTE) + if (playerType == PlayerType.REMOTE) { + if (!(contraption instanceof TranslatingContraption)) + continue; + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, + () -> () -> saveRemotePlayerFromClipping((Player) entity, contraptionEntity, contraptionMotion)); continue; + } entity.getSelfAndPassengers() .forEach(e -> { @@ -97,11 +122,12 @@ public class ContraptionCollider { if (playerType == PlayerType.SERVER) continue; - if (playerType == PlayerType.CLIENT) + if (playerType == PlayerType.CLIENT) { if (skipClientPlayer) continue; else skipClientPlayer = true; + } // Init matrix if (rotation == null) @@ -115,13 +141,15 @@ public class ContraptionCollider { float yawOffset = rotation.getYawOffset(); Vec3 position = getWorldToLocalTranslation(entity, anchorVec, rotationMatrix, yawOffset); + motion = motion.subtract(contraptionMotion); + motion = rotationMatrix.transform(motion); + // Prepare entity bounds AABB localBB = entityBounds.move(position) .inflate(1.0E-7D); + OrientedBB obb = new OrientedBB(localBB); obb.setRotation(rotationMatrix); - motion = motion.subtract(contraptionMotion); - motion = rotationMatrix.transform(motion); // Use simplified bbs when present final Vec3 motionCopy = motion; @@ -341,7 +369,8 @@ public class ContraptionCollider { entity.fallDistance = 0; for (Entity rider : entity.getIndirectPassengers()) if (getPlayerType(rider) == PlayerType.CLIENT) - AllPackets.channel.sendToServer(new ClientMotionPacket(rider.getDeltaMovement(), true, 0)); + AllPackets.getChannel() + .sendToServer(new ClientMotionPacket(rider.getDeltaMovement(), true, 0)); boolean canWalk = bounce != 0 || slide == 0; if (canWalk || !rotation.hasVerticalRotation()) { if (canWalk) @@ -365,11 +394,113 @@ public class ContraptionCollider { float limbSwing = Mth.sqrt((float) (d0 * d0 + d1 * d1)) * 4.0F; if (limbSwing > 1.0F) limbSwing = 1.0F; - AllPackets.channel.sendToServer(new ClientMotionPacket(entityMotion, true, limbSwing)); + AllPackets.getChannel() + .sendToServer(new ClientMotionPacket(entityMotion, true, limbSwing)); + + if (entity.isOnGround() && contraption instanceof TranslatingContraption) { + safetyLock.setLeft(new WeakReference<>(contraptionEntity)); + safetyLock.setRight(entity.getY() - contraptionEntity.getY()); + } } } + private static int packetCooldown = 0; + + @OnlyIn(Dist.CLIENT) + private static void saveClientPlayerFromClipping(AbstractContraptionEntity contraptionEntity, + Vec3 contraptionMotion) { + LocalPlayer entity = Minecraft.getInstance().player; + if (entity.isPassenger()) + return; + + double prevDiff = safetyLock.right; + double currentDiff = entity.getY() - contraptionEntity.getY(); + double motion = contraptionMotion.subtract(entity.getDeltaMovement()).y; + double trend = Math.signum(currentDiff - prevDiff); + + ClientPacketListener handler = entity.connection; + if (handler.getOnlinePlayers() + .size() > 1) { + if (packetCooldown > 0) + packetCooldown--; + if (packetCooldown == 0) { + AllPackets.getChannel() + .sendToServer(new ContraptionColliderLockPacketRequest(contraptionEntity.getId(), currentDiff)); + packetCooldown = 3; + } + } + + if (trend == 0) + return; + if (trend == Math.signum(motion)) + return; + + double speed = contraptionMotion.multiply(0, 1, 0) + .lengthSqr(); + if (trend > 0 && speed < 0.1) + return; + if (speed < 0.05) + return; + + if (!savePlayerFromClipping(entity, contraptionEntity, contraptionMotion, prevDiff)) + safetyLock.setLeft(null); + } + + @OnlyIn(Dist.CLIENT) + public static void lockPacketReceived(int contraptionId, int remotePlayerId, double suggestedOffset) { + ClientLevel level = Minecraft.getInstance().level; + if (!(level.getEntity(contraptionId) instanceof ControlledContraptionEntity contraptionEntity)) + return; + if (!(level.getEntity(remotePlayerId) instanceof RemotePlayer player)) + return; + remoteSafetyLocks.computeIfAbsent(contraptionEntity, $ -> new WeakHashMap<>()) + .put(player, suggestedOffset); + } + + @OnlyIn(Dist.CLIENT) + private static void saveRemotePlayerFromClipping(Player entity, AbstractContraptionEntity contraptionEntity, + Vec3 contraptionMotion) { + if (entity.isPassenger()) + return; + + Map locksOnThisContraption = + remoteSafetyLocks.getOrDefault(contraptionEntity, Collections.emptyMap()); + double prevDiff = locksOnThisContraption.getOrDefault(entity, entity.getY() - contraptionEntity.getY()); + if (!savePlayerFromClipping(entity, contraptionEntity, contraptionMotion, prevDiff)) + if (locksOnThisContraption.containsKey(entity)) + locksOnThisContraption.remove(entity); + } + + @OnlyIn(Dist.CLIENT) + private static boolean savePlayerFromClipping(Player entity, AbstractContraptionEntity contraptionEntity, + Vec3 contraptionMotion, double yStartOffset) { + AABB bb = entity.getBoundingBox() + .deflate(1 / 4f, 0, 1 / 4f); + double shortestDistance = Double.MAX_VALUE; + double yStart = entity.getStepHeight() + contraptionEntity.getY() + yStartOffset; + double rayLength = Math.max(5, Math.abs(entity.getY() - yStart)); + + for (int rayIndex = 0; rayIndex < 4; rayIndex++) { + Vec3 start = new Vec3(rayIndex / 2 == 0 ? bb.minX : bb.maxX, yStart, rayIndex % 2 == 0 ? bb.minZ : bb.maxZ); + Vec3 end = start.add(0, -rayLength, 0); + + BlockHitResult hitResult = ContraptionHandlerClient.rayTraceContraption(start, end, contraptionEntity); + if (hitResult == null) + continue; + + Vec3 hit = contraptionEntity.toGlobalVector(hitResult.getLocation(), 1); + double hitDiff = start.y - hit.y; + if (shortestDistance > hitDiff) + shortestDistance = hitDiff; + } + + if (shortestDistance > rayLength) + return false; + entity.setPos(entity.getX(), yStart - shortestDistance, entity.getZ()); + return true; + } + private static Vec3 handleDamageFromTrain(Level world, AbstractContraptionEntity contraptionEntity, Vec3 contraptionMotion, Entity entity, Vec3 entityMotion, PlayerType playerType) { @@ -377,20 +508,20 @@ public class ContraptionCollider { return entityMotion; if (!entity.isOnGround()) return entityMotion; - + CompoundTag persistentData = entity.getPersistentData(); if (persistentData.contains("ContraptionGrounded")) { persistentData.remove("ContraptionGrounded"); return entityMotion; } - + if (cce.collidingEntities.containsKey(entity)) return entityMotion; if (entity instanceof ItemEntity) return entityMotion; if (cce.nonDamageTicks != 0) return entityMotion; - if (!AllConfigs.SERVER.trains.trainsCauseDamage.get()) + if (!AllConfigs.server().trains.trainsCauseDamage.get()) return entityMotion; Vec3 diffMotion = contraptionMotion.subtract(entity.getDeltaMovement()); @@ -407,7 +538,8 @@ public class ContraptionCollider { return entityMotion; if (playerType == PlayerType.CLIENT) { - AllPackets.channel.sendToServer(new TrainCollisionPacket((int) (damage * 16), contraptionEntity.getId())); + AllPackets.getChannel() + .sendToServer(new TrainCollisionPacket((int) (damage * 16), contraptionEntity.getId())); world.playSound((Player) entity, entity.blockPosition(), SoundEvents.PLAYER_ATTACK_CRIT, SoundSource.NEUTRAL, 1, .75f); } else { @@ -445,15 +577,6 @@ public class ContraptionCollider { return true; } - public static Vec3 getWorldToLocalTranslation(Entity entity, AbstractContraptionEntity contraptionEntity) { - return getWorldToLocalTranslation(entity, contraptionEntity.getAnchorVec(), - contraptionEntity.getRotationState()); - } - - public static Vec3 getWorldToLocalTranslation(Entity entity, Vec3 anchorVec, ContraptionRotationState rotation) { - return getWorldToLocalTranslation(entity, anchorVec, rotation.asMatrix(), rotation.getYawOffset()); - } - public static Vec3 getWorldToLocalTranslation(Entity entity, Vec3 anchorVec, Matrix3d rotationMatrix, float yawOffset) { Vec3 entityPosition = entity.position(); @@ -461,35 +584,29 @@ public class ContraptionCollider { .getYsize() / 2, 0); Vec3 position = entityPosition; position = position.add(centerY); - position = position.subtract(VecHelper.CENTER_OF_ORIGIN); - position = position.subtract(anchorVec); - position = VecHelper.rotate(position, -yawOffset, Axis.Y); - position = rotationMatrix.transform(position); - position = position.add(VecHelper.CENTER_OF_ORIGIN); + position = worldToLocalPos(position, anchorVec, rotationMatrix, yawOffset); position = position.subtract(centerY); position = position.subtract(entityPosition); return position; } - public static Vec3 getWorldToLocalTranslation(Vec3 entity, AbstractContraptionEntity contraptionEntity) { - return getWorldToLocalTranslation(entity, contraptionEntity.getAnchorVec(), + public static Vec3 worldToLocalPos(Vec3 worldPos, AbstractContraptionEntity contraptionEntity) { + return worldToLocalPos(worldPos, contraptionEntity.getAnchorVec(), contraptionEntity.getRotationState()); } - public static Vec3 getWorldToLocalTranslation(Vec3 inPos, Vec3 anchorVec, ContraptionRotationState rotation) { - return getWorldToLocalTranslation(inPos, anchorVec, rotation.asMatrix(), rotation.getYawOffset()); + public static Vec3 worldToLocalPos(Vec3 worldPos, Vec3 anchorVec, ContraptionRotationState rotation) { + return worldToLocalPos(worldPos, anchorVec, rotation.asMatrix(), rotation.getYawOffset()); } - public static Vec3 getWorldToLocalTranslation(Vec3 inPos, Vec3 anchorVec, Matrix3d rotationMatrix, - float yawOffset) { - Vec3 position = inPos; - position = position.subtract(VecHelper.CENTER_OF_ORIGIN); - position = position.subtract(anchorVec); - position = VecHelper.rotate(position, -yawOffset, Axis.Y); - position = rotationMatrix.transform(position); - position = position.add(VecHelper.CENTER_OF_ORIGIN); - position = position.subtract(inPos); - return position; + public static Vec3 worldToLocalPos(Vec3 worldPos, Vec3 anchorVec, Matrix3d rotationMatrix, float yawOffset) { + Vec3 localPos = worldPos; + localPos = localPos.subtract(anchorVec); + localPos = localPos.subtract(VecHelper.CENTER_OF_ORIGIN); + localPos = VecHelper.rotate(localPos, -yawOffset, Axis.Y); + localPos = rotationMatrix.transform(localPos); + localPos = localPos.add(VecHelper.CENTER_OF_ORIGIN); + return localPos; } /** From Entity#collide **/ @@ -615,7 +732,7 @@ public class ContraptionCollider { .intersects(otherBounds.move(otherMotion))) continue; - for (BlockPos colliderPos : contraption.getColliders(world, movementDirection)) { + for (BlockPos colliderPos : contraption.getOrCreateColliders(world, movementDirection)) { colliderPos = colliderPos.offset(gridPos) .subtract(new BlockPos(otherPosition)); if (!otherContraption.getBlocks() @@ -630,7 +747,7 @@ public class ContraptionCollider { public static boolean isCollidingWithWorld(Level world, TranslatingContraption contraption, BlockPos anchor, Direction movementDirection) { - for (BlockPos pos : contraption.getColliders(world, movementDirection)) { + for (BlockPos pos : contraption.getOrCreateColliders(world, movementDirection)) { BlockPos colliderPos = pos.offset(anchor); if (!world.isLoaded(colliderPos)) diff --git a/src/main/java/com/simibubi/create/content/contraptions/ContraptionColliderLockPacket.java b/src/main/java/com/simibubi/create/content/contraptions/ContraptionColliderLockPacket.java new file mode 100644 index 000000000..3b4ff0eeb --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/ContraptionColliderLockPacket.java @@ -0,0 +1,78 @@ +package com.simibubi.create.content.contraptions; + +import com.simibubi.create.AllPackets; +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.network.NetworkEvent.Context; +import net.minecraftforge.network.PacketDistributor; + +public class ContraptionColliderLockPacket extends SimplePacketBase { + + protected int contraption; + protected double offset; + private int sender; + + public ContraptionColliderLockPacket(int contraption, double offset, int sender) { + this.contraption = contraption; + this.offset = offset; + this.sender = sender; + } + + public ContraptionColliderLockPacket(FriendlyByteBuf buffer) { + contraption = buffer.readVarInt(); + offset = buffer.readDouble(); + sender = buffer.readVarInt(); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeVarInt(contraption); + buffer.writeDouble(offset); + buffer.writeVarInt(sender); + } + + @Override + public boolean handle(Context context) { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, + () -> () -> ContraptionCollider.lockPacketReceived(contraption, sender, offset)); + return true; + } + + public static class ContraptionColliderLockPacketRequest extends SimplePacketBase { + + protected int contraption; + protected double offset; + + public ContraptionColliderLockPacketRequest(int contraption, double offset) { + this.contraption = contraption; + this.offset = offset; + } + + public ContraptionColliderLockPacketRequest(FriendlyByteBuf buffer) { + contraption = buffer.readVarInt(); + offset = buffer.readDouble(); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeVarInt(contraption); + buffer.writeDouble(offset); + } + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> { + AllPackets.getChannel() + .send(PacketDistributor.TRACKING_ENTITY.with(context::getSender), + new ContraptionColliderLockPacket(contraption, offset, context.getSender() + .getId())); + }); + return true; + } + + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/utility/ContraptionData.java b/src/main/java/com/simibubi/create/content/contraptions/ContraptionData.java similarity index 91% rename from src/main/java/com/simibubi/create/foundation/utility/ContraptionData.java rename to src/main/java/com/simibubi/create/content/contraptions/ContraptionData.java index 083cb4eae..c204d4edf 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/ContraptionData.java +++ b/src/main/java/com/simibubi/create/content/contraptions/ContraptionData.java @@ -1,8 +1,8 @@ -package com.simibubi.create.foundation.utility; +package com.simibubi.create.content.contraptions; import com.simibubi.create.compat.Mods; -import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.mixin.accessor.NbtAccounterAccessor; +import com.simibubi.create.infrastructure.config.AllConfigs; import io.netty.buffer.Unpooled; import net.minecraft.nbt.CompoundTag; @@ -30,7 +30,7 @@ public class ContraptionData { * @return true if the given NBT is too large for a contraption to be synced to clients. */ public static boolean isTooLargeForSync(CompoundTag data) { - int max = AllConfigs.SERVER.kinetics.maxDataSize.get(); + int max = AllConfigs.server().kinetics.maxDataSize.get(); return max != 0 && packetSize(data) > max; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/ContraptionDisassemblyPacket.java b/src/main/java/com/simibubi/create/content/contraptions/ContraptionDisassemblyPacket.java new file mode 100644 index 000000000..44d56748c --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/ContraptionDisassemblyPacket.java @@ -0,0 +1,38 @@ +package com.simibubi.create.content.contraptions; + +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.network.NetworkEvent.Context; + +public class ContraptionDisassemblyPacket extends SimplePacketBase { + + int entityID; + StructureTransform transform; + + public ContraptionDisassemblyPacket(int entityID, StructureTransform transform) { + this.entityID = entityID; + this.transform = transform; + } + + public ContraptionDisassemblyPacket(FriendlyByteBuf buffer) { + entityID = buffer.readInt(); + transform = StructureTransform.fromBuffer(buffer); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeInt(entityID); + transform.writeToBuffer(buffer); + } + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, + () -> () -> AbstractContraptionEntity.handleDisassemblyPacket(this))); + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionHandler.java b/src/main/java/com/simibubi/create/content/contraptions/ContraptionHandler.java similarity index 97% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionHandler.java rename to src/main/java/com/simibubi/create/content/contraptions/ContraptionHandler.java index 298e9d596..a55884112 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/ContraptionHandler.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.structureMovement; +package com.simibubi.create.content.contraptions; import java.lang.ref.WeakReference; import java.util.Collection; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionHandlerClient.java b/src/main/java/com/simibubi/create/content/contraptions/ContraptionHandlerClient.java similarity index 92% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionHandlerClient.java rename to src/main/java/com/simibubi/create/content/contraptions/ContraptionHandlerClient.java index 94468b77b..a80369809 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionHandlerClient.java +++ b/src/main/java/com/simibubi/create/content/contraptions/ContraptionHandlerClient.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.structureMovement; +package com.simibubi.create.content.contraptions; import java.lang.ref.WeakReference; import java.util.Collection; @@ -8,10 +8,10 @@ import javax.annotation.Nullable; import org.apache.commons.lang3.mutable.MutableObject; import com.simibubi.create.AllItems; -import com.simibubi.create.content.contraptions.components.structureMovement.sync.ContraptionInteractionPacket; -import com.simibubi.create.content.logistics.trains.entity.CarriageContraptionEntity; -import com.simibubi.create.content.logistics.trains.entity.TrainRelocator; -import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.AllPackets; +import com.simibubi.create.content.contraptions.sync.ContraptionInteractionPacket; +import com.simibubi.create.content.trains.entity.CarriageContraptionEntity; +import com.simibubi.create.content.trains.entity.TrainRelocator; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.RaycastHelper; @@ -109,7 +109,7 @@ public class ContraptionHandlerClient { BlockPos pos = rayTraceResult.getBlockPos(); if (contraptionEntity.handlePlayerInteraction(player, pos, face, hand)) { - AllPackets.channel.sendToServer(new ContraptionInteractionPacket(contraptionEntity, hand, pos, face)); + AllPackets.getChannel().sendToServer(new ContraptionInteractionPacket(contraptionEntity, hand, pos, face)); } else if (handleSpecialInteractions(contraptionEntity, player, pos, face, hand)) { } else continue; diff --git a/src/main/java/com/simibubi/create/content/contraptions/ContraptionMovementSetting.java b/src/main/java/com/simibubi/create/content/contraptions/ContraptionMovementSetting.java new file mode 100644 index 000000000..e8fc89990 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/ContraptionMovementSetting.java @@ -0,0 +1,61 @@ +package com.simibubi.create.content.contraptions; + +import java.util.Collection; +import java.util.function.Supplier; + +import javax.annotation.Nullable; + +import com.simibubi.create.foundation.utility.AttachedRegistry; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; +import net.minecraftforge.common.extensions.IForgeBlock; +import net.minecraftforge.registries.ForgeRegistries; + +public enum ContraptionMovementSetting { + MOVABLE, NO_PICKUP, UNMOVABLE; + + private static final AttachedRegistry> SETTING_SUPPLIERS = new AttachedRegistry<>(ForgeRegistries.BLOCKS); + + public static void register(ResourceLocation block, Supplier settingSupplier) { + SETTING_SUPPLIERS.register(block, settingSupplier); + } + + public static void register(Block block, Supplier settingSupplier) { + SETTING_SUPPLIERS.register(block, settingSupplier); + } + + @Nullable + public static ContraptionMovementSetting get(Block block) { + if (block instanceof IMovementSettingProvider provider) + return provider.getContraptionMovementSetting(); + Supplier supplier = SETTING_SUPPLIERS.get(block); + if (supplier == null) + return null; + return supplier.get(); + } + + public static boolean allAre(Collection blocks, ContraptionMovementSetting are) { + return blocks.stream().anyMatch(b -> get(b.state.getBlock()) == are); + } + + public static boolean isNoPickup(Collection blocks) { + return allAre(blocks, ContraptionMovementSetting.NO_PICKUP); + } + + public static void registerDefaults() { + register(Blocks.SPAWNER, () -> AllConfigs.server().kinetics.spawnerMovement.get()); + register(Blocks.BUDDING_AMETHYST, () -> AllConfigs.server().kinetics.amethystMovement.get()); + register(Blocks.OBSIDIAN, () -> AllConfigs.server().kinetics.obsidianMovement.get()); + register(Blocks.CRYING_OBSIDIAN, () -> AllConfigs.server().kinetics.obsidianMovement.get()); + register(Blocks.RESPAWN_ANCHOR, () -> AllConfigs.server().kinetics.obsidianMovement.get()); + register(Blocks.REINFORCED_DEEPSLATE, () -> AllConfigs.server().kinetics.reinforcedDeepslateMovement.get()); + } + + public interface IMovementSettingProvider extends IForgeBlock { + ContraptionMovementSetting getContraptionMovementSetting(); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/ContraptionRelocationPacket.java b/src/main/java/com/simibubi/create/content/contraptions/ContraptionRelocationPacket.java new file mode 100644 index 000000000..8513de073 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/ContraptionRelocationPacket.java @@ -0,0 +1,34 @@ +package com.simibubi.create.content.contraptions; + +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.network.NetworkEvent.Context; + +public class ContraptionRelocationPacket extends SimplePacketBase { + + int entityID; + + public ContraptionRelocationPacket(int entityID) { + this.entityID = entityID; + } + + public ContraptionRelocationPacket(FriendlyByteBuf buffer) { + entityID = buffer.readInt(); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeInt(entityID); + } + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, + () -> () -> OrientedContraptionEntity.handleRelocationPacket(this))); + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionStallPacket.java b/src/main/java/com/simibubi/create/content/contraptions/ContraptionStallPacket.java similarity index 75% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionStallPacket.java rename to src/main/java/com/simibubi/create/content/contraptions/ContraptionStallPacket.java index 6f7cdf3f9..0cb3ff2a1 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionStallPacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/ContraptionStallPacket.java @@ -1,6 +1,4 @@ -package com.simibubi.create.content.contraptions.components.structureMovement; - -import java.util.function.Supplier; +package com.simibubi.create.content.contraptions; import com.simibubi.create.foundation.networking.SimplePacketBase; @@ -41,10 +39,10 @@ public class ContraptionStallPacket extends SimplePacketBase { } @Override - public void handle(Supplier context) { - context.get().enqueueWork( - () -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> AbstractContraptionEntity.handleStallPacket(this))); - context.get().setPacketHandled(true); + public boolean handle(Context context) { + context.enqueueWork( + () -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> AbstractContraptionEntity.handleStallPacket(this))); + return true; } private void writeAll(FriendlyByteBuf buffer, double... doubles) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/ContraptionType.java b/src/main/java/com/simibubi/create/content/contraptions/ContraptionType.java new file mode 100644 index 000000000..1b85efc41 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/ContraptionType.java @@ -0,0 +1,53 @@ +package com.simibubi.create.content.contraptions; + +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.function.Supplier; + +import com.simibubi.create.content.contraptions.bearing.BearingContraption; +import com.simibubi.create.content.contraptions.bearing.ClockworkContraption; +import com.simibubi.create.content.contraptions.bearing.StabilizedContraption; +import com.simibubi.create.content.contraptions.elevator.ElevatorContraption; +import com.simibubi.create.content.contraptions.gantry.GantryContraption; +import com.simibubi.create.content.contraptions.mounted.MountedContraption; +import com.simibubi.create.content.contraptions.piston.PistonContraption; +import com.simibubi.create.content.contraptions.pulley.PulleyContraption; +import com.simibubi.create.content.trains.entity.CarriageContraption; + +public class ContraptionType { + + public static final Map ENTRIES = new HashMap<>(); + public static final ContraptionType + PISTON = register("piston", PistonContraption::new), + BEARING = register("bearing", BearingContraption::new), + PULLEY = register("pulley", PulleyContraption::new), + CLOCKWORK = register("clockwork", ClockworkContraption::new), + MOUNTED = register("mounted", MountedContraption::new), + STABILIZED = register("stabilized", StabilizedContraption::new), + GANTRY = register("gantry", GantryContraption::new), + CARRIAGE = register("carriage", CarriageContraption::new), + ELEVATOR = register("elevator", ElevatorContraption::new); + + Supplier factory; + String id; + + public static ContraptionType register(String id, Supplier factory) { + ContraptionType value = new ContraptionType(id, factory); + ENTRIES.put(id, value); + return value; + } + + private ContraptionType(String id, Supplier factory) { + this.factory = factory; + this.id = id; + } + + public static Contraption fromType(String type) { + for (Entry allContraptionTypes : ENTRIES.entrySet()) + if (type.equals(allContraptionTypes.getKey())) + return allContraptionTypes.getValue().factory.get(); + return null; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/ContraptionWorld.java b/src/main/java/com/simibubi/create/content/contraptions/ContraptionWorld.java new file mode 100644 index 000000000..171b9e17f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/ContraptionWorld.java @@ -0,0 +1,62 @@ +package com.simibubi.create.content.contraptions; + +import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld; + +import net.minecraft.core.BlockPos; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.sounds.SoundSource; +import net.minecraft.util.Mth; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; + +public class ContraptionWorld extends WrappedWorld { + final Contraption contraption; + private final int minY; + private final int height; + + public ContraptionWorld(Level world, Contraption contraption) { + super(world); + + this.contraption = contraption; + + // Include 1 block above/below contraption height range to avoid certain edge-case Starlight crashes with + // downward-facing mechanical pistons. + minY = nextMultipleOf16(contraption.bounds.minY - 1); + height = nextMultipleOf16(contraption.bounds.maxY + 1) - minY; + } + + // https://math.stackexchange.com/questions/291468 + private static int nextMultipleOf16(double a) { + return (((Math.abs((int) a) - 1) | 15) + 1) * Mth.sign(a); + } + + @Override + public BlockState getBlockState(BlockPos pos) { + StructureTemplate.StructureBlockInfo blockInfo = contraption.getBlocks().get(pos); + + if (blockInfo != null) + return blockInfo.state; + + return Blocks.AIR.defaultBlockState(); + } + + @Override + public void playLocalSound(double x, double y, double z, SoundEvent sound, SoundSource category, float volume, float pitch, boolean distanceDelay) { + world.playLocalSound(x, y, z, sound, category, volume, pitch, distanceDelay); + } + + // Ensure that we provide accurate information about ContraptionWorld height to mods (such as Starlight) which + // expect Levels to only have blocks located in chunks within their height range. + + @Override + public int getHeight() { + return height; + } + + @Override + public int getMinBuildHeight() { + return minY; + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ControlledContraptionEntity.java b/src/main/java/com/simibubi/create/content/contraptions/ControlledContraptionEntity.java similarity index 90% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ControlledContraptionEntity.java rename to src/main/java/com/simibubi/create/content/contraptions/ControlledContraptionEntity.java index 9dc253c18..a343b6c87 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ControlledContraptionEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/ControlledContraptionEntity.java @@ -1,11 +1,13 @@ -package com.simibubi.create.content.contraptions.components.structureMovement; +package com.simibubi.create.content.contraptions; import static com.simibubi.create.foundation.utility.AngleHelper.angleLerp; import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllEntityTypes; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.BearingContraption; +import com.simibubi.create.content.contraptions.bearing.BearingContraption; +import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.VecHelper; @@ -14,6 +16,7 @@ import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtUtils; +import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; @@ -48,6 +51,15 @@ public class ControlledContraptionEntity extends AbstractContraptionEntity { entity.setContraption(contraption); return entity; } + + @Override + public void setPos(double x, double y, double z) { + super.setPos(x, y, z); + if (!level.isClientSide()) + return; + for (Entity entity : getPassengers()) + positionRider(entity); + } @Override public Vec3 getContactPointMotion(Vec3 globalContactPoint) { @@ -62,7 +74,6 @@ public class ControlledContraptionEntity extends AbstractContraptionEntity { if (contraption instanceof BearingContraption) rotationAxis = ((BearingContraption) contraption).getFacing() .getAxis(); - } @Override @@ -113,6 +124,11 @@ public class ControlledContraptionEntity extends AbstractContraptionEntity { public void setAngle(float angle) { this.angle = angle; + + if (!level.isClientSide()) + return; + for (Entity entity : getPassengers()) + positionRider(entity); } public float getAngle(float partialTicks) { @@ -190,10 +206,10 @@ public class ControlledContraptionEntity extends AbstractContraptionEntity { return null; if (!level.isLoaded(controllerPos)) return null; - BlockEntity te = level.getBlockEntity(controllerPos); - if (!(te instanceof IControlContraption)) + BlockEntity be = level.getBlockEntity(controllerPos); + if (!(be instanceof IControlContraption)) return null; - return (IControlContraption) te; + return (IControlContraption) be; } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/DirectionalExtenderScrollOptionSlot.java b/src/main/java/com/simibubi/create/content/contraptions/DirectionalExtenderScrollOptionSlot.java similarity index 78% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/DirectionalExtenderScrollOptionSlot.java rename to src/main/java/com/simibubi/create/content/contraptions/DirectionalExtenderScrollOptionSlot.java index 0a04654c9..27b58da19 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/DirectionalExtenderScrollOptionSlot.java +++ b/src/main/java/com/simibubi/create/content/contraptions/DirectionalExtenderScrollOptionSlot.java @@ -1,10 +1,10 @@ -package com.simibubi.create.content.contraptions.components.structureMovement; +package com.simibubi.create.content.contraptions; import java.util.function.BiPredicate; import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.foundation.tileEntity.behaviour.CenteredSideValueBoxTransform; +import com.simibubi.create.foundation.blockEntity.behaviour.CenteredSideValueBoxTransform; import com.simibubi.create.foundation.utility.AngleHelper; import net.minecraft.core.Direction; @@ -19,13 +19,13 @@ public class DirectionalExtenderScrollOptionSlot extends CenteredSideValueBoxTra } @Override - protected Vec3 getLocalOffset(BlockState state) { + public Vec3 getLocalOffset(BlockState state) { return super.getLocalOffset(state) .add(Vec3.atLowerCornerOf(state.getValue(BlockStateProperties.FACING).getNormal()).scale(-2 / 16f)); } @Override - protected void rotate(BlockState state, PoseStack ms) { + public void rotate(BlockState state, PoseStack ms) { if (!getSide().getAxis().isHorizontal()) TransformStack.cast(ms) .rotateY(AngleHelper.horizontalAngle(state.getValue(BlockStateProperties.FACING)) + 180); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/IControlContraption.java b/src/main/java/com/simibubi/create/content/contraptions/IControlContraption.java similarity index 90% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/IControlContraption.java rename to src/main/java/com/simibubi/create/content/contraptions/IControlContraption.java index a48f9d883..9453fea9f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/IControlContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/IControlContraption.java @@ -1,7 +1,7 @@ -package com.simibubi.create.content.contraptions.components.structureMovement; +package com.simibubi.create.content.contraptions; +import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.INamedIconOptions; import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.INamedIconOptions; import com.simibubi.create.foundation.utility.Lang; import net.minecraft.core.BlockPos; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/IDisplayAssemblyExceptions.java b/src/main/java/com/simibubi/create/content/contraptions/IDisplayAssemblyExceptions.java similarity index 78% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/IDisplayAssemblyExceptions.java rename to src/main/java/com/simibubi/create/content/contraptions/IDisplayAssemblyExceptions.java index 0d0cee20a..c99054f41 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/IDisplayAssemblyExceptions.java +++ b/src/main/java/com/simibubi/create/content/contraptions/IDisplayAssemblyExceptions.java @@ -1,10 +1,11 @@ -package com.simibubi.create.content.contraptions.components.structureMovement; +package com.simibubi.create.content.contraptions; import java.util.Arrays; import java.util.List; -import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation; +import com.simibubi.create.content.equipment.goggles.IHaveGoggleInformation; import com.simibubi.create.foundation.item.TooltipHelper; +import com.simibubi.create.foundation.item.TooltipHelper.Palette; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Lang; @@ -27,7 +28,7 @@ public interface IDisplayAssemblyExceptions { String text = e.component.getString(); Arrays.stream(text.split("\n")) - .forEach(l -> TooltipHelper.cutStringTextComponent(l, ChatFormatting.GRAY, ChatFormatting.WHITE) + .forEach(l -> TooltipHelper.cutStringTextComponent(l, Palette.GRAY_AND_WHITE) .forEach(c -> tooltip.add(IHaveGoggleInformation.componentSpacing.plainCopy() .append(c)))); diff --git a/src/main/java/com/simibubi/create/content/contraptions/ITransformableBlock.java b/src/main/java/com/simibubi/create/content/contraptions/ITransformableBlock.java new file mode 100644 index 000000000..61c4cb0aa --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/ITransformableBlock.java @@ -0,0 +1,7 @@ +package com.simibubi.create.content.contraptions; + +import net.minecraft.world.level.block.state.BlockState; + +public interface ITransformableBlock { + BlockState transform(BlockState state, StructureTransform transform); +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/ITransformableBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/ITransformableBlockEntity.java new file mode 100644 index 000000000..cadd35946 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/ITransformableBlockEntity.java @@ -0,0 +1,7 @@ +package com.simibubi.create.content.contraptions; + +public interface ITransformableBlockEntity { + + void transform(StructureTransform transform); + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/KineticDebugger.java b/src/main/java/com/simibubi/create/content/contraptions/KineticDebugger.java deleted file mode 100644 index 5bb3dd29a..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/KineticDebugger.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.simibubi.create.content.contraptions; - -import com.simibubi.create.CreateClient; -import com.simibubi.create.content.contraptions.base.IRotate; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.utility.Color; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.core.Direction.AxisDirection; -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; -import net.minecraft.world.phys.Vec3; -import net.minecraft.world.phys.shapes.VoxelShape; - -public class KineticDebugger { - - public static void tick() { - if (!isActive()) { - if (KineticTileEntityRenderer.rainbowMode) { - KineticTileEntityRenderer.rainbowMode = false; - CreateClient.BUFFER_CACHE.invalidate(); - } - return; - } - - KineticTileEntity te = getSelectedTE(); - if (te == null) - return; - - Level world = Minecraft.getInstance().level; - BlockPos toOutline = te.hasSource() ? te.source : te.getBlockPos(); - BlockState state = te.getBlockState(); - VoxelShape shape = world.getBlockState(toOutline) - .getBlockSupportShape(world, toOutline); - - if (te.getTheoreticalSpeed() != 0 && !shape.isEmpty()) - CreateClient.OUTLINER.chaseAABB("kineticSource", shape.bounds() - .move(toOutline)) - .lineWidth(1 / 16f) - .colored(te.hasSource() ? Color.generateFromLong(te.network).getRGB() : 0xffcc00); - - if (state.getBlock() instanceof IRotate) { - Axis axis = ((IRotate) state.getBlock()).getRotationAxis(state); - Vec3 vec = Vec3.atLowerCornerOf(Direction.get(AxisDirection.POSITIVE, axis) - .getNormal()); - Vec3 center = VecHelper.getCenterOf(te.getBlockPos()); - CreateClient.OUTLINER.showLine("rotationAxis", center.add(vec), center.subtract(vec)) - .lineWidth(1 / 16f); - } - - } - - public static boolean isActive() { - return isF3DebugModeActive() && AllConfigs.CLIENT.rainbowDebug.get(); - } - - public static boolean isF3DebugModeActive() { - return Minecraft.getInstance().options.renderDebug; - } - - public static KineticTileEntity getSelectedTE() { - HitResult obj = Minecraft.getInstance().hitResult; - ClientLevel world = Minecraft.getInstance().level; - if (obj == null) - return null; - if (world == null) - return null; - if (!(obj instanceof BlockHitResult)) - return null; - - BlockHitResult ray = (BlockHitResult) obj; - BlockEntity te = world.getBlockEntity(ray.getBlockPos()); - if (!(te instanceof KineticTileEntity)) - return null; - - return (KineticTileEntity) te; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/KineticNetwork.java b/src/main/java/com/simibubi/create/content/contraptions/KineticNetwork.java deleted file mode 100644 index a3e06a424..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/KineticNetwork.java +++ /dev/null @@ -1,181 +0,0 @@ -package com.simibubi.create.content.contraptions; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -import com.simibubi.create.content.contraptions.base.KineticTileEntity; - -public class KineticNetwork { - - public Long id; - public boolean initialized; - public Map sources; - public Map members; - - private float currentCapacity; - private float currentStress; - private float unloadedCapacity; - private float unloadedStress; - private int unloadedMembers; - - public KineticNetwork() { - sources = new HashMap<>(); - members = new HashMap<>(); - } - - public void initFromTE(float maxStress, float currentStress, int members) { - unloadedCapacity = maxStress; - unloadedStress = currentStress; - unloadedMembers = members; - initialized = true; - updateStress(); - updateCapacity(); - } - - public void addSilently(KineticTileEntity te, float lastCapacity, float lastStress) { - if (members.containsKey(te)) - return; - if (te.isSource()) { - unloadedCapacity -= lastCapacity * getStressMultiplierForSpeed(te.getGeneratedSpeed()); - float addedStressCapacity = te.calculateAddedStressCapacity(); - sources.put(te, addedStressCapacity); - } - - unloadedStress -= lastStress * getStressMultiplierForSpeed(te.getTheoreticalSpeed()); - float stressApplied = te.calculateStressApplied(); - members.put(te, stressApplied); - - unloadedMembers--; - if (unloadedMembers < 0) - unloadedMembers = 0; - if (unloadedCapacity < 0) - unloadedCapacity = 0; - if (unloadedStress < 0) - unloadedStress = 0; - } - - public void add(KineticTileEntity te) { - if (members.containsKey(te)) - return; - if (te.isSource()) - sources.put(te, te.calculateAddedStressCapacity()); - members.put(te, te.calculateStressApplied()); - updateFromNetwork(te); - te.networkDirty = true; - } - - public void updateCapacityFor(KineticTileEntity te, float capacity) { - sources.put(te, capacity); - updateCapacity(); - } - - public void updateStressFor(KineticTileEntity te, float stress) { - members.put(te, stress); - updateStress(); - } - - public void remove(KineticTileEntity te) { - if (!members.containsKey(te)) - return; - if (te.isSource()) - sources.remove(te); - members.remove(te); - te.updateFromNetwork(0, 0, 0); - - if (members.isEmpty()) { - TorquePropagator.networks.get(te.getLevel()) - .remove(this.id); - return; - } - - members.keySet() - .stream() - .findFirst() - .map(member -> member.networkDirty = true); - } - - public void sync() { - for (KineticTileEntity te : members.keySet()) - updateFromNetwork(te); - } - - private void updateFromNetwork(KineticTileEntity te) { - te.updateFromNetwork(currentCapacity, currentStress, getSize()); - } - - public void updateCapacity() { - float newMaxStress = calculateCapacity(); - if (currentCapacity != newMaxStress) { - currentCapacity = newMaxStress; - sync(); - } - } - - public void updateStress() { - float newStress = calculateStress(); - if (currentStress != newStress) { - currentStress = newStress; - sync(); - } - } - - public void updateNetwork() { - float newStress = calculateStress(); - float newMaxStress = calculateCapacity(); - if (currentStress != newStress || currentCapacity != newMaxStress) { - currentStress = newStress; - currentCapacity = newMaxStress; - sync(); - } - } - - public float calculateCapacity() { - float presentCapacity = 0; - for (Iterator iterator = sources.keySet() - .iterator(); iterator.hasNext();) { - KineticTileEntity te = iterator.next(); - if (te.getLevel() - .getBlockEntity(te.getBlockPos()) != te) { - iterator.remove(); - continue; - } - presentCapacity += getActualCapacityOf(te); - } - float newMaxStress = presentCapacity + unloadedCapacity; - return newMaxStress; - } - - public float calculateStress() { - float presentStress = 0; - for (Iterator iterator = members.keySet() - .iterator(); iterator.hasNext();) { - KineticTileEntity te = iterator.next(); - if (te.getLevel() - .getBlockEntity(te.getBlockPos()) != te) { - iterator.remove(); - continue; - } - presentStress += getActualStressOf(te); - } - float newStress = presentStress + unloadedStress; - return newStress; - } - - public float getActualCapacityOf(KineticTileEntity te) { - return sources.get(te) * getStressMultiplierForSpeed(te.getGeneratedSpeed()); - } - - public float getActualStressOf(KineticTileEntity te) { - return members.get(te) * getStressMultiplierForSpeed(te.getTheoreticalSpeed()); - } - - private static float getStressMultiplierForSpeed(float speed) { - return Math.abs(speed); - } - - public int getSize() { - return unloadedMembers + members.size(); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/MountedFluidStorage.java b/src/main/java/com/simibubi/create/content/contraptions/MountedFluidStorage.java new file mode 100644 index 000000000..648995587 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/MountedFluidStorage.java @@ -0,0 +1,173 @@ +package com.simibubi.create.content.contraptions; + +import com.simibubi.create.AllPackets; +import com.simibubi.create.content.contraptions.sync.ContraptionFluidPacket; +import com.simibubi.create.content.fluids.tank.CreativeFluidTankBlockEntity; +import com.simibubi.create.content.fluids.tank.CreativeFluidTankBlockEntity.CreativeSmartFluidTank; +import com.simibubi.create.content.fluids.tank.FluidTankBlockEntity; +import com.simibubi.create.foundation.fluid.SmartFluidTank; +import com.simibubi.create.foundation.utility.NBTHelper; +import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.IFluidTank; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.network.PacketDistributor; + +public class MountedFluidStorage { + + SmartFluidTank tank; + private boolean valid; + private BlockEntity blockEntity; + + private int packetCooldown = 0; + private boolean sendPacket = false; + + public static boolean canUseAsStorage(BlockEntity be) { + if (be instanceof FluidTankBlockEntity) + return ((FluidTankBlockEntity) be).isController(); + return false; + } + + public MountedFluidStorage(BlockEntity be) { + assignBlockEntity(be); + } + + public void assignBlockEntity(BlockEntity be) { + this.blockEntity = be; + tank = createMountedTank(be); + } + + private SmartFluidTank createMountedTank(BlockEntity be) { + if (be instanceof CreativeFluidTankBlockEntity) + return new CreativeSmartFluidTank( + ((FluidTankBlockEntity) be).getTotalTankSize() * FluidTankBlockEntity.getCapacityMultiplier(), $ -> { + }); + if (be instanceof FluidTankBlockEntity) + return new SmartFluidTank( + ((FluidTankBlockEntity) be).getTotalTankSize() * FluidTankBlockEntity.getCapacityMultiplier(), + this::onFluidStackChanged); + return null; + } + + public void tick(Entity entity, BlockPos pos, boolean isRemote) { + if (!isRemote) { + if (packetCooldown > 0) + packetCooldown--; + else if (sendPacket) { + sendPacket = false; + AllPackets.getChannel().send(PacketDistributor.TRACKING_ENTITY.with(() -> entity), + new ContraptionFluidPacket(entity.getId(), pos, tank.getFluid())); + packetCooldown = 8; + } + return; + } + + if (!(blockEntity instanceof FluidTankBlockEntity)) + return; + FluidTankBlockEntity tank = (FluidTankBlockEntity) blockEntity; + tank.getFluidLevel() + .tickChaser(); + } + + public void updateFluid(FluidStack fluid) { + tank.setFluid(fluid); + if (!(blockEntity instanceof FluidTankBlockEntity)) + return; + float fillState = tank.getFluidAmount() / (float) tank.getCapacity(); + FluidTankBlockEntity tank = (FluidTankBlockEntity) blockEntity; + if (tank.getFluidLevel() == null) + tank.setFluidLevel(LerpedFloat.linear() + .startWithValue(fillState)); + tank.getFluidLevel() + .chase(fillState, 0.5, Chaser.EXP); + IFluidTank tankInventory = tank.getTankInventory(); + if (tankInventory instanceof SmartFluidTank) + ((SmartFluidTank) tankInventory).setFluid(fluid); + } + + public void removeStorageFromWorld() { + valid = false; + if (blockEntity == null) + return; + + IFluidHandler teHandler = blockEntity.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) + .orElse(null); + if (!(teHandler instanceof SmartFluidTank)) + return; + SmartFluidTank smartTank = (SmartFluidTank) teHandler; + tank.setFluid(smartTank.getFluid()); + sendPacket = false; + valid = true; + } + + private void onFluidStackChanged(FluidStack fs) { + sendPacket = true; + } + + public void addStorageToWorld(BlockEntity be) { + if (tank instanceof CreativeSmartFluidTank) + return; + + LazyOptional capability = be.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY); + IFluidHandler teHandler = capability.orElse(null); + if (!(teHandler instanceof SmartFluidTank)) + return; + + SmartFluidTank inv = (SmartFluidTank) teHandler; + inv.setFluid(tank.getFluid() + .copy()); + } + + public IFluidHandler getFluidHandler() { + return tank; + } + + public CompoundTag serialize() { + if (!valid) + return null; + CompoundTag tag = tank.writeToNBT(new CompoundTag()); + tag.putInt("Capacity", tank.getCapacity()); + + if (tank instanceof CreativeSmartFluidTank) { + NBTHelper.putMarker(tag, "Bottomless"); + tag.put("ProvidedStack", tank.getFluid() + .writeToNBT(new CompoundTag())); + } + return tag; + } + + public static MountedFluidStorage deserialize(CompoundTag nbt) { + MountedFluidStorage storage = new MountedFluidStorage(null); + if (nbt == null) + return storage; + + int capacity = nbt.getInt("Capacity"); + storage.tank = new SmartFluidTank(capacity, storage::onFluidStackChanged); + storage.valid = true; + + if (nbt.contains("Bottomless")) { + FluidStack providedStack = FluidStack.loadFluidStackFromNBT(nbt.getCompound("ProvidedStack")); + CreativeSmartFluidTank creativeSmartFluidTank = new CreativeSmartFluidTank(capacity, $ -> { + }); + creativeSmartFluidTank.setContainedFluid(providedStack); + storage.tank = creativeSmartFluidTank; + return storage; + } + + storage.tank.readFromNBT(nbt); + return storage; + } + + public boolean isValid() { + return valid; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/MountedStorage.java b/src/main/java/com/simibubi/create/content/contraptions/MountedStorage.java new file mode 100644 index 000000000..cf310f026 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/MountedStorage.java @@ -0,0 +1,215 @@ +package com.simibubi.create.content.contraptions; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllTags.AllBlockTags; +import com.simibubi.create.content.kinetics.crafter.MechanicalCrafterBlockEntity; +import com.simibubi.create.content.logistics.crate.BottomlessItemHandler; +import com.simibubi.create.content.logistics.vault.ItemVaultBlockEntity; +import com.simibubi.create.content.processing.recipe.ProcessingInventory; +import com.simibubi.create.foundation.utility.NBTHelper; + +import net.minecraft.core.NonNullList; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.ContainerHelper; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BarrelBlockEntity; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.ChestBlockEntity; +import net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.ItemStackHandler; +import net.minecraftforge.registries.ForgeRegistries; + +public class MountedStorage { + + private static final ItemStackHandler dummyHandler = new ItemStackHandler(); + + ItemStackHandler handler; + boolean noFuel; + boolean valid; + + private BlockEntity blockEntity; + + public static boolean canUseAsStorage(BlockEntity be) { + if (be == null) + return false; + if (be instanceof MechanicalCrafterBlockEntity) + return false; + if (AllBlockEntityTypes.CREATIVE_CRATE.is(be)) + return true; + if (be instanceof ShulkerBoxBlockEntity) + return true; + if (be instanceof ChestBlockEntity) + return true; + if (be instanceof BarrelBlockEntity) + return true; + if (be instanceof ItemVaultBlockEntity) + return true; + + try { + LazyOptional capability = be.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY); + IItemHandler handler = capability.orElse(null); + if (handler instanceof ItemStackHandler) + return !(handler instanceof ProcessingInventory); + return canUseModdedInventory(be, handler); + + } catch (Exception e) { + return false; + } + } + + public static boolean canUseModdedInventory(BlockEntity be, IItemHandler handler) { + if (!(handler instanceof IItemHandlerModifiable validItemHandler)) + return false; + BlockState blockState = be.getBlockState(); + if (AllBlockTags.CONTRAPTION_INVENTORY_DENY.matches(blockState)) + return false; + + // There doesn't appear to be much of a standard for tagging chests/barrels + String blockId = ForgeRegistries.BLOCKS.getKey(blockState.getBlock()) + .getPath(); + if (blockId.contains("ender")) + return false; + return blockId.endsWith("_chest") || blockId.endsWith("_barrel"); + } + + public MountedStorage(BlockEntity be) { + this.blockEntity = be; + handler = dummyHandler; + noFuel = be instanceof ItemVaultBlockEntity; + } + + public void removeStorageFromWorld() { + valid = false; + if (blockEntity == null) + return; + + if (blockEntity instanceof ChestBlockEntity) { + CompoundTag tag = blockEntity.saveWithFullMetadata(); + if (tag.contains("LootTable", 8)) + return; + + handler = new ItemStackHandler(((ChestBlockEntity) blockEntity).getContainerSize()); + NonNullList items = NonNullList.withSize(handler.getSlots(), ItemStack.EMPTY); + ContainerHelper.loadAllItems(tag, items); + for (int i = 0; i < items.size(); i++) + handler.setStackInSlot(i, items.get(i)); + valid = true; + return; + } + + IItemHandler beHandler = blockEntity.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) + .orElse(dummyHandler); + if (beHandler == dummyHandler) + return; + + // multiblock vaults need to provide individual invs + if (blockEntity instanceof ItemVaultBlockEntity) { + handler = ((ItemVaultBlockEntity) blockEntity).getInventoryOfBlock(); + valid = true; + return; + } + + // be uses ItemStackHandler + if (beHandler instanceof ItemStackHandler) { + handler = (ItemStackHandler) beHandler; + valid = true; + return; + } + + // serialization not accessible -> fill into a serializable handler + if (beHandler instanceof IItemHandlerModifiable) { + IItemHandlerModifiable inv = (IItemHandlerModifiable) beHandler; + handler = new ItemStackHandler(beHandler.getSlots()); + for (int slot = 0; slot < handler.getSlots(); slot++) { + handler.setStackInSlot(slot, inv.getStackInSlot(slot)); + inv.setStackInSlot(slot, ItemStack.EMPTY); + } + valid = true; + return; + } + + } + + public void addStorageToWorld(BlockEntity be) { + // FIXME: More dynamic mounted storage in .4 + if (handler instanceof BottomlessItemHandler) + return; + + if (be instanceof ChestBlockEntity) { + CompoundTag tag = be.saveWithFullMetadata(); + tag.remove("Items"); + NonNullList items = NonNullList.withSize(handler.getSlots(), ItemStack.EMPTY); + for (int i = 0; i < items.size(); i++) + items.set(i, handler.getStackInSlot(i)); + ContainerHelper.saveAllItems(tag, items); + be.load(tag); + return; + } + + if (be instanceof ItemVaultBlockEntity) { + ((ItemVaultBlockEntity) be).applyInventoryToBlock(handler); + return; + } + + LazyOptional capability = be.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY); + IItemHandler teHandler = capability.orElse(null); + if (!(teHandler instanceof IItemHandlerModifiable)) + return; + + IItemHandlerModifiable inv = (IItemHandlerModifiable) teHandler; + for (int slot = 0; slot < Math.min(inv.getSlots(), handler.getSlots()); slot++) + inv.setStackInSlot(slot, handler.getStackInSlot(slot)); + } + + public IItemHandlerModifiable getItemHandler() { + return handler; + } + + public CompoundTag serialize() { + if (!valid) + return null; + + CompoundTag tag = handler.serializeNBT(); + if (noFuel) + NBTHelper.putMarker(tag, "NoFuel"); + if (!(handler instanceof BottomlessItemHandler)) + return tag; + + NBTHelper.putMarker(tag, "Bottomless"); + tag.put("ProvidedStack", handler.getStackInSlot(0) + .serializeNBT()); + return tag; + } + + public static MountedStorage deserialize(CompoundTag nbt) { + MountedStorage storage = new MountedStorage(null); + storage.handler = new ItemStackHandler(); + if (nbt == null) + return storage; + storage.valid = true; + storage.noFuel = nbt.contains("NoFuel"); + + if (nbt.contains("Bottomless")) { + ItemStack providedStack = ItemStack.of(nbt.getCompound("ProvidedStack")); + storage.handler = new BottomlessItemHandler(() -> providedStack); + return storage; + } + + storage.handler.deserializeNBT(nbt); + return storage; + } + + public boolean isValid() { + return valid; + } + + public boolean canUseForFuel() { + return !noFuel; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/MountedStorageInteraction.java b/src/main/java/com/simibubi/create/content/contraptions/MountedStorageInteraction.java new file mode 100644 index 000000000..da84498db --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/MountedStorageInteraction.java @@ -0,0 +1,68 @@ +package com.simibubi.create.content.contraptions; + +import java.util.List; +import java.util.function.Supplier; + +import com.google.common.collect.ImmutableList; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.network.chat.Component; +import net.minecraft.util.Mth; +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.ChestMenu; +import net.minecraft.world.inventory.MenuType; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.wrapper.RecipeWrapper; + +public class MountedStorageInteraction { + + public static final List> menus = ImmutableList.of(MenuType.GENERIC_9x1, MenuType.GENERIC_9x2, + MenuType.GENERIC_9x3, MenuType.GENERIC_9x4, MenuType.GENERIC_9x5, MenuType.GENERIC_9x6); + + public static MenuProvider createMenuProvider(Component displayName, IItemHandlerModifiable handler, + int slotCount, Supplier stillValid) { + int rows = Mth.clamp(slotCount / 9, 1, 6); + MenuType menuType = menus.get(rows - 1); + Component menuName = Lang.translateDirect("contraptions.moving_container", displayName); + + return new MenuProvider() { + + @Override + public AbstractContainerMenu createMenu(int pContainerId, Inventory pPlayerInventory, Player pPlayer) { + return new ChestMenu(menuType, pContainerId, pPlayerInventory, new StorageInteractionContainer(handler, stillValid), + rows); + } + + @Override + public Component getDisplayName() { + return menuName; + } + + }; + } + + public static class StorageInteractionContainer extends RecipeWrapper { + + private Supplier stillValid; + + public StorageInteractionContainer(IItemHandlerModifiable inv, Supplier stillValid) { + super(inv); + this.stillValid = stillValid; + } + + @Override + public boolean stillValid(Player player) { + return stillValid.get(); + } + + @Override + public int getMaxStackSize() { + return 64; + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/MountedStorageManager.java b/src/main/java/com/simibubi/create/content/contraptions/MountedStorageManager.java new file mode 100644 index 000000000..240f74575 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/MountedStorageManager.java @@ -0,0 +1,262 @@ +package com.simibubi.create.content.contraptions; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +import com.simibubi.create.content.contraptions.Contraption.ContraptionInvWrapper; +import com.simibubi.create.content.fluids.tank.FluidTankBlockEntity; +import com.simibubi.create.foundation.fluid.CombinedTankWrapper; +import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.NBTHelper; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.Component; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.ChestBlock; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.properties.ChestType; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.IFluidTank; +import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction; +import net.minecraftforge.fluids.capability.templates.FluidTank; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.wrapper.CombinedInvWrapper; + +public class MountedStorageManager { + + protected ContraptionInvWrapper inventory; + protected ContraptionInvWrapper fuelInventory; + protected CombinedTankWrapper fluidInventory; + protected Map storage; + protected Map fluidStorage; + + public MountedStorageManager() { + storage = new HashMap<>(); + fluidStorage = new HashMap<>(); + } + + public void entityTick(AbstractContraptionEntity entity) { + fluidStorage.forEach((pos, mfs) -> mfs.tick(entity, pos, entity.level.isClientSide)); + } + + public void createHandlers() { + Collection itemHandlers = storage.values(); + + inventory = wrapItems(itemHandlers.stream() + .map(MountedStorage::getItemHandler) + .toList(), false); + + fuelInventory = wrapItems(itemHandlers.stream() + .filter(MountedStorage::canUseForFuel) + .map(MountedStorage::getItemHandler) + .toList(), true); + + fluidInventory = wrapFluids(fluidStorage.values() + .stream() + .map(MountedFluidStorage::getFluidHandler) + .collect(Collectors.toList())); + } + + protected ContraptionInvWrapper wrapItems(Collection list, boolean fuel) { + return new ContraptionInvWrapper(Arrays.copyOf(list.toArray(), list.size(), IItemHandlerModifiable[].class)); + } + + protected CombinedTankWrapper wrapFluids(Collection list) { + return new CombinedTankWrapper(Arrays.copyOf(list.toArray(), list.size(), IFluidHandler[].class)); + } + + public void addBlock(BlockPos localPos, BlockEntity be) { + if (be != null && MountedStorage.canUseAsStorage(be)) + storage.put(localPos, new MountedStorage(be)); + if (be != null && MountedFluidStorage.canUseAsStorage(be)) + fluidStorage.put(localPos, new MountedFluidStorage(be)); + } + + public void read(CompoundTag nbt, Map presentBlockEntities, boolean clientPacket) { + storage.clear(); + NBTHelper.iterateCompoundList(nbt.getList("Storage", Tag.TAG_COMPOUND), c -> storage + .put(NbtUtils.readBlockPos(c.getCompound("Pos")), MountedStorage.deserialize(c.getCompound("Data")))); + + fluidStorage.clear(); + NBTHelper.iterateCompoundList(nbt.getList("FluidStorage", Tag.TAG_COMPOUND), c -> fluidStorage + .put(NbtUtils.readBlockPos(c.getCompound("Pos")), MountedFluidStorage.deserialize(c.getCompound("Data")))); + + if (clientPacket && presentBlockEntities != null) + bindTanks(presentBlockEntities); + + List handlers = new ArrayList<>(); + List fuelHandlers = new ArrayList<>(); + for (MountedStorage mountedStorage : storage.values()) { + IItemHandlerModifiable itemHandler = mountedStorage.getItemHandler(); + handlers.add(itemHandler); + if (mountedStorage.canUseForFuel()) + fuelHandlers.add(itemHandler); + } + + inventory = wrapItems(handlers, false); + fuelInventory = wrapItems(fuelHandlers, true); + fluidInventory = wrapFluids(fluidStorage.values() + .stream() + .map(MountedFluidStorage::getFluidHandler) + .toList()); + } + + public void bindTanks(Map presentBlockEntities) { + fluidStorage.forEach((pos, mfs) -> { + BlockEntity blockEntity = presentBlockEntities.get(pos); + if (!(blockEntity instanceof FluidTankBlockEntity)) + return; + FluidTankBlockEntity tank = (FluidTankBlockEntity) blockEntity; + IFluidTank tankInventory = tank.getTankInventory(); + if (tankInventory instanceof FluidTank) + ((FluidTank) tankInventory).setFluid(mfs.tank.getFluid()); + tank.getFluidLevel() + .startWithValue(tank.getFillState()); + mfs.assignBlockEntity(tank); + }); + } + + public void write(CompoundTag nbt, boolean clientPacket) { + ListTag storageNBT = new ListTag(); + if (!clientPacket) + for (BlockPos pos : storage.keySet()) { + CompoundTag c = new CompoundTag(); + MountedStorage mountedStorage = storage.get(pos); + if (!mountedStorage.isValid()) + continue; + c.put("Pos", NbtUtils.writeBlockPos(pos)); + c.put("Data", mountedStorage.serialize()); + storageNBT.add(c); + } + + ListTag fluidStorageNBT = new ListTag(); + for (BlockPos pos : fluidStorage.keySet()) { + CompoundTag c = new CompoundTag(); + MountedFluidStorage mountedStorage = fluidStorage.get(pos); + if (!mountedStorage.isValid()) + continue; + c.put("Pos", NbtUtils.writeBlockPos(pos)); + c.put("Data", mountedStorage.serialize()); + fluidStorageNBT.add(c); + } + + nbt.put("Storage", storageNBT); + nbt.put("FluidStorage", fluidStorageNBT); + } + + public void removeStorageFromWorld() { + storage.values() + .forEach(MountedStorage::removeStorageFromWorld); + fluidStorage.values() + .forEach(MountedFluidStorage::removeStorageFromWorld); + } + + public void addStorageToWorld(StructureBlockInfo block, BlockEntity blockEntity) { + if (storage.containsKey(block.pos)) { + MountedStorage mountedStorage = storage.get(block.pos); + if (mountedStorage.isValid()) + mountedStorage.addStorageToWorld(blockEntity); + } + + if (fluidStorage.containsKey(block.pos)) { + MountedFluidStorage mountedStorage = fluidStorage.get(block.pos); + if (mountedStorage.isValid()) + mountedStorage.addStorageToWorld(blockEntity); + } + } + + public void clear() { + for (int i = 0; i < inventory.getSlots(); i++) + if (!inventory.isSlotExternal(i)) + inventory.setStackInSlot(i, ItemStack.EMPTY); + for (int i = 0; i < fluidInventory.getTanks(); i++) + fluidInventory.drain(fluidInventory.getFluidInTank(i), FluidAction.EXECUTE); + } + + public void updateContainedFluid(BlockPos localPos, FluidStack containedFluid) { + MountedFluidStorage mountedFluidStorage = fluidStorage.get(localPos); + if (mountedFluidStorage != null) + mountedFluidStorage.updateFluid(containedFluid); + } + + public void attachExternal(IItemHandlerModifiable externalStorage) { + inventory = new ContraptionInvWrapper(externalStorage, inventory); + fuelInventory = new ContraptionInvWrapper(externalStorage, fuelInventory); + } + + public IItemHandlerModifiable getItems() { + return inventory; + } + + public IItemHandlerModifiable getFuelItems() { + return fuelInventory; + } + + public IFluidHandler getFluids() { + return fluidInventory; + } + + public boolean handlePlayerStorageInteraction(Contraption contraption, Player player, BlockPos localPos) { + if (player.level.isClientSide()) { + BlockEntity localBE = contraption.presentBlockEntities.get(localPos); + return MountedStorage.canUseAsStorage(localBE); + } + + MountedStorageManager storageManager = contraption.getStorageForSpawnPacket(); + MountedStorage storage = storageManager.storage.get(localPos); + if (storage == null || storage.getItemHandler() == null) + return false; + IItemHandlerModifiable handler = storage.getItemHandler(); + + StructureBlockInfo info = contraption.getBlocks() + .get(localPos); + if (info != null && info.state.hasProperty(ChestBlock.TYPE)) { + ChestType chestType = info.state.getValue(ChestBlock.TYPE); + Direction facing = info.state.getOptionalValue(ChestBlock.FACING) + .orElse(Direction.SOUTH); + Direction connectedDirection = + chestType == ChestType.LEFT ? facing.getClockWise() : facing.getCounterClockWise(); + + if (chestType != ChestType.SINGLE) { + MountedStorage storage2 = storageManager.storage.get(localPos.relative(connectedDirection)); + if (storage2 != null && storage2.getItemHandler() != null) + handler = chestType == ChestType.RIGHT ? new CombinedInvWrapper(handler, storage2.getItemHandler()) + : new CombinedInvWrapper(storage2.getItemHandler(), handler); + } + } + + int slotCount = handler.getSlots(); + if (slotCount == 0) + return false; + if (slotCount % 9 != 0) + return false; + + Supplier stillValid = () -> contraption.entity.isAlive() + && player.distanceToSqr(contraption.entity.toGlobalVector(Vec3.atCenterOf(localPos), 0)) < 64; + Component name = info != null ? info.state.getBlock() + .getName() : Components.literal("Container"); + player.openMenu(MountedStorageInteraction.createMenuProvider(name, handler, slotCount, stillValid)); + + Vec3 soundPos = contraption.entity.toGlobalVector(Vec3.atCenterOf(localPos), 0); + player.level.playSound(null, new BlockPos(soundPos), SoundEvents.BARREL_OPEN, SoundSource.BLOCKS, 0.75f, 1f); + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/OrientedContraptionEntity.java b/src/main/java/com/simibubi/create/content/contraptions/OrientedContraptionEntity.java similarity index 96% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/OrientedContraptionEntity.java rename to src/main/java/com/simibubi/create/content/contraptions/OrientedContraptionEntity.java index cb9fbaa20..41879519b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/OrientedContraptionEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/OrientedContraptionEntity.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.structureMovement; +package com.simibubi.create.content.contraptions; import static com.simibubi.create.foundation.utility.AngleHelper.angleLerp; @@ -10,12 +10,12 @@ import javax.annotation.Nullable; import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllEntityTypes; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.StabilizedContraption; -import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerTileEntity.CartMovementMode; -import com.simibubi.create.content.contraptions.components.structureMovement.mounted.MountedContraption; -import com.simibubi.create.content.contraptions.components.structureMovement.train.MinecartSim2020; -import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.CapabilityMinecartController; -import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.MinecartController; +import com.simibubi.create.content.contraptions.bearing.StabilizedContraption; +import com.simibubi.create.content.contraptions.minecart.MinecartSim2020; +import com.simibubi.create.content.contraptions.minecart.capability.CapabilityMinecartController; +import com.simibubi.create.content.contraptions.minecart.capability.MinecartController; +import com.simibubi.create.content.contraptions.mounted.CartAssemblerBlockEntity.CartMovementMode; +import com.simibubi.create.content.contraptions.mounted.MountedContraption; import com.simibubi.create.foundation.item.ItemHelper; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.Couple; diff --git a/src/main/java/com/simibubi/create/content/contraptions/RotationPropagator.java b/src/main/java/com/simibubi/create/content/contraptions/RotationPropagator.java deleted file mode 100644 index acc77ac8f..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/RotationPropagator.java +++ /dev/null @@ -1,445 +0,0 @@ -package com.simibubi.create.content.contraptions; - -import static net.minecraft.world.level.block.state.properties.BlockStateProperties.AXIS; - -import java.util.LinkedList; -import java.util.List; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.base.IRotate; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.relays.advanced.SpeedControllerBlock; -import com.simibubi.create.content.contraptions.relays.advanced.SpeedControllerTileEntity; -import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock; -import com.simibubi.create.content.contraptions.relays.elementary.ICogWheel; -import com.simibubi.create.content.contraptions.relays.encased.DirectionalShaftHalvesTileEntity; -import com.simibubi.create.content.contraptions.relays.encased.EncasedBeltBlock; -import com.simibubi.create.content.contraptions.relays.encased.SplitShaftTileEntity; -import com.simibubi.create.content.contraptions.relays.gearbox.GearboxTileEntity; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.utility.Iterate; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -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; - - -public class RotationPropagator { - - private static final int MAX_FLICKER_SCORE = 128; - - /** - * Determines the change in rotation between two attached kinetic entities. For - * instance, an axis connection returns 1 while a 1-to-1 gear connection - * reverses the rotation and therefore returns -1. - * - * @param from - * @param to - * @return - */ - private static float getRotationSpeedModifier(KineticTileEntity from, KineticTileEntity to) { - final BlockState stateFrom = from.getBlockState(); - final BlockState stateTo = to.getBlockState(); - - Block fromBlock = stateFrom.getBlock(); - Block toBlock = stateTo.getBlock(); - if (!(fromBlock instanceof IRotate && toBlock instanceof IRotate)) - return 0; - - final IRotate definitionFrom = (IRotate) fromBlock; - final IRotate definitionTo = (IRotate) toBlock; - final BlockPos diff = to.getBlockPos() - .subtract(from.getBlockPos()); - final Direction direction = Direction.getNearest(diff.getX(), diff.getY(), diff.getZ()); - final Level world = from.getLevel(); - - boolean alignedAxes = true; - for (Axis axis : Axis.values()) - if (axis != direction.getAxis()) - if (axis.choose(diff.getX(), diff.getY(), diff.getZ()) != 0) - alignedAxes = false; - - boolean connectedByAxis = - alignedAxes && definitionFrom.hasShaftTowards(world, from.getBlockPos(), stateFrom, direction) - && definitionTo.hasShaftTowards(world, to.getBlockPos(), stateTo, direction.getOpposite()); - - boolean connectedByGears = ICogWheel.isSmallCog(stateFrom) - && ICogWheel.isSmallCog(stateTo); - - float custom = from.propagateRotationTo(to, stateFrom, stateTo, diff, connectedByAxis, connectedByGears); - if (custom != 0) - return custom; - - // Axis <-> Axis - if (connectedByAxis) { - float axisModifier = getAxisModifier(to, direction.getOpposite()); - if (axisModifier != 0) - axisModifier = 1 / axisModifier; - return getAxisModifier(from, direction) * axisModifier; - } - - // Attached Encased Belts - if (fromBlock instanceof EncasedBeltBlock && toBlock instanceof EncasedBeltBlock) { - boolean connected = EncasedBeltBlock.areBlocksConnected(stateFrom, stateTo, direction); - return connected ? EncasedBeltBlock.getRotationSpeedModifier(from, to) : 0; - } - - // Large Gear <-> Large Gear - if (isLargeToLargeGear(stateFrom, stateTo, diff)) { - Axis sourceAxis = stateFrom.getValue(AXIS); - Axis targetAxis = stateTo.getValue(AXIS); - int sourceAxisDiff = sourceAxis.choose(diff.getX(), diff.getY(), diff.getZ()); - int targetAxisDiff = targetAxis.choose(diff.getX(), diff.getY(), diff.getZ()); - - return sourceAxisDiff > 0 ^ targetAxisDiff > 0 ? -1 : 1; - } - - // Gear <-> Large Gear - if (ICogWheel.isLargeCog(stateFrom) && ICogWheel.isSmallCog(stateTo)) - if (isLargeToSmallCog(stateFrom, stateTo, definitionTo, diff)) - return -2f; - if (ICogWheel.isLargeCog(stateTo) && ICogWheel.isSmallCog(stateFrom)) - if (isLargeToSmallCog(stateTo, stateFrom, definitionFrom, diff)) - return -.5f; - - // Gear <-> Gear - if (connectedByGears) { - if (diff.distManhattan(BlockPos.ZERO) != 1) - return 0; - if (ICogWheel.isLargeCog(stateTo)) - return 0; - if (direction.getAxis() == definitionFrom.getRotationAxis(stateFrom)) - return 0; - if (definitionFrom.getRotationAxis(stateFrom) == definitionTo.getRotationAxis(stateTo)) - return -1; - } - - return 0; - } - - private static float getConveyedSpeed(KineticTileEntity from, KineticTileEntity to) { - final BlockState stateFrom = from.getBlockState(); - final BlockState stateTo = to.getBlockState(); - - // Rotation Speed Controller <-> Large Gear - if (isLargeCogToSpeedController(stateFrom, stateTo, to.getBlockPos() - .subtract(from.getBlockPos()))) - return SpeedControllerTileEntity.getConveyedSpeed(from, to, true); - if (isLargeCogToSpeedController(stateTo, stateFrom, from.getBlockPos() - .subtract(to.getBlockPos()))) - return SpeedControllerTileEntity.getConveyedSpeed(to, from, false); - - float rotationSpeedModifier = getRotationSpeedModifier(from, to); - return from.getTheoreticalSpeed() * rotationSpeedModifier; - } - - private static boolean isLargeToLargeGear(BlockState from, BlockState to, BlockPos diff) { - if (!ICogWheel.isLargeCog(from) || !ICogWheel.isLargeCog(to)) - return false; - Axis fromAxis = from.getValue(AXIS); - Axis toAxis = to.getValue(AXIS); - if (fromAxis == toAxis) - return false; - for (Axis axis : Axis.values()) { - int axisDiff = axis.choose(diff.getX(), diff.getY(), diff.getZ()); - if (axis == fromAxis || axis == toAxis) { - if (axisDiff == 0) - return false; - - } else if (axisDiff != 0) - return false; - } - return true; - } - - private static float getAxisModifier(KineticTileEntity te, Direction direction) { - if (!(te.hasSource()||te.isSource()) || !(te instanceof DirectionalShaftHalvesTileEntity)) - return 1; - Direction source = ((DirectionalShaftHalvesTileEntity) te).getSourceFacing(); - - if (te instanceof GearboxTileEntity) - return direction.getAxis() == source.getAxis() ? direction == source ? 1 : -1 - : direction.getAxisDirection() == source.getAxisDirection() ? -1 : 1; - - if (te instanceof SplitShaftTileEntity) - return ((SplitShaftTileEntity) te).getRotationSpeedModifier(direction); - - return 1; - } - - private static boolean isLargeToSmallCog(BlockState from, BlockState to, IRotate defTo, BlockPos diff) { - Axis axisFrom = from.getValue(AXIS); - if (axisFrom != defTo.getRotationAxis(to)) - return false; - if (axisFrom.choose(diff.getX(), diff.getY(), diff.getZ()) != 0) - return false; - for (Axis axis : Axis.values()) { - if (axis == axisFrom) - continue; - if (Math.abs(axis.choose(diff.getX(), diff.getY(), diff.getZ())) != 1) - return false; - } - return true; - } - - private static boolean isLargeCogToSpeedController(BlockState from, BlockState to, BlockPos diff) { - if (!ICogWheel.isLargeCog(from) || !AllBlocks.ROTATION_SPEED_CONTROLLER.has(to)) - return false; - if (!diff.equals(BlockPos.ZERO.below())) - return false; - Axis axis = from.getValue(CogWheelBlock.AXIS); - if (axis.isVertical()) - return false; - if (to.getValue(SpeedControllerBlock.HORIZONTAL_AXIS) == axis) - return false; - return true; - } - - /** - * Insert the added position to the kinetic network. - * - * @param worldIn - * @param pos - */ - public static void handleAdded(Level worldIn, BlockPos pos, KineticTileEntity addedTE) { - if (worldIn.isClientSide) - return; - if (!worldIn.isLoaded(pos)) - return; - propagateNewSource(addedTE); - } - - /** - * Search for sourceless networks attached to the given entity and update them. - * - * @param currentTE - */ - private static void propagateNewSource(KineticTileEntity currentTE) { - BlockPos pos = currentTE.getBlockPos(); - Level world = currentTE.getLevel(); - - for (KineticTileEntity neighbourTE : getConnectedNeighbours(currentTE)) { - float speedOfCurrent = currentTE.getTheoreticalSpeed(); - float speedOfNeighbour = neighbourTE.getTheoreticalSpeed(); - float newSpeed = getConveyedSpeed(currentTE, neighbourTE); - float oppositeSpeed = getConveyedSpeed(neighbourTE, currentTE); - - if (newSpeed == 0 && oppositeSpeed == 0) - continue; - - boolean incompatible = - Math.signum(newSpeed) != Math.signum(speedOfNeighbour) && (newSpeed != 0 && speedOfNeighbour != 0); - - boolean tooFast = Math.abs(newSpeed) > AllConfigs.SERVER.kinetics.maxRotationSpeed.get() - || Math.abs(oppositeSpeed) > AllConfigs.SERVER.kinetics.maxRotationSpeed.get(); - // Check for both the new speed and the opposite speed, just in case - - boolean speedChangedTooOften = currentTE.getFlickerScore() > MAX_FLICKER_SCORE; - if (tooFast || speedChangedTooOften) { - world.destroyBlock(pos, true); - return; - } - - // Opposite directions - if (incompatible) { - world.destroyBlock(pos, true); - return; - - // Same direction: overpower the slower speed - } else { - - // Neighbour faster, overpower the incoming tree - if (Math.abs(oppositeSpeed) > Math.abs(speedOfCurrent)) { - float prevSpeed = currentTE.getSpeed(); - currentTE.setSource(neighbourTE.getBlockPos()); - currentTE.setSpeed(getConveyedSpeed(neighbourTE, currentTE)); - currentTE.onSpeedChanged(prevSpeed); - currentTE.sendData(); - - propagateNewSource(currentTE); - return; - } - - // Current faster, overpower the neighbours' tree - if (Math.abs(newSpeed) >= Math.abs(speedOfNeighbour)) { - - // Do not overpower you own network -> cycle - if (!currentTE.hasNetwork() || currentTE.network.equals(neighbourTE.network)) { - float epsilon = Math.abs(speedOfNeighbour) / 256f / 256f; - if (Math.abs(newSpeed) > Math.abs(speedOfNeighbour) + epsilon) - world.destroyBlock(pos, true); - continue; - } - - if (currentTE.hasSource() && currentTE.source.equals(neighbourTE.getBlockPos())) - currentTE.removeSource(); - - float prevSpeed = neighbourTE.getSpeed(); - neighbourTE.setSource(currentTE.getBlockPos()); - neighbourTE.setSpeed(getConveyedSpeed(currentTE, neighbourTE)); - neighbourTE.onSpeedChanged(prevSpeed); - neighbourTE.sendData(); - propagateNewSource(neighbourTE); - continue; - } - } - - if (neighbourTE.getTheoreticalSpeed() == newSpeed) - continue; - - float prevSpeed = neighbourTE.getSpeed(); - neighbourTE.setSpeed(newSpeed); - neighbourTE.setSource(currentTE.getBlockPos()); - neighbourTE.onSpeedChanged(prevSpeed); - neighbourTE.sendData(); - propagateNewSource(neighbourTE); - - } - } - - /** - * Remove the given entity from the network. - * - * @param worldIn - * @param pos - * @param removedTE - */ - public static void handleRemoved(Level worldIn, BlockPos pos, KineticTileEntity removedTE) { - if (worldIn.isClientSide) - return; - if (removedTE == null) - return; - if (removedTE.getTheoreticalSpeed() == 0) - return; - - for (BlockPos neighbourPos : getPotentialNeighbourLocations(removedTE)) { - BlockState neighbourState = worldIn.getBlockState(neighbourPos); - if (!(neighbourState.getBlock() instanceof IRotate)) - continue; - BlockEntity tileEntity = worldIn.getBlockEntity(neighbourPos); - if (!(tileEntity instanceof KineticTileEntity)) - continue; - - final KineticTileEntity neighbourTE = (KineticTileEntity) tileEntity; - if (!neighbourTE.hasSource() || !neighbourTE.source.equals(pos)) - continue; - - propagateMissingSource(neighbourTE); - } - - } - - /** - * Clear the entire subnetwork depending on the given entity and find a new - * source - * - * @param updateTE - */ - private static void propagateMissingSource(KineticTileEntity updateTE) { - final Level world = updateTE.getLevel(); - - List potentialNewSources = new LinkedList<>(); - List frontier = new LinkedList<>(); - frontier.add(updateTE.getBlockPos()); - BlockPos missingSource = updateTE.hasSource() ? updateTE.source : null; - - while (!frontier.isEmpty()) { - final BlockPos pos = frontier.remove(0); - BlockEntity tileEntity = world.getBlockEntity(pos); - if (!(tileEntity instanceof KineticTileEntity)) - continue; - final KineticTileEntity currentTE = (KineticTileEntity) tileEntity; - - currentTE.removeSource(); - currentTE.sendData(); - - for (KineticTileEntity neighbourTE : getConnectedNeighbours(currentTE)) { - if (neighbourTE.getBlockPos() - .equals(missingSource)) - continue; - if (!neighbourTE.hasSource()) - continue; - - if (!neighbourTE.source.equals(pos)) { - potentialNewSources.add(neighbourTE); - continue; - } - - if (neighbourTE.isSource()) - potentialNewSources.add(neighbourTE); - - frontier.add(neighbourTE.getBlockPos()); - } - } - - for (KineticTileEntity newSource : potentialNewSources) { - if (newSource.hasSource() || newSource.isSource()) { - propagateNewSource(newSource); - return; - } - } - } - - private static KineticTileEntity findConnectedNeighbour(KineticTileEntity currentTE, BlockPos neighbourPos) { - BlockState neighbourState = currentTE.getLevel() - .getBlockState(neighbourPos); - if (!(neighbourState.getBlock() instanceof IRotate)) - return null; - if (!neighbourState.hasBlockEntity()) - return null; - BlockEntity neighbourTE = currentTE.getLevel() - .getBlockEntity(neighbourPos); - if (!(neighbourTE instanceof KineticTileEntity)) - return null; - KineticTileEntity neighbourKTE = (KineticTileEntity) neighbourTE; - if (!(neighbourKTE.getBlockState() - .getBlock() instanceof IRotate)) - return null; - if (!isConnected(currentTE, neighbourKTE) && !isConnected(neighbourKTE, currentTE)) - return null; - return neighbourKTE; - } - - public static boolean isConnected(KineticTileEntity from, KineticTileEntity to) { - final BlockState stateFrom = from.getBlockState(); - final BlockState stateTo = to.getBlockState(); - return isLargeCogToSpeedController(stateFrom, stateTo, to.getBlockPos() - .subtract(from.getBlockPos())) || getRotationSpeedModifier(from, to) != 0 - || from.isCustomConnection(to, stateFrom, stateTo); - } - - private static List getConnectedNeighbours(KineticTileEntity te) { - List neighbours = new LinkedList<>(); - for (BlockPos neighbourPos : getPotentialNeighbourLocations(te)) { - final KineticTileEntity neighbourTE = findConnectedNeighbour(te, neighbourPos); - if (neighbourTE == null) - continue; - - neighbours.add(neighbourTE); - } - return neighbours; - } - - private static List getPotentialNeighbourLocations(KineticTileEntity te) { - List neighbours = new LinkedList<>(); - - if (!te.getLevel() - .isAreaLoaded(te.getBlockPos(), 1)) - return neighbours; - - for (Direction facing : Iterate.directions) - neighbours.add(te.getBlockPos() - .relative(facing)); - - BlockState blockState = te.getBlockState(); - if (!(blockState.getBlock() instanceof IRotate)) - return neighbours; - IRotate block = (IRotate) blockState.getBlock(); - return te.addPropagationLocations(block, blockState, neighbours); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/StructureTransform.java b/src/main/java/com/simibubi/create/content/contraptions/StructureTransform.java similarity index 97% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/StructureTransform.java rename to src/main/java/com/simibubi/create/content/contraptions/StructureTransform.java index 814007e2e..0a36efe85 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/StructureTransform.java +++ b/src/main/java/com/simibubi/create/content/contraptions/StructureTransform.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.structureMovement; +package com.simibubi.create.content.contraptions; import static net.minecraft.world.level.block.state.properties.BlockStateProperties.AXIS; import static net.minecraft.world.level.block.state.properties.BlockStateProperties.FACING; @@ -110,9 +110,9 @@ public class StructureTransform { return applyWithoutOffset(localPos).offset(offset); } - public void apply(BlockEntity te) { - if (te instanceof ITransformableTE) - ((ITransformableTE) te).transform(this); + public void apply(BlockEntity be) { + if (be instanceof ITransformableBlockEntity) + ((ITransformableBlockEntity) be).transform(this); } /** diff --git a/src/main/java/com/simibubi/create/content/contraptions/TorquePropagator.java b/src/main/java/com/simibubi/create/content/contraptions/TorquePropagator.java deleted file mode 100644 index 4d7e336ce..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/TorquePropagator.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.simibubi.create.content.contraptions; - -import java.util.HashMap; -import java.util.Map; - -import com.simibubi.create.Create; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.foundation.utility.WorldHelper; - -import net.minecraft.world.level.LevelAccessor; - -public class TorquePropagator { - - static Map> networks = new HashMap<>(); - - public void onLoadWorld(LevelAccessor world) { - networks.put(world, new HashMap<>()); - Create.LOGGER.debug("Prepared Kinetic Network Space for " + WorldHelper.getDimensionID(world)); - } - - public void onUnloadWorld(LevelAccessor world) { - networks.remove(world); - Create.LOGGER.debug("Removed Kinetic Network Space for " + WorldHelper.getDimensionID(world)); - } - - public KineticNetwork getOrCreateNetworkFor(KineticTileEntity te) { - Long id = te.network; - KineticNetwork network; - Map map = networks.computeIfAbsent(te.getLevel(), $ -> new HashMap<>()); - if (id == null) - return null; - - if (!map.containsKey(id)) { - network = new KineticNetwork(); - network.id = te.network; - map.put(id, network); - } - network = map.get(id); - return network; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/TrainCollisionPacket.java b/src/main/java/com/simibubi/create/content/contraptions/TrainCollisionPacket.java similarity index 77% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/TrainCollisionPacket.java rename to src/main/java/com/simibubi/create/content/contraptions/TrainCollisionPacket.java index f68876821..926e89433 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/TrainCollisionPacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/TrainCollisionPacket.java @@ -1,8 +1,6 @@ -package com.simibubi.create.content.contraptions.components.structureMovement; +package com.simibubi.create.content.contraptions; -import java.util.function.Supplier; - -import com.simibubi.create.content.logistics.trains.entity.CarriageContraptionEntity; +import com.simibubi.create.content.trains.entity.CarriageContraptionEntity; import com.simibubi.create.foundation.networking.SimplePacketBase; import net.minecraft.network.FriendlyByteBuf; @@ -36,10 +34,9 @@ public class TrainCollisionPacket extends SimplePacketBase { } @Override - public void handle(Supplier context) { - Context ctx = context.get(); - ctx.enqueueWork(() -> { - ServerPlayer player = ctx.getSender(); + public boolean handle(Context context) { + context.enqueueWork(() -> { + ServerPlayer player = context.getSender(); Level level = player.level; Entity entity = level.getEntity(contraptionEntityId); @@ -50,7 +47,7 @@ public class TrainCollisionPacket extends SimplePacketBase { player.level.playSound(player, entity.blockPosition(), SoundEvents.PLAYER_ATTACK_CRIT, SoundSource.NEUTRAL, 1, .75f); }); - ctx.setPacketHandled(true); + return true; } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/TranslatingContraption.java b/src/main/java/com/simibubi/create/content/contraptions/TranslatingContraption.java new file mode 100644 index 000000000..e547f49f7 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/TranslatingContraption.java @@ -0,0 +1,57 @@ +package com.simibubi.create.content.contraptions; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; + +public abstract class TranslatingContraption extends Contraption { + + protected Set cachedColliders; + protected Direction cachedColliderDirection; + + public Set getOrCreateColliders(Level world, Direction movementDirection) { + if (getBlocks() == null) + return Collections.emptySet(); + if (cachedColliders == null || cachedColliderDirection != movementDirection) { + cachedColliderDirection = movementDirection; + cachedColliders= createColliders(world, movementDirection); + } + return cachedColliders; + } + + public Set createColliders(Level world, Direction movementDirection) { + Set colliders = new HashSet<>(); + for (StructureBlockInfo info : getBlocks().values()) { + BlockPos offsetPos = info.pos.relative(movementDirection); + if (info.state.getCollisionShape(world, offsetPos) + .isEmpty()) + continue; + if (getBlocks().containsKey(offsetPos) + && !getBlocks().get(offsetPos).state.getCollisionShape(world, offsetPos) + .isEmpty()) + continue; + colliders.add(info.pos); + } + return colliders; + } + + @Override + public void removeBlocksFromWorld(Level world, BlockPos offset) { + int count = blocks.size(); + super.removeBlocksFromWorld(world, offset); + if (count != blocks.size()) { + cachedColliders = null; + } + } + + @Override + public boolean canBeStabilized(Direction facing, BlockPos localPos) { + return false; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/AttachedActorBlock.java b/src/main/java/com/simibubi/create/content/contraptions/actors/AttachedActorBlock.java new file mode 100644 index 000000000..7ffb86954 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/AttachedActorBlock.java @@ -0,0 +1,100 @@ +package com.simibubi.create.content.contraptions.actors; + +import javax.annotation.ParametersAreNonnullByDefault; + +import com.simibubi.create.AllShapes; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.foundation.block.ProperWaterloggedBlock; +import com.simibubi.create.foundation.utility.BlockHelper; + +import net.minecraft.MethodsReturnNonnullByDefault; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.item.context.UseOnContext; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.HorizontalDirectionalBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition.Builder; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.level.pathfinder.PathComputationType; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +public abstract class AttachedActorBlock extends HorizontalDirectionalBlock + implements IWrenchable, ProperWaterloggedBlock { + + protected AttachedActorBlock(Properties p_i48377_1_) { + super(p_i48377_1_); + registerDefaultState(defaultBlockState().setValue(WATERLOGGED, false)); + } + + @Override + public InteractionResult onWrenched(BlockState state, UseOnContext context) { + return InteractionResult.FAIL; + } + + @Override + public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) { + Direction direction = state.getValue(FACING); + return AllShapes.HARVESTER_BASE.get(direction); + } + + @Override + protected void createBlockStateDefinition(Builder builder) { + builder.add(FACING, WATERLOGGED); + super.createBlockStateDefinition(builder); + } + + @Override + public boolean canSurvive(BlockState state, LevelReader worldIn, BlockPos pos) { + Direction direction = state.getValue(FACING); + BlockPos offset = pos.relative(direction.getOpposite()); + return BlockHelper.hasBlockSolidSide(worldIn.getBlockState(offset), worldIn, offset, direction); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext context) { + Direction facing; + if (context.getClickedFace() + .getAxis() + .isVertical()) + facing = context.getHorizontalDirection() + .getOpposite(); + else { + BlockState blockState = context.getLevel() + .getBlockState(context.getClickedPos() + .relative(context.getClickedFace() + .getOpposite())); + if (blockState.getBlock() instanceof AttachedActorBlock) + facing = blockState.getValue(FACING); + else + facing = context.getClickedFace(); + } + return withWater(defaultBlockState().setValue(FACING, facing), context); + } + + @Override + public BlockState updateShape(BlockState pState, Direction pDirection, BlockState pNeighborState, + LevelAccessor pLevel, BlockPos pCurrentPos, BlockPos pNeighborPos) { + updateWater(pLevel, pState, pCurrentPos); + return pState; + } + + @Override + public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) { + return false; + } + + @Override + public FluidState getFluidState(BlockState pState) { + return fluidState(pState); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionControlsBlock.java b/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionControlsBlock.java new file mode 100644 index 000000000..9898d1549 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionControlsBlock.java @@ -0,0 +1,65 @@ +package com.simibubi.create.content.contraptions.actors.contraptionControls; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllShapes; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.content.contraptions.actors.trainControls.ControlsBlock; +import com.simibubi.create.foundation.block.IBE; + +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.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntityType; +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.VoxelShape; + +public class ContraptionControlsBlock extends ControlsBlock implements IBE { + + public ContraptionControlsBlock(Properties pProperties) { + super(pProperties); + } + + @Override + public InteractionResult use(BlockState pState, Level pLevel, BlockPos pPos, Player pPlayer, InteractionHand pHand, + BlockHitResult pHit) { + return onBlockEntityUse(pLevel, pPos, cte -> { + cte.pressButton(); + if (!pLevel.isClientSide()) { + cte.disabled = !cte.disabled; + cte.notifyUpdate(); + ContraptionControlsBlockEntity.sendStatus(pPlayer, cte.filtering.getFilter(), !cte.disabled); + AllSoundEvents.CONTROLLER_CLICK.play(cte.getLevel(), null, cte.getBlockPos(), 1, + cte.disabled ? 0.8f : 1.5f); + } + return InteractionResult.SUCCESS; + }); + } + + @Override + public void neighborChanged(BlockState pState, Level pLevel, BlockPos pPos, Block pBlock, BlockPos pFromPos, + boolean pIsMoving) { + withBlockEntityDo(pLevel, pPos, ContraptionControlsBlockEntity::updatePoweredState); + } + + @Override + public VoxelShape getShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, CollisionContext pContext) { + return AllShapes.CONTRAPTION_CONTROLS.get(pState.getValue(FACING)); + } + + @Override + public Class getBlockEntityClass() { + return ContraptionControlsBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.CONTRAPTION_CONTROLS.get(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionControlsBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionControlsBlockEntity.java new file mode 100644 index 000000000..bcfca357b --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionControlsBlockEntity.java @@ -0,0 +1,155 @@ +package com.simibubi.create.content.contraptions.actors.contraptionControls; + +import java.util.List; + +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllTags.AllItemTags; +import com.simibubi.create.content.contraptions.actors.trainControls.ControlsBlock; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.DyeHelper; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.DyeColor; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class ContraptionControlsBlockEntity extends SmartBlockEntity { + + public FilteringBehaviour filtering; + public boolean disabled; + public boolean powered; + + public LerpedFloat indicator; + public LerpedFloat button; + + public ContraptionControlsBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + indicator = LerpedFloat.angular() + .startWithValue(0); + button = LerpedFloat.linear() + .startWithValue(0) + .chase(0, 0.125f, Chaser.EXP); + } + + @Override + public void addBehaviours(List behaviours) { + behaviours.add(filtering = new FilteringBehaviour(this, new ControlsSlot())); + filtering.setLabel(Lang.translateDirect("contraptions.contoller.target")); + filtering.withPredicate(AllItemTags.CONTRAPTION_CONTROLLED::matches); + } + + public void pressButton() { + button.setValue(1); + } + + public void updatePoweredState() { + if (level.isClientSide()) + return; + boolean powered = level.hasNeighborSignal(worldPosition); + if (this.powered == powered) + return; + this.powered = powered; + this.disabled = powered; + notifyUpdate(); + } + + @Override + public void initialize() { + super.initialize(); + updatePoweredState(); + } + + @Override + public void tick() { + super.tick(); + if (!level.isClientSide()) + return; + tickAnimations(); + int value = disabled ? 4 * 45 : 0; + indicator.setValue(value); + indicator.updateChaseTarget(value); + } + + public void tickAnimations() { + button.tickChaser(); + indicator.tickChaser(); + } + + @Override + protected void read(CompoundTag tag, boolean clientPacket) { + super.read(tag, clientPacket); + disabled = tag.getBoolean("Disabled"); + powered = tag.getBoolean("Powered"); + } + + @Override + protected void write(CompoundTag tag, boolean clientPacket) { + super.write(tag, clientPacket); + tag.putBoolean("Disabled", disabled); + tag.putBoolean("Powered", powered); + } + + public static void sendStatus(Player player, ItemStack filter, boolean enabled) { + MutableComponent state = Lang.translate("contraption.controls.actor_toggle." + (enabled ? "on" : "off")) + .color(DyeHelper.DYE_TABLE.get(enabled ? DyeColor.LIME : DyeColor.ORANGE) + .getFirst()) + .component(); + + if (filter.isEmpty()) { + Lang.translate("contraption.controls.all_actor_toggle", state) + .sendStatus(player); + return; + } + + Lang.translate("contraption.controls.specific_actor_toggle", filter.getHoverName() + .getString(), state) + .sendStatus(player); + } + + public static class ControlsSlot extends ValueBoxTransform.Sided { + + @Override + public Vec3 getLocalOffset(BlockState state) { + Direction facing = state.getValue(ControlsBlock.FACING); + float yRot = AngleHelper.horizontalAngle(facing); + return VecHelper.rotateCentered(VecHelper.voxelSpace(8, 12f, 5.5f), yRot, Axis.Y); + } + + @Override + public void rotate(BlockState state, PoseStack ms) { + Direction facing = state.getValue(ControlsBlock.FACING); + float yRot = AngleHelper.horizontalAngle(facing); + TransformStack.cast(ms) + .rotateY(yRot + 180) + .rotateX(67.5f); + } + + @Override + public float getScale() { + return .508f; + } + + @Override + protected Vec3 getSouthLocation() { + return Vec3.ZERO; + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionControlsMovement.java b/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionControlsMovement.java new file mode 100644 index 000000000..b3e9536ec --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionControlsMovement.java @@ -0,0 +1,161 @@ +package com.simibubi.create.content.contraptions.actors.contraptionControls; + +import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.contraptions.elevator.ElevatorContraption; +import com.simibubi.create.content.contraptions.render.ContraptionMatrices; +import com.simibubi.create.foundation.utility.Couple; +import com.simibubi.create.foundation.utility.IntAttached; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.Mth; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.items.ItemHandlerHelper; + +public class ContraptionControlsMovement implements MovementBehaviour { + + @Override + public ItemStack canBeDisabledVia(MovementContext context) { + return null; + } + + @Override + public void startMoving(MovementContext context) { + if (context.contraption instanceof ElevatorContraption && context.blockEntityData != null) + context.blockEntityData.remove("Filter"); + } + + @Override + public void stopMoving(MovementContext context) { + ItemStack filter = getFilter(context); + if (filter != null) + context.blockEntityData.putBoolean("Disabled", context.contraption.isActorTypeDisabled(filter) + || context.contraption.isActorTypeDisabled(ItemStack.EMPTY)); + } + + public static boolean isSameFilter(ItemStack stack1, ItemStack stack2) { + if (stack1.isEmpty() && stack2.isEmpty()) + return true; + return ItemHandlerHelper.canItemStacksStack(stack1, stack2); + } + + public static ItemStack getFilter(MovementContext ctx) { + CompoundTag blockEntityData = ctx.blockEntityData; + if (blockEntityData == null) + return null; + return ItemStack.of(blockEntityData.getCompound("Filter")); + } + + public static boolean isDisabledInitially(MovementContext ctx) { + return ctx.blockEntityData != null && ctx.blockEntityData.getBoolean("Disabled"); + } + + @Override + public void tick(MovementContext ctx) { + if (!ctx.world.isClientSide()) + return; + + Contraption contraption = ctx.contraption; + if (!(contraption instanceof ElevatorContraption ec)) { + if (!(contraption.presentBlockEntities.get(ctx.localPos) instanceof ContraptionControlsBlockEntity cbe)) + return; + ItemStack filter = getFilter(ctx); + int value = + contraption.isActorTypeDisabled(filter) || contraption.isActorTypeDisabled(ItemStack.EMPTY) ? 4 * 45 + : 0; + cbe.indicator.setValue(value); + cbe.indicator.updateChaseTarget(value); + cbe.tickAnimations(); + return; + } + + if (!(ctx.temporaryData instanceof ElevatorFloorSelection)) + ctx.temporaryData = new ElevatorFloorSelection(); + + ElevatorFloorSelection efs = (ElevatorFloorSelection) ctx.temporaryData; + tickFloorSelection(efs, ec); + + if (!(contraption.presentBlockEntities.get(ctx.localPos) instanceof ContraptionControlsBlockEntity cbe)) + return; + + cbe.tickAnimations(); + + int currentY = (int) Math.round(contraption.entity.getY() + ec.getContactYOffset()); + boolean atTargetY = ec.clientYTarget == currentY; + + LerpedFloat indicator = cbe.indicator; + float currentIndicator = indicator.getChaseTarget(); + boolean below = atTargetY ? currentIndicator > 0 : ec.clientYTarget <= currentY; + + if (currentIndicator == 0 && !atTargetY) { + int startingPoint = below ? 181 : -181; + indicator.setValue(startingPoint); + indicator.updateChaseTarget(startingPoint); + cbe.tickAnimations(); + return; + } + + int currentStage = Mth.floor(((currentIndicator % 360) + 360) % 360); + if (!atTargetY || currentStage / 45 != 0) { + float increment = currentStage / 45 == (below ? 4 : 3) ? 2.25f : 33.75f; + indicator.chase(currentIndicator + (below ? increment : -increment), 45f, Chaser.LINEAR); + return; + } + + indicator.setValue(0); + indicator.updateChaseTarget(0); + return; + } + + public static void tickFloorSelection(ElevatorFloorSelection efs, ElevatorContraption ec) { + if (ec.namesList.isEmpty()) { + efs.currentShortName = "X"; + efs.currentLongName = "No Floors"; + efs.currentIndex = 0; + efs.targetYEqualsSelection = true; + return; + } + + efs.currentIndex = Mth.clamp(efs.currentIndex, 0, ec.namesList.size() - 1); + IntAttached> entry = ec.namesList.get(efs.currentIndex); + efs.currentTargetY = entry.getFirst(); + efs.currentShortName = entry.getSecond() + .getFirst(); + efs.currentLongName = entry.getSecond() + .getSecond(); + efs.targetYEqualsSelection = efs.currentTargetY == ec.clientYTarget; + + if (ec.isTargetUnreachable(efs.currentTargetY)) + efs.currentLongName = Lang.translate("contraption.controls.floor_unreachable") + .string(); + } + + @Override + public boolean renderAsNormalBlockEntity() { + return true; + } + + @Override + @OnlyIn(Dist.CLIENT) + public void renderInContraption(MovementContext ctx, VirtualRenderWorld renderWorld, ContraptionMatrices matrices, + MultiBufferSource buffer) { + ContraptionControlsRenderer.renderInContraption(ctx, renderWorld, matrices, buffer); + } + + public static class ElevatorFloorSelection { + public int currentIndex = 0; + public int currentTargetY = 0; + public boolean targetYEqualsSelection = true; + public String currentShortName = ""; + public String currentLongName = ""; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionControlsMovingInteraction.java b/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionControlsMovingInteraction.java new file mode 100644 index 000000000..bbc5cf56f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionControlsMovingInteraction.java @@ -0,0 +1,127 @@ +package com.simibubi.create.content.contraptions.actors.contraptionControls; + +import java.util.Iterator; +import java.util.List; + +import org.apache.commons.lang3.tuple.MutablePair; + +import com.simibubi.create.AllMovementBehaviours; +import com.simibubi.create.AllPackets; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.contraptions.actors.contraptionControls.ContraptionControlsMovement.ElevatorFloorSelection; +import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.contraptions.behaviour.MovingInteractionBehaviour; +import com.simibubi.create.content.contraptions.elevator.ElevatorContraption; +import com.simibubi.create.content.contraptions.elevator.ElevatorTargetFloorPacket; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.network.PacketDistributor; + +public class ContraptionControlsMovingInteraction extends MovingInteractionBehaviour { + + @Override + public boolean handlePlayerInteraction(Player player, InteractionHand activeHand, BlockPos localPos, + AbstractContraptionEntity contraptionEntity) { + Contraption contraption = contraptionEntity.getContraption(); + + MutablePair actor = contraption.getActorAt(localPos); + if (actor == null) + return false; + MovementContext ctx = actor.right; + if (ctx == null) + return false; + if (contraption instanceof ElevatorContraption ec) + return elevatorInteraction(localPos, contraptionEntity, ec, ctx); + if (contraptionEntity.level.isClientSide()) { + if (contraption.presentBlockEntities.get(ctx.localPos) instanceof ContraptionControlsBlockEntity cbe) + cbe.pressButton(); + return true; + } + + ItemStack filter = ContraptionControlsMovement.getFilter(ctx); + boolean disable = true; + boolean invert = false; + + List disabledActors = contraption.getDisabledActors(); + for (Iterator iterator = disabledActors.iterator(); iterator.hasNext();) { + ItemStack presentFilter = iterator.next(); + boolean sameFilter = ContraptionControlsMovement.isSameFilter(presentFilter, filter); + if (presentFilter.isEmpty()) { + iterator.remove(); + disable = false; + if (!sameFilter) + invert = true; + continue; + } + if (!sameFilter) + continue; + iterator.remove(); + disable = false; + break; + } + + if (invert) { + for (MutablePair pair : contraption.getActors()) { + MovementBehaviour behaviour = AllMovementBehaviours.getBehaviour(pair.left.state); + if (behaviour == null) + continue; + ItemStack behaviourStack = behaviour.canBeDisabledVia(pair.right); + if (behaviourStack == null) + continue; + if (ContraptionControlsMovement.isSameFilter(behaviourStack, filter)) + continue; + if (contraption.isActorTypeDisabled(behaviourStack)) + continue; + disabledActors.add(behaviourStack); + send(contraptionEntity, behaviourStack, true); + } + } + + if (filter.isEmpty()) + disabledActors.clear(); + if (disable) + disabledActors.add(filter); + + contraption.setActorsActive(filter, !disable); + ContraptionControlsBlockEntity.sendStatus(player, filter, !disable); + send(contraptionEntity, filter, disable); + + AllSoundEvents.CONTROLLER_CLICK.play(player.level, null, + new BlockPos(contraptionEntity.toGlobalVector(Vec3.atCenterOf(localPos), 1)), 1, disable ? 0.8f : 1.5f); + + return true; + } + + private void send(AbstractContraptionEntity contraptionEntity, ItemStack filter, boolean disable) { + AllPackets.getChannel().send(PacketDistributor.TRACKING_ENTITY.with(() -> contraptionEntity), + new ContraptionDisableActorPacket(contraptionEntity.getId(), filter, !disable)); + } + + private boolean elevatorInteraction(BlockPos localPos, AbstractContraptionEntity contraptionEntity, + ElevatorContraption contraption, MovementContext ctx) { + if (!contraptionEntity.level.isClientSide()) { + BlockPos pos = new BlockPos(contraptionEntity.toGlobalVector(Vec3.atCenterOf(localPos), 1)); + AllSoundEvents.CONTROLLER_CLICK.play(contraptionEntity.level, null, pos, 1, 1.5f); + AllSoundEvents.CONTRAPTION_ASSEMBLE.play(contraptionEntity.level, null, pos, 0.75f, 0.8f); + return true; + } + if (!(ctx.temporaryData instanceof ElevatorFloorSelection efs)) + return false; + if (efs.currentTargetY == contraption.clientYTarget) + return true; + + AllPackets.getChannel().sendToServer(new ElevatorTargetFloorPacket(contraptionEntity, efs.currentTargetY)); + if (contraption.presentBlockEntities.get(ctx.localPos) instanceof ContraptionControlsBlockEntity cbe) + cbe.pressButton(); + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionControlsRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionControlsRenderer.java new file mode 100644 index 000000000..66548a08f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionControlsRenderer.java @@ -0,0 +1,143 @@ +package com.simibubi.create.content.contraptions.actors.contraptionControls; + +import java.util.Random; + +import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.contraptions.actors.contraptionControls.ContraptionControlsMovement.ElevatorFloorSelection; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.contraptions.render.ContraptionMatrices; +import com.simibubi.create.content.redstone.nixieTube.NixieTubeRenderer; +import com.simibubi.create.foundation.blockEntity.renderer.SmartBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.Color; +import com.simibubi.create.foundation.utility.Couple; +import com.simibubi.create.foundation.utility.DyeHelper; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider.Context; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.item.DyeColor; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class ContraptionControlsRenderer extends SmartBlockEntityRenderer { + + private static Random r = new Random(); + + public ContraptionControlsRenderer(Context context) { + super(context); + } + + @Override + protected void renderSafe(ContraptionControlsBlockEntity blockEntity, float pt, PoseStack ms, + MultiBufferSource buffer, int light, int overlay) { + BlockState blockState = blockEntity.getBlockState(); + Direction facing = blockState.getValue(ContraptionControlsBlock.FACING) + .getOpposite(); + Vec3 buttonMovementAxis = VecHelper.rotate(new Vec3(0, 1, -.325), AngleHelper.horizontalAngle(facing), Axis.Y); + Vec3 buttonMovement = buttonMovementAxis.scale(-0.07f + -1 / 24f * blockEntity.button.getValue(pt)); + Vec3 buttonOffset = buttonMovementAxis.scale(0.07f); + + ms.pushPose(); + ms.translate(buttonMovement.x, buttonMovement.y, buttonMovement.z); + super.renderSafe(blockEntity, pt, ms, buffer, light, overlay); + ms.translate(buttonOffset.x, buttonOffset.y, buttonOffset.z); + + VertexConsumer vc = buffer.getBuffer(RenderType.solid()); + CachedBufferer.partialFacing(AllPartialModels.CONTRAPTION_CONTROLS_BUTTON, blockState, facing) + .light(light) + .renderInto(ms, vc); + + ms.popPose(); + + int i = (((int) blockEntity.indicator.getValue(pt) / 45) % 8) + 8; + CachedBufferer.partialFacing(AllPartialModels.CONTRAPTION_CONTROLS_INDICATOR.get(i % 8), blockState, facing) + .light(light) + .renderInto(ms, vc); + } + + public static void renderInContraption(MovementContext ctx, VirtualRenderWorld renderWorld, + ContraptionMatrices matrices, MultiBufferSource buffer) { + + if (!(ctx.temporaryData instanceof ElevatorFloorSelection efs)) + return; + if (!AllBlocks.CONTRAPTION_CONTROLS.has(ctx.state)) + return; + + Entity cameraEntity = Minecraft.getInstance() + .getCameraEntity(); + float playerDistance = (float) (ctx.position == null || cameraEntity == null ? 0 + : ctx.position.distanceToSqr(cameraEntity.getEyePosition())); + + float flicker = r.nextFloat(); + Couple couple = DyeHelper.DYE_TABLE.get(efs.targetYEqualsSelection ? DyeColor.WHITE : DyeColor.ORANGE); + int brightColor = couple.getFirst(); + int darkColor = couple.getSecond(); + int flickeringBrightColor = Color.mixColors(brightColor, darkColor, flicker / 4); + Font fontRenderer = Minecraft.getInstance().font; + float shadowOffset = .5f; + + String text = efs.currentShortName; + String description = efs.currentLongName; + PoseStack ms = matrices.getViewProjection(); + TransformStack msr = TransformStack.cast(ms); + + ms.pushPose(); + msr.translate(ctx.localPos); + msr.rotateCentered(Direction.UP, + AngleHelper.rad(AngleHelper.horizontalAngle(ctx.state.getValue(ContraptionControlsBlock.FACING)))); + ms.translate(0.275f + 0.125f, 1, 0.5f); + msr.rotate(Direction.WEST, AngleHelper.rad(67.5f)); + + float buttondepth = -.25f; + if (ctx.contraption.presentBlockEntities.get(ctx.localPos) instanceof ContraptionControlsBlockEntity cbe) + buttondepth += -1 / 24f * cbe.button.getValue(AnimationTickHolder.getPartialTicks(renderWorld)); + + if (!text.isBlank() && playerDistance < 100) { + int actualWidth = fontRenderer.width(text); + int width = Math.max(actualWidth, 12); + float scale = 1 / (5f * (width - .5f)); + float heightCentering = (width - 8f) / 2; + + ms.pushPose(); + ms.translate(0, .15f, buttondepth); + ms.scale(scale, -scale, scale); + ms.translate(Math.max(0, width - actualWidth) / 2, heightCentering, 0); + NixieTubeRenderer.drawInWorldString(ms, buffer, text, flickeringBrightColor); + ms.translate(shadowOffset, shadowOffset, -1 / 16f); + NixieTubeRenderer.drawInWorldString(ms, buffer, text, Color.mixColors(darkColor, 0, .35f)); + ms.popPose(); + } + + if (!description.isBlank() && playerDistance < 20) { + int actualWidth = fontRenderer.width(description); + int width = Math.max(actualWidth, 55); + float scale = 1 / (3f * (width - .5f)); + float heightCentering = (width - 8f) / 2; + + ms.pushPose(); + ms.translate(-.0635f, 0.06f, buttondepth); + ms.scale(scale, -scale, scale); + ms.translate(Math.max(0, width - actualWidth) / 2, heightCentering, 0); + NixieTubeRenderer.drawInWorldString(ms, buffer, description, flickeringBrightColor); + ms.popPose(); + } + + ms.popPose(); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionDisableActorPacket.java b/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionDisableActorPacket.java new file mode 100644 index 000000000..6122b53d0 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/contraptionControls/ContraptionDisableActorPacket.java @@ -0,0 +1,70 @@ +package com.simibubi.create.content.contraptions.actors.contraptionControls; + +import java.util.Iterator; +import java.util.List; + +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.client.Minecraft; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.network.NetworkEvent.Context; + +public class ContraptionDisableActorPacket extends SimplePacketBase { + + private int entityID; + private ItemStack filter; + private boolean enable; + + public ContraptionDisableActorPacket(int entityID, ItemStack filter, boolean enable) { + this.entityID = entityID; + this.filter = filter; + this.enable = enable; + } + + public ContraptionDisableActorPacket(FriendlyByteBuf buffer) { + entityID = buffer.readInt(); + enable = buffer.readBoolean(); + filter = buffer.readItem(); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeInt(entityID); + buffer.writeBoolean(enable); + buffer.writeItem(filter); + } + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> { + Entity entityByID = Minecraft.getInstance().level.getEntity(entityID); + if (!(entityByID instanceof AbstractContraptionEntity ace)) + return; + + Contraption contraption = ace.getContraption(); + List disabledActors = contraption.getDisabledActors(); + if (filter.isEmpty()) + disabledActors.clear(); + + if (!enable) { + disabledActors.add(filter); + contraption.setActorsActive(filter, false); + return; + } + + for (Iterator iterator = disabledActors.iterator(); iterator.hasNext();) { + ItemStack next = iterator.next(); + if (ContraptionControlsMovement.isSameFilter(next, filter) || next.isEmpty()) + iterator.remove(); + } + + contraption.setActorsActive(filter, true); + }); + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/flwdata/ActorData.java b/src/main/java/com/simibubi/create/content/contraptions/actors/flwdata/ActorData.java similarity index 96% rename from src/main/java/com/simibubi/create/content/contraptions/components/actors/flwdata/ActorData.java rename to src/main/java/com/simibubi/create/content/contraptions/actors/flwdata/ActorData.java index 9e232353f..f7ee48f0b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/flwdata/ActorData.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/flwdata/ActorData.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.actors.flwdata; +package com.simibubi.create.content.contraptions.actors.flwdata; import org.joml.Quaternionf; import org.joml.Vector3f; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/flwdata/ActorType.java b/src/main/java/com/simibubi/create/content/contraptions/actors/flwdata/ActorType.java similarity index 93% rename from src/main/java/com/simibubi/create/content/contraptions/components/actors/flwdata/ActorType.java rename to src/main/java/com/simibubi/create/content/contraptions/actors/flwdata/ActorType.java index edcb0d54d..90dfffb87 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/flwdata/ActorType.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/flwdata/ActorType.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.actors.flwdata; +package com.simibubi.create.content.contraptions.actors.flwdata; import com.jozufozu.flywheel.api.struct.Batched; import com.jozufozu.flywheel.api.struct.Instanced; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/flwdata/UnsafeActorWriter.java b/src/main/java/com/simibubi/create/content/contraptions/actors/flwdata/UnsafeActorWriter.java similarity index 94% rename from src/main/java/com/simibubi/create/content/contraptions/components/actors/flwdata/UnsafeActorWriter.java rename to src/main/java/com/simibubi/create/content/contraptions/actors/flwdata/UnsafeActorWriter.java index 4479e800d..c54b11db1 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/flwdata/UnsafeActorWriter.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/flwdata/UnsafeActorWriter.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.actors.flwdata; +package com.simibubi.create.content.contraptions.actors.flwdata; import org.lwjgl.system.MemoryUtil; diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/flwdata/package-info.java b/src/main/java/com/simibubi/create/content/contraptions/actors/flwdata/package-info.java new file mode 100644 index 000000000..0498b1729 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/flwdata/package-info.java @@ -0,0 +1,6 @@ +@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault +package com.simibubi.create.content.contraptions.actors.flwdata; + +import javax.annotation.ParametersAreNonnullByDefault; + +import net.minecraft.MethodsReturnNonnullByDefault; diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/harvester/HarvesterActorInstance.java b/src/main/java/com/simibubi/create/content/contraptions/actors/harvester/HarvesterActorInstance.java new file mode 100644 index 000000000..a9baf2f65 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/harvester/HarvesterActorInstance.java @@ -0,0 +1,100 @@ +package com.simibubi.create.content.contraptions.actors.harvester; + +import com.jozufozu.flywheel.api.Material; +import com.jozufozu.flywheel.api.MaterialManager; +import com.jozufozu.flywheel.core.Materials; +import com.jozufozu.flywheel.core.PartialModel; +import com.jozufozu.flywheel.core.materials.model.ModelData; +import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.contraptions.render.ActorInstance; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.phys.Vec3; + +public class HarvesterActorInstance extends ActorInstance { + static float originOffset = 1 / 16f; + static Vec3 rotOffset = new Vec3(0.5f, -2 * originOffset + 0.5f, originOffset + 0.5f); + + protected ModelData harvester; + private Direction facing; + + protected float horizontalAngle; + + private double rotation; + private double previousRotation; + + public HarvesterActorInstance(MaterialManager materialManager, VirtualRenderWorld simulationWorld, MovementContext context) { + super(materialManager, simulationWorld, context); + + Material material = materialManager.defaultCutout() + .material(Materials.TRANSFORMED); + + BlockState state = context.state; + + facing = state.getValue(BlockStateProperties.HORIZONTAL_FACING); + + harvester = material.getModel(getRollingPartial(), state).createInstance(); + + horizontalAngle = facing.toYRot() + ((facing.getAxis() == Direction.Axis.X) ? 180 : 0); + + harvester.setBlockLight(localBlockLight()); + } + + protected PartialModel getRollingPartial() { + return AllPartialModels.HARVESTER_BLADE; + } + + protected Vec3 getRotationOffset() { + return rotOffset; + } + + protected double getRadius() { + return 6.5; + } + + @Override + public void tick() { + super.tick(); + + previousRotation = rotation; + + if (context.contraption.stalled || context.disabled + || VecHelper.isVecPointingTowards(context.relativeMotion, facing.getOpposite())) + return; + + double arcLength = context.motion.length(); + + double radians = arcLength * 16 / getRadius(); + + float deg = AngleHelper.deg(radians); + + deg = (float) (((int) (deg * 3000)) / 3000); + + rotation += deg * 1.25; + + rotation %= 360; + } + + @Override + public void beginFrame() { + harvester.loadIdentity() + .translate(context.localPos) + .centre() + .rotateY(horizontalAngle) + .unCentre() + .translate(getRotationOffset()) + .rotateX(getRotation()) + .translateBack(getRotationOffset()); + } + + protected double getRotation() { + return AngleHelper.angleLerp(AnimationTickHolder.getPartialTicks(), previousRotation, rotation); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/harvester/HarvesterBlock.java b/src/main/java/com/simibubi/create/content/contraptions/actors/harvester/HarvesterBlock.java new file mode 100644 index 000000000..31e8da723 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/harvester/HarvesterBlock.java @@ -0,0 +1,25 @@ +package com.simibubi.create.content.contraptions.actors.harvester; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.content.contraptions.actors.AttachedActorBlock; +import com.simibubi.create.foundation.block.IBE; + +import net.minecraft.world.level.block.entity.BlockEntityType; + +public class HarvesterBlock extends AttachedActorBlock implements IBE { + + public HarvesterBlock(Properties p_i48377_1_) { + super(p_i48377_1_); + } + + @Override + public Class getBlockEntityClass() { + return HarvesterBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.HARVESTER.get(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/harvester/HarvesterBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/actors/harvester/HarvesterBlockEntity.java new file mode 100644 index 000000000..b87ac1b5e --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/harvester/HarvesterBlockEntity.java @@ -0,0 +1,32 @@ +package com.simibubi.create.content.contraptions.actors.harvester; + +import com.simibubi.create.foundation.blockEntity.CachedRenderBBBlockEntity; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; + +public class HarvesterBlockEntity extends CachedRenderBBBlockEntity { + + // For simulations such as Ponder + private float manuallyAnimatedSpeed; + + public HarvesterBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + protected AABB createRenderBoundingBox() { + return new AABB(worldPosition); + } + + public float getAnimatedSpeed() { + return manuallyAnimatedSpeed; + } + + public void setAnimatedSpeed(float speed) { + manuallyAnimatedSpeed = speed; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/actors/harvester/HarvesterMovementBehaviour.java similarity index 85% rename from src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterMovementBehaviour.java rename to src/main/java/com/simibubi/create/content/contraptions/actors/harvester/HarvesterMovementBehaviour.java index 53e6acefc..fff0f5601 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/harvester/HarvesterMovementBehaviour.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.actors; +package com.simibubi.create.content.contraptions.actors.harvester; import javax.annotation.Nullable; @@ -6,14 +6,14 @@ import org.apache.commons.lang3.mutable.MutableBoolean; import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; -import com.simibubi.create.foundation.config.AllConfigs; +import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.contraptions.render.ActorInstance; +import com.simibubi.create.content.contraptions.render.ContraptionMatrices; +import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher; import com.simibubi.create.foundation.utility.BlockHelper; import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.core.BlockPos; @@ -39,8 +39,9 @@ public class HarvesterMovementBehaviour implements MovementBehaviour { @Override public boolean isActive(MovementContext context) { - return !VecHelper.isVecPointingTowards(context.relativeMotion, context.state.getValue(HarvesterBlock.FACING) - .getOpposite()); + return MovementBehaviour.super.isActive(context) + && !VecHelper.isVecPointingTowards(context.relativeMotion, context.state.getValue(HarvesterBlock.FACING) + .getOpposite()); } @Override @@ -96,7 +97,7 @@ public class HarvesterMovementBehaviour implements MovementBehaviour { MutableBoolean seedSubtracted = new MutableBoolean(notCropButCuttable); BlockState state = stateVisited; BlockHelper.destroyBlockAs(world, pos, null, item, effectChance, stack -> { - if (AllConfigs.SERVER.kinetics.harvesterReplants.get() && !seedSubtracted.getValue() + if (AllConfigs.server().kinetics.harvesterReplants.get() && !seedSubtracted.getValue() && stack.sameItem(new ItemStack(state.getBlock()))) { stack.shrink(1); seedSubtracted.setTrue(); @@ -109,8 +110,8 @@ public class HarvesterMovementBehaviour implements MovementBehaviour { } public boolean isValidCrop(Level world, BlockPos pos, BlockState state) { - boolean harvestPartial = AllConfigs.SERVER.kinetics.harvestPartiallyGrown.get(); - boolean replant = AllConfigs.SERVER.kinetics.harvesterReplants.get(); + boolean harvestPartial = AllConfigs.server().kinetics.harvestPartiallyGrown.get(); + boolean replant = AllConfigs.server().kinetics.harvesterReplants.get(); if (state.getBlock() instanceof CropBlock) { CropBlock crop = (CropBlock) state.getBlock(); @@ -174,7 +175,7 @@ public class HarvesterMovementBehaviour implements MovementBehaviour { } private BlockState cutCrop(Level world, BlockPos pos, BlockState state) { - if (!AllConfigs.SERVER.kinetics.harvesterReplants.get()) { + if (!AllConfigs.server().kinetics.harvesterReplants.get()) { if (state.getFluidState() .isEmpty()) return Blocks.AIR.defaultBlockState(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/harvester/HarvesterRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/actors/harvester/HarvesterRenderer.java new file mode 100644 index 000000000..9b99a16eb --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/harvester/HarvesterRenderer.java @@ -0,0 +1,72 @@ +package com.simibubi.create.content.contraptions.actors.harvester; + +import static net.minecraft.world.level.block.state.properties.BlockStateProperties.HORIZONTAL_FACING; + +import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.contraptions.render.ContraptionMatrices; +import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher; +import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.core.Direction; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class HarvesterRenderer extends SafeBlockEntityRenderer { + + private static final Vec3 PIVOT = new Vec3(0, 6, 9); + + public HarvesterRenderer(BlockEntityRendererProvider.Context context) {} + + @Override + protected void renderSafe(HarvesterBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + BlockState blockState = be.getBlockState(); + SuperByteBuffer superBuffer = CachedBufferer.partial(AllPartialModels.HARVESTER_BLADE, blockState); + transform(be.getLevel(), blockState.getValue(HarvesterBlock.FACING), superBuffer, be.getAnimatedSpeed(), PIVOT); + superBuffer.light(light) + .renderInto(ms, buffer.getBuffer(RenderType.cutoutMipped())); + } + + public static void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld, + ContraptionMatrices matrices, MultiBufferSource buffers) { + BlockState blockState = context.state; + Direction facing = blockState.getValue(HORIZONTAL_FACING); + SuperByteBuffer superBuffer = CachedBufferer.partial(AllPartialModels.HARVESTER_BLADE, blockState); + float speed = (float) (!VecHelper.isVecPointingTowards(context.relativeMotion, facing.getOpposite()) + ? context.getAnimationSpeed() + : 0); + if (context.contraption.stalled) + speed = 0; + + superBuffer.transform(matrices.getModel()); + transform(context.world, facing, superBuffer, speed, PIVOT); + + superBuffer + .light(matrices.getWorld(), ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) + .renderInto(matrices.getViewProjection(), buffers.getBuffer(RenderType.cutoutMipped())); + } + + public static void transform(Level world, Direction facing, SuperByteBuffer superBuffer, float speed, Vec3 pivot) { + float originOffset = 1 / 16f; + Vec3 rotOffset = new Vec3(0, pivot.y * originOffset, pivot.z * originOffset); + float time = AnimationTickHolder.getRenderTime(world) / 20; + float angle = (time * speed) % 360; + + superBuffer.rotateCentered(Direction.UP, AngleHelper.rad(AngleHelper.horizontalAngle(facing))) + .translate(rotOffset.x, rotOffset.y, rotOffset.z) + .rotate(Direction.WEST, AngleHelper.rad(angle)) + .translate(-rotOffset.x, -rotOffset.y, -rotOffset.z); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PloughBlock.java b/src/main/java/com/simibubi/create/content/contraptions/actors/plough/PloughBlock.java similarity index 82% rename from src/main/java/com/simibubi/create/content/contraptions/components/actors/PloughBlock.java rename to src/main/java/com/simibubi/create/content/contraptions/actors/plough/PloughBlock.java index ef9372851..ed70dfd0f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PloughBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/plough/PloughBlock.java @@ -1,8 +1,9 @@ -package com.simibubi.create.content.contraptions.components.actors; +package com.simibubi.create.content.contraptions.actors.plough; import java.util.UUID; import com.mojang.authlib.GameProfile; +import com.simibubi.create.content.contraptions.actors.AttachedActorBlock; import net.minecraft.server.level.ServerLevel; import net.minecraftforge.common.util.FakePlayer; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PloughMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/actors/plough/PloughMovementBehaviour.java similarity index 89% rename from src/main/java/com/simibubi/create/content/contraptions/components/actors/PloughMovementBehaviour.java rename to src/main/java/com/simibubi/create/content/contraptions/actors/plough/PloughMovementBehaviour.java index 9f95c0652..b6bc2d6b9 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PloughMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/plough/PloughMovementBehaviour.java @@ -1,9 +1,10 @@ -package com.simibubi.create.content.contraptions.components.actors; +package com.simibubi.create.content.contraptions.actors.plough; -import com.simibubi.create.content.contraptions.components.actors.PloughBlock.PloughFakePlayer; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; -import com.simibubi.create.content.logistics.trains.ITrackBlock; -import com.simibubi.create.content.logistics.trains.track.FakeTrackBlock; +import com.simibubi.create.content.contraptions.actors.plough.PloughBlock.PloughFakePlayer; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.kinetics.base.BlockBreakingMovementBehaviour; +import com.simibubi.create.content.trains.track.FakeTrackBlock; +import com.simibubi.create.content.trains.track.ITrackBlock; import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.utility.VecHelper; @@ -38,8 +39,9 @@ public class PloughMovementBehaviour extends BlockBreakingMovementBehaviour { @Override public boolean isActive(MovementContext context) { - return !VecHelper.isVecPointingTowards(context.relativeMotion, context.state.getValue(PloughBlock.FACING) - .getOpposite()); + return super.isActive(context) + && !VecHelper.isVecPointingTowards(context.relativeMotion, context.state.getValue(PloughBlock.FACING) + .getOpposite()); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PIInstance.java b/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PIInstance.java similarity index 96% rename from src/main/java/com/simibubi/create/content/contraptions/components/actors/PIInstance.java rename to src/main/java/com/simibubi/create/content/contraptions/actors/psi/PIInstance.java index ec28142a6..087c79b0c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PIInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PIInstance.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.actors; +package com.simibubi.create.content.contraptions.actors.psi; import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.core.Materials; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PSIActorInstance.java b/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PSIActorInstance.java similarity index 78% rename from src/main/java/com/simibubi/create/content/contraptions/components/actors/PSIActorInstance.java rename to src/main/java/com/simibubi/create/content/contraptions/actors/psi/PSIActorInstance.java index 8dad7184b..9cee93e99 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PSIActorInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PSIActorInstance.java @@ -1,9 +1,9 @@ -package com.simibubi.create.content.contraptions.components.actors; +package com.simibubi.create.content.contraptions.actors.psi; import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.contraptions.render.ActorInstance; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.animation.LerpedFloat; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PSIInstance.java b/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PSIInstance.java similarity index 83% rename from src/main/java/com/simibubi/create/content/contraptions/components/actors/PSIInstance.java rename to src/main/java/com/simibubi/create/content/contraptions/actors/psi/PSIInstance.java index 5ddcac06e..4fa102041 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PSIInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PSIInstance.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.actors; +package com.simibubi.create.content.contraptions.actors.psi; import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.api.instance.DynamicInstance; @@ -6,12 +6,12 @@ import com.jozufozu.flywheel.api.instance.TickableInstance; import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance; import com.simibubi.create.foundation.utility.AnimationTickHolder; -public class PSIInstance extends BlockEntityInstance implements DynamicInstance, TickableInstance { +public class PSIInstance extends BlockEntityInstance implements DynamicInstance, TickableInstance { private final PIInstance instance; - public PSIInstance(MaterialManager materialManager, PortableStorageInterfaceTileEntity tile) { - super(materialManager, tile); + public PSIInstance(MaterialManager materialManager, PortableStorageInterfaceBlockEntity blockEntity) { + super(materialManager, blockEntity); instance = new PIInstance(materialManager, blockState, getInstancePosition()); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableFluidInterfaceBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableFluidInterfaceBlockEntity.java new file mode 100644 index 000000000..99b310634 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableFluidInterfaceBlockEntity.java @@ -0,0 +1,120 @@ +package com.simibubi.create.content.contraptions.actors.psi; + +import com.simibubi.create.content.contraptions.Contraption; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fluids.capability.templates.FluidTank; + +public class PortableFluidInterfaceBlockEntity extends PortableStorageInterfaceBlockEntity { + + protected LazyOptional capability; + + public PortableFluidInterfaceBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + capability = createEmptyHandler(); + } + + @Override + public void startTransferringTo(Contraption contraption, float distance) { + LazyOptional oldcap = capability; + capability = LazyOptional.of(() -> new InterfaceFluidHandler(contraption.getSharedFluidTanks())); + oldcap.invalidate(); + super.startTransferringTo(contraption, distance); + } + + @Override + protected void invalidateCapability() { + capability.invalidate(); + } + + @Override + protected void stopTransferring() { + LazyOptional oldcap = capability; + capability = createEmptyHandler(); + oldcap.invalidate(); + super.stopTransferring(); + } + + private LazyOptional createEmptyHandler() { + return LazyOptional.of(() -> new InterfaceFluidHandler(new FluidTank(0))); + } + + @Override + public LazyOptional getCapability(Capability cap, Direction side) { + if (isFluidHandlerCap(cap)) + return capability.cast(); + return super.getCapability(cap, side); + } + + public class InterfaceFluidHandler implements IFluidHandler { + + private IFluidHandler wrapped; + + public InterfaceFluidHandler(IFluidHandler wrapped) { + this.wrapped = wrapped; + } + + @Override + public int getTanks() { + return wrapped.getTanks(); + } + + @Override + public FluidStack getFluidInTank(int tank) { + return wrapped.getFluidInTank(tank); + } + + @Override + public int getTankCapacity(int tank) { + return wrapped.getTankCapacity(tank); + } + + @Override + public boolean isFluidValid(int tank, FluidStack stack) { + return wrapped.isFluidValid(tank, stack); + } + + @Override + public int fill(FluidStack resource, FluidAction action) { + if (!isConnected()) + return 0; + int fill = wrapped.fill(resource, action); + if (fill > 0 && action.execute()) + keepAlive(); + return fill; + } + + @Override + public FluidStack drain(FluidStack resource, FluidAction action) { + if (!canTransfer()) + return FluidStack.EMPTY; + FluidStack drain = wrapped.drain(resource, action); + if (!drain.isEmpty() && action.execute()) + keepAlive(); + return drain; + } + + @Override + public FluidStack drain(int maxDrain, FluidAction action) { + if (!canTransfer()) + return FluidStack.EMPTY; + FluidStack drain = wrapped.drain(maxDrain, action); + if (!drain.isEmpty() && action.execute()) + keepAlive(); + return drain; + } + + public void keepAlive() { + onContentTransferred(); + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableItemInterfaceBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableItemInterfaceBlockEntity.java new file mode 100644 index 000000000..fd72d5627 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableItemInterfaceBlockEntity.java @@ -0,0 +1,85 @@ +package com.simibubi.create.content.contraptions.actors.psi; + +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.foundation.item.ItemHandlerWrapper; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.ItemStackHandler; + +public class PortableItemInterfaceBlockEntity extends PortableStorageInterfaceBlockEntity { + + protected LazyOptional capability; + + public PortableItemInterfaceBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + capability = createEmptyHandler(); + } + + @Override + public void startTransferringTo(Contraption contraption, float distance) { + LazyOptional oldCap = capability; + capability = LazyOptional.of(() -> new InterfaceItemHandler(contraption.getSharedInventory())); + oldCap.invalidate(); + super.startTransferringTo(contraption, distance); + } + + @Override + protected void stopTransferring() { + LazyOptional oldCap = capability; + capability = createEmptyHandler(); + oldCap.invalidate(); + super.stopTransferring(); + } + + private LazyOptional createEmptyHandler() { + return LazyOptional.of(() -> new InterfaceItemHandler(new ItemStackHandler(0))); + } + + @Override + protected void invalidateCapability() { + capability.invalidate(); + } + + @Override + public LazyOptional getCapability(Capability cap, Direction side) { + if (isItemHandlerCap(cap)) + return capability.cast(); + return super.getCapability(cap, side); + } + + class InterfaceItemHandler extends ItemHandlerWrapper { + + public InterfaceItemHandler(IItemHandlerModifiable wrapped) { + super(wrapped); + } + + @Override + public ItemStack extractItem(int slot, int amount, boolean simulate) { + if (!canTransfer()) + return ItemStack.EMPTY; + ItemStack extractItem = super.extractItem(slot, amount, simulate); + if (!simulate && !extractItem.isEmpty()) + onContentTransferred(); + return extractItem; + } + + @Override + public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) { + if (!canTransfer()) + return stack; + ItemStack insertItem = super.insertItem(slot, stack, simulate); + if (!simulate && !insertItem.equals(stack, false)) + onContentTransferred(); + return insertItem; + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceBlock.java b/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableStorageInterfaceBlock.java similarity index 78% rename from src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceBlock.java rename to src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableStorageInterfaceBlock.java index 9bda8441e..9faee84b6 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableStorageInterfaceBlock.java @@ -1,11 +1,11 @@ -package com.simibubi.create.content.contraptions.components.actors; +package com.simibubi.create.content.contraptions.actors.psi; import javax.annotation.ParametersAreNonnullByDefault; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; import com.simibubi.create.foundation.advancement.AdvancementBehaviour; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.block.WrenchableDirectionalBlock; import net.minecraft.MethodsReturnNonnullByDefault; @@ -25,7 +25,7 @@ import net.minecraft.world.phys.shapes.VoxelShape; @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault public class PortableStorageInterfaceBlock extends WrenchableDirectionalBlock - implements ITE { + implements IBE { boolean fluids; @@ -45,7 +45,7 @@ public class PortableStorageInterfaceBlock extends WrenchableDirectionalBlock @Override public void neighborChanged(BlockState state, Level world, BlockPos pos, Block p_220069_4_, BlockPos p_220069_5_, boolean p_220069_6_) { - withTileEntityDo(world, pos, PortableStorageInterfaceTileEntity::neighbourChanged); + withBlockEntityDo(world, pos, PortableStorageInterfaceBlockEntity::neighbourChanged); } @Override @@ -75,19 +75,19 @@ public class PortableStorageInterfaceBlock extends WrenchableDirectionalBlock @Override public int getAnalogOutputSignal(BlockState blockState, Level worldIn, BlockPos pos) { - return getTileEntityOptional(worldIn, pos).map(te -> te.isConnected() ? 15 : 0) + return getBlockEntityOptional(worldIn, pos).map(be -> be.isConnected() ? 15 : 0) .orElse(0); } @Override - public Class getTileEntityClass() { - return PortableStorageInterfaceTileEntity.class; + public Class getBlockEntityClass() { + return PortableStorageInterfaceBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return fluids ? AllTileEntities.PORTABLE_FLUID_INTERFACE.get() - : AllTileEntities.PORTABLE_STORAGE_INTERFACE.get(); + public BlockEntityType getBlockEntityType() { + return fluids ? AllBlockEntityTypes.PORTABLE_FLUID_INTERFACE.get() + : AllBlockEntityTypes.PORTABLE_STORAGE_INTERFACE.get(); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableStorageInterfaceBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableStorageInterfaceBlockEntity.java new file mode 100644 index 000000000..18d13c84b --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableStorageInterfaceBlockEntity.java @@ -0,0 +1,202 @@ +package com.simibubi.create.content.contraptions.actors.psi; + +import java.util.List; + +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; + +public abstract class PortableStorageInterfaceBlockEntity extends SmartBlockEntity { + + public static final int ANIMATION = 4; + protected int transferTimer; + protected float distance; + protected LerpedFloat connectionAnimation; + protected boolean powered; + protected Entity connectedEntity; + + public int keepAlive = 0; + + public PortableStorageInterfaceBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + transferTimer = 0; + connectionAnimation = LerpedFloat.linear() + .startWithValue(0); + powered = false; + } + + public void startTransferringTo(Contraption contraption, float distance) { + if (connectedEntity == contraption.entity) + return; + this.distance = Math.min(2, distance); + connectedEntity = contraption.entity; + startConnecting(); + notifyUpdate(); + } + + protected void stopTransferring() { + connectedEntity = null; + level.updateNeighborsAt(worldPosition, getBlockState().getBlock()); + } + + public boolean canTransfer() { + if (connectedEntity != null && !connectedEntity.isAlive()) + stopTransferring(); + return connectedEntity != null && isConnected(); + } + + @Override + public void initialize() { + super.initialize(); + powered = level.hasNeighborSignal(worldPosition); + if (!powered) + notifyContraptions(); + } + + protected abstract void invalidateCapability(); + + @Override + public void tick() { + super.tick(); + boolean wasConnected = isConnected(); + int timeUnit = getTransferTimeout(); + int animation = ANIMATION; + + if (keepAlive > 0) { + keepAlive--; + if (keepAlive == 0 && !level.isClientSide) { + stopTransferring(); + transferTimer = ANIMATION - 1; + sendData(); + return; + } + } + + transferTimer = Math.min(transferTimer, ANIMATION * 2 + timeUnit); + + boolean timerCanDecrement = transferTimer > ANIMATION || transferTimer > 0 && keepAlive == 0 + && (isVirtual() || !level.isClientSide || transferTimer != ANIMATION); + + if (timerCanDecrement && (!isVirtual() || transferTimer != ANIMATION)) { + transferTimer--; + if (transferTimer == ANIMATION - 1) + sendData(); + if (transferTimer <= 0 || powered) + stopTransferring(); + } + + boolean isConnected = isConnected(); + if (wasConnected != isConnected && !level.isClientSide) + setChanged(); + + float progress = 0; + if (isConnected) + progress = 1; + else if (transferTimer >= timeUnit + animation) + progress = Mth.lerp((transferTimer - timeUnit - animation) / (float) animation, 1, 0); + else if (transferTimer < animation) + progress = Mth.lerp(transferTimer / (float) animation, 0, 1); + connectionAnimation.setValue(progress); + } + + @Override + public void invalidate() { + super.invalidate(); + invalidateCapability(); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + super.read(compound, clientPacket); + transferTimer = compound.getInt("Timer"); + distance = compound.getFloat("Distance"); + boolean poweredPreviously = powered; + powered = compound.getBoolean("Powered"); + if (clientPacket && powered != poweredPreviously && !powered) + notifyContraptions(); + } + + @Override + protected void write(CompoundTag compound, boolean clientPacket) { + super.write(compound, clientPacket); + compound.putInt("Timer", transferTimer); + compound.putFloat("Distance", distance); + compound.putBoolean("Powered", powered); + } + + public void neighbourChanged() { + boolean isBlockPowered = level.hasNeighborSignal(worldPosition); + if (isBlockPowered == powered) + return; + powered = isBlockPowered; + if (!powered) + notifyContraptions(); + if (powered) + stopTransferring(); + sendData(); + } + + private void notifyContraptions() { + level.getEntitiesOfClass(AbstractContraptionEntity.class, new AABB(worldPosition).inflate(3)) + .forEach(AbstractContraptionEntity::refreshPSIs); + } + + public boolean isPowered() { + return powered; + } + + @Override + protected AABB createRenderBoundingBox() { + return super.createRenderBoundingBox().inflate(2); + } + + public boolean isTransferring() { + return transferTimer > ANIMATION; + } + + boolean isConnected() { + int timeUnit = getTransferTimeout(); + return transferTimer >= ANIMATION && transferTimer <= timeUnit + ANIMATION; + } + + float getExtensionDistance(float partialTicks) { + return (float) (Math.pow(connectionAnimation.getValue(partialTicks), 2) * distance / 2); + } + + float getConnectionDistance() { + return distance; + } + + public void startConnecting() { + transferTimer = 6 + ANIMATION * 2; + } + + public void onContentTransferred() { + int timeUnit = getTransferTimeout(); + transferTimer = timeUnit + ANIMATION; + award(AllAdvancements.PSI); + sendData(); + } + + protected Integer getTransferTimeout() { + return AllConfigs.server().logistics.psiTimeout.get(); + } + + @Override + public void addBehaviours(List behaviours) { + registerAwardables(behaviours, AllAdvancements.PSI); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceMovement.java b/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableStorageInterfaceMovement.java similarity index 84% rename from src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceMovement.java rename to src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableStorageInterfaceMovement.java index 6df522cf8..32639dd0d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceMovement.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableStorageInterfaceMovement.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.actors; +package com.simibubi.create.content.contraptions.actors.psi; import java.util.Optional; @@ -6,12 +6,12 @@ import org.jetbrains.annotations.Nullable; import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; -import com.simibubi.create.content.logistics.trains.entity.CarriageContraption; +import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.contraptions.render.ActorInstance; +import com.simibubi.create.content.contraptions.render.ContraptionMatrices; +import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher; +import com.simibubi.create.content.trains.entity.CarriageContraption; import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.animation.LerpedFloat; import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; @@ -98,7 +98,7 @@ public class PortableStorageInterfaceMovement implements MovementBehaviour { if (!currentFacingIfValid.isPresent()) return; - PortableStorageInterfaceTileEntity stationaryInterface = + PortableStorageInterfaceBlockEntity stationaryInterface = getStationaryInterfaceAt(context.world, pos, context.state, currentFacingIfValid.get()); if (stationaryInterface == null) { reset(context); @@ -108,7 +108,7 @@ public class PortableStorageInterfaceMovement implements MovementBehaviour { if (stationaryInterface.connectedEntity == null) stationaryInterface.startTransferringTo(context.contraption, stationaryInterface.distance); - boolean timerBelow = stationaryInterface.transferTimer <= PortableStorageInterfaceTileEntity.ANIMATION; + boolean timerBelow = stationaryInterface.transferTimer <= PortableStorageInterfaceBlockEntity.ANIMATION; stationaryInterface.keepAlive = 2; if (context.stall && timerBelow) { context.stall = false; @@ -123,7 +123,7 @@ public class PortableStorageInterfaceMovement implements MovementBehaviour { return false; Direction currentFacing = currentFacingIfValid.get(); - PortableStorageInterfaceTileEntity psi = + PortableStorageInterfaceBlockEntity psi = findStationaryInterface(context.world, pos, context.state, currentFacing); if (psi == null) @@ -165,10 +165,10 @@ public class PortableStorageInterfaceMovement implements MovementBehaviour { getAnimation(context).chase(0, 0.25f, Chaser.LINEAR); } - private PortableStorageInterfaceTileEntity findStationaryInterface(Level world, BlockPos pos, BlockState state, + private PortableStorageInterfaceBlockEntity findStationaryInterface(Level world, BlockPos pos, BlockState state, Direction facing) { for (int i = 0; i < 2; i++) { - PortableStorageInterfaceTileEntity interfaceAt = + PortableStorageInterfaceBlockEntity interfaceAt = getStationaryInterfaceAt(world, pos.relative(facing, i), state, facing); if (interfaceAt == null) continue; @@ -177,10 +177,10 @@ public class PortableStorageInterfaceMovement implements MovementBehaviour { return null; } - private PortableStorageInterfaceTileEntity getStationaryInterfaceAt(Level world, BlockPos pos, BlockState state, + private PortableStorageInterfaceBlockEntity getStationaryInterfaceAt(Level world, BlockPos pos, BlockState state, Direction facing) { - BlockEntity te = world.getBlockEntity(pos); - if (!(te instanceof PortableStorageInterfaceTileEntity psi)) + BlockEntity blockEntity = world.getBlockEntity(pos); + if (!(blockEntity instanceof PortableStorageInterfaceBlockEntity psi)) return null; BlockState blockState = world.getBlockState(pos); if (blockState.getBlock() != state.getBlock()) diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableStorageInterfaceRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableStorageInterfaceRenderer.java new file mode 100644 index 000000000..6ceffab7d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableStorageInterfaceRenderer.java @@ -0,0 +1,118 @@ +package com.simibubi.create.content.contraptions.actors.psi; + +import java.util.function.Consumer; + +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.core.PartialModel; +import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.contraptions.render.ContraptionMatrices; +import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher; +import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.animation.LerpedFloat; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; + +public class PortableStorageInterfaceRenderer extends SafeBlockEntityRenderer { + + public PortableStorageInterfaceRenderer(BlockEntityRendererProvider.Context context) {} + + @Override + protected void renderSafe(PortableStorageInterfaceBlockEntity be, float partialTicks, PoseStack ms, + MultiBufferSource buffer, int light, int overlay) { + if (Backend.canUseInstancing(be.getLevel())) + return; + + BlockState blockState = be.getBlockState(); + float progress = be.getExtensionDistance(partialTicks); + VertexConsumer vb = buffer.getBuffer(RenderType.solid()); + render(blockState, be.isConnected(), progress, null, sbb -> sbb.light(light) + .renderInto(ms, vb)); + } + + public static void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld, + ContraptionMatrices matrices, MultiBufferSource buffer) { + BlockState blockState = context.state; + VertexConsumer vb = buffer.getBuffer(RenderType.solid()); + float renderPartialTicks = AnimationTickHolder.getPartialTicks(); + + LerpedFloat animation = PortableStorageInterfaceMovement.getAnimation(context); + float progress = animation.getValue(renderPartialTicks); + boolean lit = animation.settled(); + render(blockState, lit, progress, matrices.getModel(), + sbb -> sbb + .light(matrices.getWorld(), ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) + .renderInto(matrices.getViewProjection(), vb)); + } + + private static void render(BlockState blockState, boolean lit, float progress, PoseStack local, + Consumer drawCallback) { + SuperByteBuffer middle = CachedBufferer.partial(getMiddleForState(blockState, lit), blockState); + SuperByteBuffer top = CachedBufferer.partial(getTopForState(blockState), blockState); + + if (local != null) { + middle.transform(local); + top.transform(local); + } + Direction facing = blockState.getValue(PortableStorageInterfaceBlock.FACING); + rotateToFacing(middle, facing); + rotateToFacing(top, facing); + middle.translate(0, progress * 0.5f + 0.375f, 0); + top.translate(0, progress, 0); + + drawCallback.accept(middle); + drawCallback.accept(top); + } + + private static void rotateToFacing(SuperByteBuffer buffer, Direction facing) { + buffer.centre() + .rotateY(AngleHelper.horizontalAngle(facing)) + .rotateX(facing == Direction.UP ? 0 : facing == Direction.DOWN ? 180 : 90) + .unCentre(); + } + + static PortableStorageInterfaceBlockEntity getTargetPSI(MovementContext context) { + String _workingPos_ = PortableStorageInterfaceMovement._workingPos_; + if (!context.data.contains(_workingPos_)) + return null; + + BlockPos pos = NbtUtils.readBlockPos(context.data.getCompound(_workingPos_)); + BlockEntity blockEntity = context.world.getBlockEntity(pos); + if (!(blockEntity instanceof PortableStorageInterfaceBlockEntity psi)) + return null; + + if (!psi.isTransferring()) + return null; + return psi; + } + + static PartialModel getMiddleForState(BlockState state, boolean lit) { + if (AllBlocks.PORTABLE_FLUID_INTERFACE.has(state)) + return lit ? AllPartialModels.PORTABLE_FLUID_INTERFACE_MIDDLE_POWERED + : AllPartialModels.PORTABLE_FLUID_INTERFACE_MIDDLE; + return lit ? AllPartialModels.PORTABLE_STORAGE_INTERFACE_MIDDLE_POWERED + : AllPartialModels.PORTABLE_STORAGE_INTERFACE_MIDDLE; + } + + static PartialModel getTopForState(BlockState state) { + if (AllBlocks.PORTABLE_FLUID_INTERFACE.has(state)) + return AllPartialModels.PORTABLE_FLUID_INTERFACE_TOP; + return AllPartialModels.PORTABLE_STORAGE_INTERFACE_TOP; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/roller/PaveTask.java b/src/main/java/com/simibubi/create/content/contraptions/actors/roller/PaveTask.java new file mode 100644 index 000000000..abefe49a6 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/roller/PaveTask.java @@ -0,0 +1,40 @@ +package com.simibubi.create.content.contraptions.actors.roller; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import com.simibubi.create.foundation.utility.Couple; + +import net.minecraft.core.BlockPos; + +public class PaveTask { + + private Couple horizontalInterval; + private Map, Float> heightValues = new HashMap<>(); + + public PaveTask(double h1, double h2) { + horizontalInterval = Couple.create(h1, h2); + } + + public Couple getHorizontalInterval() { + return horizontalInterval; + } + + public void put(int x, int z, float y) { + heightValues.put(Couple.create(x, z), y); + } + + public float get(Couple coords) { + return heightValues.get(coords); + } + + public Set> keys() { + return heightValues.keySet(); + } + + public void put(BlockPos p) { + put(p.getX(), p.getZ(), p.getY()); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerActorInstance.java b/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerActorInstance.java new file mode 100644 index 000000000..1e76217e7 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerActorInstance.java @@ -0,0 +1,64 @@ +package com.simibubi.create.content.contraptions.actors.roller; + +import com.jozufozu.flywheel.api.Material; +import com.jozufozu.flywheel.api.MaterialManager; +import com.jozufozu.flywheel.core.Materials; +import com.jozufozu.flywheel.core.PartialModel; +import com.jozufozu.flywheel.core.materials.model.ModelData; +import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.contraptions.actors.harvester.HarvesterActorInstance; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; + +import net.minecraft.world.phys.Vec3; + +public class RollerActorInstance extends HarvesterActorInstance { + + ModelData frame; + + public RollerActorInstance(MaterialManager materialManager, VirtualRenderWorld simulationWorld, + MovementContext context) { + super(materialManager, simulationWorld, context); + + Material material = materialManager.defaultCutout() + .material(Materials.TRANSFORMED); + frame = material.getModel(AllPartialModels.ROLLER_FRAME, context.state) + .createInstance(); + frame.setBlockLight(localBlockLight()); + } + + @Override + public void beginFrame() { + harvester.loadIdentity() + .translate(context.localPos) + .centre() + .rotateY(horizontalAngle) + .unCentre() + .translate(0, -.25, 17 / 16f) + .rotateX(getRotation()) + .translate(0, -.5, .5) + .rotateY(90); + + frame.loadIdentity() + .translate(context.localPos) + .centre() + .rotateY(horizontalAngle + 180) + .unCentre(); + } + + @Override + protected PartialModel getRollingPartial() { + return AllPartialModels.ROLLER_WHEEL; + } + + @Override + protected Vec3 getRotationOffset() { + return Vec3.ZERO; + } + + @Override + protected double getRadius() { + return 16.5; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerBlock.java b/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerBlock.java new file mode 100644 index 000000000..99166cd46 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerBlock.java @@ -0,0 +1,107 @@ +package com.simibubi.create.content.contraptions.actors.roller; + +import java.util.function.Predicate; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.contraptions.actors.AttachedActorBlock; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.placement.IPlacementHelper; +import com.simibubi.create.foundation.placement.PlacementHelpers; +import com.simibubi.create.foundation.placement.PoleHelper; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.entity.BlockEntityType; +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 RollerBlock extends AttachedActorBlock implements IBE { + + public static DamageSource damageSourceRoller = new DamageSource("create.mechanical_roller"); + + private static final int placementHelperId = PlacementHelpers.register(new PlacementHelper()); + + public RollerBlock(Properties p_i48377_1_) { + super(p_i48377_1_); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext context) { + return withWater(defaultBlockState().setValue(FACING, context.getHorizontalDirection() + .getOpposite()), context); + } + + @Override + public Class getBlockEntityClass() { + return RollerBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.MECHANICAL_ROLLER.get(); + } + + @Override + public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) { + return Shapes.block(); + } + + @Override + public boolean canSurvive(BlockState state, LevelReader worldIn, BlockPos pos) { + return true; + } + + @Override + public void setPlacedBy(Level pLevel, BlockPos pPos, BlockState pState, LivingEntity pPlacer, ItemStack pStack) { + super.setPlacedBy(pLevel, pPos, pState, pPlacer, pStack); + withBlockEntityDo(pLevel, pPos, RollerBlockEntity::searchForSharedValues); + } + + @Override + public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, + BlockHitResult ray) { + ItemStack heldItem = player.getItemInHand(hand); + + IPlacementHelper placementHelper = PlacementHelpers.get(placementHelperId); + if (!player.isShiftKeyDown() && player.mayBuild()) { + if (placementHelper.matchesItem(heldItem)) { + placementHelper.getOffset(player, world, state, pos, ray) + .placeInWorld(world, (BlockItem) heldItem.getItem(), player, hand, ray); + return InteractionResult.SUCCESS; + } + } + + return InteractionResult.PASS; + } + + private static class PlacementHelper extends PoleHelper { + + public PlacementHelper() { + super(AllBlocks.MECHANICAL_ROLLER::has, state -> state.getValue(FACING) + .getClockWise() + .getAxis(), FACING); + } + + @Override + public Predicate getItemPredicate() { + return AllBlocks.MECHANICAL_ROLLER::isIn; + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerBlockEntity.java new file mode 100644 index 000000000..17a3cb1b9 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerBlockEntity.java @@ -0,0 +1,207 @@ +package com.simibubi.create.content.contraptions.actors.roller; + +import java.util.List; + +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.INamedIconOptions; +import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollOptionBehaviour; +import com.simibubi.create.foundation.gui.AllIcons; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.EntityBlock; +import net.minecraft.world.level.block.StairBlock; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; + +public class RollerBlockEntity extends SmartBlockEntity { + + // For simulations such as Ponder + private float manuallyAnimatedSpeed; + + public FilteringBehaviour filtering; + public ScrollOptionBehaviour mode; + + private boolean dontPropagate; + + public RollerBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + dontPropagate = false; + } + + @Override + public void addBehaviours(List behaviours) { + behaviours.add(filtering = new FilteringBehaviour(this, new RollerValueBox(3))); + behaviours.add(mode = new ScrollOptionBehaviour(RollingMode.class, + Lang.translateDirect("contraptions.roller_mode"), this, new RollerValueBox(-3))); + + filtering.setLabel(Lang.translateDirect("contraptions.mechanical_roller.pave_material")); + filtering.withCallback(this::onFilterChanged); + filtering.withPredicate(this::isValidMaterial); + mode.withCallback(this::onModeChanged); + } + + protected void onModeChanged(int mode) { + shareValuesToAdjacent(); + } + + protected void onFilterChanged(ItemStack newFilter) { + shareValuesToAdjacent(); + } + + protected boolean isValidMaterial(ItemStack newFilter) { + if (newFilter.isEmpty()) + return true; + BlockState appliedState = RollerMovementBehaviour.getStateToPaveWith(newFilter); + if (appliedState.isAir()) + return false; + if (appliedState.getBlock() instanceof EntityBlock) + return false; + if (appliedState.getBlock() instanceof StairBlock) + return false; + VoxelShape shape = appliedState.getShape(level, worldPosition); + if (shape.isEmpty() || !shape.bounds() + .equals(Shapes.block() + .bounds())) + return false; + VoxelShape collisionShape = appliedState.getCollisionShape(level, worldPosition); + if (collisionShape.isEmpty()) + return false; + return true; + } + + @Override + protected AABB createRenderBoundingBox() { + return new AABB(worldPosition).inflate(1); + } + + public float getAnimatedSpeed() { + return manuallyAnimatedSpeed; + } + + public void setAnimatedSpeed(float speed) { + manuallyAnimatedSpeed = speed; + } + + public void searchForSharedValues() { + BlockState blockState = getBlockState(); + Direction facing = blockState.getOptionalValue(RollerBlock.FACING) + .orElse(Direction.SOUTH); + + for (int side : Iterate.positiveAndNegative) { + BlockPos pos = worldPosition.relative(facing.getClockWise(), side); + if (level.getBlockState(pos) != blockState) + continue; + if (!(level.getBlockEntity(pos) instanceof RollerBlockEntity otherRoller)) + continue; + acceptSharedValues(otherRoller.mode.getValue(), otherRoller.filtering.getFilter()); + shareValuesToAdjacent(); + break; + } + } + + protected void acceptSharedValues(int mode, ItemStack filter) { + dontPropagate = true; + this.filtering.setFilter(filter); + this.mode.setValue(mode); + dontPropagate = false; + notifyUpdate(); + } + + public void shareValuesToAdjacent() { + if (dontPropagate || level.isClientSide()) + return; + BlockState blockState = getBlockState(); + Direction facing = blockState.getOptionalValue(RollerBlock.FACING) + .orElse(Direction.SOUTH); + + for (int side : Iterate.positiveAndNegative) { + for (int i = 1; i < 100; i++) { + BlockPos pos = worldPosition.relative(facing.getClockWise(), side * i); + if (level.getBlockState(pos) != blockState) + break; + if (!(level.getBlockEntity(pos) instanceof RollerBlockEntity otherRoller)) + break; + otherRoller.acceptSharedValues(mode.getValue(), filtering.getFilter()); + } + } + } + + static enum RollingMode implements INamedIconOptions { + + TUNNEL_PAVE(AllIcons.I_ROLLER_PAVE), + STRAIGHT_FILL(AllIcons.I_ROLLER_FILL), + WIDE_FILL(AllIcons.I_ROLLER_WIDE_FILL), + + ; + + private String translationKey; + private AllIcons icon; + + private RollingMode(AllIcons icon) { + this.icon = icon; + translationKey = "contraptions.roller_mode." + Lang.asId(name()); + } + + @Override + public AllIcons getIcon() { + return icon; + } + + @Override + public String getTranslationKey() { + return translationKey; + } + + } + + private final class RollerValueBox extends ValueBoxTransform { + + private int hOffset; + + public RollerValueBox(int hOffset) { + this.hOffset = hOffset; + } + + @Override + public void rotate(BlockState state, PoseStack ms) { + Direction facing = state.getValue(RollerBlock.FACING); + float yRot = AngleHelper.horizontalAngle(facing) + 180; + TransformStack.cast(ms) + .rotateY(yRot) + .rotateX(90); + } + + @Override + public boolean testHit(BlockState state, Vec3 localHit) { + Vec3 offset = getLocalOffset(state); + if (offset == null) + return false; + return localHit.distanceTo(offset) < scale / 3; + } + + @Override + public Vec3 getLocalOffset(BlockState state) { + Direction facing = state.getValue(RollerBlock.FACING); + float stateAngle = AngleHelper.horizontalAngle(facing) + 180; + return VecHelper.rotateCentered(VecHelper.voxelSpace(8 + hOffset, 15.5f, 11), stateAngle, Axis.Y); + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerBlockItem.java b/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerBlockItem.java new file mode 100644 index 000000000..3bf7c6070 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerBlockItem.java @@ -0,0 +1,29 @@ +package com.simibubi.create.content.contraptions.actors.roller; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; + +public class RollerBlockItem extends BlockItem { + + public RollerBlockItem(Block pBlock, Properties pProperties) { + super(pBlock, pProperties); + } + + @Override + public InteractionResult place(BlockPlaceContext ctx) { + BlockPos clickedPos = ctx.getClickedPos(); + Level level = ctx.getLevel(); + BlockState blockStateBelow = level.getBlockState(clickedPos.below()); + if (!Block.isFaceFull(blockStateBelow.getCollisionShape(level, clickedPos.below()), Direction.UP)) + return super.place(ctx); + Direction clickedFace = ctx.getClickedFace(); + return super.place(BlockPlaceContext.at(ctx, clickedPos.relative(Direction.UP), clickedFace)); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerMovementBehaviour.java new file mode 100644 index 000000000..a0bf842c2 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerMovementBehaviour.java @@ -0,0 +1,470 @@ +package com.simibubi.create.content.contraptions.actors.roller; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.function.BiConsumer; + +import javax.annotation.Nullable; + +import com.jozufozu.flywheel.api.MaterialManager; +import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.contraptions.actors.roller.RollerBlockEntity.RollingMode; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.contraptions.pulley.PulleyContraption; +import com.simibubi.create.content.contraptions.render.ActorInstance; +import com.simibubi.create.content.contraptions.render.ContraptionMatrices; +import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher; +import com.simibubi.create.content.kinetics.base.BlockBreakingMovementBehaviour; +import com.simibubi.create.content.logistics.filter.FilterItem; +import com.simibubi.create.content.trains.bogey.StandardBogeyBlock; +import com.simibubi.create.content.trains.entity.Carriage; +import com.simibubi.create.content.trains.entity.CarriageBogey; +import com.simibubi.create.content.trains.entity.CarriageContraptionEntity; +import com.simibubi.create.content.trains.entity.Train; +import com.simibubi.create.content.trains.entity.TravellingPoint; +import com.simibubi.create.content.trains.entity.TravellingPoint.ITrackSelector; +import com.simibubi.create.content.trains.entity.TravellingPoint.SteerDirection; +import com.simibubi.create.content.trains.graph.TrackEdge; +import com.simibubi.create.content.trains.graph.TrackGraph; +import com.simibubi.create.foundation.item.ItemHelper; +import com.simibubi.create.foundation.utility.BlockHelper; +import com.simibubi.create.foundation.utility.Couple; +import com.simibubi.create.foundation.utility.Pair; +import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.BlockTags; +import net.minecraft.util.Mth; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.item.BlockItem; +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.Blocks; +import net.minecraft.world.level.block.FallingBlock; +import net.minecraft.world.level.block.SlabBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.SlabType; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.registries.ForgeRegistries; + +public class RollerMovementBehaviour extends BlockBreakingMovementBehaviour { + + @Override + public boolean isActive(MovementContext context) { + return super.isActive(context) && !(context.contraption instanceof PulleyContraption) + && VecHelper.isVecPointingTowards(context.relativeMotion, context.state.getValue(RollerBlock.FACING)); + } + + @Override + public boolean hasSpecialInstancedRendering() { + return true; + } + + @Nullable + @Override + public ActorInstance createInstance(MaterialManager materialManager, VirtualRenderWorld simulationWorld, + MovementContext context) { + return new RollerActorInstance(materialManager, simulationWorld, context); + } + + @Override + public void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld, + ContraptionMatrices matrices, MultiBufferSource buffers) { + if (!ContraptionRenderDispatcher.canInstance()) + RollerRenderer.renderInContraption(context, renderWorld, matrices, buffers); + } + + @Override + public Vec3 getActiveAreaOffset(MovementContext context) { + return Vec3.atLowerCornerOf(context.state.getValue(RollerBlock.FACING) + .getNormal()) + .scale(.45) + .subtract(0, 2, 0); + } + + @Override + protected float getBlockBreakingSpeed(MovementContext context) { + return Mth.clamp(super.getBlockBreakingSpeed(context) * 1.5f, 1 / 128f, 16f); + } + + @Override + public boolean canBreak(Level world, BlockPos breakingPos, BlockState state) { + return super.canBreak(world, breakingPos, state) && !state.getCollisionShape(world, breakingPos) + .isEmpty() && !AllBlocks.TRACK.has(state); + } + + @Override + protected DamageSource getDamageSource() { + return RollerBlock.damageSourceRoller; + } + + @Override + public void visitNewPosition(MovementContext context, BlockPos pos) { + Level world = context.world; + BlockState stateVisited = world.getBlockState(pos); + if (!stateVisited.isRedstoneConductor(world, pos)) + damageEntities(context, pos, world); + if (world.isClientSide) + return; + + List positionsToBreak = getPositionsToBreak(context, pos); + if (positionsToBreak.isEmpty()) { + triggerPaver(context, pos); + return; + } + + BlockPos argMax = null; + double max = -1; + for (BlockPos toBreak : positionsToBreak) { + float hardness = context.world.getBlockState(toBreak) + .getDestroySpeed(world, toBreak); + if (hardness < max) + continue; + max = hardness; + argMax = toBreak; + } + + if (argMax == null) { + triggerPaver(context, pos); + return; + } + + context.data.put("ReferencePos", NbtUtils.writeBlockPos(pos)); + context.data.put("BreakingPos", NbtUtils.writeBlockPos(argMax)); + context.stall = true; + } + + @Override + protected void onBlockBroken(MovementContext context, BlockPos pos, BlockState brokenState) { + super.onBlockBroken(context, pos, brokenState); + if (!context.data.contains("ReferencePos")) + return; + + BlockPos referencePos = NbtUtils.readBlockPos(context.data.getCompound("ReferencePos")); + for (BlockPos otherPos : getPositionsToBreak(context, referencePos)) + if (!otherPos.equals(pos)) + destroyBlock(context, otherPos); + + triggerPaver(context, referencePos); + context.data.remove("ReferencePos"); + } + + @Override + protected void destroyBlock(MovementContext context, BlockPos breakingPos) { + BlockState blockState = context.world.getBlockState(breakingPos); + boolean noHarvest = blockState.is(BlockTags.NEEDS_IRON_TOOL) || blockState.is(BlockTags.NEEDS_STONE_TOOL) + || blockState.is(BlockTags.NEEDS_DIAMOND_TOOL); + + BlockHelper.destroyBlock(context.world, breakingPos, 1f, stack -> { + if (noHarvest || context.world.random.nextBoolean()) + return; + this.dropItem(context, stack); + }); + + super.destroyBlock(context, breakingPos); + } + + RollerTravellingPoint rollerScout = new RollerTravellingPoint(); + + protected List getPositionsToBreak(MovementContext context, BlockPos visitedPos) { + ArrayList positions = new ArrayList<>(); + + RollingMode mode = getMode(context); + if (mode != RollingMode.TUNNEL_PAVE) + return positions; + + int startingY = 1; + if (!getStateToPaveWith(context).isAir()) { + ItemStack filter = ItemStack.of(context.blockEntityData.getCompound("Filter")); + if (!ItemHelper + .extract(context.contraption.getSharedInventory(), + stack -> FilterItem.test(context.world, stack, filter), 1, true) + .isEmpty()) + startingY = 0; + } + + // Train + PaveTask profileForTracks = createHeightProfileForTracks(context); + if (profileForTracks != null) { + for (Couple coords : profileForTracks.keys()) { + float height = profileForTracks.get(coords); + BlockPos targetPosition = new BlockPos(coords.getFirst(), height, coords.getSecond()); + boolean shouldPlaceSlab = height > Math.floor(height) + .45; + if (startingY == 1 && shouldPlaceSlab && context.world.getBlockState(targetPosition.above()) + .getOptionalValue(SlabBlock.TYPE) + .orElse(SlabType.DOUBLE) == SlabType.BOTTOM) + startingY = 2; + for (int i = startingY; i <= (shouldPlaceSlab ? 3 : 2); i++) + if (testBreakerTarget(context, targetPosition.above(i), i)) + positions.add(targetPosition.above(i)); + } + return positions; + } + + // Otherwise + for (int i = startingY; i <= 2; i++) + if (testBreakerTarget(context, visitedPos.above(i), i)) + positions.add(visitedPos.above(i)); + + return positions; + } + + protected boolean testBreakerTarget(MovementContext context, BlockPos target, int columnY) { + BlockState stateToPaveWith = getStateToPaveWith(context); + BlockState stateToPaveWithAsSlab = getStateToPaveWithAsSlab(context); + BlockState stateAbove = context.world.getBlockState(target); + if (columnY == 0 && stateAbove.is(stateToPaveWith.getBlock())) + return false; + if (stateToPaveWithAsSlab != null && columnY == 1 && stateAbove.is(stateToPaveWithAsSlab.getBlock())) + return false; + return canBreak(context.world, target, stateAbove); + } + + @Nullable + protected PaveTask createHeightProfileForTracks(MovementContext context) { + if (context.contraption == null) + return null; + if (!(context.contraption.entity instanceof CarriageContraptionEntity cce)) + return null; + Carriage carriage = cce.getCarriage(); + if (carriage == null) + return null; + Train train = carriage.train; + if (train == null || train.graph == null) + return null; + + CarriageBogey mainBogey = carriage.bogeys.getFirst(); + TravellingPoint point = mainBogey.trailing(); + + rollerScout.node1 = point.node1; + rollerScout.node2 = point.node2; + rollerScout.edge = point.edge; + rollerScout.position = point.position; + + Axis axis = Axis.X; + StructureBlockInfo info = context.contraption.getBlocks() + .get(BlockPos.ZERO); + if (info != null && info.state.hasProperty(StandardBogeyBlock.AXIS)) + axis = info.state.getValue(StandardBogeyBlock.AXIS); + + Direction orientation = cce.getInitialOrientation(); + Direction rollerFacing = context.state.getValue(RollerBlock.FACING); + + int step = orientation.getAxisDirection() + .getStep(); + double widthWiseOffset = axis.choose(-context.localPos.getZ(), 0, -context.localPos.getX()) * step; + double lengthWiseOffset = axis.choose(-context.localPos.getX(), 0, context.localPos.getZ()) * step - 1; + + if (rollerFacing == orientation.getClockWise()) + lengthWiseOffset += 1; + + double distanceToTravel = 2; + PaveTask heightProfile = new PaveTask(widthWiseOffset, widthWiseOffset); + ITrackSelector steering = rollerScout.steer(SteerDirection.NONE, new Vec3(0, 1, 0)); + + rollerScout.traversalCallback = (edge, coords) -> { + }; + rollerScout.travel(train.graph, lengthWiseOffset + 1, steering); + + rollerScout.traversalCallback = (edge, coords) -> TrackPaverV2.pave(heightProfile, train.graph, edge, + coords.getFirst(), coords.getSecond()); + rollerScout.travel(train.graph, distanceToTravel, steering); + + for (Couple entry : heightProfile.keys()) + heightProfile.put(entry.getFirst(), entry.getSecond(), context.localPos.getY() + heightProfile.get(entry)); + + return heightProfile; + } + + protected void triggerPaver(MovementContext context, BlockPos pos) { + BlockState stateToPaveWith = getStateToPaveWith(context); + BlockState stateToPaveWithAsSlab = getStateToPaveWithAsSlab(context); + RollingMode mode = getMode(context); + + Vec3 directionVec = Vec3.atLowerCornerOf(context.state.getValue(RollerBlock.FACING) + .getClockWise() + .getNormal()); + directionVec = context.rotation.apply(directionVec); + PaveResult paveResult = PaveResult.PASS; + int yOffset = 0; + + List> paveSet = new ArrayList<>(); + PaveTask profileForTracks = createHeightProfileForTracks(context); + if (profileForTracks == null) + paveSet.add(Pair.of(pos, false)); + else + for (Couple coords : profileForTracks.keys()) { + float height = profileForTracks.get(coords); + boolean shouldPlaceSlab = height > Math.floor(height) + .45; + BlockPos targetPosition = new BlockPos(coords.getFirst(), height, coords.getSecond()); + paveSet.add(Pair.of(targetPosition, shouldPlaceSlab)); + } + + if (paveSet.isEmpty()) + return; + + while (paveResult == PaveResult.PASS) { + if (yOffset > AllConfigs.server().kinetics.rollerFillDepth.get()) { + paveResult = PaveResult.FAIL; + break; + } + + Set> currentLayer = new HashSet<>(); + if (mode == RollingMode.WIDE_FILL) { + for (Pair anchor : paveSet) { + int radius = (yOffset + 1) / 2; + for (int i = -radius; i <= radius; i++) + for (int j = -radius; j <= radius; j++) + if (BlockPos.ZERO.distManhattan(new BlockPos(i, 0, j)) <= radius) + currentLayer.add(Pair.of(anchor.getFirst() + .offset(i, -yOffset, j), anchor.getSecond())); + } + } else + for (Pair anchor : paveSet) + currentLayer.add(Pair.of(anchor.getFirst() + .below(yOffset), anchor.getSecond())); + + boolean completelyBlocked = true; + boolean anyBlockPlaced = false; + + for (Pair currentPos : currentLayer) { + if (stateToPaveWithAsSlab != null && yOffset == 0 && currentPos.getSecond()) + tryFill(context, currentPos.getFirst() + .above(), stateToPaveWithAsSlab); + paveResult = tryFill(context, currentPos.getFirst(), stateToPaveWith); + if (paveResult != PaveResult.FAIL) + completelyBlocked = false; + if (paveResult == PaveResult.SUCCESS) + anyBlockPlaced = true; + } + + if (anyBlockPlaced) + paveResult = PaveResult.SUCCESS; + else if (!completelyBlocked || yOffset == 0) + paveResult = PaveResult.PASS; + + if (paveResult == PaveResult.SUCCESS && stateToPaveWith.getBlock() instanceof FallingBlock) + paveResult = PaveResult.PASS; + if (paveResult != PaveResult.PASS) + break; + if (mode == RollingMode.TUNNEL_PAVE) + break; + + yOffset++; + } + + if (paveResult == PaveResult.SUCCESS) { + context.data.putInt("WaitingTicks", 2); + context.data.put("LastPos", NbtUtils.writeBlockPos(pos)); + context.stall = true; + } + } + + public static BlockState getStateToPaveWith(ItemStack itemStack) { + if (itemStack.getItem()instanceof BlockItem bi) { + BlockState defaultBlockState = bi.getBlock() + .defaultBlockState(); + if (defaultBlockState.hasProperty(SlabBlock.TYPE)) + defaultBlockState = defaultBlockState.setValue(SlabBlock.TYPE, SlabType.DOUBLE); + return defaultBlockState; + } + return Blocks.AIR.defaultBlockState(); + } + + protected BlockState getStateToPaveWith(MovementContext context) { + return getStateToPaveWith(ItemStack.of(context.blockEntityData.getCompound("Filter"))); + } + + protected BlockState getStateToPaveWithAsSlab(MovementContext context) { + BlockState stateToPaveWith = getStateToPaveWith(context); + if (stateToPaveWith.hasProperty(SlabBlock.TYPE)) + return stateToPaveWith.setValue(SlabBlock.TYPE, SlabType.BOTTOM); + + Block block = stateToPaveWith.getBlock(); + if (block == null) + return null; + + ResourceLocation rl = ForgeRegistries.BLOCKS.getKey(block); + String namespace = rl.getNamespace(); + String blockName = rl.getPath(); + int nameLength = blockName.length(); + + List possibleSlabLocations = new ArrayList<>(); + possibleSlabLocations.add(blockName + "_slab"); + + if (blockName.endsWith("s") && nameLength > 1) + possibleSlabLocations.add(blockName.substring(0, nameLength - 1) + "_slab"); + if (blockName.endsWith("planks") && nameLength > 7) + possibleSlabLocations.add(blockName.substring(0, nameLength - 7) + "_slab"); + + for (String locationAttempt : possibleSlabLocations) { + Optional result = ForgeRegistries.BLOCKS.getHolder(new ResourceLocation(namespace, locationAttempt)) + .map(slabHolder -> slabHolder.value()); + if (result.isEmpty()) + continue; + return result.get() + .defaultBlockState(); + } + + return null; + } + + protected RollingMode getMode(MovementContext context) { + return RollingMode.values()[context.blockEntityData.getInt("ScrollValue")]; + } + + private final class RollerTravellingPoint extends TravellingPoint { + + public BiConsumer> traversalCallback; + + @Override + protected Double edgeTraversedFrom(TrackGraph graph, boolean forward, IEdgePointListener edgePointListener, + ITurnListener turnListener, double prevPos, double totalDistance) { + double from = forward ? prevPos : position; + double to = forward ? position : prevPos; + traversalCallback.accept(edge, Couple.create(from, to)); + return super.edgeTraversedFrom(graph, forward, edgePointListener, turnListener, prevPos, totalDistance); + } + + } + + private enum PaveResult { + FAIL, PASS, SUCCESS; + } + + protected PaveResult tryFill(MovementContext context, BlockPos targetPos, BlockState toPlace) { + Level level = context.world; + if (!level.isLoaded(targetPos)) + return PaveResult.FAIL; + BlockState existing = level.getBlockState(targetPos); + if (existing.is(toPlace.getBlock())) + return PaveResult.PASS; + if (!existing.is(BlockTags.LEAVES) && !existing.getMaterial() + .isReplaceable() + && !existing.getCollisionShape(level, targetPos) + .isEmpty()) + return PaveResult.FAIL; + + ItemStack filter = ItemStack.of(context.blockEntityData.getCompound("Filter")); + ItemStack held = ItemHelper.extract(context.contraption.getSharedInventory(), + stack -> FilterItem.test(context.world, stack, filter), 1, false); + if (held.isEmpty()) + return PaveResult.FAIL; + + level.setBlockAndUpdate(targetPos, toPlace); + return PaveResult.SUCCESS; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerRenderer.java new file mode 100644 index 000000000..ec3cab40e --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerRenderer.java @@ -0,0 +1,90 @@ +package com.simibubi.create.content.contraptions.actors.roller; + +import static net.minecraft.world.level.block.state.properties.BlockStateProperties.HORIZONTAL_FACING; + +import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.contraptions.actors.harvester.HarvesterRenderer; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.contraptions.render.ContraptionMatrices; +import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher; +import com.simibubi.create.foundation.blockEntity.renderer.SmartBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider.Context; +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class RollerRenderer extends SmartBlockEntityRenderer { + + public RollerRenderer(Context context) { + super(context); + } + + @Override + protected void renderSafe(RollerBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + super.renderSafe(be, partialTicks, ms, buffer, light, overlay); + + BlockState blockState = be.getBlockState(); + + ms.pushPose(); + ms.translate(0, -0.25, 0); + SuperByteBuffer superBuffer = CachedBufferer.partial(AllPartialModels.ROLLER_WHEEL, blockState); + Direction facing = blockState.getValue(RollerBlock.FACING); + superBuffer.translate(Vec3.atLowerCornerOf(facing.getNormal()) + .scale(17 / 16f)); + HarvesterRenderer.transform(be.getLevel(), facing, superBuffer, be.getAnimatedSpeed(), Vec3.ZERO); + superBuffer.translate(0, -.5, .5) + .rotateY(90) + .light(light) + .renderInto(ms, buffer.getBuffer(RenderType.cutoutMipped())); + ms.popPose(); + + CachedBufferer.partial(AllPartialModels.ROLLER_FRAME, blockState) + .rotateCentered(Direction.UP, AngleHelper.rad(AngleHelper.horizontalAngle(facing) + 180)) + .light(light) + .renderInto(ms, buffer.getBuffer(RenderType.cutoutMipped())); + } + + public static void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld, + ContraptionMatrices matrices, MultiBufferSource buffers) { + BlockState blockState = context.state; + Direction facing = blockState.getValue(HORIZONTAL_FACING); + SuperByteBuffer superBuffer = CachedBufferer.partial(AllPartialModels.ROLLER_WHEEL, blockState); + float speed = (float) (!VecHelper.isVecPointingTowards(context.relativeMotion, facing.getOpposite()) + ? context.getAnimationSpeed() + : -context.getAnimationSpeed()); + if (context.contraption.stalled) + speed = 0; + + superBuffer.transform(matrices.getModel()) + .translate(Vec3.atLowerCornerOf(facing.getNormal()) + .scale(17 / 16f)); + HarvesterRenderer.transform(context.world, facing, superBuffer, speed, Vec3.ZERO); + + PoseStack viewProjection = matrices.getViewProjection(); + viewProjection.pushPose(); + viewProjection.translate(0, -.25, 0); + int contraptionWorldLight = ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld); + superBuffer.translate(0, -.5, .5) + .rotateY(90) + .light(matrices.getWorld(), contraptionWorldLight) + .renderInto(viewProjection, buffers.getBuffer(RenderType.cutoutMipped())); + viewProjection.popPose(); + + CachedBufferer.partial(AllPartialModels.ROLLER_FRAME, blockState) + .transform(matrices.getModel()) + .rotateCentered(Direction.UP, AngleHelper.rad(AngleHelper.horizontalAngle(facing) + 180)) + .light(matrices.getWorld(), contraptionWorldLight) + .renderInto(viewProjection, buffers.getBuffer(RenderType.cutoutMipped())); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/roller/TrackPaverV2.java b/src/main/java/com/simibubi/create/content/contraptions/actors/roller/TrackPaverV2.java new file mode 100644 index 000000000..abcc6fae1 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/roller/TrackPaverV2.java @@ -0,0 +1,217 @@ +package com.simibubi.create.content.contraptions.actors.roller; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import com.simibubi.create.content.trains.graph.TrackEdge; +import com.simibubi.create.content.trains.graph.TrackGraph; +import com.simibubi.create.content.trains.track.BezierConnection; +import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.Pair; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.Mth; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec2; +import net.minecraft.world.phys.Vec3; + +public class TrackPaverV2 { + + public static void pave(PaveTask task, TrackGraph graph, TrackEdge edge, double from, double to) { + if (edge.isTurn()) { + paveCurve(task, edge.getTurn(), from, to); + return; + } + + Vec3 location1 = edge.node1.getLocation() + .getLocation(); + Vec3 location2 = edge.node2.getLocation() + .getLocation(); + Vec3 diff = location2.subtract(location1); + Vec3 direction = VecHelper.clampComponentWise(diff, 1); + int extent = (int) Math.round((to - from) / direction.length()); + double length = edge.getLength(); + + BlockPos pos = new BlockPos(edge.getPosition(graph, Mth.clamp(from, 1 / 16f, length - 1 / 16f) / length) + .subtract(0, diff.y != 0 ? 1 : 0.5, 0)); + + paveStraight(task, pos, direction, extent); + } + + public static void paveStraight(PaveTask task, BlockPos startPos, Vec3 direction, int extent) { + Set toPlaceOn = new HashSet<>(); + Vec3 start = VecHelper.getCenterOf(startPos); + Vec3 mainNormal = direction.cross(new Vec3(0, 1, 0)); + Vec3 normalizedDirection = direction.normalize(); + + boolean isDiagonalTrack = direction.multiply(1, 0, 1) + .length() > 1.125f; + double r1 = task.getHorizontalInterval() + .getFirst(); + int flip = (int) Math.signum(r1); + double r2 = r1 + flip; + + if (isDiagonalTrack) { + r1 /= Mth.SQRT_OF_TWO; + r2 /= Mth.SQRT_OF_TWO; + } + + int currentOffset = (int) (Math.abs(r1) * 2 + .5f); + int nextOffset = (int) (Math.abs(r2) * 2 + .5f); + + for (int i = 0; i < extent; i++) { + Vec3 offset = direction.scale(i); + Vec3 mainPos = start.add(offset.x, offset.y, offset.z); + Vec3 targetVec = mainPos.add(mainNormal.scale(flip * (int) (currentOffset / 2.0))); + + if (!isDiagonalTrack) { + toPlaceOn.add(new BlockPos(targetVec)); + continue; + } + + boolean placeRow = currentOffset % 2 == 0 || nextOffset % 2 == 1; + boolean placeSides = currentOffset % 2 == 1 || nextOffset % 2 == 0; + + if (placeSides) { + for (int side : Iterate.positiveAndNegative) { + Vec3 sideOffset = normalizedDirection.scale(side) + .add(mainNormal.normalize() + .scale(flip)) + .scale(.5); + toPlaceOn.add(new BlockPos(targetVec.add(sideOffset))); + } + } + + if (placeRow) { + if (Math.abs(currentOffset % 2) == 1) + targetVec = mainPos.add(mainNormal.scale(flip * (int) ((currentOffset + 1) / 2.0))); + toPlaceOn.add(new BlockPos(targetVec)); + } + + } + + toPlaceOn.forEach(task::put); + } + + public static void paveCurve(PaveTask task, BezierConnection bc, double from, double to) { + Map, Double> yLevels = new HashMap<>(); + Map, Double> tLevels = new HashMap<>(); + + BlockPos tePosition = bc.tePositions.getFirst(); + double radius = -task.getHorizontalInterval() + .getFirst(); + double r1 = radius - .575; + double r2 = radius + .575; + + double handleLength = bc.getHandleLength(); + Vec3 start = bc.starts.getFirst() + .subtract(Vec3.atLowerCornerOf(tePosition)) + .add(0, 3 / 16f, 0); + Vec3 end = bc.starts.getSecond() + .subtract(Vec3.atLowerCornerOf(tePosition)) + .add(0, 3 / 16f, 0); + Vec3 startHandle = bc.axes.getFirst() + .scale(handleLength) + .add(start); + Vec3 endHandle = bc.axes.getSecond() + .scale(handleLength) + .add(end); + Vec3 startNormal = bc.normals.getFirst(); + Vec3 endNormal = bc.normals.getSecond(); + + int segCount = bc.getSegmentCount(); + float[] lut = bc.getStepLUT(); + double localFrom = from / bc.getLength(); + double localTo = to / bc.getLength(); + + for (int i = 0; i < segCount; i++) { + + float t = i == segCount ? 1 : i * lut[i] / segCount; + float t1 = (i + 1) == segCount ? 1 : (i + 1) * lut[(i + 1)] / segCount; + + if (t1 < localFrom) + continue; + if (t > localTo) + continue; + + Vec3 vt = VecHelper.bezier(start, end, startHandle, endHandle, t); + Vec3 vNormal = startNormal.equals(endNormal) ? startNormal : VecHelper.slerp(t, startNormal, endNormal); + Vec3 hNormal = vNormal.cross(VecHelper.bezierDerivative(start, end, startHandle, endHandle, t) + .normalize()) + .normalize(); + vt = vt.add(vNormal.scale(-1.175f)); + + Vec3 vt1 = VecHelper.bezier(start, end, startHandle, endHandle, t1); + Vec3 vNormal1 = startNormal.equals(endNormal) ? startNormal : VecHelper.slerp(t1, startNormal, endNormal); + Vec3 hNormal1 = vNormal1.cross(VecHelper.bezierDerivative(start, end, startHandle, endHandle, t1) + .normalize()) + .normalize(); + vt1 = vt1.add(vNormal1.scale(-1.175f)); + + Vec3 a3 = vt.add(hNormal.scale(r2)); + Vec3 b3 = vt1.add(hNormal1.scale(r2)); + Vec3 c3 = vt1.add(hNormal1.scale(r1)); + Vec3 d3 = vt.add(hNormal.scale(r1)); + + Vec2 a = vec2(a3); + Vec2 b = vec2(b3); + Vec2 c = vec2(c3); + Vec2 d = vec2(d3); + + AABB aabb = new AABB(a3, b3).minmax(new AABB(c3, d3)); + + double y = vt.add(vt1).y / 2f; + for (int scanX = Mth.floor(aabb.minX); scanX <= aabb.maxX; scanX++) { + for (int scanZ = Mth.floor(aabb.minZ); scanZ <= aabb.maxZ; scanZ++) { + + Vec2 p = new Vec2(scanX + .5f, scanZ + .5f); + if (!isInTriangle(a, b, c, p) && !isInTriangle(a, c, d, p)) + continue; + + Pair key = Pair.of(scanX, scanZ); + if (!yLevels.containsKey(key) || yLevels.get(key) > y) { + yLevels.put(key, y); + tLevels.put(key, (t + t1) / 2d); + } + } + } + + } + + // + + for (Entry, Double> entry : yLevels.entrySet()) { + double yValue = entry.getValue(); + int floor = Mth.floor(yValue); + BlockPos targetPos = new BlockPos(entry.getKey() + .getFirst(), floor, + entry.getKey() + .getSecond()).offset(tePosition); + task.put(targetPos.getX(), targetPos.getZ(), targetPos.getY() + (yValue - floor >= .5 ? .5f : 0)); + } + } + + private static Vec2 vec2(Vec3 vec3) { + return new Vec2((float) vec3.x, (float) vec3.z); + } + + private static boolean isInTriangle(Vec2 a, Vec2 b, Vec2 c, Vec2 p) { + float pcx = p.x - c.x; + float pcy = p.y - c.y; + float cbx = c.x - b.x; + float bcy = b.y - c.y; + float d = bcy * (a.x - c.x) + cbx * (a.y - c.y); + float s = bcy * pcx + cbx * pcy; + float t = (c.y - a.y) * pcx + (a.x - c.x) * pcy; + return d < 0 ? s <= 0 && t <= 0 && s + t >= d : s >= 0 && t >= 0 && s + t <= d; + } + + public static double lineToPointDiff2d(Vec3 l1, Vec3 l2, Vec3 p) { + return Math.abs((l2.x - l1.x) * (l1.z - p.z) - (l1.x - p.x) * (l2.z - l1.z)); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/SeatBlock.java b/src/main/java/com/simibubi/create/content/contraptions/actors/seat/SeatBlock.java similarity index 95% rename from src/main/java/com/simibubi/create/content/contraptions/components/actors/SeatBlock.java rename to src/main/java/com/simibubi/create/content/contraptions/actors/seat/SeatBlock.java index a22aa3f3b..40ba7291c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/SeatBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/seat/SeatBlock.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.actors; +package com.simibubi.create.content.contraptions.actors.seat; import java.util.List; @@ -38,6 +38,7 @@ import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.EntityCollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; @ParametersAreNonnullByDefault @@ -116,7 +117,9 @@ public class SeatBlock extends Block implements ProperWaterloggedBlock { @Override public VoxelShape getCollisionShape(BlockState p_220071_1_, BlockGetter p_220071_2_, BlockPos p_220071_3_, - CollisionContext p_220071_4_) { + CollisionContext ctx) { + if (ctx instanceof EntityCollisionContext ecc && ecc.getEntity() instanceof Player) + return AllShapes.SEAT_COLLISION_PLAYERS; return AllShapes.SEAT_COLLISION; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/SeatEntity.java b/src/main/java/com/simibubi/create/content/contraptions/actors/seat/SeatEntity.java similarity index 98% rename from src/main/java/com/simibubi/create/content/contraptions/components/actors/SeatEntity.java rename to src/main/java/com/simibubi/create/content/contraptions/actors/seat/SeatEntity.java index 2b8f7dda0..d7cd7df0d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/SeatEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/seat/SeatEntity.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.actors; +package com.simibubi.create.content.contraptions.actors.seat; import com.simibubi.create.AllEntityTypes; diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/seat/SeatInteractionBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/actors/seat/SeatInteractionBehaviour.java new file mode 100644 index 000000000..522d0a9b2 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/seat/SeatInteractionBehaviour.java @@ -0,0 +1,32 @@ +package com.simibubi.create.content.contraptions.actors.seat; + +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.contraptions.behaviour.MovingInteractionBehaviour; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; + +public class SeatInteractionBehaviour extends MovingInteractionBehaviour { + + @Override + public boolean handlePlayerInteraction(Player player, InteractionHand activeHand, BlockPos localPos, + AbstractContraptionEntity contraptionEntity) { + return false; + } + + @Override + public void handleEntityCollision(Entity entity, BlockPos localPos, AbstractContraptionEntity contraptionEntity) { + Contraption contraption = contraptionEntity.getContraption(); + int index = contraption.getSeats() + .indexOf(localPos); + if (index == -1) + return; + if (!SeatBlock.canBePickedUp(entity)) + return; + contraptionEntity.addSittingPassenger(entity, index); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/SeatMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/actors/seat/SeatMovementBehaviour.java similarity index 84% rename from src/main/java/com/simibubi/create/content/contraptions/components/actors/SeatMovementBehaviour.java rename to src/main/java/com/simibubi/create/content/contraptions/actors/seat/SeatMovementBehaviour.java index 5c5082874..f1a26404b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/SeatMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/seat/SeatMovementBehaviour.java @@ -1,11 +1,11 @@ -package com.simibubi.create.content.contraptions.components.actors; +package com.simibubi.create.content.contraptions.actors.seat; import java.util.Map; import java.util.UUID; -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.core.BlockPos; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsBlock.java b/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsBlock.java similarity index 90% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsBlock.java rename to src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsBlock.java index 9eae0dba5..e299b3616 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsBlock.java @@ -1,8 +1,8 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls; +package com.simibubi.create.content.contraptions.actors.trainControls; import com.simibubi.create.AllShapes; -import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionWorld; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; +import com.simibubi.create.content.contraptions.ContraptionWorld; +import com.simibubi.create.content.equipment.wrench.IWrenchable; import com.simibubi.create.foundation.block.ProperWaterloggedBlock; import net.minecraft.core.BlockPos; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsHandler.java b/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsHandler.java similarity index 79% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsHandler.java rename to src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsHandler.java index 3017f10d3..d3a1b1919 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsHandler.java @@ -1,15 +1,16 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls; +package com.simibubi.create.content.contraptions.actors.trainControls; import java.lang.ref.WeakReference; import java.util.Collection; import java.util.HashSet; import java.util.Vector; +import org.jetbrains.annotations.Nullable; import org.lwjgl.glfw.GLFW; import com.mojang.blaze3d.platform.InputConstants; -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; -import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.AllPackets; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; import com.simibubi.create.foundation.utility.ControlsUtil; import com.simibubi.create.foundation.utility.Lang; @@ -23,10 +24,10 @@ public class ControlsHandler { public static Collection currentlyPressed = new HashSet<>(); public static int PACKET_RATE = 5; - static int packetCooldown; + private static int packetCooldown; - static WeakReference entityRef = new WeakReference<>(null); - static BlockPos controlsPos; + private static WeakReference entityRef = new WeakReference<>(null); + private static BlockPos controlsPos; public static void levelUnloaded(LevelAccessor level) { packetCooldown = 0; @@ -49,7 +50,7 @@ public class ControlsHandler { AbstractContraptionEntity abstractContraptionEntity = entityRef.get(); if (!currentlyPressed.isEmpty() && abstractContraptionEntity != null) - AllPackets.channel.sendToServer(new ControlsInputPacket(currentlyPressed, false, + AllPackets.getChannel().sendToServer(new ControlsInputPacket(currentlyPressed, false, abstractContraptionEntity.getId(), controlsPos, false)); packetCooldown = 0; @@ -73,7 +74,7 @@ public class ControlsHandler { .getWindow(), GLFW.GLFW_KEY_ESCAPE)) { BlockPos pos = controlsPos; stopControlling(); - AllPackets.channel + AllPackets.getChannel() .sendToServer(new ControlsInputPacket(currentlyPressed, false, entity.getId(), pos, true)); return; } @@ -92,14 +93,14 @@ public class ControlsHandler { // Released Keys if (!releasedKeys.isEmpty()) { - AllPackets.channel + AllPackets.getChannel() .sendToServer(new ControlsInputPacket(releasedKeys, false, entity.getId(), controlsPos, false)); // AllSoundEvents.CONTROLLER_CLICK.playAt(player.level, player.blockPosition(), 1f, .5f, true); } // Newly Pressed Keys if (!newKeys.isEmpty()) { - AllPackets.channel.sendToServer(new ControlsInputPacket(newKeys, true, entity.getId(), controlsPos, false)); + AllPackets.getChannel().sendToServer(new ControlsInputPacket(newKeys, true, entity.getId(), controlsPos, false)); packetCooldown = PACKET_RATE; // AllSoundEvents.CONTROLLER_CLICK.playAt(player.level, player.blockPosition(), 1f, .75f, true); } @@ -107,7 +108,7 @@ public class ControlsHandler { // Keepalive Pressed Keys if (packetCooldown == 0) { // if (!pressedKeys.isEmpty()) { - AllPackets.channel + AllPackets.getChannel() .sendToServer(new ControlsInputPacket(pressedKeys, true, entity.getId(), controlsPos, false)); packetCooldown = PACKET_RATE; // } @@ -117,4 +118,14 @@ public class ControlsHandler { controls.forEach(kb -> kb.setDown(false)); } + @Nullable + public static AbstractContraptionEntity getContraption() { + return entityRef.get(); + } + + @Nullable + public static BlockPos getControlsPos() { + return controlsPos; + } + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsInputPacket.java b/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsInputPacket.java similarity index 84% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsInputPacket.java rename to src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsInputPacket.java index e1800777b..485360536 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsInputPacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsInputPacket.java @@ -1,11 +1,10 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls; +package com.simibubi.create.content.contraptions.actors.trainControls; import java.util.ArrayList; import java.util.Collection; import java.util.UUID; -import java.util.function.Supplier; -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; import com.simibubi.create.foundation.networking.SimplePacketBase; import net.minecraft.core.BlockPos; @@ -55,10 +54,9 @@ public class ControlsInputPacket extends SimplePacketBase { } @Override - public void handle(Supplier context) { - Context ctx = context.get(); - ctx.enqueueWork(() -> { - ServerPlayer player = ctx.getSender(); + public boolean handle(Context context) { + context.enqueueWork(() -> { + ServerPlayer player = context.getSender(); Level world = player.getCommandSenderWorld(); UUID uniqueID = player.getUUID(); @@ -77,7 +75,7 @@ public class ControlsInputPacket extends SimplePacketBase { .closerThan(player.position(), 16)) ControlsServerHandler.receivePressed(world, ace, controlsPos, uniqueID, activatedButtons, press); }); - ctx.setPacketHandled(true); + return true; } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsInteractionBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsInteractionBehaviour.java similarity index 79% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsInteractionBehaviour.java rename to src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsInteractionBehaviour.java index d64f24d1a..726eb424a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsInteractionBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsInteractionBehaviour.java @@ -1,11 +1,11 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls; +package com.simibubi.create.content.contraptions.actors.trainControls; import java.util.UUID; import com.google.common.base.Objects; import com.simibubi.create.AllItems; -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.MovingInteractionBehaviour; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.behaviour.MovingInteractionBehaviour; import net.minecraft.core.BlockPos; import net.minecraft.world.InteractionHand; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsMovementBehaviour.java similarity index 80% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsMovementBehaviour.java rename to src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsMovementBehaviour.java index abff6a032..895a6979c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsMovementBehaviour.java @@ -1,19 +1,20 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls; +package com.simibubi.create.content.contraptions.actors.trainControls; import java.util.Collection; import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; -import com.simibubi.create.content.logistics.trains.entity.CarriageContraptionEntity; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.contraptions.render.ContraptionMatrices; +import com.simibubi.create.content.trains.entity.CarriageContraptionEntity; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.animation.LerpedFloat; import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.core.Direction; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -27,6 +28,11 @@ public class ControlsMovementBehaviour implements MovementBehaviour { LerpedFloat equipAnimation = LerpedFloat.linear(); } + @Override + public ItemStack canBeDisabledVia(MovementContext context) { + return null; + } + @Override public void stopMoving(MovementContext context) { context.contraption.entity.stopControlling(context.localPos); @@ -66,8 +72,8 @@ public class ControlsMovementBehaviour implements MovementBehaviour { inverted = !info.state.getValue(ControlsBlock.FACING) .equals(initialOrientation); - if (ControlsHandler.entityRef.get() == entity && ControlsHandler.controlsPos != null - && ControlsHandler.controlsPos.equals(context.localPos)) { + if (ControlsHandler.getContraption() == entity && ControlsHandler.getControlsPos() != null + && ControlsHandler.getControlsPos().equals(context.localPos)) { Collection pressed = ControlsHandler.currentlyPressed; angles.equipAnimation.chase(1, .2f, Chaser.EXP); angles.steering.chase((pressed.contains(3) ? 1 : 0) + (pressed.contains(2) ? -1 : 0), 0.2f, Chaser.EXP); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsRenderer.java similarity index 78% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsRenderer.java rename to src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsRenderer.java index 6bbfe9b0a..b4c71c2de 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsRenderer.java @@ -1,12 +1,12 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls; +package com.simibubi.create.content.contraptions.actors.trainControls; import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.contraptions.render.ContraptionMatrices; +import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher; import com.simibubi.create.foundation.render.CachedBufferer; import com.simibubi.create.foundation.render.SuperByteBuffer; import com.simibubi.create.foundation.utility.AngleHelper; @@ -25,7 +25,7 @@ public class ControlsRenderer { BlockState state = context.state; Direction facing = state.getValue(ControlsBlock.FACING); - SuperByteBuffer cover = CachedBufferer.partial(AllBlockPartials.TRAIN_CONTROLS_COVER, state); + SuperByteBuffer cover = CachedBufferer.partial(AllPartialModels.TRAIN_CONTROLS_COVER, state); float hAngle = 180 + AngleHelper.horizontalAngle(facing); PoseStack ms = matrices.getModel(); cover.transform(ms) @@ -39,7 +39,7 @@ public class ControlsRenderer { for (boolean first : Iterate.trueAndFalse) { float vAngle = (float) Mth.clamp(first ? firstLever * 70 - 25 : secondLever * 15, -45, 45); - SuperByteBuffer lever = CachedBufferer.partial(AllBlockPartials.TRAIN_CONTROLS_LEVER, state); + SuperByteBuffer lever = CachedBufferer.partial(AllPartialModels.TRAIN_CONTROLS_LEVER, state); ms.pushPose(); TransformStack.cast(ms) .centre() diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsServerHandler.java b/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsServerHandler.java similarity index 94% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsServerHandler.java rename to src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsServerHandler.java index f3d78b7c2..f3ef536d5 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsServerHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsServerHandler.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls; +package com.simibubi.create.content.contraptions.actors.trainControls; import java.util.ArrayList; import java.util.Collection; @@ -8,7 +8,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.UUID; -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; import com.simibubi.create.foundation.utility.IntAttached; import com.simibubi.create.foundation.utility.WorldAttached; diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsStopControllingPacket.java b/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsStopControllingPacket.java new file mode 100644 index 000000000..243407149 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/trainControls/ControlsStopControllingPacket.java @@ -0,0 +1,23 @@ +package com.simibubi.create.content.contraptions.actors.trainControls; + +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.network.NetworkEvent.Context; + +public class ControlsStopControllingPacket extends SimplePacketBase { + + public ControlsStopControllingPacket() {} + + public ControlsStopControllingPacket(FriendlyByteBuf buffer) {} + + @Override + public void write(FriendlyByteBuf buffer) {} + + @Override + public boolean handle(Context context) { + context.enqueueWork(ControlsHandler::stopControlling); + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/BackHalfShaftInstance.java b/src/main/java/com/simibubi/create/content/contraptions/base/BackHalfShaftInstance.java deleted file mode 100644 index 8181db747..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/base/BackHalfShaftInstance.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.simibubi.create.content.contraptions.base; - -import com.jozufozu.flywheel.api.MaterialManager; - -import net.minecraft.core.Direction; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; - -public class BackHalfShaftInstance extends HalfShaftInstance { - public BackHalfShaftInstance(MaterialManager modelManager, KineticTileEntity tile) { - super(modelManager, tile); - } - - @Override - protected Direction getShaftDirection() { - return blockState.getValue(BlockStateProperties.FACING).getOpposite(); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/CutoutRotatingInstance.java b/src/main/java/com/simibubi/create/content/contraptions/base/CutoutRotatingInstance.java deleted file mode 100644 index 3c625fa2a..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/base/CutoutRotatingInstance.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.simibubi.create.content.contraptions.base; - -import com.jozufozu.flywheel.api.Material; -import com.jozufozu.flywheel.api.MaterialManager; -import com.simibubi.create.content.contraptions.base.flwdata.RotatingData; -import com.simibubi.create.foundation.render.AllMaterialSpecs; - -public class CutoutRotatingInstance extends SingleRotatingInstance { - public CutoutRotatingInstance(MaterialManager modelManager, KineticTileEntity tile) { - super(modelManager, tile); - } - - protected Material getRotatingMaterial() { - return materialManager.defaultCutout() - .material(AllMaterialSpecs.ROTATING); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/GeneratingKineticTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/base/GeneratingKineticTileEntity.java deleted file mode 100644 index 4236d8ae0..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/base/GeneratingKineticTileEntity.java +++ /dev/null @@ -1,171 +0,0 @@ -package com.simibubi.create.content.contraptions.base; - -import java.util.List; - -import com.simibubi.create.content.contraptions.KineticNetwork; -import com.simibubi.create.content.contraptions.base.IRotate.SpeedLevel; -import com.simibubi.create.content.contraptions.base.IRotate.StressImpact; -import com.simibubi.create.foundation.utility.Lang; - -import net.minecraft.ChatFormatting; -import net.minecraft.core.BlockPos; -import net.minecraft.network.chat.Component; -import net.minecraft.util.Mth; -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 GeneratingKineticTileEntity extends KineticTileEntity { - - public boolean reActivateSource; - - public GeneratingKineticTileEntity(BlockEntityType typeIn, BlockPos pos, BlockState state) { - super(typeIn, pos, state); - } - - protected void notifyStressCapacityChange(float capacity) { - getOrCreateNetwork().updateCapacityFor(this, capacity); - } - - @Override - public void removeSource() { - if (hasSource() && isSource()) - reActivateSource = true; - super.removeSource(); - } - - @Override - public void setSource(BlockPos source) { - super.setSource(source); - BlockEntity tileEntity = level.getBlockEntity(source); - if (!(tileEntity instanceof KineticTileEntity)) - return; - KineticTileEntity sourceTe = (KineticTileEntity) tileEntity; - if (reActivateSource && Math.abs(sourceTe.getSpeed()) >= Math.abs(getGeneratedSpeed())) - reActivateSource = false; - } - - @Override - public void tick() { - super.tick(); - if (reActivateSource) { - updateGeneratedRotation(); - reActivateSource = false; - } - } - - @Override - public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { - boolean added = super.addToGoggleTooltip(tooltip, isPlayerSneaking); - if (!StressImpact.isEnabled()) - return added; - - float stressBase = calculateAddedStressCapacity(); - if (Mth.equal(stressBase, 0)) - return added; - - Lang.translate("gui.goggles.generator_stats") - .forGoggles(tooltip); - Lang.translate("tooltip.capacityProvided") - .style(ChatFormatting.GRAY) - .forGoggles(tooltip); - - float speed = getTheoreticalSpeed(); - if (speed != getGeneratedSpeed() && speed != 0) - stressBase *= getGeneratedSpeed() / speed; - speed = Math.abs(speed); - - float stressTotal = stressBase * speed; - - Lang.number(stressTotal) - .translate("generic.unit.stress") - .style(ChatFormatting.AQUA) - .space() - .add(Lang.translate("gui.goggles.at_current_speed") - .style(ChatFormatting.DARK_GRAY)) - .forGoggles(tooltip, 1); - - return true; - } - - public void updateGeneratedRotation() { - float speed = getGeneratedSpeed(); - float prevSpeed = this.speed; - - if (level == null || level.isClientSide) - return; - - if (prevSpeed != speed) { - if (!hasSource()) { - SpeedLevel levelBefore = SpeedLevel.of(this.speed); - SpeedLevel levelafter = SpeedLevel.of(speed); - if (levelBefore != levelafter) - effects.queueRotationIndicators(); - } - - applyNewSpeed(prevSpeed, speed); - } - - if (hasNetwork() && speed != 0) { - KineticNetwork network = getOrCreateNetwork(); - notifyStressCapacityChange(calculateAddedStressCapacity()); - getOrCreateNetwork().updateStressFor(this, calculateStressApplied()); - network.updateStress(); - } - - onSpeedChanged(prevSpeed); - sendData(); - } - - public void applyNewSpeed(float prevSpeed, float speed) { - - // Speed changed to 0 - if (speed == 0) { - if (hasSource()) { - notifyStressCapacityChange(0); - getOrCreateNetwork().updateStressFor(this, calculateStressApplied()); - return; - } - detachKinetics(); - setSpeed(0); - setNetwork(null); - return; - } - - // Now turning - create a new Network - if (prevSpeed == 0) { - setSpeed(speed); - setNetwork(createNetworkId()); - attachKinetics(); - return; - } - - // Change speed when overpowered by other generator - if (hasSource()) { - - // Staying below Overpowered speed - if (Math.abs(prevSpeed) >= Math.abs(speed)) { - if (Math.signum(prevSpeed) != Math.signum(speed)) - level.destroyBlock(worldPosition, true); - return; - } - - // Faster than attached network -> become the new source - detachKinetics(); - setSpeed(speed); - source = null; - setNetwork(createNetworkId()); - attachKinetics(); - return; - } - - // Reapply source - detachKinetics(); - setSpeed(speed); - attachKinetics(); - } - - public Long createNetworkId() { - return worldPosition.asLong(); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/HalfShaftInstance.java b/src/main/java/com/simibubi/create/content/contraptions/base/HalfShaftInstance.java deleted file mode 100644 index 6ddaf3acf..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/base/HalfShaftInstance.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.simibubi.create.content.contraptions.base; - -import com.jozufozu.flywheel.api.Instancer; -import com.jozufozu.flywheel.api.MaterialManager; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.flwdata.RotatingData; - -import net.minecraft.core.Direction; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; - -public class HalfShaftInstance extends SingleRotatingInstance { - public HalfShaftInstance(MaterialManager modelManager, KineticTileEntity tile) { - super(modelManager, tile); - } - - @Override - protected Instancer getModel() { - Direction dir = getShaftDirection(); - return getRotatingMaterial().getModel(AllBlockPartials.SHAFT_HALF, blockState, dir); - } - - protected Direction getShaftDirection() { - return blockState.getValue(BlockStateProperties.FACING); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/HorizontalHalfShaftInstance.java b/src/main/java/com/simibubi/create/content/contraptions/base/HorizontalHalfShaftInstance.java deleted file mode 100644 index 275adabda..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/base/HorizontalHalfShaftInstance.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.simibubi.create.content.contraptions.base; - -import com.jozufozu.flywheel.api.MaterialManager; - -import net.minecraft.core.Direction; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; - -public class HorizontalHalfShaftInstance extends HalfShaftInstance { - - public HorizontalHalfShaftInstance(MaterialManager modelManager, KineticTileEntity tile) { - super(modelManager, tile); - } - - @Override - protected Direction getShaftDirection() { - return blockState.getValue(BlockStateProperties.HORIZONTAL_FACING).getOpposite(); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/KineticBlock.java b/src/main/java/com/simibubi/create/content/contraptions/base/KineticBlock.java deleted file mode 100644 index fcecf28d0..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/base/KineticBlock.java +++ /dev/null @@ -1,107 +0,0 @@ -package com.simibubi.create.content.contraptions.base; - -import com.simibubi.create.foundation.advancement.AdvancementBehaviour; -import com.simibubi.create.foundation.block.ITE; -import com.simibubi.create.foundation.item.ItemDescription.Palette; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; - -public abstract class KineticBlock extends Block implements IRotate { - - protected static final Palette color = Palette.Red; - - public KineticBlock(Properties properties) { - super(properties); - } - - @Override - public void onPlace(BlockState state, Level worldIn, BlockPos pos, BlockState oldState, boolean isMoving) { - // onBlockAdded is useless for init, as sometimes the TE gets re-instantiated - - // however, if a block change occurs that does not change kinetic connections, - // we can prevent a major re-propagation here - - BlockEntity tileEntity = worldIn.getBlockEntity(pos); - if (tileEntity instanceof KineticTileEntity) { - KineticTileEntity kineticTileEntity = (KineticTileEntity) tileEntity; - kineticTileEntity.preventSpeedUpdate = 0; - - if (oldState.getBlock() != state.getBlock()) - return; - if (state.hasBlockEntity() != oldState.hasBlockEntity()) - return; - if (!areStatesKineticallyEquivalent(oldState, state)) - return; - - kineticTileEntity.preventSpeedUpdate = 2; - } - } - - @Override - public void onRemove(BlockState pState, Level pLevel, BlockPos pPos, BlockState pNewState, boolean pIsMoving) { - ITE.onRemove(pState, pLevel, pPos, pNewState); - } - - @Override - public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) { - return false; - } - - protected boolean areStatesKineticallyEquivalent(BlockState oldState, BlockState newState) { - if (oldState.getBlock() != newState.getBlock()) - return false; - return getRotationAxis(newState) == getRotationAxis(oldState); - } - - @Override - public void updateIndirectNeighbourShapes(BlockState stateIn, LevelAccessor worldIn, BlockPos pos, int flags, - int count) { - if (worldIn.isClientSide()) - return; - - BlockEntity tileEntity = worldIn.getBlockEntity(pos); - if (!(tileEntity instanceof KineticTileEntity)) - return; - KineticTileEntity kte = (KineticTileEntity) tileEntity; - - if (kte.preventSpeedUpdate > 0) - return; - - // Remove previous information when block is added - kte.warnOfMovement(); - kte.clearKineticInformation(); - kte.updateSpeed = true; - } - - @Override - public void setPlacedBy(Level worldIn, BlockPos pos, BlockState state, LivingEntity placer, ItemStack stack) { - AdvancementBehaviour.setPlacedBy(worldIn, pos, placer); - if (worldIn.isClientSide) - return; - - BlockEntity tileEntity = worldIn.getBlockEntity(pos); - if (!(tileEntity instanceof KineticTileEntity)) - return; - - KineticTileEntity kte = (KineticTileEntity) tileEntity; - kte.effects.queueRotationIndicators(); - } - - public float getParticleTargetRadius() { - return .65f; - } - - public float getParticleInitialRadius() { - return .75f; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntity.java deleted file mode 100644 index 548e80d3e..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntity.java +++ /dev/null @@ -1,595 +0,0 @@ -package com.simibubi.create.content.contraptions.base; - -import static net.minecraft.ChatFormatting.GOLD; -import static net.minecraft.ChatFormatting.GRAY; - -import java.util.List; - -import javax.annotation.Nullable; - -import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; -import com.simibubi.create.Create; -import com.simibubi.create.content.contraptions.KineticNetwork; -import com.simibubi.create.content.contraptions.RotationPropagator; -import com.simibubi.create.content.contraptions.base.IRotate.SpeedLevel; -import com.simibubi.create.content.contraptions.base.IRotate.StressImpact; -import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation; -import com.simibubi.create.content.contraptions.goggles.IHaveHoveringInformation; -import com.simibubi.create.content.contraptions.relays.elementary.ICogWheel; -import com.simibubi.create.content.contraptions.relays.gearbox.GearboxBlock; -import com.simibubi.create.foundation.block.BlockStressValues; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.item.TooltipHelper; -import com.simibubi.create.foundation.sound.SoundScapes; -import com.simibubi.create.foundation.sound.SoundScapes.AmbienceGroup; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.utility.Lang; - -import net.minecraft.ChatFormatting; -import net.minecraft.client.resources.language.I18n; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.core.Direction.AxisDirection; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtUtils; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.util.Mth; -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.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.fml.DistExecutor; - -public class KineticTileEntity extends SmartTileEntity implements IHaveGoggleInformation, IHaveHoveringInformation { - - public @Nullable Long network; - public @Nullable BlockPos source; - public boolean networkDirty; - public boolean updateSpeed; - public int preventSpeedUpdate; - - protected KineticEffectHandler effects; - protected float speed; - protected float capacity; - protected float stress; - protected boolean overStressed; - protected boolean wasMoved; - - private int flickerTally; - private int networkSize; - private int validationCountdown; - protected float lastStressApplied; - protected float lastCapacityProvided; - - public KineticTileEntity(BlockEntityType typeIn, BlockPos pos, BlockState state) { - super(typeIn, pos, state); - effects = new KineticEffectHandler(this); - updateSpeed = true; - } - - @Override - public void initialize() { - if (hasNetwork() && !level.isClientSide) { - KineticNetwork network = getOrCreateNetwork(); - if (!network.initialized) - network.initFromTE(capacity, stress, networkSize); - network.addSilently(this, lastCapacityProvided, lastStressApplied); - } - - super.initialize(); - } - - @Override - public void tick() { - if (!level.isClientSide && needsSpeedUpdate()) - attachKinetics(); - - super.tick(); - effects.tick(); - - preventSpeedUpdate = 0; - - if (level.isClientSide) { - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> this.tickAudio()); - return; - } - - if (validationCountdown-- <= 0) { - validationCountdown = AllConfigs.SERVER.kinetics.kineticValidationFrequency.get(); - validateKinetics(); - } - - if (getFlickerScore() > 0) - flickerTally = getFlickerScore() - 1; - - if (networkDirty) { - if (hasNetwork()) - getOrCreateNetwork().updateNetwork(); - networkDirty = false; - } - } - - private void validateKinetics() { - if (hasSource()) { - if (!hasNetwork()) { - removeSource(); - return; - } - - if (!level.isLoaded(source)) - return; - - BlockEntity tileEntity = level.getBlockEntity(source); - KineticTileEntity sourceTe = - tileEntity instanceof KineticTileEntity ? (KineticTileEntity) tileEntity : null; - if (sourceTe == null || sourceTe.speed == 0) { - removeSource(); - detachKinetics(); - return; - } - - return; - } - - if (speed != 0) { - if (getGeneratedSpeed() == 0) - speed = 0; - } - } - - public void updateFromNetwork(float maxStress, float currentStress, int networkSize) { - networkDirty = false; - this.capacity = maxStress; - this.stress = currentStress; - this.networkSize = networkSize; - boolean overStressed = maxStress < currentStress && StressImpact.isEnabled(); - setChanged(); - - if (overStressed != this.overStressed) { - float prevSpeed = getSpeed(); - this.overStressed = overStressed; - onSpeedChanged(prevSpeed); - sendData(); - } - } - - protected Block getStressConfigKey() { - return getBlockState().getBlock(); - } - - public float calculateStressApplied() { - float impact = (float) BlockStressValues.getImpact(getStressConfigKey()); - this.lastStressApplied = impact; - return impact; - } - - public float calculateAddedStressCapacity() { - float capacity = (float) BlockStressValues.getCapacity(getStressConfigKey()); - this.lastCapacityProvided = capacity; - return capacity; - } - - public void onSpeedChanged(float previousSpeed) { - boolean fromOrToZero = (previousSpeed == 0) != (getSpeed() == 0); - boolean directionSwap = !fromOrToZero && Math.signum(previousSpeed) != Math.signum(getSpeed()); - if (fromOrToZero || directionSwap) - flickerTally = getFlickerScore() + 5; - setChanged(); - } - - @Override - public void remove() { - if (!level.isClientSide) { - if (hasNetwork()) - getOrCreateNetwork().remove(this); - detachKinetics(); - } - super.remove(); - } - - @Override - protected void write(CompoundTag compound, boolean clientPacket) { - compound.putFloat("Speed", speed); - - if (needsSpeedUpdate()) - compound.putBoolean("NeedsSpeedUpdate", true); - - if (hasSource()) - compound.put("Source", NbtUtils.writeBlockPos(source)); - - if (hasNetwork()) { - CompoundTag networkTag = new CompoundTag(); - networkTag.putLong("Id", this.network); - networkTag.putFloat("Stress", stress); - networkTag.putFloat("Capacity", capacity); - networkTag.putInt("Size", networkSize); - - if (lastStressApplied != 0) - networkTag.putFloat("AddedStress", lastStressApplied); - if (lastCapacityProvided != 0) - networkTag.putFloat("AddedCapacity", lastCapacityProvided); - - compound.put("Network", networkTag); - } - - super.write(compound, clientPacket); - } - - public boolean needsSpeedUpdate() { - return updateSpeed; - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - boolean overStressedBefore = overStressed; - clearKineticInformation(); - - // DO NOT READ kinetic information when placed after movement - if (wasMoved) { - super.read(compound, clientPacket); - return; - } - - speed = compound.getFloat("Speed"); - - if (compound.contains("Source")) - source = NbtUtils.readBlockPos(compound.getCompound("Source")); - - if (compound.contains("Network")) { - CompoundTag networkTag = compound.getCompound("Network"); - network = networkTag.getLong("Id"); - stress = networkTag.getFloat("Stress"); - capacity = networkTag.getFloat("Capacity"); - networkSize = networkTag.getInt("Size"); - lastStressApplied = networkTag.getFloat("AddedStress"); - lastCapacityProvided = networkTag.getFloat("AddedCapacity"); - overStressed = capacity < stress && StressImpact.isEnabled(); - } - - super.read(compound, clientPacket); - - if (clientPacket && overStressedBefore != overStressed && speed != 0) - effects.triggerOverStressedEffect(); - - if (clientPacket) - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(this)); - } - - public float getGeneratedSpeed() { - return 0; - } - - public boolean isSource() { - return getGeneratedSpeed() != 0; - } - - public float getSpeed() { - if (overStressed) - return 0; - return getTheoreticalSpeed(); - } - - public float getTheoreticalSpeed() { - return speed; - } - - public void setSpeed(float speed) { - this.speed = speed; - } - - public boolean hasSource() { - return source != null; - } - - public void setSource(BlockPos source) { - this.source = source; - if (level == null || level.isClientSide) - return; - - BlockEntity tileEntity = level.getBlockEntity(source); - if (!(tileEntity instanceof KineticTileEntity)) { - removeSource(); - return; - } - - KineticTileEntity sourceTe = (KineticTileEntity) tileEntity; - setNetwork(sourceTe.network); - } - - public void removeSource() { - float prevSpeed = getSpeed(); - - speed = 0; - source = null; - setNetwork(null); - - onSpeedChanged(prevSpeed); - } - - public void setNetwork(@Nullable Long networkIn) { - if (network == networkIn) - return; - if (network != null) - getOrCreateNetwork().remove(this); - - network = networkIn; - setChanged(); - - if (networkIn == null) - return; - - network = networkIn; - KineticNetwork network = getOrCreateNetwork(); - network.initialized = true; - network.add(this); - } - - public KineticNetwork getOrCreateNetwork() { - return Create.TORQUE_PROPAGATOR.getOrCreateNetworkFor(this); - } - - public boolean hasNetwork() { - return network != null; - } - - public void attachKinetics() { - updateSpeed = false; - RotationPropagator.handleAdded(level, worldPosition, this); - } - - public void detachKinetics() { - RotationPropagator.handleRemoved(level, worldPosition, this); - } - - public boolean isSpeedRequirementFulfilled() { - BlockState state = getBlockState(); - if (!(getBlockState().getBlock() instanceof IRotate)) - return true; - IRotate def = (IRotate) state.getBlock(); - SpeedLevel minimumRequiredSpeedLevel = def.getMinimumRequiredSpeedLevel(); - return Math.abs(getSpeed()) >= minimumRequiredSpeedLevel.getSpeedValue(); - } - - public static void switchToBlockState(Level world, BlockPos pos, BlockState state) { - if (world.isClientSide) - return; - - BlockEntity tileEntityIn = world.getBlockEntity(pos); - BlockState currentState = world.getBlockState(pos); - boolean isKinetic = tileEntityIn instanceof KineticTileEntity; - - if (currentState == state) - return; - if (tileEntityIn == null || !isKinetic) { - world.setBlock(pos, state, 3); - return; - } - - KineticTileEntity tileEntity = (KineticTileEntity) tileEntityIn; - if (state.getBlock() instanceof KineticBlock - && !((KineticBlock) state.getBlock()).areStatesKineticallyEquivalent(currentState, state)) { - if (tileEntity.hasNetwork()) - tileEntity.getOrCreateNetwork() - .remove(tileEntity); - tileEntity.detachKinetics(); - tileEntity.removeSource(); - } - - world.setBlock(pos, state, 3); - } - - @Override - public void addBehaviours(List behaviours) {} - - @Override - public boolean addToTooltip(List tooltip, boolean isPlayerSneaking) { - boolean notFastEnough = !isSpeedRequirementFulfilled() && getSpeed() != 0; - - if (overStressed && AllConfigs.CLIENT.enableOverstressedTooltip.get()) { - Lang.translate("gui.stressometer.overstressed") - .style(GOLD) - .forGoggles(tooltip); - Component hint = Lang.translateDirect("gui.contraptions.network_overstressed"); - List cutString = TooltipHelper.cutTextComponent(hint, GRAY, ChatFormatting.WHITE); - for (int i = 0; i < cutString.size(); i++) - Lang.builder() - .add(cutString.get(i) - .copy()) - .forGoggles(tooltip); - return true; - } - - if (notFastEnough) { - Lang.translate("tooltip.speedRequirement") - .style(GOLD) - .forGoggles(tooltip); - MutableComponent hint = - Lang.translateDirect("gui.contraptions.not_fast_enough", I18n.get(getBlockState().getBlock() - .getDescriptionId())); - List cutString = TooltipHelper.cutTextComponent(hint, GRAY, ChatFormatting.WHITE); - for (int i = 0; i < cutString.size(); i++) - Lang.builder() - .add(cutString.get(i) - .copy()) - .forGoggles(tooltip); - return true; - } - - return false; - } - - @Override - public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { - boolean added = false; - - if (!StressImpact.isEnabled()) - return added; - float stressAtBase = calculateStressApplied(); - if (Mth.equal(stressAtBase, 0)) - return added; - - Lang.translate("gui.goggles.kinetic_stats") - .forGoggles(tooltip); - - addStressImpactStats(tooltip, stressAtBase); - - return true; - - } - - protected void addStressImpactStats(List tooltip, float stressAtBase) { - Lang.translate("tooltip.stressImpact") - .style(GRAY) - .forGoggles(tooltip); - - float stressTotal = stressAtBase * Math.abs(getTheoreticalSpeed()); - - Lang.number(stressTotal) - .translate("generic.unit.stress") - .style(ChatFormatting.AQUA) - .space() - .add(Lang.translate("gui.goggles.at_current_speed") - .style(ChatFormatting.DARK_GRAY)) - .forGoggles(tooltip, 1); - } - - public void clearKineticInformation() { - speed = 0; - source = null; - network = null; - overStressed = false; - stress = 0; - capacity = 0; - lastStressApplied = 0; - lastCapacityProvided = 0; - } - - public void warnOfMovement() { - wasMoved = true; - } - - public int getFlickerScore() { - return flickerTally; - } - - public static float convertToDirection(float axisSpeed, Direction d) { - return d.getAxisDirection() == AxisDirection.POSITIVE ? axisSpeed : -axisSpeed; - } - - public static float convertToLinear(float speed) { - return speed / 512f; - } - - public static float convertToAngular(float speed) { - return speed * 3 / 10f; - } - - public boolean isOverStressed() { - return overStressed; - } - - // Custom Propagation - - /** - * Specify ratio of transferred rotation from this kinetic component to a - * specific other. - * - * @param target other Kinetic TE to transfer to - * @param stateFrom this TE's blockstate - * @param stateTo other TE's blockstate - * @param diff difference in position (to.pos - from.pos) - * @param connectedViaAxes whether these kinetic blocks are connected via mutual - * IRotate.hasShaftTowards() - * @param connectedViaCogs whether these kinetic blocks are connected via mutual - * IRotate.hasIntegratedCogwheel() - * @return factor of rotation speed from this TE to other. 0 if no rotation is - * transferred, or the standard rules apply (integrated shafts/cogs) - */ - public float propagateRotationTo(KineticTileEntity target, BlockState stateFrom, BlockState stateTo, BlockPos diff, - boolean connectedViaAxes, boolean connectedViaCogs) { - return 0; - } - - /** - * Specify additional locations the rotation propagator should look for - * potentially connected components. Neighbour list contains offset positions in - * all 6 directions by default. - * - * @param block - * @param state - * @param neighbours - * @return - */ - public List addPropagationLocations(IRotate block, BlockState state, List neighbours) { - if (!canPropagateDiagonally(block, state)) - return neighbours; - - Axis axis = block.getRotationAxis(state); - BlockPos.betweenClosedStream(new BlockPos(-1, -1, -1), new BlockPos(1, 1, 1)) - .forEach(offset -> { - if (axis.choose(offset.getX(), offset.getY(), offset.getZ()) != 0) - return; - if (offset.distSqr(BlockPos.ZERO) != 2) - return; - neighbours.add(worldPosition.offset(offset)); - }); - return neighbours; - } - - /** - * Specify whether this component can propagate speed to the other in any - * circumstance. Shaft and cogwheel connections are already handled by internal - * logic. Does not have to be specified on both ends, it is assumed that this - * relation is symmetrical. - * - * @param other - * @param state - * @param otherState - * @return true if this and the other component should check their propagation - * factor and are not already connected via integrated cogs or shafts - */ - public boolean isCustomConnection(KineticTileEntity other, BlockState state, BlockState otherState) { - return false; - } - - protected boolean canPropagateDiagonally(IRotate block, BlockState state) { - return ICogWheel.isSmallCog(state); - } - - @Override - public void requestModelDataUpdate() { - super.requestModelDataUpdate(); - if (!this.remove) - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(this)); - } - - @OnlyIn(Dist.CLIENT) - public void tickAudio() { - float componentSpeed = Math.abs(getSpeed()); - if (componentSpeed == 0) - return; - float pitch = Mth.clamp((componentSpeed / 256f) + .45f, .85f, 1f); - - if (isNoisy()) - SoundScapes.play(AmbienceGroup.KINETIC, worldPosition, pitch); - - Block block = getBlockState().getBlock(); - if (ICogWheel.isSmallCog(block) || ICogWheel.isLargeCog(block) || block instanceof GearboxBlock) - SoundScapes.play(AmbienceGroup.COG, worldPosition, pitch); - } - - protected boolean isNoisy() { - return true; - } - - public int getRotationAngleOffset(Axis axis) { - return 0; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntityRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntityRenderer.java deleted file mode 100644 index 9dcd8313e..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntityRenderer.java +++ /dev/null @@ -1,143 +0,0 @@ -package com.simibubi.create.content.contraptions.base; - -import org.apache.commons.lang3.ArrayUtils; - -import com.jozufozu.flywheel.backend.Backend; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.KineticDebugger; -import com.simibubi.create.content.contraptions.relays.elementary.ICogWheel; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.render.SuperByteBufferCache; -import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.Color; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.core.Direction.AxisDirection; -import net.minecraft.util.RandomSource; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraftforge.client.ChunkRenderTypeSet; -import net.minecraftforge.client.model.data.ModelData; - -public class KineticTileEntityRenderer extends SafeTileEntityRenderer { - - public static final SuperByteBufferCache.Compartment KINETIC_TILE = new SuperByteBufferCache.Compartment<>(); - public static boolean rainbowMode = false; - - protected static final RenderType[] REVERSED_CHUNK_BUFFER_LAYERS = RenderType.chunkBufferLayers().toArray(RenderType[]::new); - static { - ArrayUtils.reverse(REVERSED_CHUNK_BUFFER_LAYERS); - } - - public KineticTileEntityRenderer(BlockEntityRendererProvider.Context context) { - } - - @Override - protected void renderSafe(KineticTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - if (Backend.canUseInstancing(te.getLevel())) return; - - BlockState state = getRenderedBlockState(te); - RenderType type = getRenderType(te, state); - if (type != null) - renderRotatingBuffer(te, getRotatedModel(te, state), ms, buffer.getBuffer(type), light); - } - - protected BlockState getRenderedBlockState(KineticTileEntity te) { - return te.getBlockState(); - } - - protected RenderType getRenderType(KineticTileEntity te, BlockState state) { - // TODO: this is not very clean - BakedModel model = Minecraft.getInstance() - .getBlockRenderer().getBlockModel(state); - ChunkRenderTypeSet typeSet = model.getRenderTypes(state, RandomSource.create(42L), ModelData.EMPTY); - for (RenderType type : REVERSED_CHUNK_BUFFER_LAYERS) - if (typeSet.contains(type)) - return type; - return null; - } - - protected SuperByteBuffer getRotatedModel(KineticTileEntity te, BlockState state) { - return CachedBufferer.block(KINETIC_TILE, state); - } - - public static void renderRotatingKineticBlock(KineticTileEntity te, BlockState renderedState, PoseStack ms, - VertexConsumer buffer, int light) { - SuperByteBuffer superByteBuffer = CachedBufferer.block(KINETIC_TILE, renderedState); - renderRotatingBuffer(te, superByteBuffer, ms, buffer, light); - } - - public static void renderRotatingBuffer(KineticTileEntity te, SuperByteBuffer superBuffer, PoseStack ms, - VertexConsumer buffer, int light) { - standardKineticRotationTransform(superBuffer, te, light).renderInto(ms, buffer); - } - - public static float getAngleForTe(KineticTileEntity te, final BlockPos pos, Axis axis) { - float time = AnimationTickHolder.getRenderTime(te.getLevel()); - float offset = getRotationOffsetForPosition(te, pos, axis); - float angle = ((time * te.getSpeed() * 3f / 10 + offset) % 360) / 180 * (float) Math.PI; - return angle; - } - - public static SuperByteBuffer standardKineticRotationTransform(SuperByteBuffer buffer, KineticTileEntity te, - int light) { - final BlockPos pos = te.getBlockPos(); - Axis axis = ((IRotate) te.getBlockState() - .getBlock()).getRotationAxis(te.getBlockState()); - return kineticRotationTransform(buffer, te, axis, getAngleForTe(te, pos, axis), light); - } - - public static SuperByteBuffer kineticRotationTransform(SuperByteBuffer buffer, KineticTileEntity te, Axis axis, - float angle, int light) { - buffer.light(light); - buffer.rotateCentered(Direction.get(AxisDirection.POSITIVE, axis), angle); - - if (KineticDebugger.isActive()) { - rainbowMode = true; - buffer.color(te.hasNetwork() ? Color.generateFromLong(te.network) : Color.WHITE); - } else { - float overStressedEffect = te.effects.overStressedEffect; - if (overStressedEffect != 0) - if (overStressedEffect > 0) - buffer.color(Color.WHITE.mixWith(Color.RED, overStressedEffect)); - else - buffer.color(Color.WHITE.mixWith(Color.SPRING_GREEN, -overStressedEffect)); - else - buffer.color(Color.WHITE); - } - - return buffer; - } - - public static float getRotationOffsetForPosition(KineticTileEntity te, final BlockPos pos, final Axis axis) { - float offset = ICogWheel.isLargeCog(te.getBlockState()) ? 11.25f : 0; - double d = (((axis == Axis.X) ? 0 : pos.getX()) + ((axis == Axis.Y) ? 0 : pos.getY()) - + ((axis == Axis.Z) ? 0 : pos.getZ())) % 2; - if (d == 0) - offset = 22.5f; - return offset + te.getRotationAngleOffset(axis); - } - - public static BlockState shaft(Axis axis) { - return AllBlocks.SHAFT.getDefaultState() - .setValue(BlockStateProperties.AXIS, axis); - } - - public static Axis getRotationAxisOf(KineticTileEntity te) { - return ((IRotate) te.getBlockState() - .getBlock()).getRotationAxis(te.getBlockState()); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileInstance.java b/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileInstance.java deleted file mode 100644 index bcaf4e436..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileInstance.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.simibubi.create.content.contraptions.base; - -import com.jozufozu.flywheel.api.Material; -import com.jozufozu.flywheel.api.MaterialManager; -import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance; -import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.base.flwdata.RotatingData; -import com.simibubi.create.content.contraptions.relays.elementary.ICogWheel; -import com.simibubi.create.content.contraptions.relays.elementary.ShaftBlock; -import com.simibubi.create.foundation.render.AllMaterialSpecs; - -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.world.level.block.state.BlockState; - -public abstract class KineticTileInstance extends BlockEntityInstance { - - protected final Direction.Axis axis; - - public KineticTileInstance(MaterialManager modelManager, T tile) { - super(modelManager, tile); - axis = (blockState.getBlock()instanceof IRotate irotate) ? irotate.getRotationAxis(blockState) : Axis.Y; - } - - protected final void updateRotation(RotatingData instance) { - updateRotation(instance, getRotationAxis(), getTileSpeed()); - } - - protected final void updateRotation(RotatingData instance, Direction.Axis axis) { - updateRotation(instance, axis, getTileSpeed()); - } - - protected final void updateRotation(RotatingData instance, float speed) { - updateRotation(instance, getRotationAxis(), speed); - } - - protected final void updateRotation(RotatingData instance, Direction.Axis axis, float speed) { - instance.setRotationAxis(axis) - .setRotationOffset(getRotationOffset(axis)) - .setRotationalSpeed(speed) - .setColor(blockEntity); - } - - protected final RotatingData setup(RotatingData key) { - return setup(key, getRotationAxis(), getTileSpeed()); - } - - protected final RotatingData setup(RotatingData key, Direction.Axis axis) { - return setup(key, axis, getTileSpeed()); - } - - protected final RotatingData setup(RotatingData key, float speed) { - return setup(key, getRotationAxis(), speed); - } - - protected final RotatingData setup(RotatingData key, Direction.Axis axis, float speed) { - key.setRotationAxis(axis) - .setRotationalSpeed(speed) - .setRotationOffset(getRotationOffset(axis)) - .setColor(blockEntity) - .setPosition(getInstancePosition()); - - return key; - } - - protected float getRotationOffset(final Direction.Axis axis) { - float offset = ICogWheel.isLargeCog(blockState) ? 11.25f : 0; - double d = (((axis == Direction.Axis.X) ? 0 : pos.getX()) + ((axis == Direction.Axis.Y) ? 0 : pos.getY()) - + ((axis == Direction.Axis.Z) ? 0 : pos.getZ())) % 2; - if (d == 0) { - offset = 22.5f; - } - return offset; - } - - protected Direction.Axis getRotationAxis() { - return axis; - } - - protected float getTileSpeed() { - return blockEntity.getSpeed(); - } - - protected BlockState shaft() { - return shaft(getRotationAxis()); - } - - protected Material getRotatingMaterial() { - return materialManager.defaultSolid() - .material(AllMaterialSpecs.ROTATING); - } - - public static BlockState shaft(Direction.Axis axis) { - return AllBlocks.SHAFT.getDefaultState() - .setValue(ShaftBlock.AXIS, axis); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/SingleRotatingInstance.java b/src/main/java/com/simibubi/create/content/contraptions/base/SingleRotatingInstance.java deleted file mode 100644 index d103b26b5..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/base/SingleRotatingInstance.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.simibubi.create.content.contraptions.base; - -import com.jozufozu.flywheel.api.Instancer; -import com.jozufozu.flywheel.api.MaterialManager; -import com.simibubi.create.content.contraptions.base.flwdata.RotatingData; - -import net.minecraft.world.level.block.state.BlockState; - -public class SingleRotatingInstance extends KineticTileInstance { - - protected RotatingData rotatingModel; - - public SingleRotatingInstance(MaterialManager modelManager, KineticTileEntity tile) { - super(modelManager, tile); - } - - @Override - public void init() { - rotatingModel = setup(getModel().createInstance()); - } - - @Override - public void update() { - updateRotation(rotatingModel); - } - - @Override - public void updateLight() { - relight(pos, rotatingModel); - } - - @Override - public void remove() { - rotatingModel.delete(); - } - - protected BlockState getRenderedBlockState() { - return blockState; - } - - protected Instancer getModel() { - return getRotatingMaterial().getModel(getRenderedBlockState()); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/flwdata/package-info.java b/src/main/java/com/simibubi/create/content/contraptions/base/flwdata/package-info.java deleted file mode 100644 index 5eed85946..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/base/flwdata/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault -package com.simibubi.create.content.contraptions.base.flwdata; - -import javax.annotation.ParametersAreNonnullByDefault; - -import net.minecraft.MethodsReturnNonnullByDefault; diff --git a/src/main/java/com/simibubi/create/content/contraptions/bearing/AnchoredLighter.java b/src/main/java/com/simibubi/create/content/contraptions/bearing/AnchoredLighter.java new file mode 100644 index 000000000..43788e223 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/bearing/AnchoredLighter.java @@ -0,0 +1,19 @@ +package com.simibubi.create.content.contraptions.bearing; + +import com.jozufozu.flywheel.util.box.GridAlignedBB; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.contraptions.render.ContraptionLighter; + +public class AnchoredLighter extends ContraptionLighter { + + public AnchoredLighter(Contraption contraption) { + super(contraption); + } + + @Override + public GridAlignedBB getContraptionBounds() { + GridAlignedBB bb = GridAlignedBB.from(contraption.bounds); + bb.translate(contraption.anchor); + return bb; + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingBlock.java b/src/main/java/com/simibubi/create/content/contraptions/bearing/BearingBlock.java similarity index 77% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingBlock.java rename to src/main/java/com/simibubi/create/content/contraptions/bearing/BearingBlock.java index 2f1c210e5..8f52312b7 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/bearing/BearingBlock.java @@ -1,6 +1,6 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.bearing; +package com.simibubi.create.content.contraptions.bearing; -import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock; +import com.simibubi.create.content.kinetics.base.DirectionalKineticBlock; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -36,9 +36,9 @@ public abstract class BearingBlock extends DirectionalKineticBlock { public InteractionResult onWrenched(BlockState state, UseOnContext context) { InteractionResult resultType = super.onWrenched(state, context); if (!context.getLevel().isClientSide && resultType.consumesAction()) { - BlockEntity te = context.getLevel().getBlockEntity(context.getClickedPos()); - if (te instanceof MechanicalBearingTileEntity) { - ((MechanicalBearingTileEntity) te).disassemble(); + BlockEntity be = context.getLevel().getBlockEntity(context.getClickedPos()); + if (be instanceof MechanicalBearingBlockEntity) { + ((MechanicalBearingBlockEntity) be).disassemble(); } } return resultType; diff --git a/src/main/java/com/simibubi/create/content/contraptions/bearing/BearingContraption.java b/src/main/java/com/simibubi/create/content/contraptions/bearing/BearingContraption.java new file mode 100644 index 000000000..2b36c5808 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/bearing/BearingContraption.java @@ -0,0 +1,112 @@ +package com.simibubi.create.content.contraptions.bearing; + +import org.apache.commons.lang3.tuple.Pair; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllTags.AllBlockTags; +import com.simibubi.create.content.contraptions.AssemblyException; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.contraptions.ContraptionType; +import com.simibubi.create.content.contraptions.render.ContraptionLighter; +import com.simibubi.create.content.decoration.copycat.CopycatBlockEntity; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +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.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public class BearingContraption extends Contraption { + + protected int sailBlocks; + protected Direction facing; + + private boolean isWindmill; + + public BearingContraption() {} + + public BearingContraption(boolean isWindmill, Direction facing) { + this.isWindmill = isWindmill; + this.facing = facing; + } + + @Override + public boolean assemble(Level world, BlockPos pos) throws AssemblyException { + BlockPos offset = pos.relative(facing); + if (!searchMovedStructure(world, offset, null)) + return false; + startMoving(world); + expandBoundsAroundAxis(facing.getAxis()); + if (isWindmill && sailBlocks < AllConfigs.server().kinetics.minimumWindmillSails.get()) + throw AssemblyException.notEnoughSails(sailBlocks); + if (blocks.isEmpty()) + return false; + return true; + } + + @Override + public ContraptionType getType() { + return ContraptionType.BEARING; + } + + @Override + protected boolean isAnchoringBlockAt(BlockPos pos) { + return pos.equals(anchor.relative(facing.getOpposite())); + } + + @Override + public void addBlock(BlockPos pos, Pair capture) { + BlockPos localPos = pos.subtract(anchor); + if (!getBlocks().containsKey(localPos) && AllBlockTags.WINDMILL_SAILS.matches(getSailBlock(capture))) + sailBlocks++; + super.addBlock(pos, capture); + } + + private BlockState getSailBlock(Pair capture) { + BlockState state = capture.getKey().state; + if (AllBlocks.COPYCAT_PANEL.has(state) && capture.getRight() instanceof CopycatBlockEntity cbe) + return cbe.getMaterial(); + return state; + } + + @Override + public CompoundTag writeNBT(boolean spawnPacket) { + CompoundTag tag = super.writeNBT(spawnPacket); + tag.putInt("Sails", sailBlocks); + tag.putInt("Facing", facing.get3DDataValue()); + return tag; + } + + @Override + public void readNBT(Level world, CompoundTag tag, boolean spawnData) { + sailBlocks = tag.getInt("Sails"); + facing = Direction.from3DDataValue(tag.getInt("Facing")); + super.readNBT(world, tag, spawnData); + } + + public int getSailBlocks() { + return sailBlocks; + } + + public Direction getFacing() { + return facing; + } + + @Override + public boolean canBeStabilized(Direction facing, BlockPos localPos) { + if (facing.getOpposite() == this.facing && BlockPos.ZERO.equals(localPos)) + return false; + return facing.getAxis() == this.facing.getAxis(); + } + + @OnlyIn(Dist.CLIENT) + @Override + public ContraptionLighter makeLighter() { + return new AnchoredLighter(this); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/bearing/BearingInstance.java b/src/main/java/com/simibubi/create/content/contraptions/bearing/BearingInstance.java new file mode 100644 index 000000000..e79787850 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/bearing/BearingInstance.java @@ -0,0 +1,75 @@ +package com.simibubi.create.content.contraptions.bearing; + +import org.joml.Quaternionf; + +import com.jozufozu.flywheel.api.MaterialManager; +import com.jozufozu.flywheel.api.instance.DynamicInstance; +import com.jozufozu.flywheel.core.PartialModel; +import com.jozufozu.flywheel.core.materials.oriented.OrientedData; +import com.mojang.math.Axis; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.BackHalfShaftInstance; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.AnimationTickHolder; + +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; + +public class BearingInstance extends BackHalfShaftInstance implements DynamicInstance { + final OrientedData topInstance; + + final Axis rotationAxis; + final Quaternionf blockOrientation; + + public BearingInstance(MaterialManager materialManager, B blockEntity) { + super(materialManager, blockEntity); + + Direction facing = blockState.getValue(BlockStateProperties.FACING); + rotationAxis = Axis.of(Direction.get(Direction.AxisDirection.POSITIVE, axis).step()); + + blockOrientation = getBlockStateOrientation(facing); + + PartialModel top = + blockEntity.isWoodenTop() ? AllPartialModels.BEARING_TOP_WOODEN : AllPartialModels.BEARING_TOP; + + topInstance = getOrientedMaterial().getModel(top, blockState).createInstance(); + + topInstance.setPosition(getInstancePosition()).setRotation(blockOrientation); + } + + @Override + public void beginFrame() { + float interpolatedAngle = blockEntity.getInterpolatedAngle(AnimationTickHolder.getPartialTicks() - 1); + Quaternionf rot = rotationAxis.rotationDegrees(interpolatedAngle); + + rot.mul(blockOrientation); + + topInstance.setRotation(rot); + } + + @Override + public void updateLight() { + super.updateLight(); + relight(pos, topInstance); + } + + @Override + public void remove() { + super.remove(); + topInstance.delete(); + } + + static Quaternionf getBlockStateOrientation(Direction facing) { + Quaternionf orientation; + + if (facing.getAxis().isHorizontal()) { + orientation = Axis.YP.rotationDegrees(AngleHelper.horizontalAngle(facing.getOpposite())); + } else { + orientation = new Quaternionf(); + } + + orientation.mul(Axis.XP.rotationDegrees(-90 - AngleHelper.verticalAngle(facing))); + return orientation; + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/bearing/BearingRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/bearing/BearingRenderer.java new file mode 100644 index 000000000..c7a4921c2 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/bearing/BearingRenderer.java @@ -0,0 +1,58 @@ +package com.simibubi.create.content.contraptions.bearing; + +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.core.PartialModel; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.AngleHelper; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; + +public class BearingRenderer extends KineticBlockEntityRenderer { + + public BearingRenderer(BlockEntityRendererProvider.Context context) { + super(context); + } + + @Override + protected void renderSafe(T be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + + if (Backend.canUseInstancing(be.getLevel())) return; + + super.renderSafe(be, partialTicks, ms, buffer, light, overlay); + + final Direction facing = be.getBlockState() + .getValue(BlockStateProperties.FACING); + PartialModel top = + be.isWoodenTop() ? AllPartialModels.BEARING_TOP_WOODEN : AllPartialModels.BEARING_TOP; + SuperByteBuffer superBuffer = CachedBufferer.partial(top, be.getBlockState()); + + float interpolatedAngle = be.getInterpolatedAngle(partialTicks - 1); + kineticRotationTransform(superBuffer, be, facing.getAxis(), (float) (interpolatedAngle / 180 * Math.PI), light); + + if (facing.getAxis() + .isHorizontal()) + superBuffer.rotateCentered(Direction.UP, + AngleHelper.rad(AngleHelper.horizontalAngle(facing.getOpposite()))); + superBuffer.rotateCentered(Direction.EAST, AngleHelper.rad(-90 - AngleHelper.verticalAngle(facing))); + superBuffer.renderInto(ms, buffer.getBuffer(RenderType.solid())); + } + + @Override + protected SuperByteBuffer getRotatedModel(KineticBlockEntity be, BlockState state) { + return CachedBufferer.partialFacing(AllPartialModels.SHAFT_HALF, state, state + .getValue(BearingBlock.FACING) + .getOpposite()); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BlankSailBlockItem.java b/src/main/java/com/simibubi/create/content/contraptions/bearing/BlankSailBlockItem.java similarity index 91% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BlankSailBlockItem.java rename to src/main/java/com/simibubi/create/content/contraptions/bearing/BlankSailBlockItem.java index 49f8ad8e7..b8ef959e9 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BlankSailBlockItem.java +++ b/src/main/java/com/simibubi/create/content/contraptions/bearing/BlankSailBlockItem.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.bearing; +package com.simibubi.create.content.contraptions.bearing; import java.util.Map; diff --git a/src/main/java/com/simibubi/create/content/contraptions/bearing/ClockworkBearingBlock.java b/src/main/java/com/simibubi/create/content/contraptions/bearing/ClockworkBearingBlock.java new file mode 100644 index 000000000..f04c93965 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/bearing/ClockworkBearingBlock.java @@ -0,0 +1,62 @@ +package com.simibubi.create.content.contraptions.bearing; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.foundation.block.IBE; + +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.item.context.UseOnContext; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; + +public class ClockworkBearingBlock extends BearingBlock implements IBE { + + public ClockworkBearingBlock(Properties properties) { + super(properties); + } + + @Override + public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, + Player player, InteractionHand handIn, BlockHitResult hit) { + if (!player.mayBuild()) + return InteractionResult.FAIL; + if (player.isShiftKeyDown()) + return InteractionResult.FAIL; + if (player.getItemInHand(handIn).isEmpty()) { + if (!worldIn.isClientSide) { + withBlockEntityDo(worldIn, pos, be -> { + if (be.running) { + be.disassemble(); + return; + } + be.assembleNextTick = true; + }); + } + return InteractionResult.SUCCESS; + } + return InteractionResult.PASS; + } + + @Override + public Class getBlockEntityClass() { + return ClockworkBearingBlockEntity.class; + } + + @Override + public InteractionResult onWrenched(BlockState state, UseOnContext context) { + InteractionResult resultType = super.onWrenched(state, context); + if (!context.getLevel().isClientSide && resultType.consumesAction()) + withBlockEntityDo(context.getLevel(), context.getClickedPos(), ClockworkBearingBlockEntity::disassemble); + return resultType; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.CLOCKWORK_BEARING.get(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/bearing/ClockworkBearingBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/bearing/ClockworkBearingBlockEntity.java new file mode 100644 index 000000000..9a4786793 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/bearing/ClockworkBearingBlockEntity.java @@ -0,0 +1,431 @@ +package com.simibubi.create.content.contraptions.bearing; + +import java.util.List; + +import org.apache.commons.lang3.tuple.Pair; + +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.AssemblyException; +import com.simibubi.create.content.contraptions.ControlledContraptionEntity; +import com.simibubi.create.content.contraptions.IDisplayAssemblyExceptions; +import com.simibubi.create.content.contraptions.bearing.ClockworkContraption.HandType; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.INamedIconOptions; +import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollOptionBehaviour; +import com.simibubi.create.foundation.gui.AllIcons; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.ServerSpeedProvider; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.Mth; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; + +public class ClockworkBearingBlockEntity extends KineticBlockEntity + implements IBearingBlockEntity, IDisplayAssemblyExceptions { + + protected ControlledContraptionEntity hourHand; + protected ControlledContraptionEntity minuteHand; + protected float hourAngle; + protected float minuteAngle; + protected float clientHourAngleDiff; + protected float clientMinuteAngleDiff; + + protected boolean running; + protected boolean assembleNextTick; + protected AssemblyException lastException; + protected ScrollOptionBehaviour operationMode; + + private float prevForcedAngle; + + public ClockworkBearingBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + setLazyTickRate(3); + } + + @Override + public void addBehaviours(List behaviours) { + super.addBehaviours(behaviours); + operationMode = new ScrollOptionBehaviour<>(ClockHands.class, + Lang.translateDirect("contraptions.clockwork.clock_hands"), this, getMovementModeSlot()); + behaviours.add(operationMode); + registerAwardables(behaviours, AllAdvancements.CLOCKWORK_BEARING); + } + + @Override + public boolean isWoodenTop() { + return false; + } + + @Override + public void tick() { + super.tick(); + + if (level.isClientSide) { + prevForcedAngle = hourAngle; + clientMinuteAngleDiff /= 2; + clientHourAngleDiff /= 2; + } + + if (!level.isClientSide && assembleNextTick) { + assembleNextTick = false; + if (running) { + boolean canDisassemble = true; + if (speed == 0 && (canDisassemble || hourHand == null || hourHand.getContraption() + .getBlocks() + .isEmpty())) { + if (hourHand != null) + hourHand.getContraption() + .stop(level); + if (minuteHand != null) + minuteHand.getContraption() + .stop(level); + disassemble(); + } + return; + } else + assemble(); + return; + } + + if (!running) + return; + + if (!(hourHand != null && hourHand.isStalled())) { + float newAngle = hourAngle + getHourArmSpeed(); + hourAngle = (float) (newAngle % 360); + } + + if (!(minuteHand != null && minuteHand.isStalled())) { + float newAngle = minuteAngle + getMinuteArmSpeed(); + minuteAngle = (float) (newAngle % 360); + } + + applyRotations(); + } + + @Override + public AssemblyException getLastAssemblyException() { + return lastException; + } + + protected void applyRotations() { + BlockState blockState = getBlockState(); + Axis axis = Axis.X; + + if (blockState.hasProperty(BlockStateProperties.FACING)) + axis = blockState.getValue(BlockStateProperties.FACING) + .getAxis(); + + if (hourHand != null) { + hourHand.setAngle(hourAngle); + hourHand.setRotationAxis(axis); + } + if (minuteHand != null) { + minuteHand.setAngle(minuteAngle); + minuteHand.setRotationAxis(axis); + } + } + + @Override + public void lazyTick() { + super.lazyTick(); + if (hourHand != null && !level.isClientSide) + sendData(); + } + + public float getHourArmSpeed() { + float speed = getAngularSpeed() / 2f; + + if (speed != 0) { + ClockHands mode = ClockHands.values()[operationMode.getValue()]; + float hourTarget = mode == ClockHands.HOUR_FIRST ? getHourTarget(false) + : mode == ClockHands.MINUTE_FIRST ? getMinuteTarget() : getHourTarget(true); + float shortestAngleDiff = AngleHelper.getShortestAngleDiff(hourAngle, hourTarget); + if (shortestAngleDiff < 0) { + speed = Math.max(speed, shortestAngleDiff); + } else { + speed = Math.min(-speed, shortestAngleDiff); + } + } + + return speed + clientHourAngleDiff / 3f; + } + + public float getMinuteArmSpeed() { + float speed = getAngularSpeed(); + + if (speed != 0) { + ClockHands mode = ClockHands.values()[operationMode.getValue()]; + float minuteTarget = mode == ClockHands.MINUTE_FIRST ? getHourTarget(false) : getMinuteTarget(); + float shortestAngleDiff = AngleHelper.getShortestAngleDiff(minuteAngle, minuteTarget); + if (shortestAngleDiff < 0) { + speed = Math.max(speed, shortestAngleDiff); + } else { + speed = Math.min(-speed, shortestAngleDiff); + } + } + + return speed + clientMinuteAngleDiff / 3f; + } + + protected float getHourTarget(boolean cycle24) { + boolean isNatural = level.dimensionType() + .natural(); + int dayTime = (int) ((level.getDayTime() * (isNatural ? 1 : 24)) % 24000); + int hours = (dayTime / 1000 + 6) % 24; + int offset = getBlockState().getValue(ClockworkBearingBlock.FACING) + .getAxisDirection() + .getStep(); + float hourTarget = (float) (offset * -360 / (cycle24 ? 24f : 12f) * (hours % (cycle24 ? 24 : 12))); + return hourTarget; + } + + protected float getMinuteTarget() { + boolean isNatural = level.dimensionType() + .natural(); + int dayTime = (int) ((level.getDayTime() * (isNatural ? 1 : 24)) % 24000); + int minutes = (dayTime % 1000) * 60 / 1000; + int offset = getBlockState().getValue(ClockworkBearingBlock.FACING) + .getAxisDirection() + .getStep(); + float minuteTarget = (float) (offset * -360 / 60f * (minutes)); + return minuteTarget; + } + + public float getAngularSpeed() { + float speed = -Math.abs(getSpeed() * 3 / 10f); + if (level.isClientSide) + speed *= ServerSpeedProvider.get(); + return speed; + } + + public void assemble() { + if (!(level.getBlockState(worldPosition) + .getBlock() instanceof ClockworkBearingBlock)) + return; + + Direction direction = getBlockState().getValue(BlockStateProperties.FACING); + + // Collect Construct + Pair contraption; + try { + contraption = ClockworkContraption.assembleClockworkAt(level, worldPosition, direction); + lastException = null; + } catch (AssemblyException e) { + lastException = e; + sendData(); + return; + } + if (contraption == null) + return; + if (contraption.getLeft() == null) + return; + if (contraption.getLeft() + .getBlocks() + .isEmpty()) + return; + BlockPos anchor = worldPosition.relative(direction); + + contraption.getLeft() + .removeBlocksFromWorld(level, BlockPos.ZERO); + hourHand = ControlledContraptionEntity.create(level, this, contraption.getLeft()); + hourHand.setPos(anchor.getX(), anchor.getY(), anchor.getZ()); + hourHand.setRotationAxis(direction.getAxis()); + level.addFreshEntity(hourHand); + + if (contraption.getLeft() + .containsBlockBreakers()) + award(AllAdvancements.CONTRAPTION_ACTORS); + + if (contraption.getRight() != null) { + anchor = worldPosition.relative(direction, contraption.getRight().offset + 1); + contraption.getRight() + .removeBlocksFromWorld(level, BlockPos.ZERO); + minuteHand = ControlledContraptionEntity.create(level, this, contraption.getRight()); + minuteHand.setPos(anchor.getX(), anchor.getY(), anchor.getZ()); + minuteHand.setRotationAxis(direction.getAxis()); + level.addFreshEntity(minuteHand); + + if (contraption.getRight() + .containsBlockBreakers()) + award(AllAdvancements.CONTRAPTION_ACTORS); + } + + award(AllAdvancements.CLOCKWORK_BEARING); + + // Run + running = true; + hourAngle = 0; + minuteAngle = 0; + sendData(); + } + + public void disassemble() { + if (!running && hourHand == null && minuteHand == null) + return; + + hourAngle = 0; + minuteAngle = 0; + applyRotations(); + + if (hourHand != null) { + hourHand.disassemble(); + } + if (minuteHand != null) + minuteHand.disassemble(); + + hourHand = null; + minuteHand = null; + running = false; + sendData(); + } + + @Override + public void attach(ControlledContraptionEntity contraption) { + if (!(contraption.getContraption() instanceof ClockworkContraption)) + return; + + ClockworkContraption cc = (ClockworkContraption) contraption.getContraption(); + setChanged(); + Direction facing = getBlockState().getValue(BlockStateProperties.FACING); + BlockPos anchor = worldPosition.relative(facing, cc.offset + 1); + if (cc.handType == HandType.HOUR) { + this.hourHand = contraption; + hourHand.setPos(anchor.getX(), anchor.getY(), anchor.getZ()); + } else { + this.minuteHand = contraption; + minuteHand.setPos(anchor.getX(), anchor.getY(), anchor.getZ()); + } + if (!level.isClientSide) { + this.running = true; + sendData(); + } + } + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + compound.putBoolean("Running", running); + compound.putFloat("HourAngle", hourAngle); + compound.putFloat("MinuteAngle", minuteAngle); + AssemblyException.write(compound, lastException); + super.write(compound, clientPacket); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + float hourAngleBefore = hourAngle; + float minuteAngleBefore = minuteAngle; + + running = compound.getBoolean("Running"); + hourAngle = compound.getFloat("HourAngle"); + minuteAngle = compound.getFloat("MinuteAngle"); + lastException = AssemblyException.read(compound); + super.read(compound, clientPacket); + + if (!clientPacket) + return; + + if (running) { + clientHourAngleDiff = AngleHelper.getShortestAngleDiff(hourAngleBefore, hourAngle); + clientMinuteAngleDiff = AngleHelper.getShortestAngleDiff(minuteAngleBefore, minuteAngle); + hourAngle = hourAngleBefore; + minuteAngle = minuteAngleBefore; + } else { + hourHand = null; + minuteHand = null; + } + } + + @Override + public void onSpeedChanged(float prevSpeed) { + super.onSpeedChanged(prevSpeed); + assembleNextTick = true; + } + + @Override + public boolean isValid() { + return !isRemoved(); + } + + @Override + public float getInterpolatedAngle(float partialTicks) { + if (isVirtual()) + return Mth.lerp(partialTicks, prevForcedAngle, hourAngle); + if (hourHand == null || hourHand.isStalled()) + partialTicks = 0; + return Mth.lerp(partialTicks, hourAngle, hourAngle + getHourArmSpeed()); + } + + @Override + public void onStall() { + if (!level.isClientSide) + sendData(); + } + + @Override + public void remove() { + if (!level.isClientSide) + disassemble(); + super.remove(); + } + + @Override + public boolean isAttachedTo(AbstractContraptionEntity contraption) { + if (!(contraption.getContraption() instanceof ClockworkContraption)) + return false; + ClockworkContraption cc = (ClockworkContraption) contraption.getContraption(); + if (cc.handType == HandType.HOUR) + return this.hourHand == contraption; + else + return this.minuteHand == contraption; + } + + public boolean isRunning() { + return running; + } + + static enum ClockHands implements INamedIconOptions { + + HOUR_FIRST(AllIcons.I_HOUR_HAND_FIRST), + MINUTE_FIRST(AllIcons.I_MINUTE_HAND_FIRST), + HOUR_FIRST_24(AllIcons.I_HOUR_HAND_FIRST_24), + + ; + + private String translationKey; + private AllIcons icon; + + private ClockHands(AllIcons icon) { + this.icon = icon; + translationKey = "contraptions.clockwork." + Lang.asId(name()); + } + + @Override + public AllIcons getIcon() { + return icon; + } + + @Override + public String getTranslationKey() { + return translationKey; + } + + } + + @Override + public BlockPos getBlockPosition() { + return worldPosition; + } + + public void setAngle(float forcedAngle) { + hourAngle = forcedAngle; + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/ClockworkContraption.java b/src/main/java/com/simibubi/create/content/contraptions/bearing/ClockworkContraption.java similarity index 88% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/ClockworkContraption.java rename to src/main/java/com/simibubi/create/content/contraptions/bearing/ClockworkContraption.java index 5027c0bea..1ab8f97af 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/ClockworkContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/bearing/ClockworkContraption.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.bearing; +package com.simibubi.create.content.contraptions.bearing; import java.util.HashSet; import java.util.Queue; @@ -6,10 +6,10 @@ import java.util.Set; import org.apache.commons.lang3.tuple.Pair; -import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException; -import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; -import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionLighter; +import com.simibubi.create.content.contraptions.AssemblyException; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.contraptions.ContraptionType; +import com.simibubi.create.content.contraptions.render.ContraptionLighter; import com.simibubi.create.foundation.utility.NBTHelper; import net.minecraft.core.BlockPos; @@ -27,7 +27,7 @@ public class ClockworkContraption extends Contraption { private Set ignoreBlocks = new HashSet<>(); @Override - protected ContraptionType getType() { + public ContraptionType getType() { return ContraptionType.CLOCKWORK; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/bearing/IBearingBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/bearing/IBearingBlockEntity.java new file mode 100644 index 000000000..31031de2c --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/bearing/IBearingBlockEntity.java @@ -0,0 +1,26 @@ +package com.simibubi.create.content.contraptions.bearing; + +import com.simibubi.create.content.contraptions.DirectionalExtenderScrollOptionSlot; +import com.simibubi.create.content.contraptions.IControlContraption; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; + +import net.minecraft.core.Direction.Axis; + +public interface IBearingBlockEntity extends IControlContraption { + + float getInterpolatedAngle(float partialTicks); + + boolean isWoodenTop(); + + default ValueBoxTransform getMovementModeSlot() { + return new DirectionalExtenderScrollOptionSlot((state, d) -> { + Axis axis = d.getAxis(); + Axis bearingAxis = state.getValue(BearingBlock.FACING) + .getAxis(); + return bearingAxis != axis; + }); + } + + void setAngle(float forcedAngle); + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/bearing/MechanicalBearingBlock.java b/src/main/java/com/simibubi/create/content/contraptions/bearing/MechanicalBearingBlock.java new file mode 100644 index 000000000..5e19fd434 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/bearing/MechanicalBearingBlock.java @@ -0,0 +1,54 @@ +package com.simibubi.create.content.contraptions.bearing; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.foundation.block.IBE; + +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.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; + +public class MechanicalBearingBlock extends BearingBlock implements IBE { + + public MechanicalBearingBlock(Properties properties) { + super(properties); + } + + @Override + public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, + BlockHitResult hit) { + if (!player.mayBuild()) + return InteractionResult.FAIL; + if (player.isShiftKeyDown()) + return InteractionResult.FAIL; + if (player.getItemInHand(handIn) + .isEmpty()) { + if (worldIn.isClientSide) + return InteractionResult.SUCCESS; + withBlockEntityDo(worldIn, pos, be -> { + if (be.running) { + be.disassemble(); + return; + } + be.assembleNextTick = true; + }); + return InteractionResult.SUCCESS; + } + return InteractionResult.PASS; + } + + @Override + public Class getBlockEntityClass() { + return MechanicalBearingBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.MECHANICAL_BEARING.get(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/bearing/MechanicalBearingBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/bearing/MechanicalBearingBlockEntity.java new file mode 100644 index 000000000..98d1fc40b --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/bearing/MechanicalBearingBlockEntity.java @@ -0,0 +1,356 @@ +package com.simibubi.create.content.contraptions.bearing; + +import java.util.List; + +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.AssemblyException; +import com.simibubi.create.content.contraptions.ControlledContraptionEntity; +import com.simibubi.create.content.contraptions.IDisplayAssemblyExceptions; +import com.simibubi.create.content.kinetics.base.GeneratingKineticBlockEntity; +import com.simibubi.create.content.kinetics.transmission.sequencer.SequencerInstructions; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollOptionBehaviour; +import com.simibubi.create.foundation.item.TooltipHelper; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.ServerSpeedProvider; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.util.Mth; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; + +public class MechanicalBearingBlockEntity extends GeneratingKineticBlockEntity + implements IBearingBlockEntity, IDisplayAssemblyExceptions { + + protected ScrollOptionBehaviour movementMode; + protected ControlledContraptionEntity movedContraption; + protected float angle; + protected boolean running; + protected boolean assembleNextTick; + protected float clientAngleDiff; + protected AssemblyException lastException; + protected double sequencedAngleLimit; + + private float prevAngle; + + public MechanicalBearingBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + setLazyTickRate(3); + sequencedAngleLimit = -1; + } + + @Override + public boolean isWoodenTop() { + return false; + } + + @Override + protected boolean syncSequenceContext() { + return true; + } + + @Override + public void addBehaviours(List behaviours) { + super.addBehaviours(behaviours); + movementMode = new ScrollOptionBehaviour<>(RotationMode.class, + Lang.translateDirect("contraptions.movement_mode"), this, getMovementModeSlot()); + behaviours.add(movementMode); + registerAwardables(behaviours, AllAdvancements.CONTRAPTION_ACTORS); + } + + @Override + public void remove() { + if (!level.isClientSide) + disassemble(); + super.remove(); + } + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + compound.putBoolean("Running", running); + compound.putFloat("Angle", angle); + if (sequencedAngleLimit >= 0) + compound.putDouble("SequencedAngleLimit", sequencedAngleLimit); + AssemblyException.write(compound, lastException); + super.write(compound, clientPacket); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + if (wasMoved) { + super.read(compound, clientPacket); + return; + } + + float angleBefore = angle; + running = compound.getBoolean("Running"); + angle = compound.getFloat("Angle"); + sequencedAngleLimit = compound.contains("SequencedAngleLimit") ? compound.getDouble("SequencedAngleLimit") : -1; + lastException = AssemblyException.read(compound); + super.read(compound, clientPacket); + if (!clientPacket) + return; + if (running) { + if (movedContraption == null || !movedContraption.isStalled()) { + clientAngleDiff = AngleHelper.getShortestAngleDiff(angleBefore, angle); + angle = angleBefore; + } + } else + movedContraption = null; + } + + @Override + public float getInterpolatedAngle(float partialTicks) { + if (isVirtual()) + return Mth.lerp(partialTicks + .5f, prevAngle, angle); + if (movedContraption == null || movedContraption.isStalled() || !running) + partialTicks = 0; + float angularSpeed = getAngularSpeed(); + if (sequencedAngleLimit >= 0) + angularSpeed = (float) Mth.clamp(angularSpeed, -sequencedAngleLimit, sequencedAngleLimit); + return Mth.lerp(partialTicks, angle, angle + angularSpeed); + } + + @Override + public void onSpeedChanged(float prevSpeed) { + super.onSpeedChanged(prevSpeed); + assembleNextTick = true; + sequencedAngleLimit = -1; + + if (movedContraption != null && Math.signum(prevSpeed) != Math.signum(getSpeed()) && prevSpeed != 0) { + if (!movedContraption.isStalled()) { + angle = Math.round(angle); + applyRotation(); + } + movedContraption.getContraption() + .stop(level); + } + + if (!isWindmill() && sequenceContext != null + && sequenceContext.instruction() == SequencerInstructions.TURN_ANGLE) + sequencedAngleLimit = sequenceContext.getEffectiveValue(getTheoreticalSpeed()); + } + + public float getAngularSpeed() { + float speed = convertToAngular(isWindmill() ? getGeneratedSpeed() : getSpeed()); + if (getSpeed() == 0) + speed = 0; + if (level.isClientSide) { + speed *= ServerSpeedProvider.get(); + speed += clientAngleDiff / 3f; + } + return speed; + } + + @Override + public AssemblyException getLastAssemblyException() { + return lastException; + } + + protected boolean isWindmill() { + return false; + } + + @Override + public BlockPos getBlockPosition() { + return worldPosition; + } + + public void assemble() { + if (!(level.getBlockState(worldPosition) + .getBlock() instanceof BearingBlock)) + return; + + Direction direction = getBlockState().getValue(BearingBlock.FACING); + BearingContraption contraption = new BearingContraption(isWindmill(), direction); + try { + if (!contraption.assemble(level, worldPosition)) + return; + + lastException = null; + } catch (AssemblyException e) { + lastException = e; + sendData(); + return; + } + + if (isWindmill()) + award(AllAdvancements.WINDMILL); + if (contraption.getSailBlocks() >= 16 * 8) + award(AllAdvancements.WINDMILL_MAXED); + + contraption.removeBlocksFromWorld(level, BlockPos.ZERO); + movedContraption = ControlledContraptionEntity.create(level, this, contraption); + BlockPos anchor = worldPosition.relative(direction); + movedContraption.setPos(anchor.getX(), anchor.getY(), anchor.getZ()); + movedContraption.setRotationAxis(direction.getAxis()); + level.addFreshEntity(movedContraption); + + AllSoundEvents.CONTRAPTION_ASSEMBLE.playOnServer(level, worldPosition); + + if (contraption.containsBlockBreakers()) + award(AllAdvancements.CONTRAPTION_ACTORS); + + running = true; + angle = 0; + sendData(); + updateGeneratedRotation(); + } + + public void disassemble() { + if (!running && movedContraption == null) + return; + angle = 0; + sequencedAngleLimit = -1; + if (isWindmill()) + applyRotation(); + if (movedContraption != null) { + movedContraption.disassemble(); + AllSoundEvents.CONTRAPTION_DISASSEMBLE.playOnServer(level, worldPosition); + } + + movedContraption = null; + running = false; + updateGeneratedRotation(); + assembleNextTick = false; + sendData(); + } + + @Override + public void tick() { + super.tick(); + + prevAngle = angle; + if (level.isClientSide) + clientAngleDiff /= 2; + + if (!level.isClientSide && assembleNextTick) { + assembleNextTick = false; + if (running) { + boolean canDisassemble = movementMode.get() == RotationMode.ROTATE_PLACE + || (isNearInitialAngle() && movementMode.get() == RotationMode.ROTATE_PLACE_RETURNED); + if (speed == 0 && (canDisassemble || movedContraption == null || movedContraption.getContraption() + .getBlocks() + .isEmpty())) { + if (movedContraption != null) + movedContraption.getContraption() + .stop(level); + disassemble(); + return; + } + } else { + if (speed == 0 && !isWindmill()) + return; + assemble(); + } + } + + if (!running) + return; + + if (!(movedContraption != null && movedContraption.isStalled())) { + float angularSpeed = getAngularSpeed(); + if (sequencedAngleLimit >= 0) { + angularSpeed = (float) Mth.clamp(angularSpeed, -sequencedAngleLimit, sequencedAngleLimit); + sequencedAngleLimit = Math.max(0, sequencedAngleLimit - Math.abs(angularSpeed)); + } + float newAngle = angle + angularSpeed; + angle = (float) (newAngle % 360); + } + + applyRotation(); + } + + public boolean isNearInitialAngle() { + return Math.abs(angle) < 22.5 || Math.abs(angle) > 360 - 22.5; + } + + @Override + public void lazyTick() { + super.lazyTick(); + if (movedContraption != null && !level.isClientSide) + sendData(); + } + + protected void applyRotation() { + if (movedContraption == null) + return; + movedContraption.setAngle(angle); + BlockState blockState = getBlockState(); + if (blockState.hasProperty(BlockStateProperties.FACING)) + movedContraption.setRotationAxis(blockState.getValue(BlockStateProperties.FACING) + .getAxis()); + } + + @Override + public void attach(ControlledContraptionEntity contraption) { + BlockState blockState = getBlockState(); + if (!(contraption.getContraption() instanceof BearingContraption)) + return; + if (!blockState.hasProperty(BearingBlock.FACING)) + return; + + this.movedContraption = contraption; + setChanged(); + BlockPos anchor = worldPosition.relative(blockState.getValue(BearingBlock.FACING)); + movedContraption.setPos(anchor.getX(), anchor.getY(), anchor.getZ()); + if (!level.isClientSide) { + this.running = true; + sendData(); + } + } + + @Override + public void onStall() { + if (!level.isClientSide) + sendData(); + } + + @Override + public boolean isValid() { + return !isRemoved(); + } + + @Override + public boolean isAttachedTo(AbstractContraptionEntity contraption) { + return movedContraption == contraption; + } + + public boolean isRunning() { + return running; + } + + @Override + public boolean addToTooltip(List tooltip, boolean isPlayerSneaking) { + if (super.addToTooltip(tooltip, isPlayerSneaking)) + return true; + if (isPlayerSneaking) + return false; + if (!isWindmill() && getSpeed() == 0) + return false; + if (running) + return false; + BlockState state = getBlockState(); + if (!(state.getBlock() instanceof BearingBlock)) + return false; + + BlockState attachedState = level.getBlockState(worldPosition.relative(state.getValue(BearingBlock.FACING))); + if (attachedState.getMaterial() + .isReplaceable()) + return false; + TooltipHelper.addHint(tooltip, "hint.empty_bearing"); + return true; + } + + public void setAngle(float forcedAngle) { + angle = forcedAngle; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/SailBlock.java b/src/main/java/com/simibubi/create/content/contraptions/bearing/SailBlock.java similarity index 92% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/SailBlock.java rename to src/main/java/com/simibubi/create/content/contraptions/bearing/SailBlock.java index 6df9cb027..334e29a46 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/SailBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/bearing/SailBlock.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.bearing; +package com.simibubi.create.content.contraptions.bearing; import java.util.ArrayList; import java.util.HashSet; @@ -11,11 +11,11 @@ import javax.annotation.Nullable; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; import com.simibubi.create.foundation.block.WrenchableDirectionalBlock; +import com.simibubi.create.foundation.placement.IPlacementHelper; +import com.simibubi.create.foundation.placement.PlacementHelpers; +import com.simibubi.create.foundation.placement.PlacementOffset; import com.simibubi.create.foundation.utility.BlockHelper; import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.placement.IPlacementHelper; -import com.simibubi.create.foundation.utility.placement.PlacementHelpers; -import com.simibubi.create.foundation.utility.placement.PlacementOffset; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; @@ -77,9 +77,13 @@ public class SailBlock extends WrenchableDirectionalBlock { ItemStack heldItem = player.getItemInHand(hand); IPlacementHelper placementHelper = PlacementHelpers.get(placementHelperId); - if (placementHelper.matchesItem(heldItem)) - return placementHelper.getOffset(player, world, state, pos, ray) - .placeInWorld(world, (BlockItem) heldItem.getItem(), player, hand, ray); + if (!player.isShiftKeyDown() && player.mayBuild()) { + if (placementHelper.matchesItem(heldItem)) { + placementHelper.getOffset(player, world, state, pos, ray) + .placeInWorld(world, (BlockItem) heldItem.getItem(), player, hand, ray); + return InteractionResult.SUCCESS; + } + } if (heldItem.getItem() instanceof ShearsItem) { if (!world.isClientSide) @@ -114,7 +118,8 @@ public class SailBlock extends WrenchableDirectionalBlock { } // Dye all adjacent - List directions = IPlacementHelper.orderedByDistanceExceptAxis(pos, hit, state.getValue(FACING).getAxis()); + List directions = IPlacementHelper.orderedByDistanceExceptAxis(pos, hit, state.getValue(FACING) + .getAxis()); for (Direction d : directions) { BlockPos offset = pos.relative(d); BlockState adjacentState = world.getBlockState(offset); @@ -177,7 +182,8 @@ public class SailBlock extends WrenchableDirectionalBlock { } @Override - public ItemStack getCloneItemStack(BlockState state, HitResult target, BlockGetter world, BlockPos pos, Player player) { + public ItemStack getCloneItemStack(BlockState state, HitResult target, BlockGetter world, BlockPos pos, + Player player) { ItemStack pickBlock = super.getCloneItemStack(state, target, world, pos, player); if (pickBlock.isEmpty()) return AllBlocks.SAIL.get() diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/StabilizedBearingInstance.java b/src/main/java/com/simibubi/create/content/contraptions/bearing/StabilizedBearingInstance.java similarity index 80% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/StabilizedBearingInstance.java rename to src/main/java/com/simibubi/create/content/contraptions/bearing/StabilizedBearingInstance.java index 69079056d..68e2689d9 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/StabilizedBearingInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/bearing/StabilizedBearingInstance.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.bearing; +package com.simibubi.create.content.contraptions.bearing; import org.joml.Quaternionf; @@ -7,10 +7,10 @@ import com.jozufozu.flywheel.core.Materials; import com.jozufozu.flywheel.core.materials.oriented.OrientedData; import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; import com.mojang.math.Axis; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.flwdata.RotatingData; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.contraptions.render.ActorInstance; +import com.simibubi.create.content.kinetics.base.flwdata.RotatingData; import com.simibubi.create.foundation.render.AllMaterialSpecs; import com.simibubi.create.foundation.utility.AnimationTickHolder; @@ -39,7 +39,7 @@ public class StabilizedBearingInstance extends ActorInstance { topInstance = materialManager.defaultSolid() .material(Materials.ORIENTED) - .getModel(AllBlockPartials.BEARING_TOP, blockState) + .getModel(AllPartialModels.BEARING_TOP, blockState) .createInstance(); int blockLight = localBlockLight(); @@ -49,7 +49,7 @@ public class StabilizedBearingInstance extends ActorInstance { shaft = materialManager.defaultSolid() .material(AllMaterialSpecs.ROTATING) - .getModel(AllBlockPartials.SHAFT_HALF, blockState, blockState.getValue(BlockStateProperties.FACING).getOpposite()) + .getModel(AllPartialModels.SHAFT_HALF, blockState, blockState.getValue(BlockStateProperties.FACING).getOpposite()) .createInstance(); // not rotating so no need to set speed, axis, etc. diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/StabilizedBearingMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/bearing/StabilizedBearingMovementBehaviour.java similarity index 76% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/StabilizedBearingMovementBehaviour.java rename to src/main/java/com/simibubi/create/content/contraptions/bearing/StabilizedBearingMovementBehaviour.java index a25796473..2d3800b4e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/StabilizedBearingMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/bearing/StabilizedBearingMovementBehaviour.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.bearing; +package com.simibubi.create.content.contraptions.bearing; import javax.annotation.Nullable; @@ -8,15 +8,15 @@ import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.core.PartialModel; import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; import com.mojang.math.Axis; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; -import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.ControlledContraptionEntity; +import com.simibubi.create.content.contraptions.OrientedContraptionEntity; +import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.contraptions.render.ActorInstance; +import com.simibubi.create.content.contraptions.render.ContraptionMatrices; +import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher; import com.simibubi.create.foundation.render.CachedBufferer; import com.simibubi.create.foundation.render.SuperByteBuffer; import com.simibubi.create.foundation.utility.AnimationTickHolder; @@ -24,12 +24,18 @@ import com.simibubi.create.foundation.utility.AnimationTickHolder; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.core.Direction; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; public class StabilizedBearingMovementBehaviour implements MovementBehaviour { + @Override + public ItemStack canBeDisabledVia(MovementContext context) { + return null; + } + @Override @OnlyIn(Dist.CLIENT) public void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld, @@ -38,7 +44,7 @@ public class StabilizedBearingMovementBehaviour implements MovementBehaviour { return; Direction facing = context.state.getValue(BlockStateProperties.FACING); - PartialModel top = AllBlockPartials.BEARING_TOP; + PartialModel top = AllPartialModels.BEARING_TOP; SuperByteBuffer superBuffer = CachedBufferer.partial(top, context.state); float renderPartialTicks = AnimationTickHolder.getPartialTicks(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/bearing/StabilizedContraption.java b/src/main/java/com/simibubi/create/content/contraptions/bearing/StabilizedContraption.java new file mode 100644 index 000000000..c4ef7cf30 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/bearing/StabilizedContraption.java @@ -0,0 +1,74 @@ +package com.simibubi.create.content.contraptions.bearing; + +import com.simibubi.create.content.contraptions.AssemblyException; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.contraptions.ContraptionType; +import com.simibubi.create.content.contraptions.render.ContraptionLighter; +import com.simibubi.create.content.contraptions.render.NonStationaryLighter; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.Level; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public class StabilizedContraption extends Contraption { + + private Direction facing; + + public StabilizedContraption() {} + + public StabilizedContraption(Direction facing) { + this.facing = facing; + } + + @Override + public boolean assemble(Level world, BlockPos pos) throws AssemblyException { + BlockPos offset = pos.relative(facing); + if (!searchMovedStructure(world, offset, null)) + return false; + startMoving(world); + if (blocks.isEmpty()) + return false; + return true; + } + + @Override + protected boolean isAnchoringBlockAt(BlockPos pos) { + return false; + } + + @Override + public ContraptionType getType() { + return ContraptionType.STABILIZED; + } + + @Override + public CompoundTag writeNBT(boolean spawnPacket) { + CompoundTag tag = super.writeNBT(spawnPacket); + tag.putInt("Facing", facing.get3DDataValue()); + return tag; + } + + @Override + public void readNBT(Level world, CompoundTag tag, boolean spawnData) { + facing = Direction.from3DDataValue(tag.getInt("Facing")); + super.readNBT(world, tag, spawnData); + } + + @Override + public boolean canBeStabilized(Direction facing, BlockPos localPos) { + return false; + } + + public Direction getFacing() { + return facing; + } + + @Override + @OnlyIn(Dist.CLIENT) + public ContraptionLighter makeLighter() { + return new NonStationaryLighter<>(this); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/bearing/WindmillBearingBlock.java b/src/main/java/com/simibubi/create/content/contraptions/bearing/WindmillBearingBlock.java new file mode 100644 index 000000000..29416b982 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/bearing/WindmillBearingBlock.java @@ -0,0 +1,59 @@ +package com.simibubi.create.content.contraptions.bearing; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.utility.Couple; + +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.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; + +public class WindmillBearingBlock extends BearingBlock implements IBE { + + public WindmillBearingBlock(Properties properties) { + super(properties); + } + + @Override + public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, + BlockHitResult hit) { + if (!player.mayBuild()) + return InteractionResult.FAIL; + if (player.isShiftKeyDown()) + return InteractionResult.FAIL; + if (player.getItemInHand(handIn) + .isEmpty()) { + if (worldIn.isClientSide) + return InteractionResult.SUCCESS; + withBlockEntityDo(worldIn, pos, be -> { + if (be.running) { + be.disassemble(); + return; + } + be.assembleNextTick = true; + }); + return InteractionResult.SUCCESS; + } + return InteractionResult.PASS; + } + + @Override + public Class getBlockEntityClass() { + return WindmillBearingBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.WINDMILL_BEARING.get(); + } + + public static Couple getSpeedRange() { + return Couple.create(1, 16); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/bearing/WindmillBearingBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/bearing/WindmillBearingBlockEntity.java new file mode 100644 index 000000000..d78dc5251 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/bearing/WindmillBearingBlockEntity.java @@ -0,0 +1,148 @@ +package com.simibubi.create.content.contraptions.bearing; + +import java.util.List; + +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.INamedIconOptions; +import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollOptionBehaviour; +import com.simibubi.create.foundation.gui.AllIcons; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.Mth; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; + +public class WindmillBearingBlockEntity extends MechanicalBearingBlockEntity { + + protected ScrollOptionBehaviour movementDirection; + protected float lastGeneratedSpeed; + + protected boolean queuedReassembly; + + public WindmillBearingBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + public void updateGeneratedRotation() { + super.updateGeneratedRotation(); + lastGeneratedSpeed = getGeneratedSpeed(); + queuedReassembly = false; + } + + @Override + public void onSpeedChanged(float prevSpeed) { + boolean cancelAssembly = assembleNextTick; + super.onSpeedChanged(prevSpeed); + assembleNextTick = cancelAssembly; + } + + @Override + public void tick() { + super.tick(); + if (level.isClientSide()) + return; + if (!queuedReassembly) + return; + queuedReassembly = false; + if (!running) + assembleNextTick = true; + } + + public void disassembleForMovement() { + if (!running) + return; + disassemble(); + queuedReassembly = true; + } + + @Override + public float getGeneratedSpeed() { + if (!running) + return 0; + if (movedContraption == null) + return lastGeneratedSpeed; + int sails = ((BearingContraption) movedContraption.getContraption()).getSailBlocks() + / AllConfigs.server().kinetics.windmillSailsPerRPM.get(); + return Mth.clamp(sails, 1, 16) * getAngleSpeedDirection(); + } + + @Override + protected boolean isWindmill() { + return true; + } + + protected float getAngleSpeedDirection() { + RotationDirection rotationDirection = RotationDirection.values()[movementDirection.getValue()]; + return (rotationDirection == RotationDirection.CLOCKWISE ? 1 : -1); + } + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + compound.putFloat("LastGenerated", lastGeneratedSpeed); + compound.putBoolean("QueueAssembly", queuedReassembly); + super.write(compound, clientPacket); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + if (!wasMoved) + lastGeneratedSpeed = compound.getFloat("LastGenerated"); + queuedReassembly = compound.getBoolean("QueueAssembly"); + super.read(compound, clientPacket); + } + + @Override + public void addBehaviours(List behaviours) { + super.addBehaviours(behaviours); + behaviours.remove(movementMode); + movementDirection = new ScrollOptionBehaviour<>(RotationDirection.class, + Lang.translateDirect("contraptions.windmill.rotation_direction"), this, getMovementModeSlot()); + movementDirection.withCallback($ -> onDirectionChanged()); + behaviours.add(movementDirection); + registerAwardables(behaviours, AllAdvancements.WINDMILL, AllAdvancements.WINDMILL_MAXED); + } + + private void onDirectionChanged() { + if (!running) + return; + if (!level.isClientSide) + updateGeneratedRotation(); + } + + @Override + public boolean isWoodenTop() { + return true; + } + + public static enum RotationDirection implements INamedIconOptions { + + CLOCKWISE(AllIcons.I_REFRESH), COUNTER_CLOCKWISE(AllIcons.I_ROTATE_CCW), + + ; + + private String translationKey; + private AllIcons icon; + + private RotationDirection(AllIcons icon) { + this.icon = icon; + translationKey = "generic." + Lang.asId(name()); + } + + @Override + public AllIcons getIcon() { + return icon; + } + + @Override + public String getTranslationKey() { + return translationKey; + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/behaviour/BellMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/BellMovementBehaviour.java new file mode 100644 index 000000000..367d06ffc --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/BellMovementBehaviour.java @@ -0,0 +1,52 @@ +package com.simibubi.create.content.contraptions.behaviour; + +import com.simibubi.create.content.equipment.bell.AbstractBellBlock; +import com.simibubi.create.content.trains.entity.CarriageContraption; + +import net.minecraft.core.BlockPos; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.phys.Vec3; + +public class BellMovementBehaviour implements MovementBehaviour { + + @Override + public boolean renderAsNormalBlockEntity() { + return true; + } + + @Override + public boolean isActive(MovementContext context) { + return MovementBehaviour.super.isActive(context) && !(context.contraption instanceof CarriageContraption); + } + + @Override + public void onSpeedChanged(MovementContext context, Vec3 oldMotion, Vec3 motion) { + double dotProduct = oldMotion.dot(motion); + + if (dotProduct <= 0 && (context.relativeMotion.length() != 0) || context.firstMovement) + playSound(context); + } + + @Override + public void stopMoving(MovementContext context) { + if (context.position != null && isActive(context)) + playSound(context); + } + + public static void playSound(MovementContext context) { + Level world = context.world; + BlockPos pos = new BlockPos(context.position); + Block block = context.state.getBlock(); + + if (block instanceof AbstractBellBlock) { + ((AbstractBellBlock) block).playSound(world, pos); + } else { + // Vanilla bell sound + world.playSound(null, pos, SoundEvents.BELL_BLOCK, + SoundSource.BLOCKS, 2f, 1f); + } + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/behaviour/CampfireMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/CampfireMovementBehaviour.java new file mode 100644 index 000000000..a6be9bf45 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/CampfireMovementBehaviour.java @@ -0,0 +1,33 @@ +package com.simibubi.create.content.contraptions.behaviour; + +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.block.CampfireBlock; + +public class CampfireMovementBehaviour implements MovementBehaviour { + @Override + public boolean renderAsNormalBlockEntity() { + return true; + } + + @Override + public void tick(MovementContext context) { + if (context.world == null || !context.world.isClientSide || context.position == null + || !context.state.getValue(CampfireBlock.LIT) || context.disabled) + return; + + // Mostly copied from CampfireBlock and CampfireBlockEntity + RandomSource random = context.world.random; + if (random.nextFloat() < 0.11F) { + for (int i = 0; i < random.nextInt(2) + 2; ++i) { + context.world.addAlwaysVisibleParticle( + context.state.getValue(CampfireBlock.SIGNAL_FIRE) ? ParticleTypes.CAMPFIRE_SIGNAL_SMOKE + : ParticleTypes.CAMPFIRE_COSY_SMOKE, + true, context.position.x() + random.nextDouble() / (random.nextBoolean() ? 3D : -3D), + context.position.y() + random.nextDouble() + random.nextDouble(), + context.position.z() + random.nextDouble() / (random.nextBoolean() ? 3D : -3D), 0.0D, 0.07D, + 0.0D); + } + } + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/DoorMovingInteraction.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/DoorMovingInteraction.java similarity index 90% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/DoorMovingInteraction.java rename to src/main/java/com/simibubi/create/content/contraptions/behaviour/DoorMovingInteraction.java index 0c5b7a22d..d58c0d129 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/DoorMovingInteraction.java +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/DoorMovingInteraction.java @@ -1,7 +1,7 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.interaction; +package com.simibubi.create.content.contraptions.behaviour; -import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; -import com.simibubi.create.content.curiosities.deco.SlidingDoorBlock; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.decoration.slidingDoor.SlidingDoorBlock; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/LeverMovingInteraction.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/LeverMovingInteraction.java similarity index 76% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/LeverMovingInteraction.java rename to src/main/java/com/simibubi/create/content/contraptions/behaviour/LeverMovingInteraction.java index 021ecf75d..19472df5d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/LeverMovingInteraction.java +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/LeverMovingInteraction.java @@ -1,6 +1,6 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.interaction; +package com.simibubi.create.content.contraptions.behaviour; -import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; +import com.simibubi.create.content.contraptions.Contraption; import net.minecraft.core.BlockPos; import net.minecraft.sounds.SoundEvents; diff --git a/src/main/java/com/simibubi/create/content/contraptions/behaviour/MovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/MovementBehaviour.java new file mode 100644 index 000000000..3c3a2432b --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/MovementBehaviour.java @@ -0,0 +1,97 @@ +package com.simibubi.create.content.contraptions.behaviour; + +import javax.annotation.Nullable; + +import com.jozufozu.flywheel.api.MaterialManager; +import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; +import com.simibubi.create.content.contraptions.render.ActorInstance; +import com.simibubi.create.content.contraptions.render.ContraptionMatrices; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.items.ItemHandlerHelper; + +public interface MovementBehaviour { + + default boolean isActive(MovementContext context) { + return !context.disabled; + } + + default void tick(MovementContext context) {} + + default void startMoving(MovementContext context) {} + + default void visitNewPosition(MovementContext context, BlockPos pos) {} + + default Vec3 getActiveAreaOffset(MovementContext context) { + return Vec3.ZERO; + } + + @Nullable + default ItemStack canBeDisabledVia(MovementContext context) { + Block block = context.state.getBlock(); + if (block == null) + return null; + return new ItemStack(block); + } + + default void onDisabledByControls(MovementContext context) { + cancelStall(context); + } + + default boolean mustTickWhileDisabled() { + return false; + } + + default void dropItem(MovementContext context, ItemStack stack) { + ItemStack remainder; + if (AllConfigs.server().kinetics.moveItemsToStorage.get()) + remainder = ItemHandlerHelper.insertItem(context.contraption.getSharedInventory(), stack, false); + else + remainder = stack; + if (remainder.isEmpty()) + return; + + Vec3 vec = context.position; + ItemEntity itemEntity = new ItemEntity(context.world, vec.x, vec.y, vec.z, remainder); + itemEntity.setDeltaMovement(context.motion.add(0, 0.5f, 0) + .scale(context.world.random.nextFloat() * .3f)); + context.world.addFreshEntity(itemEntity); + } + + default void onSpeedChanged(MovementContext context, Vec3 oldMotion, Vec3 motion) {} + + default void stopMoving(MovementContext context) {} + + default void cancelStall(MovementContext context) { + context.stall = false; + } + + default void writeExtraData(MovementContext context) {} + + default boolean renderAsNormalBlockEntity() { + return false; + } + + default boolean hasSpecialInstancedRendering() { + return false; + } + + @OnlyIn(Dist.CLIENT) + default void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld, + ContraptionMatrices matrices, MultiBufferSource buffer) {} + + @OnlyIn(Dist.CLIENT) + @Nullable + default ActorInstance createInstance(MaterialManager materialManager, VirtualRenderWorld simulationWorld, + MovementContext context) { + return null; + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovementContext.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/MovementContext.java similarity index 90% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovementContext.java rename to src/main/java/com/simibubi/create/content/contraptions/behaviour/MovementContext.java index 751044b5b..b5ff9ee76 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovementContext.java +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/MovementContext.java @@ -1,7 +1,8 @@ -package com.simibubi.create.content.contraptions.components.structureMovement; +package com.simibubi.create.content.contraptions.behaviour; import java.util.function.UnaryOperator; +import com.simibubi.create.content.contraptions.Contraption; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.core.BlockPos; @@ -22,9 +23,10 @@ public class MovementContext { public Level world; public BlockState state; public BlockPos localPos; - public CompoundTag tileData; + public CompoundTag blockEntityData; public boolean stall; + public boolean disabled; public boolean firstMovement; public CompoundTag data; public Contraption contraption; @@ -33,10 +35,11 @@ public class MovementContext { public MovementContext(Level world, StructureBlockInfo info, Contraption contraption) { this.world = world; this.state = info.state; - this.tileData = info.nbt; + this.blockEntityData = info.nbt; this.contraption = contraption; localPos = info.pos; + disabled = false; firstMovement = true; motion = Vec3.ZERO; relativeMotion = Vec3.ZERO; @@ -49,6 +52,8 @@ public class MovementContext { public float getAnimationSpeed() { int modifier = 1000; double length = -motion.length(); + if (disabled) + return 0; if (world.isClientSide && contraption.stalled) return 700; if (Math.abs(length) < 1 / 512f) diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovingInteractionBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/MovingInteractionBehaviour.java similarity index 75% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovingInteractionBehaviour.java rename to src/main/java/com/simibubi/create/content/contraptions/behaviour/MovingInteractionBehaviour.java index cd8285595..b6b2d698c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovingInteractionBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/MovingInteractionBehaviour.java @@ -1,7 +1,9 @@ -package com.simibubi.create.content.contraptions.components.structureMovement; +package com.simibubi.create.content.contraptions.behaviour; import org.apache.commons.lang3.tuple.MutablePair; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; + import net.minecraft.core.BlockPos; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.Entity; @@ -12,10 +14,10 @@ public abstract class MovingInteractionBehaviour { protected void setContraptionActorData(AbstractContraptionEntity contraptionEntity, int index, StructureBlockInfo info, MovementContext ctx) { - contraptionEntity.contraption.actors.remove(index); - contraptionEntity.contraption.actors.add(index, MutablePair.of(info, ctx)); + contraptionEntity.getContraption().getActors().remove(index); + contraptionEntity.getContraption().getActors().add(index, MutablePair.of(info, ctx)); if (contraptionEntity.level.isClientSide) - contraptionEntity.contraption.deferInvalidate = true; + contraptionEntity.getContraption().deferInvalidate = true; } protected void setContraptionBlockData(AbstractContraptionEntity contraptionEntity, BlockPos pos, diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/SimpleBlockMovingInteraction.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/SimpleBlockMovingInteraction.java similarity index 78% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/SimpleBlockMovingInteraction.java rename to src/main/java/com/simibubi/create/content/contraptions/behaviour/SimpleBlockMovingInteraction.java index eceb3c0c2..69de088b2 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/SimpleBlockMovingInteraction.java +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/SimpleBlockMovingInteraction.java @@ -1,8 +1,7 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.interaction; +package com.simibubi.create.content.contraptions.behaviour; -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; -import com.simibubi.create.content.contraptions.components.structureMovement.MovingInteractionBehaviour; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.Contraption; import net.minecraft.core.BlockPos; import net.minecraft.sounds.SoundEvent; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/TrapdoorMovingInteraction.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/TrapdoorMovingInteraction.java similarity index 82% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/TrapdoorMovingInteraction.java rename to src/main/java/com/simibubi/create/content/contraptions/behaviour/TrapdoorMovingInteraction.java index 18aed3faf..226dcfa2e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/TrapdoorMovingInteraction.java +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/TrapdoorMovingInteraction.java @@ -1,6 +1,6 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.interaction; +package com.simibubi.create.content.contraptions.behaviour; -import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; +import com.simibubi.create.content.contraptions.Contraption; import net.minecraft.core.BlockPos; import net.minecraft.sounds.SoundEvent; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/ContraptionBlockSource.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/ContraptionBlockSource.java similarity index 91% rename from src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/ContraptionBlockSource.java rename to src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/ContraptionBlockSource.java index d64758b33..870da5cdb 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/ContraptionBlockSource.java +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/ContraptionBlockSource.java @@ -1,8 +1,8 @@ -package com.simibubi.create.content.contraptions.components.actors.dispenser; +package com.simibubi.create.content.contraptions.behaviour.dispenser; import javax.annotation.Nullable; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/DispenseItemLocation.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DispenseItemLocation.java similarity index 85% rename from src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/DispenseItemLocation.java rename to src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DispenseItemLocation.java index 2b0b23916..c9134e0b3 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/DispenseItemLocation.java +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DispenseItemLocation.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.actors.dispenser; +package com.simibubi.create.content.contraptions.behaviour.dispenser; public class DispenseItemLocation { private final boolean internal; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/DispenserMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DispenserMovementBehaviour.java similarity index 94% rename from src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/DispenserMovementBehaviour.java rename to src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DispenserMovementBehaviour.java index 8ca9d9684..1018e9887 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/DispenserMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DispenserMovementBehaviour.java @@ -1,8 +1,8 @@ -package com.simibubi.create.content.contraptions.components.actors.dispenser; +package com.simibubi.create.content.contraptions.behaviour.dispenser; import java.util.HashMap; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; import com.simibubi.create.foundation.mixin.accessor.DispenserBlockAccessor; import net.minecraft.core.BlockPos; @@ -79,7 +79,7 @@ public class DispenserMovementBehaviour extends DropperMovementBehaviour { return; } } catch (NullPointerException ignored) { - itemStack = backup; // Something went wrong with the TE being null in ContraptionBlockSource, reset the stack + itemStack = backup; // Something went wrong with the BE being null in ContraptionBlockSource, reset the stack } setItemStackAt(location, DEFAULT_BEHAVIOUR.dispense(itemStack, context, pos), context); // the default: launch the item diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/DropperMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DropperMovementBehaviour.java similarity index 91% rename from src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/DropperMovementBehaviour.java rename to src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DropperMovementBehaviour.java index 03bf61698..3f854219e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/DropperMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DropperMovementBehaviour.java @@ -1,11 +1,11 @@ -package com.simibubi.create.content.contraptions.components.actors.dispenser; +package com.simibubi.create.content.contraptions.behaviour.dispenser; import java.util.ArrayList; import java.util.List; import java.util.Random; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; +import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; import com.simibubi.create.foundation.item.ItemHelper; import net.minecraft.core.BlockPos; @@ -50,7 +50,7 @@ public class DropperMovementBehaviour implements MovementBehaviour { private void updateTemporaryData(MovementContext context) { if (!(context.temporaryData instanceof NonNullList) && context.world != null) { NonNullList stacks = NonNullList.withSize(getInvSize(), ItemStack.EMPTY); - ContainerHelper.loadAllItems(context.tileData, stacks); + ContainerHelper.loadAllItems(context.blockEntityData, stacks); context.temporaryData = stacks; } } @@ -84,7 +84,7 @@ public class DropperMovementBehaviour implements MovementBehaviour { NonNullList stacks = getStacks(context); if (stacks == null) return; - ContainerHelper.saveAllItems(context.tileData, stacks); + ContainerHelper.saveAllItems(context.blockEntityData, stacks); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/IMovedDispenseItemBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/IMovedDispenseItemBehaviour.java similarity index 97% rename from src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/IMovedDispenseItemBehaviour.java rename to src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/IMovedDispenseItemBehaviour.java index a9a35e3cd..899398435 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/IMovedDispenseItemBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/IMovedDispenseItemBehaviour.java @@ -1,6 +1,6 @@ -package com.simibubi.create.content.contraptions.components.actors.dispenser; +package com.simibubi.create.content.contraptions.behaviour.dispenser; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; import net.minecraft.Util; import net.minecraft.core.BlockPos; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/MovedDefaultDispenseItemBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/MovedDefaultDispenseItemBehaviour.java similarity index 91% rename from src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/MovedDefaultDispenseItemBehaviour.java rename to src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/MovedDefaultDispenseItemBehaviour.java index 45b5a89d7..1ad03f1bc 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/MovedDefaultDispenseItemBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/MovedDefaultDispenseItemBehaviour.java @@ -1,6 +1,6 @@ -package com.simibubi.create.content.contraptions.components.actors.dispenser; +package com.simibubi.create.content.contraptions.behaviour.dispenser; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -49,13 +49,13 @@ public class MovedDefaultDispenseItemBehaviour implements IMovedDispenseItemBeha facingVec.normalize(); Direction closestToFacing = getClosestFacingDirection(facingVec); - Container iinventory = HopperBlockEntity.getContainerAt(context.world, pos.relative(closestToFacing)); - if (iinventory == null) { + Container inventory = HopperBlockEntity.getContainerAt(context.world, pos.relative(closestToFacing)); + if (inventory == null) { this.playDispenseSound(context.world, pos); this.spawnDispenseParticles(context.world, pos, closestToFacing); return this.dispenseStack(itemStack, context, pos, facingVec); } else { - if (HopperBlockEntity.addItem(null, iinventory, itemStack.copy() + if (HopperBlockEntity.addItem(null, inventory, itemStack.copy() .split(1), closestToFacing.getOpposite()) .isEmpty()) itemStack.shrink(1); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/MovedOptionalDispenseBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/MovedOptionalDispenseBehaviour.java similarity index 82% rename from src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/MovedOptionalDispenseBehaviour.java rename to src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/MovedOptionalDispenseBehaviour.java index b1af00626..3e9e77ed1 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/MovedOptionalDispenseBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/MovedOptionalDispenseBehaviour.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.actors.dispenser; +package com.simibubi.create.content.contraptions.behaviour.dispenser; import net.minecraft.core.BlockPos; import net.minecraft.world.level.LevelAccessor; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/MovedProjectileDispenserBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/MovedProjectileDispenserBehaviour.java similarity index 79% rename from src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/MovedProjectileDispenserBehaviour.java rename to src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/MovedProjectileDispenserBehaviour.java index 4add4a76e..2d99d3617 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/MovedProjectileDispenserBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/MovedProjectileDispenserBehaviour.java @@ -1,8 +1,8 @@ -package com.simibubi.create.content.contraptions.components.actors.dispenser; +package com.simibubi.create.content.contraptions.behaviour.dispenser; import javax.annotation.Nullable; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; import com.simibubi.create.foundation.mixin.accessor.AbstractProjectileDispenseBehaviorAccessor; import net.minecraft.core.BlockPos; @@ -20,12 +20,12 @@ public abstract class MovedProjectileDispenserBehaviour extends MovedDefaultDisp double x = pos.getX() + facing.x * .7 + .5; double y = pos.getY() + facing.y * .7 + .5; double z = pos.getZ() + facing.z * .7 + .5; - Projectile ProjectileEntity = this.getProjectileEntity(context.world, x, y, z, itemStack.copy()); - if (ProjectileEntity == null) + Projectile projectile = this.getProjectileEntity(context.world, x, y, z, itemStack.copy()); + if (projectile == null) return itemStack; Vec3 effectiveMovementVec = facing.scale(getProjectileVelocity()).add(context.motion); - ProjectileEntity.shoot(effectiveMovementVec.x, effectiveMovementVec.y, effectiveMovementVec.z, (float) effectiveMovementVec.length(), this.getProjectileInaccuracy()); - context.world.addFreshEntity(ProjectileEntity); + projectile.shoot(effectiveMovementVec.x, effectiveMovementVec.y, effectiveMovementVec.z, (float) effectiveMovementVec.length(), this.getProjectileInaccuracy()); + context.world.addFreshEntity(projectile); itemStack.shrink(1); return itemStack; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/SimplePos.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/SimplePos.java similarity index 83% rename from src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/SimplePos.java rename to src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/SimplePos.java index 3d62bd8c7..9b8c22acc 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/dispenser/SimplePos.java +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/SimplePos.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.actors.dispenser; +package com.simibubi.create.content.contraptions.behaviour.dispenser; import net.minecraft.core.Position; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/AbstractChassisBlock.java b/src/main/java/com/simibubi/create/content/contraptions/chassis/AbstractChassisBlock.java similarity index 89% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/AbstractChassisBlock.java rename to src/main/java/com/simibubi/create/content/contraptions/chassis/AbstractChassisBlock.java index bffbbe404..d406b5d13 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/AbstractChassisBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/chassis/AbstractChassisBlock.java @@ -1,12 +1,12 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.chassis; +package com.simibubi.create.content.contraptions.chassis; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllItems; import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.components.structureMovement.ITransformableBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.content.contraptions.ITransformableBlock; +import com.simibubi.create.content.contraptions.StructureTransform; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.utility.Iterate; import net.minecraft.core.BlockPos; @@ -28,7 +28,7 @@ import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; import net.minecraftforge.common.Tags; -public abstract class AbstractChassisBlock extends RotatedPillarBlock implements IWrenchable, ITE, ITransformableBlock { +public abstract class AbstractChassisBlock extends RotatedPillarBlock implements IWrenchable, IBE, ITransformableBlock { public AbstractChassisBlock(Properties properties) { super(properties); @@ -179,13 +179,13 @@ public abstract class AbstractChassisBlock extends RotatedPillarBlock implements } @Override - public Class getTileEntityClass() { - return ChassisTileEntity.class; + public Class getBlockEntityClass() { + return ChassisBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.CHASSIS.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.CHASSIS.get(); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/chassis/ChassisBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/chassis/ChassisBlockEntity.java new file mode 100644 index 000000000..702f9148a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/chassis/ChassisBlockEntity.java @@ -0,0 +1,301 @@ +package com.simibubi.create.content.contraptions.chassis; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; +import java.util.Set; +import java.util.function.Function; + +import com.google.common.collect.ImmutableList; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllKeys; +import com.simibubi.create.content.contraptions.BlockMovementChecks; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.CenteredSideValueBoxTransform; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsBoard; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsFormatter; +import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.BulkScrollValueBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollValueBehaviour; +import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.fml.DistExecutor; + +public class ChassisBlockEntity extends SmartBlockEntity { + + ScrollValueBehaviour range; + + public int currentlySelectedRange; + + public ChassisBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + public void addBehaviours(List behaviours) { + int max = AllConfigs.server().kinetics.maxChassisRange.get(); + range = new ChassisScrollValueBehaviour(Lang.translateDirect("contraptions.chassis.range"), this, + new CenteredSideValueBoxTransform(), be -> ((ChassisBlockEntity) be).collectChassisGroup()); + range.requiresWrench(); + range.between(1, max); + range.withClientCallback( + i -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> ChassisRangeDisplay.display(this))); + range.setValue(max / 2); + range.withFormatter(s -> String.valueOf(currentlySelectedRange)); + behaviours.add(range); + currentlySelectedRange = range.getValue(); + } + + @Override + public void initialize() { + super.initialize(); + if (getBlockState().getBlock() instanceof RadialChassisBlock) + range.setLabel(Lang.translateDirect("contraptions.chassis.radius")); + } + + @Override + protected void read(CompoundTag tag, boolean clientPacket) { + super.read(tag, clientPacket); + if (clientPacket) + currentlySelectedRange = getRange(); + } + + public int getRange() { + return range.getValue(); + } + + public List getIncludedBlockPositions(Direction forcedMovement, boolean visualize) { + if (!(getBlockState().getBlock() instanceof AbstractChassisBlock)) + return Collections.emptyList(); + return isRadial() ? getIncludedBlockPositionsRadial(forcedMovement, visualize) + : getIncludedBlockPositionsLinear(forcedMovement, visualize); + } + + protected boolean isRadial() { + return level.getBlockState(worldPosition) + .getBlock() instanceof RadialChassisBlock; + } + + public List collectChassisGroup() { + Queue frontier = new LinkedList<>(); + List collected = new ArrayList<>(); + Set visited = new HashSet<>(); + frontier.add(worldPosition); + while (!frontier.isEmpty()) { + BlockPos current = frontier.poll(); + if (visited.contains(current)) + continue; + visited.add(current); + BlockEntity blockEntity = level.getBlockEntity(current); + if (blockEntity instanceof ChassisBlockEntity) { + ChassisBlockEntity chassis = (ChassisBlockEntity) blockEntity; + collected.add(chassis); + visited.add(current); + chassis.addAttachedChasses(frontier, visited); + } + } + return collected; + } + + public boolean addAttachedChasses(Queue frontier, Set visited) { + BlockState state = getBlockState(); + if (!(state.getBlock() instanceof AbstractChassisBlock)) + return false; + Axis axis = state.getValue(AbstractChassisBlock.AXIS); + if (isRadial()) { + + // Collect chain of radial chassis + for (int offset : new int[] { -1, 1 }) { + Direction direction = Direction.get(AxisDirection.POSITIVE, axis); + BlockPos currentPos = worldPosition.relative(direction, offset); + if (!level.isLoaded(currentPos)) + return false; + + BlockState neighbourState = level.getBlockState(currentPos); + if (!AllBlocks.RADIAL_CHASSIS.has(neighbourState)) + continue; + if (axis != neighbourState.getValue(BlockStateProperties.AXIS)) + continue; + if (!visited.contains(currentPos)) + frontier.add(currentPos); + } + + return true; + } + + // Collect group of connected linear chassis + for (Direction offset : Iterate.directions) { + BlockPos current = worldPosition.relative(offset); + if (visited.contains(current)) + continue; + if (!level.isLoaded(current)) + return false; + + BlockState neighbourState = level.getBlockState(current); + if (!LinearChassisBlock.isChassis(neighbourState)) + continue; + if (!LinearChassisBlock.sameKind(state, neighbourState)) + continue; + if (neighbourState.getValue(LinearChassisBlock.AXIS) != axis) + continue; + + frontier.add(current); + } + + return true; + } + + private List getIncludedBlockPositionsLinear(Direction forcedMovement, boolean visualize) { + List positions = new ArrayList<>(); + BlockState state = getBlockState(); + AbstractChassisBlock block = (AbstractChassisBlock) state.getBlock(); + Axis axis = state.getValue(AbstractChassisBlock.AXIS); + Direction facing = Direction.get(AxisDirection.POSITIVE, axis); + int chassisRange = visualize ? currentlySelectedRange : getRange(); + + for (int offset : new int[] { 1, -1 }) { + if (offset == -1) + facing = facing.getOpposite(); + boolean sticky = state.getValue(block.getGlueableSide(state, facing)); + for (int i = 1; i <= chassisRange; i++) { + BlockPos current = worldPosition.relative(facing, i); + BlockState currentState = level.getBlockState(current); + + if (forcedMovement != facing && !sticky) + break; + + // Ignore replaceable Blocks and Air-like + if (!BlockMovementChecks.isMovementNecessary(currentState, level, current)) + break; + if (BlockMovementChecks.isBrittle(currentState)) + break; + + positions.add(current); + + if (BlockMovementChecks.isNotSupportive(currentState, facing)) + break; + } + } + + return positions; + } + + private List getIncludedBlockPositionsRadial(Direction forcedMovement, boolean visualize) { + List positions = new ArrayList<>(); + BlockState state = level.getBlockState(worldPosition); + Axis axis = state.getValue(AbstractChassisBlock.AXIS); + AbstractChassisBlock block = (AbstractChassisBlock) state.getBlock(); + int chassisRange = visualize ? currentlySelectedRange : getRange(); + + for (Direction facing : Iterate.directions) { + if (facing.getAxis() == axis) + continue; + if (!state.getValue(block.getGlueableSide(state, facing))) + continue; + + BlockPos startPos = worldPosition.relative(facing); + List localFrontier = new LinkedList<>(); + Set localVisited = new HashSet<>(); + localFrontier.add(startPos); + + while (!localFrontier.isEmpty()) { + BlockPos searchPos = localFrontier.remove(0); + BlockState searchedState = level.getBlockState(searchPos); + + if (localVisited.contains(searchPos)) + continue; + if (!searchPos.closerThan(worldPosition, chassisRange + .5f)) + continue; + if (!BlockMovementChecks.isMovementNecessary(searchedState, level, searchPos)) + continue; + if (BlockMovementChecks.isBrittle(searchedState)) + continue; + + localVisited.add(searchPos); + if (!searchPos.equals(worldPosition)) + positions.add(searchPos); + + for (Direction offset : Iterate.directions) { + if (offset.getAxis() == axis) + continue; + if (searchPos.equals(worldPosition) && offset != facing) + continue; + if (BlockMovementChecks.isNotSupportive(searchedState, offset)) + continue; + + localFrontier.add(searchPos.relative(offset)); + } + } + } + + return positions; + } + + class ChassisScrollValueBehaviour extends BulkScrollValueBehaviour { + + public ChassisScrollValueBehaviour(Component label, SmartBlockEntity be, ValueBoxTransform slot, + Function> groupGetter) { + super(label, be, slot, groupGetter); + } + + @Override + public ValueSettingsBoard createBoard(Player player, BlockHitResult hitResult) { + ImmutableList rows = ImmutableList.of(Lang.translateDirect("contraptions.chassis.distance")); + ValueSettingsFormatter formatter = + new ValueSettingsFormatter(vs -> new ValueSettings(vs.row(), vs.value() + 1).format()); + return new ValueSettingsBoard(label, max - 1, 1, rows, formatter); + } + + @Override + @OnlyIn(Dist.CLIENT) + public void newSettingHovered(ValueSettings valueSetting) { + if (!level.isClientSide) + return; + if (!AllKeys.ctrlDown()) + currentlySelectedRange = valueSetting.value() + 1; + else + for (SmartBlockEntity be : getBulk()) + if (be instanceof ChassisBlockEntity cbe) + cbe.currentlySelectedRange = valueSetting.value() + 1; + ChassisRangeDisplay.display(ChassisBlockEntity.this); + } + + @Override + public void setValueSettings(Player player, ValueSettings vs, boolean ctrlHeld) { + super.setValueSettings(player, new ValueSettings(vs.row(), vs.value() + 1), ctrlHeld); + } + + @Override + public ValueSettings getValueSettings() { + ValueSettings vs = super.getValueSettings(); + return new ValueSettings(vs.row(), vs.value() - 1); + } + + @Override + public String getClipboardKey() { + return "Chassis"; + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/chassis/ChassisRangeDisplay.java b/src/main/java/com/simibubi/create/content/contraptions/chassis/ChassisRangeDisplay.java new file mode 100644 index 000000000..b55a138aa --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/chassis/ChassisRangeDisplay.java @@ -0,0 +1,205 @@ +package com.simibubi.create.content.contraptions.chassis; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import com.mojang.datafixers.util.Pair; +import com.simibubi.create.AllItems; +import com.simibubi.create.AllKeys; +import com.simibubi.create.AllSpecialTextures; +import com.simibubi.create.CreateClient; + +import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; +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.phys.BlockHitResult; +import net.minecraft.world.phys.HitResult; + +public class ChassisRangeDisplay { + + private static final int DISPLAY_TIME = 200; + private static GroupEntry lastHoveredGroup = null; + + private static class Entry { + ChassisBlockEntity be; + int timer; + + public Entry(ChassisBlockEntity be) { + this.be = be; + timer = DISPLAY_TIME; + CreateClient.OUTLINER.showCluster(getOutlineKey(), createSelection(be)) + .colored(0xFFFFFF) + .disableLineNormals() + .lineWidth(1 / 16f) + .withFaceTexture(AllSpecialTextures.HIGHLIGHT_CHECKERED); + } + + protected Object getOutlineKey() { + return Pair.of(be.getBlockPos(), 1); + } + + protected Set createSelection(ChassisBlockEntity chassis) { + Set positions = new HashSet<>(); + List includedBlockPositions = chassis.getIncludedBlockPositions(null, true); + if (includedBlockPositions == null) + return Collections.emptySet(); + positions.addAll(includedBlockPositions); + return positions; + } + + } + + private static class GroupEntry extends Entry { + + List includedBEs; + + public GroupEntry(ChassisBlockEntity be) { + super(be); + } + + @Override + protected Object getOutlineKey() { + return this; + } + + @Override + protected Set createSelection(ChassisBlockEntity chassis) { + Set list = new HashSet<>(); + includedBEs = be.collectChassisGroup(); + if (includedBEs == null) + return list; + for (ChassisBlockEntity chassisBlockEntity : includedBEs) + list.addAll(super.createSelection(chassisBlockEntity)); + return list; + } + + } + + static Map entries = new HashMap<>(); + static List groupEntries = new ArrayList<>(); + + public static void tick() { + Player player = Minecraft.getInstance().player; + Level world = Minecraft.getInstance().level; + boolean hasWrench = AllItems.WRENCH.isIn(player.getMainHandItem()); + + for (Iterator iterator = entries.keySet() + .iterator(); iterator.hasNext();) { + BlockPos pos = iterator.next(); + Entry entry = entries.get(pos); + if (tickEntry(entry, hasWrench)) + iterator.remove(); + CreateClient.OUTLINER.keep(entry.getOutlineKey()); + } + + for (Iterator iterator = groupEntries.iterator(); iterator.hasNext();) { + GroupEntry group = iterator.next(); + if (tickEntry(group, hasWrench)) { + iterator.remove(); + if (group == lastHoveredGroup) + lastHoveredGroup = null; + } + CreateClient.OUTLINER.keep(group.getOutlineKey()); + } + + if (!hasWrench) + return; + + HitResult over = Minecraft.getInstance().hitResult; + if (!(over instanceof BlockHitResult)) + return; + BlockHitResult ray = (BlockHitResult) over; + BlockPos pos = ray.getBlockPos(); + BlockEntity blockEntity = world.getBlockEntity(pos); + if (blockEntity == null || blockEntity.isRemoved()) + return; + if (!(blockEntity instanceof ChassisBlockEntity)) + return; + + boolean ctrl = AllKeys.ctrlDown(); + ChassisBlockEntity chassisBlockEntity = (ChassisBlockEntity) blockEntity; + + if (ctrl) { + GroupEntry existingGroupForPos = getExistingGroupForPos(pos); + if (existingGroupForPos != null) { + for (ChassisBlockEntity included : existingGroupForPos.includedBEs) + entries.remove(included.getBlockPos()); + existingGroupForPos.timer = DISPLAY_TIME; + return; + } + } + + if (!entries.containsKey(pos) || ctrl) + display(chassisBlockEntity); + else { + if (!ctrl) + entries.get(pos).timer = DISPLAY_TIME; + } + } + + private static boolean tickEntry(Entry entry, boolean hasWrench) { + ChassisBlockEntity chassisBlockEntity = entry.be; + Level beWorld = chassisBlockEntity.getLevel(); + Level world = Minecraft.getInstance().level; + + if (chassisBlockEntity.isRemoved() || beWorld == null || beWorld != world + || !world.isLoaded(chassisBlockEntity.getBlockPos())) { + return true; + } + + if (!hasWrench && entry.timer > 20) { + entry.timer = 20; + return false; + } + + entry.timer--; + if (entry.timer == 0) + return true; + return false; + } + + public static void display(ChassisBlockEntity chassis) { + + // Display a group and kill any selections of its contained chassis blocks + if (AllKeys.ctrlDown()) { + GroupEntry hoveredGroup = new GroupEntry(chassis); + + for (ChassisBlockEntity included : hoveredGroup.includedBEs) + CreateClient.OUTLINER.remove(Pair.of(included.getBlockPos(), 1)); + + groupEntries.forEach(entry -> CreateClient.OUTLINER.remove(entry.getOutlineKey())); + groupEntries.clear(); + entries.clear(); + groupEntries.add(hoveredGroup); + return; + } + + // Display an individual chassis and kill any group selections that contained it + BlockPos pos = chassis.getBlockPos(); + GroupEntry entry = getExistingGroupForPos(pos); + if (entry != null) + CreateClient.OUTLINER.remove(entry.getOutlineKey()); + + groupEntries.clear(); + entries.clear(); + entries.put(pos, new Entry(chassis)); + + } + + private static GroupEntry getExistingGroupForPos(BlockPos pos) { + for (GroupEntry groupEntry : groupEntries) + for (ChassisBlockEntity chassis : groupEntry.includedBEs) + if (pos.equals(chassis.getBlockPos())) + return groupEntry; + return null; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/LinearChassisBlock.java b/src/main/java/com/simibubi/create/content/contraptions/chassis/LinearChassisBlock.java similarity index 98% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/LinearChassisBlock.java rename to src/main/java/com/simibubi/create/content/contraptions/chassis/LinearChassisBlock.java index 6545e64ec..63c400bce 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/LinearChassisBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/chassis/LinearChassisBlock.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.chassis; +package com.simibubi.create.content.contraptions.chassis; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/RadialChassisBlock.java b/src/main/java/com/simibubi/create/content/contraptions/chassis/RadialChassisBlock.java similarity index 96% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/RadialChassisBlock.java rename to src/main/java/com/simibubi/create/content/contraptions/chassis/RadialChassisBlock.java index 1c0888855..f0f297c32 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/RadialChassisBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/chassis/RadialChassisBlock.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.chassis; +package com.simibubi.create.content.contraptions.chassis; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerBlock.java b/src/main/java/com/simibubi/create/content/contraptions/chassis/StickerBlock.java similarity index 93% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerBlock.java rename to src/main/java/com/simibubi/create/content/contraptions/chassis/StickerBlock.java index 2d7d0244b..d2f71a28b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/chassis/StickerBlock.java @@ -1,8 +1,8 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.chassis; +package com.simibubi.create.content.contraptions.chassis; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.block.WrenchableDirectionalBlock; import net.minecraft.core.BlockPos; @@ -26,7 +26,7 @@ import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraft.world.phys.Vec3; -public class StickerBlock extends WrenchableDirectionalBlock implements ITE { +public class StickerBlock extends WrenchableDirectionalBlock implements IBE { public static final BooleanProperty POWERED = BlockStateProperties.POWERED; public static final BooleanProperty EXTENDED = BlockStateProperties.EXTENDED; @@ -75,13 +75,13 @@ public class StickerBlock extends WrenchableDirectionalBlock implements ITE getTileEntityClass() { - return StickerTileEntity.class; + public Class getBlockEntityClass() { + return StickerBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.STICKER.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.STICKER.get(); } // Slime block stuff diff --git a/src/main/java/com/simibubi/create/content/contraptions/chassis/StickerBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/chassis/StickerBlockEntity.java new file mode 100644 index 000000000..8b4454bea --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/chassis/StickerBlockEntity.java @@ -0,0 +1,102 @@ +package com.simibubi.create.content.contraptions.chassis; + +import java.util.List; + +import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.content.contraptions.glue.SuperGlueEntity; +import com.simibubi.create.content.contraptions.glue.SuperGlueItem; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; + +import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.fml.DistExecutor; + +public class StickerBlockEntity extends SmartBlockEntity { + + LerpedFloat piston; + boolean update; + + public StickerBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + piston = LerpedFloat.linear(); + update = false; + } + + @Override + public void addBehaviours(List behaviours) {} + + @Override + public void initialize() { + super.initialize(); + if (!level.isClientSide) + return; + piston.startWithValue(isBlockStateExtended() ? 1 : 0); + } + + public boolean isBlockStateExtended() { + BlockState blockState = getBlockState(); + boolean extended = AllBlocks.STICKER.has(blockState) && blockState.getValue(StickerBlock.EXTENDED); + return extended; + } + + @Override + public void tick() { + super.tick(); + if (!level.isClientSide) + return; + piston.tickChaser(); + + if (isAttachedToBlock() && piston.getValue(0) != piston.getValue() && piston.getValue() == 1) { + SuperGlueItem.spawnParticles(level, worldPosition, getBlockState().getValue(StickerBlock.FACING), true); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> playSound(true)); + } + + if (!update) + return; + update = false; + int target = isBlockStateExtended() ? 1 : 0; + if (isAttachedToBlock() && target == 0 && piston.getChaseTarget() == 1) + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> playSound(false)); + piston.chase(target, .4f, Chaser.LINEAR); + + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(this)); + } + + public boolean isAttachedToBlock() { + BlockState blockState = getBlockState(); + if (!AllBlocks.STICKER.has(blockState)) + return false; + Direction direction = blockState.getValue(StickerBlock.FACING); + return SuperGlueEntity.isValidFace(level, worldPosition.relative(direction), direction.getOpposite()); + } + + @Override + protected void write(CompoundTag tag, boolean clientPacket) { + super.write(tag, clientPacket); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + super.read(compound, clientPacket); + if (clientPacket) + update = true; + } + + @OnlyIn(Dist.CLIENT) + public void playSound(boolean attach) { + AllSoundEvents.SLIME_ADDED.play(level, Minecraft.getInstance().player, worldPosition, 0.35f, attach ? 0.75f : 0.2f); + } + + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerInstance.java b/src/main/java/com/simibubi/create/content/contraptions/chassis/StickerInstance.java similarity index 79% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerInstance.java rename to src/main/java/com/simibubi/create/content/contraptions/chassis/StickerInstance.java index e94e2b5ce..4b4c4a262 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/chassis/StickerInstance.java @@ -1,10 +1,10 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.chassis; +package com.simibubi.create.content.contraptions.chassis; import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.api.instance.DynamicInstance; import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance; import com.jozufozu.flywheel.core.materials.model.ModelData; -import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.AllPartialModels; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AnimationTickHolder; @@ -12,7 +12,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.core.Direction; import net.minecraft.util.Mth; -public class StickerInstance extends BlockEntityInstance implements DynamicInstance { +public class StickerInstance extends BlockEntityInstance implements DynamicInstance { float lastOffset = Float.NaN; final Direction facing; @@ -21,12 +21,12 @@ public class StickerInstance extends BlockEntityInstance impl private final ModelData head; - public StickerInstance(MaterialManager modelManager, StickerTileEntity tile) { - super(modelManager, tile); + public StickerInstance(MaterialManager materialManager, StickerBlockEntity blockEntity) { + super(materialManager, blockEntity); - head = getTransformMaterial().getModel(AllBlockPartials.STICKER_HEAD, blockState).createInstance(); + head = getTransformMaterial().getModel(AllPartialModels.STICKER_HEAD, blockState).createInstance(); - fakeWorld = tile.getLevel() != Minecraft.getInstance().level; + fakeWorld = blockEntity.getLevel() != Minecraft.getInstance().level; facing = blockState.getValue(StickerBlock.FACING); offset = blockState.getValue(StickerBlock.EXTENDED) ? 1 : 0; diff --git a/src/main/java/com/simibubi/create/content/contraptions/chassis/StickerRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/chassis/StickerRenderer.java new file mode 100644 index 000000000..846663029 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/chassis/StickerRenderer.java @@ -0,0 +1,49 @@ +package com.simibubi.create.content.contraptions.chassis; + +import com.jozufozu.flywheel.backend.Backend; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.AnimationTickHolder; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.state.BlockState; + +public class StickerRenderer extends SafeBlockEntityRenderer { + + public StickerRenderer(BlockEntityRendererProvider.Context context) { + } + + @Override + protected void renderSafe(StickerBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + + if (Backend.canUseInstancing(be.getLevel())) return; + + BlockState state = be.getBlockState(); + SuperByteBuffer head = CachedBufferer.partial(AllPartialModels.STICKER_HEAD, state); + float offset = be.piston.getValue(AnimationTickHolder.getPartialTicks(be.getLevel())); + + if (be.getLevel() != Minecraft.getInstance().level && !be.isVirtual()) + offset = state.getValue(StickerBlock.EXTENDED) ? 1 : 0; + + Direction facing = state.getValue(StickerBlock.FACING); + head.nudge(be.hashCode()) + .centre() + .rotateY(AngleHelper.horizontalAngle(facing)) + .rotateX(AngleHelper.verticalAngle(facing) + 90) + .unCentre() + .translate(0, (offset * offset) * 4 / 16f, 0); + + head.light(light) + .renderInto(ms, buffer.getBuffer(RenderType.solid())); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/AttachedActorBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/AttachedActorBlock.java deleted file mode 100644 index 4ec3b6aa1..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/AttachedActorBlock.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.simibubi.create.content.contraptions.components.actors; - -import javax.annotation.ParametersAreNonnullByDefault; - -import com.simibubi.create.AllShapes; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; -import com.simibubi.create.foundation.utility.BlockHelper; - -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.item.context.UseOnContext; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.HorizontalDirectionalBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition.Builder; -import net.minecraft.world.level.pathfinder.PathComputationType; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.VoxelShape; - -@ParametersAreNonnullByDefault -@MethodsReturnNonnullByDefault -public abstract class AttachedActorBlock extends HorizontalDirectionalBlock implements IWrenchable { - - protected AttachedActorBlock(Properties p_i48377_1_) { - super(p_i48377_1_); - } - - @Override - public InteractionResult onWrenched(BlockState state, UseOnContext context) { - return InteractionResult.FAIL; - } - - @Override - public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) { - Direction direction = state.getValue(FACING); - return AllShapes.HARVESTER_BASE.get(direction); - } - - @Override - protected void createBlockStateDefinition(Builder builder) { - builder.add(FACING); - super.createBlockStateDefinition(builder); - } - - @Override - public boolean canSurvive(BlockState state, LevelReader worldIn, BlockPos pos) { - Direction direction = state.getValue(FACING); - BlockPos offset = pos.relative(direction.getOpposite()); - return BlockHelper.hasBlockSolidSide(worldIn.getBlockState(offset), worldIn, offset, direction); - } - - @Override - public BlockState getStateForPlacement(BlockPlaceContext context) { - Direction facing; - if (context.getClickedFace().getAxis().isVertical()) - facing = context.getHorizontalDirection().getOpposite(); - else { - BlockState blockState = - context.getLevel().getBlockState(context.getClickedPos().relative(context.getClickedFace().getOpposite())); - if (blockState.getBlock() instanceof AttachedActorBlock) - facing = blockState.getValue(FACING); - else - facing = context.getClickedFace(); - } - return defaultBlockState().setValue(FACING, facing); - } - - @Override - public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) { - return false; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/BellMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/BellMovementBehaviour.java deleted file mode 100644 index e521fdfad..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/BellMovementBehaviour.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.simibubi.create.content.contraptions.components.actors; - -import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; -import com.simibubi.create.content.curiosities.bell.AbstractBellBlock; -import com.simibubi.create.content.logistics.trains.entity.CarriageContraption; - -import net.minecraft.core.BlockPos; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.phys.Vec3; - -public class BellMovementBehaviour implements MovementBehaviour { - - @Override - public boolean renderAsNormalTileEntity() { - return true; - } - - @Override - public boolean isActive(MovementContext context) { - return !(context.contraption instanceof CarriageContraption); - } - - @Override - public void onSpeedChanged(MovementContext context, Vec3 oldMotion, Vec3 motion) { - double dotProduct = oldMotion.dot(motion); - - if (dotProduct <= 0 && (context.relativeMotion.length() != 0) || context.firstMovement) - playSound(context); - } - - @Override - public void stopMoving(MovementContext context) { - if (context.position != null && isActive(context)) - playSound(context); - } - - public static void playSound(MovementContext context) { - Level world = context.world; - BlockPos pos = new BlockPos(context.position); - Block block = context.state.getBlock(); - - if (block instanceof AbstractBellBlock) { - ((AbstractBellBlock) block).playSound(world, pos); - } else { - // Vanilla bell sound - world.playSound(null, pos, SoundEvents.BELL_BLOCK, - SoundSource.BLOCKS, 2f, 1f); - } - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/BlockBreakingKineticTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/BlockBreakingKineticTileEntity.java deleted file mode 100644 index 5e1fb49f2..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/BlockBreakingKineticTileEntity.java +++ /dev/null @@ -1,159 +0,0 @@ -package com.simibubi.create.content.contraptions.components.actors; - -import java.util.concurrent.atomic.AtomicInteger; - -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.foundation.utility.BlockHelper; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtUtils; -import net.minecraft.sounds.SoundSource; -import net.minecraft.util.Mth; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.level.GameRules; -import net.minecraft.world.level.block.AirBlock; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; - -public abstract class BlockBreakingKineticTileEntity extends KineticTileEntity { - - public static final AtomicInteger NEXT_BREAKER_ID = new AtomicInteger(); - protected int ticksUntilNextProgress; - protected int destroyProgress; - protected int breakerId = -NEXT_BREAKER_ID.incrementAndGet(); - protected BlockPos breakingPos; - - public BlockBreakingKineticTileEntity(BlockEntityType typeIn, BlockPos pos, BlockState state) { - super(typeIn, pos, state); - } - - @Override - public void onSpeedChanged(float prevSpeed) { - super.onSpeedChanged(prevSpeed); - if (destroyProgress == -1) - destroyNextTick(); - } - - @Override - public void lazyTick() { - super.lazyTick(); - if (ticksUntilNextProgress == -1) - destroyNextTick(); - } - - public void destroyNextTick() { - ticksUntilNextProgress = 1; - } - - protected abstract BlockPos getBreakingPos(); - - protected boolean shouldRun() { - return true; - } - - @Override - public void write(CompoundTag compound, boolean clientPacket) { - compound.putInt("Progress", destroyProgress); - compound.putInt("NextTick", ticksUntilNextProgress); - if (breakingPos != null) - compound.put("Breaking", NbtUtils.writeBlockPos(breakingPos)); - super.write(compound, clientPacket); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - destroyProgress = compound.getInt("Progress"); - ticksUntilNextProgress = compound.getInt("NextTick"); - if (compound.contains("Breaking")) - breakingPos = NbtUtils.readBlockPos(compound.getCompound("Breaking")); - super.read(compound, clientPacket); - } - - @Override - public void invalidate() { - super.invalidate(); - if (!level.isClientSide && destroyProgress != 0) - level.destroyBlockProgress(breakerId, breakingPos, -1); - } - - @Override - public void tick() { - super.tick(); - - if (level.isClientSide) - return; - if (!shouldRun()) - return; - if (getSpeed() == 0) - return; - - breakingPos = getBreakingPos(); - - if (ticksUntilNextProgress < 0) - return; - if (ticksUntilNextProgress-- > 0) - return; - - BlockState stateToBreak = level.getBlockState(breakingPos); - float blockHardness = stateToBreak.getDestroySpeed(level, breakingPos); - - if (!canBreak(stateToBreak, blockHardness)) { - if (destroyProgress != 0) { - destroyProgress = 0; - level.destroyBlockProgress(breakerId, breakingPos, -1); - } - return; - } - - float breakSpeed = getBreakSpeed(); - destroyProgress += Mth.clamp((int) (breakSpeed / blockHardness), 1, 10 - destroyProgress); - level.playSound(null, worldPosition, stateToBreak.getSoundType() - .getHitSound(), SoundSource.NEUTRAL, .25f, 1); - - if (destroyProgress >= 10) { - onBlockBroken(stateToBreak); - destroyProgress = 0; - ticksUntilNextProgress = -1; - level.destroyBlockProgress(breakerId, breakingPos, -1); - return; - } - - ticksUntilNextProgress = (int) (blockHardness / breakSpeed); - level.destroyBlockProgress(breakerId, breakingPos, (int) destroyProgress); - } - - public boolean canBreak(BlockState stateToBreak, float blockHardness) { - return isBreakable(stateToBreak, blockHardness); - } - - public static boolean isBreakable(BlockState stateToBreak, float blockHardness) { - return !(stateToBreak.getMaterial() - .isLiquid() || stateToBreak.getBlock() instanceof AirBlock || blockHardness == -1); - } - - public void onBlockBroken(BlockState stateToBreak) { - Vec3 vec = VecHelper.offsetRandomly(VecHelper.getCenterOf(breakingPos), level.random, .125f); - BlockHelper.destroyBlock(level, breakingPos, 1f, (stack) -> { - if (stack.isEmpty()) - return; - if (!level.getGameRules() - .getBoolean(GameRules.RULE_DOBLOCKDROPS)) - return; - if (level.restoringBlockSnapshots) - return; - - ItemEntity itementity = new ItemEntity(level, vec.x, vec.y, vec.z, stack); - itementity.setDefaultPickUpDelay(); - itementity.setDeltaMovement(Vec3.ZERO); - level.addFreshEntity(itementity); - }); - } - - protected float getBreakSpeed() { - return Math.abs(getSpeed() / 100f); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/CampfireMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/CampfireMovementBehaviour.java deleted file mode 100644 index 7668f7b67..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/CampfireMovementBehaviour.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.simibubi.create.content.contraptions.components.actors; - -import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; - -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.util.RandomSource; -import net.minecraft.world.level.block.CampfireBlock; - -public class CampfireMovementBehaviour implements MovementBehaviour { - @Override - public boolean renderAsNormalTileEntity() { - return true; - } - - @Override - public void tick(MovementContext context) { - if (context.world == null || !context.world.isClientSide || context.position == null - || !context.state.getValue(CampfireBlock.LIT)) - return; - - // Mostly copied from CampfireBlock and CampfireTileEntity - RandomSource random = context.world.random; - if (random.nextFloat() < 0.11F) { - for (int i = 0; i < random.nextInt(2) + 2; ++i) { - context.world.addAlwaysVisibleParticle( - context.state.getValue(CampfireBlock.SIGNAL_FIRE) ? ParticleTypes.CAMPFIRE_SIGNAL_SMOKE - : ParticleTypes.CAMPFIRE_COSY_SMOKE, - true, context.position.x() + random.nextDouble() / (random.nextBoolean() ? 3D : -3D), - context.position.y() + random.nextDouble() + random.nextDouble(), - context.position.z() + random.nextDouble() / (random.nextBoolean() ? 3D : -3D), 0.0D, 0.07D, - 0.0D); - } - } - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillBlock.java deleted file mode 100644 index 39915dcbc..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillBlock.java +++ /dev/null @@ -1,136 +0,0 @@ -package com.simibubi.create.content.contraptions.components.actors; - -import javax.annotation.ParametersAreNonnullByDefault; - -import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock; -import com.simibubi.create.foundation.block.ITE; - -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.util.Mth; -import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.item.ItemEntity; -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.LevelReader; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.SimpleWaterloggedBlock; -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.BlockStateProperties; -import net.minecraft.world.level.material.FluidState; -import net.minecraft.world.level.material.Fluids; -import net.minecraft.world.level.material.PushReaction; -import net.minecraft.world.level.pathfinder.PathComputationType; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.VoxelShape; - -@ParametersAreNonnullByDefault -@MethodsReturnNonnullByDefault -public class DrillBlock extends DirectionalKineticBlock implements ITE, SimpleWaterloggedBlock { - public static DamageSource damageSourceDrill = new DamageSource("create.mechanical_drill").bypassArmor(); - - public DrillBlock(Properties properties) { - super(properties); - registerDefaultState(super.defaultBlockState().setValue(BlockStateProperties.WATERLOGGED, false)); - } - - @Override - public void entityInside(BlockState state, Level worldIn, BlockPos pos, Entity entityIn) { - if (entityIn instanceof ItemEntity) - return; - if (!new AABB(pos).deflate(.1f) - .intersects(entityIn.getBoundingBox())) - return; - withTileEntityDo(worldIn, pos, te -> { - if (te.getSpeed() == 0) - return; - entityIn.hurt(damageSourceDrill, (float) getDamage(te.getSpeed())); - }); - } - - @Override - public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) { - return AllShapes.CASING_12PX.get(state.getValue(FACING)); - } - - @Override - public void neighborChanged(BlockState state, Level worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, - boolean isMoving) { - withTileEntityDo(worldIn, pos, DrillTileEntity::destroyNextTick); - } - - @Override - public Axis getRotationAxis(BlockState state) { - return state.getValue(FACING) - .getAxis(); - } - - @Override - public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) { - return face == state.getValue(FACING) - .getOpposite(); - } - - @Override - public PushReaction getPistonPushReaction(BlockState state) { - return PushReaction.NORMAL; - } - - @Override - public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) { - return false; - } - - @Override - public FluidState getFluidState(BlockState state) { - return state.getValue(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getSource(false) : Fluids.EMPTY.defaultFluidState(); - } - - @Override - protected void createBlockStateDefinition(StateDefinition.Builder builder) { - builder.add(BlockStateProperties.WATERLOGGED); - super.createBlockStateDefinition(builder); - } - - @Override - public BlockState updateShape(BlockState state, Direction direction, BlockState neighbourState, - LevelAccessor world, BlockPos pos, BlockPos neighbourPos) { - if (state.getValue(BlockStateProperties.WATERLOGGED)) - world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world)); - return state; - } - - @Override - public BlockState getStateForPlacement(BlockPlaceContext context) { - FluidState FluidState = context.getLevel().getFluidState(context.getClickedPos()); - return super.getStateForPlacement(context).setValue(BlockStateProperties.WATERLOGGED, Boolean.valueOf(FluidState.getType() == Fluids.WATER)); - } - - public static double getDamage(float speed) { - float speedAbs = Math.abs(speed); - double sub1 = Math.min(speedAbs / 16, 2); - double sub2 = Math.min(speedAbs / 32, 4); - double sub3 = Math.min(speedAbs / 64, 4); - return Mth.clamp(sub1 + sub2 + sub3, 1, 10); - } - - @Override - public Class getTileEntityClass() { - return DrillTileEntity.class; - } - - @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.DRILL.get(); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillInstance.java deleted file mode 100644 index cf949ebd4..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillInstance.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.simibubi.create.content.contraptions.components.actors; - -import com.jozufozu.flywheel.api.Instancer; -import com.jozufozu.flywheel.api.MaterialManager; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.SingleRotatingInstance; -import com.simibubi.create.content.contraptions.base.flwdata.RotatingData; - -import net.minecraft.core.Direction; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; - -public class DrillInstance extends SingleRotatingInstance { - - public DrillInstance(MaterialManager modelManager, KineticTileEntity tile) { - super(modelManager, tile); - } - - @Override - protected Instancer getModel() { - BlockState referenceState = blockEntity.getBlockState(); - Direction facing = referenceState.getValue(BlockStateProperties.FACING); - return getRotatingMaterial().getModel(AllBlockPartials.DRILL_HEAD, referenceState, facing); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillMovementBehaviour.java deleted file mode 100644 index 89ebb9582..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillMovementBehaviour.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.simibubi.create.content.contraptions.components.actors; - -import javax.annotation.Nullable; - -import com.jozufozu.flywheel.api.MaterialManager; -import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; -import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.core.BlockPos; -import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -public class DrillMovementBehaviour extends BlockBreakingMovementBehaviour { - - @Override - public boolean isActive(MovementContext context) { - return !VecHelper.isVecPointingTowards(context.relativeMotion, context.state.getValue(DrillBlock.FACING) - .getOpposite()); - } - - @Override - public Vec3 getActiveAreaOffset(MovementContext context) { - return Vec3.atLowerCornerOf(context.state.getValue(DrillBlock.FACING) - .getNormal()).scale(.65f); - } - - @Override - @OnlyIn(value = Dist.CLIENT) - public void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld, - ContraptionMatrices matrices, MultiBufferSource buffer) { - if (!ContraptionRenderDispatcher.canInstance()) - DrillRenderer.renderInContraption(context, renderWorld, matrices, buffer); - } - - @Override - public boolean hasSpecialInstancedRendering() { - return true; - } - - @Nullable - @Override - public ActorInstance createInstance(MaterialManager materialManager, VirtualRenderWorld simulationWorld, MovementContext context) { - return new DrillActorInstance(materialManager, simulationWorld, context); - } - - @Override - protected DamageSource getDamageSource() { - return DrillBlock.damageSourceDrill; - } - - @Override - public boolean canBreak(Level world, BlockPos breakingPos, BlockState state) { - return super.canBreak(world, breakingPos, state) && !state.getCollisionShape(world, breakingPos) - .isEmpty() && !AllBlocks.TRACK.has(state); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillRenderer.java deleted file mode 100644 index 28140233b..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillRenderer.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.simibubi.create.content.contraptions.components.actors; - -import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.Direction; -import net.minecraft.world.level.block.state.BlockState; - -public class DrillRenderer extends KineticTileEntityRenderer { - - public DrillRenderer(BlockEntityRendererProvider.Context context) { - super(context); - } - - @Override - protected SuperByteBuffer getRotatedModel(KineticTileEntity te, BlockState state) { - return CachedBufferer.partialFacing(AllBlockPartials.DRILL_HEAD, state); - } - - public static void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld, - ContraptionMatrices matrices, MultiBufferSource buffer) { - BlockState state = context.state; - SuperByteBuffer superBuffer = CachedBufferer.partial(AllBlockPartials.DRILL_HEAD, state); - Direction facing = state.getValue(DrillBlock.FACING); - - float speed = (float) (context.contraption.stalled - || !VecHelper.isVecPointingTowards(context.relativeMotion, facing - .getOpposite()) ? context.getAnimationSpeed() : 0); - float time = AnimationTickHolder.getRenderTime() / 20; - float angle = (float) (((time * speed) % 360)); - - superBuffer - .transform(matrices.getModel()) - .centre() - .rotateY(AngleHelper.horizontalAngle(facing)) - .rotateX(AngleHelper.verticalAngle(facing)) - .rotateZ(angle) - .unCentre() - .light(matrices.getWorld(), - ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) - .renderInto(matrices.getViewProjection(), buffer.getBuffer(RenderType.solid())); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillTileEntity.java deleted file mode 100644 index 8879fa80d..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillTileEntity.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.simibubi.create.content.contraptions.components.actors; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; - -public class DrillTileEntity extends BlockBreakingKineticTileEntity { - - public DrillTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - @Override - protected BlockPos getBreakingPos() { - return getBlockPos().relative(getBlockState().getValue(DrillBlock.FACING)); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterActorInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterActorInstance.java deleted file mode 100644 index de07acdd9..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterActorInstance.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.simibubi.create.content.contraptions.components.actors; - -import com.jozufozu.flywheel.api.Material; -import com.jozufozu.flywheel.api.MaterialManager; -import com.jozufozu.flywheel.core.Materials; -import com.jozufozu.flywheel.core.materials.model.ModelData; -import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.core.Direction; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.phys.Vec3; - -public class HarvesterActorInstance extends ActorInstance { - static double oneOverRadius = 16.0 / 6.5; - static float originOffset = 1 / 16f; - static Vec3 rotOffset = new Vec3(0.5f, -2 * originOffset + 0.5f, originOffset + 0.5f); - - - ModelData harvester; - private Direction facing; - - private float horizontalAngle; - - private double rotation; - private double previousRotation; - - public HarvesterActorInstance(MaterialManager materialManager, VirtualRenderWorld simulationWorld, MovementContext context) { - super(materialManager, simulationWorld, context); - - Material material = materialManager.defaultCutout() - .material(Materials.TRANSFORMED); - - BlockState state = context.state; - - facing = state.getValue(BlockStateProperties.HORIZONTAL_FACING); - - harvester = material.getModel(AllBlockPartials.HARVESTER_BLADE, state).createInstance(); - - horizontalAngle = facing.toYRot() + ((facing.getAxis() == Direction.Axis.X) ? 180 : 0); - - harvester.setBlockLight(localBlockLight()); - } - - @Override - public void tick() { - super.tick(); - - previousRotation = rotation; - - if (context.contraption.stalled || VecHelper.isVecPointingTowards(context.relativeMotion, facing.getOpposite())) - return; - - double arcLength = context.motion.length(); - - double radians = arcLength * oneOverRadius; - - float deg = AngleHelper.deg(radians); - - deg = (float) (((int) (deg * 3000)) / 3000); - - rotation += deg * 1.25; - - rotation %= 360; - } - - @Override - public void beginFrame() { - harvester.loadIdentity() - .translate(context.localPos) - .centre() - .rotateY(horizontalAngle) - .unCentre() - .translate(rotOffset) - .rotateX(getRotation()) - .translateBack(rotOffset); - } - - private double getRotation() { - return AngleHelper.angleLerp(AnimationTickHolder.getPartialTicks(), previousRotation, rotation); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterBlock.java deleted file mode 100644 index b5f4fd566..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterBlock.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.simibubi.create.content.contraptions.components.actors; - -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.foundation.block.ITE; - -import net.minecraft.world.level.block.entity.BlockEntityType; - -public class HarvesterBlock extends AttachedActorBlock implements ITE { - - public HarvesterBlock(Properties p_i48377_1_) { - super(p_i48377_1_); - } - - @Override - public Class getTileEntityClass() { - return HarvesterTileEntity.class; - } - - @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.HARVESTER.get(); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterRenderer.java deleted file mode 100644 index 0fbe0c3d8..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterRenderer.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.simibubi.create.content.contraptions.components.actors; - -import static net.minecraft.world.level.block.state.properties.BlockStateProperties.HORIZONTAL_FACING; - -import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; - -public class HarvesterRenderer extends SafeTileEntityRenderer { - - public HarvesterRenderer(BlockEntityRendererProvider.Context context) { - } - - @Override - protected void renderSafe(HarvesterTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - BlockState blockState = te.getBlockState(); - SuperByteBuffer superBuffer = CachedBufferer.partial(AllBlockPartials.HARVESTER_BLADE, blockState); - transform(te.getLevel(), blockState.getValue(HarvesterBlock.FACING), superBuffer, - te.getAnimatedSpeed()); - superBuffer.light(light) - .renderInto(ms, buffer.getBuffer(RenderType.cutoutMipped())); - } - - public static void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld, - ContraptionMatrices matrices, MultiBufferSource buffers) { - BlockState blockState = context.state; - Direction facing = blockState.getValue(HORIZONTAL_FACING); - SuperByteBuffer superBuffer = CachedBufferer.partial(AllBlockPartials.HARVESTER_BLADE, blockState); - float speed = (float) (!VecHelper.isVecPointingTowards(context.relativeMotion, facing.getOpposite()) - ? context.getAnimationSpeed() - : 0); - if (context.contraption.stalled) - speed = 0; - - superBuffer.transform(matrices.getModel()); - transform(context.world, facing, superBuffer, speed); - - superBuffer - .light(matrices.getWorld(), - ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) - .renderInto(matrices.getViewProjection(), buffers.getBuffer(RenderType.cutoutMipped())); - } - - public static void transform(Level world, Direction facing, SuperByteBuffer superBuffer, float speed) { - float originOffset = 1 / 16f; - Vec3 rotOffset = new Vec3(0, -2 * originOffset, originOffset).add(VecHelper.getCenterOf(BlockPos.ZERO)); - float time = AnimationTickHolder.getRenderTime(world) / 20; - float angle = (time * speed) % 360; - - superBuffer.rotateCentered(Direction.UP, AngleHelper.rad(AngleHelper.horizontalAngle(facing))) - .translate(rotOffset.x, rotOffset.y, rotOffset.z) - .rotate(Direction.WEST, AngleHelper.rad(angle)) - .translate(-rotOffset.x, -rotOffset.y, -rotOffset.z); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterTileEntity.java deleted file mode 100644 index 93dc35fa3..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterTileEntity.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.simibubi.create.content.contraptions.components.actors; - -import com.simibubi.create.foundation.tileEntity.CachedRenderBBTileEntity; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.AABB; - -public class HarvesterTileEntity extends CachedRenderBBTileEntity { - - // For simulations such as Ponder - private float manuallyAnimatedSpeed; - - public HarvesterTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - @Override - protected AABB createRenderBoundingBox() { - return new AABB(worldPosition); - } - - public float getAnimatedSpeed() { - return manuallyAnimatedSpeed; - } - - public void setAnimatedSpeed(float speed) { - manuallyAnimatedSpeed = speed; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableFluidInterfaceTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableFluidInterfaceTileEntity.java deleted file mode 100644 index ec1b2ff60..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableFluidInterfaceTileEntity.java +++ /dev/null @@ -1,120 +0,0 @@ -package com.simibubi.create.content.contraptions.components.actors; - -import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.capability.IFluidHandler; -import net.minecraftforge.fluids.capability.templates.FluidTank; - -public class PortableFluidInterfaceTileEntity extends PortableStorageInterfaceTileEntity { - - protected LazyOptional capability; - - public PortableFluidInterfaceTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - capability = createEmptyHandler(); - } - - @Override - public void startTransferringTo(Contraption contraption, float distance) { - LazyOptional oldcap = capability; - capability = LazyOptional.of(() -> new InterfaceFluidHandler(contraption.getSharedFluidTanks())); - oldcap.invalidate(); - super.startTransferringTo(contraption, distance); - } - - @Override - protected void invalidateCapability() { - capability.invalidate(); - } - - @Override - protected void stopTransferring() { - LazyOptional oldcap = capability; - capability = createEmptyHandler(); - oldcap.invalidate(); - super.stopTransferring(); - } - - private LazyOptional createEmptyHandler() { - return LazyOptional.of(() -> new InterfaceFluidHandler(new FluidTank(0))); - } - - @Override - public LazyOptional getCapability(Capability cap, Direction side) { - if (isFluidHandlerCap(cap)) - return capability.cast(); - return super.getCapability(cap, side); - } - - public class InterfaceFluidHandler implements IFluidHandler { - - private IFluidHandler wrapped; - - public InterfaceFluidHandler(IFluidHandler wrapped) { - this.wrapped = wrapped; - } - - @Override - public int getTanks() { - return wrapped.getTanks(); - } - - @Override - public FluidStack getFluidInTank(int tank) { - return wrapped.getFluidInTank(tank); - } - - @Override - public int getTankCapacity(int tank) { - return wrapped.getTankCapacity(tank); - } - - @Override - public boolean isFluidValid(int tank, FluidStack stack) { - return wrapped.isFluidValid(tank, stack); - } - - @Override - public int fill(FluidStack resource, FluidAction action) { - if (!isConnected()) - return 0; - int fill = wrapped.fill(resource, action); - if (fill > 0 && action.execute()) - keepAlive(); - return fill; - } - - @Override - public FluidStack drain(FluidStack resource, FluidAction action) { - if (!canTransfer()) - return FluidStack.EMPTY; - FluidStack drain = wrapped.drain(resource, action); - if (!drain.isEmpty() && action.execute()) - keepAlive(); - return drain; - } - - @Override - public FluidStack drain(int maxDrain, FluidAction action) { - if (!canTransfer()) - return FluidStack.EMPTY; - FluidStack drain = wrapped.drain(maxDrain, action); - if (!drain.isEmpty() && action.execute()) - keepAlive(); - return drain; - } - - public void keepAlive() { - onContentTransferred(); - } - - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableItemInterfaceTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableItemInterfaceTileEntity.java deleted file mode 100644 index d729c6180..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableItemInterfaceTileEntity.java +++ /dev/null @@ -1,85 +0,0 @@ -package com.simibubi.create.content.contraptions.components.actors; - -import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; -import com.simibubi.create.foundation.item.ItemHandlerWrapper; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.ItemStackHandler; - -public class PortableItemInterfaceTileEntity extends PortableStorageInterfaceTileEntity { - - protected LazyOptional capability; - - public PortableItemInterfaceTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - capability = createEmptyHandler(); - } - - @Override - public void startTransferringTo(Contraption contraption, float distance) { - LazyOptional oldCap = capability; - capability = LazyOptional.of(() -> new InterfaceItemHandler(contraption.getSharedInventory())); - oldCap.invalidate(); - super.startTransferringTo(contraption, distance); - } - - @Override - protected void stopTransferring() { - LazyOptional oldCap = capability; - capability = createEmptyHandler(); - oldCap.invalidate(); - super.stopTransferring(); - } - - private LazyOptional createEmptyHandler() { - return LazyOptional.of(() -> new InterfaceItemHandler(new ItemStackHandler(0))); - } - - @Override - protected void invalidateCapability() { - capability.invalidate(); - } - - @Override - public LazyOptional getCapability(Capability cap, Direction side) { - if (isItemHandlerCap(cap)) - return capability.cast(); - return super.getCapability(cap, side); - } - - class InterfaceItemHandler extends ItemHandlerWrapper { - - public InterfaceItemHandler(IItemHandlerModifiable wrapped) { - super(wrapped); - } - - @Override - public ItemStack extractItem(int slot, int amount, boolean simulate) { - if (!canTransfer()) - return ItemStack.EMPTY; - ItemStack extractItem = super.extractItem(slot, amount, simulate); - if (!simulate && !extractItem.isEmpty()) - onContentTransferred(); - return extractItem; - } - - @Override - public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) { - if (!canTransfer()) - return stack; - ItemStack insertItem = super.insertItem(slot, stack, simulate); - if (!simulate && !insertItem.equals(stack, false)) - onContentTransferred(); - return insertItem; - } - - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceRenderer.java deleted file mode 100644 index 051f63086..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceRenderer.java +++ /dev/null @@ -1,118 +0,0 @@ -package com.simibubi.create.content.contraptions.components.actors; - -import java.util.function.Consumer; - -import com.jozufozu.flywheel.backend.Backend; -import com.jozufozu.flywheel.core.PartialModel; -import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.NbtUtils; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; - -public class PortableStorageInterfaceRenderer extends SafeTileEntityRenderer { - - public PortableStorageInterfaceRenderer(BlockEntityRendererProvider.Context context) {} - - @Override - protected void renderSafe(PortableStorageInterfaceTileEntity te, float partialTicks, PoseStack ms, - MultiBufferSource buffer, int light, int overlay) { - if (Backend.canUseInstancing(te.getLevel())) - return; - - BlockState blockState = te.getBlockState(); - float progress = te.getExtensionDistance(partialTicks); - VertexConsumer vb = buffer.getBuffer(RenderType.solid()); - render(blockState, te.isConnected(), progress, null, sbb -> sbb.light(light) - .renderInto(ms, vb)); - } - - public static void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld, - ContraptionMatrices matrices, MultiBufferSource buffer) { - BlockState blockState = context.state; - VertexConsumer vb = buffer.getBuffer(RenderType.solid()); - float renderPartialTicks = AnimationTickHolder.getPartialTicks(); - - LerpedFloat animation = PortableStorageInterfaceMovement.getAnimation(context); - float progress = animation.getValue(renderPartialTicks); - boolean lit = animation.settled(); - render(blockState, lit, progress, matrices.getModel(), - sbb -> sbb - .light(matrices.getWorld(), ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) - .renderInto(matrices.getViewProjection(), vb)); - } - - private static void render(BlockState blockState, boolean lit, float progress, PoseStack local, - Consumer drawCallback) { - SuperByteBuffer middle = CachedBufferer.partial(getMiddleForState(blockState, lit), blockState); - SuperByteBuffer top = CachedBufferer.partial(getTopForState(blockState), blockState); - - if (local != null) { - middle.transform(local); - top.transform(local); - } - Direction facing = blockState.getValue(PortableStorageInterfaceBlock.FACING); - rotateToFacing(middle, facing); - rotateToFacing(top, facing); - middle.translate(0, progress * 0.5f + 0.375f, 0); - top.translate(0, progress, 0); - - drawCallback.accept(middle); - drawCallback.accept(top); - } - - private static void rotateToFacing(SuperByteBuffer buffer, Direction facing) { - buffer.centre() - .rotateY(AngleHelper.horizontalAngle(facing)) - .rotateX(facing == Direction.UP ? 0 : facing == Direction.DOWN ? 180 : 90) - .unCentre(); - } - - static PortableStorageInterfaceTileEntity getTargetPSI(MovementContext context) { - String _workingPos_ = PortableStorageInterfaceMovement._workingPos_; - if (!context.data.contains(_workingPos_)) - return null; - - BlockPos pos = NbtUtils.readBlockPos(context.data.getCompound(_workingPos_)); - BlockEntity tileEntity = context.world.getBlockEntity(pos); - if (!(tileEntity instanceof PortableStorageInterfaceTileEntity psi)) - return null; - - if (!psi.isTransferring()) - return null; - return psi; - } - - static PartialModel getMiddleForState(BlockState state, boolean lit) { - if (AllBlocks.PORTABLE_FLUID_INTERFACE.has(state)) - return lit ? AllBlockPartials.PORTABLE_FLUID_INTERFACE_MIDDLE_POWERED - : AllBlockPartials.PORTABLE_FLUID_INTERFACE_MIDDLE; - return lit ? AllBlockPartials.PORTABLE_STORAGE_INTERFACE_MIDDLE_POWERED - : AllBlockPartials.PORTABLE_STORAGE_INTERFACE_MIDDLE; - } - - static PartialModel getTopForState(BlockState state) { - if (AllBlocks.PORTABLE_FLUID_INTERFACE.has(state)) - return AllBlockPartials.PORTABLE_FLUID_INTERFACE_TOP; - return AllBlockPartials.PORTABLE_STORAGE_INTERFACE_TOP; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceTileEntity.java deleted file mode 100644 index f2125015d..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceTileEntity.java +++ /dev/null @@ -1,202 +0,0 @@ -package com.simibubi.create.content.contraptions.components.actors; - -import java.util.List; - -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; - -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.util.Mth; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.AABB; - -public abstract class PortableStorageInterfaceTileEntity extends SmartTileEntity { - - public static final int ANIMATION = 4; - protected int transferTimer; - protected float distance; - protected LerpedFloat connectionAnimation; - protected boolean powered; - protected Entity connectedEntity; - - public int keepAlive = 0; - - public PortableStorageInterfaceTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - transferTimer = 0; - connectionAnimation = LerpedFloat.linear() - .startWithValue(0); - powered = false; - } - - public void startTransferringTo(Contraption contraption, float distance) { - if (connectedEntity == contraption.entity) - return; - this.distance = Math.min(2, distance); - connectedEntity = contraption.entity; - startConnecting(); - notifyUpdate(); - } - - protected void stopTransferring() { - connectedEntity = null; - level.updateNeighborsAt(worldPosition, getBlockState().getBlock()); - } - - public boolean canTransfer() { - if (connectedEntity != null && !connectedEntity.isAlive()) - stopTransferring(); - return connectedEntity != null && isConnected(); - } - - @Override - public void initialize() { - super.initialize(); - powered = level.hasNeighborSignal(worldPosition); - if (!powered) - notifyContraptions(); - } - - protected abstract void invalidateCapability(); - - @Override - public void tick() { - super.tick(); - boolean wasConnected = isConnected(); - int timeUnit = getTransferTimeout(); - int animation = ANIMATION; - - if (keepAlive > 0) { - keepAlive--; - if (keepAlive == 0 && !level.isClientSide) { - stopTransferring(); - transferTimer = ANIMATION - 1; - sendData(); - return; - } - } - - transferTimer = Math.min(transferTimer, ANIMATION * 2 + getTransferTimeout()); - - boolean timerCanDecrement = transferTimer > ANIMATION || transferTimer > 0 && keepAlive == 0 - && (isVirtual() || !level.isClientSide || transferTimer != ANIMATION); - - if (timerCanDecrement && (!isVirtual() || transferTimer != timeUnit)) { - transferTimer--; - if (transferTimer == ANIMATION - 1) - sendData(); - if (transferTimer <= 0 || powered) - stopTransferring(); - } - - boolean isConnected = isConnected(); - if (wasConnected != isConnected && !level.isClientSide) - setChanged(); - - float progress = 0; - if (isConnected) - progress = 1; - else if (transferTimer >= timeUnit + animation) - progress = Mth.lerp((transferTimer - timeUnit - animation) / (float) animation, 1, 0); - else if (transferTimer < animation) - progress = Mth.lerp(transferTimer / (float) animation, 0, 1); - connectionAnimation.setValue(progress); - } - - @Override - public void invalidate() { - super.invalidate(); - invalidateCapability(); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - super.read(compound, clientPacket); - transferTimer = compound.getInt("Timer"); - distance = compound.getFloat("Distance"); - boolean poweredPreviously = powered; - powered = compound.getBoolean("Powered"); - if (clientPacket && powered != poweredPreviously && !powered) - notifyContraptions(); - } - - @Override - protected void write(CompoundTag compound, boolean clientPacket) { - super.write(compound, clientPacket); - compound.putInt("Timer", transferTimer); - compound.putFloat("Distance", distance); - compound.putBoolean("Powered", powered); - } - - public void neighbourChanged() { - boolean isBlockPowered = level.hasNeighborSignal(worldPosition); - if (isBlockPowered == powered) - return; - powered = isBlockPowered; - if (!powered) - notifyContraptions(); - if (powered) - stopTransferring(); - sendData(); - } - - private void notifyContraptions() { - level.getEntitiesOfClass(AbstractContraptionEntity.class, new AABB(worldPosition).inflate(3)) - .forEach(AbstractContraptionEntity::refreshPSIs); - } - - public boolean isPowered() { - return powered; - } - - @Override - protected AABB createRenderBoundingBox() { - return super.createRenderBoundingBox().inflate(2); - } - - public boolean isTransferring() { - return transferTimer > ANIMATION; - } - - boolean isConnected() { - int timeUnit = getTransferTimeout(); - return transferTimer >= ANIMATION && transferTimer <= timeUnit + ANIMATION; - } - - float getExtensionDistance(float partialTicks) { - return (float) (Math.pow(connectionAnimation.getValue(partialTicks), 2) * distance / 2); - } - - float getConnectionDistance() { - return distance; - } - - public void startConnecting() { - transferTimer = getTransferTimeout() + ANIMATION * 2; - } - - public void onContentTransferred() { - int timeUnit = getTransferTimeout(); - transferTimer = timeUnit + ANIMATION; - award(AllAdvancements.PSI); - sendData(); - } - - protected Integer getTransferTimeout() { - return AllConfigs.SERVER.logistics.psiTimeout.get(); - } - - @Override - public void addBehaviours(List behaviours) { - registerAwardables(behaviours, AllAdvancements.PSI); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/SeatInteractionBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/SeatInteractionBehaviour.java deleted file mode 100644 index 47e9beb0c..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/SeatInteractionBehaviour.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.simibubi.create.content.contraptions.components.actors; - -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; -import com.simibubi.create.content.contraptions.components.structureMovement.MovingInteractionBehaviour; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.player.Player; - -public class SeatInteractionBehaviour extends MovingInteractionBehaviour { - - @Override - public boolean handlePlayerInteraction(Player player, InteractionHand activeHand, BlockPos localPos, - AbstractContraptionEntity contraptionEntity) { - return false; - } - - @Override - public void handleEntityCollision(Entity entity, BlockPos localPos, AbstractContraptionEntity contraptionEntity) { - Contraption contraption = contraptionEntity.getContraption(); - int index = contraption.getSeats() - .indexOf(localPos); - if (index == -1) - return; - if (!SeatBlock.canBePickedUp(entity)) - return; - contraptionEntity.addSittingPassenger(entity, index); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/StorageInterfaceMovement.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/StorageInterfaceMovement.java deleted file mode 100644 index 93be485cb..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/StorageInterfaceMovement.java +++ /dev/null @@ -1,157 +0,0 @@ -//package com.simibubi.create.content.contraptions.components.actors; -// -//import java.util.function.Predicate; -// -//import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; -//import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; -//import com.simibubi.create.content.logistics.block.transposer.TransposerBlock; -//import com.simibubi.create.content.logistics.block.transposer.TransposerTileEntity; -//import com.simibubi.create.foundation.config.AllConfigs; -//import com.simibubi.create.foundation.item.ItemHelper; -//import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -//import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; -//import com.simibubi.create.foundation.tileEntity.behaviour.inventory.SingleTargetAutoExtractingBehaviour; -//import com.simibubi.create.foundation.utility.VecHelper; -// -//import net.minecraft.item.ItemStack; -//import net.minecraft.nbt.NBTUtil; -//import net.minecraft.tileentity.TileEntity; -//import net.minecraft.core.Direction; -//import net.minecraft.core.Direction.Axis; -//import net.minecraft.util.math.BlockPos; -//import net.minecraft.util.math.vector.Vector3d; -//import net.minecraft.world.World; -//import net.minecraftforge.items.IItemHandlerModifiable; -//import net.minecraftforge.items.ItemHandlerHelper; -// -//public class StorageInterfaceMovement extends MovementBehaviour { -// -// private static final String _exporting_ = "Exporting"; -// private static final String _delay_ = "Delay"; -// private static final String _workingPos_ = "WorkingPos"; -// -// @Override -// public Vector3d getActiveAreaOffset(MovementContext context) { -// return new Vector3d(context.state.get(PortableStorageInterfaceBlock.FACING).getDirectionVec()).scale(.85f); -// } -// -// @Override -// public void visitNewPosition(MovementContext context, BlockPos pos) { -// Direction currentFacing = getCurrentFacing(context); -// TransposerTileEntity transposer = getValidTransposer(context.world, pos, currentFacing.getAxis()); -// if (transposer == null) -// return; -// context.data.put(_workingPos_, NBTUtil.writeBlockPos(pos)); -// context.data.putBoolean(_exporting_, -// TransposerBlock.getBlockFacing(transposer.getBlockState()) != currentFacing); -// context.stall = true; -// } -// -// @Override -// public void tick(MovementContext context) { -// if (!context.data.contains(_workingPos_)) -// return; -// if (context.world.isRemote) -// return; -// -// BlockPos pos = NBTUtil.readBlockPos(context.data.getCompound(_workingPos_)); -// TransposerTileEntity transposer = getValidTransposer(context.world, pos, getCurrentFacing(context).getAxis()); -// if (transposer == null) { -// reset(context); -// return; -// } -// -// int nextExtract = context.data.getInt(_delay_); -// if (nextExtract > 0) { -// nextExtract--; -// context.data.putInt(_delay_, nextExtract); -// return; -// } -// -// boolean extract = context.data.getBoolean(_exporting_); -// boolean success = false; -// IItemHandlerModifiable inv = context.contraption.inventory; -// SingleTargetAutoExtractingBehaviour extracting = -// TileEntityBehaviour.get(transposer, SingleTargetAutoExtractingBehaviour.TYPE); -// FilteringBehaviour filtering = TileEntityBehaviour.get(transposer, FilteringBehaviour.TYPE); -// -// if (extract) { -// // Export from Contraption -// Predicate test = extracting.getFilterTest(); -// int exactAmount = extracting.getAmountFromFilter(); -// ItemStack itemExtracted = ItemStack.EMPTY; -// if (exactAmount != -1) -// itemExtracted = ItemHelper.extract(inv, test, exactAmount, false); -// else -// itemExtracted = ItemHelper.extract(inv, test, transposer::amountToExtract, false); -// -// if (!itemExtracted.isEmpty()) { -// transposer.onExtract(itemExtracted); -// success = exactAmount == -1; -// } -// -// } else { -// // Import to Contraption -// if (extracting != null) { -// extracting.setSynchronized(false); -// extracting.withAdditionalFilter(stack -> { -// if (filtering.anyAmount()) -// return true; -// return ItemHandlerHelper.insertItemStacked(inv, stack, true).isEmpty(); -// }); -// -// extracting.withAmountThreshold(stack -> { -// ItemStack tester = stack.copy(); -// tester.setCount(tester.getMaxStackSize()); -// return stack.getCount() - ItemHandlerHelper.insertItemStacked(inv, stack, true).getCount(); -// }); -// -// extracting.setCallback(stack -> { -// ItemHandlerHelper.insertItemStacked(inv, stack, false); -// }); -// -// success = extracting.extract() && filtering.anyAmount(); -// extracting.setSynchronized(true); -// transposer.applyFilteringCallbacks(); -// extracting.setCallback(transposer::onExtract); -// } -// } -// -// if (!success) { -// reset(context); -// return; -// } -// -// context.data.putInt(_delay_, AllConfigs.SERVER.logistics.extractorDelay.get()); -// } -// -// @Override -// public void stopMoving(MovementContext context) { -// reset(context); -// } -// -// public void reset(MovementContext context) { -// context.data.remove(_workingPos_); -// context.data.remove(_delay_); -// context.data.remove(_exporting_); -// context.stall = false; -// } -// -// private TransposerTileEntity getValidTransposer(World world, BlockPos pos, Axis validAxis) { -// TileEntity te = world.getTileEntity(pos); -// if (!(te instanceof TransposerTileEntity)) -// return null; -// if (TransposerBlock.getBlockFacing(world.getBlockState(pos)).getAxis() != validAxis) -// return null; -// if (world.isBlockPowered(pos)) -// return null; -// return (TransposerTileEntity) te; -// } -// -// private Direction getCurrentFacing(MovementContext context) { -// Vector3d directionVec = new Vector3d(context.state.get(PortableStorageInterfaceBlock.FACING).getDirectionVec()); -// directionVec = VecHelper.rotate(directionVec, context.rotation.x, context.rotation.y, context.rotation.z); -// return Direction.getFacingFromVector(directionVec.x, directionVec.y, directionVec.z); -// } -// -//} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/flwdata/package-info.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/flwdata/package-info.java deleted file mode 100644 index 125403077..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/flwdata/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault -package com.simibubi.create.content.contraptions.components.actors.flwdata; - -import javax.annotation.ParametersAreNonnullByDefault; - -import net.minecraft.MethodsReturnNonnullByDefault; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/clock/CuckooClockRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/clock/CuckooClockRenderer.java deleted file mode 100644 index db08c740e..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/clock/CuckooClockRenderer.java +++ /dev/null @@ -1,121 +0,0 @@ -package com.simibubi.create.content.contraptions.components.clock; - -import com.jozufozu.flywheel.core.PartialModel; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.content.contraptions.components.clock.CuckooClockTileEntity.Animation; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.Direction; -import net.minecraft.util.Mth; -import net.minecraft.world.level.block.state.BlockState; - -public class CuckooClockRenderer extends KineticTileEntityRenderer { - - public CuckooClockRenderer(BlockEntityRendererProvider.Context context) { - super(context); - } - - @Override - protected void renderSafe(KineticTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - super.renderSafe(te, partialTicks, ms, buffer, light, overlay); - if (!(te instanceof CuckooClockTileEntity)) - return; - - CuckooClockTileEntity clock = (CuckooClockTileEntity) te; - BlockState blockState = te.getBlockState(); - Direction direction = blockState.getValue(CuckooClockBlock.HORIZONTAL_FACING); - - VertexConsumer vb = buffer.getBuffer(RenderType.solid()); - - // Render Hands - SuperByteBuffer hourHand = CachedBufferer.partial(AllBlockPartials.CUCKOO_HOUR_HAND, blockState); - SuperByteBuffer minuteHand = CachedBufferer.partial(AllBlockPartials.CUCKOO_MINUTE_HAND, blockState); - float hourAngle = clock.hourHand.getValue(partialTicks); - float minuteAngle = clock.minuteHand.getValue(partialTicks); - rotateHand(hourHand, hourAngle, direction).light(light) - .renderInto(ms, vb); - rotateHand(minuteHand, minuteAngle, direction).light(light) - .renderInto(ms, vb); - - // Doors - SuperByteBuffer leftDoor = CachedBufferer.partial(AllBlockPartials.CUCKOO_LEFT_DOOR, blockState); - SuperByteBuffer rightDoor = CachedBufferer.partial(AllBlockPartials.CUCKOO_RIGHT_DOOR, blockState); - float angle = 0; - float offset = 0; - - if (clock.animationType != null) { - float value = clock.animationProgress.getValue(partialTicks); - int step = clock.animationType == Animation.SURPRISE ? 3 : 15; - for (int phase = 30; phase <= 60; phase += step) { - float local = value - phase; - if (local < -step / 3) - continue; - else if (local < 0) - angle = Mth.lerp(((value - (phase - 5)) / 5), 0, 135); - else if (local < step / 3) - angle = 135; - else if (local < 2 * step / 3) - angle = Mth.lerp(((value - (phase + 5)) / 5), 135, 0); - - } - } - - rotateDoor(leftDoor, angle, true, direction).light(light) - .renderInto(ms, vb); - rotateDoor(rightDoor, angle, false, direction).light(light) - .renderInto(ms, vb); - - // Figure - if (clock.animationType != Animation.NONE) { - offset = -(angle / 135) * 1 / 2f + 10 / 16f; - PartialModel partialModel = (clock.animationType == Animation.PIG ? AllBlockPartials.CUCKOO_PIG : AllBlockPartials.CUCKOO_CREEPER); - SuperByteBuffer figure = - CachedBufferer.partial(partialModel, blockState); - figure.rotateCentered(Direction.UP, AngleHelper.rad(AngleHelper.horizontalAngle(direction.getCounterClockWise()))); - figure.translate(offset, 0, 0); - figure.light(light) - .renderInto(ms, vb); - } - - } - - @Override - protected SuperByteBuffer getRotatedModel(KineticTileEntity te, BlockState state) { - return CachedBufferer.partialFacing(AllBlockPartials.SHAFT_HALF, state, state - .getValue(CuckooClockBlock.HORIZONTAL_FACING) - .getOpposite()); - } - - private SuperByteBuffer rotateHand(SuperByteBuffer buffer, float angle, Direction facing) { - float pivotX = 2 / 16f; - float pivotY = 6 / 16f; - float pivotZ = 8 / 16f; - buffer.rotateCentered(Direction.UP, AngleHelper.rad(AngleHelper.horizontalAngle(facing.getCounterClockWise()))); - buffer.translate(pivotX, pivotY, pivotZ); - buffer.rotate(Direction.EAST, AngleHelper.rad(angle)); - buffer.translate(-pivotX, -pivotY, -pivotZ); - return buffer; - } - - private SuperByteBuffer rotateDoor(SuperByteBuffer buffer, float angle, boolean left, Direction facing) { - float pivotX = 2 / 16f; - float pivotY = 0; - float pivotZ = (left ? 6 : 10) / 16f; - buffer.rotateCentered(Direction.UP, AngleHelper.rad(AngleHelper.horizontalAngle(facing.getCounterClockWise()))); - buffer.translate(pivotX, pivotY, pivotZ); - buffer.rotate(Direction.UP, AngleHelper.rad(angle) * (left ? -1 : 1)); - buffer.translate(-pivotX, -pivotY, -pivotZ); - return buffer; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/clock/CuckooClockTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/clock/CuckooClockTileEntity.java deleted file mode 100644 index 846711cf1..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/clock/CuckooClockTileEntity.java +++ /dev/null @@ -1,194 +0,0 @@ -package com.simibubi.create.content.contraptions.components.clock; - -import java.util.List; - -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.sounds.SoundEvent; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.util.Mth; -import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.level.Level.ExplosionInteraction; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; - -public class CuckooClockTileEntity extends KineticTileEntity { - - public static DamageSource CUCKOO_SURPRISE = new DamageSource("create.cuckoo_clock_explosion").setExplosion(); - - public LerpedFloat hourHand = LerpedFloat.angular(); - public LerpedFloat minuteHand = LerpedFloat.angular(); - public LerpedFloat animationProgress = LerpedFloat.linear(); - public Animation animationType; - private boolean sendAnimationUpdate; - - enum Animation { - PIG, CREEPER, SURPRISE, NONE; - } - - public CuckooClockTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - animationType = Animation.NONE; - } - - @Override - public void addBehaviours(List behaviours) { - super.addBehaviours(behaviours); - registerAwardables(behaviours, AllAdvancements.CUCKOO_CLOCK); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - super.read(compound, clientPacket); - if (clientPacket && compound.contains("Animation")) { - animationType = NBTHelper.readEnum(compound, "Animation", Animation.class); - animationProgress.startWithValue(0); - } - } - - @Override - public void write(CompoundTag compound, boolean clientPacket) { - if (clientPacket && sendAnimationUpdate) - NBTHelper.writeEnum(compound, "Animation", animationType); - sendAnimationUpdate = false; - super.write(compound, clientPacket); - } - - @Override - public void tick() { - super.tick(); - if (getSpeed() == 0) - return; - - - boolean isNatural = level.dimensionType().natural(); - int dayTime = (int) ((level.getDayTime() * (isNatural ? 1 : 24)) % 24000); - int hours = (dayTime / 1000 + 6) % 24; - int minutes = (dayTime % 1000) * 60 / 1000; - - if (!isNatural) { - if (level.isClientSide) { - moveHands(hours, minutes); - - if (AnimationTickHolder.getTicks() % 6 == 0) - playSound(SoundEvents.NOTE_BLOCK_HAT.get(), 1 / 16f, 2f); - else if (AnimationTickHolder.getTicks() % 3 == 0) - playSound(SoundEvents.NOTE_BLOCK_HAT.get(), 1 / 16f, 1.5f); - } - return; - } - - if (!level.isClientSide) { - if (animationType == Animation.NONE) { - if (hours == 12 && minutes < 5) - startAnimation(Animation.PIG); - if (hours == 18 && minutes < 36 && minutes > 31) - startAnimation(Animation.CREEPER); - } else { - float value = animationProgress.getValue(); - animationProgress.setValue(value + 1); - if (value > 100) - animationType = Animation.NONE; - - if (animationType == Animation.SURPRISE && Mth.equal(animationProgress.getValue(), 50)) { - Vec3 center = VecHelper.getCenterOf(worldPosition); - level.destroyBlock(worldPosition, false); - level.explode(null, CUCKOO_SURPRISE, null, center.x, center.y, center.z, 3, false, - ExplosionInteraction.BLOCK); - } - - } - } - - if (level.isClientSide) { - moveHands(hours, minutes); - - if (animationType == Animation.NONE) { - if (AnimationTickHolder.getTicks() % 32 == 0) - playSound(SoundEvents.NOTE_BLOCK_HAT.get(), 1 / 16f, 2f); - else if (AnimationTickHolder.getTicks() % 16 == 0) - playSound(SoundEvents.NOTE_BLOCK_HAT.get(), 1 / 16f, 1.5f); - } else { - - boolean isSurprise = animationType == Animation.SURPRISE; - float value = animationProgress.getValue(); - animationProgress.setValue(value + 1); - if (value > 100) - animationType = null; - - // sounds - - if (value == 1) - playSound(SoundEvents.NOTE_BLOCK_CHIME.get(), 2, .5f); - if (value == 21) - playSound(SoundEvents.NOTE_BLOCK_CHIME.get(), 2, 0.793701f); - - if (value > 30 && isSurprise) { - Vec3 pos = VecHelper.offsetRandomly(VecHelper.getCenterOf(this.worldPosition), level.random, .5f); - level.addParticle(ParticleTypes.LARGE_SMOKE, pos.x, pos.y, pos.z, 0, 0, 0); - } - if (value == 40 && isSurprise) - playSound(SoundEvents.TNT_PRIMED, 1f, 1f); - - int step = isSurprise ? 3 : 15; - for (int phase = 30; phase <= 60; phase += step) { - if (value == phase - step / 3) - playSound(SoundEvents.CHEST_OPEN, 1 / 16f, 2f); - if (value == phase) { - if (animationType == Animation.PIG) - playSound(SoundEvents.PIG_AMBIENT, 1 / 4f, 1f); - else - playSound(SoundEvents.CREEPER_HURT, 1 / 4f, 3f); - } - if (value == phase + step / 3) - playSound(SoundEvents.CHEST_CLOSE, 1 / 16f, 2f); - - } - - } - - return; - } - } - - public void startAnimation(Animation animation) { - animationType = animation; - if (animation != null && CuckooClockBlock.containsSurprise(getBlockState())) - animationType = Animation.SURPRISE; - animationProgress.startWithValue(0); - sendAnimationUpdate = true; - - if (animation == Animation.CREEPER) - awardIfNear(AllAdvancements.CUCKOO_CLOCK, 32); - - sendData(); - } - - public void moveHands(int hours, int minutes) { - float hourTarget = (float) (360 / 12 * (hours % 12)); - float minuteTarget = (float) (360 / 60 * minutes); - - hourHand.chase(hourTarget, .2f, Chaser.EXP); - minuteHand.chase(minuteTarget, .2f, Chaser.EXP); - - hourHand.tickChaser(); - minuteHand.tickChaser(); - } - - private void playSound(SoundEvent sound, float volume, float pitch) { - Vec3 vec = VecHelper.getCenterOf(worldPosition); - level.playLocalSound(vec.x, vec.y, vec.z, sound, SoundSource.BLOCKS, volume, pitch, false); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/CrafterCTBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/crafter/CrafterCTBehaviour.java deleted file mode 100644 index 369d36908..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/CrafterCTBehaviour.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.simibubi.create.content.contraptions.components.crafter; - -import static com.simibubi.create.content.contraptions.base.HorizontalKineticBlock.HORIZONTAL_FACING; - -import org.jetbrains.annotations.Nullable; - -import com.simibubi.create.AllSpriteShifts; -import com.simibubi.create.content.contraptions.components.crafter.ConnectedInputHandler.ConnectedInput; -import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry; -import com.simibubi.create.foundation.block.connected.ConnectedTextureBehaviour; - -import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.core.Direction.AxisDirection; -import net.minecraft.world.level.BlockAndTintGetter; -import net.minecraft.world.level.block.state.BlockState; - -public class CrafterCTBehaviour extends ConnectedTextureBehaviour.Base { - - @Override - public boolean connectsTo(BlockState state, BlockState other, BlockAndTintGetter reader, BlockPos pos, BlockPos otherPos, - Direction face) { - if (state.getBlock() != other.getBlock()) - return false; - if (state.getValue(HORIZONTAL_FACING) != other.getValue(HORIZONTAL_FACING)) - return false; - - ConnectedInput input1 = CrafterHelper.getInput(reader, pos); - ConnectedInput input2 = CrafterHelper.getInput(reader, otherPos); - - if (input1 == null || input2 == null) - return false; - if (input1.data.isEmpty() || input2.data.isEmpty()) - return false; - try { - if (pos.offset(input1.data.get(0)) - .equals(otherPos.offset(input2.data.get(0)))) - return true; - } catch (IndexOutOfBoundsException e) { - // race condition. data somehow becomes empty between the last 2 if statements - } - - return false; - } - - @Override - protected boolean reverseUVs(BlockState state, Direction direction) { - if (!direction.getAxis() - .isVertical()) - return false; - Direction facing = state.getValue(HORIZONTAL_FACING); - if (facing.getAxis() == direction.getAxis()) - return false; - - boolean isNegative = facing.getAxisDirection() == AxisDirection.NEGATIVE; - if (direction == Direction.DOWN && facing.getAxis() == Axis.Z) - return !isNegative; - return isNegative; - } - - @Override - public CTSpriteShiftEntry getShift(BlockState state, Direction direction, @Nullable TextureAtlasSprite sprite) { - Direction facing = state.getValue(HORIZONTAL_FACING); - boolean isFront = facing.getAxis() == direction.getAxis(); - boolean isVertical = direction.getAxis() - .isVertical(); - boolean facingX = facing.getAxis() == Axis.X; - return isFront ? AllSpriteShifts.CRAFTER_FRONT - : isVertical && !facingX ? AllSpriteShifts.CRAFTER_OTHERSIDE : AllSpriteShifts.CRAFTER_SIDE; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/CrafterHelper.java b/src/main/java/com/simibubi/create/content/contraptions/components/crafter/CrafterHelper.java deleted file mode 100644 index d04f3449e..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/CrafterHelper.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.simibubi.create.content.contraptions.components.crafter; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.BlockAndTintGetter; -import net.minecraft.world.level.block.entity.BlockEntity; - -public class CrafterHelper { - - public static MechanicalCrafterTileEntity getCrafter(BlockAndTintGetter reader, BlockPos pos) { - BlockEntity te = reader.getBlockEntity(pos); - if (!(te instanceof MechanicalCrafterTileEntity)) - return null; - return (MechanicalCrafterTileEntity) te; - } - - public static ConnectedInputHandler.ConnectedInput getInput(BlockAndTintGetter reader, BlockPos pos) { - MechanicalCrafterTileEntity crafter = getCrafter(reader, pos); - return crafter == null ? null : crafter.input; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterInstance.java deleted file mode 100644 index f0536efbf..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterInstance.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.simibubi.create.content.contraptions.components.crafter; - -import java.util.function.Supplier; - -import com.jozufozu.flywheel.api.Instancer; -import com.jozufozu.flywheel.api.MaterialManager; -import com.jozufozu.flywheel.util.transform.TransformStack; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.SingleRotatingInstance; -import com.simibubi.create.content.contraptions.base.flwdata.RotatingData; - -import net.minecraft.core.Direction; - -public class MechanicalCrafterInstance extends SingleRotatingInstance { - - public MechanicalCrafterInstance(MaterialManager modelManager, KineticTileEntity tile) { - super(modelManager, tile); - } - - @Override - protected Instancer getModel() { - Direction facing = blockState.getValue(MechanicalCrafterBlock.HORIZONTAL_FACING); - - return getRotatingMaterial().getModel(AllBlockPartials.SHAFTLESS_COGWHEEL, blockState, facing, rotateToFace(facing)); - } - - private Supplier rotateToFace(Direction facing) { - return () -> { - PoseStack stack = new PoseStack(); - TransformStack stacker = TransformStack.cast(stack) - .centre(); - - if (facing.getAxis() == Direction.Axis.X) stacker.rotateZ(90); - else if (facing.getAxis() == Direction.Axis.Z) stacker.rotateX(90); - - stacker.unCentre(); - return stack; - }; - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterRenderer.java deleted file mode 100644 index 62ddecd4d..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterRenderer.java +++ /dev/null @@ -1,223 +0,0 @@ -package com.simibubi.create.content.contraptions.components.crafter; - -import static com.simibubi.create.content.contraptions.base.HorizontalKineticBlock.HORIZONTAL_FACING; -import static com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer.standardKineticRotationTransform; - -import com.jozufozu.flywheel.backend.Backend; -import com.jozufozu.flywheel.core.PartialModel; -import com.jozufozu.flywheel.util.transform.TransformStack; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import com.mojang.math.Axis; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.AllSpriteShifts; -import com.simibubi.create.content.contraptions.components.crafter.MechanicalCrafterTileEntity.Phase; -import com.simibubi.create.content.contraptions.components.crafter.RecipeGridHandler.GroupedItems; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.Pointing; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.block.model.ItemTransforms.TransformType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.util.Mth; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; - -public class MechanicalCrafterRenderer extends SafeTileEntityRenderer { - - public MechanicalCrafterRenderer(BlockEntityRendererProvider.Context context) { - } - - @Override - protected void renderSafe(MechanicalCrafterTileEntity te, float partialTicks, PoseStack ms, - MultiBufferSource buffer, int light, int overlay) { - ms.pushPose(); - Direction facing = te.getBlockState() - .getValue(HORIZONTAL_FACING); - Vec3 vec = Vec3.atLowerCornerOf(facing.getNormal()) - .scale(.58) - .add(.5, .5, .5); - - if (te.phase == Phase.EXPORTING) { - Direction targetDirection = MechanicalCrafterBlock.getTargetDirection(te.getBlockState()); - float progress = - Mth.clamp((1000 - te.countDown + te.getCountDownSpeed() * partialTicks) / 1000f, 0, 1); - vec = vec.add(Vec3.atLowerCornerOf(targetDirection.getNormal()) - .scale(progress * .75f)); - } - - ms.translate(vec.x, vec.y, vec.z); - ms.scale(1 / 2f, 1 / 2f, 1 / 2f); - float yRot = AngleHelper.horizontalAngle(facing); - ms.mulPose(Axis.YP.rotationDegrees(yRot)); - renderItems(te, partialTicks, ms, buffer, light, overlay); - ms.popPose(); - - renderFast(te, partialTicks, ms, buffer, light); - } - - public void renderItems(MechanicalCrafterTileEntity te, float partialTicks, PoseStack ms, - MultiBufferSource buffer, int light, int overlay) { - if (te.phase == Phase.IDLE) { - ItemStack stack = te.getInventory() - .getItem(0); - if (!stack.isEmpty()) { - ms.pushPose(); - ms.translate(0, 0, -1 / 256f); - ms.mulPose(Axis.YP.rotationDegrees(180)); - Minecraft.getInstance() - .getItemRenderer() - .renderStatic(stack, TransformType.FIXED, light, overlay, ms, buffer, 0); - ms.popPose(); - } - } else { - // render grouped items - GroupedItems items = te.groupedItems; - float distance = .5f; - - ms.pushPose(); - - if (te.phase == Phase.CRAFTING) { - items = te.groupedItemsBeforeCraft; - items.calcStats(); - float progress = - Mth.clamp((2000 - te.countDown + te.getCountDownSpeed() * partialTicks) / 1000f, 0, 1); - float earlyProgress = Mth.clamp(progress * 2, 0, 1); - float lateProgress = Mth.clamp(progress * 2 - 1, 0, 1); - - ms.scale(1 - lateProgress, 1 - lateProgress, 1 - lateProgress); - Vec3 centering = - new Vec3(-items.minX + (-items.width + 1) / 2f, -items.minY + (-items.height + 1) / 2f, 0) - .scale(earlyProgress); - ms.translate(centering.x * .5f, centering.y * .5f, 0); - distance += (-4 * (progress - .5f) * (progress - .5f) + 1) * .25f; - } - - boolean onlyRenderFirst = te.phase == Phase.INSERTING || te.phase == Phase.CRAFTING && te.countDown < 1000; - final float spacing = distance; - items.grid.forEach((pair, stack) -> { - if (onlyRenderFirst && (pair.getLeft() - .intValue() != 0 - || pair.getRight() - .intValue() != 0)) - return; - - ms.pushPose(); - Integer x = pair.getKey(); - Integer y = pair.getValue(); - ms.translate(x * spacing, y * spacing, 0); - - int offset = 0; - if (te.phase == Phase.EXPORTING && te.getBlockState().hasProperty(MechanicalCrafterBlock.POINTING)) { - Pointing value = te.getBlockState().getValue(MechanicalCrafterBlock.POINTING); - offset = value == Pointing.UP ? -1 : value == Pointing.LEFT ? 2 : value == Pointing.RIGHT ? -2 : 1; - } - - TransformStack.cast(ms) - .rotateY(180) - .translate(0, 0, (x + y * 3 + offset * 9) / 1024f ); - Minecraft.getInstance() - .getItemRenderer() - .renderStatic(stack, TransformType.FIXED, light, overlay, ms, buffer, 0); - ms.popPose(); - }); - - ms.popPose(); - - if (te.phase == Phase.CRAFTING) { - items = te.groupedItems; - float progress = - Mth.clamp((1000 - te.countDown + te.getCountDownSpeed() * partialTicks) / 1000f, 0, 1); - float earlyProgress = Mth.clamp(progress * 2, 0, 1); - float lateProgress = Mth.clamp(progress * 2 - 1, 0, 1); - - ms.mulPose(Axis.ZP.rotationDegrees(earlyProgress * 2 * 360)); - float upScaling = earlyProgress * 1.125f; - float downScaling = 1 + (1 - lateProgress) * .125f; - ms.scale(upScaling, upScaling, upScaling); - ms.scale(downScaling, downScaling, downScaling); - - items.grid.forEach((pair, stack) -> { - if (pair.getLeft() - .intValue() != 0 - || pair.getRight() - .intValue() != 0) - return; - ms.pushPose(); - ms.mulPose(Axis.YP.rotationDegrees(180)); - Minecraft.getInstance() - .getItemRenderer() - .renderStatic(stack, TransformType.FIXED, light, overlay, ms, buffer, 0); - ms.popPose(); - }); - } - - } - } - - public void renderFast(MechanicalCrafterTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light) { - BlockState blockState = te.getBlockState(); - VertexConsumer vb = buffer.getBuffer(RenderType.solid()); - - if (!Backend.canUseInstancing(te.getLevel())) { - SuperByteBuffer superBuffer = CachedBufferer.partial(AllBlockPartials.SHAFTLESS_COGWHEEL, blockState); - standardKineticRotationTransform(superBuffer, te, light); - superBuffer.rotateCentered(Direction.UP, (float) (blockState.getValue(HORIZONTAL_FACING) - .getAxis() != Direction.Axis.X ? 0 : Math.PI / 2)); - superBuffer.rotateCentered(Direction.EAST, (float) (Math.PI / 2)); - superBuffer.renderInto(ms, vb); - } - - Direction targetDirection = MechanicalCrafterBlock.getTargetDirection(blockState); - BlockPos pos = te.getBlockPos(); - - if ((te.covered || te.phase != Phase.IDLE) && te.phase != Phase.CRAFTING && te.phase != Phase.INSERTING) { - SuperByteBuffer lidBuffer = renderAndTransform(AllBlockPartials.MECHANICAL_CRAFTER_LID, blockState); - lidBuffer.light(light) - .renderInto(ms, vb); - } - - if (MechanicalCrafterBlock.isValidTarget(te.getLevel(), pos.relative(targetDirection), blockState)) { - SuperByteBuffer beltBuffer = renderAndTransform(AllBlockPartials.MECHANICAL_CRAFTER_BELT, blockState); - SuperByteBuffer beltFrameBuffer = - renderAndTransform(AllBlockPartials.MECHANICAL_CRAFTER_BELT_FRAME, blockState); - - if (te.phase == Phase.EXPORTING) { - int textureIndex = (int) ((te.getCountDownSpeed() / 128f * AnimationTickHolder.getTicks())); - beltBuffer.shiftUVtoSheet(AllSpriteShifts.CRAFTER_THINGIES, (textureIndex % 4) / 4f, 0, 1); - } - - beltBuffer.light(light) - .renderInto(ms, vb); - beltFrameBuffer.light(light) - .renderInto(ms, vb); - - } else { - SuperByteBuffer arrowBuffer = renderAndTransform(AllBlockPartials.MECHANICAL_CRAFTER_ARROW, blockState); - arrowBuffer.light(light) - .renderInto(ms, vb); - } - - } - - private SuperByteBuffer renderAndTransform(PartialModel renderBlock, BlockState crafterState) { - SuperByteBuffer buffer = CachedBufferer.partial(renderBlock, crafterState); - float xRot = crafterState.getValue(MechanicalCrafterBlock.POINTING) - .getXRotation(); - float yRot = AngleHelper.horizontalAngle(crafterState.getValue(HORIZONTAL_FACING)); - buffer.rotateCentered(Direction.UP, (float) ((yRot + 90) / 180 * Math.PI)); - buffer.rotateCentered(Direction.EAST, (float) ((xRot) / 180 * Math.PI)); - return buffer; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterTileEntity.java deleted file mode 100644 index 42a8c921e..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterTileEntity.java +++ /dev/null @@ -1,542 +0,0 @@ -package com.simibubi.create.content.contraptions.components.crafter; - -import static com.simibubi.create.content.contraptions.base.HorizontalKineticBlock.HORIZONTAL_FACING; - -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; -import java.util.Map.Entry; - -import org.apache.commons.lang3.tuple.Pair; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllItems; -import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.components.crafter.ConnectedInputHandler.ConnectedInput; -import com.simibubi.create.content.contraptions.components.crafter.RecipeGridHandler.GroupedItems; -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.item.SmartInventory; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.edgeInteraction.EdgeInteractionBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.inventory.InvManipulationBehaviour; -import com.simibubi.create.foundation.utility.BlockFace; -import com.simibubi.create.foundation.utility.Pointing; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.particles.ItemParticleOption; -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.util.Mth; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.items.IItemHandler; - -public class MechanicalCrafterTileEntity extends KineticTileEntity { - - enum Phase { - IDLE, ACCEPTING, ASSEMBLING, EXPORTING, WAITING, CRAFTING, INSERTING; - } - - public static class Inventory extends SmartInventory { - - private MechanicalCrafterTileEntity te; - - public Inventory(MechanicalCrafterTileEntity te) { - super(1, te, 1, false); - this.te = te; - forbidExtraction(); - whenContentsChanged(slot -> { - if (getItem(slot).isEmpty()) - return; - if (te.phase == Phase.IDLE) - te.checkCompletedRecipe(false); - }); - } - - @Override - public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) { - if (te.phase != Phase.IDLE) - return stack; - if (te.covered) - return stack; - ItemStack insertItem = super.insertItem(slot, stack, simulate); - if (insertItem.getCount() != stack.getCount() && !simulate) - te.getLevel() - .playSound(null, te.getBlockPos(), SoundEvents.ITEM_FRAME_ADD_ITEM, SoundSource.BLOCKS, .25f, .5f); - return insertItem; - } - - } - - protected Inventory inventory; - protected GroupedItems groupedItems = new GroupedItems(); - protected ConnectedInput input = new ConnectedInput(); - protected LazyOptional invSupplier = - LazyOptional.of(() -> input.getItemHandler(level, worldPosition)); - protected boolean reRender; - protected Phase phase; - protected int countDown; - protected boolean covered; - protected boolean wasPoweredBefore; - - protected GroupedItems groupedItemsBeforeCraft; // for rendering on client - private InvManipulationBehaviour inserting; - private EdgeInteractionBehaviour connectivity; - - private ItemStack scriptedResult = ItemStack.EMPTY; - - public MechanicalCrafterTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - setLazyTickRate(20); - phase = Phase.IDLE; - groupedItemsBeforeCraft = new GroupedItems(); - inventory = new Inventory(this); - - // Does not get serialized due to active checking in tick - wasPoweredBefore = true; - } - - @Override - public void addBehaviours(List behaviours) { - super.addBehaviours(behaviours); - inserting = new InvManipulationBehaviour(this, this::getTargetFace); - connectivity = new EdgeInteractionBehaviour(this, ConnectedInputHandler::toggleConnection) - .connectivity(ConnectedInputHandler::shouldConnect) - .require(AllItems.WRENCH.get()); - behaviours.add(inserting); - behaviours.add(connectivity); - registerAwardables(behaviours, AllAdvancements.CRAFTER, AllAdvancements.CRAFTER_LAZY); - } - - @Override - public void onSpeedChanged(float previousSpeed) { - super.onSpeedChanged(previousSpeed); - if (!Mth.equal(getSpeed(), 0)) { - award(AllAdvancements.CRAFTER); - if (Math.abs(getSpeed()) < 5) - award(AllAdvancements.CRAFTER_LAZY); - } - } - - public void blockChanged() { - removeBehaviour(InvManipulationBehaviour.TYPE); - inserting = new InvManipulationBehaviour(this, this::getTargetFace); - attachBehaviourLate(inserting); - } - - public BlockFace getTargetFace(Level world, BlockPos pos, BlockState state) { - return new BlockFace(pos, MechanicalCrafterBlock.getTargetDirection(state)); - } - - public Direction getTargetDirection() { - return MechanicalCrafterBlock.getTargetDirection(getBlockState()); - } - - @Override - public void writeSafe(CompoundTag compound) { - super.writeSafe(compound); - if (input == null) - return; - - CompoundTag inputNBT = new CompoundTag(); - input.write(inputNBT); - compound.put("ConnectedInput", inputNBT); - } - - @Override - public void write(CompoundTag compound, boolean clientPacket) { - compound.put("Inventory", inventory.serializeNBT()); - - CompoundTag inputNBT = new CompoundTag(); - input.write(inputNBT); - compound.put("ConnectedInput", inputNBT); - - CompoundTag groupedItemsNBT = new CompoundTag(); - groupedItems.write(groupedItemsNBT); - compound.put("GroupedItems", groupedItemsNBT); - - compound.putString("Phase", phase.name()); - compound.putInt("CountDown", countDown); - compound.putBoolean("Cover", covered); - - super.write(compound, clientPacket); - - if (clientPacket && reRender) { - compound.putBoolean("Redraw", true); - reRender = false; - } - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - Phase phaseBefore = phase; - GroupedItems before = this.groupedItems; - - inventory.deserializeNBT(compound.getCompound("Inventory")); - input.read(compound.getCompound("ConnectedInput")); - groupedItems = GroupedItems.read(compound.getCompound("GroupedItems")); - phase = Phase.IDLE; - String name = compound.getString("Phase"); - for (Phase phase : Phase.values()) - if (phase.name() - .equals(name)) - this.phase = phase; - countDown = compound.getInt("CountDown"); - covered = compound.getBoolean("Cover"); - super.read(compound, clientPacket); - if (!clientPacket) - return; - if (compound.contains("Redraw")) - level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 16); - if (phaseBefore != phase && phase == Phase.CRAFTING) - groupedItemsBeforeCraft = before; - if (phaseBefore == Phase.EXPORTING && phase == Phase.WAITING) { - Direction facing = getBlockState().getValue(MechanicalCrafterBlock.HORIZONTAL_FACING); - Vec3 vec = Vec3.atLowerCornerOf(facing.getNormal()) - .scale(.75) - .add(VecHelper.getCenterOf(worldPosition)); - Direction targetDirection = MechanicalCrafterBlock.getTargetDirection(getBlockState()); - vec = vec.add(Vec3.atLowerCornerOf(targetDirection.getNormal()) - .scale(1)); - level.addParticle(ParticleTypes.CRIT, vec.x, vec.y, vec.z, 0, 0, 0); - } - } - - @Override - public void invalidate() { - super.invalidate(); - invSupplier.invalidate(); - } - - public int getCountDownSpeed() { - if (getSpeed() == 0) - return 0; - return Mth.clamp((int) Math.abs(getSpeed()), 4, 250); - } - - @Override - public void tick() { - super.tick(); - - if (phase == Phase.ACCEPTING) - return; - - boolean onClient = level.isClientSide; - boolean runLogic = !onClient || isVirtual(); - - if (wasPoweredBefore != level.hasNeighborSignal(worldPosition)) { - wasPoweredBefore = level.hasNeighborSignal(worldPosition); - if (wasPoweredBefore) { - if (!runLogic) - return; - checkCompletedRecipe(true); - } - } - - if (phase == Phase.ASSEMBLING) { - countDown -= getCountDownSpeed(); - if (countDown < 0) { - countDown = 0; - if (!runLogic) - return; - if (RecipeGridHandler.getTargetingCrafter(this) != null) { - phase = Phase.EXPORTING; - countDown = 1000; - sendData(); - return; - } - - ItemStack result = - isVirtual() ? scriptedResult : RecipeGridHandler.tryToApplyRecipe(level, groupedItems); - - if (result != null) { - List containers = new ArrayList<>(); - groupedItems.grid.values() - .forEach(stack -> { - if (stack.hasCraftingRemainingItem()) - containers.add(stack.getCraftingRemainingItem() - .copy()); - }); - - if (isVirtual()) - groupedItemsBeforeCraft = groupedItems; - - groupedItems = new GroupedItems(result); - for (int i = 0; i < containers.size(); i++) { - ItemStack stack = containers.get(i); - GroupedItems container = new GroupedItems(); - container.grid.put(Pair.of(i, 0), stack); - container.mergeOnto(groupedItems, Pointing.LEFT); - } - - phase = Phase.CRAFTING; - countDown = 2000; - sendData(); - return; - } - ejectWholeGrid(); - return; - } - } - - if (phase == Phase.EXPORTING) { - countDown -= getCountDownSpeed(); - - if (countDown < 0) { - countDown = 0; - if (!runLogic) - return; - - MechanicalCrafterTileEntity targetingCrafter = RecipeGridHandler.getTargetingCrafter(this); - if (targetingCrafter == null) { - ejectWholeGrid(); - return; - } - - Pointing pointing = getBlockState().getValue(MechanicalCrafterBlock.POINTING); - groupedItems.mergeOnto(targetingCrafter.groupedItems, pointing); - groupedItems = new GroupedItems(); - - float pitch = targetingCrafter.groupedItems.grid.size() * 1 / 16f + .5f; - AllSoundEvents.CRAFTER_CLICK.playOnServer(level, worldPosition, 1, pitch); - - phase = Phase.WAITING; - countDown = 0; - sendData(); - targetingCrafter.continueIfAllPrecedingFinished(); - targetingCrafter.sendData(); - return; - } - } - - if (phase == Phase.CRAFTING) { - - if (onClient) { - Direction facing = getBlockState().getValue(MechanicalCrafterBlock.HORIZONTAL_FACING); - float progress = countDown / 2000f; - Vec3 facingVec = Vec3.atLowerCornerOf(facing.getNormal()); - Vec3 vec = facingVec.scale(.65) - .add(VecHelper.getCenterOf(worldPosition)); - Vec3 offset = VecHelper.offsetRandomly(Vec3.ZERO, level.random, .125f) - .multiply(VecHelper.axisAlingedPlaneOf(facingVec)) - .normalize() - .scale(progress * .5f) - .add(vec); - if (progress > .5f) - level.addParticle(ParticleTypes.CRIT, offset.x, offset.y, offset.z, 0, 0, 0); - - if (!groupedItemsBeforeCraft.grid.isEmpty() && progress < .5f) { - if (groupedItems.grid.containsKey(Pair.of(0, 0))) { - ItemStack stack = groupedItems.grid.get(Pair.of(0, 0)); - groupedItemsBeforeCraft = new GroupedItems(); - - for (int i = 0; i < 10; i++) { - Vec3 randVec = VecHelper.offsetRandomly(Vec3.ZERO, level.random, .125f) - .multiply(VecHelper.axisAlingedPlaneOf(facingVec)) - .normalize() - .scale(.25f); - Vec3 offset2 = randVec.add(vec); - randVec = randVec.scale(.35f); - level.addParticle(new ItemParticleOption(ParticleTypes.ITEM, stack), offset2.x, offset2.y, - offset2.z, randVec.x, randVec.y, randVec.z); - } - } - } - } - - int prev = countDown; - countDown -= getCountDownSpeed(); - - if (countDown < 1000 && prev >= 1000) { - AllSoundEvents.CRAFTER_CLICK.playOnServer(level, worldPosition, 1, 2); - AllSoundEvents.CRAFTER_CRAFT.playOnServer(level, worldPosition); - } - - if (countDown < 0) { - countDown = 0; - if (!runLogic) - return; - tryInsert(); - return; - } - } - - if (phase == Phase.INSERTING) { - if (runLogic && isTargetingBelt()) - tryInsert(); - return; - } - } - - protected boolean isTargetingBelt() { - DirectBeltInputBehaviour behaviour = getTargetingBelt(); - return behaviour != null && behaviour.canInsertFromSide(getTargetDirection()); - } - - protected DirectBeltInputBehaviour getTargetingBelt() { - BlockPos targetPos = worldPosition.relative(getTargetDirection()); - return TileEntityBehaviour.get(level, targetPos, DirectBeltInputBehaviour.TYPE); - } - - public void tryInsert() { - if (!inserting.hasInventory() && !isTargetingBelt()) { - ejectWholeGrid(); - return; - } - - boolean chagedPhase = phase != Phase.INSERTING; - final List> inserted = new LinkedList<>(); - - DirectBeltInputBehaviour behaviour = getTargetingBelt(); - for (Entry, ItemStack> entry : groupedItems.grid.entrySet()) { - Pair pair = entry.getKey(); - ItemStack stack = entry.getValue(); - BlockFace face = getTargetFace(level, worldPosition, getBlockState()); - - ItemStack remainder = behaviour == null ? inserting.insert(stack.copy()) - : behaviour.handleInsertion(stack, face.getFace(), false); - if (!remainder.isEmpty()) { - stack.setCount(remainder.getCount()); - continue; - } - - inserted.add(pair); - } - - inserted.forEach(groupedItems.grid::remove); - if (groupedItems.grid.isEmpty()) - ejectWholeGrid(); - else - phase = Phase.INSERTING; - if (!inserted.isEmpty() || chagedPhase) - sendData(); - } - - public void ejectWholeGrid() { - List chain = RecipeGridHandler.getAllCraftersOfChain(this); - if (chain == null) - return; - chain.forEach(MechanicalCrafterTileEntity::eject); - } - - public void eject() { - BlockState blockState = getBlockState(); - boolean present = AllBlocks.MECHANICAL_CRAFTER.has(blockState); - Vec3 vec = present ? Vec3.atLowerCornerOf(blockState.getValue(HORIZONTAL_FACING) - .getNormal()) - .scale(.75f) : Vec3.ZERO; - Vec3 ejectPos = VecHelper.getCenterOf(worldPosition) - .add(vec); - groupedItems.grid.forEach((pair, stack) -> dropItem(ejectPos, stack)); - if (!inventory.getItem(0) - .isEmpty()) - dropItem(ejectPos, inventory.getItem(0)); - phase = Phase.IDLE; - groupedItems = new GroupedItems(); - inventory.setStackInSlot(0, ItemStack.EMPTY); - sendData(); - } - - public void dropItem(Vec3 ejectPos, ItemStack stack) { - ItemEntity itemEntity = new ItemEntity(level, ejectPos.x, ejectPos.y, ejectPos.z, stack); - itemEntity.setDefaultPickUpDelay(); - level.addFreshEntity(itemEntity); - } - - @Override - public void lazyTick() { - super.lazyTick(); - if (level.isClientSide && !isVirtual()) - return; - if (phase == Phase.IDLE && craftingItemPresent()) - checkCompletedRecipe(false); - if (phase == Phase.INSERTING) - tryInsert(); - } - - public boolean craftingItemPresent() { - return !inventory.getItem(0) - .isEmpty(); - } - - public boolean craftingItemOrCoverPresent() { - return !inventory.getItem(0) - .isEmpty() || covered; - } - - protected void checkCompletedRecipe(boolean poweredStart) { - if (getSpeed() == 0) - return; - if (level.isClientSide && !isVirtual()) - return; - List chain = RecipeGridHandler.getAllCraftersOfChainIf(this, - poweredStart ? MechanicalCrafterTileEntity::craftingItemPresent - : MechanicalCrafterTileEntity::craftingItemOrCoverPresent, - poweredStart); - if (chain == null) - return; - chain.forEach(MechanicalCrafterTileEntity::begin); - } - - protected void begin() { - phase = Phase.ACCEPTING; - groupedItems = new GroupedItems(inventory.getItem(0)); - inventory.setStackInSlot(0, ItemStack.EMPTY); - if (RecipeGridHandler.getPrecedingCrafters(this) - .isEmpty()) { - phase = Phase.ASSEMBLING; - countDown = 500; - } - sendData(); - } - - protected void continueIfAllPrecedingFinished() { - List preceding = RecipeGridHandler.getPrecedingCrafters(this); - if (preceding == null) { - ejectWholeGrid(); - return; - } - - for (MechanicalCrafterTileEntity mechanicalCrafterTileEntity : preceding) - if (mechanicalCrafterTileEntity.phase != Phase.WAITING) - return; - - phase = Phase.ASSEMBLING; - countDown = Math.max(100, getCountDownSpeed() + 1); - } - - @Override - public LazyOptional getCapability(Capability cap, Direction side) { - if (isItemHandlerCap(cap)) - return invSupplier.cast(); - return super.getCapability(cap, side); - } - - public void connectivityChanged() { - reRender = true; - sendData(); - invSupplier.invalidate(); - invSupplier = LazyOptional.of(() -> input.getItemHandler(level, worldPosition)); - } - - public Inventory getInventory() { - return inventory; - } - - public void setScriptedResult(ItemStack scriptedResult) { - this.scriptedResult = scriptedResult; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankInstance.java deleted file mode 100644 index c3eaeb218..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankInstance.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.simibubi.create.content.contraptions.components.crank; - -import com.jozufozu.flywheel.api.Instancer; -import com.jozufozu.flywheel.api.MaterialManager; -import com.jozufozu.flywheel.api.instance.DynamicInstance; -import com.jozufozu.flywheel.core.PartialModel; -import com.jozufozu.flywheel.core.materials.model.ModelData; -import com.simibubi.create.content.contraptions.base.SingleRotatingInstance; -import com.simibubi.create.foundation.utility.AnimationTickHolder; - -import net.minecraft.core.Direction; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; - -public class HandCrankInstance extends SingleRotatingInstance implements DynamicInstance { - - private final HandCrankTileEntity tile; - private ModelData crank; - private Direction facing; - - public HandCrankInstance(MaterialManager modelManager, HandCrankTileEntity tile) { - super(modelManager, tile); - this.tile = tile; - - Block block = blockState.getBlock(); - PartialModel renderedHandle = null; - if (block instanceof HandCrankBlock) - renderedHandle = ((HandCrankBlock) block).getRenderedHandle(); - if (renderedHandle == null) - return; - - facing = blockState.getValue(BlockStateProperties.FACING); - Direction opposite = facing.getOpposite(); - Instancer model = getTransformMaterial().getModel(renderedHandle, blockState, opposite); - crank = model.createInstance(); - - rotateCrank(); - } - - @Override - public void beginFrame() { - if (crank == null) return; - - rotateCrank(); - } - - private void rotateCrank() { - Direction.Axis axis = facing.getAxis(); - float angle = (tile.independentAngle + AnimationTickHolder.getPartialTicks() * tile.chasingVelocity) / 360; - - crank.loadIdentity() - .translate(getInstancePosition()) - .centre() - .rotate(Direction.get(Direction.AxisDirection.POSITIVE, axis), angle) - .unCentre(); - } - - @Override - public void remove() { - super.remove(); - if (crank != null) crank.delete(); - } - - @Override - public void updateLight() { - super.updateLight(); - if (crank != null) relight(pos, crank); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankRenderer.java deleted file mode 100644 index 05dce03e5..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankRenderer.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.simibubi.create.content.contraptions.components.crank; - -import static net.minecraft.world.level.block.state.properties.BlockStateProperties.FACING; - -import com.jozufozu.flywheel.backend.Backend; -import com.jozufozu.flywheel.core.PartialModel; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.Direction; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; - -public class HandCrankRenderer extends KineticTileEntityRenderer { - - public HandCrankRenderer(BlockEntityRendererProvider.Context context) { - super(context); - } - - @Override - protected void renderSafe(KineticTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - super.renderSafe(te, partialTicks, ms, buffer, light, overlay); - - if (Backend.canUseInstancing(te.getLevel())) return; - - BlockState state = te.getBlockState(); - Block block = state.getBlock(); - PartialModel renderedHandle = null; - if (block instanceof HandCrankBlock) - renderedHandle = ((HandCrankBlock) block).getRenderedHandle(); - if (renderedHandle == null) - return; - - Direction facing = state.getValue(FACING); - SuperByteBuffer handle = CachedBufferer.partialFacing(renderedHandle, state, facing.getOpposite()); - HandCrankTileEntity crank = (HandCrankTileEntity) te; - kineticRotationTransform(handle, te, facing.getAxis(), - (crank.independentAngle + partialTicks * crank.chasingVelocity) / 360, light); - handle.renderInto(ms, buffer.getBuffer(RenderType.solid())); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankTileEntity.java deleted file mode 100644 index 4ef31339f..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankTileEntity.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.simibubi.create.content.contraptions.components.crank; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.content.contraptions.base.GeneratingKineticTileEntity; -import com.simibubi.create.foundation.utility.AnimationTickHolder; - -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -public class HandCrankTileEntity extends GeneratingKineticTileEntity { - - public int inUse; - public boolean backwards; - public float independentAngle; - public float chasingVelocity; - - public HandCrankTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - public void turn(boolean back) { - boolean update = false; - - if (getGeneratedSpeed() == 0 || back != backwards) - update = true; - - inUse = 10; - this.backwards = back; - if (update && !level.isClientSide) - updateGeneratedRotation(); - } - - @Override - public float getGeneratedSpeed() { - Block block = getBlockState().getBlock(); - if (!(block instanceof HandCrankBlock)) - return 0; - HandCrankBlock crank = (HandCrankBlock) block; - int speed = (inUse == 0 ? 0 : backwards ? -1 : 1) * crank.getRotationSpeed(); - return convertToDirection(speed, getBlockState().getValue(HandCrankBlock.FACING)); - } - - @Override - public void write(CompoundTag compound, boolean clientPacket) { - compound.putInt("InUse", inUse); - super.write(compound, clientPacket); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - inUse = compound.getInt("InUse"); - super.read(compound, clientPacket); - } - - @Override - public void tick() { - super.tick(); - - float actualSpeed = getSpeed(); - chasingVelocity += ((actualSpeed * 10 / 3f) - chasingVelocity) * .25f; - independentAngle += chasingVelocity; - - if (inUse > 0) { - inUse--; - - if (inUse == 0 && !level.isClientSide) - updateGeneratedRotation(); - } - } - - @Override - protected Block getStressConfigKey() { - return AllBlocks.HAND_CRANK.get(); - } - - @Override - @OnlyIn(Dist.CLIENT) - public void tickAudio() { - super.tickAudio(); - if (inUse > 0 && AnimationTickHolder.getTicks() % 10 == 0) { - if (!AllBlocks.HAND_CRANK.has(getBlockState())) - return; - AllSoundEvents.CRANKING.playAt(level, worldPosition, (inUse) / 2.5f, .65f + (10 - inUse) / 10f, true); - } - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crank/ValveHandleBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/crank/ValveHandleBlock.java deleted file mode 100644 index 8ade00970..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crank/ValveHandleBlock.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.simibubi.create.content.contraptions.components.crank; - -import javax.annotation.ParametersAreNonnullByDefault; - -import com.jozufozu.flywheel.core.PartialModel; -import com.simibubi.create.AllBlocks; -import com.simibubi.create.foundation.utility.BlockHelper; -import com.simibubi.create.foundation.utility.Couple; - -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.item.DyeColor; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -@ParametersAreNonnullByDefault -public class ValveHandleBlock extends HandCrankBlock { - - private final DyeColor color; - - public static ValveHandleBlock copper(Properties properties) { - return new ValveHandleBlock(properties, null); - } - - public static ValveHandleBlock dyed(Properties properties, DyeColor color) { - return new ValveHandleBlock(properties, color); - } - - private ValveHandleBlock(Properties properties, DyeColor color) { - super(properties); - this.color = color; - } - - @Override - public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, - BlockHitResult hit) { - ItemStack heldItem = player.getItemInHand(hand); - DyeColor color = DyeColor.getColor(heldItem); - if (color != null && color != this.color) { - if (world.isClientSide) - return InteractionResult.SUCCESS; - BlockState newState = BlockHelper.copyProperties(state, AllBlocks.DYED_VALVE_HANDLES.get(color).getDefaultState()); - world.setBlockAndUpdate(pos, newState); - return InteractionResult.SUCCESS; - } - - return super.use(state, world, pos, player, hand, hit); - } - - @Override - @OnlyIn(Dist.CLIENT) - public PartialModel getRenderedHandle() { - return null; - } - - @Override - public int getRotationSpeed() { - return 16; - } - - public static Couple getSpeedRange() { - return Couple.create(16, 16); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crusher/AbstractCrushingRecipe.java b/src/main/java/com/simibubi/create/content/contraptions/components/crusher/AbstractCrushingRecipe.java deleted file mode 100644 index ec8c290d4..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crusher/AbstractCrushingRecipe.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.simibubi.create.content.contraptions.components.crusher; - -import com.simibubi.create.content.contraptions.processing.ProcessingRecipe; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder.ProcessingRecipeParams; -import com.simibubi.create.foundation.utility.recipe.IRecipeTypeInfo; - -import net.minecraftforge.items.wrapper.RecipeWrapper; - -public abstract class AbstractCrushingRecipe extends ProcessingRecipe { - - public AbstractCrushingRecipe(IRecipeTypeInfo recipeType, ProcessingRecipeParams params) { - super(recipeType, params); - } - - @Override - protected int getMaxInputCount() { - return 1; - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelControllerTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelControllerTileEntity.java deleted file mode 100644 index 02014d05b..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelControllerTileEntity.java +++ /dev/null @@ -1,375 +0,0 @@ -package com.simibubi.create.content.contraptions.components.crusher; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.UUID; - -import com.simibubi.create.AllRecipeTypes; -import com.simibubi.create.content.contraptions.processing.ProcessingInventory; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipe; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.item.ItemHelper; -import com.simibubi.create.foundation.sound.SoundScapes; -import com.simibubi.create.foundation.sound.SoundScapes.AmbienceGroup; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.core.particles.BlockParticleOption; -import net.minecraft.core.particles.ItemParticleOption; -import net.minecraft.core.particles.ParticleOptions; -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtUtils; -import net.minecraft.util.Mth; -import net.minecraft.util.RandomSource; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.fml.DistExecutor; -import net.minecraftforge.items.CapabilityItemHandler; -import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.wrapper.RecipeWrapper; - -public class CrushingWheelControllerTileEntity extends SmartTileEntity { - - public Entity processingEntity; - private UUID entityUUID; - protected boolean searchForEntity; - - public ProcessingInventory inventory; - protected LazyOptional handler = LazyOptional.of(() -> inventory); - private RecipeWrapper wrapper; - public float crushingspeed; - - public CrushingWheelControllerTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - inventory = new ProcessingInventory(this::itemInserted) { - - @Override - public boolean isItemValid(int slot, ItemStack stack) { - return super.isItemValid(slot, stack) && processingEntity == null; - } - - }; - wrapper = new RecipeWrapper(inventory); - } - - @Override - public void addBehaviours(List behaviours) { - behaviours.add(new DirectBeltInputBehaviour(this).onlyInsertWhen(this::supportsDirectBeltInput)); - } - - private boolean supportsDirectBeltInput(Direction side) { - BlockState blockState = getBlockState(); - if (blockState == null) - return false; - Direction direction = blockState.getValue(CrushingWheelControllerBlock.FACING); - return direction == Direction.DOWN || direction == side; - } - - @Override - public void tick() { - super.tick(); - if (searchForEntity) { - searchForEntity = false; - List search = level.getEntities((Entity) null, new AABB(getBlockPos()), - e -> entityUUID.equals(e.getUUID())); - if (search.isEmpty()) - clear(); - else - processingEntity = search.get(0); - } - - if (!isOccupied()) - return; - if (crushingspeed == 0) - return; - - if (level.isClientSide) - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> this.tickAudio()); - - float speed = crushingspeed * 4; - - Vec3 centerPos = VecHelper.getCenterOf(worldPosition); - Direction facing = getBlockState().getValue(CrushingWheelControllerBlock.FACING); - int offset = facing.getAxisDirection() - .getStep(); - Vec3 outSpeed = new Vec3((facing.getAxis() == Axis.X ? 0.25D : 0.0D) * offset, - offset == 1 ? (facing.getAxis() == Axis.Y ? 0.5D : 0.0D) : 0.0D // Increased upwards speed so upwards - // crushing wheels shoot out the item - // properly. - , (facing.getAxis() == Axis.Z ? 0.25D : 0.0D) * offset); // No downwards speed, so downwards crushing wheels - // drop the items as before. - Vec3 outPos = centerPos.add((facing.getAxis() == Axis.X ? .55f * offset : 0f), - (facing.getAxis() == Axis.Y ? .55f * offset : 0f), (facing.getAxis() == Axis.Z ? .55f * offset : 0f)); - - if (!hasEntity()) { - - float processingSpeed = - Mth.clamp((speed) / (!inventory.appliedRecipe ? Mth.log2(inventory.getStackInSlot(0) - .getCount()) : 1), .25f, 20); - inventory.remainingTime -= processingSpeed; - spawnParticles(inventory.getStackInSlot(0)); - - if (level.isClientSide) - return; - - if (inventory.remainingTime < 20 && !inventory.appliedRecipe) { - applyRecipe(); - inventory.appliedRecipe = true; - level.sendBlockUpdated(worldPosition, getBlockState(), getBlockState(), 2 | 16); - return; - } - - if (inventory.remainingTime > 0) { - return; - } - inventory.remainingTime = 0; - - // Output Items - if (facing != Direction.UP) { - BlockPos nextPos = worldPosition.offset(facing.getAxis() == Axis.X ? 1f * offset : 0f, (-1f), - facing.getAxis() == Axis.Z ? 1f * offset : 0f); - DirectBeltInputBehaviour behaviour = - TileEntityBehaviour.get(level, nextPos, DirectBeltInputBehaviour.TYPE); - if (behaviour != null) { - boolean changed = false; - if (!behaviour.canInsertFromSide(facing)) - return; - for (int slot = 0; slot < inventory.getSlots(); slot++) { - ItemStack stack = inventory.getStackInSlot(slot); - if (stack.isEmpty()) - continue; - ItemStack remainder = behaviour.handleInsertion(stack, facing, false); - if (remainder.equals(stack, false)) - continue; - inventory.setStackInSlot(slot, remainder); - changed = true; - } - if (changed) { - setChanged(); - sendData(); - } - return; - } - } - - // Eject Items - for (int slot = 0; slot < inventory.getSlots(); slot++) { - ItemStack stack = inventory.getStackInSlot(slot); - if (stack.isEmpty()) - continue; - ItemEntity entityIn = new ItemEntity(level, outPos.x, outPos.y, outPos.z, stack); - entityIn.setDeltaMovement(outSpeed); - entityIn.getPersistentData() - .put("BypassCrushingWheel", NbtUtils.writeBlockPos(worldPosition)); - level.addFreshEntity(entityIn); - } - inventory.clear(); - level.sendBlockUpdated(worldPosition, getBlockState(), getBlockState(), 2 | 16); - - return; - } - - if (!processingEntity.isAlive() || !processingEntity.getBoundingBox() - .intersects(new AABB(worldPosition).inflate(.5f))) { - clear(); - return; - } - - double xMotion = ((worldPosition.getX() + .5f) - processingEntity.getX()) / 2f; - double zMotion = ((worldPosition.getZ() + .5f) - processingEntity.getZ()) / 2f; - if (processingEntity.isShiftKeyDown()) - xMotion = zMotion = 0; - double movement = Math.max(-speed / 4f, -.5f) * -offset; - processingEntity.setDeltaMovement( - new Vec3(facing.getAxis() == Axis.X ? movement : xMotion, facing.getAxis() == Axis.Y ? movement : 0f // Do - // not - // move - // entities - // upwards - // or - // downwards - // for - // horizontal - // crushers, - , facing.getAxis() == Axis.Z ? movement : zMotion)); // Or they'll only get their feet crushed. - - if (level.isClientSide) - return; - - if (!(processingEntity instanceof ItemEntity)) { - Vec3 entityOutPos = outPos.add(facing.getAxis() == Axis.X ? .5f * offset : 0f, - facing.getAxis() == Axis.Y ? .5f * offset : 0f, facing.getAxis() == Axis.Z ? .5f * offset : 0f); - int crusherDamage = AllConfigs.SERVER.kinetics.crushingDamage.get(); - - if (processingEntity instanceof LivingEntity) { - if ((((LivingEntity) processingEntity).getHealth() - crusherDamage <= 0) // Takes LivingEntity instances - // as exception, so it can - // move them before it would - // kill them. - && (((LivingEntity) processingEntity).hurtTime <= 0)) { // This way it can actually output the items - // to the right spot. - processingEntity.setPos(entityOutPos.x, entityOutPos.y, entityOutPos.z); - } - } - processingEntity.hurt(CrushingWheelTileEntity.DAMAGE_SOURCE, crusherDamage); - if (!processingEntity.isAlive()) { - processingEntity.setPos(entityOutPos.x, entityOutPos.y, entityOutPos.z); - } - return; - } - - ItemEntity itemEntity = (ItemEntity) processingEntity; - itemEntity.setPickUpDelay(20); - if (facing.getAxis() == Axis.Y) { - if (processingEntity.getY() * -offset < (centerPos.y - .25f) * -offset) { - intakeItem(itemEntity); - } - } else if (facing.getAxis() == Axis.Z) { - if (processingEntity.getZ() * -offset < (centerPos.z - .25f) * -offset) { - intakeItem(itemEntity); - } - } else { - if (processingEntity.getX() * -offset < (centerPos.x - .25f) * -offset) { - intakeItem(itemEntity); - } - } - } - - @OnlyIn(Dist.CLIENT) - public void tickAudio() { - float pitch = Mth.clamp((crushingspeed / 256f) + .45f, .85f, 1f); - if (entityUUID == null && inventory.getStackInSlot(0) - .isEmpty()) - return; - SoundScapes.play(AmbienceGroup.CRUSHING, worldPosition, pitch); - } - - private void intakeItem(ItemEntity itemEntity) { - inventory.clear(); - inventory.setStackInSlot(0, itemEntity.getItem() - .copy()); - itemInserted(inventory.getStackInSlot(0)); - itemEntity.discard(); - level.sendBlockUpdated(worldPosition, getBlockState(), getBlockState(), 2 | 16); - } - - protected void spawnParticles(ItemStack stack) { - if (stack == null || stack.isEmpty()) - return; - - ParticleOptions particleData = null; - if (stack.getItem() instanceof BlockItem) - particleData = new BlockParticleOption(ParticleTypes.BLOCK, ((BlockItem) stack.getItem()).getBlock() - .defaultBlockState()); - else - particleData = new ItemParticleOption(ParticleTypes.ITEM, stack); - - RandomSource r = level.random; - for (int i = 0; i < 4; i++) - level.addParticle(particleData, worldPosition.getX() + r.nextFloat(), worldPosition.getY() + r.nextFloat(), - worldPosition.getZ() + r.nextFloat(), 0, 0, 0); - } - - private void applyRecipe() { - Optional> recipe = findRecipe(); - - List list = new ArrayList<>(); - if (recipe.isPresent()) { - int rolls = inventory.getStackInSlot(0) - .getCount(); - inventory.clear(); - for (int roll = 0; roll < rolls; roll++) { - List rolledResults = recipe.get() - .rollResults(); - for (int i = 0; i < rolledResults.size(); i++) { - ItemStack stack = rolledResults.get(i); - ItemHelper.addToList(stack, list); - } - } - for (int slot = 0; slot < list.size() && slot + 1 < inventory.getSlots(); slot++) - inventory.setStackInSlot(slot + 1, list.get(slot)); - } else { - inventory.clear(); - } - - } - - public Optional> findRecipe() { - Optional> crushingRecipe = AllRecipeTypes.CRUSHING.find(wrapper, level); - if (!crushingRecipe.isPresent()) - crushingRecipe = AllRecipeTypes.MILLING.find(wrapper, level); - return crushingRecipe; - } - - @Override - public void write(CompoundTag compound, boolean clientPacket) { - if (hasEntity()) - compound.put("Entity", NbtUtils.createUUID(entityUUID)); - compound.put("Inventory", inventory.serializeNBT()); - compound.putFloat("Speed", crushingspeed); - super.write(compound, clientPacket); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - super.read(compound, clientPacket); - if (compound.contains("Entity") && !isOccupied()) { - entityUUID = NbtUtils.loadUUID(NBTHelper.getINBT(compound, "Entity")); - this.searchForEntity = true; - } - crushingspeed = compound.getFloat("Speed"); - inventory.deserializeNBT(compound.getCompound("Inventory")); - } - - public void startCrushing(Entity entity) { - processingEntity = entity; - entityUUID = entity.getUUID(); - } - - private void itemInserted(ItemStack stack) { - Optional> recipe = findRecipe(); - inventory.remainingTime = recipe.isPresent() ? recipe.get() - .getProcessingDuration() : 100; - inventory.appliedRecipe = false; - } - - @Override - public LazyOptional getCapability(Capability cap, Direction side) { - if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) - return handler.cast(); - return super.getCapability(cap, side); - } - - public void clear() { - processingEntity = null; - entityUUID = null; - } - - public boolean isOccupied() { - return hasEntity() || !inventory.isEmpty(); - } - - public boolean hasEntity() { - return processingEntity != null; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelTileEntity.java deleted file mode 100644 index 7cedbe8ce..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelTileEntity.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.simibubi.create.content.contraptions.components.crusher; - -import java.util.List; - -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.utility.Iterate; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.event.entity.living.LivingDropsEvent; -import net.minecraftforge.event.entity.living.LootingLevelEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod.EventBusSubscriber; - -@EventBusSubscriber -public class CrushingWheelTileEntity extends KineticTileEntity { - - public static final DamageSource DAMAGE_SOURCE = new DamageSource("create.crush").bypassArmor() - .setScalesWithDifficulty(); - - public CrushingWheelTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - setLazyTickRate(20); - } - - @Override - public void addBehaviours(List behaviours) { - super.addBehaviours(behaviours); - registerAwardables(behaviours, AllAdvancements.CRUSHING_WHEEL, AllAdvancements.CRUSHER_MAXED); - } - - @Override - public void onSpeedChanged(float prevSpeed) { - super.onSpeedChanged(prevSpeed); - fixControllers(); - } - - public void fixControllers() { - for (Direction d : Iterate.directions) - ((CrushingWheelBlock) getBlockState().getBlock()).updateControllers(getBlockState(), getLevel(), getBlockPos(), - d); - } - - @Override - protected AABB createRenderBoundingBox() { - return new AABB(worldPosition).inflate(1); - } - - @Override - public void lazyTick() { - super.lazyTick(); - fixControllers(); - } - - @SubscribeEvent - public static void crushingIsFortunate(LootingLevelEvent event) { - if (event.getDamageSource() != DAMAGE_SOURCE) - return; - event.setLootingLevel(2); //This does not currently increase mob drops. It seems like this only works for damage done by an entity. - } - - @SubscribeEvent - public static void handleCrushedMobDrops(LivingDropsEvent event) { - if (event.getSource() != CrushingWheelTileEntity.DAMAGE_SOURCE) - return; - Vec3 outSpeed = Vec3.ZERO; - for (ItemEntity outputItem : event.getDrops()) { - outputItem.setDeltaMovement(outSpeed); - } - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/BeltDeployerCallbacks.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/BeltDeployerCallbacks.java deleted file mode 100644 index 82b69aa97..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/BeltDeployerCallbacks.java +++ /dev/null @@ -1,176 +0,0 @@ -package com.simibubi.create.content.contraptions.components.deployer; - -import static com.simibubi.create.content.contraptions.base.DirectionalKineticBlock.FACING; - -import java.util.List; -import java.util.stream.Collectors; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.Create; -import com.simibubi.create.content.contraptions.components.deployer.DeployerTileEntity.Mode; -import com.simibubi.create.content.contraptions.components.deployer.DeployerTileEntity.State; -import com.simibubi.create.content.contraptions.processing.InWorldProcessing; -import com.simibubi.create.content.contraptions.processing.ItemApplicationRecipe; -import com.simibubi.create.content.contraptions.relays.belt.BeltHelper; -import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack; -import com.simibubi.create.content.curiosities.tools.SandPaperPolishingRecipe; -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.advancement.CreateAdvancement; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProcessingBehaviour.ProcessingResult; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour.TransportedResult; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.Recipe; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.items.ItemHandlerHelper; - -public class BeltDeployerCallbacks { - - public static ProcessingResult onItemReceived(TransportedItemStack s, TransportedItemStackHandlerBehaviour i, - DeployerTileEntity deployerTileEntity) { - - if (deployerTileEntity.getSpeed() == 0) - return ProcessingResult.PASS; - if (deployerTileEntity.mode == Mode.PUNCH) - return ProcessingResult.PASS; - BlockState blockState = deployerTileEntity.getBlockState(); - if (!blockState.hasProperty(FACING) || blockState.getValue(FACING) != Direction.DOWN) - return ProcessingResult.PASS; - if (deployerTileEntity.state != State.WAITING) - return ProcessingResult.HOLD; - if (deployerTileEntity.redstoneLocked) - return ProcessingResult.PASS; - - DeployerFakePlayer player = deployerTileEntity.getPlayer(); - ItemStack held = player == null ? ItemStack.EMPTY : player.getMainHandItem(); - - if (held.isEmpty()) - return ProcessingResult.HOLD; - if (deployerTileEntity.getRecipe(s.stack) == null) - return ProcessingResult.PASS; - - deployerTileEntity.start(); - return ProcessingResult.HOLD; - } - - public static ProcessingResult whenItemHeld(TransportedItemStack s, TransportedItemStackHandlerBehaviour i, - DeployerTileEntity deployerTileEntity) { - - if (deployerTileEntity.getSpeed() == 0) - return ProcessingResult.PASS; - BlockState blockState = deployerTileEntity.getBlockState(); - if (!blockState.hasProperty(FACING) || blockState.getValue(FACING) != Direction.DOWN) - return ProcessingResult.PASS; - - DeployerFakePlayer player = deployerTileEntity.getPlayer(); - ItemStack held = player == null ? ItemStack.EMPTY : player.getMainHandItem(); - if (held.isEmpty()) - return ProcessingResult.HOLD; - - Recipe recipe = deployerTileEntity.getRecipe(s.stack); - if (recipe == null) - return ProcessingResult.PASS; - - if (deployerTileEntity.state == State.RETRACTING && deployerTileEntity.timer == 1000) { - activate(s, i, deployerTileEntity, recipe); - return ProcessingResult.HOLD; - } - - if (deployerTileEntity.state == State.WAITING) { - if (deployerTileEntity.redstoneLocked) - return ProcessingResult.PASS; - deployerTileEntity.start(); - } - - return ProcessingResult.HOLD; - } - - public static void activate(TransportedItemStack transported, TransportedItemStackHandlerBehaviour handler, - DeployerTileEntity deployerTileEntity, Recipe recipe) { - - List collect = - InWorldProcessing.applyRecipeOn(ItemHandlerHelper.copyStackWithSize(transported.stack, 1), recipe) - .stream() - .map(stack -> { - TransportedItemStack copy = transported.copy(); - boolean centered = BeltHelper.isItemUpright(stack); - copy.stack = stack; - copy.locked = true; - copy.angle = centered ? 180 : Create.RANDOM.nextInt(360); - return copy; - }) - .map(t -> { - t.locked = false; - return t; - }) - .collect(Collectors.toList()); - - deployerTileEntity.award(AllAdvancements.DEPLOYER); - - TransportedItemStack left = transported.copy(); - deployerTileEntity.player.spawnedItemEffects = transported.stack.copy(); - left.stack.shrink(1); - ItemStack resultItem = null; - - if (collect.isEmpty()) { - resultItem = left.stack.copy(); - handler.handleProcessingOnItem(transported, TransportedResult.convertTo(left)); - } else { - resultItem = collect.get(0).stack.copy(); - handler.handleProcessingOnItem(transported, TransportedResult.convertToAndLeaveHeld(collect, left)); - } - - ItemStack heldItem = deployerTileEntity.player.getMainHandItem(); - boolean unbreakable = heldItem.hasTag() && heldItem.getTag() - .getBoolean("Unbreakable"); - boolean keepHeld = - recipe instanceof ItemApplicationRecipe && ((ItemApplicationRecipe) recipe).shouldKeepHeldItem(); - - if (!unbreakable && !keepHeld) { - if (heldItem.isDamageableItem()) - heldItem.hurtAndBreak(1, deployerTileEntity.player, - s -> s.broadcastBreakEvent(InteractionHand.MAIN_HAND)); - else - heldItem.shrink(1); - } - - if (resultItem != null && !resultItem.isEmpty()) - awardAdvancements(deployerTileEntity, resultItem); - - BlockPos pos = deployerTileEntity.getBlockPos(); - Level world = deployerTileEntity.getLevel(); - if (heldItem.isEmpty()) - world.playSound(null, pos, SoundEvents.ITEM_BREAK, SoundSource.BLOCKS, .25f, 1); - world.playSound(null, pos, SoundEvents.ITEM_PICKUP, SoundSource.BLOCKS, .25f, .75f); - if (recipe instanceof SandPaperPolishingRecipe) - AllSoundEvents.SANDING_SHORT.playOnServer(world, pos, .35f, 1f); - - deployerTileEntity.sendData(); - } - - private static void awardAdvancements(DeployerTileEntity deployerTileEntity, ItemStack created) { - CreateAdvancement advancement = null; - - if (AllBlocks.ANDESITE_CASING.isIn(created)) - advancement = AllAdvancements.ANDESITE_CASING; - else if (AllBlocks.BRASS_CASING.isIn(created)) - advancement = AllAdvancements.BRASS_CASING; - else if (AllBlocks.COPPER_CASING.isIn(created)) - advancement = AllAdvancements.COPPER_CASING; - else if (AllBlocks.RAILWAY_CASING.isIn(created)) - advancement = AllAdvancements.TRAIN_CASING; - else - return; - - deployerTileEntity.award(advancement); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerBlock.java deleted file mode 100644 index 673789b4d..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerBlock.java +++ /dev/null @@ -1,128 +0,0 @@ -package com.simibubi.create.content.contraptions.components.deployer; - -import javax.annotation.ParametersAreNonnullByDefault; - -import com.simibubi.create.AllItems; -import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.DirectionalAxisKineticBlock; -import com.simibubi.create.content.contraptions.components.AssemblyOperatorUseContext; -import com.simibubi.create.foundation.block.ITE; - -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -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.item.context.BlockPlaceContext; -import net.minecraft.world.item.context.UseOnContext; -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.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.PushReaction; -import net.minecraft.world.level.pathfinder.PathComputationType; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.VoxelShape; - -@ParametersAreNonnullByDefault -@MethodsReturnNonnullByDefault -public class DeployerBlock extends DirectionalAxisKineticBlock implements ITE { - - public DeployerBlock(Properties properties) { - super(properties); - } - - @Override - public PushReaction getPistonPushReaction(BlockState state) { - return PushReaction.NORMAL; - } - - @Override - public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) { - return AllShapes.CASING_12PX.get(state.getValue(FACING)); - } - - @Override - public InteractionResult onWrenched(BlockState state, UseOnContext context) { - if (context.getClickedFace() == state.getValue(FACING)) { - if (!context.getLevel().isClientSide) - withTileEntityDo(context.getLevel(), context.getClickedPos(), DeployerTileEntity::changeMode); - return InteractionResult.SUCCESS; - } - return super.onWrenched(state, context); - } - - @Override - public void onRemove(BlockState state, Level worldIn, BlockPos pos, BlockState newState, boolean isMoving) { - if (!isMoving && !state.is(newState.getBlock())) - withTileEntityDo(worldIn, pos, DeployerTileEntity::discardPlayer); - super.onRemove(state, worldIn, pos, newState, isMoving); - } - - @Override - public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, - BlockHitResult hit) { - ItemStack heldByPlayer = player.getItemInHand(handIn) - .copy(); - if (AllItems.WRENCH.isIn(heldByPlayer)) - return InteractionResult.PASS; - - if (hit.getDirection() != state.getValue(FACING)) - return InteractionResult.PASS; - if (worldIn.isClientSide) - return InteractionResult.SUCCESS; - - withTileEntityDo(worldIn, pos, te -> { - ItemStack heldByDeployer = te.player.getMainHandItem() - .copy(); - if (heldByDeployer.isEmpty() && heldByPlayer.isEmpty()) - return; - - player.setItemInHand(handIn, heldByDeployer); - te.player.setItemInHand(InteractionHand.MAIN_HAND, heldByPlayer); - te.sendData(); - }); - - return InteractionResult.SUCCESS; - } - - @Override - public Class getTileEntityClass() { - return DeployerTileEntity.class; - } - - @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.DEPLOYER.get(); - } - - @Override - public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean isMoving) { - super.onPlace(state, world, pos, oldState, isMoving); - withTileEntityDo(world, pos, DeployerTileEntity::redstoneUpdate); - } - - @Override - public void neighborChanged(BlockState state, Level world, BlockPos pos, Block p_220069_4_, BlockPos p_220069_5_, - boolean p_220069_6_) { - withTileEntityDo(world, pos, DeployerTileEntity::redstoneUpdate); - } - - @Override - public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) { - return false; - } - - @Override - protected Direction getFacingForPlacement(BlockPlaceContext context) { - if (context instanceof AssemblyOperatorUseContext) - return Direction.DOWN; - else - return super.getFacingForPlacement(context); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerFakePlayer.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerFakePlayer.java deleted file mode 100644 index 89f732c9b..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerFakePlayer.java +++ /dev/null @@ -1,178 +0,0 @@ -package com.simibubi.create.content.contraptions.components.deployer; - -import java.util.OptionalInt; -import java.util.UUID; - -import javax.annotation.Nullable; - -import org.apache.commons.lang3.tuple.Pair; - -import com.mojang.authlib.GameProfile; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.config.CKinetics; -import com.simibubi.create.foundation.utility.Lang; - -import net.minecraft.core.BlockPos; -import net.minecraft.network.Connection; -import net.minecraft.network.PacketSendListener; -import net.minecraft.network.chat.Component; -import net.minecraft.network.protocol.Packet; -import net.minecraft.network.protocol.PacketFlow; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.server.network.ServerGamePacketListenerImpl; -import net.minecraft.world.MenuProvider; -import net.minecraft.world.damagesource.EntityDamageSource; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.Mob; -import net.minecraft.world.entity.Pose; -import net.minecraft.world.entity.monster.Creeper; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.common.util.FakePlayer; -import net.minecraftforge.event.entity.EntityEvent; -import net.minecraftforge.event.entity.living.LivingDropsEvent; -import net.minecraftforge.event.entity.living.LivingExperienceDropEvent; -import net.minecraftforge.event.entity.living.LivingSetAttackTargetEvent; -import net.minecraftforge.eventbus.api.EventPriority; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod.EventBusSubscriber; - -@EventBusSubscriber -public class DeployerFakePlayer extends FakePlayer { - - private static final Connection NETWORK_MANAGER = new Connection(PacketFlow.CLIENTBOUND); - public static final GameProfile DEPLOYER_PROFILE = - new GameProfile(UUID.fromString("9e2faded-cafe-4ec2-c314-dad129ae971d"), "Deployer"); - Pair blockBreakingProgress; - ItemStack spawnedItemEffects; - public boolean placedTracks; - public boolean onMinecartContraption; - - public DeployerFakePlayer(ServerLevel world) { - super(world, DEPLOYER_PROFILE); - connection = new FakePlayNetHandler(world.getServer(), this); - } - - @Override - public OptionalInt openMenu(MenuProvider container) { - return OptionalInt.empty(); - } - - @Override - public Component getDisplayName() { - return Lang.translateDirect("block.deployer.damage_source_name"); - } - - @Override - @OnlyIn(Dist.CLIENT) - public float getEyeHeight(Pose poseIn) { - return 0; - } - - @Override - public Vec3 position() { - return new Vec3(getX(), getY(), getZ()); - } - - @Override - public float getCurrentItemAttackStrengthDelay() { - return 1 / 64f; - } - - @Override - public boolean canEat(boolean ignoreHunger) { - return false; - } - - @Override - public ItemStack eat(Level world, ItemStack stack) { - stack.shrink(1); - return stack; - } - - @SubscribeEvent - public static void deployerHasEyesOnHisFeet(EntityEvent.Size event) { - if (event.getEntity() instanceof DeployerFakePlayer) - event.setNewEyeHeight(0); - } - - @SubscribeEvent(priority = EventPriority.LOWEST) - public static void deployerCollectsDropsFromKilledEntities(LivingDropsEvent event) { - if (!(event.getSource() instanceof EntityDamageSource)) - return; - EntityDamageSource source = (EntityDamageSource) event.getSource(); - Entity trueSource = source.getEntity(); - if (trueSource != null && trueSource instanceof DeployerFakePlayer) { - DeployerFakePlayer fakePlayer = (DeployerFakePlayer) trueSource; - event.getDrops() - .forEach(stack -> fakePlayer.getInventory() - .placeItemBackInInventory(stack.getItem())); - event.setCanceled(true); - } - } - - @Override - protected boolean doesEmitEquipEvent(EquipmentSlot p_217035_) { - return false; - } - - @Override - protected void playEquipSound(ItemStack p_217042_) {} - - @Override - public void remove(RemovalReason p_150097_) { - if (blockBreakingProgress != null && !level.isClientSide) - level.destroyBlockProgress(getId(), blockBreakingProgress.getKey(), -1); - super.remove(p_150097_); - } - - @SubscribeEvent - public static void deployerKillsDoNotSpawnXP(LivingExperienceDropEvent event) { - if (event.getAttackingPlayer() instanceof DeployerFakePlayer) - event.setCanceled(true); - } - - @SubscribeEvent - public static void entitiesDontRetaliate(LivingSetAttackTargetEvent event) { - if (!(event.getTarget() instanceof DeployerFakePlayer)) - return; - LivingEntity entityLiving = event.getEntity(); - if (!(entityLiving instanceof Mob)) - return; - Mob mob = (Mob) entityLiving; - - CKinetics.DeployerAggroSetting setting = AllConfigs.SERVER.kinetics.ignoreDeployerAttacks.get(); - - switch (setting) { - case ALL: - mob.setTarget(null); - break; - case CREEPERS: - if (mob instanceof Creeper) - mob.setTarget(null); - break; - case NONE: - default: - } - } - - private static class FakePlayNetHandler extends ServerGamePacketListenerImpl { - public FakePlayNetHandler(MinecraftServer server, ServerPlayer playerIn) { - super(server, NETWORK_MANAGER, playerIn); - } - - @Override - public void send(Packet packetIn) {} - - @Override - public void send(Packet p_243227_, @Nullable PacketSendListener p_243273_) {} - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerFilterSlot.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerFilterSlot.java deleted file mode 100644 index ae37feff1..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerFilterSlot.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.simibubi.create.content.contraptions.components.deployer; - -import com.jozufozu.flywheel.util.transform.TransformStack; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; - -public class DeployerFilterSlot extends ValueBoxTransform { - - @Override - protected Vec3 getLocalOffset(BlockState state) { - Direction facing = state.getValue(DeployerBlock.FACING); - Vec3 vec = VecHelper.voxelSpace(8f, 13.5f, 11.5f); - - float yRot = AngleHelper.horizontalAngle(facing); - float xRot = facing == Direction.UP ? 270 : facing == Direction.DOWN ? 90 : 0; - vec = VecHelper.rotateCentered(vec, yRot, Axis.Y); - vec = VecHelper.rotateCentered(vec, xRot, Axis.X); - - return vec; - } - - @Override - protected void rotate(BlockState state, PoseStack ms) { - Direction facing = state.getValue(DeployerBlock.FACING); - float xRot = facing == Direction.UP ? 90 : facing == Direction.DOWN ? 270 : 0; - float yRot = AngleHelper.horizontalAngle(facing) + 180; - TransformStack.cast(ms) - .rotateY(yRot) - .rotateX(xRot); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerInstance.java deleted file mode 100644 index f1100d10f..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerInstance.java +++ /dev/null @@ -1,137 +0,0 @@ -package com.simibubi.create.content.contraptions.components.deployer; - -import static com.simibubi.create.content.contraptions.base.DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE; -import static com.simibubi.create.content.contraptions.base.DirectionalKineticBlock.FACING; - -import org.joml.Quaternionf; - -import com.jozufozu.flywheel.api.MaterialManager; -import com.jozufozu.flywheel.api.instance.DynamicInstance; -import com.jozufozu.flywheel.api.instance.TickableInstance; -import com.jozufozu.flywheel.core.PartialModel; -import com.jozufozu.flywheel.core.materials.oriented.OrientedData; -import com.mojang.math.Axis; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.relays.encased.ShaftInstance; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Vec3i; -import net.minecraft.util.Mth; - -public class DeployerInstance extends ShaftInstance implements DynamicInstance, TickableInstance { - - final DeployerTileEntity tile; - final Direction facing; - final float yRot; - final float xRot; - final float zRot; - - protected final OrientedData pole; - - protected OrientedData hand; - - PartialModel currentHand; - float progress; - - public DeployerInstance(MaterialManager dispatcher, KineticTileEntity tile) { - super(dispatcher, tile); - - this.tile = (DeployerTileEntity) super.blockEntity; - facing = blockState.getValue(FACING); - - boolean rotatePole = blockState.getValue(AXIS_ALONG_FIRST_COORDINATE) ^ facing.getAxis() == Direction.Axis.Z; - - yRot = AngleHelper.horizontalAngle(facing); - xRot = facing == Direction.UP ? 270 : facing == Direction.DOWN ? 90 : 0; - zRot = rotatePole ? 90 : 0; - - pole = getOrientedMaterial().getModel(AllBlockPartials.DEPLOYER_POLE, blockState).createInstance(); - - currentHand = this.tile.getHandPose(); - - hand = getOrientedMaterial().getModel(currentHand, blockState).createInstance(); - - progress = getProgress(AnimationTickHolder.getPartialTicks()); - updateRotation(pole, hand, yRot, xRot, zRot); - updatePosition(); - } - - @Override - public void tick() { - PartialModel handPose = tile.getHandPose(); - - if (currentHand != handPose) { - currentHand = handPose; - getOrientedMaterial().getModel(currentHand, blockState) - .stealInstance(hand); - } - } - - @Override - public void beginFrame() { - - float newProgress = getProgress(AnimationTickHolder.getPartialTicks()); - - if (Mth.equal(newProgress, progress)) return; - - progress = newProgress; - - updatePosition(); - } - - @Override - public void updateLight() { - super.updateLight(); - relight(pos, hand, pole); - } - - @Override - public void remove() { - super.remove(); - hand.delete(); - pole.delete(); - } - - private float getProgress(float partialTicks) { - if (tile.state == DeployerTileEntity.State.EXPANDING) { - float f = 1 - (tile.timer - partialTicks * tile.getTimerSpeed()) / 1000f; - if (tile.fistBump) - f *= f; - return f; - } - if (tile.state == DeployerTileEntity.State.RETRACTING) - return (tile.timer - partialTicks * tile.getTimerSpeed()) / 1000f; - return 0; - } - - private void updatePosition() { - float handLength = currentHand == AllBlockPartials.DEPLOYER_HAND_POINTING ? 0 - : currentHand == AllBlockPartials.DEPLOYER_HAND_HOLDING ? 4 / 16f : 3 / 16f; - float distance = Math.min(Mth.clamp(progress, 0, 1) * (tile.reach + handLength), 21 / 16f); - Vec3i facingVec = facing.getNormal(); - BlockPos blockPos = getInstancePosition(); - - float x = blockPos.getX() + ((float) facingVec.getX()) * distance; - float y = blockPos.getY() + ((float) facingVec.getY()) * distance; - float z = blockPos.getZ() + ((float) facingVec.getZ()) * distance; - - pole.setPosition(x, y, z); - hand.setPosition(x, y, z); - } - - static void updateRotation(OrientedData pole, OrientedData hand, float yRot, float xRot, float zRot) { - - Quaternionf q = Axis.YP.rotationDegrees(yRot); - q.mul(Axis.XP.rotationDegrees(xRot)); - - hand.setRotation(q); - - q.mul(Axis.ZP.rotationDegrees(zRot)); - - pole.setRotation(q); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerItemHandler.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerItemHandler.java deleted file mode 100644 index 5d8b00047..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerItemHandler.java +++ /dev/null @@ -1,131 +0,0 @@ -package com.simibubi.create.content.contraptions.components.deployer; - -import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; - -import net.minecraft.world.InteractionHand; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.ItemHandlerHelper; - -public class DeployerItemHandler implements IItemHandlerModifiable { - - private DeployerTileEntity te; - private DeployerFakePlayer player; - - public DeployerItemHandler(DeployerTileEntity te) { - this.te = te; - this.player = te.player; - } - - @Override - public int getSlots() { - return 1 + te.overflowItems.size(); - } - - @Override - public ItemStack getStackInSlot(int slot) { - return slot >= te.overflowItems.size() ? getHeld() : te.overflowItems.get(slot); - } - - public ItemStack getHeld() { - if (player == null) - return ItemStack.EMPTY; - return player.getMainHandItem(); - } - - public void set(ItemStack stack) { - if (player == null) - return; - if (te.getLevel().isClientSide) - return; - player.setItemInHand(InteractionHand.MAIN_HAND, stack); - te.setChanged(); - te.sendData(); - } - - @Override - public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) { - if (slot < te.overflowItems.size()) - return stack; - if (!isItemValid(slot, stack)) - return stack; - - ItemStack held = getHeld(); - if (held.isEmpty()) { - if (!simulate) - set(stack); - return ItemStack.EMPTY; - } - - if (!ItemHandlerHelper.canItemStacksStack(held, stack)) - return stack; - - int space = held.getMaxStackSize() - held.getCount(); - ItemStack remainder = stack.copy(); - ItemStack split = remainder.split(space); - - if (space == 0) - return stack; - if (!simulate) { - held = held.copy(); - held.setCount(held.getCount() + split.getCount()); - set(held); - } - - return remainder; - } - - @Override - public ItemStack extractItem(int slot, int amount, boolean simulate) { - if (amount == 0) - return ItemStack.EMPTY; - - if (slot < te.overflowItems.size()) { - ItemStack itemStack = te.overflowItems.get(slot); - int toExtract = Math.min(amount, itemStack.getCount()); - ItemStack extracted = simulate ? itemStack.copy() : itemStack.split(toExtract); - extracted.setCount(toExtract); - if (!simulate && itemStack.isEmpty()) - te.overflowItems.remove(slot); - if (!simulate && !extracted.isEmpty()) - te.setChanged(); - return extracted; - } - - ItemStack held = getHeld(); - if (amount == 0 || held.isEmpty()) - return ItemStack.EMPTY; - if (!te.filtering.getFilter() - .isEmpty() && te.filtering.test(held)) - return ItemStack.EMPTY; - if (simulate) - return held.copy() - .split(amount); - - ItemStack toReturn = held.split(amount); - te.setChanged(); - te.sendData(); - return toReturn; - } - - @Override - public int getSlotLimit(int slot) { - return Math.min(getStackInSlot(slot).getMaxStackSize(), 64); - } - - @Override - public boolean isItemValid(int slot, ItemStack stack) { - FilteringBehaviour filteringBehaviour = te.getBehaviour(FilteringBehaviour.TYPE); - return filteringBehaviour == null || filteringBehaviour.test(stack); - } - - @Override - public void setStackInSlot(int slot, ItemStack stack) { - if (slot < te.overflowItems.size()) { - te.overflowItems.set(slot, stack); - return; - } - set(stack); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerMovingInteraction.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerMovingInteraction.java deleted file mode 100644 index 58bedbfd1..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerMovingInteraction.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.simibubi.create.content.contraptions.components.deployer; - -import org.apache.commons.lang3.tuple.MutablePair; - -import com.simibubi.create.AllItems; -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; -import com.simibubi.create.content.contraptions.components.structureMovement.MovingInteractionBehaviour; -import com.simibubi.create.content.contraptions.components.structureMovement.mounted.MountedContraption; -import com.simibubi.create.foundation.utility.NBTHelper; - -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.Tag; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; - -public class DeployerMovingInteraction extends MovingInteractionBehaviour { - - @Override - public boolean handlePlayerInteraction(Player player, InteractionHand activeHand, BlockPos localPos, - AbstractContraptionEntity contraptionEntity) { - StructureBlockInfo info = contraptionEntity.getContraption() - .getBlocks() - .get(localPos); - if (info == null) - return false; - MovementContext ctx = null; - int index = -1; - for (MutablePair pair : contraptionEntity.getContraption() - .getActors()) { - if (info.equals(pair.left)) { - ctx = pair.right; - index = contraptionEntity.getContraption() - .getActors() - .indexOf(pair); - break; - } - } - if (ctx == null) - return false; - - ItemStack heldStack = player.getItemInHand(activeHand); - if (heldStack.getItem() - .equals(AllItems.WRENCH.get())) { - DeployerTileEntity.Mode mode = NBTHelper.readEnum(ctx.tileData, "Mode", DeployerTileEntity.Mode.class); - NBTHelper.writeEnum(ctx.tileData, "Mode", - mode == DeployerTileEntity.Mode.PUNCH ? DeployerTileEntity.Mode.USE : DeployerTileEntity.Mode.PUNCH); - - } else { - if (ctx.world.isClientSide) - return true; // we'll try again on the server side - DeployerFakePlayer fake = null; - - if (!(ctx.temporaryData instanceof DeployerFakePlayer) && ctx.world instanceof ServerLevel) { - DeployerFakePlayer deployerFakePlayer = new DeployerFakePlayer((ServerLevel) ctx.world); - deployerFakePlayer.onMinecartContraption = ctx.contraption instanceof MountedContraption; - deployerFakePlayer.getInventory() - .load(ctx.tileData.getList("Inventory", Tag.TAG_COMPOUND)); - ctx.temporaryData = fake = deployerFakePlayer; - ctx.tileData.remove("Inventory"); - } else - fake = (DeployerFakePlayer) ctx.temporaryData; - - if (fake == null) - return false; - - ItemStack deployerItem = fake.getMainHandItem(); - player.setItemInHand(activeHand, deployerItem.copy()); - fake.setItemInHand(InteractionHand.MAIN_HAND, heldStack.copy()); - ctx.tileData.put("HeldItem", heldStack.serializeNBT()); - ctx.data.put("HeldItem", heldStack.serializeNBT()); - } - if (index >= 0) - setContraptionActorData(contraptionEntity, index, info, ctx); - return true; - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerRenderer.java deleted file mode 100644 index 3e353633f..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerRenderer.java +++ /dev/null @@ -1,229 +0,0 @@ -package com.simibubi.create.content.contraptions.components.deployer; - -import static com.simibubi.create.content.contraptions.base.DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE; -import static com.simibubi.create.content.contraptions.base.DirectionalKineticBlock.FACING; - -import com.jozufozu.flywheel.backend.Backend; -import com.jozufozu.flywheel.core.PartialModel; -import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; -import com.jozufozu.flywheel.util.transform.TransformStack; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import com.mojang.math.Axis; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.base.IRotate; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.content.contraptions.components.deployer.DeployerTileEntity.Mode; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringRenderer; -import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.block.model.ItemTransforms.TransformType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.client.renderer.entity.ItemRenderer; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.AxisDirection; -import net.minecraft.util.Mth; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; - -public class DeployerRenderer extends SafeTileEntityRenderer { - - public DeployerRenderer(BlockEntityRendererProvider.Context context) { - } - - @Override - protected void renderSafe(DeployerTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - renderItem(te, partialTicks, ms, buffer, light, overlay); - FilteringRenderer.renderOnTileEntity(te, partialTicks, ms, buffer, light, overlay); - - if (Backend.canUseInstancing(te.getLevel())) return; - - renderComponents(te, partialTicks, ms, buffer, light, overlay); - } - - protected void renderItem(DeployerTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - - if (te.heldItem.isEmpty()) return; - - BlockState deployerState = te.getBlockState(); - Vec3 offset = getHandOffset(te, partialTicks, deployerState).add(VecHelper.getCenterOf(BlockPos.ZERO)); - ms.pushPose(); - ms.translate(offset.x, offset.y, offset.z); - - Direction facing = deployerState.getValue(FACING); - boolean punching = te.mode == Mode.PUNCH; - - float yRot = AngleHelper.horizontalAngle(facing) + 180; - float xRot = facing == Direction.UP ? 90 : facing == Direction.DOWN ? 270 : 0; - boolean displayMode = facing == Direction.UP && te.getSpeed() == 0 && !punching; - - ms.mulPose(Axis.YP.rotationDegrees(yRot)); - if (!displayMode) { - ms.mulPose(Axis.XP.rotationDegrees(xRot)); - ms.translate(0, 0, -11 / 16f); - } - - if (punching) - ms.translate(0, 1 / 8f, -1 / 16f); - - ItemRenderer itemRenderer = Minecraft.getInstance() - .getItemRenderer(); - - TransformType transform = TransformType.NONE; - boolean isBlockItem = (te.heldItem.getItem() instanceof BlockItem) - && itemRenderer.getModel(te.heldItem, te.getLevel(), null, 0) - .isGui3d(); - - if (displayMode) { - float scale = isBlockItem ? 1.25f : 1; - ms.translate(0, isBlockItem ? 9 / 16f : 11 / 16f, 0); - ms.scale(scale, scale, scale); - transform = TransformType.GROUND; - ms.mulPose(Axis.YP.rotationDegrees(AnimationTickHolder.getRenderTime(te.getLevel()))); - - } else { - float scale = punching ? .75f : isBlockItem ? .75f - 1 / 64f : .5f; - ms.scale(scale, scale, scale); - transform = punching ? TransformType.THIRD_PERSON_RIGHT_HAND : TransformType.FIXED; - } - - itemRenderer.renderStatic(te.heldItem, transform, light, overlay, ms, buffer, 0); - ms.popPose(); - } - - protected void renderComponents(DeployerTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - VertexConsumer vb = buffer.getBuffer(RenderType.solid()); - if (!Backend.canUseInstancing(te.getLevel())) { - KineticTileEntityRenderer.renderRotatingKineticBlock(te, getRenderedBlockState(te), ms, vb, light); - } - - BlockState blockState = te.getBlockState(); - Vec3 offset = getHandOffset(te, partialTicks, blockState); - - SuperByteBuffer pole = CachedBufferer.partial(AllBlockPartials.DEPLOYER_POLE, blockState); - SuperByteBuffer hand = CachedBufferer.partial(te.getHandPose(), blockState); - - transform(pole.translate(offset.x, offset.y, offset.z), blockState, true) - .light(light) - .renderInto(ms, vb); - transform(hand.translate(offset.x, offset.y, offset.z), blockState, false) - .light(light) - .renderInto(ms, vb); - } - - protected Vec3 getHandOffset(DeployerTileEntity te, float partialTicks, BlockState blockState) { - float distance = te.getHandOffset(partialTicks); - return Vec3.atLowerCornerOf(blockState.getValue(FACING).getNormal()).scale(distance); - } - - protected BlockState getRenderedBlockState(KineticTileEntity te) { - return KineticTileEntityRenderer.shaft(KineticTileEntityRenderer.getRotationAxisOf(te)); - } - - private static SuperByteBuffer transform(SuperByteBuffer buffer, BlockState deployerState, boolean axisDirectionMatters) { - Direction facing = deployerState.getValue(FACING); - - float yRot = AngleHelper.horizontalAngle(facing); - float xRot = facing == Direction.UP ? 270 : facing == Direction.DOWN ? 90 : 0; - float zRot = - axisDirectionMatters && (deployerState.getValue(AXIS_ALONG_FIRST_COORDINATE) ^ facing.getAxis() == Direction.Axis.Z) ? 90 - : 0; - - buffer.rotateCentered(Direction.UP, (float) ((yRot) / 180 * Math.PI)); - buffer.rotateCentered(Direction.EAST, (float) ((xRot) / 180 * Math.PI)); - buffer.rotateCentered(Direction.SOUTH, (float) ((zRot) / 180 * Math.PI)); - return buffer; - } - - public static void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld, - ContraptionMatrices matrices, MultiBufferSource buffer) { - VertexConsumer builder = buffer.getBuffer(RenderType.solid()); - BlockState blockState = context.state; - Mode mode = NBTHelper.readEnum(context.tileData, "Mode", Mode.class); - PartialModel handPose = getHandPose(mode); - - float speed = (float) context.getAnimationSpeed(); - if (context.contraption.stalled) - speed = 0; - - SuperByteBuffer shaft = CachedBufferer.block(AllBlocks.SHAFT.getDefaultState()); - SuperByteBuffer pole = CachedBufferer.partial(AllBlockPartials.DEPLOYER_POLE, blockState); - SuperByteBuffer hand = CachedBufferer.partial(handPose, blockState); - - double factor; - if (context.contraption.stalled || context.position == null || context.data.contains("StationaryTimer")) { - factor = Mth.sin(AnimationTickHolder.getRenderTime() * .5f) * .25f + .25f; - } else { - Vec3 center = VecHelper.getCenterOf(new BlockPos(context.position)); - double distance = context.position.distanceTo(center); - double nextDistance = context.position.add(context.motion) - .distanceTo(center); - factor = .5f - Mth.clamp(Mth.lerp(AnimationTickHolder.getPartialTicks(), distance, nextDistance), 0, 1); - } - - Vec3 offset = Vec3.atLowerCornerOf(blockState.getValue(FACING) - .getNormal()).scale(factor); - - PoseStack m = matrices.getModel(); - m.pushPose(); - - m.pushPose(); - Direction.Axis axis = Direction.Axis.Y; - if (context.state.getBlock() instanceof IRotate) { - IRotate def = (IRotate) context.state.getBlock(); - axis = def.getRotationAxis(context.state); - } - - float time = AnimationTickHolder.getRenderTime(context.world) / 20; - float angle = (time * speed) % 360; - - TransformStack.cast(m) - .centre() - .rotateY(axis == Direction.Axis.Z ? 90 : 0) - .rotateZ(axis.isHorizontal() ? 90 : 0) - .unCentre(); - shaft.transform(m); - shaft.rotateCentered(Direction.get(AxisDirection.POSITIVE, Direction.Axis.Y), angle); - m.popPose(); - - m.translate(offset.x, offset.y, offset.z); - pole.transform(m); - hand.transform(m); - - transform(pole, blockState, true); - transform(hand, blockState, false); - - shaft.light(matrices.getWorld(), ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) - .renderInto(matrices.getViewProjection(), builder); - pole.light(matrices.getWorld(), ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) - .renderInto(matrices.getViewProjection(), builder); - hand.light(matrices.getWorld(), ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) - .renderInto(matrices.getViewProjection(), builder); - - m.popPose(); - } - - static PartialModel getHandPose(DeployerTileEntity.Mode mode) { - return mode == DeployerTileEntity.Mode.PUNCH ? AllBlockPartials.DEPLOYER_HAND_PUNCHING : AllBlockPartials.DEPLOYER_HAND_POINTING; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerTileEntity.java deleted file mode 100644 index 31d8dfc6f..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerTileEntity.java +++ /dev/null @@ -1,565 +0,0 @@ -package com.simibubi.create.content.contraptions.components.deployer; - -import static com.simibubi.create.content.contraptions.base.DirectionalKineticBlock.FACING; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import javax.annotation.Nullable; - -import com.jozufozu.flywheel.core.PartialModel; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllRecipeTypes; -import com.simibubi.create.content.contraptions.base.IRotate.StressImpact; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.itemAssembly.SequencedAssemblyRecipe; -import com.simibubi.create.content.curiosities.tools.SandPaperItem; -import com.simibubi.create.content.curiosities.tools.SandPaperPolishingRecipe.SandPaperInv; -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.item.TooltipHelper; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProcessingBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; - -import net.minecraft.ChatFormatting; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.Tag; -import net.minecraft.network.chat.Component; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.util.Mth; -import net.minecraft.world.Container; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.Recipe; -import net.minecraft.world.level.ClipContext; -import net.minecraft.world.level.ClipContext.Block; -import net.minecraft.world.level.ClipContext.Fluid; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.ItemStackHandler; -import net.minecraftforge.items.wrapper.RecipeWrapper; - -public class DeployerTileEntity extends KineticTileEntity { - - protected State state; - protected Mode mode; - protected ItemStack heldItem = ItemStack.EMPTY; - protected DeployerFakePlayer player; - protected int timer; - protected float reach; - protected boolean fistBump = false; - protected List overflowItems = new ArrayList<>(); - protected FilteringBehaviour filtering; - protected boolean redstoneLocked; - private LazyOptional invHandler; - private ListTag deferredInventoryList; - - private LerpedFloat animatedOffset; - - public BeltProcessingBehaviour processingBehaviour; - - enum State { - WAITING, EXPANDING, RETRACTING, DUMPING; - } - - enum Mode { - PUNCH, USE - } - - public DeployerTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - this.state = State.WAITING; - mode = Mode.USE; - heldItem = ItemStack.EMPTY; - redstoneLocked = false; - animatedOffset = LerpedFloat.linear() - .startWithValue(0); - } - - @Override - public void addBehaviours(List behaviours) { - super.addBehaviours(behaviours); - filtering = new FilteringBehaviour(this, new DeployerFilterSlot()); - behaviours.add(filtering); - processingBehaviour = - new BeltProcessingBehaviour(this).whenItemEnters((s, i) -> BeltDeployerCallbacks.onItemReceived(s, i, this)) - .whileItemHeld((s, i) -> BeltDeployerCallbacks.whenItemHeld(s, i, this)); - behaviours.add(processingBehaviour); - - registerAwardables(behaviours, AllAdvancements.TRAIN_CASING, AllAdvancements.ANDESITE_CASING, - AllAdvancements.BRASS_CASING, AllAdvancements.COPPER_CASING, AllAdvancements.FIST_BUMP, - AllAdvancements.DEPLOYER, AllAdvancements.SELF_DEPLOYING); - } - - @Override - public void initialize() { - super.initialize(); - initHandler(); - } - - private void initHandler() { - if (invHandler != null) - return; - if (level instanceof ServerLevel sLevel) { - player = new DeployerFakePlayer(sLevel); - if (deferredInventoryList != null) { - player.getInventory() - .load(deferredInventoryList); - deferredInventoryList = null; - heldItem = player.getMainHandItem(); - sendData(); - } - Vec3 initialPos = VecHelper.getCenterOf(worldPosition.relative(getBlockState().getValue(FACING))); - player.setPos(initialPos.x, initialPos.y, initialPos.z); - } - invHandler = LazyOptional.of(this::createHandler); - } - - protected void onExtract(ItemStack stack) { - player.setItemInHand(InteractionHand.MAIN_HAND, stack.copy()); - sendData(); - setChanged(); - } - - protected int getTimerSpeed() { - return (int) (getSpeed() == 0 ? 0 : Mth.clamp(Math.abs(getSpeed() * 2), 8, 512)); - } - - @Override - public void tick() { - super.tick(); - - if (getSpeed() == 0) - return; - if (!level.isClientSide && player != null && player.blockBreakingProgress != null) { - if (level.isEmptyBlock(player.blockBreakingProgress.getKey())) { - level.destroyBlockProgress(player.getId(), player.blockBreakingProgress.getKey(), -1); - player.blockBreakingProgress = null; - } - } - if (timer > 0) { - timer -= getTimerSpeed(); - return; - } - if (level.isClientSide) - return; - - ItemStack stack = player.getMainHandItem(); - if (state == State.WAITING) { - if (!overflowItems.isEmpty()) { - timer = getTimerSpeed() * 10; - return; - } - - boolean changed = false; - Inventory inventory = player.getInventory(); - for (int i = 0; i < inventory.getContainerSize(); i++) { - if (overflowItems.size() > 10) - break; - ItemStack item = inventory.getItem(i); - if (item.isEmpty()) - continue; - if (item != stack || !filtering.test(item)) { - overflowItems.add(item); - inventory.setItem(i, ItemStack.EMPTY); - changed = true; - } - } - - if (changed) { - sendData(); - timer = getTimerSpeed() * 10; - return; - } - - Direction facing = getBlockState().getValue(FACING); - if (mode == Mode.USE - && !DeployerHandler.shouldActivate(stack, level, worldPosition.relative(facing, 2), facing)) { - timer = getTimerSpeed() * 10; - return; - } - - // Check for advancement conditions - if (mode == Mode.PUNCH && !fistBump && startFistBump(facing)) - return; - if (redstoneLocked) - return; - - start(); - return; - } - - if (state == State.EXPANDING) { - if (fistBump) - triggerFistBump(); - activate(); - - state = State.RETRACTING; - timer = 1000; - sendData(); - return; - } - - if (state == State.RETRACTING) { - state = State.WAITING; - timer = 500; - sendData(); - return; - } - - } - - protected void start() { - state = State.EXPANDING; - Vec3 movementVector = getMovementVector(); - Vec3 rayOrigin = VecHelper.getCenterOf(worldPosition) - .add(movementVector.scale(3 / 2f)); - Vec3 rayTarget = VecHelper.getCenterOf(worldPosition) - .add(movementVector.scale(5 / 2f)); - ClipContext rayTraceContext = new ClipContext(rayOrigin, rayTarget, Block.OUTLINE, Fluid.NONE, player); - BlockHitResult result = level.clip(rayTraceContext); - reach = (float) (.5f + Math.min(result.getLocation() - .subtract(rayOrigin) - .length(), .75f)); - timer = 1000; - sendData(); - } - - public boolean startFistBump(Direction facing) { - int i = 0; - DeployerTileEntity partner = null; - - for (i = 2; i < 5; i++) { - BlockPos otherDeployer = worldPosition.relative(facing, i); - if (!level.isLoaded(otherDeployer)) - return false; - BlockEntity otherTile = level.getBlockEntity(otherDeployer); - if (otherTile instanceof DeployerTileEntity dpe) { - partner = dpe; - break; - } - } - - if (partner == null) - return false; - - if (level.getBlockState(partner.getBlockPos()) - .getValue(FACING) - .getOpposite() != facing || partner.mode != Mode.PUNCH) - return false; - if (partner.getSpeed() == 0) - return false; - - for (DeployerTileEntity te : Arrays.asList(this, partner)) { - te.fistBump = true; - te.reach = ((i - 2)) * .5f; - te.timer = 1000; - te.state = State.EXPANDING; - te.sendData(); - } - - return true; - } - - public void triggerFistBump() { - int i = 0; - DeployerTileEntity deployerTile = null; - for (i = 2; i < 5; i++) { - BlockPos pos = worldPosition.relative(getBlockState().getValue(FACING), i); - if (!level.isLoaded(pos)) - return; - if (level.getBlockEntity(pos) instanceof DeployerTileEntity dpe) { - deployerTile = dpe; - break; - } - } - - if (deployerTile == null) - return; - if (!deployerTile.fistBump || deployerTile.state != State.EXPANDING) - return; - if (deployerTile.timer > 0) - return; - - fistBump = false; - deployerTile.fistBump = false; - deployerTile.state = State.RETRACTING; - deployerTile.timer = 1000; - deployerTile.sendData(); - award(AllAdvancements.FIST_BUMP); - - BlockPos soundLocation = new BlockPos(Vec3.atCenterOf(worldPosition) - .add(Vec3.atCenterOf(deployerTile.getBlockPos())) - .scale(.5f)); - level.playSound(null, soundLocation, SoundEvents.PLAYER_ATTACK_NODAMAGE, SoundSource.BLOCKS, .75f, .75f); - } - - protected void activate() { - Vec3 movementVector = getMovementVector(); - Direction direction = getBlockState().getValue(FACING); - Vec3 center = VecHelper.getCenterOf(worldPosition); - BlockPos clickedPos = worldPosition.relative(direction, 2); - player.setXRot(direction == Direction.UP ? -90 : direction == Direction.DOWN ? 90 : 0); - player.setYRot(direction.toYRot()); - - if (direction == Direction.DOWN - && TileEntityBehaviour.get(level, clickedPos, TransportedItemStackHandlerBehaviour.TYPE) != null) - return; // Belt processing handled in BeltDeployerCallbacks - - DeployerHandler.activate(player, center, clickedPos, movementVector, mode); - award(AllAdvancements.DEPLOYER); - - if (player != null) - heldItem = player.getMainHandItem(); - } - - protected Vec3 getMovementVector() { - if (!AllBlocks.DEPLOYER.has(getBlockState())) - return Vec3.ZERO; - return Vec3.atLowerCornerOf(getBlockState().getValue(FACING) - .getNormal()); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - state = NBTHelper.readEnum(compound, "State", State.class); - mode = NBTHelper.readEnum(compound, "Mode", Mode.class); - timer = compound.getInt("Timer"); - redstoneLocked = compound.getBoolean("Powered"); - - deferredInventoryList = compound.getList("Inventory", Tag.TAG_COMPOUND); - overflowItems = NBTHelper.readItemList(compound.getList("Overflow", Tag.TAG_COMPOUND)); - if (compound.contains("HeldItem")) - heldItem = ItemStack.of(compound.getCompound("HeldItem")); - super.read(compound, clientPacket); - - if (!clientPacket) - return; - fistBump = compound.getBoolean("Fistbump"); - reach = compound.getFloat("Reach"); - if (compound.contains("Particle")) { - ItemStack particleStack = ItemStack.of(compound.getCompound("Particle")); - SandPaperItem.spawnParticles(VecHelper.getCenterOf(worldPosition) - .add(getMovementVector().scale(reach + 1)), particleStack, this.level); - } - } - - @Override - public void write(CompoundTag compound, boolean clientPacket) { - NBTHelper.writeEnum(compound, "Mode", mode); - NBTHelper.writeEnum(compound, "State", state); - compound.putInt("Timer", timer); - compound.putBoolean("Powered", redstoneLocked); - - if (player != null) { - ListTag invNBT = new ListTag(); - player.getInventory() - .save(invNBT); - compound.put("Inventory", invNBT); - compound.put("HeldItem", player.getMainHandItem() - .serializeNBT()); - compound.put("Overflow", NBTHelper.writeItemList(overflowItems)); - } else if (deferredInventoryList != null) { - compound.put("Inventory", deferredInventoryList); - } - - super.write(compound, clientPacket); - - if (!clientPacket) - return; - compound.putBoolean("Fistbump", fistBump); - compound.putFloat("Reach", reach); - if (player == null) - return; - compound.put("HeldItem", player.getMainHandItem() - .serializeNBT()); - if (player.spawnedItemEffects != null) { - compound.put("Particle", player.spawnedItemEffects.serializeNBT()); - player.spawnedItemEffects = null; - } - } - - @Override - public void writeSafe(CompoundTag tag) { - NBTHelper.writeEnum(tag, "Mode", mode); - super.writeSafe(tag); - } - - private IItemHandlerModifiable createHandler() { - return new DeployerItemHandler(this); - } - - public void redstoneUpdate() { - if (level.isClientSide) - return; - boolean blockPowered = level.hasNeighborSignal(worldPosition); - if (blockPowered == redstoneLocked) - return; - redstoneLocked = blockPowered; - sendData(); - } - - @OnlyIn(Dist.CLIENT) - public PartialModel getHandPose() { - return mode == Mode.PUNCH ? AllBlockPartials.DEPLOYER_HAND_PUNCHING - : heldItem.isEmpty() ? AllBlockPartials.DEPLOYER_HAND_POINTING : AllBlockPartials.DEPLOYER_HAND_HOLDING; - } - - @Override - protected AABB createRenderBoundingBox() { - return super.createRenderBoundingBox().inflate(3); - } - - public void discardPlayer() { - if (player == null) - return; - player.getInventory() - .dropAll(); - overflowItems.forEach(itemstack -> player.drop(itemstack, true, false)); - player.discard(); - player = null; - } - - @Override - public void invalidate() { - super.invalidate(); - if (invHandler != null) - invHandler.invalidate(); - } - - public void changeMode() { - mode = mode == Mode.PUNCH ? Mode.USE : Mode.PUNCH; - setChanged(); - sendData(); - } - - @Override - public LazyOptional getCapability(Capability cap, Direction side) { - if (isItemHandlerCap(cap)) { - if (invHandler == null) - initHandler(); - return invHandler.cast(); - } - return super.getCapability(cap, side); - } - - @Override - public boolean addToTooltip(List tooltip, boolean isPlayerSneaking) { - if (super.addToTooltip(tooltip, isPlayerSneaking)) - return true; - if (getSpeed() == 0) - return false; - if (overflowItems.isEmpty()) - return false; - TooltipHelper.addHint(tooltip, "hint.full_deployer"); - return true; - } - - @Override - public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { - Lang.translate("tooltip.deployer.header") - .forGoggles(tooltip); - - Lang.translate("tooltip.deployer." + (mode == Mode.USE ? "using" : "punching")) - .style(ChatFormatting.YELLOW) - .forGoggles(tooltip); - - if (!heldItem.isEmpty()) - Lang.translate("tooltip.deployer.contains", - Components.translatable(heldItem.getDescriptionId()).getString(), heldItem.getCount()) - .style(ChatFormatting.GREEN) - .forGoggles(tooltip); - - float stressAtBase = calculateStressApplied(); - if (StressImpact.isEnabled() && !Mth.equal(stressAtBase, 0)) { - tooltip.add(Components.immutableEmpty()); - addStressImpactStats(tooltip, stressAtBase); - } - - return true; - } - - @OnlyIn(Dist.CLIENT) - public float getHandOffset(float partialTicks) { - if (isVirtual()) - return animatedOffset.getValue(partialTicks); - - float progress = 0; - int timerSpeed = getTimerSpeed(); - PartialModel handPose = getHandPose(); - - if (state == State.EXPANDING) { - progress = 1 - (timer - partialTicks * timerSpeed) / 1000f; - if (fistBump) - progress *= progress; - } - if (state == State.RETRACTING) - progress = (timer - partialTicks * timerSpeed) / 1000f; - float handLength = handPose == AllBlockPartials.DEPLOYER_HAND_POINTING ? 0 - : handPose == AllBlockPartials.DEPLOYER_HAND_HOLDING ? 4 / 16f : 3 / 16f; - float distance = Math.min(Mth.clamp(progress, 0, 1) * (reach + handLength), 21 / 16f); - - return distance; - } - - public void setAnimatedOffset(float offset) { - animatedOffset.setValue(offset); - } - - RecipeWrapper recipeInv = new RecipeWrapper(new ItemStackHandler(2)); - SandPaperInv sandpaperInv = new SandPaperInv(ItemStack.EMPTY); - - @Nullable - public Recipe getRecipe(ItemStack stack) { - if (player == null || level == null) - return null; - - ItemStack heldItemMainhand = player.getMainHandItem(); - if (heldItemMainhand.getItem() instanceof SandPaperItem) { - sandpaperInv.setItem(0, stack); - return AllRecipeTypes.SANDPAPER_POLISHING.find(sandpaperInv, level) - .orElse(null); - } - - recipeInv.setItem(0, stack); - recipeInv.setItem(1, heldItemMainhand); - - DeployerRecipeSearchEvent event = new DeployerRecipeSearchEvent(this, recipeInv); - - event.addRecipe(() -> SequencedAssemblyRecipe.getRecipe(level, event.getInventory(), - AllRecipeTypes.DEPLOYING.getType(), DeployerApplicationRecipe.class), 100); - event.addRecipe(() -> AllRecipeTypes.DEPLOYING.find(event.getInventory(), level), 50); - event.addRecipe(() -> AllRecipeTypes.ITEM_APPLICATION.find(event.getInventory(), level), 50); - - MinecraftForge.EVENT_BUS.post(event); - return event.getRecipe(); - } - - public DeployerFakePlayer getPlayer() { - return player; - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanRenderer.java deleted file mode 100644 index 73b918fa7..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanRenderer.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.simibubi.create.content.contraptions.components.fan; - -import static net.minecraft.world.level.block.state.properties.BlockStateProperties.FACING; - -import com.jozufozu.flywheel.backend.Backend; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; - -import net.minecraft.client.renderer.LevelRenderer; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.Direction; -import net.minecraft.util.Mth; - -public class EncasedFanRenderer extends KineticTileEntityRenderer { - - public EncasedFanRenderer(BlockEntityRendererProvider.Context context) { - super(context); - } - - @Override - protected void renderSafe(KineticTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - if (Backend.canUseInstancing(te.getLevel())) return; - - Direction direction = te.getBlockState() - .getValue(FACING); - VertexConsumer vb = buffer.getBuffer(RenderType.cutoutMipped()); - - int lightBehind = LevelRenderer.getLightColor(te.getLevel(), te.getBlockPos().relative(direction.getOpposite())); - int lightInFront = LevelRenderer.getLightColor(te.getLevel(), te.getBlockPos().relative(direction)); - - SuperByteBuffer shaftHalf = - CachedBufferer.partialFacing(AllBlockPartials.SHAFT_HALF, te.getBlockState(), direction.getOpposite()); - SuperByteBuffer fanInner = - CachedBufferer.partialFacing(AllBlockPartials.ENCASED_FAN_INNER, te.getBlockState(), direction.getOpposite()); - - float time = AnimationTickHolder.getRenderTime(te.getLevel()); - float speed = te.getSpeed() * 5; - if (speed > 0) - speed = Mth.clamp(speed, 80, 64 * 20); - if (speed < 0) - speed = Mth.clamp(speed, -64 * 20, -80); - float angle = (time * speed * 3 / 10f) % 360; - angle = angle / 180f * (float) Math.PI; - - standardKineticRotationTransform(shaftHalf, te, lightBehind).renderInto(ms, vb); - kineticRotationTransform(fanInner, te, direction.getAxis(), angle, lightInFront).renderInto(ms, vb); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanTileEntity.java deleted file mode 100644 index 691167097..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanTileEntity.java +++ /dev/null @@ -1,154 +0,0 @@ -package com.simibubi.create.content.contraptions.components.fan; - -import java.util.List; - -import javax.annotation.Nullable; - -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.logistics.block.chute.ChuteTileEntity; -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; - -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; - -@MethodsReturnNonnullByDefault -public class EncasedFanTileEntity extends KineticTileEntity implements IAirCurrentSource { - - public AirCurrent airCurrent; - protected int airCurrentUpdateCooldown; - protected int entitySearchCooldown; - protected boolean updateAirFlow; - - public EncasedFanTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - airCurrent = new AirCurrent(this); - updateAirFlow = true; - } - - @Override - public void addBehaviours(List behaviours) { - super.addBehaviours(behaviours); - registerAwardables(behaviours, AllAdvancements.ENCASED_FAN, AllAdvancements.FAN_PROCESSING); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - super.read(compound, clientPacket); - if (clientPacket) - airCurrent.rebuild(); - } - - @Override - public void write(CompoundTag compound, boolean clientPacket) { - super.write(compound, clientPacket); - } - - @Override - public AirCurrent getAirCurrent() { - return airCurrent; - } - - @Nullable - @Override - public Level getAirCurrentWorld() { - return level; - } - - @Override - public BlockPos getAirCurrentPos() { - return worldPosition; - } - - @Override - public Direction getAirflowOriginSide() { - return this.getBlockState() - .getValue(EncasedFanBlock.FACING); - } - - @Override - public Direction getAirFlowDirection() { - float speed = getSpeed(); - if (speed == 0) - return null; - Direction facing = getBlockState().getValue(BlockStateProperties.FACING); - speed = convertToDirection(speed, facing); - return speed > 0 ? facing : facing.getOpposite(); - } - - @Override - public void remove() { - super.remove(); - updateChute(); - } - - @Override - public boolean isSourceRemoved() { - return remove; - } - - @Override - public void onSpeedChanged(float prevSpeed) { - super.onSpeedChanged(prevSpeed); - updateAirFlow = true; - updateChute(); - } - - public void updateChute() { - Direction direction = getBlockState().getValue(EncasedFanBlock.FACING); - if (!direction.getAxis() - .isVertical()) - return; - BlockEntity poweredChute = level.getBlockEntity(worldPosition.relative(direction)); - if (!(poweredChute instanceof ChuteTileEntity)) - return; - ChuteTileEntity chuteTE = (ChuteTileEntity) poweredChute; - if (direction == Direction.DOWN) - chuteTE.updatePull(); - else - chuteTE.updatePush(1); - } - - public void blockInFrontChanged() { - updateAirFlow = true; - } - - @Override - public void tick() { - super.tick(); - - boolean server = !level.isClientSide || isVirtual(); - - if (server && airCurrentUpdateCooldown-- <= 0) { - airCurrentUpdateCooldown = AllConfigs.SERVER.kinetics.fanBlockCheckRate.get(); - updateAirFlow = true; - } - - if (updateAirFlow) { - updateAirFlow = false; - airCurrent.rebuild(); - if (airCurrent.maxDistance > 0) - award(AllAdvancements.ENCASED_FAN); - sendData(); - } - - if (getSpeed() == 0) - return; - - if (entitySearchCooldown-- <= 0) { - entitySearchCooldown = 5; - airCurrent.findEntities(); - } - - airCurrent.tick(); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/fan/FanInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/fan/FanInstance.java deleted file mode 100644 index 9a7dfa93b..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/fan/FanInstance.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.simibubi.create.content.contraptions.components.fan; - -import static net.minecraft.world.level.block.state.properties.BlockStateProperties.FACING; - -import com.jozufozu.flywheel.api.MaterialManager; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.KineticTileInstance; -import com.simibubi.create.content.contraptions.base.flwdata.RotatingData; -import com.simibubi.create.foundation.render.AllMaterialSpecs; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.util.Mth; - -public class FanInstance extends KineticTileInstance { - - protected final RotatingData shaft; - protected final RotatingData fan; - final Direction direction; - private final Direction opposite; - - public FanInstance(MaterialManager modelManager, EncasedFanTileEntity tile) { - super(modelManager, tile); - - direction = blockState.getValue(FACING); - - opposite = direction.getOpposite(); - shaft = getRotatingMaterial().getModel(AllBlockPartials.SHAFT_HALF, blockState, opposite).createInstance(); - fan = modelManager.defaultCutout() - .material(AllMaterialSpecs.ROTATING) - .getModel(AllBlockPartials.ENCASED_FAN_INNER, blockState, opposite) - .createInstance(); - - setup(shaft); - setup(fan, getFanSpeed()); - } - - private float getFanSpeed() { - float speed = blockEntity.getSpeed() * 5; - if (speed > 0) - speed = Mth.clamp(speed, 80, 64 * 20); - if (speed < 0) - speed = Mth.clamp(speed, -64 * 20, -80); - return speed; - } - - @Override - public void update() { - updateRotation(shaft); - updateRotation(fan, getFanSpeed()); - } - - @Override - public void updateLight() { - BlockPos behind = pos.relative(opposite); - relight(behind, shaft); - - BlockPos inFront = pos.relative(direction); - relight(inFront, fan); - } - - @Override - public void remove() { - shaft.delete(); - fan.delete(); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/fan/HauntingRecipe.java b/src/main/java/com/simibubi/create/content/contraptions/components/fan/HauntingRecipe.java deleted file mode 100644 index 443642a5d..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/fan/HauntingRecipe.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.simibubi.create.content.contraptions.components.fan; - -import javax.annotation.ParametersAreNonnullByDefault; - -import com.simibubi.create.AllRecipeTypes; -import com.simibubi.create.content.contraptions.processing.InWorldProcessing; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipe; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder.ProcessingRecipeParams; - -import net.minecraft.world.level.Level; - -@ParametersAreNonnullByDefault -public class HauntingRecipe extends ProcessingRecipe { - - public HauntingRecipe(ProcessingRecipeParams params) { - super(AllRecipeTypes.HAUNTING, params); - } - - @Override - public boolean matches(InWorldProcessing.HauntingWrapper inv, Level worldIn) { - if (inv.isEmpty()) - return false; - return ingredients.get(0) - .test(inv.getItem(0)); - } - - @Override - protected int getMaxInputCount() { - return 1; - } - - @Override - protected int getMaxOutputCount() { - return 12; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/fan/NozzleTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/fan/NozzleTileEntity.java deleted file mode 100644 index f39b1d43c..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/fan/NozzleTileEntity.java +++ /dev/null @@ -1,191 +0,0 @@ -package com.simibubi.create.content.contraptions.components.fan; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.util.Mth; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.level.ClipContext; -import net.minecraft.world.level.ClipContext.Block; -import net.minecraft.world.level.ClipContext.Fluid; -import net.minecraft.world.level.Level.ExplosionInteraction; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.Vec3; - -public class NozzleTileEntity extends SmartTileEntity { - - private List pushingEntities = new ArrayList<>(); - private float range; - private boolean pushing; - private BlockPos fanPos; - - public NozzleTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - setLazyTickRate(5); - } - - @Override - public void addBehaviours(List behaviours) {} - - @Override - protected void write(CompoundTag compound, boolean clientPacket) { - super.write(compound, clientPacket); - if (!clientPacket) - return; - compound.putFloat("Range", range); - compound.putBoolean("Pushing", pushing); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - super.read(compound, clientPacket); - if (!clientPacket) - return; - range = compound.getFloat("Range"); - pushing = compound.getBoolean("Pushing"); - } - - @Override - public void initialize() { - fanPos = worldPosition.relative(getBlockState().getValue(NozzleBlock.FACING) - .getOpposite()); - super.initialize(); - } - - @Override - public void tick() { - super.tick(); - - float range = calcRange(); - if (this.range != range) - setRange(range); - - Vec3 center = VecHelper.getCenterOf(worldPosition); - if (level.isClientSide && range != 0) { - if (level.random.nextInt( - Mth.clamp((AllConfigs.SERVER.kinetics.fanPushDistance.get() - (int) range), 1, 10)) == 0) { - Vec3 start = VecHelper.offsetRandomly(center, level.random, pushing ? 1 : range / 2); - Vec3 motion = center.subtract(start) - .normalize() - .scale(Mth.clamp(range * (pushing ? .025f : 1f), 0, .5f) * (pushing ? -1 : 1)); - level.addParticle(ParticleTypes.POOF, start.x, start.y, start.z, motion.x, motion.y, motion.z); - } - } - - for (Iterator iterator = pushingEntities.iterator(); iterator.hasNext();) { - Entity entity = iterator.next(); - Vec3 diff = entity.position() - .subtract(center); - - if (!(entity instanceof Player) && level.isClientSide) - continue; - - double distance = diff.length(); - if (distance > range || entity.isShiftKeyDown() || AirCurrent.isPlayerCreativeFlying(entity)) { - iterator.remove(); - continue; - } - - if (!pushing && distance < 1.5f) - continue; - - float factor = (entity instanceof ItemEntity) ? 1 / 128f : 1 / 32f; - Vec3 pushVec = diff.normalize() - .scale((range - distance) * (pushing ? 1 : -1)); - entity.setDeltaMovement(entity.getDeltaMovement() - .add(pushVec.scale(factor))); - entity.fallDistance = 0; - entity.hurtMarked = true; - } - - } - - public void setRange(float range) { - this.range = range; - if (range == 0) - pushingEntities.clear(); - sendData(); - } - - private float calcRange() { - BlockEntity te = level.getBlockEntity(fanPos); - if (!(te instanceof IAirCurrentSource)) - return 0; - - IAirCurrentSource source = (IAirCurrentSource) te; - if (source.getAirCurrent() == null) - return 0; - if (source.getSpeed() == 0) - return 0; - pushing = source.getAirFlowDirection() == source.getAirflowOriginSide(); - return source.getMaxDistance(); - } - - @Override - public void lazyTick() { - super.lazyTick(); - - if (range == 0) - return; - - Vec3 center = VecHelper.getCenterOf(worldPosition); - AABB bb = new AABB(center, center).inflate(range / 2f); - - for (Entity entity : level.getEntitiesOfClass(Entity.class, bb)) { - Vec3 diff = entity.position() - .subtract(center); - - double distance = diff.length(); - if (distance > range || entity.isShiftKeyDown() || AirCurrent.isPlayerCreativeFlying(entity)) - continue; - - boolean canSee = canSee(entity); - if (!canSee) { - pushingEntities.remove(entity); - continue; - } - - if (!pushingEntities.contains(entity)) - pushingEntities.add(entity); - } - - for (Iterator iterator = pushingEntities.iterator(); iterator.hasNext();) { - Entity entity = iterator.next(); - if (entity.isAlive()) - continue; - iterator.remove(); - } - - if (!pushing && pushingEntities.size() > 256 && !level.isClientSide) { - level.explode(null, center.x, center.y, center.z, 2, ExplosionInteraction.NONE); - for (Iterator iterator = pushingEntities.iterator(); iterator.hasNext();) { - Entity entity = iterator.next(); - entity.discard(); - iterator.remove(); - } - } - - } - - private boolean canSee(Entity entity) { - ClipContext context = new ClipContext(entity.position(), VecHelper.getCenterOf(worldPosition), - Block.COLLIDER, Fluid.NONE, entity); - return worldPosition.equals(level.clip(context) - .getBlockPos()); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/fan/SplashingRecipe.java b/src/main/java/com/simibubi/create/content/contraptions/components/fan/SplashingRecipe.java deleted file mode 100644 index 4918ddb82..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/fan/SplashingRecipe.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.simibubi.create.content.contraptions.components.fan; - -import javax.annotation.ParametersAreNonnullByDefault; - -import com.simibubi.create.AllRecipeTypes; -import com.simibubi.create.content.contraptions.processing.InWorldProcessing; -import com.simibubi.create.content.contraptions.processing.InWorldProcessing.SplashingWrapper; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipe; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder.ProcessingRecipeParams; - -import net.minecraft.world.level.Level; - -@ParametersAreNonnullByDefault -public class SplashingRecipe extends ProcessingRecipe { - - public SplashingRecipe(ProcessingRecipeParams params) { - super(AllRecipeTypes.SPLASHING, params); - } - - @Override - public boolean matches(SplashingWrapper inv, Level worldIn) { - if (inv.isEmpty()) - return false; - return ingredients.get(0) - .test(inv.getItem(0)); - } - - @Override - protected int getMaxInputCount() { - return 1; - } - - @Override - protected int getMaxOutputCount() { - return 12; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlyWheelInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlyWheelInstance.java deleted file mode 100644 index d7b8dd9b7..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlyWheelInstance.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.simibubi.create.content.contraptions.components.flywheel; - -import com.jozufozu.flywheel.api.MaterialManager; -import com.jozufozu.flywheel.api.instance.DynamicInstance; -import com.jozufozu.flywheel.core.materials.model.ModelData; -import com.jozufozu.flywheel.util.transform.TransformStack; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.content.contraptions.base.KineticTileInstance; -import com.simibubi.create.content.contraptions.base.flwdata.RotatingData; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; - -import net.minecraft.core.Direction; - -public class FlyWheelInstance extends KineticTileInstance implements DynamicInstance { - - protected final RotatingData shaft; - protected final ModelData wheel; - protected float lastAngle = Float.NaN; - - public FlyWheelInstance(MaterialManager modelManager, FlywheelTileEntity tile) { - super(modelManager, tile); - - shaft = setup(getRotatingMaterial().getModel(shaft()) - .createInstance()); - wheel = getTransformMaterial().getModel(blockState) - .createInstance(); - - animate(tile.angle); - } - - @Override - public void beginFrame() { - - float partialTicks = AnimationTickHolder.getPartialTicks(); - - float speed = blockEntity.visualSpeed.getValue(partialTicks) * 3 / 10f; - float angle = blockEntity.angle + speed * partialTicks; - - if (Math.abs(angle - lastAngle) < 0.001) - return; - - animate(angle); - - lastAngle = angle; - } - - private void animate(float angle) { - PoseStack ms = new PoseStack(); - TransformStack msr = TransformStack.cast(ms); - - msr.translate(getInstancePosition()); - msr.centre() - .rotate(Direction.get(Direction.AxisDirection.POSITIVE, axis), AngleHelper.rad(angle)) - .unCentre(); - - wheel.setTransform(ms); - } - - @Override - public void update() { - updateRotation(shaft); - } - - @Override - public void updateLight() { - relight(pos, shaft, wheel); - } - - @Override - public void remove() { - shaft.delete(); - wheel.delete(); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelBlock.java deleted file mode 100644 index 47c961334..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelBlock.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.simibubi.create.content.contraptions.components.flywheel; - -import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock; -import com.simibubi.create.foundation.block.ITE; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.RenderShape; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.VoxelShape; - -public class FlywheelBlock extends RotatedPillarKineticBlock implements ITE { - - public FlywheelBlock(Properties properties) { - super(properties); - } - - @Override - public Class getTileEntityClass() { - return FlywheelTileEntity.class; - } - - @Override - public VoxelShape getShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, CollisionContext pContext) { - return AllShapes.LARGE_GEAR.get(pState.getValue(AXIS)); - } - - @Override - public RenderShape getRenderShape(BlockState pState) { - return RenderShape.ENTITYBLOCK_ANIMATED; - } - - @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.FLYWHEEL.get(); - } - - @Override - public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) { - return face.getAxis() == getRotationAxis(state); - } - - @Override - public Axis getRotationAxis(BlockState state) { - return state.getValue(AXIS); - } - - @Override - public float getParticleTargetRadius() { - return 2f; - } - - @Override - public float getParticleInitialRadius() { - return 1.75f; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelRenderer.java deleted file mode 100644 index 274f8ba2f..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelRenderer.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.simibubi.create.content.contraptions.components.flywheel; - -import com.jozufozu.flywheel.backend.Backend; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.world.level.block.state.BlockState; - -public class FlywheelRenderer extends KineticTileEntityRenderer { - - public FlywheelRenderer(BlockEntityRendererProvider.Context context) { - super(context); - } - - @Override - protected void renderSafe(KineticTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - super.renderSafe(te, partialTicks, ms, buffer, light, overlay); - - if (Backend.canUseInstancing(te.getLevel())) - return; - - BlockState blockState = te.getBlockState(); - FlywheelTileEntity wte = (FlywheelTileEntity) te; - - float speed = wte.visualSpeed.getValue(partialTicks) * 3 / 10f; - float angle = wte.angle + speed * partialTicks; - - VertexConsumer vb = buffer.getBuffer(RenderType.solid()); - renderFlywheel(te, ms, light, blockState, angle, vb); - } - - private void renderFlywheel(KineticTileEntity te, PoseStack ms, int light, BlockState blockState, float angle, - VertexConsumer vb) { - SuperByteBuffer wheel = CachedBufferer.block(blockState); - kineticRotationTransform(wheel, te, getRotationAxisOf(te), AngleHelper.rad(angle), light); - wheel.renderInto(ms, vb); - } - - @Override - protected BlockState getRenderedBlockState(KineticTileEntity te) { - return shaft(getRotationAxisOf(te)); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelTileEntity.java deleted file mode 100644 index dc9700099..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelTileEntity.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.simibubi.create.content.contraptions.components.flywheel; - -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; - -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.AABB; - -public class FlywheelTileEntity extends KineticTileEntity { - - LerpedFloat visualSpeed = LerpedFloat.linear(); - float angle; - - public FlywheelTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - @Override - protected AABB createRenderBoundingBox() { - return super.createRenderBoundingBox().inflate(2); - } - - @Override - public void write(CompoundTag compound, boolean clientPacket) { - super.write(compound, clientPacket); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - super.read(compound, clientPacket); - if (clientPacket) - visualSpeed.chase(getGeneratedSpeed(), 1 / 64f, Chaser.EXP); - } - - @Override - public void tick() { - super.tick(); - - if (!level.isClientSide) - return; - - float targetSpeed = getSpeed(); - visualSpeed.updateChaseTarget(targetSpeed); - visualSpeed.tickChaser(); - angle += visualSpeed.getValue() * 3 / 10f; - angle %= 360; - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/millstone/MillStoneCogInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/millstone/MillStoneCogInstance.java deleted file mode 100644 index 1e8831261..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/millstone/MillStoneCogInstance.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.simibubi.create.content.contraptions.components.millstone; - -import com.jozufozu.flywheel.api.Instancer; -import com.jozufozu.flywheel.api.MaterialManager; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.SingleRotatingInstance; -import com.simibubi.create.content.contraptions.base.flwdata.RotatingData; - -public class MillStoneCogInstance extends SingleRotatingInstance { - - public MillStoneCogInstance(MaterialManager modelManager, KineticTileEntity tile) { - super(modelManager, tile); - } - - @Override - protected Instancer getModel() { - return getRotatingMaterial().getModel(AllBlockPartials.MILLSTONE_COG, blockEntity.getBlockState()); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/millstone/MillingRecipe.java b/src/main/java/com/simibubi/create/content/contraptions/components/millstone/MillingRecipe.java deleted file mode 100644 index 849154b04..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/millstone/MillingRecipe.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.simibubi.create.content.contraptions.components.millstone; - -import javax.annotation.ParametersAreNonnullByDefault; - -import com.simibubi.create.AllRecipeTypes; -import com.simibubi.create.content.contraptions.components.crusher.AbstractCrushingRecipe; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder.ProcessingRecipeParams; - -import net.minecraft.world.level.Level; -import net.minecraftforge.items.wrapper.RecipeWrapper; - -@ParametersAreNonnullByDefault -public class MillingRecipe extends AbstractCrushingRecipe { - - public MillingRecipe(ProcessingRecipeParams params) { - super(AllRecipeTypes.MILLING, params); - } - - @Override - public boolean matches(RecipeWrapper inv, Level worldIn) { - if (inv.isEmpty()) - return false; - return ingredients.get(0) - .test(inv.getItem(0)); - } - - @Override - protected int getMaxOutputCount() { - return 4; - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/millstone/MillstoneRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/millstone/MillstoneRenderer.java deleted file mode 100644 index 0dfd15517..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/millstone/MillstoneRenderer.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.simibubi.create.content.contraptions.components.millstone; - -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; - -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.world.level.block.state.BlockState; - -public class MillstoneRenderer extends KineticTileEntityRenderer { - - public MillstoneRenderer(BlockEntityRendererProvider.Context context) { - super(context); - } - - @Override - protected SuperByteBuffer getRotatedModel(KineticTileEntity te, BlockState state) { - return CachedBufferer.partial(AllBlockPartials.MILLSTONE_COG, state); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/millstone/MillstoneTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/millstone/MillstoneTileEntity.java deleted file mode 100644 index 91a1fa51b..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/millstone/MillstoneTileEntity.java +++ /dev/null @@ -1,238 +0,0 @@ -package com.simibubi.create.content.contraptions.components.millstone; - -import java.util.List; -import java.util.Optional; - -import com.simibubi.create.AllRecipeTypes; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.item.ItemHelper; -import com.simibubi.create.foundation.sound.SoundScapes; -import com.simibubi.create.foundation.sound.SoundScapes.AmbienceGroup; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.core.particles.ItemParticleOption; -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.util.Mth; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.ItemHandlerHelper; -import net.minecraftforge.items.ItemStackHandler; -import net.minecraftforge.items.wrapper.CombinedInvWrapper; -import net.minecraftforge.items.wrapper.RecipeWrapper; - -public class MillstoneTileEntity extends KineticTileEntity { - - public ItemStackHandler inputInv; - public ItemStackHandler outputInv; - public LazyOptional capability; - public int timer; - private MillingRecipe lastRecipe; - - public MillstoneTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - inputInv = new ItemStackHandler(1); - outputInv = new ItemStackHandler(9); - capability = LazyOptional.of(MillstoneInventoryHandler::new); - } - - @Override - public void addBehaviours(List behaviours) { - behaviours.add(new DirectBeltInputBehaviour(this)); - super.addBehaviours(behaviours); - registerAwardables(behaviours, AllAdvancements.MILLSTONE); - } - - @Override - @OnlyIn(Dist.CLIENT) - public void tickAudio() { - super.tickAudio(); - - if (getSpeed() == 0) - return; - if (inputInv.getStackInSlot(0) - .isEmpty()) - return; - - float pitch = Mth.clamp((Math.abs(getSpeed()) / 256f) + .45f, .85f, 1f); - SoundScapes.play(AmbienceGroup.MILLING, worldPosition, pitch); - } - - @Override - public void tick() { - super.tick(); - - if (getSpeed() == 0) - return; - for (int i = 0; i < outputInv.getSlots(); i++) - if (outputInv.getStackInSlot(i) - .getCount() == outputInv.getSlotLimit(i)) - return; - - if (timer > 0) { - timer -= getProcessingSpeed(); - - if (level.isClientSide) { - spawnParticles(); - return; - } - if (timer <= 0) - process(); - return; - } - - if (inputInv.getStackInSlot(0) - .isEmpty()) - return; - - RecipeWrapper inventoryIn = new RecipeWrapper(inputInv); - if (lastRecipe == null || !lastRecipe.matches(inventoryIn, level)) { - Optional recipe = AllRecipeTypes.MILLING.find(inventoryIn, level); - if (!recipe.isPresent()) { - timer = 100; - sendData(); - } else { - lastRecipe = recipe.get(); - timer = lastRecipe.getProcessingDuration(); - sendData(); - } - return; - } - - timer = lastRecipe.getProcessingDuration(); - sendData(); - } - - @Override - public void invalidate() { - super.invalidate(); - capability.invalidate(); - } - - @Override - public void destroy() { - super.destroy(); - ItemHelper.dropContents(level, worldPosition, inputInv); - ItemHelper.dropContents(level, worldPosition, outputInv); - } - - private void process() { - RecipeWrapper inventoryIn = new RecipeWrapper(inputInv); - - if (lastRecipe == null || !lastRecipe.matches(inventoryIn, level)) { - Optional recipe = AllRecipeTypes.MILLING.find(inventoryIn, level); - if (!recipe.isPresent()) - return; - lastRecipe = recipe.get(); - } - - ItemStack stackInSlot = inputInv.getStackInSlot(0); - stackInSlot.shrink(1); - inputInv.setStackInSlot(0, stackInSlot); - lastRecipe.rollResults() - .forEach(stack -> ItemHandlerHelper.insertItemStacked(outputInv, stack, false)); - award(AllAdvancements.MILLSTONE); - - sendData(); - setChanged(); - } - - public void spawnParticles() { - ItemStack stackInSlot = inputInv.getStackInSlot(0); - if (stackInSlot.isEmpty()) - return; - - ItemParticleOption data = new ItemParticleOption(ParticleTypes.ITEM, stackInSlot); - float angle = level.random.nextFloat() * 360; - Vec3 offset = new Vec3(0, 0, 0.5f); - offset = VecHelper.rotate(offset, angle, Axis.Y); - Vec3 target = VecHelper.rotate(offset, getSpeed() > 0 ? 25 : -25, Axis.Y); - - Vec3 center = offset.add(VecHelper.getCenterOf(worldPosition)); - target = VecHelper.offsetRandomly(target.subtract(offset), level.random, 1 / 128f); - level.addParticle(data, center.x, center.y, center.z, target.x, target.y, target.z); - } - - @Override - public void write(CompoundTag compound, boolean clientPacket) { - compound.putInt("Timer", timer); - compound.put("InputInventory", inputInv.serializeNBT()); - compound.put("OutputInventory", outputInv.serializeNBT()); - super.write(compound, clientPacket); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - timer = compound.getInt("Timer"); - inputInv.deserializeNBT(compound.getCompound("InputInventory")); - outputInv.deserializeNBT(compound.getCompound("OutputInventory")); - super.read(compound, clientPacket); - } - - public int getProcessingSpeed() { - return Mth.clamp((int) Math.abs(getSpeed() / 16f), 1, 512); - } - - @Override - public LazyOptional getCapability(Capability cap, Direction side) { - if (isItemHandlerCap(cap)) - return capability.cast(); - return super.getCapability(cap, side); - } - - private boolean canProcess(ItemStack stack) { - ItemStackHandler tester = new ItemStackHandler(1); - tester.setStackInSlot(0, stack); - RecipeWrapper inventoryIn = new RecipeWrapper(tester); - - if (lastRecipe != null && lastRecipe.matches(inventoryIn, level)) - return true; - return AllRecipeTypes.MILLING.find(inventoryIn, level) - .isPresent(); - } - - private class MillstoneInventoryHandler extends CombinedInvWrapper { - - public MillstoneInventoryHandler() { - super(inputInv, outputInv); - } - - @Override - public boolean isItemValid(int slot, ItemStack stack) { - if (outputInv == getHandlerFromIndex(getIndexForSlot(slot))) - return false; - return canProcess(stack) && super.isItemValid(slot, stack); - } - - @Override - public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) { - if (outputInv == getHandlerFromIndex(getIndexForSlot(slot))) - return stack; - if (!isItemValid(slot, stack)) - return stack; - return super.insertItem(slot, stack, simulate); - } - - @Override - public ItemStack extractItem(int slot, int amount, boolean simulate) { - if (inputInv == getHandlerFromIndex(getIndexForSlot(slot))) - return ItemStack.EMPTY; - return super.extractItem(slot, amount, simulate); - } - - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/mixer/CompactingRecipe.java b/src/main/java/com/simibubi/create/content/contraptions/components/mixer/CompactingRecipe.java deleted file mode 100644 index 7e25e410e..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/mixer/CompactingRecipe.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.simibubi.create.content.contraptions.components.mixer; - -import com.simibubi.create.AllRecipeTypes; -import com.simibubi.create.content.contraptions.processing.BasinRecipe; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder.ProcessingRecipeParams; - -public class CompactingRecipe extends BasinRecipe { - - public CompactingRecipe(ProcessingRecipeParams params) { - super(AllRecipeTypes.COMPACTING, params); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MechanicalMixerRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MechanicalMixerRenderer.java deleted file mode 100644 index ec59b2037..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MechanicalMixerRenderer.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.simibubi.create.content.contraptions.components.mixer; - -import com.jozufozu.flywheel.backend.Backend; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.Direction; -import net.minecraft.world.level.block.state.BlockState; - -public class MechanicalMixerRenderer extends KineticTileEntityRenderer { - - public MechanicalMixerRenderer(BlockEntityRendererProvider.Context context) { - super(context); - } - - @Override - public boolean shouldRenderOffScreen(KineticTileEntity te) { - return true; - } - - @Override - protected void renderSafe(KineticTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - - if (Backend.canUseInstancing(te.getLevel())) return; - - BlockState blockState = te.getBlockState(); - MechanicalMixerTileEntity mixer = (MechanicalMixerTileEntity) te; - - VertexConsumer vb = buffer.getBuffer(RenderType.solid()); - - SuperByteBuffer superBuffer = CachedBufferer.partial(AllBlockPartials.SHAFTLESS_COGWHEEL, blockState); - standardKineticRotationTransform(superBuffer, te, light).renderInto(ms, vb); - - float renderedHeadOffset = mixer.getRenderedHeadOffset(partialTicks); - float speed = mixer.getRenderedHeadRotationSpeed(partialTicks); - float time = AnimationTickHolder.getRenderTime(te.getLevel()); - float angle = ((time * speed * 6 / 10f) % 360) / 180 * (float) Math.PI; - - SuperByteBuffer poleRender = CachedBufferer.partial(AllBlockPartials.MECHANICAL_MIXER_POLE, blockState); - poleRender.translate(0, -renderedHeadOffset, 0) - .light(light) - .renderInto(ms, vb); - - SuperByteBuffer headRender = CachedBufferer.partial(AllBlockPartials.MECHANICAL_MIXER_HEAD, blockState); - headRender.rotateCentered(Direction.UP, angle) - .translate(0, -renderedHeadOffset, 0) - .light(light) - .renderInto(ms, vb); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MechanicalMixerTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MechanicalMixerTileEntity.java deleted file mode 100644 index a32b40ea5..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MechanicalMixerTileEntity.java +++ /dev/null @@ -1,314 +0,0 @@ -package com.simibubi.create.content.contraptions.components.mixer; - -import java.util.List; -import java.util.Optional; - -import com.simibubi.create.AllRecipeTypes; -import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.content.contraptions.components.press.MechanicalPressTileEntity; -import com.simibubi.create.content.contraptions.fluids.FluidFX; -import com.simibubi.create.content.contraptions.fluids.recipe.PotionMixingRecipes; -import com.simibubi.create.content.contraptions.processing.BasinOperatingTileEntity; -import com.simibubi.create.content.contraptions.processing.BasinTileEntity; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipe; -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.advancement.CreateAdvancement; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.item.SmartInventory; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour.TankSegment; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction.Axis; -import net.minecraft.core.particles.ItemParticleOption; -import net.minecraft.core.particles.ParticleOptions; -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.util.Mth; -import net.minecraft.world.Container; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.CraftingRecipe; -import net.minecraft.world.item.crafting.Recipe; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.common.crafting.IShapedRecipe; -import net.minecraftforge.items.CapabilityItemHandler; -import net.minecraftforge.items.IItemHandler; - -public class MechanicalMixerTileEntity extends BasinOperatingTileEntity { - - private static final Object shapelessOrMixingRecipesKey = new Object(); - - public int runningTicks; - public int processingTicks; - public boolean running; - - public MechanicalMixerTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - public float getRenderedHeadOffset(float partialTicks) { - int localTick; - float offset = 0; - if (running) { - if (runningTicks < 20) { - localTick = runningTicks; - float num = (localTick + partialTicks) / 20f; - num = ((2 - Mth.cos((float) (num * Math.PI))) / 2); - offset = num - .5f; - } else if (runningTicks <= 20) { - offset = 1; - } else { - localTick = 40 - runningTicks; - float num = (localTick - partialTicks) / 20f; - num = ((2 - Mth.cos((float) (num * Math.PI))) / 2); - offset = num - .5f; - } - } - return offset + 7 / 16f; - } - - public float getRenderedHeadRotationSpeed(float partialTicks) { - float speed = getSpeed(); - if (running) { - if (runningTicks < 15) { - return speed; - } - if (runningTicks <= 20) { - return speed * 2; - } - return speed; - } - return speed / 2; - } - - @Override - public void addBehaviours(List behaviours) { - super.addBehaviours(behaviours); - registerAwardables(behaviours, AllAdvancements.MIXER); - } - - @Override - protected AABB createRenderBoundingBox() { - return new AABB(worldPosition).expandTowards(0, -1.5, 0); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - running = compound.getBoolean("Running"); - runningTicks = compound.getInt("Ticks"); - super.read(compound, clientPacket); - - if (clientPacket && hasLevel()) - getBasin().ifPresent(bte -> bte.setAreFluidsMoving(running && runningTicks <= 20)); - } - - @Override - public void write(CompoundTag compound, boolean clientPacket) { - compound.putBoolean("Running", running); - compound.putInt("Ticks", runningTicks); - super.write(compound, clientPacket); - } - - @Override - public void tick() { - super.tick(); - - if (runningTicks >= 40) { - running = false; - runningTicks = 0; - basinChecker.scheduleUpdate(); - return; - } - - float speed = Math.abs(getSpeed()); - if (running && level != null) { - if (level.isClientSide && runningTicks == 20) - renderParticles(); - - if ((!level.isClientSide || isVirtual()) && runningTicks == 20) { - if (processingTicks < 0) { - float recipeSpeed = 1; - if (currentRecipe instanceof ProcessingRecipe) { - int t = ((ProcessingRecipe) currentRecipe).getProcessingDuration(); - if (t != 0) - recipeSpeed = t / 100f; - } - - processingTicks = Mth.clamp((Mth.log2((int) (512 / speed))) * Mth.ceil(recipeSpeed * 15) + 1, 1, 512); - - Optional basin = getBasin(); - if (basin.isPresent()) { - Couple tanks = basin.get() - .getTanks(); - if (!tanks.getFirst() - .isEmpty() - || !tanks.getSecond() - .isEmpty()) - level.playSound(null, worldPosition, SoundEvents.BUBBLE_COLUMN_WHIRLPOOL_AMBIENT, - SoundSource.BLOCKS, .75f, speed < 65 ? .75f : 1.5f); - } - - } else { - processingTicks--; - if (processingTicks == 0) { - runningTicks++; - processingTicks = -1; - applyBasinRecipe(); - sendData(); - } - } - } - - if (runningTicks != 20) - runningTicks++; - } - } - - public void renderParticles() { - Optional basin = getBasin(); - if (!basin.isPresent() || level == null) - return; - - for (SmartInventory inv : basin.get() - .getInvs()) { - for (int slot = 0; slot < inv.getSlots(); slot++) { - ItemStack stackInSlot = inv.getItem(slot); - if (stackInSlot.isEmpty()) - continue; - ItemParticleOption data = new ItemParticleOption(ParticleTypes.ITEM, stackInSlot); - spillParticle(data); - } - } - - for (SmartFluidTankBehaviour behaviour : basin.get() - .getTanks()) { - if (behaviour == null) - continue; - for (TankSegment tankSegment : behaviour.getTanks()) { - if (tankSegment.isEmpty(0)) - continue; - spillParticle(FluidFX.getFluidParticle(tankSegment.getRenderedFluid())); - } - } - } - - protected void spillParticle(ParticleOptions data) { - float angle = level.random.nextFloat() * 360; - Vec3 offset = new Vec3(0, 0, 0.25f); - offset = VecHelper.rotate(offset, angle, Axis.Y); - Vec3 target = VecHelper.rotate(offset, getSpeed() > 0 ? 25 : -25, Axis.Y) - .add(0, .25f, 0); - Vec3 center = offset.add(VecHelper.getCenterOf(worldPosition)); - target = VecHelper.offsetRandomly(target.subtract(offset), level.random, 1 / 128f); - level.addParticle(data, center.x, center.y - 1.75f, center.z, target.x, target.y, target.z); - } - - @Override - protected List> getMatchingRecipes() { - List> matchingRecipes = super.getMatchingRecipes(); - - if (!AllConfigs.SERVER.recipes.allowBrewingInMixer.get()) - return matchingRecipes; - - Optional basin = getBasin(); - if (!basin.isPresent()) - return matchingRecipes; - - BasinTileEntity basinTileEntity = basin.get(); - if (basin.isEmpty()) - return matchingRecipes; - - IItemHandler availableItems = basinTileEntity - .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) - .orElse(null); - if (availableItems == null) - return matchingRecipes; - - for (int i = 0; i < availableItems.getSlots(); i++) { - ItemStack stack = availableItems.getStackInSlot(i); - if (stack.isEmpty()) - continue; - - List list = PotionMixingRecipes.BY_ITEM.get(stack.getItem()); - if (list == null) - continue; - for (MixingRecipe mixingRecipe : list) - if (matchBasinRecipe(mixingRecipe)) - matchingRecipes.add(mixingRecipe); - } - - return matchingRecipes; - } - - @Override - protected boolean matchStaticFilters(Recipe r) { - return ((r instanceof CraftingRecipe && !(r instanceof IShapedRecipe) - && AllConfigs.SERVER.recipes.allowShapelessInMixer.get() && r.getIngredients() - .size() > 1 - && !MechanicalPressTileEntity.canCompress(r)) && !AllRecipeTypes.shouldIgnoreInAutomation(r) - || r.getType() == AllRecipeTypes.MIXING.getType()); - } - - @Override - public void startProcessingBasin() { - if (running && runningTicks <= 20) - return; - super.startProcessingBasin(); - running = true; - runningTicks = 0; - } - - @Override - public boolean continueWithPreviousRecipe() { - runningTicks = 20; - return true; - } - - @Override - protected void onBasinRemoved() { - if (!running) - return; - runningTicks = 40; - running = false; - } - - @Override - protected Object getRecipeCacheKey() { - return shapelessOrMixingRecipesKey; - } - - @Override - protected boolean isRunning() { - return running; - } - - @Override - protected Optional getProcessedRecipeTrigger() { - return Optional.of(AllAdvancements.MIXER); - } - - @Override - @OnlyIn(Dist.CLIENT) - public void tickAudio() { - super.tickAudio(); - - // SoundEvents.BLOCK_STONE_BREAK - boolean slow = Math.abs(getSpeed()) < 65; - if (slow && AnimationTickHolder.getTicks() % 2 == 0) - return; - if (runningTicks == 20) - AllSoundEvents.MIXING.playAt(level, worldPosition, .75f, 1, true); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MixerInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MixerInstance.java deleted file mode 100644 index 8104dd20b..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MixerInstance.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.simibubi.create.content.contraptions.components.mixer; - -import com.jozufozu.flywheel.api.Instancer; -import com.jozufozu.flywheel.api.MaterialManager; -import com.jozufozu.flywheel.api.instance.DynamicInstance; -import com.jozufozu.flywheel.core.materials.oriented.OrientedData; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.flwdata.RotatingData; -import com.simibubi.create.content.contraptions.relays.encased.EncasedCogInstance; -import com.simibubi.create.foundation.render.AllMaterialSpecs; -import com.simibubi.create.foundation.utility.AnimationTickHolder; - -import net.minecraft.core.Direction; - -public class MixerInstance extends EncasedCogInstance implements DynamicInstance { - - private final RotatingData mixerHead; - private final OrientedData mixerPole; - private final MechanicalMixerTileEntity mixer; - - public MixerInstance(MaterialManager dispatcher, MechanicalMixerTileEntity tile) { - super(dispatcher, tile, false); - this.mixer = tile; - - mixerHead = getRotatingMaterial().getModel(AllBlockPartials.MECHANICAL_MIXER_HEAD, blockState) - .createInstance(); - - mixerHead.setRotationAxis(Direction.Axis.Y); - - mixerPole = getOrientedMaterial() - .getModel(AllBlockPartials.MECHANICAL_MIXER_POLE, blockState) - .createInstance(); - - - float renderedHeadOffset = getRenderedHeadOffset(); - - transformPole(renderedHeadOffset); - transformHead(renderedHeadOffset); - } - - @Override - protected Instancer getCogModel() { - return materialManager.defaultSolid() - .material(AllMaterialSpecs.ROTATING) - .getModel(AllBlockPartials.SHAFTLESS_COGWHEEL, blockEntity.getBlockState()); - } - - @Override - public void beginFrame() { - - float renderedHeadOffset = getRenderedHeadOffset(); - - transformPole(renderedHeadOffset); - transformHead(renderedHeadOffset); - } - - private void transformHead(float renderedHeadOffset) { - float speed = mixer.getRenderedHeadRotationSpeed(AnimationTickHolder.getPartialTicks()); - - mixerHead.setPosition(getInstancePosition()) - .nudge(0, -renderedHeadOffset, 0) - .setRotationalSpeed(speed * 2); - } - - private void transformPole(float renderedHeadOffset) { - mixerPole.setPosition(getInstancePosition()) - .nudge(0, -renderedHeadOffset, 0); - } - - private float getRenderedHeadOffset() { - return mixer.getRenderedHeadOffset(AnimationTickHolder.getPartialTicks()); - } - - @Override - public void updateLight() { - super.updateLight(); - - relight(pos.below(), mixerHead); - relight(pos, mixerPole); - } - - @Override - public void remove() { - super.remove(); - mixerHead.delete(); - mixerPole.delete(); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MixingRecipe.java b/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MixingRecipe.java deleted file mode 100644 index 12e1d7b0f..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MixingRecipe.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.simibubi.create.content.contraptions.components.mixer; - -import com.simibubi.create.AllRecipeTypes; -import com.simibubi.create.content.contraptions.processing.BasinRecipe; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder.ProcessingRecipeParams; - -public class MixingRecipe extends BasinRecipe { - - public MixingRecipe(ProcessingRecipeParams params) { - super(AllRecipeTypes.MIXING, params); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/motor/CreativeMotorRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/motor/CreativeMotorRenderer.java deleted file mode 100644 index 6885a9ea8..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/motor/CreativeMotorRenderer.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.simibubi.create.content.contraptions.components.motor; - -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; - -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.world.level.block.state.BlockState; - -public class CreativeMotorRenderer extends KineticTileEntityRenderer { - - public CreativeMotorRenderer(BlockEntityRendererProvider.Context context) { - super(context); - } - - @Override - protected SuperByteBuffer getRotatedModel(KineticTileEntity te, BlockState state) { - return CachedBufferer.partialFacing(AllBlockPartials.SHAFT_HALF, state); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/motor/CreativeMotorTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/motor/CreativeMotorTileEntity.java deleted file mode 100644 index 1e8c397c1..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/motor/CreativeMotorTileEntity.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.simibubi.create.content.contraptions.components.motor; - -import java.util.List; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.base.GeneratingKineticTileEntity; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.CenteredSideValueBoxTransform; -import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueBehaviour.StepContext; -import com.simibubi.create.foundation.utility.Lang; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; - -public class CreativeMotorTileEntity extends GeneratingKineticTileEntity { - - public static final int DEFAULT_SPEED = 16; - protected ScrollValueBehaviour generatedSpeed; - - public CreativeMotorTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - @Override - public void addBehaviours(List behaviours) { - super.addBehaviours(behaviours); - Integer max = AllConfigs.SERVER.kinetics.maxMotorSpeed.get(); - - CenteredSideValueBoxTransform slot = new CenteredSideValueBoxTransform( - (motor, side) -> motor.getValue(CreativeMotorBlock.FACING) == side.getOpposite()); - - generatedSpeed = new ScrollValueBehaviour(Lang.translateDirect("generic.speed"), this, slot); - generatedSpeed.between(-max, max); - generatedSpeed.value = DEFAULT_SPEED; - generatedSpeed.scrollableValue = DEFAULT_SPEED; - generatedSpeed.withUnit(i -> Lang.translateDirect("generic.unit.rpm")); - generatedSpeed.withCallback(i -> this.updateGeneratedRotation()); - generatedSpeed.withStepFunction(CreativeMotorTileEntity::step); - behaviours.add(generatedSpeed); - } - - @Override - public void initialize() { - super.initialize(); - if (!hasSource() || getGeneratedSpeed() > getTheoreticalSpeed()) - updateGeneratedRotation(); - } - - @Override - public float getGeneratedSpeed() { - if (!AllBlocks.CREATIVE_MOTOR.has(getBlockState())) - return 0; - return convertToDirection(generatedSpeed.getValue(), getBlockState().getValue(CreativeMotorBlock.FACING)); - } - - public static int step(StepContext context) { - int current = context.currentValue; - int step = 1; - - if (!context.shift) { - int magnitude = Math.abs(current) - (context.forward == current > 0 ? 0 : 1); - - if (magnitude >= 4) - step *= 4; - if (magnitude >= 32) - step *= 4; - if (magnitude >= 128) - step *= 4; - } - - return (int) (current + (context.forward ? step : -step) == 0 ? step + 1 : step); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/press/BeltPressingCallbacks.java b/src/main/java/com/simibubi/create/content/contraptions/components/press/BeltPressingCallbacks.java deleted file mode 100644 index def61353d..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/press/BeltPressingCallbacks.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.simibubi.create.content.contraptions.components.press; - -import static com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProcessingBehaviour.ProcessingResult.HOLD; -import static com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProcessingBehaviour.ProcessingResult.PASS; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -import com.simibubi.create.Create; -import com.simibubi.create.content.contraptions.components.press.PressingBehaviour.Mode; -import com.simibubi.create.content.contraptions.relays.belt.BeltHelper; -import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProcessingBehaviour.ProcessingResult; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour.TransportedResult; - -import net.minecraft.world.item.ItemStack; - -public class BeltPressingCallbacks { - - static ProcessingResult onItemReceived(TransportedItemStack transported, - TransportedItemStackHandlerBehaviour handler, PressingBehaviour behaviour) { - if (behaviour.specifics.getKineticSpeed() == 0) - return PASS; - if (behaviour.running) - return HOLD; - if (!behaviour.specifics.tryProcessOnBelt(transported, null, true)) - return PASS; - - behaviour.start(Mode.BELT); - return HOLD; - } - - static ProcessingResult whenItemHeld(TransportedItemStack transported, TransportedItemStackHandlerBehaviour handler, - PressingBehaviour behaviour) { - - if (behaviour.specifics.getKineticSpeed() == 0) - return PASS; - if (!behaviour.running) - return PASS; - if (behaviour.runningTicks != PressingBehaviour.CYCLE / 2) - return HOLD; - - behaviour.particleItems.clear(); - ArrayList results = new ArrayList<>(); - if (!behaviour.specifics.tryProcessOnBelt(transported, results, false)) - return PASS; - - boolean bulk = behaviour.specifics.canProcessInBulk() || transported.stack.getCount() == 1; - - List collect = results.stream() - .map(stack -> { - TransportedItemStack copy = transported.copy(); - boolean centered = BeltHelper.isItemUpright(stack); - copy.stack = stack; - copy.locked = true; - copy.angle = centered ? 180 : Create.RANDOM.nextInt(360); - return copy; - }) - .collect(Collectors.toList()); - - if (bulk) { - if (collect.isEmpty()) - handler.handleProcessingOnItem(transported, TransportedResult.removeItem()); - else - handler.handleProcessingOnItem(transported, TransportedResult.convertTo(collect)); - - } else { - TransportedItemStack left = transported.copy(); - left.stack.shrink(1); - - if (collect.isEmpty()) - handler.handleProcessingOnItem(transported, TransportedResult.convertTo(left)); - else - handler.handleProcessingOnItem(transported, TransportedResult.convertToAndLeaveHeld(collect, left)); - } - - behaviour.tileEntity.sendData(); - return HOLD; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/press/MechanicalPressRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/press/MechanicalPressRenderer.java deleted file mode 100644 index 44302ce7c..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/press/MechanicalPressRenderer.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.simibubi.create.content.contraptions.components.press; - -import static net.minecraft.world.level.block.state.properties.BlockStateProperties.HORIZONTAL_FACING; - -import com.jozufozu.flywheel.backend.Backend; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.world.level.block.state.BlockState; - -public class MechanicalPressRenderer extends KineticTileEntityRenderer { - - public MechanicalPressRenderer(BlockEntityRendererProvider.Context context) { - super(context); - } - - @Override - public boolean shouldRenderOffScreen(KineticTileEntity te) { - return true; - } - - @Override - protected void renderSafe(KineticTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - super.renderSafe(te, partialTicks, ms, buffer, light, overlay); - - if (Backend.canUseInstancing(te.getLevel())) - return; - - BlockState blockState = te.getBlockState(); - PressingBehaviour pressingBehaviour = ((MechanicalPressTileEntity) te).getPressingBehaviour(); - float renderedHeadOffset = - pressingBehaviour.getRenderedHeadOffset(partialTicks) * pressingBehaviour.mode.headOffset; - - SuperByteBuffer headRender = CachedBufferer.partialFacing(AllBlockPartials.MECHANICAL_PRESS_HEAD, blockState, - blockState.getValue(HORIZONTAL_FACING)); - headRender.translate(0, -renderedHeadOffset, 0) - .light(light) - .renderInto(ms, buffer.getBuffer(RenderType.solid())); - } - - @Override - protected BlockState getRenderedBlockState(KineticTileEntity te) { - return shaft(getRotationAxisOf(te)); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/press/MechanicalPressTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/press/MechanicalPressTileEntity.java deleted file mode 100644 index 09ee5eeff..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/press/MechanicalPressTileEntity.java +++ /dev/null @@ -1,253 +0,0 @@ -package com.simibubi.create.content.contraptions.components.press; - -import java.util.List; -import java.util.Optional; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllRecipeTypes; -import com.simibubi.create.content.contraptions.components.crafter.MechanicalCraftingRecipe; -import com.simibubi.create.content.contraptions.components.press.PressingBehaviour.Mode; -import com.simibubi.create.content.contraptions.components.press.PressingBehaviour.PressingBehaviourSpecifics; -import com.simibubi.create.content.contraptions.itemAssembly.SequencedAssemblyRecipe; -import com.simibubi.create.content.contraptions.processing.BasinOperatingTileEntity; -import com.simibubi.create.content.contraptions.processing.BasinTileEntity; -import com.simibubi.create.content.contraptions.processing.InWorldProcessing; -import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack; -import com.simibubi.create.foundation.advancement.AdvancementBehaviour; -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.advancement.CreateAdvancement; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.item.ItemHelper; -import com.simibubi.create.foundation.item.SmartInventory; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.NonNullList; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.Container; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.CraftingRecipe; -import net.minecraft.world.item.crafting.Ingredient; -import net.minecraft.world.item.crafting.Recipe; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.items.ItemHandlerHelper; -import net.minecraftforge.items.ItemStackHandler; -import net.minecraftforge.items.wrapper.RecipeWrapper; - -public class MechanicalPressTileEntity extends BasinOperatingTileEntity implements PressingBehaviourSpecifics { - - private static final Object compressingRecipesKey = new Object(); - - public PressingBehaviour pressingBehaviour; - private int tracksCreated; - - public MechanicalPressTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - @Override - protected AABB createRenderBoundingBox() { - return new AABB(worldPosition).expandTowards(0, -1.5, 0) - .expandTowards(0, 1, 0); - } - - @Override - public void addBehaviours(List behaviours) { - super.addBehaviours(behaviours); - pressingBehaviour = new PressingBehaviour(this); - behaviours.add(pressingBehaviour); - - registerAwardables(behaviours, AllAdvancements.PRESS, AllAdvancements.COMPACTING, - AllAdvancements.TRACK_CRAFTING); - } - - public void onItemPressed(ItemStack result) { - award(AllAdvancements.PRESS); - if (AllBlocks.TRACK.isIn(result)) - tracksCreated += result.getCount(); - if (tracksCreated >= 1000) { - award(AllAdvancements.TRACK_CRAFTING); - tracksCreated = 0; - } - } - - public PressingBehaviour getPressingBehaviour() { - return pressingBehaviour; - } - - @Override - public boolean tryProcessInBasin(boolean simulate) { - applyBasinRecipe(); - - Optional basin = getBasin(); - if (basin.isPresent()) { - SmartInventory inputs = basin.get() - .getInputInventory(); - for (int slot = 0; slot < inputs.getSlots(); slot++) { - ItemStack stackInSlot = inputs.getItem(slot); - if (stackInSlot.isEmpty()) - continue; - pressingBehaviour.particleItems.add(stackInSlot); - } - } - - return true; - } - - @Override - protected void write(CompoundTag compound, boolean clientPacket) { - super.write(compound, clientPacket); - if (getBehaviour(AdvancementBehaviour.TYPE).isOwnerPresent()) - compound.putInt("TracksCreated", tracksCreated); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - super.read(compound, clientPacket); - tracksCreated = compound.getInt("TracksCreated"); - } - - @Override - public boolean tryProcessInWorld(ItemEntity itemEntity, boolean simulate) { - ItemStack item = itemEntity.getItem(); - Optional recipe = getRecipe(item); - if (!recipe.isPresent()) - return false; - if (simulate) - return true; - - ItemStack itemCreated = ItemStack.EMPTY; - pressingBehaviour.particleItems.add(item); - if (canProcessInBulk() || item.getCount() == 1) { - InWorldProcessing.applyRecipeOn(itemEntity, recipe.get()); - itemCreated = itemEntity.getItem() - .copy(); - } else { - for (ItemStack result : InWorldProcessing.applyRecipeOn(ItemHandlerHelper.copyStackWithSize(item, 1), - recipe.get())) { - if (itemCreated.isEmpty()) - itemCreated = result.copy(); - ItemEntity created = - new ItemEntity(level, itemEntity.getX(), itemEntity.getY(), itemEntity.getZ(), result); - created.setDefaultPickUpDelay(); - created.setDeltaMovement(VecHelper.offsetRandomly(Vec3.ZERO, level.random, .05f)); - level.addFreshEntity(created); - } - item.shrink(1); - } - - if (!itemCreated.isEmpty()) - onItemPressed(itemCreated); - return true; - } - - @Override - public boolean tryProcessOnBelt(TransportedItemStack input, List outputList, boolean simulate) { - Optional recipe = getRecipe(input.stack); - if (!recipe.isPresent()) - return false; - if (simulate) - return true; - pressingBehaviour.particleItems.add(input.stack); - List outputs = InWorldProcessing.applyRecipeOn( - canProcessInBulk() ? input.stack : ItemHandlerHelper.copyStackWithSize(input.stack, 1), recipe.get()); - - for (ItemStack created : outputs) { - if (!created.isEmpty()) { - onItemPressed(created); - break; - } - } - - outputList.addAll(outputs); - return true; - } - - @Override - public void onPressingCompleted() { - if (pressingBehaviour.onBasin() && matchBasinRecipe(currentRecipe) - && getBasin().filter(BasinTileEntity::canContinueProcessing) - .isPresent()) - startProcessingBasin(); - else - basinChecker.scheduleUpdate(); - } - - private static final RecipeWrapper pressingInv = new RecipeWrapper(new ItemStackHandler(1)); - - public Optional getRecipe(ItemStack item) { - Optional assemblyRecipe = - SequencedAssemblyRecipe.getRecipe(level, item, AllRecipeTypes.PRESSING.getType(), PressingRecipe.class); - if (assemblyRecipe.isPresent()) - return assemblyRecipe; - - pressingInv.setItem(0, item); - return AllRecipeTypes.PRESSING.find(pressingInv, level); - } - - public static boolean canCompress(Recipe recipe) { - if (!(recipe instanceof CraftingRecipe) || !AllConfigs.SERVER.recipes.allowShapedSquareInPress.get()) - return false; - NonNullList ingredients = recipe.getIngredients(); - return (ingredients.size() == 4 || ingredients.size() == 9) && ItemHelper.matchAllIngredients(ingredients); - } - - @Override - protected boolean matchStaticFilters(Recipe recipe) { - return (recipe instanceof CraftingRecipe && !(recipe instanceof MechanicalCraftingRecipe) && canCompress(recipe) - && !AllRecipeTypes.shouldIgnoreInAutomation(recipe)) - || recipe.getType() == AllRecipeTypes.COMPACTING.getType(); - } - - @Override - public float getKineticSpeed() { - return getSpeed(); - } - - @Override - public boolean canProcessInBulk() { - return AllConfigs.SERVER.recipes.bulkPressing.get(); - } - - @Override - protected Object getRecipeCacheKey() { - return compressingRecipesKey; - } - - @Override - public int getParticleAmount() { - return 15; - } - - @Override - public void startProcessingBasin() { - if (pressingBehaviour.running && pressingBehaviour.runningTicks <= PressingBehaviour.CYCLE / 2) - return; - super.startProcessingBasin(); - pressingBehaviour.start(Mode.BASIN); - } - - @Override - protected void onBasinRemoved() { - pressingBehaviour.particleItems.clear(); - pressingBehaviour.running = false; - pressingBehaviour.runningTicks = 0; - sendData(); - } - - @Override - protected boolean isRunning() { - return pressingBehaviour.running; - } - - @Override - protected Optional getProcessedRecipeTrigger() { - return Optional.of(AllAdvancements.COMPACTING); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/press/PressInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/press/PressInstance.java deleted file mode 100644 index 2d4d8b033..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/press/PressInstance.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.simibubi.create.content.contraptions.components.press; - -import org.joml.Quaternionf; - -import com.jozufozu.flywheel.api.MaterialManager; -import com.jozufozu.flywheel.api.instance.DynamicInstance; -import com.jozufozu.flywheel.core.Materials; -import com.jozufozu.flywheel.core.materials.oriented.OrientedData; -import com.mojang.math.Axis; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.relays.encased.ShaftInstance; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; - -public class PressInstance extends ShaftInstance implements DynamicInstance { - - private final OrientedData pressHead; - private final MechanicalPressTileEntity press; - - public PressInstance(MaterialManager dispatcher, MechanicalPressTileEntity tile) { - super(dispatcher, tile); - press = tile; - - pressHead = dispatcher.defaultSolid() - .material(Materials.ORIENTED) - .getModel(AllBlockPartials.MECHANICAL_PRESS_HEAD, blockState) - .createInstance(); - - Quaternionf q = Axis.YP - .rotationDegrees(AngleHelper.horizontalAngle(blockState.getValue(MechanicalPressBlock.HORIZONTAL_FACING))); - - pressHead.setRotation(q); - - transformModels(); - } - - @Override - public void beginFrame() { - transformModels(); - } - - private void transformModels() { - float renderedHeadOffset = getRenderedHeadOffset(press); - - pressHead.setPosition(getInstancePosition()) - .nudge(0, -renderedHeadOffset, 0); - } - - private float getRenderedHeadOffset(MechanicalPressTileEntity press) { - PressingBehaviour pressingBehaviour = press.getPressingBehaviour(); - return pressingBehaviour.getRenderedHeadOffset(AnimationTickHolder.getPartialTicks()) - * pressingBehaviour.mode.headOffset; - } - - @Override - public void updateLight() { - super.updateLight(); - - relight(pos, pressHead); - } - - @Override - public void remove() { - super.remove(); - pressHead.delete(); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawBlock.java deleted file mode 100644 index c444caa2e..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawBlock.java +++ /dev/null @@ -1,117 +0,0 @@ -package com.simibubi.create.content.contraptions.components.saw; - -import javax.annotation.ParametersAreNonnullByDefault; - -import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.DirectionalAxisKineticBlock; -import com.simibubi.create.content.contraptions.components.actors.DrillBlock; -import com.simibubi.create.foundation.block.ITE; - -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.PushReaction; -import net.minecraft.world.level.pathfinder.PathComputationType; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.VoxelShape; - -@ParametersAreNonnullByDefault -@MethodsReturnNonnullByDefault -public class SawBlock extends DirectionalAxisKineticBlock implements ITE { - public static DamageSource damageSourceSaw = new DamageSource("create.mechanical_saw").bypassArmor(); - - public SawBlock(Properties properties) { - super(properties); - } - - @Override - public BlockState getStateForPlacement(BlockPlaceContext context) { - BlockState stateForPlacement = super.getStateForPlacement(context); - Direction facing = stateForPlacement.getValue(FACING); - if (facing.getAxis().isVertical()) - return stateForPlacement; - return stateForPlacement.setValue(AXIS_ALONG_FIRST_COORDINATE, facing.getAxis() == Axis.X); - } - - @Override - public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) { - return AllShapes.CASING_12PX.get(state.getValue(FACING)); - } - - @Override - public void entityInside(BlockState state, Level worldIn, BlockPos pos, Entity entityIn) { - if (entityIn instanceof ItemEntity) - return; - if (!new AABB(pos).deflate(.1f).intersects(entityIn.getBoundingBox())) - return; - withTileEntityDo(worldIn, pos, te -> { - if (te.getSpeed() == 0) - return; - entityIn.hurt(damageSourceSaw, (float) DrillBlock.getDamage(te.getSpeed())); - }); - } - - @Override - public void updateEntityAfterFallOn(BlockGetter worldIn, Entity entityIn) { - super.updateEntityAfterFallOn(worldIn, entityIn); - if (!(entityIn instanceof ItemEntity)) - return; - if (entityIn.level.isClientSide) - return; - - BlockPos pos = entityIn.blockPosition(); - withTileEntityDo(entityIn.level, pos, te -> { - if (te.getSpeed() == 0) - return; - te.insertItem((ItemEntity) entityIn); - }); - } - - @Override - public PushReaction getPistonPushReaction(BlockState state) { - return PushReaction.NORMAL; - } - - public static boolean isHorizontal(BlockState state) { - return state.getValue(FACING).getAxis().isHorizontal(); - } - - @Override - public Axis getRotationAxis(BlockState state) { - return isHorizontal(state) ? state.getValue(FACING).getAxis() : super.getRotationAxis(state); - } - - @Override - public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) { - return isHorizontal(state) ? face == state.getValue(FACING).getOpposite() - : super.hasShaftTowards(world, pos, state, face); - } - - @Override - public Class getTileEntityClass() { - return SawTileEntity.class; - } - - @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.SAW.get(); - } - - @Override - public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) { - return false; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawFilterSlot.java b/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawFilterSlot.java deleted file mode 100644 index c9a407a64..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawFilterSlot.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.simibubi.create.content.contraptions.components.saw; - -import com.jozufozu.flywheel.util.transform.TransformStack; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.core.Direction; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; - -public class SawFilterSlot extends ValueBoxTransform { - - @Override - protected Vec3 getLocalOffset(BlockState state) { - if (state.getValue(SawBlock.FACING) != Direction.UP) - return null; - Vec3 x = VecHelper.voxelSpace(8f, 12.5f, 12.25f); - Vec3 z = VecHelper.voxelSpace(12.25f, 12.5f, 8f); - return state.getValue(SawBlock.AXIS_ALONG_FIRST_COORDINATE) ? z : x; - } - - @Override - protected void rotate(BlockState state, PoseStack ms) { - int yRot = state.getValue(SawBlock.AXIS_ALONG_FIRST_COORDINATE) ? 270 : 180; - TransformStack.cast(ms) - .rotateY(yRot) - .rotateX(90); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawInstance.java deleted file mode 100644 index bba424cbf..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawInstance.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.simibubi.create.content.contraptions.components.saw; - -import com.jozufozu.flywheel.api.Instancer; -import com.jozufozu.flywheel.api.MaterialManager; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.SingleRotatingInstance; -import com.simibubi.create.content.contraptions.base.flwdata.RotatingData; - -import net.minecraft.core.Direction; -import net.minecraft.world.level.block.Rotation; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; - -public class SawInstance extends SingleRotatingInstance { - - public SawInstance(MaterialManager modelManager, KineticTileEntity tile) { - super(modelManager, tile); - } - - @Override - protected Instancer getModel() { - if (blockState.getValue(BlockStateProperties.FACING) - .getAxis() - .isHorizontal()) { - BlockState referenceState = blockState.rotate(blockEntity.getLevel(), blockEntity.getBlockPos(), Rotation.CLOCKWISE_180); - Direction facing = referenceState.getValue(BlockStateProperties.FACING); - return getRotatingMaterial().getModel(AllBlockPartials.SHAFT_HALF, referenceState, facing); - } else { - return getRotatingMaterial().getModel(shaft()); - } - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawRenderer.java deleted file mode 100644 index c409fed17..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawRenderer.java +++ /dev/null @@ -1,205 +0,0 @@ -package com.simibubi.create.content.contraptions.components.saw; - -import static net.minecraft.world.level.block.state.properties.BlockStateProperties.FACING; - -import com.jozufozu.flywheel.backend.Backend; -import com.jozufozu.flywheel.core.PartialModel; -import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.math.Axis; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringRenderer; -import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.block.model.ItemTransforms; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.client.renderer.entity.ItemRenderer; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.core.Direction; -import net.minecraft.util.Mth; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.Rotation; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; - -public class SawRenderer extends SafeTileEntityRenderer { - - public SawRenderer(BlockEntityRendererProvider.Context context) { - } - - @Override - protected void renderSafe(SawTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light, - int overlay) { - renderBlade(te, ms, buffer, light); - renderItems(te, partialTicks, ms, buffer, light, overlay); - FilteringRenderer.renderOnTileEntity(te, partialTicks, ms, buffer, light, overlay); - - if (Backend.canUseInstancing(te.getLevel())) - return; - - renderShaft(te, ms, buffer, light, overlay); - } - - protected void renderBlade(SawTileEntity te, PoseStack ms, MultiBufferSource buffer, int light) { - BlockState blockState = te.getBlockState(); - PartialModel partial; - float speed = te.getSpeed(); - boolean rotate = false; - - if (SawBlock.isHorizontal(blockState)) { - if (speed > 0) { - partial = AllBlockPartials.SAW_BLADE_HORIZONTAL_ACTIVE; - } else if (speed < 0) { - partial = AllBlockPartials.SAW_BLADE_HORIZONTAL_REVERSED; - } else { - partial = AllBlockPartials.SAW_BLADE_HORIZONTAL_INACTIVE; - } - } else { - if (te.getSpeed() > 0) { - partial = AllBlockPartials.SAW_BLADE_VERTICAL_ACTIVE; - } else if (speed < 0) { - partial = AllBlockPartials.SAW_BLADE_VERTICAL_REVERSED; - } else { - partial = AllBlockPartials.SAW_BLADE_VERTICAL_INACTIVE; - } - - if (blockState.getValue(SawBlock.AXIS_ALONG_FIRST_COORDINATE)) - rotate = true; - } - - SuperByteBuffer superBuffer = CachedBufferer.partialFacing(partial, blockState); - if (rotate) { - superBuffer.rotateCentered(Direction.UP, AngleHelper.rad(90)); - } - superBuffer.color(0xFFFFFF) - .light(light) - .renderInto(ms, buffer.getBuffer(RenderType.cutoutMipped())); - } - - protected void renderShaft(SawTileEntity te, PoseStack ms, MultiBufferSource buffer, int light, int overlay) { - KineticTileEntityRenderer.renderRotatingBuffer(te, getRotatedModel(te), ms, - buffer.getBuffer(RenderType.solid()), light); - } - - protected void renderItems(SawTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - boolean processingMode = te.getBlockState() - .getValue(SawBlock.FACING) == Direction.UP; - if (processingMode && !te.inventory.isEmpty()) { - boolean alongZ = !te.getBlockState() - .getValue(SawBlock.AXIS_ALONG_FIRST_COORDINATE); - ms.pushPose(); - - boolean moving = te.inventory.recipeDuration != 0; - float offset = moving ? (float) (te.inventory.remainingTime) / te.inventory.recipeDuration : 0; - float processingSpeed = Mth.clamp(Math.abs(te.getSpeed()) / 32, 1, 128); - if (moving) { - offset = Mth - .clamp(offset + ((-partialTicks + .5f) * processingSpeed) / te.inventory.recipeDuration, 0.125f, 1f); - if (!te.inventory.appliedRecipe) - offset += 1; - offset /= 2; - } - - if (te.getSpeed() == 0) - offset = .5f; - if (te.getSpeed() < 0 ^ alongZ) - offset = 1 - offset; - - for (int i = 0; i < te.inventory.getSlots(); i++) { - ItemStack stack = te.inventory.getStackInSlot(i); - if (stack.isEmpty()) - continue; - - ItemRenderer itemRenderer = Minecraft.getInstance() - .getItemRenderer(); - BakedModel modelWithOverrides = itemRenderer.getModel(stack, te.getLevel(), null, 0); - boolean blockItem = modelWithOverrides.isGui3d(); - - ms.translate(alongZ ? offset : .5, blockItem ? .925f : 13f / 16f, alongZ ? .5 : offset); - - ms.scale(.5f, .5f, .5f); - if (alongZ) - ms.mulPose(Axis.YP.rotationDegrees(90)); - ms.mulPose(Axis.XP.rotationDegrees(90)); - itemRenderer.renderStatic(stack, ItemTransforms.TransformType.FIXED, light, overlay, ms, buffer, 0); - break; - } - - ms.popPose(); - } - } - - protected SuperByteBuffer getRotatedModel(KineticTileEntity te) { - BlockState state = te.getBlockState(); - if (state.getValue(FACING) - .getAxis() - .isHorizontal()) - return CachedBufferer.partialFacing(AllBlockPartials.SHAFT_HALF, - state.rotate(te.getLevel(), te.getBlockPos(), Rotation.CLOCKWISE_180)); - return CachedBufferer.block(KineticTileEntityRenderer.KINETIC_TILE, - getRenderedBlockState(te)); - } - - protected BlockState getRenderedBlockState(KineticTileEntity te) { - return KineticTileEntityRenderer.shaft(KineticTileEntityRenderer.getRotationAxisOf(te)); - } - - public static void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld, - ContraptionMatrices matrices, MultiBufferSource buffer) { - BlockState state = context.state; - Direction facing = state.getValue(SawBlock.FACING); - - Vec3 facingVec = Vec3.atLowerCornerOf(context.state.getValue(SawBlock.FACING) - .getNormal()); - facingVec = context.rotation.apply(facingVec); - - Direction closestToFacing = Direction.getNearest(facingVec.x, facingVec.y, facingVec.z); - - boolean horizontal = closestToFacing.getAxis() - .isHorizontal(); - boolean backwards = VecHelper.isVecPointingTowards(context.relativeMotion, facing.getOpposite()); - boolean moving = context.getAnimationSpeed() != 0; - boolean shouldAnimate = - (context.contraption.stalled && horizontal) || (!context.contraption.stalled && !backwards && moving); - - SuperByteBuffer superBuffer; - if (SawBlock.isHorizontal(state)) { - if (shouldAnimate) - superBuffer = CachedBufferer.partial(AllBlockPartials.SAW_BLADE_HORIZONTAL_ACTIVE, state); - else - superBuffer = CachedBufferer.partial(AllBlockPartials.SAW_BLADE_HORIZONTAL_INACTIVE, state); - } else { - if (shouldAnimate) - superBuffer = CachedBufferer.partial(AllBlockPartials.SAW_BLADE_VERTICAL_ACTIVE, state); - else - superBuffer = CachedBufferer.partial(AllBlockPartials.SAW_BLADE_VERTICAL_INACTIVE, state); - } - - superBuffer.transform(matrices.getModel()) - .centre() - .rotateY(AngleHelper.horizontalAngle(facing)) - .rotateX(AngleHelper.verticalAngle(facing)); - - if (!SawBlock.isHorizontal(state)) { - superBuffer.rotateZ(state.getValue(SawBlock.AXIS_ALONG_FIRST_COORDINATE) ? 90 : 0); - } - - superBuffer.unCentre() - .light(matrices.getWorld(), ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) - .renderInto(matrices.getViewProjection(), buffer.getBuffer(RenderType.cutoutMipped())); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawTileEntity.java deleted file mode 100644 index 39b90ab0f..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawTileEntity.java +++ /dev/null @@ -1,510 +0,0 @@ -package com.simibubi.create.content.contraptions.components.saw; - -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; -import java.util.Optional; -import java.util.function.Predicate; -import java.util.function.Supplier; -import java.util.stream.Collectors; - -import javax.annotation.ParametersAreNonnullByDefault; - -import com.google.common.base.Suppliers; -import com.google.common.collect.ImmutableList; -import com.simibubi.create.AllRecipeTypes; -import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.content.contraptions.components.actors.BlockBreakingKineticTileEntity; -import com.simibubi.create.content.contraptions.itemAssembly.SequencedAssemblyRecipe; -import com.simibubi.create.content.contraptions.processing.ProcessingInventory; -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.item.ItemHelper; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; -import com.simibubi.create.foundation.utility.AbstractBlockBreakQueue; -import com.simibubi.create.foundation.utility.TreeCutter; -import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.foundation.utility.recipe.RecipeConditions; -import com.simibubi.create.foundation.utility.recipe.RecipeFinder; - -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.particles.BlockParticleOption; -import net.minecraft.core.particles.ItemParticleOption; -import net.minecraft.core.particles.ParticleOptions; -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.tags.BlockTags; -import net.minecraft.util.Mth; -import net.minecraft.util.RandomSource; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.Recipe; -import net.minecraft.world.item.crafting.RecipeType; -import net.minecraft.world.item.crafting.StonecutterRecipe; -import net.minecraft.world.level.block.BambooStalkBlock; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.CactusBlock; -import net.minecraft.world.level.block.ChorusPlantBlock; -import net.minecraft.world.level.block.KelpBlock; -import net.minecraft.world.level.block.KelpPlantBlock; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.block.StemGrownBlock; -import net.minecraft.world.level.block.SugarCaneBlock; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.items.CapabilityItemHandler; -import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.registries.ForgeRegistries; - -@ParametersAreNonnullByDefault -@MethodsReturnNonnullByDefault -public class SawTileEntity extends BlockBreakingKineticTileEntity { - - private static final Object cuttingRecipesKey = new Object(); - public static final Supplier> woodcuttingRecipeType = - Suppliers.memoize(() -> ForgeRegistries.RECIPE_TYPES.getValue(new ResourceLocation("druidcraft", "woodcutting"))); - - public ProcessingInventory inventory; - private int recipeIndex; - private final LazyOptional invProvider; - private FilteringBehaviour filtering; - - private ItemStack playEvent; - - public SawTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - inventory = new ProcessingInventory(this::start).withSlotLimit(!AllConfigs.SERVER.recipes.bulkCutting.get()); - inventory.remainingTime = -1; - recipeIndex = 0; - invProvider = LazyOptional.of(() -> inventory); - playEvent = ItemStack.EMPTY; - } - - @Override - public void addBehaviours(List behaviours) { - super.addBehaviours(behaviours); - filtering = new FilteringBehaviour(this, new SawFilterSlot()).forRecipes(); - behaviours.add(filtering); - behaviours.add(new DirectBeltInputBehaviour(this).allowingBeltFunnelsWhen(this::canProcess)); - registerAwardables(behaviours, AllAdvancements.SAW_PROCESSING); - } - - @Override - public void write(CompoundTag compound, boolean clientPacket) { - compound.put("Inventory", inventory.serializeNBT()); - compound.putInt("RecipeIndex", recipeIndex); - super.write(compound, clientPacket); - - if (!clientPacket || playEvent.isEmpty()) - return; - compound.put("PlayEvent", playEvent.serializeNBT()); - playEvent = ItemStack.EMPTY; - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - super.read(compound, clientPacket); - inventory.deserializeNBT(compound.getCompound("Inventory")); - recipeIndex = compound.getInt("RecipeIndex"); - if (compound.contains("PlayEvent")) - playEvent = ItemStack.of(compound.getCompound("PlayEvent")); - } - - @Override - protected AABB createRenderBoundingBox() { - return new AABB(worldPosition).inflate(.125f); - } - - @Override - @OnlyIn(Dist.CLIENT) - public void tickAudio() { - super.tickAudio(); - if (getSpeed() == 0) - return; - - if (!playEvent.isEmpty()) { - boolean isWood = false; - Item item = playEvent.getItem(); - if (item instanceof BlockItem) { - Block block = ((BlockItem) item).getBlock(); - isWood = block.getSoundType(block.defaultBlockState(), level, worldPosition, null) == SoundType.WOOD; - } - spawnEventParticles(playEvent); - playEvent = ItemStack.EMPTY; - if (!isWood) - AllSoundEvents.SAW_ACTIVATE_STONE.playAt(level, worldPosition, 3, 1, true); - else - AllSoundEvents.SAW_ACTIVATE_WOOD.playAt(level, worldPosition, 3, 1, true); - return; - } - } - - @Override - public void tick() { - if (shouldRun() && ticksUntilNextProgress < 0) - destroyNextTick(); - super.tick(); - - if (!canProcess()) - return; - if (getSpeed() == 0) - return; - if (inventory.remainingTime == -1) { - if (!inventory.isEmpty() && !inventory.appliedRecipe) - start(inventory.getStackInSlot(0)); - return; - } - - float processingSpeed = Mth.clamp(Math.abs(getSpeed()) / 24, 1, 128); - inventory.remainingTime -= processingSpeed; - - if (inventory.remainingTime > 0) - spawnParticles(inventory.getStackInSlot(0)); - - if (inventory.remainingTime < 5 && !inventory.appliedRecipe) { - if (level.isClientSide && !isVirtual()) - return; - playEvent = inventory.getStackInSlot(0); - applyRecipe(); - inventory.appliedRecipe = true; - inventory.recipeDuration = 20; - inventory.remainingTime = 20; - sendData(); - return; - } - - Vec3 itemMovement = getItemMovementVec(); - Direction itemMovementFacing = Direction.getNearest(itemMovement.x, itemMovement.y, itemMovement.z); - if (inventory.remainingTime > 0) - return; - inventory.remainingTime = 0; - - for (int slot = 0; slot < inventory.getSlots(); slot++) { - ItemStack stack = inventory.getStackInSlot(slot); - if (stack.isEmpty()) - continue; - ItemStack tryExportingToBeltFunnel = getBehaviour(DirectBeltInputBehaviour.TYPE) - .tryExportingToBeltFunnel(stack, itemMovementFacing.getOpposite(), false); - if (tryExportingToBeltFunnel != null) { - if (tryExportingToBeltFunnel.getCount() != stack.getCount()) { - inventory.setStackInSlot(slot, tryExportingToBeltFunnel); - notifyUpdate(); - return; - } - if (!tryExportingToBeltFunnel.isEmpty()) - return; - } - } - - BlockPos nextPos = worldPosition.offset(itemMovement.x, itemMovement.y, itemMovement.z); - DirectBeltInputBehaviour behaviour = TileEntityBehaviour.get(level, nextPos, DirectBeltInputBehaviour.TYPE); - if (behaviour != null) { - boolean changed = false; - if (!behaviour.canInsertFromSide(itemMovementFacing)) - return; - if (level.isClientSide && !isVirtual()) - return; - for (int slot = 0; slot < inventory.getSlots(); slot++) { - ItemStack stack = inventory.getStackInSlot(slot); - if (stack.isEmpty()) - continue; - ItemStack remainder = behaviour.handleInsertion(stack, itemMovementFacing, false); - if (remainder.equals(stack, false)) - continue; - inventory.setStackInSlot(slot, remainder); - changed = true; - } - if (changed) { - setChanged(); - sendData(); - } - return; - } - - // Eject Items - Vec3 outPos = VecHelper.getCenterOf(worldPosition) - .add(itemMovement.scale(.5f) - .add(0, .5, 0)); - Vec3 outMotion = itemMovement.scale(.0625) - .add(0, .125, 0); - for (int slot = 0; slot < inventory.getSlots(); slot++) { - ItemStack stack = inventory.getStackInSlot(slot); - if (stack.isEmpty()) - continue; - ItemEntity entityIn = new ItemEntity(level, outPos.x, outPos.y, outPos.z, stack); - entityIn.setDeltaMovement(outMotion); - level.addFreshEntity(entityIn); - } - inventory.clear(); - level.updateNeighbourForOutputSignal(worldPosition, getBlockState().getBlock()); - inventory.remainingTime = -1; - sendData(); - } - - @Override - public void invalidate() { - super.invalidate(); - invProvider.invalidate(); - } - - @Override - public void destroy() { - super.destroy(); - ItemHelper.dropContents(level, worldPosition, inventory); - } - - @Override - public LazyOptional getCapability(Capability cap, Direction side) { - if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY && side != Direction.DOWN) - return invProvider.cast(); - return super.getCapability(cap, side); - } - - protected void spawnEventParticles(ItemStack stack) { - if (stack == null || stack.isEmpty()) - return; - - ParticleOptions particleData = null; - if (stack.getItem() instanceof BlockItem) - particleData = new BlockParticleOption(ParticleTypes.BLOCK, ((BlockItem) stack.getItem()).getBlock() - .defaultBlockState()); - else - particleData = new ItemParticleOption(ParticleTypes.ITEM, stack); - - RandomSource r = level.random; - Vec3 v = VecHelper.getCenterOf(this.worldPosition) - .add(0, 5 / 16f, 0); - for (int i = 0; i < 10; i++) { - Vec3 m = VecHelper.offsetRandomly(new Vec3(0, 0.25f, 0), r, .125f); - level.addParticle(particleData, v.x, v.y, v.z, m.x, m.y, m.y); - } - } - - protected void spawnParticles(ItemStack stack) { - if (stack == null || stack.isEmpty()) - return; - - ParticleOptions particleData = null; - float speed = 1; - if (stack.getItem() instanceof BlockItem) - particleData = new BlockParticleOption(ParticleTypes.BLOCK, ((BlockItem) stack.getItem()).getBlock() - .defaultBlockState()); - else { - particleData = new ItemParticleOption(ParticleTypes.ITEM, stack); - speed = .125f; - } - - RandomSource r = level.random; - Vec3 vec = getItemMovementVec(); - Vec3 pos = VecHelper.getCenterOf(this.worldPosition); - float offset = inventory.recipeDuration != 0 ? (float) (inventory.remainingTime) / inventory.recipeDuration : 0; - offset /= 2; - if (inventory.appliedRecipe) - offset -= .5f; - level.addParticle(particleData, pos.x() + -vec.x * offset, pos.y() + .45f, pos.z() + -vec.z * offset, - -vec.x * speed, r.nextFloat() * speed, -vec.z * speed); - } - - public Vec3 getItemMovementVec() { - boolean alongX = !getBlockState().getValue(SawBlock.AXIS_ALONG_FIRST_COORDINATE); - int offset = getSpeed() < 0 ? -1 : 1; - return new Vec3(offset * (alongX ? 1 : 0), 0, offset * (alongX ? 0 : -1)); - } - - private void applyRecipe() { - List> recipes = getRecipes(); - if (recipes.isEmpty()) - return; - if (recipeIndex >= recipes.size()) - recipeIndex = 0; - - Recipe recipe = recipes.get(recipeIndex); - - int rolls = inventory.getStackInSlot(0) - .getCount(); - inventory.clear(); - - List list = new ArrayList<>(); - for (int roll = 0; roll < rolls; roll++) { - List results = new LinkedList(); - if (recipe instanceof CuttingRecipe) - results = ((CuttingRecipe) recipe).rollResults(); - else if (recipe instanceof StonecutterRecipe || recipe.getType() == woodcuttingRecipeType.get()) - results.add(recipe.getResultItem() - .copy()); - - for (int i = 0; i < results.size(); i++) { - ItemStack stack = results.get(i); - ItemHelper.addToList(stack, list); - } - } - - for (int slot = 0; slot < list.size() && slot + 1 < inventory.getSlots(); slot++) - inventory.setStackInSlot(slot + 1, list.get(slot)); - - award(AllAdvancements.SAW_PROCESSING); - } - - private List> getRecipes() { - Optional assemblyRecipe = SequencedAssemblyRecipe.getRecipe(level, inventory.getStackInSlot(0), - AllRecipeTypes.CUTTING.getType(), CuttingRecipe.class); - if (assemblyRecipe.isPresent() && filtering.test(assemblyRecipe.get() - .getResultItem())) - return ImmutableList.of(assemblyRecipe.get()); - - Predicate> types = RecipeConditions.isOfType(AllRecipeTypes.CUTTING.getType(), - AllConfigs.SERVER.recipes.allowStonecuttingOnSaw.get() ? RecipeType.STONECUTTING : null, - AllConfigs.SERVER.recipes.allowWoodcuttingOnSaw.get() ? woodcuttingRecipeType.get() : null); - - List> startedSearch = RecipeFinder.get(cuttingRecipesKey, level, types); - return startedSearch.stream() - .filter(RecipeConditions.outputMatchesFilter(filtering)) - .filter(RecipeConditions.firstIngredientMatches(inventory.getStackInSlot(0))) - .filter(r -> !AllRecipeTypes.shouldIgnoreInAutomation(r)) - .collect(Collectors.toList()); - } - - public void insertItem(ItemEntity entity) { - if (!canProcess()) - return; - if (!inventory.isEmpty()) - return; - if (!entity.isAlive()) - return; - if (level.isClientSide) - return; - - inventory.clear(); - ItemStack remainder = inventory.insertItem(0, entity.getItem() - .copy(), false); - if (remainder.isEmpty()) - entity.discard(); - else - entity.setItem(remainder); - } - - public void start(ItemStack inserted) { - if (!canProcess()) - return; - if (inventory.isEmpty()) - return; - if (level.isClientSide && !isVirtual()) - return; - - List> recipes = getRecipes(); - boolean valid = !recipes.isEmpty(); - int time = 50; - - if (recipes.isEmpty()) { - inventory.remainingTime = inventory.recipeDuration = 10; - inventory.appliedRecipe = false; - sendData(); - return; - } - - if (valid) { - recipeIndex++; - if (recipeIndex >= recipes.size()) - recipeIndex = 0; - } - - Recipe recipe = recipes.get(recipeIndex); - if (recipe instanceof CuttingRecipe) { - time = ((CuttingRecipe) recipe).getProcessingDuration(); - } - - inventory.remainingTime = time * Math.max(1, (inserted.getCount() / 5)); - inventory.recipeDuration = inventory.remainingTime; - inventory.appliedRecipe = false; - sendData(); - } - - protected boolean canProcess() { - return getBlockState().getValue(SawBlock.FACING) == Direction.UP; - } - - // Block Breaker - - @Override - protected boolean shouldRun() { - return getBlockState().getValue(SawBlock.FACING) - .getAxis() - .isHorizontal(); - } - - @Override - protected BlockPos getBreakingPos() { - return getBlockPos().relative(getBlockState().getValue(SawBlock.FACING)); - } - - @Override - public void onBlockBroken(BlockState stateToBreak) { - Optional dynamicTree = - TreeCutter.findDynamicTree(stateToBreak.getBlock(), breakingPos); - if (dynamicTree.isPresent()) { - dynamicTree.get() - .destroyBlocks(level, null, this::dropItemFromCutTree); - return; - } - - super.onBlockBroken(stateToBreak); - TreeCutter.findTree(level, breakingPos) - .destroyBlocks(level, null, this::dropItemFromCutTree); - } - - public void dropItemFromCutTree(BlockPos pos, ItemStack stack) { - float distance = (float) Math.sqrt(pos.distSqr(breakingPos)); - Vec3 dropPos = VecHelper.getCenterOf(pos); - ItemEntity entity = new ItemEntity(level, dropPos.x, dropPos.y, dropPos.z, stack); - entity.setDeltaMovement(Vec3.atLowerCornerOf(breakingPos.subtract(this.worldPosition)) - .scale(distance / 20f)); - level.addFreshEntity(entity); - } - - @Override - public boolean canBreak(BlockState stateToBreak, float blockHardness) { - boolean sawable = isSawable(stateToBreak); - return super.canBreak(stateToBreak, blockHardness) && sawable; - } - - public static boolean isSawable(BlockState stateToBreak) { - if (stateToBreak.is(BlockTags.SAPLINGS)) - return false; - if (TreeCutter.isLog(stateToBreak) || (stateToBreak.is(BlockTags.LEAVES))) - return true; - if (TreeCutter.isRoot(stateToBreak)) - return true; - Block block = stateToBreak.getBlock(); - if (block instanceof BambooStalkBlock) - return true; - if (block instanceof StemGrownBlock) - return true; - if (block instanceof CactusBlock) - return true; - if (block instanceof SugarCaneBlock) - return true; - if (block instanceof KelpPlantBlock) - return true; - if (block instanceof KelpBlock) - return true; - if (block instanceof ChorusPlantBlock) - return true; - if (TreeCutter.canDynamicTreeCutFrom(block)) - return true; - return false; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/steam/PoweredShaftTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/steam/PoweredShaftTileEntity.java deleted file mode 100644 index 8efc121fd..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/steam/PoweredShaftTileEntity.java +++ /dev/null @@ -1,140 +0,0 @@ -package com.simibubi.create.content.contraptions.components.steam; - -import java.util.List; - -import com.simibubi.create.content.contraptions.base.GeneratingKineticTileEntity; -import com.simibubi.create.foundation.block.BlockStressValues; -import com.simibubi.create.foundation.utility.RegisteredObjects; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction.Axis; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtUtils; -import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.util.Mth; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.registries.ForgeRegistries; - -public class PoweredShaftTileEntity extends GeneratingKineticTileEntity { - - public BlockPos enginePos; - public float engineEfficiency; - public int movementDirection; - public int initialTicks; - public Block capacityKey; - - public PoweredShaftTileEntity(BlockEntityType typeIn, BlockPos pos, BlockState state) { - super(typeIn, pos, state); - movementDirection = 1; - initialTicks = 3; - } - - @Override - public void tick() { - super.tick(); - if (initialTicks > 0) - initialTicks--; - } - - public void update(BlockPos sourcePos, int direction, float efficiency) { - BlockPos key = worldPosition.subtract(sourcePos); - enginePos = key; - float prev = engineEfficiency; - engineEfficiency = efficiency; - int prevDirection = this.movementDirection; - if (Mth.equal(efficiency, prev) && prevDirection == direction) - return; - - capacityKey = level.getBlockState(sourcePos) - .getBlock(); - this.movementDirection = direction; - updateGeneratedRotation(); - } - - public void remove(BlockPos sourcePos) { - if (!isPoweredBy(sourcePos)) - return; - - enginePos = null; - engineEfficiency = 0; - movementDirection = 0; - capacityKey = null; - updateGeneratedRotation(); - } - - public boolean canBePoweredBy(BlockPos globalPos) { - return initialTicks == 0 && (enginePos == null || isPoweredBy(globalPos)); - } - - public boolean isPoweredBy(BlockPos globalPos) { - BlockPos key = worldPosition.subtract(globalPos); - return key.equals(enginePos); - } - - @Override - protected void write(CompoundTag compound, boolean clientPacket) { - compound.putInt("Direction", movementDirection); - if (initialTicks > 0) - compound.putInt("Warmup", initialTicks); - if (enginePos != null && capacityKey != null) { - compound.put("EnginePos", NbtUtils.writeBlockPos(enginePos)); - compound.putFloat("EnginePower", engineEfficiency); - compound.putString("EngineType", RegisteredObjects.getKeyOrThrow(capacityKey) - .toString()); - } - super.write(compound, clientPacket); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - super.read(compound, clientPacket); - movementDirection = compound.getInt("Direction"); - initialTicks = compound.getInt("Warmup"); - enginePos = null; - engineEfficiency = 0; - if (compound.contains("EnginePos")) { - enginePos = NbtUtils.readBlockPos(compound.getCompound("EnginePos")); - engineEfficiency = compound.getFloat("EnginePower"); - capacityKey = ForgeRegistries.BLOCKS.getValue(new ResourceLocation(compound.getString("EngineType"))); - } - } - - @Override - public float getGeneratedSpeed() { - return getCombinedCapacity() > 0 ? movementDirection * 16 * getSpeedModifier() : 0; - } - - private float getCombinedCapacity() { - return capacityKey == null ? 0 : (float) (engineEfficiency * BlockStressValues.getCapacity(capacityKey)); - } - - private int getSpeedModifier() { - return (int) (1 + (engineEfficiency >= 1 ? 3 : Math.min(2, Math.floor(engineEfficiency * 4)))); - } - - @Override - public float calculateAddedStressCapacity() { - float capacity = getCombinedCapacity() / getSpeedModifier(); - this.lastCapacityProvided = capacity; - return capacity; - } - - @Override - public int getRotationAngleOffset(Axis axis) { - int combinedCoords = axis.choose(worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()); - return super.getRotationAngleOffset(axis) + (combinedCoords % 2 == 0 ? 180 : 0); - } - - @Override - public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { - return false; - } - - public boolean addToEngineTooltip(List tooltip, boolean isPlayerSneaking) { - return super.addToGoggleTooltip(tooltip, isPlayerSneaking); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/steam/SteamEngineRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/steam/SteamEngineRenderer.java deleted file mode 100644 index 936700aa5..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/steam/SteamEngineRenderer.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.simibubi.create.content.contraptions.components.steam; - -import com.jozufozu.flywheel.backend.Backend; -import com.jozufozu.flywheel.core.PartialModel; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; -import com.simibubi.create.foundation.utility.AngleHelper; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.util.Mth; -import net.minecraft.world.level.block.state.BlockState; - -public class SteamEngineRenderer extends SafeTileEntityRenderer { - - public SteamEngineRenderer(BlockEntityRendererProvider.Context context) {} - - @Override - protected void renderSafe(SteamEngineTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - if (Backend.canUseInstancing(te.getLevel())) - return; - - Float angle = te.getTargetAngle(); - if (angle == null) - return; - - BlockState blockState = te.getBlockState(); - Direction facing = SteamEngineBlock.getFacing(blockState); - Axis facingAxis = facing.getAxis(); - Axis axis = Axis.Y; - - PoweredShaftTileEntity shaft = te.getShaft(); - if (shaft != null) - axis = KineticTileEntityRenderer.getRotationAxisOf(shaft); - - boolean roll90 = facingAxis.isHorizontal() && axis == Axis.Y || facingAxis.isVertical() && axis == Axis.Z; - float sine = Mth.sin(angle); - float sine2 = Mth.sin(angle - Mth.HALF_PI); - float piston = ((1 - sine) / 4) * 24 / 16f; - - VertexConsumer vb = buffer.getBuffer(RenderType.solid()); - - transformed(AllBlockPartials.ENGINE_PISTON, blockState, facing, roll90) - .translate(0, piston, 0) - .light(light) - .renderInto(ms, vb); - - transformed(AllBlockPartials.ENGINE_LINKAGE, blockState, facing, roll90) - .centre() - .translate(0, 1, 0) - .unCentre() - .translate(0, piston, 0) - .translate(0, 4 / 16f, 8 / 16f) - .rotateX(sine2 * 23f) - .translate(0, -4 / 16f, -8 / 16f) - .light(light) - .renderInto(ms, vb); - - transformed(AllBlockPartials.ENGINE_CONNECTOR, blockState, facing, roll90) - .translate(0, 2, 0) - .centre() - .rotateXRadians(-angle + Mth.HALF_PI) - .unCentre() - .light(light) - .renderInto(ms, vb); - } - - private SuperByteBuffer transformed(PartialModel model, BlockState blockState, Direction facing, boolean roll90) { - return CachedBufferer.partial(model, blockState) - .centre() - .rotateY(AngleHelper.horizontalAngle(facing)) - .rotateX(AngleHelper.verticalAngle(facing) + 90) - .rotateY(roll90 ? -90 : 0) - .unCentre(); - } - - @Override - public int getViewDistance() { - return 128; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/steam/SteamEngineTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/steam/SteamEngineTileEntity.java deleted file mode 100644 index e2fe33f67..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/steam/SteamEngineTileEntity.java +++ /dev/null @@ -1,270 +0,0 @@ -package com.simibubi.create.content.contraptions.components.steam; - -import java.lang.ref.WeakReference; -import java.util.List; - -import javax.annotation.Nullable; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.content.contraptions.base.GeneratingKineticTileEntity; -import com.simibubi.create.content.contraptions.base.IRotate; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.WindmillBearingTileEntity.RotationDirection; -import com.simibubi.create.content.contraptions.fluids.tank.FluidTankTileEntity; -import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation; -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollOptionBehaviour; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.core.Direction.AxisDirection; -import net.minecraft.network.chat.Component; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.util.Mth; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.fml.DistExecutor; - -public class SteamEngineTileEntity extends SmartTileEntity implements IHaveGoggleInformation { - - protected ScrollOptionBehaviour movementDirection; - - public WeakReference target; - public WeakReference source; - - public SteamEngineTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - source = new WeakReference<>(null); - target = new WeakReference<>(null); - } - - @Override - public void addBehaviours(List behaviours) { - movementDirection = new ScrollOptionBehaviour<>(RotationDirection.class, - Lang.translateDirect("contraptions.windmill.rotation_direction"), this, new SteamEngineValueBox()); - movementDirection.requiresWrench(); - movementDirection.onlyActiveWhen(() -> { - PoweredShaftTileEntity shaft = getShaft(); - return shaft == null || !shaft.hasSource(); - }); - movementDirection.withCallback($ -> onDirectionChanged()); - behaviours.add(movementDirection); - - registerAwardables(behaviours, AllAdvancements.STEAM_ENGINE); - } - - private void onDirectionChanged() {} - - @Override - public void tick() { - super.tick(); - FluidTankTileEntity tank = getTank(); - PoweredShaftTileEntity shaft = getShaft(); - - if (tank == null || shaft == null) { - if (level.isClientSide()) - return; - if (shaft == null) - return; - if (!shaft.getBlockPos() - .subtract(worldPosition) - .equals(shaft.enginePos)) - return; - if (shaft.engineEfficiency == 0) - return; - Direction facing = SteamEngineBlock.getFacing(getBlockState()); - if (level.isLoaded(worldPosition.relative(facing.getOpposite()))) - shaft.update(worldPosition, 0, 0); - return; - } - - boolean verticalTarget = false; - BlockState shaftState = shaft.getBlockState(); - Axis targetAxis = Axis.X; - if (shaftState.getBlock()instanceof IRotate ir) - targetAxis = ir.getRotationAxis(shaftState); - verticalTarget = targetAxis == Axis.Y; - - BlockState blockState = getBlockState(); - if (!AllBlocks.STEAM_ENGINE.has(blockState)) - return; - Direction facing = SteamEngineBlock.getFacing(blockState); - if (facing.getAxis() == Axis.Y) - facing = blockState.getValue(SteamEngineBlock.FACING); - - float efficiency = Mth.clamp(tank.boiler.getEngineEfficiency(tank.getTotalTankSize()), 0, 1); - if (efficiency > 0) - - award(AllAdvancements.STEAM_ENGINE); - - int conveyedSpeedLevel = - efficiency == 0 ? 1 : verticalTarget ? 1 : (int) GeneratingKineticTileEntity.convertToDirection(1, facing); - if (targetAxis == Axis.Z) - conveyedSpeedLevel *= -1; - if (movementDirection.get() == RotationDirection.COUNTER_CLOCKWISE) - conveyedSpeedLevel *= -1; - - float shaftSpeed = shaft.getTheoreticalSpeed(); - if (shaft.hasSource() && shaftSpeed != 0 && conveyedSpeedLevel != 0 - && (shaftSpeed > 0) != (conveyedSpeedLevel > 0)) { - movementDirection.setValue(1 - movementDirection.get() - .ordinal()); - conveyedSpeedLevel *= -1; - } - - shaft.update(worldPosition, conveyedSpeedLevel, efficiency); - - if (!level.isClientSide) - return; - - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> this::spawnParticles); - } - - @Override - public void remove() { - PoweredShaftTileEntity shaft = getShaft(); - if (shaft != null) - shaft.remove(worldPosition); - super.remove(); - } - - @Override - @OnlyIn(Dist.CLIENT) - protected AABB createRenderBoundingBox() { - return super.createRenderBoundingBox().inflate(2); - } - - public PoweredShaftTileEntity getShaft() { - PoweredShaftTileEntity shaft = target.get(); - if (shaft == null || shaft.isRemoved() || !shaft.canBePoweredBy(worldPosition)) { - if (shaft != null) - target = new WeakReference<>(null); - Direction facing = SteamEngineBlock.getFacing(getBlockState()); - BlockEntity anyShaftAt = level.getBlockEntity(worldPosition.relative(facing, 2)); - if (anyShaftAt instanceof PoweredShaftTileEntity ps && ps.canBePoweredBy(worldPosition)) - target = new WeakReference<>(shaft = ps); - } - return shaft; - } - - public FluidTankTileEntity getTank() { - FluidTankTileEntity tank = source.get(); - if (tank == null || tank.isRemoved()) { - if (tank != null) - source = new WeakReference<>(null); - Direction facing = SteamEngineBlock.getFacing(getBlockState()); - BlockEntity be = level.getBlockEntity(worldPosition.relative(facing.getOpposite())); - if (be instanceof FluidTankTileEntity tankTe) - source = new WeakReference<>(tank = tankTe); - } - if (tank == null) - return null; - return tank.getControllerTE(); - } - - float prevAngle = 0; - - @OnlyIn(Dist.CLIENT) - private void spawnParticles() { - Float targetAngle = getTargetAngle(); - PoweredShaftTileEntity ste = target.get(); - if (ste == null) - return; - if (!ste.isPoweredBy(worldPosition) || ste.engineEfficiency == 0) - return; - if (targetAngle == null) - return; - - float angle = AngleHelper.deg(targetAngle); - angle += (angle < 0) ? -180 + 75 : 360 - 75; - angle %= 360; - - PoweredShaftTileEntity shaft = getShaft(); - if (shaft == null || shaft.getSpeed() == 0) - return; - - if (angle >= 0 && !(prevAngle > 180 && angle < 180)) { - prevAngle = angle; - return; - } - if (angle < 0 && !(prevAngle < -180 && angle > -180)) { - prevAngle = angle; - return; - } - - FluidTankTileEntity sourceTE = source.get(); - if (sourceTE != null) { - FluidTankTileEntity controller = sourceTE.getControllerTE(); - if (controller != null && controller.boiler != null) { - float volume = 3f / Math.max(2, controller.boiler.attachedEngines / 6); - float pitch = 1.18f - level.random.nextFloat() * .25f; - level.playLocalSound(worldPosition.getX(), worldPosition.getY(), worldPosition.getZ(), - SoundEvents.CANDLE_EXTINGUISH, SoundSource.BLOCKS, volume, pitch, false); - AllSoundEvents.STEAM.playAt(level, worldPosition, volume / 16, .8f, false); - } - } - - Direction facing = SteamEngineBlock.getFacing(getBlockState()); - - Vec3 offset = VecHelper.rotate(new Vec3(0, 0, 1).add(VecHelper.offsetRandomly(Vec3.ZERO, level.random, 1) - .multiply(1, 1, 0) - .normalize() - .scale(.5f)), AngleHelper.verticalAngle(facing), Axis.X); - offset = VecHelper.rotate(offset, AngleHelper.horizontalAngle(facing), Axis.Y); - Vec3 v = offset.scale(.5f) - .add(Vec3.atCenterOf(worldPosition)); - Vec3 m = offset.subtract(Vec3.atLowerCornerOf(facing.getNormal()) - .scale(.75f)); - level.addParticle(new SteamJetParticleData(1), v.x, v.y, v.z, m.x, m.y, m.z); - - prevAngle = angle; - } - - @Nullable - @OnlyIn(Dist.CLIENT) - public Float getTargetAngle() { - float angle = 0; - BlockState blockState = getBlockState(); - if (!AllBlocks.STEAM_ENGINE.has(blockState)) - return null; - - Direction facing = SteamEngineBlock.getFacing(blockState); - PoweredShaftTileEntity shaft = getShaft(); - Axis facingAxis = facing.getAxis(); - Axis axis = Axis.Y; - - if (shaft == null) - return null; - - axis = KineticTileEntityRenderer.getRotationAxisOf(shaft); - angle = KineticTileEntityRenderer.getAngleForTe(shaft, shaft.getBlockPos(), axis); - - if (axis == facingAxis) - return null; - if (axis.isHorizontal() && (facingAxis == Axis.X ^ facing.getAxisDirection() == AxisDirection.POSITIVE)) - angle *= -1; - if (axis == Axis.X && facing == Direction.DOWN) - angle *= -1; - return angle; - } - - @Override - public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { - PoweredShaftTileEntity shaft = getShaft(); - return shaft == null ? false : shaft.addToEngineTooltip(tooltip, isPlayerSneaking); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/steam/SteamEngineValueBox.java b/src/main/java/com/simibubi/create/content/contraptions/components/steam/SteamEngineValueBox.java deleted file mode 100644 index 2b294850a..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/steam/SteamEngineValueBox.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.simibubi.create.content.contraptions.components.steam; - -import com.jozufozu.flywheel.util.transform.TransformStack; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.Pointing; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; - -public class SteamEngineValueBox extends ValueBoxTransform.Sided { - - @Override - protected boolean isSideActive(BlockState state, Direction direction) { - return SteamEngineBlock.getFacing(state) - .getAxis() != direction.getAxis(); - } - - @Override - protected Vec3 getLocalOffset(BlockState state) { - Direction side = getSide(); - Direction engineFacing = SteamEngineBlock.getFacing(state); - - float roll = 0; - for (Pointing p : Pointing.values()) { - if (p.getCombinedDirection(engineFacing) == side) - roll = p.getXRotation(); - } - if (engineFacing == Direction.UP) - roll += 180; - - float horizontalAngle = AngleHelper.horizontalAngle(engineFacing); - float verticalAngle = AngleHelper.verticalAngle(engineFacing); - - boolean recessed = roll % 180 == 0; - if (engineFacing.getAxis() == Axis.Y) - recessed ^= state.getValue(SteamEngineBlock.FACING).getAxis() == Axis.X; - - Vec3 local = VecHelper.voxelSpace(8, recessed ? 13 : 15, 9); - - local = VecHelper.rotateCentered(local, roll, Axis.Z); - local = VecHelper.rotateCentered(local, horizontalAngle, Axis.Y); - local = VecHelper.rotateCentered(local, verticalAngle, Axis.X); - - return local; - } - - @Override - protected void rotate(BlockState state, PoseStack ms) { - Direction facing = SteamEngineBlock.getFacing(state); - - if (facing.getAxis() == Axis.Y) { - super.rotate(state, ms); - return; - } - - float roll = 0; - for (Pointing p : Pointing.values()) { - if (p.getCombinedDirection(facing) == getSide()) - roll = p.getXRotation(); - } - - float yRot = AngleHelper.horizontalAngle(facing) + (facing == Direction.DOWN ? 180 : 0); - TransformStack.cast(ms) - .rotateY(yRot) - .rotateX(facing == Direction.DOWN ? -90 : 90) - .rotateY(roll); - } - - @Override - protected Vec3 getSouthLocation() { - return Vec3.ZERO; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/steam/whistle/WhistleRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/steam/whistle/WhistleRenderer.java deleted file mode 100644 index 1aafc8d7b..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/steam/whistle/WhistleRenderer.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.simibubi.create.content.contraptions.components.steam.whistle; - -import com.jozufozu.flywheel.core.PartialModel; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.components.steam.whistle.WhistleBlock.WhistleSize; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.Direction; -import net.minecraft.util.Mth; -import net.minecraft.world.level.block.state.BlockState; - -public class WhistleRenderer extends SafeTileEntityRenderer { - - public WhistleRenderer(BlockEntityRendererProvider.Context context) {} - - @Override - protected void renderSafe(WhistleTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - BlockState blockState = te.getBlockState(); - if (!(blockState.getBlock() instanceof WhistleBlock)) - return; - - Direction direction = blockState.getValue(WhistleBlock.FACING); - WhistleSize size = blockState.getValue(WhistleBlock.SIZE); - - PartialModel mouth = size == WhistleSize.LARGE ? AllBlockPartials.WHISTLE_MOUTH_LARGE - : size == WhistleSize.MEDIUM ? AllBlockPartials.WHISTLE_MOUTH_MEDIUM : AllBlockPartials.WHISTLE_MOUTH_SMALL; - - float offset = te.animation.getValue(partialTicks); - if (te.animation.getChaseTarget() > 0 && te.animation.getValue() > 0.5f) { - float wiggleProgress = (AnimationTickHolder.getTicks(te.getLevel()) + partialTicks) / 8f; - offset -= Math.sin(wiggleProgress * (2 * Mth.PI) * (4 - size.ordinal())) / 16f; - } - - CachedBufferer.partial(mouth, blockState) - .centre() - .rotateY(AngleHelper.horizontalAngle(direction)) - .unCentre() - .translate(0, offset * 4 / 16f, 0) - .light(light) - .renderInto(ms, buffer.getBuffer(RenderType.solid())); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/steam/whistle/WhistleTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/steam/whistle/WhistleTileEntity.java deleted file mode 100644 index 6855445eb..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/steam/whistle/WhistleTileEntity.java +++ /dev/null @@ -1,197 +0,0 @@ -package com.simibubi.create.content.contraptions.components.steam.whistle; - -import java.lang.ref.WeakReference; -import java.util.List; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.content.contraptions.components.steam.SteamJetParticleData; -import com.simibubi.create.content.contraptions.components.steam.whistle.WhistleBlock.WhistleSize; -import com.simibubi.create.content.contraptions.components.steam.whistle.WhistleExtenderBlock.WhistleExtenderShape; -import com.simibubi.create.content.contraptions.fluids.tank.FluidTankTileEntity; -import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation; -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; - -import net.minecraft.client.Minecraft; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.util.Mth; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.fml.DistExecutor; - -public class WhistleTileEntity extends SmartTileEntity implements IHaveGoggleInformation { - - public WeakReference source; - public LerpedFloat animation; - protected int pitch; - - public WhistleTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - source = new WeakReference<>(null); - animation = LerpedFloat.linear(); - } - - @Override - public void addBehaviours(List behaviours) { - registerAwardables(behaviours, AllAdvancements.STEAM_WHISTLE); - } - - public void updatePitch() { - BlockPos currentPos = worldPosition.above(); - int newPitch; - for (newPitch = 0; newPitch <= 24; newPitch += 2) { - BlockState blockState = level.getBlockState(currentPos); - if (!AllBlocks.STEAM_WHISTLE_EXTENSION.has(blockState)) - break; - if (blockState.getValue(WhistleExtenderBlock.SHAPE) == WhistleExtenderShape.SINGLE) { - newPitch++; - break; - } - currentPos = currentPos.above(); - } - if (pitch == newPitch) - return; - pitch = newPitch; - - notifyUpdate(); - - FluidTankTileEntity tank = getTank(); - if (tank != null && tank.boiler != null) - tank.boiler.checkPipeOrganAdvancement(tank); - } - - @Override - public void tick() { - super.tick(); - if (!level.isClientSide()) { - if (isPowered()) - award(AllAdvancements.STEAM_WHISTLE); - return; - } - - FluidTankTileEntity tank = getTank(); - boolean powered = isPowered() - && (tank != null && tank.boiler.isActive() && (tank.boiler.passiveHeat || tank.boiler.activeHeat > 0) - || isVirtual()); - animation.chase(powered ? 1 : 0, powered ? .5f : .4f, powered ? Chaser.EXP : Chaser.LINEAR); - animation.tickChaser(); - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> this.tickAudio(getOctave(), powered)); - } - - @Override - protected void write(CompoundTag tag, boolean clientPacket) { - tag.putInt("Pitch", pitch); - super.write(tag, clientPacket); - } - - @Override - protected void read(CompoundTag tag, boolean clientPacket) { - pitch = tag.getInt("Pitch"); - super.read(tag, clientPacket); - } - - @Override - public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { - String[] pitches = Lang.translateDirect("generic.notes") - .getString() - .split(";"); - MutableComponent textComponent = Components.literal(spacing); - tooltip.add(textComponent.append(Lang.translateDirect("generic.pitch", pitches[pitch % pitches.length]))); - return true; - } - - protected boolean isPowered() { - return getBlockState().getOptionalValue(WhistleBlock.POWERED) - .orElse(false); - } - - protected WhistleSize getOctave() { - return getBlockState().getOptionalValue(WhistleBlock.SIZE) - .orElse(WhistleSize.MEDIUM); - } - - @OnlyIn(Dist.CLIENT) - protected WhistleSoundInstance soundInstance; - - @OnlyIn(Dist.CLIENT) - protected void tickAudio(WhistleSize size, boolean powered) { - if (!powered) { - if (soundInstance != null) { - soundInstance.fadeOut(); - soundInstance = null; - } - return; - } - - float f = (float) Math.pow(2, -pitch / 12.0); - boolean particle = level.getGameTime() % 8 == 0; - Vec3 eyePosition = Minecraft.getInstance().cameraEntity.getEyePosition(); - float maxVolume = (float) Mth.clamp((64 - eyePosition.distanceTo(Vec3.atCenterOf(worldPosition))) / 64, 0, 1); - - if (soundInstance == null || soundInstance.isStopped() || soundInstance.getOctave() != size) { - Minecraft.getInstance() - .getSoundManager() - .play(soundInstance = new WhistleSoundInstance(size, worldPosition)); - AllSoundEvents.WHISTLE_CHIFF.playAt(level, worldPosition, maxVolume * .175f, - size == WhistleSize.SMALL ? f + .75f : f, false); - particle = true; - } - - soundInstance.keepAlive(); - soundInstance.setPitch(f); - - if (!particle) - return; - - Direction facing = getBlockState().getOptionalValue(WhistleBlock.FACING) - .orElse(Direction.SOUTH); - float angle = 180 + AngleHelper.horizontalAngle(facing); - Vec3 sizeOffset = VecHelper.rotate(new Vec3(0, -0.4f, 1 / 16f * size.ordinal()), angle, Axis.Y); - Vec3 offset = VecHelper.rotate(new Vec3(0, 1, 0.75f), angle, Axis.Y); - Vec3 v = offset.scale(.45f) - .add(sizeOffset) - .add(Vec3.atCenterOf(worldPosition)); - Vec3 m = offset.subtract(Vec3.atLowerCornerOf(facing.getNormal()) - .scale(.75f)); - level.addParticle(new SteamJetParticleData(1), v.x, v.y, v.z, m.x, m.y, m.z); - } - - public int getPitchId() { - return pitch + 100 * getBlockState().getOptionalValue(WhistleBlock.SIZE) - .orElse(WhistleSize.MEDIUM) - .ordinal(); - } - - public FluidTankTileEntity getTank() { - FluidTankTileEntity tank = source.get(); - if (tank == null || tank.isRemoved()) { - if (tank != null) - source = new WeakReference<>(null); - Direction facing = WhistleBlock.getAttachedDirection(getBlockState()); - BlockEntity be = level.getBlockEntity(worldPosition.relative(facing)); - if (be instanceof FluidTankTileEntity tankTe) - source = new WeakReference<>(tank = tankTe); - } - if (tank == null) - return null; - return tank.getControllerTE(); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionDisassemblyPacket.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionDisassemblyPacket.java deleted file mode 100644 index 1020cfebc..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionDisassemblyPacket.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement; - -import java.util.function.Supplier; - -import com.simibubi.create.foundation.networking.SimplePacketBase; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.fml.DistExecutor; -import net.minecraftforge.network.NetworkEvent.Context; - -public class ContraptionDisassemblyPacket extends SimplePacketBase { - - int entityID; - StructureTransform transform; - - public ContraptionDisassemblyPacket(int entityID, StructureTransform transform) { - this.entityID = entityID; - this.transform = transform; - } - - public ContraptionDisassemblyPacket(FriendlyByteBuf buffer) { - entityID = buffer.readInt(); - transform = StructureTransform.fromBuffer(buffer); - } - - @Override - public void write(FriendlyByteBuf buffer) { - buffer.writeInt(entityID); - transform.writeToBuffer(buffer); - } - - @Override - public void handle(Supplier context) { - context.get() - .enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, - () -> () -> AbstractContraptionEntity.handleDisassemblyPacket(this))); - context.get() - .setPacketHandled(true); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionRelocationPacket.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionRelocationPacket.java deleted file mode 100644 index 5ff0fa20b..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionRelocationPacket.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement; - -import java.util.function.Supplier; - -import com.simibubi.create.foundation.networking.SimplePacketBase; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.fml.DistExecutor; -import net.minecraftforge.network.NetworkEvent.Context; - -public class ContraptionRelocationPacket extends SimplePacketBase { - - int entityID; - - public ContraptionRelocationPacket(int entityID) { - this.entityID = entityID; - } - - public ContraptionRelocationPacket(FriendlyByteBuf buffer) { - entityID = buffer.readInt(); - } - - @Override - public void write(FriendlyByteBuf buffer) { - buffer.writeInt(entityID); - } - - @Override - public void handle(Supplier context) { - context.get() - .enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, - () -> () -> OrientedContraptionEntity.handleRelocationPacket(this))); - context.get() - .setPacketHandled(true); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionType.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionType.java deleted file mode 100644 index 4b5d8fcd0..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionType.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement; - -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.function.Supplier; - -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.BearingContraption; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.ClockworkContraption; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.StabilizedContraption; -import com.simibubi.create.content.contraptions.components.structureMovement.gantry.GantryContraption; -import com.simibubi.create.content.contraptions.components.structureMovement.mounted.MountedContraption; -import com.simibubi.create.content.contraptions.components.structureMovement.piston.PistonContraption; -import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyContraption; -import com.simibubi.create.content.logistics.trains.entity.CarriageContraption; - -public class ContraptionType { - - public static Map entries = new HashMap<>(); - public static ContraptionType - PISTON = register("piston", PistonContraption::new), - BEARING = register("bearing", BearingContraption::new), - PULLEY = register("pulley", PulleyContraption::new), - CLOCKWORK = register("clockwork", ClockworkContraption::new), - MOUNTED = register("mounted", MountedContraption::new), - STABILIZED = register("stabilized", StabilizedContraption::new), - GANTRY = register("gantry", GantryContraption::new), - CARRIAGE = register("carriage", CarriageContraption::new); - - Supplier factory; - String id; - - public static ContraptionType register(String id, Supplier factory) { - ContraptionType value = new ContraptionType(id, factory); - entries.put(id, value); - return value; - } - - private ContraptionType(String id, Supplier factory) { - this.factory = factory; - this.id = id; - } - - public static Contraption fromType(String type) { - for (Entry allContraptionTypes : entries.entrySet()) - if (type.equals(allContraptionTypes.getKey())) - return allContraptionTypes.getValue().factory.get(); - return null; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionWorld.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionWorld.java deleted file mode 100644 index c5e429949..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionWorld.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement; - -import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld; - -import net.minecraft.core.BlockPos; -import net.minecraft.sounds.SoundEvent; -import net.minecraft.sounds.SoundSource; -import net.minecraft.util.Mth; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; -import net.minecraft.world.phys.Vec3; - -public class ContraptionWorld extends WrappedWorld { - final Contraption contraption; - private final int minY; - private final int height; - - public ContraptionWorld(Level world, Contraption contraption) { - super(world); - - this.contraption = contraption; - - // Include 1 block above/below contraption height range to avoid certain edge-case Starlight crashes with - // downward-facing mechanical pistons. - minY = nextMultipleOf16(contraption.bounds.minY - 1); - height = nextMultipleOf16(contraption.bounds.maxY + 1) - minY; - } - - // https://math.stackexchange.com/questions/291468 - private static int nextMultipleOf16(double a) { - return (((Math.abs((int) a) - 1) | 15) + 1) * Mth.sign(a); - } - - @Override - public BlockState getBlockState(BlockPos pos) { - StructureTemplate.StructureBlockInfo blockInfo = contraption.getBlocks().get(pos); - - if (blockInfo != null) - return blockInfo.state; - - return Blocks.AIR.defaultBlockState(); - } - - @Override - public void playSound(Player player, double x, double y, double z, SoundEvent soundIn, SoundSource category, float volume, float pitch) { - - Vec3 worldPos = ContraptionCollider.getWorldToLocalTranslation(new Vec3(x, y, z), this.contraption.entity); - - worldPos = worldPos.add(x, y, z); - - world.playSound(player, worldPos.x, worldPos.y, worldPos.z, soundIn, category, volume, pitch); - } - - @Override - public void playLocalSound(double x, double y, double z, SoundEvent p_184134_7_, SoundSource p_184134_8_, float p_184134_9_, float p_184134_10_, boolean p_184134_11_) { - world.playLocalSound(x, y, z, p_184134_7_, p_184134_8_, p_184134_9_, p_184134_10_, p_184134_11_); - } - - // Ensure that we provide accurate information about ContraptionWorld height to mods (such as Starlight) which - // expect Levels to only have blocks located in chunks within their height range. - - @Override - public int getHeight() { - return height; - } - - @Override - public int getMinBuildHeight() { - return minY; - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ITransformableBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ITransformableBlock.java deleted file mode 100644 index 3e5fc78eb..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ITransformableBlock.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement; - -import net.minecraft.world.level.block.state.BlockState; - -public interface ITransformableBlock { - BlockState transform(BlockState state, StructureTransform transform); -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ITransformableTE.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ITransformableTE.java deleted file mode 100644 index 64d77b497..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ITransformableTE.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement; - -public interface ITransformableTE { - - void transform(StructureTransform transform); - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MountedFluidStorage.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MountedFluidStorage.java deleted file mode 100644 index a86acebfa..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MountedFluidStorage.java +++ /dev/null @@ -1,173 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement; - -import com.simibubi.create.content.contraptions.components.structureMovement.sync.ContraptionFluidPacket; -import com.simibubi.create.content.contraptions.fluids.tank.CreativeFluidTankTileEntity; -import com.simibubi.create.content.contraptions.fluids.tank.CreativeFluidTankTileEntity.CreativeSmartFluidTank; -import com.simibubi.create.content.contraptions.fluids.tank.FluidTankTileEntity; -import com.simibubi.create.foundation.fluid.SmartFluidTank; -import com.simibubi.create.foundation.networking.AllPackets; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; - -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.IFluidTank; -import net.minecraftforge.fluids.capability.CapabilityFluidHandler; -import net.minecraftforge.fluids.capability.IFluidHandler; -import net.minecraftforge.network.PacketDistributor; - -public class MountedFluidStorage { - - SmartFluidTank tank; - private boolean valid; - private BlockEntity te; - - private int packetCooldown = 0; - private boolean sendPacket = false; - - public static boolean canUseAsStorage(BlockEntity te) { - if (te instanceof FluidTankTileEntity) - return ((FluidTankTileEntity) te).isController(); - return false; - } - - public MountedFluidStorage(BlockEntity te) { - assignTileEntity(te); - } - - public void assignTileEntity(BlockEntity te) { - this.te = te; - tank = createMountedTank(te); - } - - private SmartFluidTank createMountedTank(BlockEntity te) { - if (te instanceof CreativeFluidTankTileEntity) - return new CreativeSmartFluidTank( - ((FluidTankTileEntity) te).getTotalTankSize() * FluidTankTileEntity.getCapacityMultiplier(), $ -> { - }); - if (te instanceof FluidTankTileEntity) - return new SmartFluidTank( - ((FluidTankTileEntity) te).getTotalTankSize() * FluidTankTileEntity.getCapacityMultiplier(), - this::onFluidStackChanged); - return null; - } - - public void tick(Entity entity, BlockPos pos, boolean isRemote) { - if (!isRemote) { - if (packetCooldown > 0) - packetCooldown--; - else if (sendPacket) { - sendPacket = false; - AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> entity), - new ContraptionFluidPacket(entity.getId(), pos, tank.getFluid())); - packetCooldown = 8; - } - return; - } - - if (!(te instanceof FluidTankTileEntity)) - return; - FluidTankTileEntity tank = (FluidTankTileEntity) te; - tank.getFluidLevel() - .tickChaser(); - } - - public void updateFluid(FluidStack fluid) { - tank.setFluid(fluid); - if (!(te instanceof FluidTankTileEntity)) - return; - float fillState = tank.getFluidAmount() / (float) tank.getCapacity(); - FluidTankTileEntity tank = (FluidTankTileEntity) te; - if (tank.getFluidLevel() == null) - tank.setFluidLevel(LerpedFloat.linear() - .startWithValue(fillState)); - tank.getFluidLevel() - .chase(fillState, 0.5, Chaser.EXP); - IFluidTank tankInventory = tank.getTankInventory(); - if (tankInventory instanceof SmartFluidTank) - ((SmartFluidTank) tankInventory).setFluid(fluid); - } - - public void removeStorageFromWorld() { - valid = false; - if (te == null) - return; - - IFluidHandler teHandler = te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) - .orElse(null); - if (!(teHandler instanceof SmartFluidTank)) - return; - SmartFluidTank smartTank = (SmartFluidTank) teHandler; - tank.setFluid(smartTank.getFluid()); - sendPacket = false; - valid = true; - } - - private void onFluidStackChanged(FluidStack fs) { - sendPacket = true; - } - - public void addStorageToWorld(BlockEntity te) { - if (tank instanceof CreativeSmartFluidTank) - return; - - LazyOptional capability = te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY); - IFluidHandler teHandler = capability.orElse(null); - if (!(teHandler instanceof SmartFluidTank)) - return; - - SmartFluidTank inv = (SmartFluidTank) teHandler; - inv.setFluid(tank.getFluid() - .copy()); - } - - public IFluidHandler getFluidHandler() { - return tank; - } - - public CompoundTag serialize() { - if (!valid) - return null; - CompoundTag tag = tank.writeToNBT(new CompoundTag()); - tag.putInt("Capacity", tank.getCapacity()); - - if (tank instanceof CreativeSmartFluidTank) { - NBTHelper.putMarker(tag, "Bottomless"); - tag.put("ProvidedStack", tank.getFluid() - .writeToNBT(new CompoundTag())); - } - return tag; - } - - public static MountedFluidStorage deserialize(CompoundTag nbt) { - MountedFluidStorage storage = new MountedFluidStorage(null); - if (nbt == null) - return storage; - - int capacity = nbt.getInt("Capacity"); - storage.tank = new SmartFluidTank(capacity, storage::onFluidStackChanged); - storage.valid = true; - - if (nbt.contains("Bottomless")) { - FluidStack providedStack = FluidStack.loadFluidStackFromNBT(nbt.getCompound("ProvidedStack")); - CreativeSmartFluidTank creativeSmartFluidTank = new CreativeSmartFluidTank(capacity, $ -> { - }); - creativeSmartFluidTank.setContainedFluid(providedStack); - storage.tank = creativeSmartFluidTank; - return storage; - } - - storage.tank.readFromNBT(nbt); - return storage; - } - - public boolean isValid() { - return valid; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MountedStorage.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MountedStorage.java deleted file mode 100644 index f9d8f2813..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MountedStorage.java +++ /dev/null @@ -1,190 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement; - -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.components.crafter.MechanicalCrafterTileEntity; -import com.simibubi.create.content.contraptions.processing.ProcessingInventory; -import com.simibubi.create.content.logistics.block.inventories.BottomlessItemHandler; -import com.simibubi.create.content.logistics.block.vault.ItemVaultTileEntity; -import com.simibubi.create.foundation.utility.NBTHelper; - -import net.minecraft.core.NonNullList; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.ContainerHelper; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.entity.BarrelBlockEntity; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.ChestBlockEntity; -import net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.items.CapabilityItemHandler; -import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.ItemStackHandler; - -public class MountedStorage { - - private static final ItemStackHandler dummyHandler = new ItemStackHandler(); - - ItemStackHandler handler; - boolean noFuel; - boolean valid; - - private BlockEntity te; - - public static boolean canUseAsStorage(BlockEntity te) { - if (te == null) - return false; - if (te instanceof MechanicalCrafterTileEntity) - return false; - if (AllTileEntities.CREATIVE_CRATE.is(te)) - return true; - if (te instanceof ShulkerBoxBlockEntity) - return true; - if (te instanceof ChestBlockEntity) - return true; - if (te instanceof BarrelBlockEntity) - return true; - if (te instanceof ItemVaultTileEntity) - return true; - - LazyOptional capability = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY); - IItemHandler handler = capability.orElse(null); - return handler instanceof ItemStackHandler && !(handler instanceof ProcessingInventory); - } - - public MountedStorage(BlockEntity te) { - this.te = te; - handler = dummyHandler; - noFuel = te instanceof ItemVaultTileEntity; - } - - public void removeStorageFromWorld() { - valid = false; - if (te == null) - return; - - if (te instanceof ChestBlockEntity) { - CompoundTag tag = te.saveWithFullMetadata(); - if (tag.contains("LootTable", 8)) - return; - - handler = new ItemStackHandler(((ChestBlockEntity) te).getContainerSize()); - NonNullList items = NonNullList.withSize(handler.getSlots(), ItemStack.EMPTY); - ContainerHelper.loadAllItems(tag, items); - for (int i = 0; i < items.size(); i++) - handler.setStackInSlot(i, items.get(i)); - valid = true; - return; - } - - IItemHandler teHandler = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) - .orElse(dummyHandler); - if (teHandler == dummyHandler) - return; - - // multiblock vaults need to provide individual invs - if (te instanceof ItemVaultTileEntity) { - handler = ((ItemVaultTileEntity) te).getInventoryOfBlock(); - valid = true; - return; - } - - // te uses ItemStackHandler - if (teHandler instanceof ItemStackHandler) { - handler = (ItemStackHandler) teHandler; - valid = true; - return; - } - - // serialization not accessible -> fill into a serializable handler - if (teHandler instanceof IItemHandlerModifiable) { - IItemHandlerModifiable inv = (IItemHandlerModifiable) teHandler; - handler = new ItemStackHandler(teHandler.getSlots()); - for (int slot = 0; slot < handler.getSlots(); slot++) { - handler.setStackInSlot(slot, inv.getStackInSlot(slot)); - inv.setStackInSlot(slot, ItemStack.EMPTY); - } - valid = true; - return; - } - - } - - public void addStorageToWorld(BlockEntity te) { - // FIXME: More dynamic mounted storage in .4 - if (handler instanceof BottomlessItemHandler) - return; - - if (te instanceof ChestBlockEntity) { - CompoundTag tag = te.saveWithFullMetadata(); - tag.remove("Items"); - NonNullList items = NonNullList.withSize(handler.getSlots(), ItemStack.EMPTY); - for (int i = 0; i < items.size(); i++) - items.set(i, handler.getStackInSlot(i)); - ContainerHelper.saveAllItems(tag, items); - te.load(tag); - return; - } - - if (te instanceof ItemVaultTileEntity) { - ((ItemVaultTileEntity) te).applyInventoryToBlock(handler); - return; - } - - LazyOptional capability = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY); - IItemHandler teHandler = capability.orElse(null); - if (!(teHandler instanceof IItemHandlerModifiable)) - return; - - IItemHandlerModifiable inv = (IItemHandlerModifiable) teHandler; - for (int slot = 0; slot < Math.min(inv.getSlots(), handler.getSlots()); slot++) - inv.setStackInSlot(slot, handler.getStackInSlot(slot)); - } - - public IItemHandlerModifiable getItemHandler() { - return handler; - } - - public CompoundTag serialize() { - if (!valid) - return null; - - CompoundTag tag = handler.serializeNBT(); - if (noFuel) - NBTHelper.putMarker(tag, "NoFuel"); - if (!(handler instanceof BottomlessItemHandler)) - return tag; - - NBTHelper.putMarker(tag, "Bottomless"); - tag.put("ProvidedStack", handler.getStackInSlot(0) - .serializeNBT()); - return tag; - } - - public static MountedStorage deserialize(CompoundTag nbt) { - MountedStorage storage = new MountedStorage(null); - storage.handler = new ItemStackHandler(); - if (nbt == null) - return storage; - storage.valid = true; - storage.noFuel = nbt.contains("NoFuel"); - - if (nbt.contains("Bottomless")) { - ItemStack providedStack = ItemStack.of(nbt.getCompound("ProvidedStack")); - storage.handler = new BottomlessItemHandler(() -> providedStack); - return storage; - } - - storage.handler.deserializeNBT(nbt); - return storage; - } - - public boolean isValid() { - return valid; - } - - public boolean canUseForFuel() { - return !noFuel; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MountedStorageManager.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MountedStorageManager.java deleted file mode 100644 index 6d7566867..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MountedStorageManager.java +++ /dev/null @@ -1,205 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import com.simibubi.create.content.contraptions.components.structureMovement.Contraption.ContraptionInvWrapper; -import com.simibubi.create.content.contraptions.fluids.tank.FluidTankTileEntity; -import com.simibubi.create.foundation.fluid.CombinedTankWrapper; -import com.simibubi.create.foundation.utility.NBTHelper; - -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.NbtUtils; -import net.minecraft.nbt.Tag; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.IFluidTank; -import net.minecraftforge.fluids.capability.IFluidHandler; -import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction; -import net.minecraftforge.fluids.capability.templates.FluidTank; -import net.minecraftforge.items.IItemHandlerModifiable; - -public class MountedStorageManager { - - protected ContraptionInvWrapper inventory; - protected ContraptionInvWrapper fuelInventory; - protected CombinedTankWrapper fluidInventory; - protected Map storage; - protected Map fluidStorage; - - public MountedStorageManager() { - storage = new HashMap<>(); - fluidStorage = new HashMap<>(); - } - - public void entityTick(AbstractContraptionEntity entity) { - fluidStorage.forEach((pos, mfs) -> mfs.tick(entity, pos, entity.level.isClientSide)); - } - - public void createHandlers() { - Collection itemHandlers = storage.values(); - - inventory = wrapItems(itemHandlers.stream() - .map(MountedStorage::getItemHandler) - .toList(), false); - - fuelInventory = wrapItems(itemHandlers.stream() - .filter(MountedStorage::canUseForFuel) - .map(MountedStorage::getItemHandler) - .toList(), true); - - fluidInventory = wrapFluids(fluidStorage.values() - .stream() - .map(MountedFluidStorage::getFluidHandler) - .collect(Collectors.toList())); - } - - protected ContraptionInvWrapper wrapItems(Collection list, boolean fuel) { - return new ContraptionInvWrapper(Arrays.copyOf(list.toArray(), list.size(), IItemHandlerModifiable[].class)); - } - - protected CombinedTankWrapper wrapFluids(Collection list) { - return new CombinedTankWrapper(Arrays.copyOf(list.toArray(), list.size(), IFluidHandler[].class)); - } - - public void addBlock(BlockPos localPos, BlockEntity te) { - if (te != null && MountedStorage.canUseAsStorage(te)) - storage.put(localPos, new MountedStorage(te)); - if (te != null && MountedFluidStorage.canUseAsStorage(te)) - fluidStorage.put(localPos, new MountedFluidStorage(te)); - } - - public void read(CompoundTag nbt, Map presentTileEntities, boolean clientPacket) { - storage.clear(); - NBTHelper.iterateCompoundList(nbt.getList("Storage", Tag.TAG_COMPOUND), c -> storage - .put(NbtUtils.readBlockPos(c.getCompound("Pos")), MountedStorage.deserialize(c.getCompound("Data")))); - - fluidStorage.clear(); - NBTHelper.iterateCompoundList(nbt.getList("FluidStorage", Tag.TAG_COMPOUND), c -> fluidStorage - .put(NbtUtils.readBlockPos(c.getCompound("Pos")), MountedFluidStorage.deserialize(c.getCompound("Data")))); - - if (clientPacket && presentTileEntities != null) - bindTanks(presentTileEntities); - - List handlers = new ArrayList<>(); - List fuelHandlers = new ArrayList<>(); - for (MountedStorage mountedStorage : storage.values()) { - IItemHandlerModifiable itemHandler = mountedStorage.getItemHandler(); - handlers.add(itemHandler); - if (mountedStorage.canUseForFuel()) - fuelHandlers.add(itemHandler); - } - - inventory = wrapItems(handlers, false); - fuelInventory = wrapItems(fuelHandlers, true); - fluidInventory = wrapFluids(fluidStorage.values() - .stream() - .map(MountedFluidStorage::getFluidHandler) - .toList()); - } - - public void bindTanks(Map presentTileEntities) { - fluidStorage.forEach((pos, mfs) -> { - BlockEntity tileEntity = presentTileEntities.get(pos); - if (!(tileEntity instanceof FluidTankTileEntity)) - return; - FluidTankTileEntity tank = (FluidTankTileEntity) tileEntity; - IFluidTank tankInventory = tank.getTankInventory(); - if (tankInventory instanceof FluidTank) - ((FluidTank) tankInventory).setFluid(mfs.tank.getFluid()); - tank.getFluidLevel() - .startWithValue(tank.getFillState()); - mfs.assignTileEntity(tank); - }); - } - - public void write(CompoundTag nbt, boolean clientPacket) { - ListTag storageNBT = new ListTag(); - if (!clientPacket) - for (BlockPos pos : storage.keySet()) { - CompoundTag c = new CompoundTag(); - MountedStorage mountedStorage = storage.get(pos); - if (!mountedStorage.isValid()) - continue; - c.put("Pos", NbtUtils.writeBlockPos(pos)); - c.put("Data", mountedStorage.serialize()); - storageNBT.add(c); - } - - ListTag fluidStorageNBT = new ListTag(); - for (BlockPos pos : fluidStorage.keySet()) { - CompoundTag c = new CompoundTag(); - MountedFluidStorage mountedStorage = fluidStorage.get(pos); - if (!mountedStorage.isValid()) - continue; - c.put("Pos", NbtUtils.writeBlockPos(pos)); - c.put("Data", mountedStorage.serialize()); - fluidStorageNBT.add(c); - } - - nbt.put("Storage", storageNBT); - nbt.put("FluidStorage", fluidStorageNBT); - } - - public void removeStorageFromWorld() { - storage.values() - .forEach(MountedStorage::removeStorageFromWorld); - fluidStorage.values() - .forEach(MountedFluidStorage::removeStorageFromWorld); - } - - public void addStorageToWorld(StructureBlockInfo block, BlockEntity tileEntity) { - if (storage.containsKey(block.pos)) { - MountedStorage mountedStorage = storage.get(block.pos); - if (mountedStorage.isValid()) - mountedStorage.addStorageToWorld(tileEntity); - } - - if (fluidStorage.containsKey(block.pos)) { - MountedFluidStorage mountedStorage = fluidStorage.get(block.pos); - if (mountedStorage.isValid()) - mountedStorage.addStorageToWorld(tileEntity); - } - } - - public void clear() { - for (int i = 0; i < inventory.getSlots(); i++) - if (!inventory.isSlotExternal(i)) - inventory.setStackInSlot(i, ItemStack.EMPTY); - for (int i = 0; i < fluidInventory.getTanks(); i++) - fluidInventory.drain(fluidInventory.getFluidInTank(i), FluidAction.EXECUTE); - } - - public void updateContainedFluid(BlockPos localPos, FluidStack containedFluid) { - MountedFluidStorage mountedFluidStorage = fluidStorage.get(localPos); - if (mountedFluidStorage != null) - mountedFluidStorage.updateFluid(containedFluid); - } - - public void attachExternal(IItemHandlerModifiable externalStorage) { - inventory = new ContraptionInvWrapper(externalStorage, inventory); - fuelInventory = new ContraptionInvWrapper(externalStorage, fuelInventory); - } - - public IItemHandlerModifiable getItems() { - return inventory; - } - - public IItemHandlerModifiable getFuelItems() { - return fuelInventory; - } - - public IFluidHandler getFluids() { - return fluidInventory; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovementBehaviour.java deleted file mode 100644 index 642e7da4f..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovementBehaviour.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement; - -import javax.annotation.Nullable; - -import com.jozufozu.flywheel.api.MaterialManager; -import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; -import com.simibubi.create.foundation.config.AllConfigs; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.core.BlockPos; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.items.ItemHandlerHelper; - -public interface MovementBehaviour { - - default boolean isActive(MovementContext context) { - return true; - } - - default void tick(MovementContext context) {} - - default void startMoving(MovementContext context) {} - - default void visitNewPosition(MovementContext context, BlockPos pos) {} - - default Vec3 getActiveAreaOffset(MovementContext context) { - return Vec3.ZERO; - } - - default void dropItem(MovementContext context, ItemStack stack) { - ItemStack remainder; - if (AllConfigs.SERVER.kinetics.moveItemsToStorage.get()) - remainder = ItemHandlerHelper.insertItem(context.contraption.getSharedInventory(), stack, false); - else - remainder = stack; - if (remainder.isEmpty()) - return; - - Vec3 vec = context.position; - ItemEntity itemEntity = new ItemEntity(context.world, vec.x, vec.y, vec.z, remainder); - itemEntity.setDeltaMovement(context.motion.add(0, 0.5f, 0) - .scale(context.world.random.nextFloat() * .3f)); - context.world.addFreshEntity(itemEntity); - } - - default void onSpeedChanged(MovementContext context, Vec3 oldMotion, Vec3 motion) {} - - default void stopMoving(MovementContext context) {} - - default void cancelStall(MovementContext context) { - context.stall = false; - } - - default void writeExtraData(MovementContext context) {} - - default boolean renderAsNormalTileEntity() { - return false; - } - - default boolean hasSpecialInstancedRendering() { - return false; - } - - @OnlyIn(Dist.CLIENT) - default void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld, - ContraptionMatrices matrices, MultiBufferSource buffer) {} - - @OnlyIn(Dist.CLIENT) - @Nullable - default ActorInstance createInstance(MaterialManager materialManager, VirtualRenderWorld simulationWorld, - MovementContext context) { - return null; - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/NonStationaryLighter.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/NonStationaryLighter.java deleted file mode 100644 index 3c66e2c60..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/NonStationaryLighter.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement; - -import com.jozufozu.flywheel.light.TickingLightListener; -import com.jozufozu.flywheel.util.box.GridAlignedBB; -import com.jozufozu.flywheel.util.box.ImmutableBox; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionLighter; -import com.simibubi.create.foundation.config.AllConfigs; - -public class NonStationaryLighter extends ContraptionLighter implements TickingLightListener { - public NonStationaryLighter(C contraption) { - super(contraption); - } - - @Override - public boolean tickLightListener() { - if (getVolume().volume() > AllConfigs.CLIENT.maxContraptionLightVolume.get()) - return false; - - ImmutableBox contraptionBounds = getContraptionBounds(); - - if (bounds.sameAs(contraptionBounds, 2)) { - return false; - } - bounds.assign(contraptionBounds); - growBoundsForEdgeData(bounds); - - lightVolume.move(bounds); - - return true; - } - - @Override - public GridAlignedBB getContraptionBounds() { - GridAlignedBB bb = GridAlignedBB.from(contraption.bounds); - - bb.translate(contraption.entity.blockPosition()); - - return bb; - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/TranslatingContraption.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/TranslatingContraption.java deleted file mode 100644 index b3a2c616c..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/TranslatingContraption.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; - -public abstract class TranslatingContraption extends Contraption { - - protected Set cachedColliders; - protected Direction cachedColliderDirection; - - public Set getColliders(Level world, Direction movementDirection) { - if (getBlocks() == null) - return Collections.emptySet(); - if (cachedColliders == null || cachedColliderDirection != movementDirection) { - cachedColliders = new HashSet<>(); - cachedColliderDirection = movementDirection; - - for (StructureBlockInfo info : getBlocks().values()) { - BlockPos offsetPos = info.pos.relative(movementDirection); - if (info.state.getCollisionShape(world, offsetPos) - .isEmpty()) - continue; - if (getBlocks().containsKey(offsetPos) - && !getBlocks().get(offsetPos).state.getCollisionShape(world, offsetPos) - .isEmpty()) - continue; - cachedColliders.add(info.pos); - } - - } - return cachedColliders; - } - - @Override - public void removeBlocksFromWorld(Level world, BlockPos offset) { - int count = blocks.size(); - super.removeBlocksFromWorld(world, offset); - if (count != blocks.size()) { - cachedColliders = null; - } - } - - @Override - public boolean canBeStabilized(Direction facing, BlockPos localPos) { - return false; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/AnchoredLighter.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/AnchoredLighter.java deleted file mode 100644 index e195ae9b3..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/AnchoredLighter.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.bearing; - -import com.jozufozu.flywheel.util.box.GridAlignedBB; -import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionLighter; - -public class AnchoredLighter extends ContraptionLighter { - - public AnchoredLighter(Contraption contraption) { - super(contraption); - } - - @Override - public GridAlignedBB getContraptionBounds() { - GridAlignedBB bb = GridAlignedBB.from(contraption.bounds); - bb.translate(contraption.anchor); - return bb; - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingContraption.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingContraption.java deleted file mode 100644 index 788b111b7..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingContraption.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.bearing; - -import org.apache.commons.lang3.tuple.Pair; - -import com.simibubi.create.AllTags.AllBlockTags; -import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException; -import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; -import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionLighter; -import com.simibubi.create.foundation.config.AllConfigs; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -public class BearingContraption extends Contraption { - - protected int sailBlocks; - protected Direction facing; - - private boolean isWindmill; - - public BearingContraption() {} - - public BearingContraption(boolean isWindmill, Direction facing) { - this.isWindmill = isWindmill; - this.facing = facing; - } - - @Override - public boolean assemble(Level world, BlockPos pos) throws AssemblyException { - BlockPos offset = pos.relative(facing); - if (!searchMovedStructure(world, offset, null)) - return false; - startMoving(world); - expandBoundsAroundAxis(facing.getAxis()); - if (isWindmill && sailBlocks < AllConfigs.SERVER.kinetics.minimumWindmillSails.get()) - throw AssemblyException.notEnoughSails(sailBlocks); - if (blocks.isEmpty()) - return false; - return true; - } - - @Override - protected ContraptionType getType() { - return ContraptionType.BEARING; - } - - @Override - protected boolean isAnchoringBlockAt(BlockPos pos) { - return pos.equals(anchor.relative(facing.getOpposite())); - } - - @Override - public void addBlock(BlockPos pos, Pair capture) { - BlockPos localPos = pos.subtract(anchor); - if (!getBlocks().containsKey(localPos) && AllBlockTags.WINDMILL_SAILS.matches(capture.getKey().state)) - sailBlocks++; - super.addBlock(pos, capture); - } - - @Override - public CompoundTag writeNBT(boolean spawnPacket) { - CompoundTag tag = super.writeNBT(spawnPacket); - tag.putInt("Sails", sailBlocks); - tag.putInt("Facing", facing.get3DDataValue()); - return tag; - } - - @Override - public void readNBT(Level world, CompoundTag tag, boolean spawnData) { - sailBlocks = tag.getInt("Sails"); - facing = Direction.from3DDataValue(tag.getInt("Facing")); - super.readNBT(world, tag, spawnData); - } - - public int getSailBlocks() { - return sailBlocks; - } - - public Direction getFacing() { - return facing; - } - - @Override - public boolean canBeStabilized(Direction facing, BlockPos localPos) { - if (facing.getOpposite() == this.facing && BlockPos.ZERO.equals(localPos)) - return false; - return facing.getAxis() == this.facing.getAxis(); - } - - @OnlyIn(Dist.CLIENT) - @Override - public ContraptionLighter makeLighter() { - return new AnchoredLighter(this); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingInstance.java deleted file mode 100644 index e7ea2ede5..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingInstance.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.bearing; - -import org.joml.Quaternionf; - -import com.jozufozu.flywheel.api.MaterialManager; -import com.jozufozu.flywheel.api.instance.DynamicInstance; -import com.jozufozu.flywheel.core.PartialModel; -import com.jozufozu.flywheel.core.materials.oriented.OrientedData; -import com.mojang.math.Axis; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.BackHalfShaftInstance; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; - -import net.minecraft.core.Direction; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; - -public class BearingInstance extends BackHalfShaftInstance implements DynamicInstance { - final B bearing; - - final OrientedData topInstance; - - final Axis rotationAxis; - final Quaternionf blockOrientation; - - public BearingInstance(MaterialManager modelManager, B tile) { - super(modelManager, tile); - this.bearing = tile; - - Direction facing = blockState.getValue(BlockStateProperties.FACING); - rotationAxis = Axis.of(Direction.get(Direction.AxisDirection.POSITIVE, axis).step()); - - blockOrientation = getBlockStateOrientation(facing); - - PartialModel top = - bearing.isWoodenTop() ? AllBlockPartials.BEARING_TOP_WOODEN : AllBlockPartials.BEARING_TOP; - - topInstance = getOrientedMaterial().getModel(top, blockState).createInstance(); - - topInstance.setPosition(getInstancePosition()).setRotation(blockOrientation); - } - - @Override - public void beginFrame() { - - float interpolatedAngle = bearing.getInterpolatedAngle(AnimationTickHolder.getPartialTicks() - 1); - Quaternionf rot = rotationAxis.rotationDegrees(interpolatedAngle); - - rot.mul(blockOrientation); - - topInstance.setRotation(rot); - } - - @Override - public void updateLight() { - super.updateLight(); - relight(pos, topInstance); - } - - @Override - public void remove() { - super.remove(); - topInstance.delete(); - } - - static Quaternionf getBlockStateOrientation(Direction facing) { - Quaternionf orientation; - - if (facing.getAxis().isHorizontal()) { - orientation = Axis.YP.rotationDegrees(AngleHelper.horizontalAngle(facing.getOpposite())); - } else { - orientation = new Quaternionf(); - } - - orientation.mul(Axis.XP.rotationDegrees(-90 - AngleHelper.verticalAngle(facing))); - return orientation; - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingRenderer.java deleted file mode 100644 index 659152cce..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingRenderer.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.bearing; - -import com.jozufozu.flywheel.backend.Backend; -import com.jozufozu.flywheel.core.PartialModel; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.Direction; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; - -public class BearingRenderer extends KineticTileEntityRenderer { - - public BearingRenderer(BlockEntityRendererProvider.Context context) { - super(context); - } - - @Override - protected void renderSafe(KineticTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - - if (Backend.canUseInstancing(te.getLevel())) return; - - super.renderSafe(te, partialTicks, ms, buffer, light, overlay); - - IBearingTileEntity bearingTe = (IBearingTileEntity) te; - final Direction facing = te.getBlockState() - .getValue(BlockStateProperties.FACING); - PartialModel top = - bearingTe.isWoodenTop() ? AllBlockPartials.BEARING_TOP_WOODEN : AllBlockPartials.BEARING_TOP; - SuperByteBuffer superBuffer = CachedBufferer.partial(top, te.getBlockState()); - - float interpolatedAngle = bearingTe.getInterpolatedAngle(partialTicks - 1); - kineticRotationTransform(superBuffer, te, facing.getAxis(), (float) (interpolatedAngle / 180 * Math.PI), light); - - if (facing.getAxis() - .isHorizontal()) - superBuffer.rotateCentered(Direction.UP, - AngleHelper.rad(AngleHelper.horizontalAngle(facing.getOpposite()))); - superBuffer.rotateCentered(Direction.EAST, AngleHelper.rad(-90 - AngleHelper.verticalAngle(facing))); - superBuffer.renderInto(ms, buffer.getBuffer(RenderType.solid())); - } - - @Override - protected SuperByteBuffer getRotatedModel(KineticTileEntity te, BlockState state) { - return CachedBufferer.partialFacing(AllBlockPartials.SHAFT_HALF, state, state - .getValue(BearingBlock.FACING) - .getOpposite()); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/ClockworkBearingBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/ClockworkBearingBlock.java deleted file mode 100644 index 0b59b1f71..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/ClockworkBearingBlock.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.bearing; - -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.foundation.block.ITE; - -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.item.context.UseOnContext; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.BlockHitResult; - -public class ClockworkBearingBlock extends BearingBlock implements ITE { - - public ClockworkBearingBlock(Properties properties) { - super(properties); - } - - @Override - public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, - Player player, InteractionHand handIn, BlockHitResult hit) { - if (!player.mayBuild()) - return InteractionResult.FAIL; - if (player.isShiftKeyDown()) - return InteractionResult.FAIL; - if (player.getItemInHand(handIn).isEmpty()) { - if (!worldIn.isClientSide) { - withTileEntityDo(worldIn, pos, te -> { - if (te.running) { - te.disassemble(); - return; - } - te.assembleNextTick = true; - }); - } - return InteractionResult.SUCCESS; - } - return InteractionResult.PASS; - } - - @Override - public Class getTileEntityClass() { - return ClockworkBearingTileEntity.class; - } - - @Override - public InteractionResult onWrenched(BlockState state, UseOnContext context) { - InteractionResult resultType = super.onWrenched(state, context); - if (!context.getLevel().isClientSide && resultType.consumesAction()) - withTileEntityDo(context.getLevel(), context.getClickedPos(), ClockworkBearingTileEntity::disassemble); - return resultType; - } - - @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.CLOCKWORK_BEARING.get(); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/ClockworkBearingTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/ClockworkBearingTileEntity.java deleted file mode 100644 index 424020c75..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/ClockworkBearingTileEntity.java +++ /dev/null @@ -1,432 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.bearing; - -import java.util.List; - -import org.apache.commons.lang3.tuple.Pair; - -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException; -import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.IDisplayAssemblyExceptions; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.ClockworkContraption.HandType; -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.INamedIconOptions; -import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollOptionBehaviour; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.ServerSpeedProvider; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.util.Mth; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; - -public class ClockworkBearingTileEntity extends KineticTileEntity - implements IBearingTileEntity, IDisplayAssemblyExceptions { - - protected ControlledContraptionEntity hourHand; - protected ControlledContraptionEntity minuteHand; - protected float hourAngle; - protected float minuteAngle; - protected float clientHourAngleDiff; - protected float clientMinuteAngleDiff; - - protected boolean running; - protected boolean assembleNextTick; - protected AssemblyException lastException; - protected ScrollOptionBehaviour operationMode; - - private float prevForcedAngle; - - public ClockworkBearingTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - setLazyTickRate(3); - } - - @Override - public void addBehaviours(List behaviours) { - super.addBehaviours(behaviours); - operationMode = new ScrollOptionBehaviour<>(ClockHands.class, - Lang.translateDirect("contraptions.clockwork.clock_hands"), this, getMovementModeSlot()); - operationMode.requiresWrench(); - behaviours.add(operationMode); - registerAwardables(behaviours, AllAdvancements.CLOCKWORK_BEARING); - } - - @Override - public boolean isWoodenTop() { - return false; - } - - @Override - public void tick() { - super.tick(); - - if (level.isClientSide) { - prevForcedAngle = hourAngle; - clientMinuteAngleDiff /= 2; - clientHourAngleDiff /= 2; - } - - if (!level.isClientSide && assembleNextTick) { - assembleNextTick = false; - if (running) { - boolean canDisassemble = true; - if (speed == 0 && (canDisassemble || hourHand == null || hourHand.getContraption() - .getBlocks() - .isEmpty())) { - if (hourHand != null) - hourHand.getContraption() - .stop(level); - if (minuteHand != null) - minuteHand.getContraption() - .stop(level); - disassemble(); - } - return; - } else - assemble(); - return; - } - - if (!running) - return; - - if (!(hourHand != null && hourHand.isStalled())) { - float newAngle = hourAngle + getHourArmSpeed(); - hourAngle = (float) (newAngle % 360); - } - - if (!(minuteHand != null && minuteHand.isStalled())) { - float newAngle = minuteAngle + getMinuteArmSpeed(); - minuteAngle = (float) (newAngle % 360); - } - - applyRotations(); - } - - @Override - public AssemblyException getLastAssemblyException() { - return lastException; - } - - protected void applyRotations() { - BlockState blockState = getBlockState(); - Axis axis = Axis.X; - - if (blockState.hasProperty(BlockStateProperties.FACING)) - axis = blockState.getValue(BlockStateProperties.FACING) - .getAxis(); - - if (hourHand != null) { - hourHand.setAngle(hourAngle); - hourHand.setRotationAxis(axis); - } - if (minuteHand != null) { - minuteHand.setAngle(minuteAngle); - minuteHand.setRotationAxis(axis); - } - } - - @Override - public void lazyTick() { - super.lazyTick(); - if (hourHand != null && !level.isClientSide) - sendData(); - } - - public float getHourArmSpeed() { - float speed = getAngularSpeed() / 2f; - - if (speed != 0) { - ClockHands mode = ClockHands.values()[operationMode.getValue()]; - float hourTarget = mode == ClockHands.HOUR_FIRST ? getHourTarget(false) - : mode == ClockHands.MINUTE_FIRST ? getMinuteTarget() : getHourTarget(true); - float shortestAngleDiff = AngleHelper.getShortestAngleDiff(hourAngle, hourTarget); - if (shortestAngleDiff < 0) { - speed = Math.max(speed, shortestAngleDiff); - } else { - speed = Math.min(-speed, shortestAngleDiff); - } - } - - return speed + clientHourAngleDiff / 3f; - } - - public float getMinuteArmSpeed() { - float speed = getAngularSpeed(); - - if (speed != 0) { - ClockHands mode = ClockHands.values()[operationMode.getValue()]; - float minuteTarget = mode == ClockHands.MINUTE_FIRST ? getHourTarget(false) : getMinuteTarget(); - float shortestAngleDiff = AngleHelper.getShortestAngleDiff(minuteAngle, minuteTarget); - if (shortestAngleDiff < 0) { - speed = Math.max(speed, shortestAngleDiff); - } else { - speed = Math.min(-speed, shortestAngleDiff); - } - } - - return speed + clientMinuteAngleDiff / 3f; - } - - protected float getHourTarget(boolean cycle24) { - boolean isNatural = level.dimensionType() - .natural(); - int dayTime = (int) ((level.getDayTime() * (isNatural ? 1 : 24)) % 24000); - int hours = (dayTime / 1000 + 6) % 24; - int offset = getBlockState().getValue(ClockworkBearingBlock.FACING) - .getAxisDirection() - .getStep(); - float hourTarget = (float) (offset * -360 / (cycle24 ? 24f : 12f) * (hours % (cycle24 ? 24 : 12))); - return hourTarget; - } - - protected float getMinuteTarget() { - boolean isNatural = level.dimensionType() - .natural(); - int dayTime = (int) ((level.getDayTime() * (isNatural ? 1 : 24)) % 24000); - int minutes = (dayTime % 1000) * 60 / 1000; - int offset = getBlockState().getValue(ClockworkBearingBlock.FACING) - .getAxisDirection() - .getStep(); - float minuteTarget = (float) (offset * -360 / 60f * (minutes)); - return minuteTarget; - } - - public float getAngularSpeed() { - float speed = -Math.abs(getSpeed() * 3 / 10f); - if (level.isClientSide) - speed *= ServerSpeedProvider.get(); - return speed; - } - - public void assemble() { - if (!(level.getBlockState(worldPosition) - .getBlock() instanceof ClockworkBearingBlock)) - return; - - Direction direction = getBlockState().getValue(BlockStateProperties.FACING); - - // Collect Construct - Pair contraption; - try { - contraption = ClockworkContraption.assembleClockworkAt(level, worldPosition, direction); - lastException = null; - } catch (AssemblyException e) { - lastException = e; - sendData(); - return; - } - if (contraption == null) - return; - if (contraption.getLeft() == null) - return; - if (contraption.getLeft() - .getBlocks() - .isEmpty()) - return; - BlockPos anchor = worldPosition.relative(direction); - - contraption.getLeft() - .removeBlocksFromWorld(level, BlockPos.ZERO); - hourHand = ControlledContraptionEntity.create(level, this, contraption.getLeft()); - hourHand.setPos(anchor.getX(), anchor.getY(), anchor.getZ()); - hourHand.setRotationAxis(direction.getAxis()); - level.addFreshEntity(hourHand); - - if (contraption.getLeft() - .containsBlockBreakers()) - award(AllAdvancements.CONTRAPTION_ACTORS); - - if (contraption.getRight() != null) { - anchor = worldPosition.relative(direction, contraption.getRight().offset + 1); - contraption.getRight() - .removeBlocksFromWorld(level, BlockPos.ZERO); - minuteHand = ControlledContraptionEntity.create(level, this, contraption.getRight()); - minuteHand.setPos(anchor.getX(), anchor.getY(), anchor.getZ()); - minuteHand.setRotationAxis(direction.getAxis()); - level.addFreshEntity(minuteHand); - - if (contraption.getRight() - .containsBlockBreakers()) - award(AllAdvancements.CONTRAPTION_ACTORS); - } - - award(AllAdvancements.CLOCKWORK_BEARING); - - // Run - running = true; - hourAngle = 0; - minuteAngle = 0; - sendData(); - } - - public void disassemble() { - if (!running && hourHand == null && minuteHand == null) - return; - - hourAngle = 0; - minuteAngle = 0; - applyRotations(); - - if (hourHand != null) { - hourHand.disassemble(); - } - if (minuteHand != null) - minuteHand.disassemble(); - - hourHand = null; - minuteHand = null; - running = false; - sendData(); - } - - @Override - public void attach(ControlledContraptionEntity contraption) { - if (!(contraption.getContraption() instanceof ClockworkContraption)) - return; - - ClockworkContraption cc = (ClockworkContraption) contraption.getContraption(); - setChanged(); - Direction facing = getBlockState().getValue(BlockStateProperties.FACING); - BlockPos anchor = worldPosition.relative(facing, cc.offset + 1); - if (cc.handType == HandType.HOUR) { - this.hourHand = contraption; - hourHand.setPos(anchor.getX(), anchor.getY(), anchor.getZ()); - } else { - this.minuteHand = contraption; - minuteHand.setPos(anchor.getX(), anchor.getY(), anchor.getZ()); - } - if (!level.isClientSide) { - this.running = true; - sendData(); - } - } - - @Override - public void write(CompoundTag compound, boolean clientPacket) { - compound.putBoolean("Running", running); - compound.putFloat("HourAngle", hourAngle); - compound.putFloat("MinuteAngle", minuteAngle); - AssemblyException.write(compound, lastException); - super.write(compound, clientPacket); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - float hourAngleBefore = hourAngle; - float minuteAngleBefore = minuteAngle; - - running = compound.getBoolean("Running"); - hourAngle = compound.getFloat("HourAngle"); - minuteAngle = compound.getFloat("MinuteAngle"); - lastException = AssemblyException.read(compound); - super.read(compound, clientPacket); - - if (!clientPacket) - return; - - if (running) { - clientHourAngleDiff = AngleHelper.getShortestAngleDiff(hourAngleBefore, hourAngle); - clientMinuteAngleDiff = AngleHelper.getShortestAngleDiff(minuteAngleBefore, minuteAngle); - hourAngle = hourAngleBefore; - minuteAngle = minuteAngleBefore; - } else { - hourHand = null; - minuteHand = null; - } - } - - @Override - public void onSpeedChanged(float prevSpeed) { - super.onSpeedChanged(prevSpeed); - assembleNextTick = true; - } - - @Override - public boolean isValid() { - return !isRemoved(); - } - - @Override - public float getInterpolatedAngle(float partialTicks) { - if (isVirtual()) - return Mth.lerp(partialTicks, prevForcedAngle, hourAngle); - if (hourHand == null || hourHand.isStalled()) - partialTicks = 0; - return Mth.lerp(partialTicks, hourAngle, hourAngle + getHourArmSpeed()); - } - - @Override - public void onStall() { - if (!level.isClientSide) - sendData(); - } - - @Override - public void remove() { - if (!level.isClientSide) - disassemble(); - super.remove(); - } - - @Override - public boolean isAttachedTo(AbstractContraptionEntity contraption) { - if (!(contraption.getContraption() instanceof ClockworkContraption)) - return false; - ClockworkContraption cc = (ClockworkContraption) contraption.getContraption(); - if (cc.handType == HandType.HOUR) - return this.hourHand == contraption; - else - return this.minuteHand == contraption; - } - - public boolean isRunning() { - return running; - } - - static enum ClockHands implements INamedIconOptions { - - HOUR_FIRST(AllIcons.I_HOUR_HAND_FIRST), - MINUTE_FIRST(AllIcons.I_MINUTE_HAND_FIRST), - HOUR_FIRST_24(AllIcons.I_HOUR_HAND_FIRST_24), - - ; - - private String translationKey; - private AllIcons icon; - - private ClockHands(AllIcons icon) { - this.icon = icon; - translationKey = "contraptions.clockwork." + Lang.asId(name()); - } - - @Override - public AllIcons getIcon() { - return icon; - } - - @Override - public String getTranslationKey() { - return translationKey; - } - - } - - @Override - public BlockPos getBlockPosition() { - return worldPosition; - } - - public void setAngle(float forcedAngle) { - hourAngle = forcedAngle; - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/IBearingTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/IBearingTileEntity.java deleted file mode 100644 index 8d7b04e16..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/IBearingTileEntity.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.bearing; - -import com.simibubi.create.content.contraptions.components.structureMovement.DirectionalExtenderScrollOptionSlot; -import com.simibubi.create.content.contraptions.components.structureMovement.IControlContraption; -import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform; - -import net.minecraft.core.Direction.Axis; - -public interface IBearingTileEntity extends IControlContraption { - - float getInterpolatedAngle(float partialTicks); - - boolean isWoodenTop(); - - default ValueBoxTransform getMovementModeSlot() { - return new DirectionalExtenderScrollOptionSlot((state, d) -> { - Axis axis = d.getAxis(); - Axis bearingAxis = state.getValue(BearingBlock.FACING) - .getAxis(); - return bearingAxis != axis; - }); - } - - void setAngle(float forcedAngle); - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/MechanicalBearingBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/MechanicalBearingBlock.java deleted file mode 100644 index 702b54bac..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/MechanicalBearingBlock.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.bearing; - -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.foundation.block.ITE; - -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.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.BlockHitResult; - -public class MechanicalBearingBlock extends BearingBlock implements ITE { - - public MechanicalBearingBlock(Properties properties) { - super(properties); - } - - @Override - public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, - BlockHitResult hit) { - if (!player.mayBuild()) - return InteractionResult.FAIL; - if (player.isShiftKeyDown()) - return InteractionResult.FAIL; - if (player.getItemInHand(handIn) - .isEmpty()) { - if (worldIn.isClientSide) - return InteractionResult.SUCCESS; - withTileEntityDo(worldIn, pos, te -> { - if (te.running) { - te.disassemble(); - return; - } - te.assembleNextTick = true; - }); - return InteractionResult.SUCCESS; - } - return InteractionResult.PASS; - } - - @Override - public Class getTileEntityClass() { - return MechanicalBearingTileEntity.class; - } - - @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.MECHANICAL_BEARING.get(); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/MechanicalBearingTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/MechanicalBearingTileEntity.java deleted file mode 100644 index 716912d1e..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/MechanicalBearingTileEntity.java +++ /dev/null @@ -1,329 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.bearing; - -import java.util.List; - -import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.content.contraptions.base.GeneratingKineticTileEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException; -import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.IDisplayAssemblyExceptions; -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.item.TooltipHelper; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollOptionBehaviour; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.ServerSpeedProvider; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.util.Mth; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; - -public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity - implements IBearingTileEntity, IDisplayAssemblyExceptions { - - protected ScrollOptionBehaviour movementMode; - protected ControlledContraptionEntity movedContraption; - protected float angle; - protected boolean running; - protected boolean assembleNextTick; - protected float clientAngleDiff; - protected AssemblyException lastException; - - private float prevAngle; - - public MechanicalBearingTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - setLazyTickRate(3); - } - - @Override - public boolean isWoodenTop() { - return false; - } - - @Override - public void addBehaviours(List behaviours) { - super.addBehaviours(behaviours); - movementMode = new ScrollOptionBehaviour<>(RotationMode.class, Lang.translateDirect("contraptions.movement_mode"), - this, getMovementModeSlot()); - movementMode.requiresWrench(); - behaviours.add(movementMode); - registerAwardables(behaviours, AllAdvancements.CONTRAPTION_ACTORS); - } - - @Override - public void remove() { - if (!level.isClientSide) - disassemble(); - super.remove(); - } - - @Override - public void write(CompoundTag compound, boolean clientPacket) { - compound.putBoolean("Running", running); - compound.putFloat("Angle", angle); - AssemblyException.write(compound, lastException); - super.write(compound, clientPacket); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - if (wasMoved) { - super.read(compound, clientPacket); - return; - } - - float angleBefore = angle; - running = compound.getBoolean("Running"); - angle = compound.getFloat("Angle"); - lastException = AssemblyException.read(compound); - super.read(compound, clientPacket); - if (!clientPacket) - return; - if (running) { - if (movedContraption == null || !movedContraption.isStalled()) { - clientAngleDiff = AngleHelper.getShortestAngleDiff(angleBefore, angle); - angle = angleBefore; - } - } else - movedContraption = null; - } - - @Override - public float getInterpolatedAngle(float partialTicks) { - if (isVirtual()) - return Mth.lerp(partialTicks + .5f, prevAngle, angle); - if (movedContraption == null || movedContraption.isStalled() || !running) - partialTicks = 0; - return Mth.lerp(partialTicks, angle, angle + getAngularSpeed()); - } - - @Override - public void onSpeedChanged(float prevSpeed) { - super.onSpeedChanged(prevSpeed); - assembleNextTick = true; - - if (movedContraption != null && Math.signum(prevSpeed) != Math.signum(getSpeed()) && prevSpeed != 0) { - movedContraption.getContraption() - .stop(level); - } - } - - public float getAngularSpeed() { - float speed = convertToAngular(isWindmill() ? getGeneratedSpeed() : getSpeed()); - if (getSpeed() == 0) - speed = 0; - if (level.isClientSide) { - speed *= ServerSpeedProvider.get(); - speed += clientAngleDiff / 3f; - } - return speed; - } - - @Override - public AssemblyException getLastAssemblyException() { - return lastException; - } - - protected boolean isWindmill() { - return false; - } - - @Override - public BlockPos getBlockPosition() { - return worldPosition; - } - - public void assemble() { - if (!(level.getBlockState(worldPosition) - .getBlock() instanceof BearingBlock)) - return; - - Direction direction = getBlockState().getValue(BearingBlock.FACING); - BearingContraption contraption = new BearingContraption(isWindmill(), direction); - try { - if (!contraption.assemble(level, worldPosition)) - return; - - lastException = null; - } catch (AssemblyException e) { - lastException = e; - sendData(); - return; - } - - if (isWindmill()) - award(AllAdvancements.WINDMILL); - if (contraption.getSailBlocks() >= 16 * 8) - award(AllAdvancements.WINDMILL_MAXED); - - contraption.removeBlocksFromWorld(level, BlockPos.ZERO); - movedContraption = ControlledContraptionEntity.create(level, this, contraption); - BlockPos anchor = worldPosition.relative(direction); - movedContraption.setPos(anchor.getX(), anchor.getY(), anchor.getZ()); - movedContraption.setRotationAxis(direction.getAxis()); - level.addFreshEntity(movedContraption); - - AllSoundEvents.CONTRAPTION_ASSEMBLE.playOnServer(level, worldPosition); - - if (contraption.containsBlockBreakers()) - award(AllAdvancements.CONTRAPTION_ACTORS); - - running = true; - angle = 0; - sendData(); - updateGeneratedRotation(); - } - - public void disassemble() { - if (!running && movedContraption == null) - return; - angle = 0; - if (isWindmill()) - applyRotation(); - if (movedContraption != null) { - movedContraption.disassemble(); - AllSoundEvents.CONTRAPTION_DISASSEMBLE.playOnServer(level, worldPosition); - } - - movedContraption = null; - running = false; - updateGeneratedRotation(); - assembleNextTick = false; - sendData(); - } - - @Override - public void tick() { - super.tick(); - - prevAngle = angle; - if (level.isClientSide) - clientAngleDiff /= 2; - - if (!level.isClientSide && assembleNextTick) { - assembleNextTick = false; - if (running) { - boolean canDisassemble = movementMode.get() == RotationMode.ROTATE_PLACE - || (isNearInitialAngle() && movementMode.get() == RotationMode.ROTATE_PLACE_RETURNED); - if (speed == 0 && (canDisassemble || movedContraption == null || movedContraption.getContraption() - .getBlocks() - .isEmpty())) { - if (movedContraption != null) - movedContraption.getContraption() - .stop(level); - disassemble(); - return; - } - } else { - if (speed == 0 && !isWindmill()) - return; - assemble(); - } - } - - if (!running) - return; - - if (!(movedContraption != null && movedContraption.isStalled())) { - float angularSpeed = getAngularSpeed(); - float newAngle = angle + angularSpeed; - angle = (float) (newAngle % 360); - } - - applyRotation(); - } - - public boolean isNearInitialAngle() { - return Math.abs(angle) < 45 || Math.abs(angle) > 7 * 45; - } - - @Override - public void lazyTick() { - super.lazyTick(); - if (movedContraption != null && !level.isClientSide) - sendData(); - } - - protected void applyRotation() { - if (movedContraption == null) - return; - movedContraption.setAngle(angle); - BlockState blockState = getBlockState(); - if (blockState.hasProperty(BlockStateProperties.FACING)) - movedContraption.setRotationAxis(blockState.getValue(BlockStateProperties.FACING) - .getAxis()); - } - - @Override - public void attach(ControlledContraptionEntity contraption) { - BlockState blockState = getBlockState(); - if (!(contraption.getContraption() instanceof BearingContraption)) - return; - if (!blockState.hasProperty(BearingBlock.FACING)) - return; - - this.movedContraption = contraption; - setChanged(); - BlockPos anchor = worldPosition.relative(blockState.getValue(BearingBlock.FACING)); - movedContraption.setPos(anchor.getX(), anchor.getY(), anchor.getZ()); - if (!level.isClientSide) { - this.running = true; - sendData(); - } - } - - @Override - public void onStall() { - if (!level.isClientSide) - sendData(); - } - - @Override - public boolean isValid() { - return !isRemoved(); - } - - @Override - public boolean isAttachedTo(AbstractContraptionEntity contraption) { - return movedContraption == contraption; - } - - public boolean isRunning() { - return running; - } - - @Override - public boolean addToTooltip(List tooltip, boolean isPlayerSneaking) { - if (super.addToTooltip(tooltip, isPlayerSneaking)) - return true; - if (isPlayerSneaking) - return false; - if (!isWindmill() && getSpeed() == 0) - return false; - if (running) - return false; - BlockState state = getBlockState(); - if (!(state.getBlock() instanceof BearingBlock)) - return false; - - BlockState attachedState = level.getBlockState(worldPosition.relative(state.getValue(BearingBlock.FACING))); - if (attachedState.getMaterial() - .isReplaceable()) - return false; - TooltipHelper.addHint(tooltip, "hint.empty_bearing"); - return true; - } - - public void setAngle(float forcedAngle) { - angle = forcedAngle; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/StabilizedContraption.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/StabilizedContraption.java deleted file mode 100644 index ca4526b8d..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/StabilizedContraption.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.bearing; - -import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException; -import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; -import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType; -import com.simibubi.create.content.contraptions.components.structureMovement.NonStationaryLighter; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionLighter; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.level.Level; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -public class StabilizedContraption extends Contraption { - - private Direction facing; - - public StabilizedContraption() {} - - public StabilizedContraption(Direction facing) { - this.facing = facing; - } - - @Override - public boolean assemble(Level world, BlockPos pos) throws AssemblyException { - BlockPos offset = pos.relative(facing); - if (!searchMovedStructure(world, offset, null)) - return false; - startMoving(world); - if (blocks.isEmpty()) - return false; - return true; - } - - @Override - protected boolean isAnchoringBlockAt(BlockPos pos) { - return false; - } - - @Override - protected ContraptionType getType() { - return ContraptionType.STABILIZED; - } - - @Override - public CompoundTag writeNBT(boolean spawnPacket) { - CompoundTag tag = super.writeNBT(spawnPacket); - tag.putInt("Facing", facing.get3DDataValue()); - return tag; - } - - @Override - public void readNBT(Level world, CompoundTag tag, boolean spawnData) { - facing = Direction.from3DDataValue(tag.getInt("Facing")); - super.readNBT(world, tag, spawnData); - } - - @Override - public boolean canBeStabilized(Direction facing, BlockPos localPos) { - return false; - } - - public Direction getFacing() { - return facing; - } - - @Override - @OnlyIn(Dist.CLIENT) - public ContraptionLighter makeLighter() { - return new NonStationaryLighter<>(this); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/WindmillBearingBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/WindmillBearingBlock.java deleted file mode 100644 index a28c89f02..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/WindmillBearingBlock.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.bearing; - -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.foundation.block.ITE; -import com.simibubi.create.foundation.utility.Couple; - -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.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.BlockHitResult; - -public class WindmillBearingBlock extends BearingBlock implements ITE { - - public WindmillBearingBlock(Properties properties) { - super(properties); - } - - @Override - public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, - BlockHitResult hit) { - if (!player.mayBuild()) - return InteractionResult.FAIL; - if (player.isShiftKeyDown()) - return InteractionResult.FAIL; - if (player.getItemInHand(handIn) - .isEmpty()) { - if (worldIn.isClientSide) - return InteractionResult.SUCCESS; - withTileEntityDo(worldIn, pos, te -> { - if (te.running) { - te.disassemble(); - return; - } - te.assembleNextTick = true; - }); - return InteractionResult.SUCCESS; - } - return InteractionResult.PASS; - } - - @Override - public Class getTileEntityClass() { - return WindmillBearingTileEntity.class; - } - - @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.WINDMILL_BEARING.get(); - } - - public static Couple getSpeedRange() { - return Couple.create(1, 16); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/WindmillBearingTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/WindmillBearingTileEntity.java deleted file mode 100644 index e9c5d7079..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/WindmillBearingTileEntity.java +++ /dev/null @@ -1,149 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.bearing; - -import java.util.List; - -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.INamedIconOptions; -import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollOptionBehaviour; -import com.simibubi.create.foundation.utility.Lang; - -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.util.Mth; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; - -public class WindmillBearingTileEntity extends MechanicalBearingTileEntity { - - protected ScrollOptionBehaviour movementDirection; - protected float lastGeneratedSpeed; - - protected boolean queuedReassembly; - - public WindmillBearingTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - @Override - public void updateGeneratedRotation() { - super.updateGeneratedRotation(); - lastGeneratedSpeed = getGeneratedSpeed(); - queuedReassembly = false; - } - - @Override - public void onSpeedChanged(float prevSpeed) { - boolean cancelAssembly = assembleNextTick; - super.onSpeedChanged(prevSpeed); - assembleNextTick = cancelAssembly; - } - - @Override - public void tick() { - super.tick(); - if (level.isClientSide()) - return; - if (!queuedReassembly) - return; - queuedReassembly = false; - if (!running) - assembleNextTick = true; - } - - public void disassembleForMovement() { - if (!running) - return; - disassemble(); - queuedReassembly = true; - } - - @Override - public float getGeneratedSpeed() { - if (!running) - return 0; - if (movedContraption == null) - return lastGeneratedSpeed; - int sails = ((BearingContraption) movedContraption.getContraption()).getSailBlocks() - / AllConfigs.SERVER.kinetics.windmillSailsPerRPM.get(); - return Mth.clamp(sails, 1, 16) * getAngleSpeedDirection(); - } - - @Override - protected boolean isWindmill() { - return true; - } - - protected float getAngleSpeedDirection() { - RotationDirection rotationDirection = RotationDirection.values()[movementDirection.getValue()]; - return (rotationDirection == RotationDirection.CLOCKWISE ? 1 : -1); - } - - @Override - public void write(CompoundTag compound, boolean clientPacket) { - compound.putFloat("LastGenerated", lastGeneratedSpeed); - compound.putBoolean("QueueAssembly", queuedReassembly); - super.write(compound, clientPacket); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - if (!wasMoved) - lastGeneratedSpeed = compound.getFloat("LastGenerated"); - queuedReassembly = compound.getBoolean("QueueAssembly"); - super.read(compound, clientPacket); - } - - @Override - public void addBehaviours(List behaviours) { - super.addBehaviours(behaviours); - behaviours.remove(movementMode); - movementDirection = new ScrollOptionBehaviour<>(RotationDirection.class, - Lang.translateDirect("contraptions.windmill.rotation_direction"), this, getMovementModeSlot()); - movementDirection.requiresWrench(); - movementDirection.withCallback($ -> onDirectionChanged()); - behaviours.add(movementDirection); - registerAwardables(behaviours, AllAdvancements.WINDMILL, AllAdvancements.WINDMILL_MAXED); - } - - private void onDirectionChanged() { - if (!running) - return; - if (!level.isClientSide) - updateGeneratedRotation(); - } - - @Override - public boolean isWoodenTop() { - return true; - } - - public static enum RotationDirection implements INamedIconOptions { - - CLOCKWISE(AllIcons.I_REFRESH), COUNTER_CLOCKWISE(AllIcons.I_ROTATE_CCW), - - ; - - private String translationKey; - private AllIcons icon; - - private RotationDirection(AllIcons icon) { - this.icon = icon; - translationKey = "generic." + Lang.asId(name()); - } - - @Override - public AllIcons getIcon() { - return icon; - } - - @Override - public String getTranslationKey() { - return translationKey; - } - - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/ChassisRangeDisplay.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/ChassisRangeDisplay.java deleted file mode 100644 index 26a1ca324..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/ChassisRangeDisplay.java +++ /dev/null @@ -1,205 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.chassis; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import com.mojang.datafixers.util.Pair; -import com.simibubi.create.AllItems; -import com.simibubi.create.AllKeys; -import com.simibubi.create.AllSpecialTextures; -import com.simibubi.create.CreateClient; - -import net.minecraft.client.Minecraft; -import net.minecraft.core.BlockPos; -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.phys.BlockHitResult; -import net.minecraft.world.phys.HitResult; - -public class ChassisRangeDisplay { - - private static final int DISPLAY_TIME = 200; - private static GroupEntry lastHoveredGroup = null; - - private static class Entry { - ChassisTileEntity te; - int timer; - - public Entry(ChassisTileEntity te) { - this.te = te; - timer = DISPLAY_TIME; - CreateClient.OUTLINER.showCluster(getOutlineKey(), createSelection(te)) - .colored(0xFFFFFF) - .disableNormals() - .lineWidth(1 / 16f) - .withFaceTexture(AllSpecialTextures.HIGHLIGHT_CHECKERED); - } - - protected Object getOutlineKey() { - return Pair.of(te.getBlockPos(), 1); - } - - protected Set createSelection(ChassisTileEntity chassis) { - Set positions = new HashSet<>(); - List includedBlockPositions = chassis.getIncludedBlockPositions(null, true); - if (includedBlockPositions == null) - return Collections.emptySet(); - positions.addAll(includedBlockPositions); - return positions; - } - - } - - private static class GroupEntry extends Entry { - - List includedTEs; - - public GroupEntry(ChassisTileEntity te) { - super(te); - } - - @Override - protected Object getOutlineKey() { - return this; - } - - @Override - protected Set createSelection(ChassisTileEntity chassis) { - Set list = new HashSet<>(); - includedTEs = te.collectChassisGroup(); - if (includedTEs == null) - return list; - for (ChassisTileEntity chassisTileEntity : includedTEs) - list.addAll(super.createSelection(chassisTileEntity)); - return list; - } - - } - - static Map entries = new HashMap<>(); - static List groupEntries = new ArrayList<>(); - - public static void tick() { - Player player = Minecraft.getInstance().player; - Level world = Minecraft.getInstance().level; - boolean hasWrench = AllItems.WRENCH.isIn(player.getMainHandItem()); - - for (Iterator iterator = entries.keySet() - .iterator(); iterator.hasNext();) { - BlockPos pos = iterator.next(); - Entry entry = entries.get(pos); - if (tickEntry(entry, hasWrench)) - iterator.remove(); - CreateClient.OUTLINER.keep(entry.getOutlineKey()); - } - - for (Iterator iterator = groupEntries.iterator(); iterator.hasNext();) { - GroupEntry group = iterator.next(); - if (tickEntry(group, hasWrench)) { - iterator.remove(); - if (group == lastHoveredGroup) - lastHoveredGroup = null; - } - CreateClient.OUTLINER.keep(group.getOutlineKey()); - } - - if (!hasWrench) - return; - - HitResult over = Minecraft.getInstance().hitResult; - if (!(over instanceof BlockHitResult)) - return; - BlockHitResult ray = (BlockHitResult) over; - BlockPos pos = ray.getBlockPos(); - BlockEntity tileEntity = world.getBlockEntity(pos); - if (tileEntity == null || tileEntity.isRemoved()) - return; - if (!(tileEntity instanceof ChassisTileEntity)) - return; - - boolean ctrl = AllKeys.ctrlDown(); - ChassisTileEntity chassisTileEntity = (ChassisTileEntity) tileEntity; - - if (ctrl) { - GroupEntry existingGroupForPos = getExistingGroupForPos(pos); - if (existingGroupForPos != null) { - for (ChassisTileEntity included : existingGroupForPos.includedTEs) - entries.remove(included.getBlockPos()); - existingGroupForPos.timer = DISPLAY_TIME; - return; - } - } - - if (!entries.containsKey(pos) || ctrl) - display(chassisTileEntity); - else { - if (!ctrl) - entries.get(pos).timer = DISPLAY_TIME; - } - } - - private static boolean tickEntry(Entry entry, boolean hasWrench) { - ChassisTileEntity chassisTileEntity = entry.te; - Level teWorld = chassisTileEntity.getLevel(); - Level world = Minecraft.getInstance().level; - - if (chassisTileEntity.isRemoved() || teWorld == null || teWorld != world - || !world.isLoaded(chassisTileEntity.getBlockPos())) { - return true; - } - - if (!hasWrench && entry.timer > 20) { - entry.timer = 20; - return false; - } - - entry.timer--; - if (entry.timer == 0) - return true; - return false; - } - - public static void display(ChassisTileEntity chassis) { - - // Display a group and kill any selections of its contained chassis blocks - if (AllKeys.ctrlDown()) { - GroupEntry hoveredGroup = new GroupEntry(chassis); - - for (ChassisTileEntity included : hoveredGroup.includedTEs) - CreateClient.OUTLINER.remove(included.getBlockPos()); - - groupEntries.forEach(entry -> CreateClient.OUTLINER.remove(entry.getOutlineKey())); - groupEntries.clear(); - entries.clear(); - groupEntries.add(hoveredGroup); - return; - } - - // Display an individual chassis and kill any group selections that contained it - BlockPos pos = chassis.getBlockPos(); - GroupEntry entry = getExistingGroupForPos(pos); - if (entry != null) - CreateClient.OUTLINER.remove(entry.getOutlineKey()); - - groupEntries.clear(); - entries.clear(); - entries.put(pos, new Entry(chassis)); - - } - - private static GroupEntry getExistingGroupForPos(BlockPos pos) { - for (GroupEntry groupEntry : groupEntries) - for (ChassisTileEntity chassis : groupEntry.includedTEs) - if (pos.equals(chassis.getBlockPos())) - return groupEntry; - return null; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/ChassisTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/ChassisTileEntity.java deleted file mode 100644 index 2a552461c..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/ChassisTileEntity.java +++ /dev/null @@ -1,232 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.chassis; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Queue; -import java.util.Set; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.components.structureMovement.BlockMovementChecks; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.CenteredSideValueBoxTransform; -import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.BulkScrollValueBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueBehaviour; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Lang; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.core.Direction.AxisDirection; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.fml.DistExecutor; - -public class ChassisTileEntity extends SmartTileEntity { - - ScrollValueBehaviour range; - - public ChassisTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - @Override - public void addBehaviours(List behaviours) { - int max = AllConfigs.SERVER.kinetics.maxChassisRange.get(); - range = new BulkScrollValueBehaviour(Lang.translateDirect("generic.range"), this, new CenteredSideValueBoxTransform(), - te -> ((ChassisTileEntity) te).collectChassisGroup()); - range.requiresWrench(); - range.between(1, max); - range - .withClientCallback( - i -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> ChassisRangeDisplay.display(this))); - range.value = max / 2; - behaviours.add(range); - } - - @Override - public void initialize() { - super.initialize(); - if (getBlockState().getBlock() instanceof RadialChassisBlock) - range.setLabel(Lang.translateDirect("generic.radius")); - } - - public int getRange() { - return range.getValue(); - } - - public List getIncludedBlockPositions(Direction forcedMovement, boolean visualize) { - if (!(getBlockState().getBlock() instanceof AbstractChassisBlock)) - return Collections.emptyList(); - return isRadial() ? getIncludedBlockPositionsRadial(forcedMovement, visualize) - : getIncludedBlockPositionsLinear(forcedMovement, visualize); - } - - protected boolean isRadial() { - return level.getBlockState(worldPosition).getBlock() instanceof RadialChassisBlock; - } - - public List collectChassisGroup() { - Queue frontier = new LinkedList<>(); - List collected = new ArrayList<>(); - Set visited = new HashSet<>(); - frontier.add(worldPosition); - while (!frontier.isEmpty()) { - BlockPos current = frontier.poll(); - if (visited.contains(current)) - continue; - visited.add(current); - BlockEntity tileEntity = level.getBlockEntity(current); - if (tileEntity instanceof ChassisTileEntity) { - ChassisTileEntity chassis = (ChassisTileEntity) tileEntity; - collected.add(chassis); - visited.add(current); - chassis.addAttachedChasses(frontier, visited); - } - } - return collected; - } - - public boolean addAttachedChasses(Queue frontier, Set visited) { - BlockState state = getBlockState(); - if (!(state.getBlock() instanceof AbstractChassisBlock)) - return false; - Axis axis = state.getValue(AbstractChassisBlock.AXIS); - if (isRadial()) { - - // Collect chain of radial chassis - for (int offset : new int[] { -1, 1 }) { - Direction direction = Direction.get(AxisDirection.POSITIVE, axis); - BlockPos currentPos = worldPosition.relative(direction, offset); - if (!level.isLoaded(currentPos)) - return false; - - BlockState neighbourState = level.getBlockState(currentPos); - if (!AllBlocks.RADIAL_CHASSIS.has(neighbourState)) - continue; - if (axis != neighbourState.getValue(BlockStateProperties.AXIS)) - continue; - if (!visited.contains(currentPos)) - frontier.add(currentPos); - } - - return true; - } - - // Collect group of connected linear chassis - for (Direction offset : Iterate.directions) { - BlockPos current = worldPosition.relative(offset); - if (visited.contains(current)) - continue; - if (!level.isLoaded(current)) - return false; - - BlockState neighbourState = level.getBlockState(current); - if (!LinearChassisBlock.isChassis(neighbourState)) - continue; - if (!LinearChassisBlock.sameKind(state, neighbourState)) - continue; - if (neighbourState.getValue(LinearChassisBlock.AXIS) != axis) - continue; - - frontier.add(current); - } - - return true; - } - - private List getIncludedBlockPositionsLinear(Direction forcedMovement, boolean visualize) { - List positions = new ArrayList<>(); - BlockState state = getBlockState(); - AbstractChassisBlock block = (AbstractChassisBlock) state.getBlock(); - Axis axis = state.getValue(AbstractChassisBlock.AXIS); - Direction facing = Direction.get(AxisDirection.POSITIVE, axis); - int chassisRange = visualize ? range.scrollableValue : getRange(); - - for (int offset : new int[] { 1, -1 }) { - if (offset == -1) - facing = facing.getOpposite(); - boolean sticky = state.getValue(block.getGlueableSide(state, facing)); - for (int i = 1; i <= chassisRange; i++) { - BlockPos current = worldPosition.relative(facing, i); - BlockState currentState = level.getBlockState(current); - - if (forcedMovement != facing && !sticky) - break; - - // Ignore replaceable Blocks and Air-like - if (!BlockMovementChecks.isMovementNecessary(currentState, level, current)) - break; - if (BlockMovementChecks.isBrittle(currentState)) - break; - - positions.add(current); - - if (BlockMovementChecks.isNotSupportive(currentState, facing)) - break; - } - } - - return positions; - } - - private List getIncludedBlockPositionsRadial(Direction forcedMovement, boolean visualize) { - List positions = new ArrayList<>(); - BlockState state = level.getBlockState(worldPosition); - Axis axis = state.getValue(AbstractChassisBlock.AXIS); - AbstractChassisBlock block = (AbstractChassisBlock) state.getBlock(); - int chassisRange = visualize ? range.scrollableValue : getRange(); - - for (Direction facing : Iterate.directions) { - if (facing.getAxis() == axis) - continue; - if (!state.getValue(block.getGlueableSide(state, facing))) - continue; - - BlockPos startPos = worldPosition.relative(facing); - List localFrontier = new LinkedList<>(); - Set localVisited = new HashSet<>(); - localFrontier.add(startPos); - - while (!localFrontier.isEmpty()) { - BlockPos searchPos = localFrontier.remove(0); - BlockState searchedState = level.getBlockState(searchPos); - - if (localVisited.contains(searchPos)) - continue; - if (!searchPos.closerThan(worldPosition, chassisRange + .5f)) - continue; - if (!BlockMovementChecks.isMovementNecessary(searchedState, level, searchPos)) - continue; - if (BlockMovementChecks.isBrittle(searchedState)) - continue; - - localVisited.add(searchPos); - if (!searchPos.equals(worldPosition)) - positions.add(searchPos); - - for (Direction offset : Iterate.directions) { - if (offset.getAxis() == axis) - continue; - if (searchPos.equals(worldPosition) && offset != facing) - continue; - if (BlockMovementChecks.isNotSupportive(searchedState, offset)) - continue; - - localFrontier.add(searchPos.relative(offset)); - } - } - } - - return positions; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerRenderer.java deleted file mode 100644 index cfb6a1d0e..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerRenderer.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.chassis; - -import com.jozufozu.flywheel.backend.Backend; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.Direction; -import net.minecraft.world.level.block.state.BlockState; - -public class StickerRenderer extends SafeTileEntityRenderer { - - public StickerRenderer(BlockEntityRendererProvider.Context context) { - } - - @Override - protected void renderSafe(StickerTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - - if (Backend.canUseInstancing(te.getLevel())) return; - - BlockState state = te.getBlockState(); - SuperByteBuffer head = CachedBufferer.partial(AllBlockPartials.STICKER_HEAD, state); - float offset = te.piston.getValue(AnimationTickHolder.getPartialTicks(te.getLevel())); - - if (te.getLevel() != Minecraft.getInstance().level && !te.isVirtual()) - offset = state.getValue(StickerBlock.EXTENDED) ? 1 : 0; - - Direction facing = state.getValue(StickerBlock.FACING); - head.nudge(te.hashCode()) - .centre() - .rotateY(AngleHelper.horizontalAngle(facing)) - .rotateX(AngleHelper.verticalAngle(facing) + 90) - .unCentre() - .translate(0, (offset * offset) * 4 / 16f, 0); - - head.light(light) - .renderInto(ms, buffer.getBuffer(RenderType.solid())); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerTileEntity.java deleted file mode 100644 index 71724bf40..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerTileEntity.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.chassis; - -import java.util.List; - -import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; -import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueItem; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; - -import net.minecraft.client.Minecraft; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.fml.DistExecutor; - -public class StickerTileEntity extends SmartTileEntity { - - LerpedFloat piston; - boolean update; - - public StickerTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - piston = LerpedFloat.linear(); - update = false; - } - - @Override - public void addBehaviours(List behaviours) {} - - @Override - public void initialize() { - super.initialize(); - if (!level.isClientSide) - return; - piston.startWithValue(isBlockStateExtended() ? 1 : 0); - } - - public boolean isBlockStateExtended() { - BlockState blockState = getBlockState(); - boolean extended = AllBlocks.STICKER.has(blockState) && blockState.getValue(StickerBlock.EXTENDED); - return extended; - } - - @Override - public void tick() { - super.tick(); - if (!level.isClientSide) - return; - piston.tickChaser(); - - if (isAttachedToBlock() && piston.getValue(0) != piston.getValue() && piston.getValue() == 1) { - SuperGlueItem.spawnParticles(level, worldPosition, getBlockState().getValue(StickerBlock.FACING), true); - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> playSound(true)); - } - - if (!update) - return; - update = false; - int target = isBlockStateExtended() ? 1 : 0; - if (isAttachedToBlock() && target == 0 && piston.getChaseTarget() == 1) - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> playSound(false)); - piston.chase(target, .4f, Chaser.LINEAR); - - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(this)); - } - - public boolean isAttachedToBlock() { - BlockState blockState = getBlockState(); - if (!AllBlocks.STICKER.has(blockState)) - return false; - Direction direction = blockState.getValue(StickerBlock.FACING); - return SuperGlueEntity.isValidFace(level, worldPosition.relative(direction), direction.getOpposite()); - } - - @Override - protected void write(CompoundTag tag, boolean clientPacket) { - super.write(tag, clientPacket); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - super.read(compound, clientPacket); - if (clientPacket) - update = true; - } - - @OnlyIn(Dist.CLIENT) - public void playSound(boolean attach) { - AllSoundEvents.SLIME_ADDED.play(level, Minecraft.getInstance().player, worldPosition, 0.35f, attach ? 0.75f : 0.2f); - } - - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageRenderer.java deleted file mode 100644 index 6e3e6fd44..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageRenderer.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.gantry; - -import com.jozufozu.flywheel.backend.Backend; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.Iterate; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.core.Direction.AxisDirection; -import net.minecraft.world.level.block.state.BlockState; - -public class GantryCarriageRenderer extends KineticTileEntityRenderer { - - public GantryCarriageRenderer(BlockEntityRendererProvider.Context context) { - super(context); - } - - @Override - protected void renderSafe(KineticTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - super.renderSafe(te, partialTicks, ms, buffer, light, overlay); - - if (Backend.canUseInstancing(te.getLevel())) return; - - BlockState state = te.getBlockState(); - Direction facing = state.getValue(GantryCarriageBlock.FACING); - Boolean alongFirst = state.getValue(GantryCarriageBlock.AXIS_ALONG_FIRST_COORDINATE); - Axis rotationAxis = getRotationAxisOf(te); - BlockPos visualPos = facing.getAxisDirection() == AxisDirection.POSITIVE ? te.getBlockPos() - : te.getBlockPos() - .relative(facing.getOpposite()); - float angleForTe = getAngleForTe(te, visualPos, rotationAxis); - - Axis gantryAxis = Axis.X; - for (Axis axis : Iterate.axes) - if (axis != rotationAxis && axis != facing.getAxis()) - gantryAxis = axis; - - if (gantryAxis == Axis.X) - if (facing == Direction.UP) - angleForTe *= -1; - if (gantryAxis == Axis.Y) - if (facing == Direction.NORTH || facing == Direction.EAST) - angleForTe *= -1; - - SuperByteBuffer cogs = CachedBufferer.partial(AllBlockPartials.GANTRY_COGS, state); - cogs.centre() - .rotateY(AngleHelper.horizontalAngle(facing)) - .rotateX(facing == Direction.UP ? 0 : facing == Direction.DOWN ? 180 : 90) - .rotateY(alongFirst ^ facing.getAxis() == Axis.X ? 0 : 90) - .translate(0, -9 / 16f, 0) - .rotateX(-angleForTe) - .translate(0, 9 / 16f, 0) - .unCentre(); - - cogs.light(light) - .renderInto(ms, buffer.getBuffer(RenderType.solid())); - - } - - public static float getAngleForTe(KineticTileEntity te, final BlockPos pos, Axis axis) { - float time = AnimationTickHolder.getRenderTime(te.getLevel()); - float offset = getRotationOffsetForPosition(te, pos, axis); - return (time * te.getSpeed() * 3f / 20 + offset) % 360; - } - - @Override - protected BlockState getRenderedBlockState(KineticTileEntity te) { - return shaft(getRotationAxisOf(te)); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageTileEntity.java deleted file mode 100644 index 79e7c7c72..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageTileEntity.java +++ /dev/null @@ -1,187 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.gantry; - -import java.util.List; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException; -import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionCollider; -import com.simibubi.create.content.contraptions.components.structureMovement.IDisplayAssemblyExceptions; -import com.simibubi.create.content.contraptions.relays.advanced.GantryShaftBlock; -import com.simibubi.create.content.contraptions.relays.advanced.GantryShaftTileEntity; -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.nbt.CompoundTag; -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 class GantryCarriageTileEntity extends KineticTileEntity implements IDisplayAssemblyExceptions { - - boolean assembleNextTick; - protected AssemblyException lastException; - - public GantryCarriageTileEntity(BlockEntityType typeIn, BlockPos pos, BlockState state) { - super(typeIn, pos, state); - } - - @Override - public void addBehaviours(List behaviours) { - super.addBehaviours(behaviours); - registerAwardables(behaviours, AllAdvancements.CONTRAPTION_ACTORS); - } - - @Override - public void onSpeedChanged(float previousSpeed) { - super.onSpeedChanged(previousSpeed); - } - - public void checkValidGantryShaft() { - if (shouldAssemble()) - queueAssembly(); - } - - @Override - public void initialize() { - super.initialize(); - if (!getBlockState().canSurvive(level, worldPosition)) - level.destroyBlock(worldPosition, true); - } - - public void queueAssembly() { - assembleNextTick = true; - } - - @Override - public void tick() { - super.tick(); - - if (level.isClientSide) - return; - - if (assembleNextTick) { - tryAssemble(); - assembleNextTick = false; - } - } - - @Override - public AssemblyException getLastAssemblyException() { - return lastException; - } - - private void tryAssemble() { - BlockState blockState = getBlockState(); - if (!(blockState.getBlock() instanceof GantryCarriageBlock)) - return; - - Direction direction = blockState.getValue(GantryCarriageBlock.FACING); - GantryContraption contraption = new GantryContraption(direction); - - BlockEntity shaftTe = level.getBlockEntity(worldPosition.relative(direction.getOpposite())); - if (!(shaftTe instanceof GantryShaftTileEntity)) - return; - BlockState shaftState = shaftTe.getBlockState(); - if (!AllBlocks.GANTRY_SHAFT.has(shaftState)) - return; - - float pinionMovementSpeed = ((GantryShaftTileEntity) shaftTe).getPinionMovementSpeed(); - Direction shaftOrientation = shaftState.getValue(GantryShaftBlock.FACING); - Direction movementDirection = shaftOrientation; - if (pinionMovementSpeed < 0) - movementDirection = movementDirection.getOpposite(); - - try { - lastException = null; - if (!contraption.assemble(level, worldPosition)) - return; - - sendData(); - } catch (AssemblyException e) { - lastException = e; - sendData(); - return; - } - if (ContraptionCollider.isCollidingWithWorld(level, contraption, worldPosition.relative(movementDirection), - movementDirection)) - return; - - if (contraption.containsBlockBreakers()) - award(AllAdvancements.CONTRAPTION_ACTORS); - - contraption.removeBlocksFromWorld(level, BlockPos.ZERO); - GantryContraptionEntity movedContraption = - GantryContraptionEntity.create(level, contraption, shaftOrientation); - BlockPos anchor = worldPosition; - movedContraption.setPos(anchor.getX(), anchor.getY(), anchor.getZ()); - AllSoundEvents.CONTRAPTION_ASSEMBLE.playOnServer(level, worldPosition); - level.addFreshEntity(movedContraption); - } - - @Override - protected void write(CompoundTag compound, boolean clientPacket) { - AssemblyException.write(compound, lastException); - super.write(compound, clientPacket); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - lastException = AssemblyException.read(compound); - super.read(compound, clientPacket); - } - - @Override - public float propagateRotationTo(KineticTileEntity target, BlockState stateFrom, BlockState stateTo, BlockPos diff, - boolean connectedViaAxes, boolean connectedViaCogs) { - float defaultModifier = - super.propagateRotationTo(target, stateFrom, stateTo, diff, connectedViaAxes, connectedViaCogs); - - if (connectedViaAxes) - return defaultModifier; - if (!AllBlocks.GANTRY_SHAFT.has(stateTo)) - return defaultModifier; - if (!stateTo.getValue(GantryShaftBlock.POWERED)) - return defaultModifier; - - Direction direction = Direction.getNearest(diff.getX(), diff.getY(), diff.getZ()); - if (stateFrom.getValue(GantryCarriageBlock.FACING) != direction.getOpposite()) - return defaultModifier; - return getGantryPinionModifier(stateTo.getValue(GantryShaftBlock.FACING), stateFrom.getValue(GantryCarriageBlock.FACING)); - } - - public static float getGantryPinionModifier(Direction shaft, Direction pinionDirection) { - Axis shaftAxis = shaft.getAxis(); - float directionModifier = shaft.getAxisDirection() - .getStep(); - if (shaftAxis == Axis.Y) - if (pinionDirection == Direction.NORTH || pinionDirection == Direction.EAST) - return -directionModifier; - if (shaftAxis == Axis.X) - if (pinionDirection == Direction.DOWN || pinionDirection == Direction.SOUTH) - return -directionModifier; - if (shaftAxis == Axis.Z) - if (pinionDirection == Direction.UP || pinionDirection == Direction.WEST) - return -directionModifier; - return directionModifier; - } - - private boolean shouldAssemble() { - BlockState blockState = getBlockState(); - if (!(blockState.getBlock() instanceof GantryCarriageBlock)) - return false; - Direction facing = blockState.getValue(GantryCarriageBlock.FACING) - .getOpposite(); - BlockState shaftState = level.getBlockState(worldPosition.relative(facing)); - if (!(shaftState.getBlock() instanceof GantryShaftBlock)) - return false; - if (shaftState.getValue(GantryShaftBlock.POWERED)) - return false; - BlockEntity te = level.getBlockEntity(worldPosition.relative(facing)); - return te instanceof GantryShaftTileEntity && ((GantryShaftTileEntity) te).canAssembleOn(); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryContraption.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryContraption.java deleted file mode 100644 index bbb995b66..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryContraption.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.gantry; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException; -import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType; -import com.simibubi.create.content.contraptions.components.structureMovement.NonStationaryLighter; -import com.simibubi.create.content.contraptions.components.structureMovement.TranslatingContraption; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionLighter; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -public class GantryContraption extends TranslatingContraption { - - protected Direction facing; - - public GantryContraption() {} - - public GantryContraption(Direction facing) { - this.facing = facing; - } - - @Override - public boolean assemble(Level world, BlockPos pos) throws AssemblyException { - if (!searchMovedStructure(world, pos, null)) - return false; - startMoving(world); - return true; - } - - @Override - public CompoundTag writeNBT(boolean spawnPacket) { - CompoundTag tag = super.writeNBT(spawnPacket); - tag.putInt("Facing", facing.get3DDataValue()); - return tag; - } - - @Override - public void readNBT(Level world, CompoundTag tag, boolean spawnData) { - facing = Direction.from3DDataValue(tag.getInt("Facing")); - super.readNBT(world, tag, spawnData); - } - - @Override - protected boolean isAnchoringBlockAt(BlockPos pos) { - return super.isAnchoringBlockAt(pos.relative(facing)); - } - - @Override - protected ContraptionType getType() { - return ContraptionType.GANTRY; - } - - public Direction getFacing() { - return facing; - } - - @Override - protected boolean shouldUpdateAfterMovement(StructureBlockInfo info) { - return super.shouldUpdateAfterMovement(info) && !AllBlocks.GANTRY_CARRIAGE.has(info.state); - } - - @Override - @OnlyIn(Dist.CLIENT) - public ContraptionLighter makeLighter() { - return new NonStationaryLighter<>(this); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryContraptionEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryContraptionEntity.java deleted file mode 100644 index d20f50ef2..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryContraptionEntity.java +++ /dev/null @@ -1,209 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.gantry; - -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllEntityTypes; -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; -import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionCollider; -import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform; -import com.simibubi.create.content.contraptions.relays.advanced.GantryShaftBlock; -import com.simibubi.create.content.contraptions.relays.advanced.GantryShaftTileEntity; -import com.simibubi.create.foundation.networking.AllPackets; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.ServerSpeedProvider; - -import net.minecraft.client.Minecraft; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.util.Mth; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EntityType; -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.Vec3; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.network.PacketDistributor; - -public class GantryContraptionEntity extends AbstractContraptionEntity { - - Direction movementAxis; - double clientOffsetDiff; - double axisMotion; - - public GantryContraptionEntity(EntityType entityTypeIn, Level worldIn) { - super(entityTypeIn, worldIn); - } - - public static GantryContraptionEntity create(Level world, Contraption contraption, Direction movementAxis) { - GantryContraptionEntity entity = new GantryContraptionEntity(AllEntityTypes.GANTRY_CONTRAPTION.get(), world); - entity.setContraption(contraption); - entity.movementAxis = movementAxis; - return entity; - } - - @Override - protected void tickContraption() { - if (!(contraption instanceof GantryContraption)) - return; - - double prevAxisMotion = axisMotion; - if (level.isClientSide) { - clientOffsetDiff *= .75f; - updateClientMotion(); - } - - checkPinionShaft(); - tickActors(); - Vec3 movementVec = getDeltaMovement(); - - if (ContraptionCollider.collideBlocks(this)) { - if (!level.isClientSide) - disassemble(); - return; - } - - if (!isStalled() && tickCount > 2) - move(movementVec.x, movementVec.y, movementVec.z); - - if (Math.signum(prevAxisMotion) != Math.signum(axisMotion) && prevAxisMotion != 0) - contraption.stop(level); - if (!level.isClientSide && (prevAxisMotion != axisMotion || tickCount % 3 == 0)) - sendPacket(); - } - - protected void checkPinionShaft() { - Vec3 movementVec; - Direction facing = ((GantryContraption) contraption).getFacing(); - Vec3 currentPosition = getAnchorVec().add(.5, .5, .5); - BlockPos gantryShaftPos = new BlockPos(currentPosition).relative(facing.getOpposite()); - - BlockEntity te = level.getBlockEntity(gantryShaftPos); - if (!(te instanceof GantryShaftTileEntity) || !AllBlocks.GANTRY_SHAFT.has(te.getBlockState())) { - if (!level.isClientSide) { - setContraptionMotion(Vec3.ZERO); - disassemble(); - } - return; - } - - BlockState blockState = te.getBlockState(); - Direction direction = blockState.getValue(GantryShaftBlock.FACING); - GantryShaftTileEntity gantryShaftTileEntity = (GantryShaftTileEntity) te; - - float pinionMovementSpeed = gantryShaftTileEntity.getPinionMovementSpeed(); - movementVec = Vec3.atLowerCornerOf(direction.getNormal()).scale(pinionMovementSpeed); - - if (blockState.getValue(GantryShaftBlock.POWERED) || pinionMovementSpeed == 0) { - setContraptionMotion(Vec3.ZERO); - if (!level.isClientSide) - disassemble(); - return; - } - - Vec3 nextPosition = currentPosition.add(movementVec); - double currentCoord = direction.getAxis() - .choose(currentPosition.x, currentPosition.y, currentPosition.z); - double nextCoord = direction.getAxis() - .choose(nextPosition.x, nextPosition.y, nextPosition.z); - - if ((Mth.floor(currentCoord) + .5f < nextCoord != (pinionMovementSpeed * direction.getAxisDirection() - .getStep() < 0))) - if (!gantryShaftTileEntity.canAssembleOn()) { - setContraptionMotion(Vec3.ZERO); - if (!level.isClientSide) - disassemble(); - return; - } - - if (level.isClientSide) - return; - - axisMotion = pinionMovementSpeed; - setContraptionMotion(movementVec); - } - - @Override - protected void writeAdditional(CompoundTag compound, boolean spawnPacket) { - NBTHelper.writeEnum(compound, "GantryAxis", movementAxis); - super.writeAdditional(compound, spawnPacket); - } - - protected void readAdditional(CompoundTag compound, boolean spawnData) { - movementAxis = NBTHelper.readEnum(compound, "GantryAxis", Direction.class); - super.readAdditional(compound, spawnData); - } - - @Override - public Vec3 applyRotation(Vec3 localPos, float partialTicks) { - return localPos; - } - - @Override - public Vec3 reverseRotation(Vec3 localPos, float partialTicks) { - return localPos; - } - - @Override - protected StructureTransform makeStructureTransform() { - return new StructureTransform(new BlockPos(getAnchorVec().add(.5, .5, .5)), 0, 0, 0); - } - - @Override - protected float getStalledAngle() { - return 0; - } - - @Override - public void teleportTo(double p_70634_1_, double p_70634_3_, double p_70634_5_) {} - - @Override - @OnlyIn(Dist.CLIENT) - public void lerpTo(double x, double y, double z, float yw, float pt, int inc, boolean t) {} - - @Override - protected void handleStallInformation(double x, double y, double z, float angle) { - setPosRaw(x, y, z); - clientOffsetDiff = 0; - } - - @Override - public ContraptionRotationState getRotationState() { - return ContraptionRotationState.NONE; - } - - @Override - public void applyLocalTransforms(PoseStack matrixStack, float partialTicks) { } - - public void updateClientMotion() { - float modifier = movementAxis.getAxisDirection() - .getStep(); - setContraptionMotion(Vec3.atLowerCornerOf(movementAxis.getNormal()) - .scale((axisMotion + clientOffsetDiff * modifier / 2f) * ServerSpeedProvider.get())); - } - - public double getAxisCoord() { - Vec3 anchorVec = getAnchorVec(); - return movementAxis.getAxis() - .choose(anchorVec.x, anchorVec.y, anchorVec.z); - } - - public void sendPacket() { - AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> this), - new GantryContraptionUpdatePacket(getId(), getAxisCoord(), axisMotion)); - } - - @OnlyIn(Dist.CLIENT) - public static void handlePacket(GantryContraptionUpdatePacket packet) { - Entity entity = Minecraft.getInstance().level.getEntity(packet.entityID); - if (!(entity instanceof GantryContraptionEntity)) - return; - GantryContraptionEntity ce = (GantryContraptionEntity) entity; - ce.axisMotion = packet.motion; - ce.clientOffsetDiff = packet.coord - ce.getAxisCoord(); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryContraptionUpdatePacket.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryContraptionUpdatePacket.java deleted file mode 100644 index 2fb4b9af2..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryContraptionUpdatePacket.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.gantry; - -import java.util.function.Supplier; - -import com.simibubi.create.foundation.networking.SimplePacketBase; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.fml.DistExecutor; -import net.minecraftforge.network.NetworkEvent.Context; - -public class GantryContraptionUpdatePacket extends SimplePacketBase { - - int entityID; - double coord; - double motion; - - public GantryContraptionUpdatePacket(int entityID, double coord, double motion) { - this.entityID = entityID; - this.coord = coord; - this.motion = motion; - } - - public GantryContraptionUpdatePacket(FriendlyByteBuf buffer) { - entityID = buffer.readInt(); - coord = buffer.readFloat(); - motion = buffer.readFloat(); - } - - @Override - public void write(FriendlyByteBuf buffer) { - buffer.writeInt(entityID); - buffer.writeFloat((float) coord); - buffer.writeFloat((float) motion); - } - - @Override - public void handle(Supplier context) { - context.get() - .enqueueWork( - () -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> GantryContraptionEntity.handlePacket(this))); - context.get() - .setPacketHandled(true); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/GlueEffectPacket.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/GlueEffectPacket.java deleted file mode 100644 index ddbce17e0..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/GlueEffectPacket.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.glue; - -import java.util.function.Supplier; - -import com.simibubi.create.foundation.networking.SimplePacketBase; - -import net.minecraft.client.Minecraft; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.fml.DistExecutor; -import net.minecraftforge.network.NetworkEvent.Context; - -public class GlueEffectPacket extends SimplePacketBase { - - private BlockPos pos; - private Direction direction; - private boolean fullBlock; - - public GlueEffectPacket(BlockPos pos, Direction direction, boolean fullBlock) { - this.pos = pos; - this.direction = direction; - this.fullBlock = fullBlock; - } - - public GlueEffectPacket(FriendlyByteBuf buffer) { - pos = buffer.readBlockPos(); - direction = Direction.from3DDataValue(buffer.readByte()); - fullBlock = buffer.readBoolean(); - } - - public void write(FriendlyByteBuf buffer) { - buffer.writeBlockPos(pos); - buffer.writeByte(direction.get3DDataValue()); - buffer.writeBoolean(fullBlock); - } - - @OnlyIn(Dist.CLIENT) - public void handle(Supplier context) { - context.get().enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { - Minecraft mc = Minecraft.getInstance(); - if (!mc.player.blockPosition().closerThan(pos, 100)) - return; - SuperGlueItem.spawnParticles(mc.level, pos, direction, fullBlock); - })); - context.get().setPacketHandled(true); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsStopControllingPacket.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsStopControllingPacket.java deleted file mode 100644 index 088f8bb50..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/ControlsStopControllingPacket.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls; - -import java.util.function.Supplier; - -import com.simibubi.create.foundation.networking.SimplePacketBase; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraftforge.network.NetworkEvent.Context; - -public class ControlsStopControllingPacket extends SimplePacketBase { - - public ControlsStopControllingPacket() {} - - public ControlsStopControllingPacket(FriendlyByteBuf buffer) {} - - @Override - public void write(FriendlyByteBuf buffer) {} - - @Override - public void handle(Supplier context) { - context.get() - .enqueueWork(ControlsHandler::stopControlling); - context.get() - .setPacketHandled(true); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/HonkPacket.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/HonkPacket.java deleted file mode 100644 index 4dac38aa9..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/HonkPacket.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls; - -import java.util.UUID; -import java.util.function.Supplier; - -import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.entity.Train; -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.networking.AllPackets; -import com.simibubi.create.foundation.networking.SimplePacketBase; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.server.level.ServerPlayer; -import net.minecraftforge.network.NetworkEvent.Context; -import net.minecraftforge.network.PacketDistributor; - -public class HonkPacket extends SimplePacketBase { - - UUID trainId; - boolean isHonk; - - public HonkPacket() {} - - public HonkPacket(Train train, boolean isHonk) { - trainId = train.id; - this.isHonk = isHonk; - } - - public HonkPacket(FriendlyByteBuf buffer) { - trainId = buffer.readUUID(); - isHonk = buffer.readBoolean(); - } - - @Override - public void write(FriendlyByteBuf buffer) { - buffer.writeUUID(trainId); - buffer.writeBoolean(isHonk); - } - - @Override - public void handle(Supplier context) { - Context c = context.get(); - c.enqueueWork(() -> { - ServerPlayer sender = c.getSender(); - boolean clientSide = sender == null; - Train train = Create.RAILWAYS.sided(clientSide ? null : sender.level).trains.get(trainId); - if (train == null) - return; - - if (clientSide) { - if (isHonk) - train.honkTicks = train.honkTicks == 0 ? 20 : 13; - else - train.honkTicks = train.honkTicks > 5 ? 6 : 0; - } else { - AllAdvancements.TRAIN_WHISTLE.awardTo(sender); - AllPackets.channel.send(PacketDistributor.ALL.noArg(), new HonkPacket(train, isHonk)); - } - - }); - c.setPacketHandled(true); - } - - public static class Serverbound extends HonkPacket { - - public Serverbound(FriendlyByteBuf buffer) { - super(buffer); - } - - public Serverbound(Train train, boolean isHonk) { - super(train, isHonk); - } - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssemblerTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssemblerTileEntity.java deleted file mode 100644 index 0ae9a855a..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssemblerTileEntity.java +++ /dev/null @@ -1,325 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.mounted; - -import java.util.List; -import java.util.UUID; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException; -import com.simibubi.create.content.contraptions.components.structureMovement.IDisplayAssemblyExceptions; -import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingHandler; -import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.CapabilityMinecartController; -import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.MinecartController; -import com.simibubi.create.content.contraptions.components.tracks.ControllerRailBlock; -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.CenteredSideValueBoxTransform; -import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform; -import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.INamedIconOptions; -import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollOptionBehaviour; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.core.Vec3i; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.util.Mth; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.vehicle.AbstractMinecart; -import net.minecraft.world.entity.vehicle.MinecartFurnace; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.RailShape; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.fml.common.Mod.EventBusSubscriber; - -@EventBusSubscriber -public class CartAssemblerTileEntity extends SmartTileEntity implements IDisplayAssemblyExceptions { - private static final int assemblyCooldown = 8; - - protected ScrollOptionBehaviour movementMode; - private int ticksSinceMinecartUpdate; - protected AssemblyException lastException; - protected AbstractMinecart cartToAssemble; - - public CartAssemblerTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - ticksSinceMinecartUpdate = assemblyCooldown; - } - - @Override - public void tick() { - super.tick(); - if (ticksSinceMinecartUpdate < assemblyCooldown) { - ticksSinceMinecartUpdate++; - } - - tryAssemble(cartToAssemble); - cartToAssemble = null; - } - - public void tryAssemble(AbstractMinecart cart) { - if (cart == null) - return; - - if (!isMinecartUpdateValid()) - return; - resetTicksSinceMinecartUpdate(); - - BlockState state = level.getBlockState(worldPosition); - if (!AllBlocks.CART_ASSEMBLER.has(state)) - return; - CartAssemblerBlock block = (CartAssemblerBlock) state.getBlock(); - - CartAssemblerBlock.CartAssemblerAction action = CartAssemblerBlock.getActionForCart(state, cart); - if (action.shouldAssemble()) - assemble(level, worldPosition, cart); - if (action.shouldDisassemble()) - disassemble(level, worldPosition, cart); - if (action == CartAssemblerBlock.CartAssemblerAction.ASSEMBLE_ACCELERATE) { - if (cart.getDeltaMovement() - .length() > 1 / 128f) { - Direction facing = cart.getMotionDirection(); - RailShape railShape = state.getValue(CartAssemblerBlock.RAIL_SHAPE); - for (Direction d : Iterate.directionsInAxis(railShape == RailShape.EAST_WEST ? Axis.X : Axis.Z)) - if (level.getBlockState(worldPosition.relative(d)) - .isRedstoneConductor(level, worldPosition.relative(d))) - facing = d.getOpposite(); - - float speed = block.getRailMaxSpeed(state, level, worldPosition, cart); - cart.setDeltaMovement(facing.getStepX() * speed, facing.getStepY() * speed, facing.getStepZ() * speed); - } - } - if (action == CartAssemblerBlock.CartAssemblerAction.ASSEMBLE_ACCELERATE_DIRECTIONAL) { - Vec3i accelerationVector = - ControllerRailBlock.getAccelerationVector(AllBlocks.CONTROLLER_RAIL.getDefaultState() - .setValue(ControllerRailBlock.SHAPE, state.getValue(CartAssemblerBlock.RAIL_SHAPE)) - .setValue(ControllerRailBlock.BACKWARDS, state.getValue(CartAssemblerBlock.BACKWARDS))); - float speed = block.getRailMaxSpeed(state, level, worldPosition, cart); - cart.setDeltaMovement(Vec3.atLowerCornerOf(accelerationVector) - .scale(speed)); - } - if (action == CartAssemblerBlock.CartAssemblerAction.DISASSEMBLE_BRAKE) { - Vec3 diff = VecHelper.getCenterOf(worldPosition) - .subtract(cart.position()); - cart.setDeltaMovement(diff.x / 16f, 0, diff.z / 16f); - } - } - - protected void assemble(Level world, BlockPos pos, AbstractMinecart cart) { - if (!cart.getPassengers() - .isEmpty()) - return; - - LazyOptional optional = - cart.getCapability(CapabilityMinecartController.MINECART_CONTROLLER_CAPABILITY); - if (optional.isPresent() && optional.orElse(null) - .isCoupledThroughContraption()) - return; - - CartMovementMode mode = CartMovementMode.values()[movementMode.value]; - - MountedContraption contraption = new MountedContraption(mode); - try { - if (!contraption.assemble(world, pos)) - return; - - lastException = null; - sendData(); - } catch (AssemblyException e) { - lastException = e; - sendData(); - return; - } - - boolean couplingFound = contraption.connectedCart != null; - Direction initialOrientation = CartAssemblerBlock.getHorizontalDirection(getBlockState()); - - if (couplingFound) { - cart.setPos(pos.getX() + .5f, pos.getY(), pos.getZ() + .5f); - if (!CouplingHandler.tryToCoupleCarts(null, world, cart.getId(), - contraption.connectedCart.getId())) - return; - } - - contraption.removeBlocksFromWorld(world, BlockPos.ZERO); - contraption.startMoving(world); - contraption.expandBoundsAroundAxis(Axis.Y); - - if (couplingFound) { - Vec3 diff = contraption.connectedCart.position() - .subtract(cart.position()); - initialOrientation = Direction.fromYRot(Mth.atan2(diff.z, diff.x) * 180 / Math.PI); - } - - OrientedContraptionEntity entity = OrientedContraptionEntity.create(world, contraption, initialOrientation); - if (couplingFound) - entity.setCouplingId(cart.getUUID()); - entity.setPos(pos.getX() + .5, pos.getY(), pos.getZ() + .5); - world.addFreshEntity(entity); - entity.startRiding(cart); - - if (cart instanceof MinecartFurnace) { - CompoundTag nbt = cart.serializeNBT(); - nbt.putDouble("PushZ", 0); - nbt.putDouble("PushX", 0); - cart.deserializeNBT(nbt); - } - - if (contraption.containsBlockBreakers()) - award(AllAdvancements.CONTRAPTION_ACTORS); - } - - protected void disassemble(Level world, BlockPos pos, AbstractMinecart cart) { - if (cart.getPassengers() - .isEmpty()) - return; - Entity entity = cart.getPassengers() - .get(0); - if (!(entity instanceof OrientedContraptionEntity)) - return; - OrientedContraptionEntity contraption = (OrientedContraptionEntity) entity; - UUID couplingId = contraption.getCouplingId(); - - if (couplingId == null) { - contraption.yaw = CartAssemblerBlock.getHorizontalDirection(getBlockState()) - .toYRot(); - disassembleCart(cart); - return; - } - - Couple coupledCarts = contraption.getCoupledCartsIfPresent(); - if (coupledCarts == null) - return; - - // Make sure connected cart is present and being disassembled - for (boolean current : Iterate.trueAndFalse) { - MinecartController minecartController = coupledCarts.get(current); - if (minecartController.cart() == cart) - continue; - BlockPos otherPos = minecartController.cart() - .blockPosition(); - BlockState blockState = world.getBlockState(otherPos); - if (!AllBlocks.CART_ASSEMBLER.has(blockState)) - return; - if (!CartAssemblerBlock.getActionForCart(blockState, minecartController.cart()) - .shouldDisassemble()) - return; - } - - for (boolean current : Iterate.trueAndFalse) - coupledCarts.get(current) - .removeConnection(current); - disassembleCart(cart); - } - - protected void disassembleCart(AbstractMinecart cart) { - cart.ejectPassengers(); - if (cart instanceof MinecartFurnace) { - CompoundTag nbt = cart.serializeNBT(); - nbt.putDouble("PushZ", cart.getDeltaMovement().x); - nbt.putDouble("PushX", cart.getDeltaMovement().z); - cart.deserializeNBT(nbt); - } - } - - @Override - public void addBehaviours(List behaviours) { - movementMode = new ScrollOptionBehaviour<>(CartMovementMode.class, - Lang.translateDirect("contraptions.cart_movement_mode"), this, getMovementModeSlot()); - movementMode.requiresWrench(); - behaviours.add(movementMode); - registerAwardables(behaviours, AllAdvancements.CONTRAPTION_ACTORS); - } - - @Override - public void write(CompoundTag compound, boolean clientPacket) { - AssemblyException.write(compound, lastException); - super.write(compound, clientPacket); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - lastException = AssemblyException.read(compound); - super.read(compound, clientPacket); - } - - @Override - public AssemblyException getLastAssemblyException() { - return lastException; - } - - protected ValueBoxTransform getMovementModeSlot() { - return new CartAssemblerValueBoxTransform(); - } - - private class CartAssemblerValueBoxTransform extends CenteredSideValueBoxTransform { - - public CartAssemblerValueBoxTransform() { - super((state, d) -> { - if (d.getAxis() - .isVertical()) - return false; - if (!state.hasProperty(CartAssemblerBlock.RAIL_SHAPE)) - return false; - RailShape railShape = state.getValue(CartAssemblerBlock.RAIL_SHAPE); - return (d.getAxis() == Axis.X) == (railShape == RailShape.NORTH_SOUTH); - }); - } - - @Override - protected Vec3 getSouthLocation() { - return VecHelper.voxelSpace(8, 8, 18); - } - - } - - public enum CartMovementMode implements INamedIconOptions { - - ROTATE(AllIcons.I_CART_ROTATE), - ROTATE_PAUSED(AllIcons.I_CART_ROTATE_PAUSED), - ROTATION_LOCKED(AllIcons.I_CART_ROTATE_LOCKED), - - ; - - private String translationKey; - private AllIcons icon; - - CartMovementMode(AllIcons icon) { - this.icon = icon; - translationKey = "contraptions.cart_movement_mode." + Lang.asId(name()); - } - - @Override - public AllIcons getIcon() { - return icon; - } - - @Override - public String getTranslationKey() { - return translationKey; - } - } - - public void resetTicksSinceMinecartUpdate() { - ticksSinceMinecartUpdate = 0; - } - - public void assembleNextTick(AbstractMinecart cart) { - if (cartToAssemble == null) - cartToAssemble = cart; - } - - public boolean isMinecartUpdateValid() { - return ticksSinceMinecartUpdate >= assemblyCooldown; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/LinearActuatorTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/LinearActuatorTileEntity.java deleted file mode 100644 index 1090f204d..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/LinearActuatorTileEntity.java +++ /dev/null @@ -1,339 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.piston; - -import java.util.List; - -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException; -import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionCollider; -import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.IControlContraption; -import com.simibubi.create.content.contraptions.components.structureMovement.IDisplayAssemblyExceptions; -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform; -import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollOptionBehaviour; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.ServerSpeedProvider; - -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.util.Mth; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; - -public abstract class LinearActuatorTileEntity extends KineticTileEntity - implements IControlContraption, IDisplayAssemblyExceptions { - - public float offset; - public boolean running; - public boolean assembleNextTick; - public boolean needsContraption; - public AbstractContraptionEntity movedContraption; - protected boolean forceMove; - protected ScrollOptionBehaviour movementMode; - protected boolean waitingForSpeedChange; - protected AssemblyException lastException; - - // Custom position sync - protected float clientOffsetDiff; - - public LinearActuatorTileEntity(BlockEntityType typeIn, BlockPos pos, BlockState state) { - super(typeIn, pos, state); - setLazyTickRate(3); - forceMove = true; - needsContraption = true; - } - - @Override - public void addBehaviours(List behaviours) { - super.addBehaviours(behaviours); - movementMode = new ScrollOptionBehaviour<>(MovementMode.class, Lang.translateDirect("contraptions.movement_mode"), - this, getMovementModeSlot()); - movementMode.requiresWrench(); - movementMode.withCallback(t -> waitingForSpeedChange = false); - behaviours.add(movementMode); - registerAwardables(behaviours, AllAdvancements.CONTRAPTION_ACTORS); - } - - @Override - public void tick() { - super.tick(); - - if (movedContraption != null) { - if (!movedContraption.isAlive()) - movedContraption = null; - } - - if (level.isClientSide) - clientOffsetDiff *= .75f; - - if (waitingForSpeedChange) { - if (movedContraption != null) { - if (level.isClientSide) { - float syncSpeed = clientOffsetDiff / 2f; - offset += syncSpeed; - movedContraption.setContraptionMotion(toMotionVector(syncSpeed)); - return; - } - movedContraption.setContraptionMotion(Vec3.ZERO); - } - return; - } - - if (!level.isClientSide && assembleNextTick) { - assembleNextTick = false; - if (running) { - if (getSpeed() == 0) - tryDisassemble(); - else - sendData(); - return; - } else { - if (getSpeed() != 0) - try { - assemble(); - lastException = null; - } catch (AssemblyException e) { - lastException = e; - } - sendData(); - } - return; - } - - if (!running) - return; - - boolean contraptionPresent = movedContraption != null; - if (needsContraption && !contraptionPresent) - return; - - float movementSpeed = getMovementSpeed(); - float newOffset = offset + movementSpeed; - if ((int) newOffset != (int) offset) - visitNewPosition(); - - if (contraptionPresent) { - if (moveAndCollideContraption()) { - movedContraption.setContraptionMotion(Vec3.ZERO); - offset = getGridOffset(offset); - resetContraptionToOffset(); - collided(); - return; - } - } - - if (!contraptionPresent || !movedContraption.isStalled()) - offset = newOffset; - - int extensionRange = getExtensionRange(); - if (offset <= 0 || offset >= extensionRange) { - offset = offset <= 0 ? 0 : extensionRange; - if (!level.isClientSide) { - moveAndCollideContraption(); - resetContraptionToOffset(); - tryDisassemble(); - if (waitingForSpeedChange) { - forceMove = true; - sendData(); - } - } - return; - } - } - - @Override - public void lazyTick() { - super.lazyTick(); - if (movedContraption != null && !level.isClientSide) - sendData(); - } - - protected int getGridOffset(float offset) { - return Mth.clamp((int) (offset + .5f), 0, getExtensionRange()); - } - - public float getInterpolatedOffset(float partialTicks) { - float interpolatedOffset = - Mth.clamp(offset + (partialTicks - .5f) * getMovementSpeed(), 0, getExtensionRange()); - return interpolatedOffset; - } - - @Override - public void onSpeedChanged(float prevSpeed) { - super.onSpeedChanged(prevSpeed); - assembleNextTick = true; - waitingForSpeedChange = false; - - if (movedContraption != null && Math.signum(prevSpeed) != Math.signum(getSpeed()) && prevSpeed != 0) { - movedContraption.getContraption() - .stop(level); - } - } - - @Override - public void remove() { - this.remove = true; - if (!level.isClientSide) - disassemble(); - super.remove(); - } - - @Override - protected void write(CompoundTag compound, boolean clientPacket) { - compound.putBoolean("Running", running); - compound.putBoolean("Waiting", waitingForSpeedChange); - compound.putFloat("Offset", offset); - AssemblyException.write(compound, lastException); - super.write(compound, clientPacket); - - if (clientPacket && forceMove) { - compound.putBoolean("ForceMovement", forceMove); - forceMove = false; - } - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - boolean forceMovement = compound.contains("ForceMovement"); - float offsetBefore = offset; - - running = compound.getBoolean("Running"); - waitingForSpeedChange = compound.getBoolean("Waiting"); - offset = compound.getFloat("Offset"); - lastException = AssemblyException.read(compound); - super.read(compound, clientPacket); - - if (!clientPacket) - return; - if (forceMovement) - resetContraptionToOffset(); - else if (running) { - clientOffsetDiff = offset - offsetBefore; - offset = offsetBefore; - } - if (!running) - movedContraption = null; - } - - @Override - public AssemblyException getLastAssemblyException() { - return lastException; - } - - public abstract void disassemble(); - - protected abstract void assemble() throws AssemblyException; - - protected abstract int getExtensionRange(); - - protected abstract int getInitialOffset(); - - protected abstract ValueBoxTransform getMovementModeSlot(); - - protected abstract Vec3 toMotionVector(float speed); - - protected abstract Vec3 toPosition(float offset); - - protected void visitNewPosition() {} - - protected void tryDisassemble() { - if (remove) { - disassemble(); - return; - } - if (movementMode.get() == MovementMode.MOVE_NEVER_PLACE) { - waitingForSpeedChange = true; - return; - } - int initial = getInitialOffset(); - if ((int) (offset + .5f) != initial && movementMode.get() == MovementMode.MOVE_PLACE_RETURNED) { - waitingForSpeedChange = true; - return; - } - disassemble(); - } - - protected boolean moveAndCollideContraption() { - if (movedContraption == null) - return false; - if (movedContraption.isStalled()) { - movedContraption.setContraptionMotion(Vec3.ZERO); - return false; - } - - Vec3 motion = getMotionVector(); - movedContraption.setContraptionMotion(getMotionVector()); - movedContraption.move(motion.x, motion.y, motion.z); - return ContraptionCollider.collideBlocks(movedContraption); - } - - protected void collided() { - if (level.isClientSide) { - waitingForSpeedChange = true; - return; - } - offset = getGridOffset(offset - getMovementSpeed()); - resetContraptionToOffset(); - tryDisassemble(); - } - - protected void resetContraptionToOffset() { - if (movedContraption == null) - return; - Vec3 vec = toPosition(offset); - movedContraption.setPos(vec.x, vec.y, vec.z); - if (getSpeed() == 0 || waitingForSpeedChange) - movedContraption.setContraptionMotion(Vec3.ZERO); - } - - public float getMovementSpeed() { - float movementSpeed = Mth.clamp(convertToLinear(getSpeed()), -.49f, .49f) + clientOffsetDiff / 2f; - if (level.isClientSide) - movementSpeed *= ServerSpeedProvider.get(); - return movementSpeed; - } - - public Vec3 getMotionVector() { - return toMotionVector(getMovementSpeed()); - } - - @Override - public void onStall() { - if (!level.isClientSide) { - forceMove = true; - sendData(); - } - } - - public void onLengthBroken() { - offset = 0; - sendData(); - } - - @Override - public boolean isValid() { - return !isRemoved(); - } - - @Override - public void attach(ControlledContraptionEntity contraption) { - this.movedContraption = contraption; - if (!level.isClientSide) { - this.running = true; - sendData(); - } - } - - @Override - public boolean isAttachedTo(AbstractContraptionEntity contraption) { - return movedContraption == contraption; - } - - @Override - public BlockPos getBlockPosition() { - return worldPosition; - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonRenderer.java deleted file mode 100644 index 65c327ccb..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonRenderer.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.piston; - -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; - -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.world.level.block.state.BlockState; - -public class MechanicalPistonRenderer extends KineticTileEntityRenderer { - - public MechanicalPistonRenderer(BlockEntityRendererProvider.Context context) { - super(context); - } - - @Override - protected BlockState getRenderedBlockState(KineticTileEntity te) { - return shaft(getRotationAxisOf(te)); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonTileEntity.java deleted file mode 100644 index 0492ee77c..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonTileEntity.java +++ /dev/null @@ -1,178 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.piston; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.content.contraptions.base.IRotate; -import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException; -import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionCollider; -import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.DirectionalExtenderScrollOptionSlot; -import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.PistonState; -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform; -import com.simibubi.create.foundation.utility.ServerSpeedProvider; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.core.Direction.AxisDirection; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.util.Mth; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.phys.Vec3; - -public class MechanicalPistonTileEntity extends LinearActuatorTileEntity { - - protected boolean hadCollisionWithOtherPiston; - protected int extensionLength; - - public MechanicalPistonTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - extensionLength = compound.getInt("ExtensionLength"); - super.read(compound, clientPacket); - } - - @Override - protected void write(CompoundTag tag, boolean clientPacket) { - tag.putInt("ExtensionLength", extensionLength); - super.write(tag, clientPacket); - } - - @Override - public void assemble() throws AssemblyException { - if (!(level.getBlockState(worldPosition) - .getBlock() instanceof MechanicalPistonBlock)) - return; - - Direction direction = getBlockState().getValue(BlockStateProperties.FACING); - - // Collect Construct - PistonContraption contraption = new PistonContraption(direction, getMovementSpeed() < 0); - if (!contraption.assemble(level, worldPosition)) - return; - - Direction positive = Direction.get(AxisDirection.POSITIVE, direction.getAxis()); - Direction movementDirection = - getSpeed() > 0 ^ direction.getAxis() != Axis.Z ? positive : positive.getOpposite(); - - BlockPos anchor = contraption.anchor.relative(direction, contraption.initialExtensionProgress); - if (ContraptionCollider.isCollidingWithWorld(level, contraption, anchor.relative(movementDirection), - movementDirection)) - return; - - // Check if not at limit already - extensionLength = contraption.extensionLength; - float resultingOffset = contraption.initialExtensionProgress + Math.signum(getMovementSpeed()) * .5f; - if (resultingOffset <= 0 || resultingOffset >= extensionLength) { - return; - } - - // Run - running = true; - offset = contraption.initialExtensionProgress; - sendData(); - clientOffsetDiff = 0; - - BlockPos startPos = BlockPos.ZERO.relative(direction, contraption.initialExtensionProgress); - contraption.removeBlocksFromWorld(level, startPos); - movedContraption = ControlledContraptionEntity.create(getLevel(), this, contraption); - resetContraptionToOffset(); - forceMove = true; - level.addFreshEntity(movedContraption); - - AllSoundEvents.CONTRAPTION_ASSEMBLE.playOnServer(level, worldPosition); - - if (contraption.containsBlockBreakers()) - award(AllAdvancements.CONTRAPTION_ACTORS); - } - - @Override - public void disassemble() { - if (!running && movedContraption == null) - return; - if (!remove) - getLevel().setBlock(worldPosition, getBlockState().setValue(MechanicalPistonBlock.STATE, PistonState.EXTENDED), - 3 | 16); - if (movedContraption != null) { - resetContraptionToOffset(); - movedContraption.disassemble(); - AllSoundEvents.CONTRAPTION_DISASSEMBLE.playOnServer(level, worldPosition); - } - running = false; - movedContraption = null; - sendData(); - - if (remove) - AllBlocks.MECHANICAL_PISTON.get() - .playerWillDestroy(level, worldPosition, getBlockState(), null); - } - - @Override - protected void collided() { - super.collided(); - if (!running && getMovementSpeed() > 0) - assembleNextTick = true; - } - - @Override - public float getMovementSpeed() { - float movementSpeed = Mth.clamp(convertToLinear(getSpeed()), -.49f, .49f); - if (level.isClientSide) - movementSpeed *= ServerSpeedProvider.get(); - Direction pistonDirection = getBlockState().getValue(BlockStateProperties.FACING); - int movementModifier = pistonDirection.getAxisDirection() - .getStep() * (pistonDirection.getAxis() == Axis.Z ? -1 : 1); - movementSpeed = movementSpeed * -movementModifier + clientOffsetDiff / 2f; - - int extensionRange = getExtensionRange(); - movementSpeed = Mth.clamp(movementSpeed, 0 - offset, extensionRange - offset); - return movementSpeed; - } - - @Override - protected int getExtensionRange() { - return extensionLength; - } - - @Override - protected void visitNewPosition() {} - - @Override - protected Vec3 toMotionVector(float speed) { - Direction pistonDirection = getBlockState().getValue(BlockStateProperties.FACING); - return Vec3.atLowerCornerOf(pistonDirection.getNormal()) - .scale(speed); - } - - @Override - protected Vec3 toPosition(float offset) { - Vec3 position = Vec3.atLowerCornerOf(getBlockState().getValue(BlockStateProperties.FACING) - .getNormal()) - .scale(offset); - return position.add(Vec3.atLowerCornerOf(movedContraption.getContraption().anchor)); - } - - @Override - protected ValueBoxTransform getMovementModeSlot() { - return new DirectionalExtenderScrollOptionSlot((state, d) -> { - Axis axis = d.getAxis(); - Axis extensionAxis = state.getValue(MechanicalPistonBlock.FACING) - .getAxis(); - Axis shaftAxis = ((IRotate) state.getBlock()).getRotationAxis(state); - return extensionAxis != axis && shaftAxis != axis; - }); - } - - @Override - protected int getInitialOffset() { - return movedContraption == null ? 0 - : ((PistonContraption) movedContraption.getContraption()).initialExtensionProgress; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/AbstractPulleyRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/AbstractPulleyRenderer.java deleted file mode 100644 index dfa6dcd0c..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/AbstractPulleyRenderer.java +++ /dev/null @@ -1,120 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.pulley; - -import com.jozufozu.flywheel.backend.Backend; -import com.jozufozu.flywheel.core.PartialModel; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import com.simibubi.create.content.contraptions.base.IRotate; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; - -import net.minecraft.client.renderer.LevelRenderer; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.core.Direction.AxisDirection; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.block.state.BlockState; - -public abstract class AbstractPulleyRenderer extends KineticTileEntityRenderer { - - private PartialModel halfRope; - private PartialModel halfMagnet; - - public AbstractPulleyRenderer(BlockEntityRendererProvider.Context context, PartialModel halfRope, - PartialModel halfMagnet) { - super(context); - this.halfRope = halfRope; - this.halfMagnet = halfMagnet; - } - - @Override - public boolean shouldRenderOffScreen(KineticTileEntity p_188185_1_) { - return true; - } - - @Override - protected void renderSafe(KineticTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - - if (Backend.canUseInstancing(te.getLevel())) - return; - - super.renderSafe(te, partialTicks, ms, buffer, light, overlay); - float offset = getOffset(te, partialTicks); - boolean running = isRunning(te); - - Axis rotationAxis = ((IRotate) te.getBlockState() - .getBlock()).getRotationAxis(te.getBlockState()); - kineticRotationTransform(getRotatedCoil(te), te, rotationAxis, AngleHelper.rad(offset * 180), light) - .renderInto(ms, buffer.getBuffer(RenderType.solid())); - - Level world = te.getLevel(); - BlockState blockState = te.getBlockState(); - BlockPos pos = te.getBlockPos(); - - SuperByteBuffer halfMagnet = CachedBufferer.partial(this.halfMagnet, blockState); - SuperByteBuffer halfRope = CachedBufferer.partial(this.halfRope, blockState); - SuperByteBuffer magnet = renderMagnet(te); - SuperByteBuffer rope = renderRope(te); - - VertexConsumer vb = buffer.getBuffer(RenderType.solid()); - if (running || offset == 0) - renderAt(world, offset > .25f ? magnet : halfMagnet, offset, pos, ms, vb); - - float f = offset % 1; - if (offset > .75f && (f < .25f || f > .75f)) - renderAt(world, halfRope, f > .75f ? f - 1 : f, pos, ms, vb); - - if (!running) - return; - - for (int i = 0; i < offset - 1.25f; i++) - renderAt(world, rope, offset - i - 1, pos, ms, vb); - } - - private void renderAt(LevelAccessor world, SuperByteBuffer partial, float offset, BlockPos pulleyPos, PoseStack ms, - VertexConsumer buffer) { - BlockPos actualPos = pulleyPos.below((int) offset); - int light = LevelRenderer.getLightColor(world, world.getBlockState(actualPos), actualPos); - partial.translate(0, -offset, 0) - .light(light) - .renderInto(ms, buffer); - } - - protected abstract Axis getShaftAxis(KineticTileEntity te); - - protected abstract PartialModel getCoil(); - - protected abstract SuperByteBuffer renderRope(KineticTileEntity te); - - protected abstract SuperByteBuffer renderMagnet(KineticTileEntity te); - - protected abstract float getOffset(KineticTileEntity te, float partialTicks); - - protected abstract boolean isRunning(KineticTileEntity te); - - @Override - protected BlockState getRenderedBlockState(KineticTileEntity te) { - return shaft(getShaftAxis(te)); - } - - protected SuperByteBuffer getRotatedCoil(KineticTileEntity te) { - BlockState blockState = te.getBlockState(); - return CachedBufferer.partialFacing(getCoil(), blockState, - Direction.get(AxisDirection.POSITIVE, getShaftAxis(te))); - } - - @Override - public int getViewDistance() { - return 256; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/HosePulleyInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/HosePulleyInstance.java deleted file mode 100644 index 62d7c0e65..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/HosePulleyInstance.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.pulley; - -import com.jozufozu.flywheel.api.Instancer; -import com.jozufozu.flywheel.api.MaterialManager; -import com.jozufozu.flywheel.core.Materials; -import com.jozufozu.flywheel.core.materials.oriented.OrientedData; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.fluids.actors.HosePulleyTileEntity; -import com.simibubi.create.foundation.utility.AnimationTickHolder; - -public class HosePulleyInstance extends AbstractPulleyInstance { - - public HosePulleyInstance(MaterialManager dispatcher, HosePulleyTileEntity tile) { - super(dispatcher, tile); - } - - protected Instancer getRopeModel() { - return getOrientedMaterial().getModel(AllBlockPartials.HOSE, blockState); - } - - protected Instancer getMagnetModel() { - return materialManager.defaultCutout() - .material(Materials.ORIENTED) - .getModel(AllBlockPartials.HOSE_MAGNET, blockState); - } - - protected Instancer getHalfMagnetModel() { - return materialManager.defaultCutout() - .material(Materials.ORIENTED) - .getModel(AllBlockPartials.HOSE_HALF_MAGNET, blockState); - } - - protected Instancer getCoilModel() { - return getOrientedMaterial().getModel(AllBlockPartials.HOSE_COIL, blockState, rotatingAbout); - } - - protected Instancer getHalfRopeModel() { - return getOrientedMaterial().getModel(AllBlockPartials.HOSE_HALF, blockState); - } - - protected float getOffset() { - return ((HosePulleyTileEntity) blockEntity).getInterpolatedOffset(AnimationTickHolder.getPartialTicks()); - } - - protected boolean isRunning() { - return true; - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyContraption.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyContraption.java deleted file mode 100644 index ee53dfc94..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyContraption.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.pulley; - -import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException; -import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType; -import com.simibubi.create.content.contraptions.components.structureMovement.TranslatingContraption; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionLighter; - -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.level.Level; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -public class PulleyContraption extends TranslatingContraption { - - int initialOffset; - - @Override - protected ContraptionType getType() { - return ContraptionType.PULLEY; - } - - public PulleyContraption() {} - - public PulleyContraption(int initialOffset) { - this.initialOffset = initialOffset; - } - - @Override - public boolean assemble(Level world, BlockPos pos) throws AssemblyException { - if (!searchMovedStructure(world, pos, null)) - return false; - startMoving(world); - return true; - } - - @Override - protected boolean isAnchoringBlockAt(BlockPos pos) { - if (pos.getX() != anchor.getX() || pos.getZ() != anchor.getZ()) - return false; - int y = pos.getY(); - if (y <= anchor.getY() || y > anchor.getY() + initialOffset + 1) - return false; - return true; - } - - @Override - public CompoundTag writeNBT(boolean spawnPacket) { - CompoundTag tag = super.writeNBT(spawnPacket); - tag.putInt("InitialOffset", initialOffset); - return tag; - } - - @Override - public void readNBT(Level world, CompoundTag nbt, boolean spawnData) { - initialOffset = nbt.getInt("InitialOffset"); - super.readNBT(world, nbt, spawnData); - } - - @Override - @OnlyIn(Dist.CLIENT) - public ContraptionLighter makeLighter() { - return new PulleyLighter(this); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyRenderer.java deleted file mode 100644 index ce547d079..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyRenderer.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.pulley; - -import com.jozufozu.flywheel.core.PartialModel; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; - -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.Direction.Axis; -import net.minecraft.util.Mth; - -public class PulleyRenderer extends AbstractPulleyRenderer { - - public PulleyRenderer(BlockEntityRendererProvider.Context context) { - super(context, AllBlockPartials.ROPE_HALF, AllBlockPartials.ROPE_HALF_MAGNET); - } - - @Override - protected Axis getShaftAxis(KineticTileEntity te) { - return te.getBlockState() - .getValue(PulleyBlock.HORIZONTAL_AXIS); - } - - @Override - protected PartialModel getCoil() { - return AllBlockPartials.ROPE_COIL; - } - - @Override - protected SuperByteBuffer renderRope(KineticTileEntity te) { - return CachedBufferer.block(AllBlocks.ROPE.getDefaultState()); - } - - @Override - protected SuperByteBuffer renderMagnet(KineticTileEntity te) { - return CachedBufferer.block(AllBlocks.PULLEY_MAGNET.getDefaultState()); - } - - @Override - protected float getOffset(KineticTileEntity te, float partialTicks) { - PulleyTileEntity pulley = (PulleyTileEntity) te; - return getTileOffset(partialTicks, pulley); - } - - @Override - protected boolean isRunning(KineticTileEntity te) { - return ((PulleyTileEntity) te).running || te.isVirtual(); - } - - - static float getTileOffset(float partialTicks, PulleyTileEntity tile) { - float offset = tile.getInterpolatedOffset(partialTicks); - - if (tile.movedContraption != null) { - AbstractContraptionEntity e = tile.movedContraption; - PulleyContraption c = (PulleyContraption) tile.movedContraption.getContraption(); - double entityPos = Mth.lerp(partialTicks, e.yOld, e.getY()); - offset = (float) -(entityPos - c.anchor.getY() - c.initialOffset); - } - - return offset; - } - - @Override - public int getViewDistance() { - return 128; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyTileEntity.java deleted file mode 100644 index a71661c89..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyTileEntity.java +++ /dev/null @@ -1,270 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.pulley; - -import java.util.List; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException; -import com.simibubi.create.content.contraptions.components.structureMovement.BlockMovementChecks; -import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionCollider; -import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.piston.LinearActuatorTileEntity; -import com.simibubi.create.content.logistics.block.redstone.StockpileSwitchObservable; -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.CenteredSideValueBoxTransform; -import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.util.Mth; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.SimpleWaterloggedBlock; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.material.FluidState; -import net.minecraft.world.level.material.Fluids; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.Vec3; - -public class PulleyTileEntity extends LinearActuatorTileEntity implements StockpileSwitchObservable { - - protected int initialOffset; - private float prevAnimatedOffset; - - public PulleyTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - @Override - protected AABB createRenderBoundingBox() { - return super.createRenderBoundingBox().expandTowards(0, -offset, 0); - } - - @Override - public void addBehaviours(List behaviours) { - super.addBehaviours(behaviours); - registerAwardables(behaviours, AllAdvancements.PULLEY_MAXED); - } - - @Override - public void tick() { - float prevOffset = offset; - super.tick(); - if (isVirtual()) - prevAnimatedOffset = offset; - invalidateRenderBoundingBox(); - - if (prevOffset < 200 && offset >= 200) - award(AllAdvancements.PULLEY_MAXED); - } - - @Override - protected void assemble() throws AssemblyException { - if (!(level.getBlockState(worldPosition) - .getBlock() instanceof PulleyBlock)) - return; - if (speed == 0) - return; - int maxLength = AllConfigs.SERVER.kinetics.maxRopeLength.get(); - int i = 1; - while (i <= maxLength) { - BlockPos ropePos = worldPosition.below(i); - BlockState ropeState = level.getBlockState(ropePos); - if (!AllBlocks.ROPE.has(ropeState) && !AllBlocks.PULLEY_MAGNET.has(ropeState)) { - break; - } - ++i; - } - offset = i - 1; - if (offset >= getExtensionRange() && getSpeed() > 0) - return; - if (offset <= 0 && getSpeed() < 0) - return; - - // Collect Construct - if (!level.isClientSide) { - needsContraption = false; - BlockPos anchor = worldPosition.below(Mth.floor(offset + 1)); - initialOffset = Mth.floor(offset); - PulleyContraption contraption = new PulleyContraption(initialOffset); - boolean canAssembleStructure = contraption.assemble(level, anchor); - - if (canAssembleStructure) { - Direction movementDirection = getSpeed() > 0 ? Direction.DOWN : Direction.UP; - if (ContraptionCollider.isCollidingWithWorld(level, contraption, anchor.relative(movementDirection), - movementDirection)) - canAssembleStructure = false; - } - - if (!canAssembleStructure && getSpeed() > 0) - return; - - for (i = ((int) offset); i > 0; i--) { - BlockPos offset = worldPosition.below(i); - BlockState oldState = level.getBlockState(offset); - if (oldState.getBlock() instanceof SimpleWaterloggedBlock - && oldState.hasProperty(BlockStateProperties.WATERLOGGED) - && oldState.getValue(BlockStateProperties.WATERLOGGED)) { - level.setBlock(offset, Blocks.WATER.defaultBlockState(), 66); - continue; - } - level.setBlock(offset, Blocks.AIR.defaultBlockState(), 66); - } - - if (!contraption.getBlocks() - .isEmpty()) { - contraption.removeBlocksFromWorld(level, BlockPos.ZERO); - movedContraption = ControlledContraptionEntity.create(level, this, contraption); - movedContraption.setPos(anchor.getX(), anchor.getY(), anchor.getZ()); - level.addFreshEntity(movedContraption); - forceMove = true; - needsContraption = true; - - if (contraption.containsBlockBreakers()) - award(AllAdvancements.CONTRAPTION_ACTORS); - } - } - - clientOffsetDiff = 0; - running = true; - sendData(); - } - - @Override - public void disassemble() { - if (!running && movedContraption == null) - return; - offset = getGridOffset(offset); - if (movedContraption != null) - resetContraptionToOffset(); - - if (!level.isClientSide) { - if (!remove) { - if (offset > 0) { - BlockPos magnetPos = worldPosition.below((int) offset); - FluidState ifluidstate = level.getFluidState(magnetPos); - level.destroyBlock(magnetPos, level.getBlockState(magnetPos) - .getCollisionShape(level, magnetPos) - .isEmpty()); - level.setBlock(magnetPos, AllBlocks.PULLEY_MAGNET.getDefaultState() - .setValue(BlockStateProperties.WATERLOGGED, - Boolean.valueOf(ifluidstate.getType() == Fluids.WATER)), - 66); - } - - boolean[] waterlog = new boolean[(int) offset]; - - for (int i = 1; i <= ((int) offset) - 1; i++) { - BlockPos ropePos = worldPosition.below(i); - FluidState ifluidstate = level.getFluidState(ropePos); - waterlog[i] = ifluidstate.getType() == Fluids.WATER; - level.destroyBlock(ropePos, level.getBlockState(ropePos) - .getCollisionShape(level, ropePos) - .isEmpty()); - } - for (int i = 1; i <= ((int) offset) - 1; i++) - level.setBlock(worldPosition.below(i), AllBlocks.ROPE.getDefaultState() - .setValue(BlockStateProperties.WATERLOGGED, waterlog[i]), 66); - } - - if (movedContraption != null) - movedContraption.disassemble(); - } - - if (movedContraption != null) - movedContraption.discard(); - movedContraption = null; - initialOffset = 0; - running = false; - sendData(); - } - - @Override - protected Vec3 toPosition(float offset) { - if (movedContraption.getContraption() instanceof PulleyContraption) { - PulleyContraption contraption = (PulleyContraption) movedContraption.getContraption(); - return Vec3.atLowerCornerOf(contraption.anchor) - .add(0, contraption.initialOffset - offset, 0); - - } - return Vec3.ZERO; - } - - @Override - protected void visitNewPosition() { - super.visitNewPosition(); - if (level.isClientSide) - return; - if (movedContraption != null) - return; - if (getSpeed() <= 0) - return; - - BlockPos posBelow = worldPosition.below((int) (offset + getMovementSpeed()) + 1); - BlockState state = level.getBlockState(posBelow); - if (!BlockMovementChecks.isMovementNecessary(state, level, posBelow)) - return; - if (BlockMovementChecks.isBrittle(state)) - return; - - disassemble(); - assembleNextTick = true; - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - initialOffset = compound.getInt("InitialOffset"); - needsContraption = compound.getBoolean("NeedsContraption"); - super.read(compound, clientPacket); - } - - @Override - public void write(CompoundTag compound, boolean clientPacket) { - compound.putInt("InitialOffset", initialOffset); - super.write(compound, clientPacket); - } - - @Override - protected int getExtensionRange() { - return Math.max(0, Math.min(AllConfigs.SERVER.kinetics.maxRopeLength.get(), - (worldPosition.getY() - 1) - level.getMinBuildHeight())); - } - - @Override - protected int getInitialOffset() { - return initialOffset; - } - - @Override - protected Vec3 toMotionVector(float speed) { - return new Vec3(0, -speed, 0); - } - - @Override - protected ValueBoxTransform getMovementModeSlot() { - return new CenteredSideValueBoxTransform((state, d) -> d == Direction.UP); - } - - @Override - public float getInterpolatedOffset(float partialTicks) { - if (isVirtual()) - return Mth.lerp(partialTicks, prevAnimatedOffset, offset); - boolean moving = running && (movedContraption == null || !movedContraption.isStalled()); - return super.getInterpolatedOffset(moving ? partialTicks : 0.5f); - } - - public void animateOffset(float forcedOffset) { - offset = forcedOffset; - } - - @Override - public float getPercent() { - int distance = worldPosition.getY() - level.getMinBuildHeight(); - if (distance <= 0) - return 100; - return 100 * getInterpolatedOffset(.5f) / distance; - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/RopePulleyInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/RopePulleyInstance.java deleted file mode 100644 index 5eac17ee0..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/RopePulleyInstance.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.pulley; - - -import com.jozufozu.flywheel.api.Instancer; -import com.jozufozu.flywheel.api.MaterialManager; -import com.jozufozu.flywheel.core.materials.oriented.OrientedData; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.AllBlocks; -import com.simibubi.create.foundation.utility.AnimationTickHolder; - -public class RopePulleyInstance extends AbstractPulleyInstance { - public RopePulleyInstance(MaterialManager dispatcher, PulleyTileEntity tile) { - super(dispatcher, tile); - } - - protected Instancer getRopeModel() { - return getOrientedMaterial().getModel(AllBlocks.ROPE.getDefaultState()); - } - - protected Instancer getMagnetModel() { - return getOrientedMaterial().getModel(AllBlocks.PULLEY_MAGNET.getDefaultState()); - } - - protected Instancer getHalfMagnetModel() { - return getOrientedMaterial().getModel(AllBlockPartials.ROPE_HALF_MAGNET, blockState); - } - - protected Instancer getCoilModel() { - return getOrientedMaterial().getModel(AllBlockPartials.ROPE_COIL, blockState, rotatingAbout); - } - - protected Instancer getHalfRopeModel() { - return getOrientedMaterial().getModel(AllBlockPartials.ROPE_HALF, blockState); - } - - protected float getOffset() { - float partialTicks = AnimationTickHolder.getPartialTicks(); - return PulleyRenderer.getTileOffset(partialTicks, (PulleyTileEntity) blockEntity); - } - - protected boolean isRunning() { - return ((PulleyTileEntity) blockEntity).running || blockEntity.isVirtual(); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/EmptyLighter.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/EmptyLighter.java deleted file mode 100644 index c223dea3b..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/EmptyLighter.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.render; - -import com.jozufozu.flywheel.util.box.GridAlignedBB; -import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; - -// so other contraptions don't crash before they have a lighter -public class EmptyLighter extends ContraptionLighter { - public EmptyLighter(Contraption contraption) { - super(contraption); - } - - @Override - public GridAlignedBB getContraptionBounds() { - return new GridAlignedBB(0, 0, 0, 1, 1, 1); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/package-info.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/package-info.java deleted file mode 100644 index 08edd5958..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault -package com.simibubi.create.content.contraptions.components.structureMovement.render; - -import javax.annotation.ParametersAreNonnullByDefault; - -import net.minecraft.MethodsReturnNonnullByDefault; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/ClientMotionPacket.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/ClientMotionPacket.java deleted file mode 100644 index 7f95c9894..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/ClientMotionPacket.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.sync; - -import java.util.function.Supplier; - -import com.simibubi.create.foundation.networking.AllPackets; -import com.simibubi.create.foundation.networking.SimplePacketBase; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.network.NetworkEvent.Context; -import net.minecraftforge.network.PacketDistributor; - -public class ClientMotionPacket extends SimplePacketBase { - - private Vec3 motion; - private boolean onGround; - private float limbSwing; - - public ClientMotionPacket(Vec3 motion, boolean onGround, float limbSwing) { - this.motion = motion; - this.onGround = onGround; - this.limbSwing = limbSwing; - } - - public ClientMotionPacket(FriendlyByteBuf buffer) { - motion = new Vec3(buffer.readFloat(), buffer.readFloat(), buffer.readFloat()); - onGround = buffer.readBoolean(); - limbSwing = buffer.readFloat(); - } - - @Override - public void write(FriendlyByteBuf buffer) { - buffer.writeFloat((float) motion.x); - buffer.writeFloat((float) motion.y); - buffer.writeFloat((float) motion.z); - buffer.writeBoolean(onGround); - buffer.writeFloat(limbSwing); - } - - @Override - public void handle(Supplier context) { - context.get() - .enqueueWork(() -> { - ServerPlayer sender = context.get() - .getSender(); - if (sender == null) - return; - sender.setDeltaMovement(motion); - sender.setOnGround(onGround); - if (onGround) { - sender.causeFallDamage(sender.fallDistance, 1, DamageSource.FALL); - sender.fallDistance = 0; - sender.connection.aboveGroundTickCount = 0; - sender.connection.aboveGroundVehicleTickCount = 0; - } - AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> sender), - new LimbSwingUpdatePacket(sender.getId(), sender.position(), limbSwing)); - }); - context.get() - .setPacketHandled(true); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/ContraptionFluidPacket.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/ContraptionFluidPacket.java deleted file mode 100644 index 5624adc33..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/ContraptionFluidPacket.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.sync; - -import java.util.function.Supplier; - -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; -import com.simibubi.create.foundation.networking.SimplePacketBase; - -import net.minecraft.client.Minecraft; -import net.minecraft.core.BlockPos; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.entity.Entity; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.network.NetworkEvent.Context; - -public class ContraptionFluidPacket extends SimplePacketBase { - - private int entityId; - private BlockPos localPos; - private FluidStack containedFluid; - - public ContraptionFluidPacket(int entityId, BlockPos localPos, FluidStack containedFluid) { - this.entityId = entityId; - this.localPos = localPos; - this.containedFluid = containedFluid; - } - - public ContraptionFluidPacket(FriendlyByteBuf buffer) { - entityId = buffer.readInt(); - localPos = buffer.readBlockPos(); - containedFluid = FluidStack.readFromPacket(buffer); - } - - @Override - public void write(FriendlyByteBuf buffer) { - buffer.writeInt(entityId); - buffer.writeBlockPos(localPos); - containedFluid.writeToPacket(buffer); - } - - @Override - public void handle(Supplier context) { - context.get() - .enqueueWork(() -> { - Entity entityByID = Minecraft.getInstance().level.getEntity(entityId); - if (!(entityByID instanceof AbstractContraptionEntity)) - return; - AbstractContraptionEntity contraptionEntity = (AbstractContraptionEntity) entityByID; - contraptionEntity.getContraption().handleContraptionFluidPacket(localPos, containedFluid); - }); - context.get() - .setPacketHandled(true); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/ContraptionSeatMappingPacket.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/ContraptionSeatMappingPacket.java deleted file mode 100644 index ac2582af3..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/ContraptionSeatMappingPacket.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.sync; - -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; -import java.util.function.Supplier; - -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; -import com.simibubi.create.foundation.networking.SimplePacketBase; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.client.Minecraft; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.network.NetworkEvent.Context; - -public class ContraptionSeatMappingPacket extends SimplePacketBase { - - private Map mapping; - private int entityID; - private int dismountedID; - - public ContraptionSeatMappingPacket(int entityID, Map mapping) { - this(entityID, mapping, -1); - } - - public ContraptionSeatMappingPacket(int entityID, Map mapping, int dismountedID) { - this.entityID = entityID; - this.mapping = mapping; - this.dismountedID = dismountedID; - } - - public ContraptionSeatMappingPacket(FriendlyByteBuf buffer) { - entityID = buffer.readInt(); - dismountedID = buffer.readInt(); - mapping = new HashMap<>(); - short size = buffer.readShort(); - for (int i = 0; i < size; i++) - mapping.put(buffer.readUUID(), (int) buffer.readShort()); - } - - @Override - public void write(FriendlyByteBuf buffer) { - buffer.writeInt(entityID); - buffer.writeInt(dismountedID); - buffer.writeShort(mapping.size()); - mapping.forEach((k, v) -> { - buffer.writeUUID(k); - buffer.writeShort(v); - }); - } - - @Override - public void handle(Supplier context) { - context.get() - .enqueueWork(() -> { - Entity entityByID = Minecraft.getInstance().level.getEntity(entityID); - if (!(entityByID instanceof AbstractContraptionEntity)) - return; - AbstractContraptionEntity contraptionEntity = (AbstractContraptionEntity) entityByID; - - if (dismountedID != -1) { - Entity dismountedByID = Minecraft.getInstance().level.getEntity(dismountedID); - if (Minecraft.getInstance().player != dismountedByID) - return; - Vec3 transformedVector = contraptionEntity.getPassengerPosition(dismountedByID, 1); - if (transformedVector != null) - dismountedByID.getPersistentData() - .put("ContraptionDismountLocation", VecHelper.writeNBT(transformedVector)); - } - - contraptionEntity.getContraption() - .setSeatMapping(mapping); - }); - context.get() - .setPacketHandled(true); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/LimbSwingUpdatePacket.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/LimbSwingUpdatePacket.java deleted file mode 100644 index 5d0bdfd38..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/LimbSwingUpdatePacket.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.sync; - -import java.util.function.Supplier; - -import com.simibubi.create.foundation.networking.SimplePacketBase; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.network.NetworkEvent.Context; - -public class LimbSwingUpdatePacket extends SimplePacketBase { - - private int entityId; - private Vec3 position; - private float limbSwing; - - public LimbSwingUpdatePacket(int entityId, Vec3 position, float limbSwing) { - this.entityId = entityId; - this.position = position; - this.limbSwing = limbSwing; - } - - public LimbSwingUpdatePacket(FriendlyByteBuf buffer) { - entityId = buffer.readInt(); - position = new Vec3(buffer.readDouble(), buffer.readDouble(), buffer.readDouble()); - limbSwing = buffer.readFloat(); - } - - @Override - public void write(FriendlyByteBuf buffer) { - buffer.writeInt(entityId); - buffer.writeDouble(position.x); - buffer.writeDouble(position.y); - buffer.writeDouble(position.z); - buffer.writeFloat(limbSwing); - } - - @Override - public void handle(Supplier context) { - context.get() - .enqueueWork(() -> { - ClientLevel world = Minecraft.getInstance().level; - if (world == null) - return; - Entity entity = world.getEntity(entityId); - if (entity == null) - return; - CompoundTag data = entity.getPersistentData(); - data.putInt("LastOverrideLimbSwingUpdate", 0); - data.putFloat("OverrideLimbSwing", limbSwing); - entity.lerpTo(position.x, position.y, position.z, entity.getYRot(), - entity.getXRot(), 2, false); - }); - context.get() - .setPacketHandled(true); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingCreationPacket.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingCreationPacket.java deleted file mode 100644 index 7fbaf3479..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingCreationPacket.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.train; - -import java.util.function.Supplier; - -import com.simibubi.create.foundation.networking.SimplePacketBase; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.vehicle.AbstractMinecart; -import net.minecraftforge.network.NetworkEvent.Context; - -public class CouplingCreationPacket extends SimplePacketBase { - - int id1, id2; - - public CouplingCreationPacket(AbstractMinecart cart1, AbstractMinecart cart2) { - id1 = cart1.getId(); - id2 = cart2.getId(); - } - - public CouplingCreationPacket(FriendlyByteBuf buffer) { - id1 = buffer.readInt(); - id2 = buffer.readInt(); - } - - @Override - public void write(FriendlyByteBuf buffer) { - buffer.writeInt(id1); - buffer.writeInt(id2); - } - - @Override - public void handle(Supplier context) { - context.get() - .enqueueWork(() -> { - ServerPlayer sender = context.get() - .getSender(); - if (sender != null) - CouplingHandler.tryToCoupleCarts(sender, sender.level, id1, id2); - }); - context.get() - .setPacketHandled(true); - } - -} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingRenderer.java deleted file mode 100644 index 0841bdc79..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingRenderer.java +++ /dev/null @@ -1,242 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.train; - -import static net.minecraft.util.Mth.lerp; - -import com.jozufozu.flywheel.util.transform.TransformStack; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import com.mojang.math.Axis; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.CreateClient; -import com.simibubi.create.content.contraptions.KineticDebugger; -import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.MinecartController; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.Color; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.renderer.LevelRenderer; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.util.Mth; -import net.minecraft.world.entity.vehicle.AbstractMinecart; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; - -public class CouplingRenderer { - - public static void renderAll(PoseStack ms, MultiBufferSource buffer) { - CouplingHandler.forEachLoadedCoupling(Minecraft.getInstance().level, - c -> { - if (c.getFirst().hasContraptionCoupling(true)) - return; - CouplingRenderer.renderCoupling(ms, buffer, c.map(MinecartController::cart)); - }); - } - - public static void tickDebugModeRenders() { - if (KineticDebugger.isActive()) - CouplingHandler.forEachLoadedCoupling(Minecraft.getInstance().level, CouplingRenderer::doDebugRender); - } - - public static void renderCoupling(PoseStack ms, MultiBufferSource buffer, Couple carts) { - ClientLevel world = Minecraft.getInstance().level; - - if (carts.getFirst() == null || carts.getSecond() == null) - return; - - Couple lightValues = - carts.map(c -> LevelRenderer.getLightColor(world, new BlockPos(c.getBoundingBox() - .getCenter()))); - - Vec3 center = carts.getFirst() - .position() - .add(carts.getSecond() - .position()) - .scale(.5f); - - Couple transforms = carts.map(c -> getSuitableCartEndpoint(c, center)); - - BlockState renderState = Blocks.AIR.defaultBlockState(); - VertexConsumer builder = buffer.getBuffer(RenderType.solid()); - SuperByteBuffer attachment = CachedBufferer.partial(AllBlockPartials.COUPLING_ATTACHMENT, renderState); - SuperByteBuffer ring = CachedBufferer.partial(AllBlockPartials.COUPLING_RING, renderState); - SuperByteBuffer connector = CachedBufferer.partial(AllBlockPartials.COUPLING_CONNECTOR, renderState); - - Vec3 zero = Vec3.ZERO; - Vec3 firstEndpoint = transforms.getFirst() - .apply(zero); - Vec3 secondEndpoint = transforms.getSecond() - .apply(zero); - Vec3 endPointDiff = secondEndpoint.subtract(firstEndpoint); - double connectorYaw = -Math.atan2(endPointDiff.z, endPointDiff.x) * 180.0D / Math.PI; - double connectorPitch = Math.atan2(endPointDiff.y, endPointDiff.multiply(1, 0, 1) - .length()) * 180 / Math.PI; - - TransformStack msr = TransformStack.cast(ms); - carts.forEachWithContext((cart, isFirst) -> { - CartEndpoint cartTransform = transforms.get(isFirst); - - ms.pushPose(); - cartTransform.apply(ms); - attachment.light(lightValues.get(isFirst)) - .renderInto(ms, builder); - msr.rotateY(connectorYaw - cartTransform.yaw); - ring.light(lightValues.get(isFirst)) - .renderInto(ms, builder); - ms.popPose(); - }); - - int l1 = lightValues.getFirst(); - int l2 = lightValues.getSecond(); - int meanBlockLight = (((l1 >> 4) & 0xf) + ((l2 >> 4) & 0xf)) / 2; - int meanSkyLight = (((l1 >> 20) & 0xf) + ((l2 >> 20) & 0xf)) / 2; - - ms.pushPose(); - msr.translate(firstEndpoint) - .rotateY(connectorYaw) - .rotateZ(connectorPitch); - ms.scale((float) endPointDiff.length(), 1, 1); - - connector.light(meanSkyLight << 20 | meanBlockLight << 4) - .renderInto(ms, builder); - ms.popPose(); - } - - private static CartEndpoint getSuitableCartEndpoint(AbstractMinecart cart, Vec3 centerOfCoupling) { - long i = cart.getId() * 493286711L; - i = i * i * 4392167121L + i * 98761L; - float x = (((float) (i >> 16 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F; - float y = (((float) (i >> 20 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F + 0.375F; - float z = (((float) (i >> 24 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F; - - float pt = AnimationTickHolder.getPartialTicks(); - - double xIn = lerp(pt, cart.xOld, cart.getX()); - double yIn = lerp(pt, cart.yOld, cart.getY()); - double zIn = lerp(pt, cart.zOld, cart.getZ()); - - float yaw = lerp(pt, cart.yRotO, cart.getYRot()); - float pitch = lerp(pt, cart.xRotO, cart.getXRot()); - float roll = cart.getHurtTime() - pt; - - float rollAmplifier = cart.getDamage() - pt; - if (rollAmplifier < 0.0F) - rollAmplifier = 0.0F; - roll = roll > 0 ? Mth.sin(roll) * roll * rollAmplifier / 10.0F * cart.getHurtDir() : 0; - - Vec3 positionVec = new Vec3(xIn, yIn, zIn); - Vec3 frontVec = positionVec.add(VecHelper.rotate(new Vec3(.5, 0, 0), 180 - yaw, Direction.Axis.Y)); - Vec3 backVec = positionVec.add(VecHelper.rotate(new Vec3(-.5, 0, 0), 180 - yaw, Direction.Axis.Y)); - - Vec3 railVecOfPos = cart.getPos(xIn, yIn, zIn); - boolean flip = false; - - if (railVecOfPos != null) { - frontVec = cart.getPosOffs(xIn, yIn, zIn, (double) 0.3F); - backVec = cart.getPosOffs(xIn, yIn, zIn, (double) -0.3F); - if (frontVec == null) - frontVec = railVecOfPos; - if (backVec == null) - backVec = railVecOfPos; - - x += railVecOfPos.x; - y += (frontVec.y + backVec.y) / 2; - z += railVecOfPos.z; - - Vec3 endPointDiff = backVec.add(-frontVec.x, -frontVec.y, -frontVec.z); - if (endPointDiff.length() != 0.0D) { - endPointDiff = endPointDiff.normalize(); - yaw = (float) (Math.atan2(endPointDiff.z, endPointDiff.x) * 180.0D / Math.PI); - pitch = (float) (Math.atan(endPointDiff.y) * 73.0D); - } - } else { - x += xIn; - y += yIn; - z += zIn; - } - - final float offsetMagnitude = 13 / 16f; - boolean isBackFaceCloser = - frontVec.distanceToSqr(centerOfCoupling) > backVec.distanceToSqr(centerOfCoupling); - flip = isBackFaceCloser; - float offset = isBackFaceCloser ? -offsetMagnitude : offsetMagnitude; - - return new CartEndpoint(x, y + 2 / 16f, z, 180 - yaw, -pitch, roll, offset, flip); - } - - static class CartEndpoint { - - float x; - float y; - float z; - float yaw; - float pitch; - float roll; - float offset; - boolean flip; - - public CartEndpoint(float x, float y, float z, float yaw, float pitch, float roll, float offset, boolean flip) { - this.x = x; - this.y = y; - this.z = z; - this.yaw = yaw; - this.pitch = pitch; - this.roll = roll; - this.offset = offset; - this.flip = flip; - } - - public Vec3 apply(Vec3 vec) { - vec = vec.add(offset, 0, 0); - vec = VecHelper.rotate(vec, roll, Direction.Axis.X); - vec = VecHelper.rotate(vec, pitch, Direction.Axis.Z); - vec = VecHelper.rotate(vec, yaw, Direction.Axis.Y); - return vec.add(x, y, z); - } - - public void apply(PoseStack ms) { - ms.translate(x, y, z); - ms.mulPose(Axis.YP.rotationDegrees(yaw)); - ms.mulPose(Axis.ZP.rotationDegrees(pitch)); - ms.mulPose(Axis.XP.rotationDegrees(roll)); - ms.translate(offset, 0, 0); - if (flip) - ms.mulPose(Axis.YP.rotationDegrees(180)); - } - - } - - public static void doDebugRender(Couple c) { - int yOffset = 1; - MinecartController first = c.getFirst(); - AbstractMinecart mainCart = first.cart(); - Vec3 mainCenter = mainCart.position() - .add(0, yOffset, 0); - Vec3 connectedCenter = c.getSecond() - .cart() - .position() - .add(0, yOffset, 0); - - int color = Color.mixColors(0xabf0e9, 0xee8572, (float) Mth - .clamp(Math.abs(first.getCouplingLength(true) - connectedCenter.distanceTo(mainCenter)) * 8, 0, 1)); - - CreateClient.OUTLINER.showLine(mainCart.getId() + "", mainCenter, connectedCenter) - .colored(color) - .lineWidth(1 / 8f); - - Vec3 point = mainCart.position() - .add(0, yOffset, 0); - CreateClient.OUTLINER.showLine(mainCart.getId() + "_dot", point, point.add(0, 1 / 128f, 0)) - .colored(0xffffff) - .lineWidth(1 / 4f); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/turntable/TurntableTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/turntable/TurntableTileEntity.java deleted file mode 100644 index eae84a2da..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/turntable/TurntableTileEntity.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.simibubi.create.content.contraptions.components.turntable; - -import com.simibubi.create.content.contraptions.base.KineticTileEntity; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; - -public class TurntableTileEntity extends KineticTileEntity { - - public TurntableTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/waterwheel/WaterWheelBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/waterwheel/WaterWheelBlock.java deleted file mode 100644 index 058dab2d9..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/waterwheel/WaterWheelBlock.java +++ /dev/null @@ -1,225 +0,0 @@ -package com.simibubi.create.content.contraptions.components.waterwheel; - -import javax.annotation.ParametersAreNonnullByDefault; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock; -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.block.ITE; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.fluid.FluidHelper; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld; - -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.core.Direction.AxisDirection; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.BubbleColumnBlock; -import net.minecraft.world.level.block.RenderShape; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.FluidState; -import net.minecraft.world.phys.Vec3; - -@ParametersAreNonnullByDefault -@MethodsReturnNonnullByDefault -public class WaterWheelBlock extends DirectionalKineticBlock implements ITE { - - public WaterWheelBlock(Properties properties) { - super(properties); - } - - @Override - public RenderShape getRenderShape(BlockState state) { - return RenderShape.ENTITYBLOCK_ANIMATED; - } - - @Override - public boolean canSurvive(BlockState state, LevelReader worldIn, BlockPos pos) { - for (Direction direction : Iterate.directions) { - BlockPos neighbourPos = pos.relative(direction); - BlockState neighbourState = worldIn.getBlockState(neighbourPos); - if (!AllBlocks.WATER_WHEEL.has(neighbourState)) - continue; - if (neighbourState.getValue(FACING) - .getAxis() != state.getValue(FACING) - .getAxis() - || state.getValue(FACING) - .getAxis() != direction.getAxis()) - return false; - } - - return true; - } - - @Override - public BlockState updateShape(BlockState stateIn, Direction facing, BlockState facingState, LevelAccessor worldIn, - BlockPos currentPos, BlockPos facingPos) { - if (worldIn instanceof WrappedWorld) - return stateIn; - updateFlowAt(stateIn, worldIn, currentPos, facing); - updateWheelSpeed(worldIn, currentPos); - return stateIn; - } - - @Override - public void onPlace(BlockState state, Level worldIn, BlockPos pos, BlockState oldState, boolean isMoving) { - super.onPlace(state, worldIn, pos, oldState, isMoving); - updateAllSides(state, worldIn, pos); - } - - public void updateAllSides(BlockState state, Level worldIn, BlockPos pos) { - for (Direction d : Iterate.directions) - updateFlowAt(state, worldIn, pos, d); - updateWheelSpeed(worldIn, pos); - } - - private void updateFlowAt(BlockState state, LevelAccessor world, BlockPos pos, Direction side) { - if (side.getAxis() == state.getValue(FACING) - .getAxis()) - return; - - FluidState fluid = world.getFluidState(pos.relative(side)); - Direction wf = state.getValue(FACING); - boolean clockwise = wf.getAxisDirection() == AxisDirection.POSITIVE; - int clockwiseMultiplier = 2; - - Vec3 vec = fluid.getFlow(world, pos.relative(side)); - if (side.getAxis() - .isHorizontal()) { - BlockState adjacentBlock = world.getBlockState(pos.relative(side)); - if (adjacentBlock.getBlock() == Blocks.BUBBLE_COLUMN) - vec = new Vec3(0, adjacentBlock.getValue(BubbleColumnBlock.DRAG_DOWN) ? -1 : 1, 0); - } - - vec = vec.scale(side.getAxisDirection() - .getStep()); - vec = new Vec3(Math.signum(vec.x), Math.signum(vec.y), Math.signum(vec.z)); - Vec3 flow = vec; - - withTileEntityDo(world, pos, te -> { - double flowStrength = 0; - - if (wf.getAxis() == Axis.Z) { - if (side.getAxis() == Axis.Y) - flowStrength = flow.x > 0 ^ !clockwise ? -flow.x * clockwiseMultiplier : -flow.x; - if (side.getAxis() == Axis.X) - flowStrength = flow.y < 0 ^ !clockwise ? flow.y * clockwiseMultiplier : flow.y; - } - - if (wf.getAxis() == Axis.X) { - if (side.getAxis() == Axis.Y) - flowStrength = flow.z < 0 ^ !clockwise ? flow.z * clockwiseMultiplier : flow.z; - if (side.getAxis() == Axis.Z) - flowStrength = flow.y > 0 ^ !clockwise ? -flow.y * clockwiseMultiplier : -flow.y; - } - - if (wf.getAxis() == Axis.Y) { - if (side.getAxis() == Axis.Z) - flowStrength = flow.x < 0 ^ !clockwise ? flow.x * clockwiseMultiplier : flow.x; - if (side.getAxis() == Axis.X) - flowStrength = flow.z > 0 ^ !clockwise ? -flow.z * clockwiseMultiplier : -flow.z; - } - - if (te.getSpeed() == 0 && flowStrength != 0 && !world.isClientSide()) - te.award( - FluidHelper.isLava(fluid.getType()) ? AllAdvancements.LAVA_WHEEL : AllAdvancements.WATER_WHEEL); - - Integer flowModifier = AllConfigs.SERVER.kinetics.waterWheelFlowSpeed.get(); - te.setFlow(side, (float) (flowStrength * flowModifier / 2f)); - }); - } - - private void updateWheelSpeed(LevelAccessor world, BlockPos pos) { - withTileEntityDo(world, pos, WaterWheelTileEntity::updateGeneratedRotation); - } - - @Override - public BlockState getStateForPlacement(BlockPlaceContext context) { - Direction face = context.getClickedFace(); - Direction horizontalFacing = context.getHorizontalDirection(); - BlockPos pos = context.getClickedPos(); - Level world = context.getLevel(); - Player player = context.getPlayer(); - - BlockState placedOn = world.getBlockState(pos.relative(face.getOpposite())); - if (AllBlocks.WATER_WHEEL.has(placedOn)) - return defaultBlockState().setValue(FACING, placedOn.getValue(FACING)); - - Direction facing = face; - boolean sneaking = player != null && player.isShiftKeyDown(); - if (player != null) { - - Vec3 lookVec = player.getLookAngle(); - double tolerance = 0.985; - - if (!canSurvive(defaultBlockState().setValue(FACING, Direction.UP), world, pos)) - facing = horizontalFacing; - else if (Vec3.atLowerCornerOf(Direction.DOWN.getNormal()) - .dot(lookVec.normalize()) > tolerance) - facing = Direction.DOWN; - else if (Vec3.atLowerCornerOf(Direction.UP.getNormal()) - .dot(lookVec.normalize()) > tolerance) - facing = Direction.UP; - else - facing = horizontalFacing; - - } - - return defaultBlockState().setValue(FACING, sneaking ? facing.getOpposite() : facing); - } - - @Override - public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) { - return state.getValue(FACING) - .getAxis() == face.getAxis(); - } - - @Override - public Axis getRotationAxis(BlockState state) { - return state.getValue(FACING) - .getAxis(); - } - - @Override - public float getParticleTargetRadius() { - return 1.125f; - } - - @Override - public float getParticleInitialRadius() { - return 1f; - } - - @Override - public boolean hideStressImpact() { - return true; - } - - @Override - public Class getTileEntityClass() { - return WaterWheelTileEntity.class; - } - - @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.WATER_WHEEL.get(); - } - - public static Couple getSpeedRange() { - Integer base = AllConfigs.SERVER.kinetics.waterWheelBaseSpeed.get(); - Integer flow = AllConfigs.SERVER.kinetics.waterWheelFlowSpeed.get(); - return Couple.create(base, base + 4 * flow); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/waterwheel/WaterWheelTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/waterwheel/WaterWheelTileEntity.java deleted file mode 100644 index 07aa48bec..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/waterwheel/WaterWheelTileEntity.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.simibubi.create.content.contraptions.components.waterwheel; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.base.GeneratingKineticTileEntity; -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.utility.Iterate; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.AABB; - -public class WaterWheelTileEntity extends GeneratingKineticTileEntity { - - private Map flows; - - public WaterWheelTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - flows = new HashMap<>(); - for (Direction d : Iterate.directions) - setFlow(d, 0); - setLazyTickRate(20); - } - - @Override - public void addBehaviours(List behaviours) { - super.addBehaviours(behaviours); - registerAwardables(behaviours, AllAdvancements.LAVA_WHEEL, AllAdvancements.WATER_WHEEL); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - super.read(compound, clientPacket); - if (compound.contains("Flows")) { - for (Direction d : Iterate.directions) - setFlow(d, compound.getCompound("Flows") - .getFloat(d.getSerializedName())); - } - } - - @Override - protected AABB createRenderBoundingBox() { - return new AABB(worldPosition).inflate(1); - } - - @Override - public void write(CompoundTag compound, boolean clientPacket) { - CompoundTag flows = new CompoundTag(); - for (Direction d : Iterate.directions) - flows.putFloat(d.getSerializedName(), this.flows.get(d)); - compound.put("Flows", flows); - - super.write(compound, clientPacket); - } - - public void setFlow(Direction direction, float speed) { - flows.put(direction, speed); - setChanged(); - } - - @Override - public float getGeneratedSpeed() { - float speed = 0; - for (Float f : flows.values()) - speed += f; - if (speed != 0) - speed += AllConfigs.SERVER.kinetics.waterWheelBaseSpeed.get() * Math.signum(speed); - return speed; - } - - @Override - public void lazyTick() { - super.lazyTick(); - AllBlocks.WATER_WHEEL.get() - .updateAllSides(getBlockState(), level, worldPosition); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorColumn.java b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorColumn.java new file mode 100644 index 000000000..348c2f23e --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorColumn.java @@ -0,0 +1,226 @@ +package com.simibubi.create.content.contraptions.elevator; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import javax.annotation.Nullable; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.foundation.utility.BlockHelper; +import com.simibubi.create.foundation.utility.Couple; +import com.simibubi.create.foundation.utility.IntAttached; +import com.simibubi.create.foundation.utility.NBTHelper; +import com.simibubi.create.foundation.utility.WorldAttached; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.entity.BlockEntity; + +public class ElevatorColumn { + + public static WorldAttached> LOADED_COLUMNS = + new WorldAttached<>($ -> new HashMap<>()); + + protected LevelAccessor level; + protected ColumnCoords coords; + protected List contacts; + protected int targetedYLevel; + protected boolean isActive; + + @Nullable + public static ElevatorColumn get(LevelAccessor level, ColumnCoords coords) { + return LOADED_COLUMNS.get(level) + .get(coords); + } + + public static ElevatorColumn getOrCreate(LevelAccessor level, ColumnCoords coords) { + return LOADED_COLUMNS.get(level) + .computeIfAbsent(coords, c -> new ElevatorColumn(level, c)); + } + + public ElevatorColumn(LevelAccessor level, ColumnCoords coords) { + this.level = level; + this.coords = coords; + contacts = new ArrayList<>(); + } + + public void markDirty() { + for (BlockPos pos : getContacts()) { + BlockEntity blockEntity = level.getBlockEntity(pos); + if (blockEntity instanceof ElevatorContactBlockEntity ecbe) + ecbe.setChanged(); + } + } + + public void floorReached(LevelAccessor level, String name) { + getContacts().stream() + .forEach(p -> { + if (level.getBlockEntity(p) instanceof ElevatorContactBlockEntity ecbe) + ecbe.updateDisplayedFloor(name); + }); + } + + public int namesListVersion; + + public List>> compileNamesList() { + return getContacts().stream() + .map(p -> { + if (level.getBlockEntity(p) instanceof ElevatorContactBlockEntity ecbe) + return IntAttached.with(p.getY(), ecbe.getNames()); + return null; + }) + .filter(Objects::nonNull) + .toList(); + } + + public void namesChanged() { + namesListVersion++; + } + + public Collection getContacts() { + return contacts.stream() + .map(this::contactAt) + .toList(); + } + + public void gatherAll() { + BlockPos.betweenClosedStream(contactAt(level.getMinBuildHeight()), contactAt(level.getMaxBuildHeight())) + .filter(p -> coords.equals(ElevatorContactBlock.getColumnCoords(level, p))) + .forEach(p -> level.setBlock(p, + BlockHelper.copyProperties(level.getBlockState(p), AllBlocks.ELEVATOR_CONTACT.getDefaultState()), 3)); + } + + public BlockPos contactAt(int y) { + return new BlockPos(coords.x, y, coords.z); + } + + public void setActive(boolean isActive) { + this.isActive = isActive; + markDirty(); + checkEmpty(); + } + + public boolean isActive() { + return isActive; + } + + public void target(int yLevel) { + targetedYLevel = yLevel; + } + + public int getTargetedYLevel() { + return targetedYLevel; + } + + public void initNames(Level level) { + Integer prevLevel = null; + + for (int i = 0; i < contacts.size(); i++) { + Integer y = contacts.get(i); + + BlockPos pos = contactAt(y); + if (!(level.getBlockEntity(pos) instanceof ElevatorContactBlockEntity ecbe)) + continue; + + Integer currentLevel = null; + + if (!ecbe.shortName.isBlank()) { + Integer tryValueOf = tryValueOf(ecbe.shortName); + if (tryValueOf != null) + currentLevel = tryValueOf; + if (currentLevel == null) + continue; + } + + if (prevLevel != null) + currentLevel = prevLevel + 1; + + Integer nextLevel = null; + + for (int peekI = i + 1; peekI < contacts.size(); peekI++) { + BlockPos peekPos = contactAt(contacts.get(peekI)); + if (!(level.getBlockEntity(peekPos) instanceof ElevatorContactBlockEntity peekEcbe)) + continue; + Integer tryValueOf = tryValueOf(peekEcbe.shortName); + if (tryValueOf == null) + continue; + if (currentLevel != null && currentLevel >= tryValueOf) { + peekEcbe.shortName = ""; + break; + } + nextLevel = tryValueOf; + break; + } + + if (currentLevel == null) + currentLevel = nextLevel != null ? nextLevel - 1 : 0; + + ecbe.updateName(String.valueOf(currentLevel), ecbe.longName); + prevLevel = currentLevel; + } + + } + + private static Integer tryValueOf(String floorName) { + try { + return Integer.valueOf(floorName, 10); + } catch (NumberFormatException nfe) { + return null; + } + } + + public void add(BlockPos contactPos) { + int coord = contactPos.getY(); + if (contacts.contains(coord)) + return; + int index = 0; + for (; index < contacts.size(); index++) + if (contacts.get(index) > coord) + break; + contacts.add(index, coord); + namesChanged(); + } + + public void remove(BlockPos contactPos) { + contacts.remove((Object) contactPos.getY()); + checkEmpty(); + namesChanged(); + } + + private void checkEmpty() { + if (contacts.isEmpty() && !isActive()) + LOADED_COLUMNS.get(level) + .remove(coords); + } + + public static record ColumnCoords(int x, int z, Direction side) { + + public ColumnCoords relative(BlockPos anchor) { + return new ColumnCoords(x + anchor.getX(), z + anchor.getZ(), side); + } + + public CompoundTag write() { + CompoundTag tag = new CompoundTag(); + tag.putInt("X", x); + tag.putInt("Z", z); + NBTHelper.writeEnum(tag, "Side", side); + return tag; + } + + public static ColumnCoords read(CompoundTag tag) { + int x = tag.getInt("X"); + int z = tag.getInt("Z"); + Direction side = NBTHelper.readEnum(tag, "Side", Direction.class); + return new ColumnCoords(x, z, side); + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorContactBlock.java b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorContactBlock.java new file mode 100644 index 000000000..875a4a893 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorContactBlock.java @@ -0,0 +1,251 @@ +package com.simibubi.create.content.contraptions.elevator; + +import java.util.Optional; + +import javax.annotation.Nullable; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllItems; +import com.simibubi.create.content.contraptions.elevator.ElevatorColumn.ColumnCoords; +import com.simibubi.create.content.redstone.contact.RedstoneContactBlock; +import com.simibubi.create.content.redstone.diodes.BrassDiodeBlock; +import com.simibubi.create.content.schematics.requirement.ISpecialBlockItemRequirement; +import com.simibubi.create.content.schematics.requirement.ItemRequirement; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.block.WrenchableDirectionalBlock; +import com.simibubi.create.foundation.gui.ScreenOpener; +import com.simibubi.create.foundation.utility.BlockHelper; + +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.NonNullList; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.CreativeModeTab; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.UseOnContext; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition.Builder; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.fml.DistExecutor; + +public class ElevatorContactBlock extends WrenchableDirectionalBlock + implements IBE, ISpecialBlockItemRequirement { + + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; + public static final BooleanProperty CALLING = BooleanProperty.create("calling"); + public static final BooleanProperty POWERING = BrassDiodeBlock.POWERING; + + public ElevatorContactBlock(Properties pProperties) { + super(pProperties); + registerDefaultState(defaultBlockState().setValue(CALLING, false) + .setValue(POWERING, false) + .setValue(POWERED, false) + .setValue(FACING, Direction.SOUTH)); + } + + @Override + protected void createBlockStateDefinition(Builder builder) { + super.createBlockStateDefinition(builder.add(CALLING, POWERING, POWERED)); + } + + @Override + public InteractionResult onWrenched(BlockState state, UseOnContext context) { + InteractionResult onWrenched = super.onWrenched(state, context); + if (onWrenched != InteractionResult.SUCCESS) + return onWrenched; + + Level level = context.getLevel(); + if (level.isClientSide()) + return onWrenched; + + BlockPos pos = context.getClickedPos(); + state = level.getBlockState(pos); + Direction facing = state.getValue(RedstoneContactBlock.FACING); + if (facing.getAxis() != Axis.Y + && ElevatorColumn.get(level, new ColumnCoords(pos.getX(), pos.getZ(), facing)) != null) + return onWrenched; + + level.setBlockAndUpdate(pos, BlockHelper.copyProperties(state, AllBlocks.REDSTONE_CONTACT.getDefaultState())); + + return onWrenched; + } + + @Nullable + public static ColumnCoords getColumnCoords(LevelAccessor level, BlockPos pos) { + BlockState blockState = level.getBlockState(pos); + if (!AllBlocks.ELEVATOR_CONTACT.has(blockState) && !AllBlocks.REDSTONE_CONTACT.has(blockState)) + return null; + Direction facing = blockState.getValue(FACING); + BlockPos target = pos; + return new ColumnCoords(target.getX(), target.getZ(), facing); + } + + @Override + public void neighborChanged(BlockState pState, Level pLevel, BlockPos pPos, Block pBlock, BlockPos pFromPos, + boolean pIsMoving) { + if (pLevel.isClientSide) + return; + + boolean isPowered = pState.getValue(POWERED); + if (isPowered == pLevel.hasNeighborSignal(pPos)) + return; + + pLevel.setBlock(pPos, pState.cycle(POWERED), 2); + + if (isPowered) + return; + if (pState.getValue(CALLING)) + return; + + ElevatorColumn elevatorColumn = ElevatorColumn.getOrCreate(pLevel, getColumnCoords(pLevel, pPos)); + callToContactAndUpdate(elevatorColumn, pState, pLevel, pPos, true); + } + + public void callToContactAndUpdate(ElevatorColumn elevatorColumn, BlockState pState, Level pLevel, BlockPos pPos, + boolean powered) { + pLevel.setBlock(pPos, pState.cycle(CALLING), 2); + + for (BlockPos otherPos : elevatorColumn.getContacts()) { + if (otherPos.equals(pPos)) + continue; + BlockState otherState = pLevel.getBlockState(otherPos); + if (!AllBlocks.ELEVATOR_CONTACT.has(otherState)) + continue; + pLevel.setBlock(otherPos, otherState.setValue(CALLING, false), 2 | 16); + scheduleActivation(pLevel, otherPos); + } + + if (powered) + pState = pState.setValue(POWERED, true); + pLevel.setBlock(pPos, pState.setValue(CALLING, true), 2); + pLevel.updateNeighborsAt(pPos, this); + + elevatorColumn.target(pPos.getY()); + elevatorColumn.markDirty(); + } + + public void scheduleActivation(LevelAccessor pLevel, BlockPos pPos) { + if (!pLevel.getBlockTicks() + .hasScheduledTick(pPos, this)) + pLevel.scheduleTick(pPos, this, 1); + } + + @Override + public void tick(BlockState pState, ServerLevel pLevel, BlockPos pPos, RandomSource pRand) { + boolean wasPowering = pState.getValue(POWERING); + + Optional optionalBE = getBlockEntityOptional(pLevel, pPos); + boolean shouldBePowering = optionalBE.map(be -> { + boolean activateBlock = be.activateBlock; + be.activateBlock = false; + be.setChanged(); + return activateBlock; + }) + .orElse(false); + + shouldBePowering |= RedstoneContactBlock.hasValidContact(pLevel, pPos, pState.getValue(FACING)); + + if (wasPowering || shouldBePowering) + pLevel.setBlock(pPos, pState.setValue(POWERING, shouldBePowering), 2 | 16); + + pLevel.updateNeighborsAt(pPos, this); + } + + @Override + public BlockState updateShape(BlockState stateIn, Direction facing, BlockState facingState, LevelAccessor worldIn, + BlockPos currentPos, BlockPos facingPos) { + if (facing != stateIn.getValue(FACING)) + return stateIn; + boolean hasValidContact = RedstoneContactBlock.hasValidContact(worldIn, currentPos, facing); + if (stateIn.getValue(POWERING) != hasValidContact) + scheduleActivation(worldIn, currentPos); + return stateIn; + } + + @Override + public boolean shouldCheckWeakPower(BlockState state, LevelReader level, BlockPos pos, Direction side) { + return false; + } + + @Override + public boolean isSignalSource(BlockState state) { + return state.getValue(POWERING); + } + + @Override + public ItemStack getCloneItemStack(BlockGetter pLevel, BlockPos pPos, BlockState pState) { + return AllBlocks.REDSTONE_CONTACT.asStack(); + } + + @Override + public boolean canConnectRedstone(BlockState state, BlockGetter world, BlockPos pos, @Nullable Direction side) { + if (side == null) + return true; + return state.getValue(FACING) != side.getOpposite(); + } + + @Override + public int getSignal(BlockState state, BlockGetter blockAccess, BlockPos pos, Direction side) { + if (side == null) + return 0; + BlockState toState = blockAccess.getBlockState(pos.relative(side.getOpposite())); + if (toState.is(this)) + return 0; + return state.getValue(POWERING) ? 15 : 0; + } + + @Override + public Class getBlockEntityClass() { + return ElevatorContactBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.ELEVATOR_CONTACT.get(); + } + + @Override + public ItemRequirement getRequiredItems(BlockState state, BlockEntity be) { + return ItemRequirement.of(AllBlocks.REDSTONE_CONTACT.getDefaultState(), be); + } + + @Override + public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, + BlockHitResult hit) { + if (player != null && AllItems.WRENCH.isIn(player.getItemInHand(handIn))) + return InteractionResult.PASS; + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, + () -> () -> withBlockEntityDo(worldIn, pos, be -> this.displayScreen(be, player))); + return InteractionResult.SUCCESS; + } + + @OnlyIn(value = Dist.CLIENT) + protected void displayScreen(ElevatorContactBlockEntity be, Player player) { + if (player instanceof LocalPlayer) + ScreenOpener + .open(new ElevatorContactScreen(be.getBlockPos(), be.shortName, be.longName, be.doorControls.mode)); + } + + public static int getLight(BlockState state) { + return state.getValue(POWERING) ? 10 : 0; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorContactBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorContactBlockEntity.java new file mode 100644 index 000000000..8a3f09b27 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorContactBlockEntity.java @@ -0,0 +1,158 @@ +package com.simibubi.create.content.contraptions.elevator; + +import java.util.List; + +import com.simibubi.create.content.contraptions.elevator.ElevatorColumn.ColumnCoords; +import com.simibubi.create.content.decoration.slidingDoor.DoorControlBehaviour; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkBlock; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.Couple; +import com.simibubi.create.foundation.utility.NBTHelper; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; + +public class ElevatorContactBlockEntity extends SmartBlockEntity { + + public DoorControlBehaviour doorControls; + public ColumnCoords columnCoords; + public boolean activateBlock; + + public String shortName; + public String longName; + + public String lastReportedCurrentFloor; + + private int yTargetFromNBT = Integer.MIN_VALUE; + private boolean deferNameGenerator; + + public ElevatorContactBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + shortName = ""; + longName = ""; + deferNameGenerator = false; + } + + @Override + public void addBehaviours(List behaviours) { + behaviours.add(doorControls = new DoorControlBehaviour(this)); + } + + @Override + protected void write(CompoundTag tag, boolean clientPacket) { + super.write(tag, clientPacket); + + tag.putString("ShortName", shortName); + tag.putString("LongName", longName); + + if (lastReportedCurrentFloor != null) + tag.putString("LastReportedCurrentFloor", lastReportedCurrentFloor); + + if (clientPacket) + return; + tag.putBoolean("Activate", activateBlock); + if (columnCoords == null) + return; + + ElevatorColumn column = ElevatorColumn.get(level, columnCoords); + if (column == null) + return; + tag.putInt("ColumnTarget", column.getTargetedYLevel()); + if (column.isActive()) + NBTHelper.putMarker(tag, "ColumnActive"); + } + + @Override + protected void read(CompoundTag tag, boolean clientPacket) { + super.read(tag, clientPacket); + + shortName = tag.getString("ShortName"); + longName = tag.getString("LongName"); + + if (tag.contains("LastReportedCurrentFloor")) + lastReportedCurrentFloor = tag.getString("LastReportedCurrentFloor"); + + if (clientPacket) + return; + activateBlock = tag.getBoolean("Activate"); + if (!tag.contains("ColumnTarget")) + return; + + int target = tag.getInt("ColumnTarget"); + boolean active = tag.contains("ColumnActive"); + + if (columnCoords == null) { + yTargetFromNBT = target; + return; + } + + ElevatorColumn column = ElevatorColumn.getOrCreate(level, columnCoords); + column.target(target); + column.setActive(active); + } + + public void updateDisplayedFloor(String floor) { + if (floor.equals(lastReportedCurrentFloor)) + return; + lastReportedCurrentFloor = floor; + DisplayLinkBlock.notifyGatherers(level, worldPosition); + } + + @Override + public void initialize() { + super.initialize(); + if (level.isClientSide()) + return; + columnCoords = ElevatorContactBlock.getColumnCoords(level, worldPosition); + if (columnCoords == null) + return; + ElevatorColumn column = ElevatorColumn.getOrCreate(level, columnCoords); + column.add(worldPosition); + if (shortName.isBlank()) + deferNameGenerator = true; + if (yTargetFromNBT == Integer.MIN_VALUE) + return; + column.target(yTargetFromNBT); + yTargetFromNBT = Integer.MIN_VALUE; + } + + @Override + public void tick() { + super.tick(); + if (!deferNameGenerator) + return; + if (columnCoords != null) + ElevatorColumn.getOrCreate(level, columnCoords) + .initNames(level); + deferNameGenerator = false; + } + + @Override + public void invalidate() { + if (columnCoords != null) { + ElevatorColumn column = ElevatorColumn.get(level, columnCoords); + if (column != null) + column.remove(worldPosition); + } + super.invalidate(); + } + + public void updateName(String shortName, String longName) { + this.shortName = shortName; + this.longName = longName; + this.deferNameGenerator = false; + notifyUpdate(); + + ElevatorColumn column = ElevatorColumn.get(level, columnCoords); + if (column != null) + column.namesChanged(); + } + + public Couple getNames() { + return Couple.create(shortName, longName); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorContactEditPacket.java b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorContactEditPacket.java new file mode 100644 index 000000000..81d331d54 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorContactEditPacket.java @@ -0,0 +1,47 @@ +package com.simibubi.create.content.contraptions.elevator; + +import com.simibubi.create.content.decoration.slidingDoor.DoorControl; +import com.simibubi.create.foundation.networking.BlockEntityConfigurationPacket; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.util.Mth; + +public class ElevatorContactEditPacket extends BlockEntityConfigurationPacket { + + private String shortName; + private String longName; + private DoorControl doorControl; + + public ElevatorContactEditPacket(BlockPos pos, String shortName, String longName, DoorControl doorControl) { + super(pos); + this.shortName = shortName; + this.longName = longName; + this.doorControl = doorControl; + } + + public ElevatorContactEditPacket(FriendlyByteBuf buffer) { + super(buffer); + } + + @Override + protected void writeSettings(FriendlyByteBuf buffer) { + buffer.writeUtf(shortName, 4); + buffer.writeUtf(longName, 30); + buffer.writeVarInt(doorControl.ordinal()); + } + + @Override + protected void readSettings(FriendlyByteBuf buffer) { + shortName = buffer.readUtf(4); + longName = buffer.readUtf(30); + doorControl = DoorControl.values()[Mth.clamp(buffer.readVarInt(), 0, DoorControl.values().length)]; + } + + @Override + protected void applySettings(ElevatorContactBlockEntity be) { + be.updateName(shortName, longName); + be.doorControls.set(doorControl); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorContactScreen.java b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorContactScreen.java new file mode 100644 index 000000000..27e97d530 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorContactScreen.java @@ -0,0 +1,185 @@ +package com.simibubi.create.content.contraptions.elevator; + +import org.lwjgl.glfw.GLFW; + +import com.google.common.collect.ImmutableList; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPackets; +import com.simibubi.create.content.decoration.slidingDoor.DoorControl; +import com.simibubi.create.foundation.gui.AbstractSimiScreen; +import com.simibubi.create.foundation.gui.AllGuiTextures; +import com.simibubi.create.foundation.gui.AllIcons; +import com.simibubi.create.foundation.gui.element.GuiGameElement; +import com.simibubi.create.foundation.gui.widget.IconButton; +import com.simibubi.create.foundation.gui.widget.Label; +import com.simibubi.create.foundation.gui.widget.ScrollInput; +import com.simibubi.create.foundation.gui.widget.TooltipArea; +import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.Pair; + +import net.minecraft.ChatFormatting; +import net.minecraft.client.gui.components.EditBox; +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.util.FormattedCharSequence; + +public class ElevatorContactScreen extends AbstractSimiScreen { + + private AllGuiTextures background; + + private EditBox shortNameInput; + private EditBox longNameInput; + private IconButton confirm; + + private String shortName; + private String longName; + private DoorControl doorControl; + + private BlockPos pos; + + public ElevatorContactScreen(BlockPos pos, String prevShortName, String prevLongName, DoorControl prevDoorControl) { + super(Lang.translateDirect("elevator_contact.title")); + this.pos = pos; + this.doorControl = prevDoorControl; + background = AllGuiTextures.ELEVATOR_CONTACT; + this.shortName = prevShortName; + this.longName = prevLongName; + } + + @Override + public void init() { + setWindowSize(background.width + 30, background.height); + super.init(); + + int x = guiLeft; + int y = guiTop; + + confirm = new IconButton(x + 200, y + 58, AllIcons.I_CONFIRM); + confirm.withCallback(this::confirm); + addRenderableWidget(confirm); + + shortNameInput = editBox(33, 30, 4); + shortNameInput.setValue(shortName); + centerInput(x); + shortNameInput.setResponder(s -> { + shortName = s; + centerInput(x); + }); + shortNameInput.changeFocus(true); + setFocused(shortNameInput); + shortNameInput.setHighlightPos(0); + + longNameInput = editBox(63, 140, 30); + longNameInput.setValue(longName); + longNameInput.setResponder(s -> longName = s); + + MutableComponent rmbToEdit = Lang.translate("gui.schedule.lmb_edit") + .style(ChatFormatting.DARK_GRAY) + .style(ChatFormatting.ITALIC) + .component(); + + addRenderableOnly(new TooltipArea(x + 21, y + 23, 30, 18) + .withTooltip(ImmutableList.of(Lang.translate("elevator_contact.floor_identifier") + .color(0x5391E1) + .component(), rmbToEdit))); + + addRenderableOnly(new TooltipArea(x + 57, y + 23, 147, 18).withTooltip(ImmutableList.of( + Lang.translate("elevator_contact.floor_description") + .color(0x5391E1) + .component(), + Lang.translate("crafting_blueprint.optional") + .style(ChatFormatting.GRAY) + .component(), + rmbToEdit))); + + Pair doorControlWidgets = + DoorControl.createWidget(x + 58, y + 57, mode -> doorControl = mode, doorControl); + addRenderableWidget(doorControlWidgets.getFirst()); + addRenderableWidget(doorControlWidgets.getSecond()); + } + + private int centerInput(int x) { + int centeredX = x + (shortName.isEmpty() ? 34 : 36 - font.width(shortName) / 2); + shortNameInput.setX(centeredX); + return centeredX; + } + + private EditBox editBox(int x, int width, int chars) { + EditBox editBox = new EditBox(font, guiLeft + x, guiTop + 30, width, 10, Components.immutableEmpty()); + editBox.setTextColor(-1); + editBox.setTextColorUneditable(-1); + editBox.setBordered(false); + editBox.setMaxLength(chars); + editBox.changeFocus(false); + editBox.mouseClicked(0, 0, 0); + addRenderableWidget(editBox); + return editBox; + } + + @Override + protected void renderWindow(PoseStack ms, int mouseX, int mouseY, float partialTicks) { + int x = guiLeft; + int y = guiTop; + + background.render(ms, x, y, this); + + FormattedCharSequence formattedcharsequence = title.getVisualOrderText(); + font.draw(ms, formattedcharsequence, + (float) (x + (background.width - 8) / 2 - font.width(formattedcharsequence) / 2), (float) y + 6, 0x2F3738); + + GuiGameElement.of(AllBlocks.ELEVATOR_CONTACT.asStack()).at(x + background.width + 6, y + background.height - 56, -200) + .scale(5) + .render(ms); + + itemRenderer.renderGuiItem(AllBlocks.TRAIN_DOOR.asStack(), x + 37, y + 58); + } + + @Override + public boolean mouseClicked(double pMouseX, double pMouseY, int pButton) { + boolean consumed = super.mouseClicked(pMouseX, pMouseY, pButton); + + if (!shortNameInput.isFocused()) { + int length = shortNameInput.getValue() + .length(); + shortNameInput.setHighlightPos(length); + shortNameInput.setCursorPosition(length); + } + + if (shortNameInput.isHoveredOrFocused()) + longNameInput.mouseClicked(0, 0, 0); + + if (!consumed && pMouseX > guiLeft + 22 && pMouseY > guiTop + 24 && pMouseX < guiLeft + 50 + && pMouseY < guiTop + 40) { + setFocused(shortNameInput); + shortNameInput.changeFocus(true); + return true; + } + + return consumed; + } + + @Override + public boolean keyPressed(int keyCode, int p_keyPressed_2_, int p_keyPressed_3_) { + if (super.keyPressed(keyCode, p_keyPressed_2_, p_keyPressed_3_)) + return true; + if (keyCode == GLFW.GLFW_KEY_ENTER) { + confirm(); + return true; + } + if (keyCode == 256 && this.shouldCloseOnEsc()) { + this.onClose(); + return true; + } + return false; + } + + private void confirm() { + AllPackets.getChannel() + .sendToServer(new ElevatorContactEditPacket(pos, shortName, longName, doorControl)); + onClose(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorContraption.java b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorContraption.java new file mode 100644 index 000000000..d1c1df426 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorContraption.java @@ -0,0 +1,199 @@ +package com.simibubi.create.content.contraptions.elevator; + +import java.util.List; + +import org.apache.commons.lang3.tuple.MutablePair; +import org.apache.commons.lang3.tuple.Pair; + +import com.google.common.collect.ImmutableList; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPackets; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.AssemblyException; +import com.simibubi.create.content.contraptions.ContraptionType; +import com.simibubi.create.content.contraptions.actors.contraptionControls.ContraptionControlsMovement.ElevatorFloorSelection; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.contraptions.elevator.ElevatorColumn.ColumnCoords; +import com.simibubi.create.content.contraptions.pulley.PulleyContraption; +import com.simibubi.create.content.redstone.contact.RedstoneContactBlock; +import com.simibubi.create.foundation.utility.Couple; +import com.simibubi.create.foundation.utility.IntAttached; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.nbt.CompoundTag; +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.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; +import net.minecraftforge.network.PacketDistributor; + +public class ElevatorContraption extends PulleyContraption { + + protected ColumnCoords column; + protected int contactYOffset; + public boolean arrived; + + private int namesListVersion = -1; + public List>> namesList = ImmutableList.of(); + public int clientYTarget; + + public int maxContactY; + public int minContactY; + + // during assembly only + private int contacts; + + public ElevatorContraption() { + super(); + } + + public ElevatorContraption(int initialOffset) { + super(initialOffset); + } + + @Override + public void tickStorage(AbstractContraptionEntity entity) { + super.tickStorage(entity); + + if (entity.tickCount % 10 != 0) + return; + + ColumnCoords coords = getGlobalColumn(); + ElevatorColumn column = ElevatorColumn.get(entity.level, coords); + + if (column == null) + return; + if (column.namesListVersion == namesListVersion) + return; + + namesList = column.compileNamesList(); + namesListVersion = column.namesListVersion; + AllPackets.getChannel().send(PacketDistributor.TRACKING_ENTITY.with(() -> entity), + new ElevatorFloorListPacket(entity, namesList)); + } + + @Override + protected void disableActorOnStart(MovementContext context) {} + + public ColumnCoords getGlobalColumn() { + return column.relative(anchor); + } + + public Integer getCurrentTargetY(Level level) { + ColumnCoords coords = getGlobalColumn(); + ElevatorColumn column = ElevatorColumn.get(level, coords); + if (column == null) + return null; + int targetedYLevel = column.targetedYLevel; + if (isTargetUnreachable(targetedYLevel)) + return null; + return targetedYLevel; + } + + public boolean isTargetUnreachable(int contactY) { + return contactY < minContactY || contactY > maxContactY; + } + + @Override + public boolean assemble(Level world, BlockPos pos) throws AssemblyException { + if (!searchMovedStructure(world, pos, null)) + return false; + if (blocks.size() <= 0) + return false; + if (contacts == 0) + throw new AssemblyException(Lang.translateDirect("gui.assembly.exception.no_contacts")); + if (contacts > 1) + throw new AssemblyException(Lang.translateDirect("gui.assembly.exception.too_many_contacts")); + + ElevatorColumn column = ElevatorColumn.get(world, getGlobalColumn()); + if (column != null && column.isActive()) + throw new AssemblyException(Lang.translateDirect("gui.assembly.exception.column_conflict")); + + startMoving(world); + return true; + } + + @Override + protected Pair capture(Level world, BlockPos pos) { + BlockState blockState = world.getBlockState(pos); + + if (!AllBlocks.REDSTONE_CONTACT.has(blockState)) + return super.capture(world, pos); + + Direction facing = blockState.getValue(RedstoneContactBlock.FACING); + if (facing.getAxis() == Axis.Y) + return super.capture(world, pos); + + contacts++; + BlockPos local = toLocalPos(pos.relative(facing)); + column = new ColumnCoords(local.getX(), local.getZ(), facing.getOpposite()); + contactYOffset = local.getY(); + + return super.capture(world, pos); + } + + public int getContactYOffset() { + return contactYOffset; + } + + public void broadcastFloorData(Level level, BlockPos contactPos) { + ElevatorColumn column = ElevatorColumn.get(level, getGlobalColumn()); + if (!(world.getBlockEntity(contactPos) instanceof ElevatorContactBlockEntity ecbe)) + return; + if (column != null) + column.floorReached(level, ecbe.shortName); + } + + @Override + public CompoundTag writeNBT(boolean spawnPacket) { + CompoundTag tag = super.writeNBT(spawnPacket); + tag.putBoolean("Arrived", arrived); + tag.put("Column", column.write()); + tag.putInt("ContactY", contactYOffset); + tag.putInt("MaxContactY", maxContactY); + tag.putInt("MinContactY", minContactY); + return tag; + } + + @Override + public void readNBT(Level world, CompoundTag nbt, boolean spawnData) { + arrived = nbt.getBoolean("Arrived"); + column = ColumnCoords.read(nbt.getCompound("Column")); + contactYOffset = nbt.getInt("ContactY"); + maxContactY = nbt.getInt("MaxContactY"); + minContactY = nbt.getInt("MinContactY"); + super.readNBT(world, nbt, spawnData); + } + + @Override + public ContraptionType getType() { + return ContraptionType.ELEVATOR; + } + + public void setClientYTarget(int clientYTarget) { + if (this.clientYTarget == clientYTarget) + return; + + this.clientYTarget = clientYTarget; + syncControlDisplays(); + } + + public void syncControlDisplays() { + if (namesList.isEmpty()) + return; + for (int i = 0; i < namesList.size(); i++) + if (namesList.get(i) + .getFirst() == clientYTarget) + setAllControlsToFloor(i); + } + + public void setAllControlsToFloor(int floorIndex) { + for (MutablePair pair : actors) + if (pair.right != null && pair.right.temporaryData instanceof ElevatorFloorSelection efs) + efs.currentIndex = floorIndex; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorControlsHandler.java b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorControlsHandler.java new file mode 100644 index 000000000..ed99e353b --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorControlsHandler.java @@ -0,0 +1,130 @@ +package com.simibubi.create.content.contraptions.elevator; + +import java.lang.ref.WeakReference; +import java.util.Collection; + +import org.apache.commons.lang3.tuple.MutablePair; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.contraptions.ContraptionHandler; +import com.simibubi.create.content.contraptions.ContraptionHandlerClient; +import com.simibubi.create.content.contraptions.actors.contraptionControls.ContraptionControlsBlockEntity; +import com.simibubi.create.content.contraptions.actors.contraptionControls.ContraptionControlsBlockEntity.ControlsSlot; +import com.simibubi.create.content.contraptions.actors.contraptionControls.ContraptionControlsMovement; +import com.simibubi.create.content.contraptions.actors.contraptionControls.ContraptionControlsMovement.ElevatorFloorSelection; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.foundation.utility.Couple; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.core.BlockPos; +import net.minecraft.util.Mth; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public class ElevatorControlsHandler { + + private static ControlsSlot slot = new ElevatorControlsSlot(); + + private static class ElevatorControlsSlot extends ContraptionControlsBlockEntity.ControlsSlot { + + @Override + public boolean testHit(BlockState state, Vec3 localHit) { + Vec3 offset = getLocalOffset(state); + if (offset == null) + return false; + return localHit.distanceTo(offset) < scale * .85; + } + + } + + @OnlyIn(Dist.CLIENT) + public static boolean onScroll(double delta) { + Minecraft mc = Minecraft.getInstance(); + LocalPlayer player = mc.player; + + if (player == null) + return false; + if (player.isSpectator()) + return false; + if (mc.level == null) + return false; + + Couple rayInputs = ContraptionHandlerClient.getRayInputs(player); + Vec3 origin = rayInputs.getFirst(); + Vec3 target = rayInputs.getSecond(); + AABB aabb = new AABB(origin, target).inflate(16); + + Collection> contraptions = + ContraptionHandler.loadedContraptions.get(mc.level) + .values(); + + for (WeakReference ref : contraptions) { + AbstractContraptionEntity contraptionEntity = ref.get(); + if (contraptionEntity == null) + continue; + + Contraption contraption = contraptionEntity.getContraption(); + if (!(contraption instanceof ElevatorContraption ec)) + continue; + + if (!contraptionEntity.getBoundingBox() + .intersects(aabb)) + continue; + + BlockHitResult rayTraceResult = + ContraptionHandlerClient.rayTraceContraption(origin, target, contraptionEntity); + if (rayTraceResult == null) + continue; + + BlockPos pos = rayTraceResult.getBlockPos(); + StructureBlockInfo info = contraption.getBlocks() + .get(pos); + + if (info == null) + continue; + if (!AllBlocks.CONTRAPTION_CONTROLS.has(info.state)) + continue; + + if (!slot.testHit(info.state, rayTraceResult.getLocation() + .subtract(Vec3.atLowerCornerOf(pos)))) + continue; + + MovementContext ctx = null; + for (MutablePair pair : contraption.getActors()) { + if (info.equals(pair.left)) { + ctx = pair.right; + break; + } + } + + if (!(ctx.temporaryData instanceof ElevatorFloorSelection)) + ctx.temporaryData = new ElevatorFloorSelection(); + + ElevatorFloorSelection efs = (ElevatorFloorSelection) ctx.temporaryData; + int prev = efs.currentIndex; + efs.currentIndex += delta; + ContraptionControlsMovement.tickFloorSelection(efs, ec); + + if (prev != efs.currentIndex && !ec.namesList.isEmpty()) { + float pitch = (efs.currentIndex) / (float) (ec.namesList.size()); + pitch = Mth.lerp(pitch, 1f, 1.5f); + AllSoundEvents.SCROLL_VALUE.play(mc.player.level, mc.player, + new BlockPos(contraptionEntity.toGlobalVector(rayTraceResult.getLocation(), 1)), 1, pitch); + } + + return true; + } + + return false; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorFloorListPacket.java b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorFloorListPacket.java new file mode 100644 index 000000000..fac96cced --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorFloorListPacket.java @@ -0,0 +1,98 @@ +package com.simibubi.create.content.contraptions.elevator; + +import java.util.ArrayList; +import java.util.List; + +import com.simibubi.create.AllPackets; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.foundation.networking.SimplePacketBase; +import com.simibubi.create.foundation.utility.Couple; +import com.simibubi.create.foundation.utility.IntAttached; + +import net.minecraft.client.Minecraft; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.Entity; +import net.minecraftforge.network.NetworkEvent.Context; +import net.minecraftforge.network.PacketDistributor; + +public class ElevatorFloorListPacket extends SimplePacketBase { + + private int entityId; + private List>> floorsList; + + public ElevatorFloorListPacket(AbstractContraptionEntity entity, List>> floorsList) { + this.entityId = entity.getId(); + this.floorsList = floorsList; + } + + public ElevatorFloorListPacket(FriendlyByteBuf buffer) { + entityId = buffer.readInt(); + int size = buffer.readInt(); + floorsList = new ArrayList<>(); + for (int i = 0; i < size; i++) + floorsList.add(IntAttached.with(buffer.readInt(), Couple.create(buffer.readUtf(), buffer.readUtf()))); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeInt(entityId); + buffer.writeInt(floorsList.size()); + for (IntAttached> entry : floorsList) { + buffer.writeInt(entry.getFirst()); + entry.getSecond() + .forEach(buffer::writeUtf); + } + } + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> { + Entity entityByID = Minecraft.getInstance().level.getEntity(entityId); + if (!(entityByID instanceof AbstractContraptionEntity ace)) + return; + if (!(ace.getContraption()instanceof ElevatorContraption ec)) + return; + + ec.namesList = floorsList; + ec.syncControlDisplays(); + }); + return true; + } + + public static class RequestFloorList extends SimplePacketBase { + + private int entityId; + + public RequestFloorList(AbstractContraptionEntity entity) { + this.entityId = entity.getId(); + } + + public RequestFloorList(FriendlyByteBuf buffer) { + entityId = buffer.readInt(); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeInt(entityId); + } + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> { + ServerPlayer sender = context.getSender(); + Entity entityByID = sender.getLevel() + .getEntity(entityId); + if (!(entityByID instanceof AbstractContraptionEntity ace)) + return; + if (!(ace.getContraption()instanceof ElevatorContraption ec)) + return; + AllPackets.getChannel().send(PacketDistributor.PLAYER.with(() -> sender), + new ElevatorFloorListPacket(ace, ec.namesList)); + }); + return true; + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorPulleyBlock.java b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorPulleyBlock.java new file mode 100644 index 000000000..03e64c027 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorPulleyBlock.java @@ -0,0 +1,74 @@ +package com.simibubi.create.content.contraptions.elevator; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllShapes; +import com.simibubi.create.content.kinetics.base.HorizontalKineticBlock; +import com.simibubi.create.foundation.block.IBE; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +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.LevelReader; +import net.minecraft.world.level.block.entity.BlockEntityType; +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.VoxelShape; + +public class ElevatorPulleyBlock extends HorizontalKineticBlock implements IBE { + + public ElevatorPulleyBlock(Properties properties) { + super(properties); + } + + @Override + public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, + BlockHitResult hit) { + if (!player.mayBuild()) + return InteractionResult.FAIL; + if (player.isShiftKeyDown()) + return InteractionResult.FAIL; + if (!player.getItemInHand(handIn) + .isEmpty()) + return InteractionResult.PASS; + if (worldIn.isClientSide) + return InteractionResult.SUCCESS; + return onBlockEntityUse(worldIn, pos, be -> { + be.clicked(); + return InteractionResult.SUCCESS; + }); + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.ELEVATOR_PULLEY.get(); + } + + @Override + public Axis getRotationAxis(BlockState state) { + return state.getValue(HORIZONTAL_FACING) + .getClockWise() + .getAxis(); + } + + @Override + public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) { + return AllShapes.ELEVATOR_PULLEY.get(state.getValue(HORIZONTAL_FACING)); + } + + @Override + public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) { + return getRotationAxis(state) == face.getAxis(); + } + + @Override + public Class getBlockEntityClass() { + return ElevatorPulleyBlockEntity.class; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorPulleyBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorPulleyBlockEntity.java new file mode 100644 index 000000000..faa722ffd --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorPulleyBlockEntity.java @@ -0,0 +1,325 @@ +package com.simibubi.create.content.contraptions.elevator; + +import java.util.List; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPackets; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.content.contraptions.AssemblyException; +import com.simibubi.create.content.contraptions.ControlledContraptionEntity; +import com.simibubi.create.content.contraptions.elevator.ElevatorColumn.ColumnCoords; +import com.simibubi.create.content.contraptions.pulley.PulleyBlockEntity; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.Mth; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; + +public class ElevatorPulleyBlockEntity extends PulleyBlockEntity { + + private float prevSpeed; + private boolean arrived; + private int clientOffsetTarget; + private boolean initialOffsetReceived; + + public ElevatorPulleyBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + prevSpeed = 0; + arrived = true; + initialOffsetReceived = false; + } + + private int getTargetOffset() { + if (level.isClientSide) + return clientOffsetTarget; + if (movedContraption == null || !(movedContraption.getContraption()instanceof ElevatorContraption ec)) + return (int) offset; + + Integer target = ec.getCurrentTargetY(level); + if (target == null) + return (int) offset; + + return worldPosition.getY() - target + ec.contactYOffset - 1; + } + + @Override + public void attach(ControlledContraptionEntity contraption) { + super.attach(contraption); + if (offset >= 0) + resetContraptionToOffset(); + if (level.isClientSide) { + AllPackets.getChannel().sendToServer(new ElevatorFloorListPacket.RequestFloorList(contraption)); + return; + } + + if (contraption.getContraption()instanceof ElevatorContraption ec) + ElevatorColumn.getOrCreate(level, ec.getGlobalColumn()) + .setActive(true); + } + + @Override + public void tick() { + boolean wasArrived = arrived; + super.tick(); + + if (movedContraption == null) + return; + if (!(movedContraption.getContraption()instanceof ElevatorContraption ec)) + return; + if (level.isClientSide()) + ec.setClientYTarget(worldPosition.getY() - clientOffsetTarget + ec.contactYOffset - 1); + + waitingForSpeedChange = false; + ec.arrived = wasArrived; + + if (!arrived) + return; + + double y = movedContraption.getY(); + int targetLevel = Mth.floor(0.5f + y) + ec.contactYOffset; + + Integer ecCurrentTargetY = ec.getCurrentTargetY(level); + if (ecCurrentTargetY != null) + targetLevel = ecCurrentTargetY; + if (level.isClientSide()) + targetLevel = ec.clientYTarget; + if (!wasArrived && !level.isClientSide()) { + triggerContact(ec, targetLevel); + AllSoundEvents.CONTRAPTION_DISASSEMBLE.play(level, null, worldPosition.below((int) offset), 0.75f, 0.8f); + } + + double diff = targetLevel - y - ec.contactYOffset; + if (Math.abs(diff) > 1f / 128) + diff *= 0.25f; + movedContraption.setPos(movedContraption.position() + .add(0, diff, 0)); + } + + @Override + public void lazyTick() { + super.lazyTick(); + if (level.isClientSide() || !arrived) + return; + if (movedContraption == null || !movedContraption.isAlive()) + return; + if (!(movedContraption.getContraption()instanceof ElevatorContraption ec)) + return; + if (getTargetOffset() != (int) offset) + return; + + double y = movedContraption.getY(); + int targetLevel = Mth.floor(0.5f + y); + triggerContact(ec, targetLevel); + } + + private void triggerContact(ElevatorContraption ec, int targetLevel) { + ColumnCoords coords = ec.getGlobalColumn(); + ElevatorColumn column = ElevatorColumn.get(level, coords); + if (column == null) + return; + + BlockPos contactPos = column.contactAt(targetLevel + ec.contactYOffset); + if (!level.isLoaded(contactPos)) + return; + BlockState contactState = level.getBlockState(contactPos); + if (!AllBlocks.ELEVATOR_CONTACT.has(contactState)) + return; + if (contactState.getValue(ElevatorContactBlock.POWERING)) + return; + + ElevatorContactBlock ecb = AllBlocks.ELEVATOR_CONTACT.get(); + ecb.withBlockEntityDo(level, contactPos, be -> be.activateBlock = true); + ecb.scheduleActivation(level, contactPos); + } + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + super.write(compound, clientPacket); + if (clientPacket) + compound.putInt("ClientTarget", clientOffsetTarget); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + super.read(compound, clientPacket); + if (!clientPacket) + return; + + clientOffsetTarget = compound.getInt("ClientTarget"); + if (initialOffsetReceived) + return; + + offset = compound.getFloat("Offset"); + initialOffsetReceived = true; + resetContraptionToOffset(); + } + + @Override + public float getMovementSpeed() { + int currentTarget = getTargetOffset(); + + if (!level.isClientSide() && currentTarget != clientOffsetTarget) { + clientOffsetTarget = currentTarget; + sendData(); + } + + float diff = currentTarget - offset; + float movementSpeed = Mth.clamp(convertToLinear(getSpeed() * 2), -1.99f, 1.99f); + float rpmLimit = Math.abs(movementSpeed); + + float configacc = Mth.lerp(Math.abs(movementSpeed), 0.0075f, 0.0175f); + float decelleration = (float) Math.sqrt(2 * Math.abs(diff) * configacc); + + float speed = diff; + speed = Mth.clamp(speed, -rpmLimit, rpmLimit); + speed = Mth.clamp(speed, prevSpeed - configacc, prevSpeed + configacc); + speed = Mth.clamp(speed, -decelleration, decelleration); + + arrived = Math.abs(diff) < 0.5f; + + if (speed > 1 / 1024f && !level.isClientSide()) + setChanged(); + + return prevSpeed = speed; + } + + @Override + protected boolean shouldCreateRopes() { + return false; + } + + @Override + public void disassemble() { + if (movedContraption != null && movedContraption.getContraption()instanceof ElevatorContraption ec) { + ElevatorColumn column = ElevatorColumn.get(level, ec.getGlobalColumn()); + if (column != null) + column.setActive(false); + } + + super.disassemble(); + offset = -1; + sendData(); + } + + public void clicked() { + if (isPassive() && level.getBlockEntity(mirrorParent)instanceof ElevatorPulleyBlockEntity parent) { + parent.clicked(); + return; + } + + if (running) + disassemble(); + else + assembleNextTick = true; + } + + @Override + protected boolean moveAndCollideContraption() { + if (arrived) + return false; + super.moveAndCollideContraption(); + return false; + } + + @Override + public void addBehaviours(List behaviours) { + registerAwardables(behaviours, AllAdvancements.CONTRAPTION_ACTORS); + } + + @Override + protected void assemble() throws AssemblyException { + if (!(level.getBlockState(worldPosition) + .getBlock() instanceof ElevatorPulleyBlock)) + return; + if (getSpeed() == 0) + return; + + int maxLength = AllConfigs.server().kinetics.maxRopeLength.get(); + int i = 1; + while (i <= maxLength) { + BlockPos ropePos = worldPosition.below(i); + BlockState ropeState = level.getBlockState(ropePos); + if (!ropeState.getCollisionShape(level, ropePos) + .isEmpty() + && !ropeState.getMaterial() + .isReplaceable()) { + break; + } + ++i; + } + + offset = i - 1; + forceMove = true; + + // Collect Construct + if (!level.isClientSide && mirrorParent == null) { + needsContraption = false; + BlockPos anchor = worldPosition.below(Mth.floor(offset + 1)); + offset = Mth.floor(offset); + ElevatorContraption contraption = new ElevatorContraption((int) offset); + + float offsetOnSucess = offset; + offset = 0; + + boolean canAssembleStructure = contraption.assemble(level, anchor); + if (!canAssembleStructure && getSpeed() > 0) + return; + + if (!contraption.getBlocks() + .isEmpty()) { + offset = offsetOnSucess; + contraption.removeBlocksFromWorld(level, BlockPos.ZERO); + movedContraption = ControlledContraptionEntity.create(level, this, contraption); + movedContraption.setPos(anchor.getX(), anchor.getY(), anchor.getZ()); + contraption.maxContactY = worldPosition.getY() + contraption.contactYOffset - 1; + contraption.minContactY = contraption.maxContactY - maxLength; + level.addFreshEntity(movedContraption); + forceMove = true; + needsContraption = true; + + if (contraption.containsBlockBreakers()) + award(AllAdvancements.CONTRAPTION_ACTORS); + + for (BlockPos pos : contraption.createColliders(level, Direction.UP)) { + if (pos.getY() != 0) + continue; + pos = pos.offset(anchor); + if (level.getBlockEntity(new BlockPos(pos.getX(), worldPosition.getY(), + pos.getZ())) instanceof ElevatorPulleyBlockEntity pbe) + pbe.startMirroringOther(worldPosition); + } + + ElevatorColumn column = ElevatorColumn.getOrCreate(level, contraption.getGlobalColumn()); + int target = (int) (worldPosition.getY() + contraption.contactYOffset - 1 - offset); + column.target(target); + column.gatherAll(); + column.setActive(true); + column.markDirty(); + + contraption.broadcastFloorData(level, column.contactAt(target)); + clientOffsetTarget = column.getTargetedYLevel(); + arrived = true; + } + } + + clientOffsetDiff = 0; + running = true; + sendData(); + } + + @Override + public void onSpeedChanged(float previousSpeed) { + setChanged(); + } + + @Override + protected MovementMode getMovementMode() { + return MovementMode.MOVE_NEVER_PLACE; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorPulleyInstance.java b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorPulleyInstance.java new file mode 100644 index 000000000..ac5e07f78 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorPulleyInstance.java @@ -0,0 +1,24 @@ +package com.simibubi.create.content.contraptions.elevator; + +import com.jozufozu.flywheel.api.MaterialManager; +import com.jozufozu.flywheel.api.instance.DynamicInstance; +import com.jozufozu.flywheel.light.TickingLightListener; +import com.simibubi.create.content.kinetics.base.ShaftInstance; + +// TODO +public class ElevatorPulleyInstance extends ShaftInstance implements DynamicInstance, TickingLightListener { + + public ElevatorPulleyInstance(MaterialManager materialManager, ElevatorPulleyBlockEntity blockEntity) { + super(materialManager, blockEntity); + } + + @Override + public boolean tickLightListener() { + return false; + } + + @Override + public void beginFrame() { + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorPulleyRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorPulleyRenderer.java new file mode 100644 index 000000000..c34c701dd --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorPulleyRenderer.java @@ -0,0 +1,127 @@ +package com.simibubi.create.content.contraptions.elevator; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.AllSpriteShifts; +import com.simibubi.create.content.contraptions.pulley.AbstractPulleyRenderer; +import com.simibubi.create.content.contraptions.pulley.PulleyRenderer; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.foundation.block.render.SpriteShiftEntry; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.AngleHelper; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; + +public class ElevatorPulleyRenderer extends KineticBlockEntityRenderer { + + public ElevatorPulleyRenderer(BlockEntityRendererProvider.Context context) { + super(context); + } + + @Override + protected void renderSafe(ElevatorPulleyBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + +// if (Backend.canUseInstancing(be.getLevel())) +// return; + + // from KBE. replace with super call when flw instance is implemented + BlockState state = getRenderedBlockState(be); + RenderType type = getRenderType(be, state); + if (type != null) + renderRotatingBuffer(be, getRotatedModel(be, state), ms, buffer.getBuffer(type), light); + // + + float offset = PulleyRenderer.getBlockEntityOffset(partialTicks, be); + boolean running = PulleyRenderer.isPulleyRunning(be); + + SpriteShiftEntry beltShift = AllSpriteShifts.ELEVATOR_BELT; + SpriteShiftEntry coilShift = AllSpriteShifts.ELEVATOR_COIL; + VertexConsumer vb = buffer.getBuffer(RenderType.solid()); + Level world = be.getLevel(); + BlockState blockState = be.getBlockState(); + BlockPos pos = be.getBlockPos(); + + float blockStateAngle = + 180 + AngleHelper.horizontalAngle(blockState.getValue(ElevatorPulleyBlock.HORIZONTAL_FACING)); + + SuperByteBuffer magnet = CachedBufferer.partial(AllPartialModels.ELEVATOR_MAGNET, blockState); + if (running || offset == 0) + AbstractPulleyRenderer.renderAt(world, magnet.centre() + .rotateY(blockStateAngle) + .unCentre(), offset, pos, ms, vb); + + SuperByteBuffer rotatedCoil = getRotatedCoil(be); + if (offset == 0) { + rotatedCoil.light(light) + .renderInto(ms, vb); + return; + } + + float spriteSize = beltShift.getTarget() + .getV1() + - beltShift.getTarget() + .getV0(); + + double coilScroll = -(offset + 3 / 16f) - Math.floor((offset + 3 / 16f) * -2) / 2; + double beltScroll = (-(offset + .5) - Math.floor(-(offset + .5))) / 2; + + rotatedCoil.shiftUVScrolling(coilShift, (float) coilScroll * spriteSize) + .light(light) + .renderInto(ms, vb); + + SuperByteBuffer halfRope = CachedBufferer.partial(AllPartialModels.ELEVATOR_BELT_HALF, blockState); + SuperByteBuffer rope = CachedBufferer.partial(AllPartialModels.ELEVATOR_BELT, blockState); + + float f = offset % 1; + if (f < .25f || f > .75f) { + halfRope.centre() + .rotateY(blockStateAngle) + .unCentre(); + AbstractPulleyRenderer.renderAt(world, + halfRope.shiftUVScrolling(beltShift, (float) beltScroll * spriteSize), f > .75f ? f - 1 : f, pos, ms, + vb); + } + + if (!running) + return; + + for (int i = 0; i < offset - .25f; i++) { + rope.centre() + .rotateY(blockStateAngle) + .unCentre(); + AbstractPulleyRenderer.renderAt(world, rope.shiftUVScrolling(beltShift, (float) beltScroll * spriteSize), + offset - i, pos, ms, vb); + } + } + + @Override + protected BlockState getRenderedBlockState(ElevatorPulleyBlockEntity be) { + return shaft(getRotationAxisOf(be)); + } + + protected SuperByteBuffer getRotatedCoil(KineticBlockEntity be) { + BlockState blockState = be.getBlockState(); + return CachedBufferer.partialFacing(AllPartialModels.ELEVATOR_COIL, blockState, + blockState.getValue(ElevatorPulleyBlock.HORIZONTAL_FACING)); + } + + @Override + public int getViewDistance() { + return 128; + } + + @Override + public boolean shouldRenderOffScreen(ElevatorPulleyBlockEntity p_188185_1_) { + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorTargetFloorPacket.java b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorTargetFloorPacket.java new file mode 100644 index 000000000..1e6ec3afc --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/elevator/ElevatorTargetFloorPacket.java @@ -0,0 +1,65 @@ +package com.simibubi.create.content.contraptions.elevator; + +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.network.NetworkEvent.Context; + +public class ElevatorTargetFloorPacket extends SimplePacketBase { + + private int entityId; + private int targetY; + + public ElevatorTargetFloorPacket(AbstractContraptionEntity entity, int targetY) { + this.targetY = targetY; + this.entityId = entity.getId(); + } + + public ElevatorTargetFloorPacket(FriendlyByteBuf buffer) { + entityId = buffer.readInt(); + targetY = buffer.readInt(); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeInt(entityId); + buffer.writeInt(targetY); + } + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> { + ServerPlayer sender = context.getSender(); + Entity entityByID = sender.getLevel() + .getEntity(entityId); + if (!(entityByID instanceof AbstractContraptionEntity ace)) + return; + if (!(ace.getContraption() instanceof ElevatorContraption ec)) + return; + if (ace.distanceToSqr(sender) > 50 * 50) + return; + + Level level = sender.level; + ElevatorColumn elevatorColumn = ElevatorColumn.get(level, ec.getGlobalColumn()); + if (!elevatorColumn.contacts.contains(targetY)) + return; + if (ec.isTargetUnreachable(targetY)) + return; + + BlockPos pos = elevatorColumn.contactAt(targetY); + BlockState blockState = level.getBlockState(pos); + if (!(blockState.getBlock() instanceof ElevatorContactBlock ecb)) + return; + + ecb.callToContactAndUpdate(elevatorColumn, blockState, level, pos, false); + }); + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpCogInstance.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpCogInstance.java deleted file mode 100644 index 6d85b1fc0..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpCogInstance.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.simibubi.create.content.contraptions.fluids; - -import com.jozufozu.flywheel.api.Instancer; -import com.jozufozu.flywheel.api.MaterialManager; -import com.jozufozu.flywheel.api.instance.DynamicInstance; -import com.jozufozu.flywheel.core.Materials; -import com.jozufozu.flywheel.core.materials.model.ModelData; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.SingleRotatingInstance; -import com.simibubi.create.content.contraptions.base.flwdata.RotatingData; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; - -import net.minecraft.core.Direction; -import net.minecraft.util.Mth; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; - -public class PumpCogInstance extends SingleRotatingInstance implements DynamicInstance { - - private final PumpTileEntity blockEntity = (PumpTileEntity) super.blockEntity; - private final ModelData[] arrows = new ModelData[2]; - private final Direction direction = blockState.getValue(PumpBlock.FACING); - - public PumpCogInstance(MaterialManager modelManager, PumpTileEntity tile) { - super(modelManager, tile); - } - - @Override - public void init() { - super.init(); - - materialManager.defaultSolid() - .material(Materials.TRANSFORMED) - .getModel(AllBlockPartials.MECHANICAL_PUMP_ARROW, blockState) - .createInstances(arrows); - } - - @Override - public void beginFrame() { - float angle = Mth.lerp(blockEntity.arrowDirection.getValue(AnimationTickHolder.getPartialTicks()), 0, 90) - 90; - for (int i = 0, arrowsLength = arrows.length; i < arrowsLength; i++) { - arrows[i].loadIdentity() - .translate(getInstancePosition()) - .centre() - .rotateY(AngleHelper.horizontalAngle(direction) + 180) - .rotateX(-AngleHelper.verticalAngle(direction) - 90) - .unCentre() - .translate(.5, 14 / 16f, .5) - .rotateY(90 * i) - .rotateZ(angle) - .translateBack(.5, 14 / 16f, .5); - } - } - - @Override - public void updateLight() { - super.updateLight(); - relight(pos, arrows); - } - - @Override - protected Instancer getModel() { - BlockState referenceState = blockEntity.getBlockState(); - Direction facing = referenceState.getValue(BlockStateProperties.FACING); - return getRotatingMaterial().getModel(AllBlockPartials.MECHANICAL_PUMP_COG, referenceState, facing); - } - - @Override - public void remove() { - super.remove(); - - for (ModelData arrow : arrows) { - arrow.delete(); - } - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpRenderer.java deleted file mode 100644 index 23e41b42a..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpRenderer.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.simibubi.create.content.contraptions.fluids; - -import com.jozufozu.flywheel.backend.Backend; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.Direction; -import net.minecraft.util.Mth; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; - -public class PumpRenderer extends KineticTileEntityRenderer { - - public PumpRenderer(BlockEntityRendererProvider.Context context) { - super(context); - } - - @Override - protected void renderSafe(KineticTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - super.renderSafe(te, partialTicks, ms, buffer, light, overlay); - if (Backend.canUseInstancing(te.getLevel())) return; - if (!(te instanceof PumpTileEntity pump)) - return; - Vec3 rotationOffset = new Vec3(.5, 14 / 16f, .5); - BlockState blockState = te.getBlockState(); - float angle = Mth.lerp(pump.arrowDirection.getValue(partialTicks), 0, 90) - 90; - SuperByteBuffer arrow = CachedBufferer.partial(AllBlockPartials.MECHANICAL_PUMP_ARROW, blockState); - for (float yRot : new float[] { 0, 90 }) { - Direction direction = blockState.getValue(PumpBlock.FACING); - arrow.centre() - .rotateY(AngleHelper.horizontalAngle(direction) + 180) - .rotateX(-AngleHelper.verticalAngle(direction) - 90) - .unCentre() - .translate(rotationOffset) - .rotateY(yRot) - .rotateZ(angle) - .translateBack(rotationOffset) - .light(light) - .renderInto(ms, buffer.getBuffer(RenderType.solid())); - } - } - - @Override - protected SuperByteBuffer getRotatedModel(KineticTileEntity te, BlockState state) { - return CachedBufferer.partialFacing(AllBlockPartials.MECHANICAL_PUMP_COG, state); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpTileEntity.java deleted file mode 100644 index 94c155f01..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpTileEntity.java +++ /dev/null @@ -1,397 +0,0 @@ -package com.simibubi.create.content.contraptions.fluids; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.IdentityHashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -import javax.annotation.Nullable; - -import org.apache.commons.lang3.mutable.MutableBoolean; - -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.utility.BlockFace; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Pair; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.level.BlockAndTintGetter; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.fluids.capability.CapabilityFluidHandler; -import net.minecraftforge.fluids.capability.IFluidHandler; - -public class PumpTileEntity extends KineticTileEntity { - - LerpedFloat arrowDirection; - Couple sidesToUpdate; - boolean pressureUpdate; - boolean reversed; - - public PumpTileEntity(BlockEntityType typeIn, BlockPos pos, BlockState state) { - super(typeIn, pos, state); - arrowDirection = LerpedFloat.linear() - .startWithValue(1); - sidesToUpdate = Couple.create(MutableBoolean::new); - } - - @Override - public void addBehaviours(List behaviours) { - super.addBehaviours(behaviours); - behaviours.add(new PumpFluidTransferBehaviour(this)); - registerAwardables(behaviours, FluidPropagator.getSharedTriggers()); - registerAwardables(behaviours, AllAdvancements.PUMP); - } - - @Override - public void initialize() { - super.initialize(); - reversed = getSpeed() < 0; - } - - @Override - public void tick() { - super.tick(); - float speed = getSpeed(); - - if (level.isClientSide) { - if (speed == 0) - return; - arrowDirection.chase(speed >= 0 ? 1 : -1, .5f, Chaser.EXP); - arrowDirection.tickChaser(); - if (!isVirtual()) - return; - } - -// if (pressureUpdate) -// updatePressureChange(); - - sidesToUpdate.forEachWithContext((update, isFront) -> { - if (update.isFalse()) - return; - update.setFalse(); - distributePressureTo(isFront ? getFront() : getFront().getOpposite()); - }); - - if (speed == 0) - return; - if (speed < 0 != reversed) { - reversed = speed < 0; - updatePressureChange(); - return; - } - } - - @Override - public void onSpeedChanged(float previousSpeed) { - super.onSpeedChanged(previousSpeed); - - if (previousSpeed == getSpeed()) - return; - if (speed != 0) { - reversed = speed < 0; - award(AllAdvancements.PUMP); - } - if (level.isClientSide && !isVirtual()) - return; - - updatePressureChange(); - } - - public void updatePressureChange() { - pressureUpdate = false; - BlockPos frontPos = worldPosition.relative(getFront()); - BlockPos backPos = worldPosition.relative(getFront().getOpposite()); - FluidPropagator.propagateChangedPipe(level, frontPos, level.getBlockState(frontPos)); - FluidPropagator.propagateChangedPipe(level, backPos, level.getBlockState(backPos)); - - FluidTransportBehaviour behaviour = getBehaviour(FluidTransportBehaviour.TYPE); - if (behaviour != null) - behaviour.wipePressure(); - sidesToUpdate.forEach(MutableBoolean::setTrue); - } - - protected void distributePressureTo(Direction side) { - if (getSpeed() == 0) - return; - - BlockFace start = new BlockFace(worldPosition, side); - boolean pull = isPullingOnSide(isFront(side)); - Set targets = new HashSet<>(); - Map>> pipeGraph = new HashMap<>(); - - if (!pull) - FluidPropagator.resetAffectedFluidNetworks(level, worldPosition, side.getOpposite()); - - if (!hasReachedValidEndpoint(level, start, pull)) { - - pipeGraph.computeIfAbsent(worldPosition, $ -> Pair.of(0, new IdentityHashMap<>())) - .getSecond() - .put(side, pull); - pipeGraph.computeIfAbsent(start.getConnectedPos(), $ -> Pair.of(1, new IdentityHashMap<>())) - .getSecond() - .put(side.getOpposite(), !pull); - - List> frontier = new ArrayList<>(); - Set visited = new HashSet<>(); - int maxDistance = FluidPropagator.getPumpRange(); - frontier.add(Pair.of(1, start.getConnectedPos())); - - while (!frontier.isEmpty()) { - Pair entry = frontier.remove(0); - int distance = entry.getFirst(); - BlockPos currentPos = entry.getSecond(); - - if (!level.isLoaded(currentPos)) - continue; - if (visited.contains(currentPos)) - continue; - visited.add(currentPos); - BlockState currentState = level.getBlockState(currentPos); - FluidTransportBehaviour pipe = FluidPropagator.getPipe(level, currentPos); - if (pipe == null) - continue; - - for (Direction face : FluidPropagator.getPipeConnections(currentState, pipe)) { - BlockFace blockFace = new BlockFace(currentPos, face); - BlockPos connectedPos = blockFace.getConnectedPos(); - - if (!level.isLoaded(connectedPos)) - continue; - if (blockFace.isEquivalent(start)) - continue; - if (hasReachedValidEndpoint(level, blockFace, pull)) { - pipeGraph.computeIfAbsent(currentPos, $ -> Pair.of(distance, new IdentityHashMap<>())) - .getSecond() - .put(face, pull); - targets.add(blockFace); - continue; - } - - FluidTransportBehaviour pipeBehaviour = FluidPropagator.getPipe(level, connectedPos); - if (pipeBehaviour == null) - continue; - if (pipeBehaviour instanceof PumpFluidTransferBehaviour) - continue; - if (visited.contains(connectedPos)) - continue; - if (distance + 1 >= maxDistance) { - pipeGraph.computeIfAbsent(currentPos, $ -> Pair.of(distance, new IdentityHashMap<>())) - .getSecond() - .put(face, pull); - targets.add(blockFace); - continue; - } - - pipeGraph.computeIfAbsent(currentPos, $ -> Pair.of(distance, new IdentityHashMap<>())) - .getSecond() - .put(face, pull); - pipeGraph.computeIfAbsent(connectedPos, $ -> Pair.of(distance + 1, new IdentityHashMap<>())) - .getSecond() - .put(face.getOpposite(), !pull); - frontier.add(Pair.of(distance + 1, connectedPos)); - } - } - } - - // DFS - Map> validFaces = new HashMap<>(); - searchForEndpointRecursively(pipeGraph, targets, validFaces, - new BlockFace(start.getPos(), start.getOppositeFace()), pull); - - float pressure = Math.abs(getSpeed()); - for (Set set : validFaces.values()) { - int parallelBranches = set.size(); - for (BlockFace face : set) { - BlockPos pipePos = face.getPos(); - Direction pipeSide = face.getFace(); - - if (pipePos.equals(worldPosition)) - continue; - - boolean inbound = pipeGraph.get(pipePos) - .getSecond() - .get(pipeSide); - FluidTransportBehaviour pipeBehaviour = FluidPropagator.getPipe(level, pipePos); - if (pipeBehaviour == null) - continue; - - pipeBehaviour.addPressure(pipeSide, inbound, pressure / parallelBranches); - } - } - - } - - protected boolean searchForEndpointRecursively(Map>> pipeGraph, - Set targets, Map> validFaces, BlockFace currentFace, boolean pull) { - BlockPos currentPos = currentFace.getPos(); - if (!pipeGraph.containsKey(currentPos)) - return false; - Pair> pair = pipeGraph.get(currentPos); - int distance = pair.getFirst(); - - boolean atLeastOneBranchSuccessful = false; - for (Direction nextFacing : Iterate.directions) { - if (nextFacing == currentFace.getFace()) - continue; - Map map = pair.getSecond(); - if (!map.containsKey(nextFacing)) - continue; - - BlockFace localTarget = new BlockFace(currentPos, nextFacing); - if (targets.contains(localTarget)) { - validFaces.computeIfAbsent(distance, $ -> new HashSet<>()) - .add(localTarget); - atLeastOneBranchSuccessful = true; - continue; - } - - if (map.get(nextFacing) != pull) - continue; - if (!searchForEndpointRecursively(pipeGraph, targets, validFaces, - new BlockFace(currentPos.relative(nextFacing), nextFacing.getOpposite()), pull)) - continue; - - validFaces.computeIfAbsent(distance, $ -> new HashSet<>()) - .add(localTarget); - atLeastOneBranchSuccessful = true; - } - - if (atLeastOneBranchSuccessful) - validFaces.computeIfAbsent(distance, $ -> new HashSet<>()) - .add(currentFace); - - return atLeastOneBranchSuccessful; - } - - private boolean hasReachedValidEndpoint(LevelAccessor world, BlockFace blockFace, boolean pull) { - BlockPos connectedPos = blockFace.getConnectedPos(); - BlockState connectedState = world.getBlockState(connectedPos); - BlockEntity tileEntity = world.getBlockEntity(connectedPos); - Direction face = blockFace.getFace(); - - // facing a pump - if (PumpBlock.isPump(connectedState) && connectedState.getValue(PumpBlock.FACING) - .getAxis() == face.getAxis() && tileEntity instanceof PumpTileEntity) { - PumpTileEntity pumpTE = (PumpTileEntity) tileEntity; - return pumpTE.isPullingOnSide(pumpTE.isFront(blockFace.getOppositeFace())) != pull; - } - - // other pipe, no endpoint - FluidTransportBehaviour pipe = FluidPropagator.getPipe(world, connectedPos); - if (pipe != null && pipe.canHaveFlowToward(connectedState, blockFace.getOppositeFace())) - return false; - - // fluid handler endpoint - if (tileEntity != null) { - LazyOptional capability = - tileEntity.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, face.getOpposite()); - if (capability.isPresent()) - return true; - } - - // open endpoint - return FluidPropagator.isOpenEnd(world, blockFace.getPos(), face); - } - - @Override - public void write(CompoundTag compound, boolean clientPacket) { - compound.putBoolean("Reversed", reversed); - super.write(compound, clientPacket); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - reversed = compound.getBoolean("Reversed"); - super.read(compound, clientPacket); - } - - public void updatePipesOnSide(Direction side) { - if (!isSideAccessible(side)) - return; - updatePipeNetwork(isFront(side)); - getBehaviour(FluidTransportBehaviour.TYPE).wipePressure(); - } - - protected boolean isFront(Direction side) { - BlockState blockState = getBlockState(); - if (!(blockState.getBlock() instanceof PumpBlock)) - return false; - Direction front = blockState.getValue(PumpBlock.FACING); - boolean isFront = side == front; - return isFront; - } - - @Nullable - protected Direction getFront() { - BlockState blockState = getBlockState(); - if (!(blockState.getBlock() instanceof PumpBlock)) - return null; - return blockState.getValue(PumpBlock.FACING); - } - - protected void updatePipeNetwork(boolean front) { - sidesToUpdate.get(front) - .setTrue(); - } - - public boolean isSideAccessible(Direction side) { - BlockState blockState = getBlockState(); - if (!(blockState.getBlock() instanceof PumpBlock)) - return false; - return blockState.getValue(PumpBlock.FACING) - .getAxis() == side.getAxis(); - } - - public boolean isPullingOnSide(boolean front) { - return front == reversed; - } - - class PumpFluidTransferBehaviour extends FluidTransportBehaviour { - - public PumpFluidTransferBehaviour(SmartTileEntity te) { - super(te); - } - - @Override - public void tick() { - super.tick(); - for (Entry entry : interfaces.entrySet()) { - boolean pull = isPullingOnSide(isFront(entry.getKey())); - Couple pressure = entry.getValue().pressure; - pressure.set(pull, Math.abs(getSpeed())); - pressure.set(!pull, 0f); - } - } - - @Override - public boolean canHaveFlowToward(BlockState state, Direction direction) { - return isSideAccessible(direction); - } - - @Override - public AttachmentTypes getRenderedRimAttachment(BlockAndTintGetter world, BlockPos pos, BlockState state, - Direction direction) { - AttachmentTypes attachment = super.getRenderedRimAttachment(world, pos, state, direction); - if (attachment == AttachmentTypes.RIM) - return AttachmentTypes.NONE; - return attachment; - } - - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidSplashPacket.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidSplashPacket.java deleted file mode 100644 index f6bd734b0..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidSplashPacket.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.simibubi.create.content.contraptions.fluids.actors; - -import java.util.function.Supplier; - -import com.simibubi.create.content.contraptions.fluids.FluidFX; -import com.simibubi.create.foundation.networking.SimplePacketBase; - -import net.minecraft.client.Minecraft; -import net.minecraft.core.BlockPos; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fml.DistExecutor; -import net.minecraftforge.network.NetworkEvent.Context; - -public class FluidSplashPacket extends SimplePacketBase { - - private BlockPos pos; - private FluidStack fluid; - - public FluidSplashPacket(BlockPos pos, FluidStack fluid) { - this.pos = pos; - this.fluid = fluid; - } - - public FluidSplashPacket(FriendlyByteBuf buffer) { - pos = buffer.readBlockPos(); - fluid = buffer.readFluidStack(); - } - - public void write(FriendlyByteBuf buffer) { - buffer.writeBlockPos(pos); - buffer.writeFluidStack(fluid); - } - - public void handle(Supplier ctx) { - ctx.get() - .enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { - if (Minecraft.getInstance().player.position() - .distanceTo(new Vec3(pos.getX(), pos.getY(), pos.getZ())) > 100) - return; - FluidFX.splash(pos, fluid); - })); - ctx.get() - .setPacketHandled(true); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/HosePulleyRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/HosePulleyRenderer.java deleted file mode 100644 index 5f14a97d9..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/HosePulleyRenderer.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.simibubi.create.content.contraptions.fluids.actors; - -import com.jozufozu.flywheel.core.PartialModel; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.pulley.AbstractPulleyRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; - -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.Direction.Axis; - -public class HosePulleyRenderer extends AbstractPulleyRenderer { - - public HosePulleyRenderer(BlockEntityRendererProvider.Context context) { - super(context, AllBlockPartials.HOSE_HALF, AllBlockPartials.HOSE_HALF_MAGNET); - } - - @Override - protected Axis getShaftAxis(KineticTileEntity te) { - return te.getBlockState() - .getValue(HosePulleyBlock.HORIZONTAL_FACING) - .getClockWise() - .getAxis(); - } - - @Override - protected PartialModel getCoil() { - return AllBlockPartials.HOSE_COIL; - } - - @Override - protected SuperByteBuffer renderRope(KineticTileEntity te) { - return CachedBufferer.partial(AllBlockPartials.HOSE, te.getBlockState()); - } - - @Override - protected SuperByteBuffer renderMagnet(KineticTileEntity te) { - return CachedBufferer.partial(AllBlockPartials.HOSE_MAGNET, te.getBlockState()); - } - - @Override - protected float getOffset(KineticTileEntity te, float partialTicks) { - return ((HosePulleyTileEntity) te).getInterpolatedOffset(partialTicks); - } - - @Override - protected boolean isRunning(KineticTileEntity te) { - return true; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/HosePulleyTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/HosePulleyTileEntity.java deleted file mode 100644 index 30e6c2282..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/HosePulleyTileEntity.java +++ /dev/null @@ -1,192 +0,0 @@ -package com.simibubi.create.content.contraptions.fluids.actors; - -import java.util.List; - -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.fluid.SmartFluidTank; -import com.simibubi.create.foundation.item.TooltipHelper; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.utility.ServerSpeedProvider; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.AABB; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.capability.IFluidHandler; - -public class HosePulleyTileEntity extends KineticTileEntity { - - LerpedFloat offset; - boolean isMoving; - - private SmartFluidTank internalTank; - private LazyOptional capability; - private FluidDrainingBehaviour drainer; - private FluidFillingBehaviour filler; - private HosePulleyFluidHandler handler; - private boolean infinite; - - public HosePulleyTileEntity(BlockEntityType typeIn, BlockPos pos, BlockState state) { - super(typeIn, pos, state); - offset = LerpedFloat.linear() - .startWithValue(0); - isMoving = true; - internalTank = new SmartFluidTank(1500, this::onTankContentsChanged); - handler = new HosePulleyFluidHandler(internalTank, filler, drainer, - () -> worldPosition.below((int) Math.ceil(offset.getValue())), () -> !this.isMoving); - capability = LazyOptional.of(() -> handler); - } - - @Override - public void sendData() { - infinite = filler.infinite || drainer.infinite; - super.sendData(); - } - - @Override - public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { - boolean addToGoggleTooltip = super.addToGoggleTooltip(tooltip, isPlayerSneaking); - if (infinite) - TooltipHelper.addHint(tooltip, "hint.hose_pulley"); - return addToGoggleTooltip; - } - - @Override - public void addBehaviours(List behaviours) { - drainer = new FluidDrainingBehaviour(this); - filler = new FluidFillingBehaviour(this); - behaviours.add(drainer); - behaviours.add(filler); - super.addBehaviours(behaviours); - registerAwardables(behaviours, AllAdvancements.HOSE_PULLEY, AllAdvancements.HOSE_PULLEY_LAVA); - } - - protected void onTankContentsChanged(FluidStack contents) {} - - @Override - public void onSpeedChanged(float previousSpeed) { - isMoving = true; - if (getSpeed() == 0) { - offset.forceNextSync(); - offset.setValue(Math.round(offset.getValue())); - isMoving = false; - } - - if (isMoving) { - float newOffset = offset.getValue() + getMovementSpeed(); - if (newOffset < 0) - isMoving = false; - if (!level.getBlockState(worldPosition.below((int) Math.ceil(newOffset))) - .getMaterial() - .isReplaceable()) { - isMoving = false; - } - if (isMoving) { - drainer.reset(); - filler.reset(); - } - } - - super.onSpeedChanged(previousSpeed); - } - - @Override - protected AABB createRenderBoundingBox() { - return super.createRenderBoundingBox().expandTowards(0, -offset.getValue(), 0); - } - - @Override - public void tick() { - super.tick(); - float newOffset = offset.getValue() + getMovementSpeed(); - if (newOffset < 0) { - newOffset = 0; - isMoving = false; - } - if (!level.getBlockState(worldPosition.below((int) Math.ceil(newOffset))) - .getMaterial() - .isReplaceable()) { - newOffset = (int) newOffset; - isMoving = false; - } - if (getSpeed() == 0) - isMoving = false; - - offset.setValue(newOffset); - invalidateRenderBoundingBox(); - } - - @Override - public void lazyTick() { - super.lazyTick(); - if (level.isClientSide) - return; - if (isMoving) - return; - - int ceil = (int) Math.ceil(offset.getValue() + getMovementSpeed()); - if (getMovementSpeed() > 0 && level.getBlockState(worldPosition.below(ceil)) - .getMaterial() - .isReplaceable()) { - isMoving = true; - drainer.reset(); - filler.reset(); - return; - } - - sendData(); - } - - @Override - protected void write(CompoundTag compound, boolean clientPacket) { - if (clientPacket) - offset.forceNextSync(); - compound.put("Offset", offset.writeNBT()); - compound.put("Tank", internalTank.writeToNBT(new CompoundTag())); - super.write(compound, clientPacket); - if (clientPacket) - compound.putBoolean("Infinite", infinite); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - offset.readNBT(compound.getCompound("Offset"), clientPacket); - internalTank.readFromNBT(compound.getCompound("Tank")); - super.read(compound, clientPacket); - if (clientPacket) - infinite = compound.getBoolean("Infinite"); - } - - @Override - public void invalidate() { - super.invalidate(); - capability.invalidate(); - } - - public float getMovementSpeed() { - float movementSpeed = convertToLinear(getSpeed()); - if (level.isClientSide) - movementSpeed *= ServerSpeedProvider.get(); - return movementSpeed; - } - - public float getInterpolatedOffset(float pt) { - return offset.getValue(pt); - } - - @Override - public LazyOptional getCapability(Capability cap, Direction side) { - if (isFluidHandlerCap(cap) - && (side == null || HosePulleyBlock.hasPipeTowards(level, worldPosition, getBlockState(), side))) - return this.capability.cast(); - return super.getCapability(cap, side); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/ItemDrainBlock.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/ItemDrainBlock.java deleted file mode 100644 index e7a76079a..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/ItemDrainBlock.java +++ /dev/null @@ -1,125 +0,0 @@ -package com.simibubi.create.content.contraptions.fluids.actors; - -import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.processing.EmptyingByBasin; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; -import com.simibubi.create.foundation.advancement.AdvancementBehaviour; -import com.simibubi.create.foundation.block.ITE; -import com.simibubi.create.foundation.fluid.FluidHelper; -import com.simibubi.create.foundation.tileEntity.ComparatorUtil; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.Containers; -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.BlockItem; -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.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.pathfinder.PathComputationType; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.VoxelShape; -import net.minecraftforge.fluids.capability.CapabilityFluidHandler; - -public class ItemDrainBlock extends Block implements IWrenchable, ITE { - - public ItemDrainBlock(Properties p_i48440_1_) { - super(p_i48440_1_); - } - - @Override - public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, - BlockHitResult hit) { - ItemStack heldItem = player.getItemInHand(handIn); - - if (heldItem.getItem() instanceof BlockItem - && !heldItem.getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY) - .isPresent()) - return InteractionResult.PASS; - - return onTileEntityUse(worldIn, pos, te -> { - if (!heldItem.isEmpty()) { - te.internalTank.allowInsertion(); - InteractionResult tryExchange = tryExchange(worldIn, player, handIn, heldItem, te); - te.internalTank.forbidInsertion(); - if (tryExchange.consumesAction()) - return tryExchange; - } - - ItemStack heldItemStack = te.getHeldItemStack(); - if (!worldIn.isClientSide && !heldItemStack.isEmpty()) { - player.getInventory().placeItemBackInInventory(heldItemStack); - te.heldItem = null; - te.notifyUpdate(); - } - return InteractionResult.SUCCESS; - }); - } - - protected InteractionResult tryExchange(Level worldIn, Player player, InteractionHand handIn, ItemStack heldItem, - ItemDrainTileEntity te) { - if (FluidHelper.tryEmptyItemIntoTE(worldIn, player, handIn, heldItem, te)) - return InteractionResult.SUCCESS; - if (EmptyingByBasin.canItemBeEmptied(worldIn, heldItem)) - return InteractionResult.SUCCESS; - return InteractionResult.PASS; - } - - @Override - public VoxelShape getShape(BlockState p_220053_1_, BlockGetter p_220053_2_, BlockPos p_220053_3_, - CollisionContext p_220053_4_) { - return AllShapes.CASING_13PX.get(Direction.UP); - } - - @Override - public void onRemove(BlockState state, Level worldIn, BlockPos pos, BlockState newState, boolean isMoving) { - if (!state.hasBlockEntity() || state.getBlock() == newState.getBlock()) - return; - withTileEntityDo(worldIn, pos, te -> { - ItemStack heldItemStack = te.getHeldItemStack(); - if (!heldItemStack.isEmpty()) - Containers.dropItemStack(worldIn, pos.getX(), pos.getY(), pos.getZ(), heldItemStack); - }); - worldIn.removeBlockEntity(pos); - } - - @Override - public Class getTileEntityClass() { - return ItemDrainTileEntity.class; - } - - @Override - public void setPlacedBy(Level pLevel, BlockPos pPos, BlockState pState, LivingEntity pPlacer, ItemStack pStack) { - super.setPlacedBy(pLevel, pPos, pState, pPlacer, pStack); - AdvancementBehaviour.setPlacedBy(pLevel, pPos, pPlacer); - } - - @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.ITEM_DRAIN.get(); - } - - @Override - public boolean hasAnalogOutputSignal(BlockState state) { - return true; - } - - @Override - public int getAnalogOutputSignal(BlockState blockState, Level worldIn, BlockPos pos) { - return ComparatorUtil.levelOfSmartFluidTank(worldIn, pos); - } - - @Override - public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) { - return false; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/ItemDrainItemHandler.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/ItemDrainItemHandler.java deleted file mode 100644 index d04a6316a..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/ItemDrainItemHandler.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.simibubi.create.content.contraptions.fluids.actors; - -import com.simibubi.create.content.contraptions.processing.EmptyingByBasin; -import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack; - -import net.minecraft.core.Direction; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.ItemHandlerHelper; - -public class ItemDrainItemHandler implements IItemHandler { - - private ItemDrainTileEntity te; - private Direction side; - - public ItemDrainItemHandler(ItemDrainTileEntity te, Direction side) { - this.te = te; - this.side = side; - } - - @Override - public int getSlots() { - return 1; - } - - @Override - public ItemStack getStackInSlot(int slot) { - return te.getHeldItemStack(); - } - - @Override - public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) { - if (!te.getHeldItemStack() - .isEmpty()) - return stack; - - ItemStack returned = ItemStack.EMPTY; - if (stack.getCount() > 1 && EmptyingByBasin.canItemBeEmptied(te.getLevel(), stack)) { - returned = ItemHandlerHelper.copyStackWithSize(stack, stack.getCount() - 1); - stack = ItemHandlerHelper.copyStackWithSize(stack, 1); - } - - if (!simulate) { - TransportedItemStack heldItem = new TransportedItemStack(stack); - heldItem.prevBeltPosition = 0; - te.setHeldItem(heldItem, side.getOpposite()); - te.notifyUpdate(); - } - - return returned; - } - - @Override - public ItemStack extractItem(int slot, int amount, boolean simulate) { - TransportedItemStack held = te.heldItem; - if (held == null) - return ItemStack.EMPTY; - - ItemStack stack = held.stack.copy(); - ItemStack extracted = stack.split(amount); - if (!simulate) { - te.heldItem.stack = stack; - if (stack.isEmpty()) - te.heldItem = null; - te.notifyUpdate(); - } - return extracted; - } - - @Override - public int getSlotLimit(int slot) { - return 64; - } - - @Override - public boolean isItemValid(int slot, ItemStack stack) { - return true; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/ItemDrainTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/ItemDrainTileEntity.java deleted file mode 100644 index 2e9414ebf..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/ItemDrainTileEntity.java +++ /dev/null @@ -1,302 +0,0 @@ -package com.simibubi.create.content.contraptions.fluids.actors; - -import java.util.IdentityHashMap; -import java.util.List; -import java.util.Map; - -import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation; -import com.simibubi.create.content.contraptions.processing.EmptyingByBasin; -import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack; -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour; -import com.simibubi.create.foundation.utility.BlockHelper; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Pair; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.capability.CapabilityFluidHandler; -import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction; -import net.minecraftforge.items.ItemHandlerHelper; - -public class ItemDrainTileEntity extends SmartTileEntity implements IHaveGoggleInformation { - - public static final int FILLING_TIME = 20; - - SmartFluidTankBehaviour internalTank; - TransportedItemStack heldItem; - protected int processingTicks; - Map> itemHandlers; - - public ItemDrainTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - itemHandlers = new IdentityHashMap<>(); - for (Direction d : Iterate.horizontalDirections) { - ItemDrainItemHandler itemDrainItemHandler = new ItemDrainItemHandler(this, d); - itemHandlers.put(d, LazyOptional.of(() -> itemDrainItemHandler)); - } - } - - @Override - public void addBehaviours(List behaviours) { - behaviours.add(new DirectBeltInputBehaviour(this).allowingBeltFunnels() - .setInsertionHandler(this::tryInsertingFromSide)); - behaviours.add(internalTank = SmartFluidTankBehaviour.single(this, 1500) - .allowExtraction() - .forbidInsertion()); - registerAwardables(behaviours, AllAdvancements.DRAIN, AllAdvancements.CHAINED_DRAIN); - } - - private ItemStack tryInsertingFromSide(TransportedItemStack transportedStack, Direction side, boolean simulate) { - ItemStack inserted = transportedStack.stack; - ItemStack returned = ItemStack.EMPTY; - - if (!getHeldItemStack().isEmpty()) - return inserted; - - if (inserted.getCount() > 1 && EmptyingByBasin.canItemBeEmptied(level, inserted)) { - returned = ItemHandlerHelper.copyStackWithSize(inserted, inserted.getCount() - 1); - inserted = ItemHandlerHelper.copyStackWithSize(inserted, 1); - } - - if (simulate) - return returned; - - transportedStack = transportedStack.copy(); - transportedStack.stack = inserted.copy(); - transportedStack.beltPosition = side.getAxis() - .isVertical() ? .5f : 0; - transportedStack.prevSideOffset = transportedStack.sideOffset; - transportedStack.prevBeltPosition = transportedStack.beltPosition; - setHeldItem(transportedStack, side); - setChanged(); - sendData(); - - return returned; - } - - public ItemStack getHeldItemStack() { - return heldItem == null ? ItemStack.EMPTY : heldItem.stack; - } - - @Override - public void tick() { - super.tick(); - - if (heldItem == null) { - processingTicks = 0; - return; - } - - boolean onClient = level.isClientSide && !isVirtual(); - - if (processingTicks > 0) { - heldItem.prevBeltPosition = .5f; - boolean wasAtBeginning = processingTicks == FILLING_TIME; - if (!onClient || processingTicks < FILLING_TIME) - processingTicks--; - if (!continueProcessing()) { - processingTicks = 0; - notifyUpdate(); - return; - } - if (wasAtBeginning != (processingTicks == FILLING_TIME)) - sendData(); - return; - } - - heldItem.prevBeltPosition = heldItem.beltPosition; - heldItem.prevSideOffset = heldItem.sideOffset; - - heldItem.beltPosition += itemMovementPerTick(); - if (heldItem.beltPosition > 1) { - heldItem.beltPosition = 1; - - if (onClient) - return; - - Direction side = heldItem.insertedFrom; - - ItemStack tryExportingToBeltFunnel = getBehaviour(DirectBeltInputBehaviour.TYPE) - .tryExportingToBeltFunnel(heldItem.stack, side.getOpposite(), false); - if (tryExportingToBeltFunnel != null) { - if (tryExportingToBeltFunnel.getCount() != heldItem.stack.getCount()) { - if (tryExportingToBeltFunnel.isEmpty()) - heldItem = null; - else - heldItem.stack = tryExportingToBeltFunnel; - notifyUpdate(); - return; - } - if (!tryExportingToBeltFunnel.isEmpty()) - return; - } - - BlockPos nextPosition = worldPosition.relative(side); - DirectBeltInputBehaviour directBeltInputBehaviour = - TileEntityBehaviour.get(level, nextPosition, DirectBeltInputBehaviour.TYPE); - if (directBeltInputBehaviour == null) { - if (!BlockHelper.hasBlockSolidSide(level.getBlockState(nextPosition), level, nextPosition, - side.getOpposite())) { - ItemStack ejected = heldItem.stack; - Vec3 outPos = VecHelper.getCenterOf(worldPosition) - .add(Vec3.atLowerCornerOf(side.getNormal()) - .scale(.75)); - float movementSpeed = itemMovementPerTick(); - Vec3 outMotion = Vec3.atLowerCornerOf(side.getNormal()) - .scale(movementSpeed) - .add(0, 1 / 8f, 0); - outPos.add(outMotion.normalize()); - ItemEntity entity = new ItemEntity(level, outPos.x, outPos.y + 6 / 16f, outPos.z, ejected); - entity.setDeltaMovement(outMotion); - entity.setDefaultPickUpDelay(); - entity.hurtMarked = true; - level.addFreshEntity(entity); - - heldItem = null; - notifyUpdate(); - } - return; - } - - if (!directBeltInputBehaviour.canInsertFromSide(side)) - return; - - ItemStack returned = directBeltInputBehaviour.handleInsertion(heldItem.copy(), side, false); - - if (returned.isEmpty()) { - if (level.getBlockEntity(nextPosition) instanceof ItemDrainTileEntity) - award(AllAdvancements.CHAINED_DRAIN); - heldItem = null; - notifyUpdate(); - return; - } - - if (returned.getCount() != heldItem.stack.getCount()) { - heldItem.stack = returned; - notifyUpdate(); - return; - } - - return; - } - - if (heldItem.prevBeltPosition < .5f && heldItem.beltPosition >= .5f) { - if (!EmptyingByBasin.canItemBeEmptied(level, heldItem.stack)) - return; - heldItem.beltPosition = .5f; - if (onClient) - return; - processingTicks = FILLING_TIME; - sendData(); - } - - } - - protected boolean continueProcessing() { - if (level.isClientSide && !isVirtual()) - return true; - if (processingTicks < 5) - return true; - if (!EmptyingByBasin.canItemBeEmptied(level, heldItem.stack)) - return false; - - Pair emptyItem = EmptyingByBasin.emptyItem(level, heldItem.stack, true); - FluidStack fluidFromItem = emptyItem.getFirst(); - - if (processingTicks > 5) { - internalTank.allowInsertion(); - if (internalTank.getPrimaryHandler() - .fill(fluidFromItem, FluidAction.SIMULATE) != fluidFromItem.getAmount()) { - internalTank.forbidInsertion(); - processingTicks = FILLING_TIME; - return true; - } - internalTank.forbidInsertion(); - return true; - } - - emptyItem = EmptyingByBasin.emptyItem(level, heldItem.stack.copy(), false); - award(AllAdvancements.DRAIN); - - // Process finished - ItemStack out = emptyItem.getSecond(); - if (!out.isEmpty()) - heldItem.stack = out; - else - heldItem = null; - internalTank.allowInsertion(); - internalTank.getPrimaryHandler() - .fill(fluidFromItem, FluidAction.EXECUTE); - internalTank.forbidInsertion(); - notifyUpdate(); - return true; - } - - private float itemMovementPerTick() { - return 1 / 8f; - } - - @Override - public void invalidate() { - super.invalidate(); - for (LazyOptional lazyOptional : itemHandlers.values()) - lazyOptional.invalidate(); - } - - public void setHeldItem(TransportedItemStack heldItem, Direction insertedFrom) { - this.heldItem = heldItem; - this.heldItem.insertedFrom = insertedFrom; - } - - @Override - public void write(CompoundTag compound, boolean clientPacket) { - compound.putInt("ProcessingTicks", processingTicks); - if (heldItem != null) - compound.put("HeldItem", heldItem.serializeNBT()); - super.write(compound, clientPacket); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - heldItem = null; - processingTicks = compound.getInt("ProcessingTicks"); - if (compound.contains("HeldItem")) - heldItem = TransportedItemStack.read(compound.getCompound("HeldItem")); - super.read(compound, clientPacket); - } - - @Override - public LazyOptional getCapability(Capability cap, Direction side) { - if (side != null && side.getAxis() - .isHorizontal() && isItemHandlerCap(cap)) - return itemHandlers.get(side) - .cast(); - - if (side != Direction.UP && isFluidHandlerCap(cap)) - return internalTank.getCapability() - .cast(); - - return super.getCapability(cap, side); - } - - @Override - public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { - return containedFluidTooltip(tooltip, isPlayerSneaking, getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY)); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/SpoutBlock.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/SpoutBlock.java deleted file mode 100644 index b0264e0c8..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/SpoutBlock.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.simibubi.create.content.contraptions.fluids.actors; - -import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; -import com.simibubi.create.foundation.advancement.AdvancementBehaviour; -import com.simibubi.create.foundation.block.ITE; -import com.simibubi.create.foundation.tileEntity.ComparatorUtil; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.entity.LivingEntity; -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.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.pathfinder.PathComputationType; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.VoxelShape; - -public class SpoutBlock extends Block implements IWrenchable, ITE { - - public SpoutBlock(Properties p_i48440_1_) { - super(p_i48440_1_); - } - - @Override - public VoxelShape getShape(BlockState p_220053_1_, BlockGetter p_220053_2_, BlockPos p_220053_3_, - CollisionContext p_220053_4_) { - return AllShapes.SPOUT; - } - - @Override - public void setPlacedBy(Level pLevel, BlockPos pPos, BlockState pState, LivingEntity pPlacer, ItemStack pStack) { - super.setPlacedBy(pLevel, pPos, pState, pPlacer, pStack); - AdvancementBehaviour.setPlacedBy(pLevel, pPos, pPlacer); - } - - @Override - public boolean hasAnalogOutputSignal(BlockState state) { - return true; - } - - @Override - public int getAnalogOutputSignal(BlockState blockState, Level worldIn, BlockPos pos) { - return ComparatorUtil.levelOfSmartFluidTank(worldIn, pos); - } - - @Override - public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) { - return false; - } - - @Override - public Class getTileEntityClass() { - return SpoutTileEntity.class; - } - - @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.SPOUT.get(); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/SpoutRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/SpoutRenderer.java deleted file mode 100644 index cc6443589..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/SpoutRenderer.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.simibubi.create.content.contraptions.fluids.actors; - -import com.jozufozu.flywheel.core.PartialModel; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.foundation.fluid.FluidRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour.TankSegment; -import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.util.Mth; -import net.minecraft.world.phys.AABB; -import net.minecraftforge.fluids.FluidStack; - -public class SpoutRenderer extends SafeTileEntityRenderer { - - public SpoutRenderer(BlockEntityRendererProvider.Context context) { - } - - static final PartialModel[] BITS = - { AllBlockPartials.SPOUT_TOP, AllBlockPartials.SPOUT_MIDDLE, AllBlockPartials.SPOUT_BOTTOM }; - - @Override - protected void renderSafe(SpoutTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - - SmartFluidTankBehaviour tank = te.tank; - if (tank == null) - return; - - TankSegment primaryTank = tank.getPrimaryTank(); - FluidStack fluidStack = primaryTank.getRenderedFluid(); - float level = primaryTank.getFluidLevel() - .getValue(partialTicks); - - if (!fluidStack.isEmpty() && level != 0) { - level = Math.max(level, 0.175f); - float min = 2.5f / 16f; - float max = min + (11 / 16f); - float yOffset = (11 / 16f) * level; - ms.pushPose(); - ms.translate(0, yOffset, 0); - FluidRenderer.renderFluidBox(fluidStack, min, min - yOffset, min, max, min, max, buffer, ms, light, - false); - ms.popPose(); - } - - int processingTicks = te.processingTicks; - float processingPT = processingTicks - partialTicks; - float processingProgress = 1 - (processingPT - 5) / 10; - processingProgress = Mth.clamp(processingProgress, 0, 1); - float radius = 0; - - if (processingTicks != -1) { - radius = (float) (Math.pow(((2 * processingProgress) - 1), 2) - 1); - AABB bb = new AABB(0.5, .5, 0.5, 0.5, -1.2, 0.5).inflate(radius / 32f); - FluidRenderer.renderFluidBox(fluidStack, (float) bb.minX, (float) bb.minY, (float) bb.minZ, - (float) bb.maxX, (float) bb.maxY, (float) bb.maxZ, buffer, ms, light, true); - } - - float squeeze = radius; - if (processingPT < 0) - squeeze = 0; - else if (processingPT < 2) - squeeze = Mth.lerp(processingPT / 2f, 0, -1); - else if (processingPT < 10) - squeeze = -1; - - ms.pushPose(); - for (PartialModel bit : BITS) { - CachedBufferer.partial(bit, te.getBlockState()) - .light(light) - .renderInto(ms, buffer.getBuffer(RenderType.solid())); - ms.translate(0, -3 * squeeze / 32f, 0); - } - ms.popPose(); - - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/SpoutTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/SpoutTileEntity.java deleted file mode 100644 index 56525f5f5..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/SpoutTileEntity.java +++ /dev/null @@ -1,258 +0,0 @@ -package com.simibubi.create.content.contraptions.fluids.actors; - -import static com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProcessingBehaviour.ProcessingResult.HOLD; -import static com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProcessingBehaviour.ProcessingResult.PASS; - -import java.util.ArrayList; -import java.util.List; - -import com.simibubi.create.AllItems; -import com.simibubi.create.api.behaviour.BlockSpoutingBehaviour; -import com.simibubi.create.content.contraptions.fluids.FluidFX; -import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation; -import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack; -import com.simibubi.create.foundation.advancement.AdvancementBehaviour; -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.fluid.FluidHelper; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProcessingBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProcessingBehaviour.ProcessingResult; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour.TransportedResult; -import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.particles.ParticleOptions; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.capability.CapabilityFluidHandler; - -public class SpoutTileEntity extends SmartTileEntity implements IHaveGoggleInformation { - - public static final int FILLING_TIME = 20; - protected BeltProcessingBehaviour beltProcessing; - - public int processingTicks; - public boolean sendSplash; - public BlockSpoutingBehaviour customProcess; - - SmartFluidTankBehaviour tank; - - private boolean createdSweetRoll, createdHoneyApple, createdChocolateBerries; - - public SpoutTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - processingTicks = -1; - } - - @Override - protected AABB createRenderBoundingBox() { - return super.createRenderBoundingBox().expandTowards(0, -2, 0); - } - - @Override - public void addBehaviours(List behaviours) { - tank = SmartFluidTankBehaviour.single(this, 1000); - behaviours.add(tank); - - beltProcessing = new BeltProcessingBehaviour(this).whenItemEnters(this::onItemReceived) - .whileItemHeld(this::whenItemHeld); - behaviours.add(beltProcessing); - - registerAwardables(behaviours, AllAdvancements.SPOUT, AllAdvancements.FOODS); - } - - protected ProcessingResult onItemReceived(TransportedItemStack transported, - TransportedItemStackHandlerBehaviour handler) { - if (handler.tileEntity.isVirtual()) - return PASS; - if (!FillingBySpout.canItemBeFilled(level, transported.stack)) - return PASS; - if (tank.isEmpty()) - return HOLD; - if (FillingBySpout.getRequiredAmountForItem(level, transported.stack, getCurrentFluidInTank()) == -1) - return PASS; - return HOLD; - } - - protected ProcessingResult whenItemHeld(TransportedItemStack transported, - TransportedItemStackHandlerBehaviour handler) { - if (processingTicks != -1 && processingTicks != 5) - return HOLD; - if (!FillingBySpout.canItemBeFilled(level, transported.stack)) - return PASS; - if (tank.isEmpty()) - return HOLD; - FluidStack fluid = getCurrentFluidInTank(); - int requiredAmountForItem = FillingBySpout.getRequiredAmountForItem(level, transported.stack, fluid.copy()); - if (requiredAmountForItem == -1) - return PASS; - if (requiredAmountForItem > fluid.getAmount()) - return HOLD; - - if (processingTicks == -1) { - processingTicks = FILLING_TIME; - notifyUpdate(); - return HOLD; - } - - // Process finished - ItemStack out = FillingBySpout.fillItem(level, requiredAmountForItem, transported.stack, fluid); - if (!out.isEmpty()) { - List outList = new ArrayList<>(); - TransportedItemStack held = null; - TransportedItemStack result = transported.copy(); - result.stack = out; - if (!transported.stack.isEmpty()) - held = transported.copy(); - outList.add(result); - handler.handleProcessingOnItem(transported, TransportedResult.convertToAndLeaveHeld(outList, held)); - } - - award(AllAdvancements.SPOUT); - if (trackFoods()) { - createdChocolateBerries |= AllItems.CHOCOLATE_BERRIES.isIn(out); - createdHoneyApple |= AllItems.HONEYED_APPLE.isIn(out); - createdSweetRoll |= AllItems.SWEET_ROLL.isIn(out); - if (createdChocolateBerries && createdHoneyApple && createdSweetRoll) - award(AllAdvancements.FOODS); - } - - tank.getPrimaryHandler() - .setFluid(fluid); - sendSplash = true; - notifyUpdate(); - return HOLD; - } - - private FluidStack getCurrentFluidInTank() { - return tank.getPrimaryHandler() - .getFluid(); - } - - @Override - protected void write(CompoundTag compound, boolean clientPacket) { - super.write(compound, clientPacket); - - compound.putInt("ProcessingTicks", processingTicks); - if (sendSplash && clientPacket) { - compound.putBoolean("Splash", true); - sendSplash = false; - } - - if (!trackFoods()) - return; - if (createdChocolateBerries) - NBTHelper.putMarker(compound, "ChocolateBerries"); - if (createdHoneyApple) - NBTHelper.putMarker(compound, "HoneyApple"); - if (createdSweetRoll) - NBTHelper.putMarker(compound, "SweetRoll"); - } - - private boolean trackFoods() { - return getBehaviour(AdvancementBehaviour.TYPE).isOwnerPresent(); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - super.read(compound, clientPacket); - processingTicks = compound.getInt("ProcessingTicks"); - - createdChocolateBerries = compound.contains("ChocolateBerries"); - createdHoneyApple = compound.contains("HoneyApple"); - createdSweetRoll = compound.contains("SweetRoll"); - - if (!clientPacket) - return; - if (compound.contains("Splash")) - spawnSplash(tank.getPrimaryTank() - .getRenderedFluid()); - } - - @Override - public LazyOptional getCapability(Capability cap, Direction side) { - if (cap == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY && side != Direction.DOWN) - return tank.getCapability() - .cast(); - return super.getCapability(cap, side); - } - - public void tick() { - super.tick(); - - FluidStack currentFluidInTank = getCurrentFluidInTank(); - if (processingTicks == -1 && (isVirtual() || !level.isClientSide()) && !currentFluidInTank.isEmpty()) { - BlockSpoutingBehaviour.forEach(behaviour -> { - if (customProcess != null) - return; - if (behaviour.fillBlock(level, worldPosition.below(2), this, currentFluidInTank, true) > 0) { - processingTicks = FILLING_TIME; - customProcess = behaviour; - notifyUpdate(); - } - }); - } - - if (processingTicks >= 0) { - processingTicks--; - if (processingTicks == 5 && customProcess != null) { - int fillBlock = customProcess.fillBlock(level, worldPosition.below(2), this, currentFluidInTank, false); - customProcess = null; - if (fillBlock > 0) { - tank.getPrimaryHandler() - .setFluid(FluidHelper.copyStackWithAmount(currentFluidInTank, - currentFluidInTank.getAmount() - fillBlock)); - sendSplash = true; - notifyUpdate(); - } - } - } - - if (processingTicks >= 8 && level.isClientSide) - spawnProcessingParticles(tank.getPrimaryTank() - .getRenderedFluid()); - } - - protected void spawnProcessingParticles(FluidStack fluid) { - if (isVirtual()) - return; - Vec3 vec = VecHelper.getCenterOf(worldPosition); - vec = vec.subtract(0, 8 / 16f, 0); - ParticleOptions particle = FluidFX.getFluidParticle(fluid); - level.addAlwaysVisibleParticle(particle, vec.x, vec.y, vec.z, 0, -.1f, 0); - } - - protected static int SPLASH_PARTICLE_COUNT = 20; - - protected void spawnSplash(FluidStack fluid) { - if (isVirtual()) - return; - Vec3 vec = VecHelper.getCenterOf(worldPosition); - vec = vec.subtract(0, 2 - 5 / 16f, 0); - ParticleOptions particle = FluidFX.getFluidParticle(fluid); - for (int i = 0; i < SPLASH_PARTICLE_COUNT; i++) { - Vec3 m = VecHelper.offsetRandomly(Vec3.ZERO, level.random, 0.125f); - m = new Vec3(m.x, Math.abs(m.y), m.z); - level.addAlwaysVisibleParticle(particle, vec.x, vec.y, vec.z, m.x, m.y, m.z); - } - } - - @Override - public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { - return containedFluidTooltip(tooltip, isPlayerSneaking, - getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY)); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidPipeTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidPipeTileEntity.java deleted file mode 100644 index d3a238a7a..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidPipeTileEntity.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.simibubi.create.content.contraptions.fluids.pipes; - -import java.util.List; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.components.structureMovement.ITransformableTE; -import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform; -import com.simibubi.create.content.contraptions.fluids.FluidPropagator; -import com.simibubi.create.content.contraptions.fluids.FluidTransportBehaviour; -import com.simibubi.create.content.contraptions.relays.elementary.BracketedTileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.BlockAndTintGetter; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; - -public class FluidPipeTileEntity extends SmartTileEntity implements ITransformableTE { - - public FluidPipeTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - @Override - public void addBehaviours(List behaviours) { - behaviours.add(new StandardPipeFluidTransportBehaviour(this)); - behaviours.add(new BracketedTileEntityBehaviour(this, this::canHaveBracket)); - registerAwardables(behaviours, FluidPropagator.getSharedTriggers()); - } - - @Override - public void transform(StructureTransform transform) { - BracketedTileEntityBehaviour bracketBehaviour = getBehaviour(BracketedTileEntityBehaviour.TYPE); - if (bracketBehaviour != null) { - bracketBehaviour.transformBracket(transform); - } - } - - private boolean canHaveBracket(BlockState state) { - return !(state.getBlock() instanceof EncasedPipeBlock); - } - - class StandardPipeFluidTransportBehaviour extends FluidTransportBehaviour { - - public StandardPipeFluidTransportBehaviour(SmartTileEntity te) { - super(te); - } - - @Override - public boolean canHaveFlowToward(BlockState state, Direction direction) { - return (FluidPipeBlock.isPipe(state) || state.getBlock() instanceof EncasedPipeBlock) - && state.getValue(FluidPipeBlock.PROPERTY_BY_DIRECTION.get(direction)); - } - - @Override - public AttachmentTypes getRenderedRimAttachment(BlockAndTintGetter world, BlockPos pos, BlockState state, - Direction direction) { - AttachmentTypes attachment = super.getRenderedRimAttachment(world, pos, state, direction); - - BlockPos offsetPos = pos.relative(direction); - BlockState otherState = world.getBlockState(offsetPos); - - if (attachment == AttachmentTypes.RIM && !FluidPipeBlock.isPipe(otherState) - && !AllBlocks.MECHANICAL_PUMP.has(otherState) && !AllBlocks.ENCASED_FLUID_PIPE.has(otherState)) { - FluidTransportBehaviour pipeBehaviour = - TileEntityBehaviour.get(world, offsetPos, FluidTransportBehaviour.TYPE); - if (pipeBehaviour != null) - if (pipeBehaviour.canHaveFlowToward(otherState, direction.getOpposite())) - return AttachmentTypes.CONNECTION; - } - - if (attachment == AttachmentTypes.RIM && !FluidPipeBlock.shouldDrawRim(world, pos, state, direction)) - return AttachmentTypes.CONNECTION; - if (attachment == AttachmentTypes.NONE && state.getValue(FluidPipeBlock.PROPERTY_BY_DIRECTION.get(direction))) - return AttachmentTypes.CONNECTION; - return attachment; - } - - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveInstance.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveInstance.java deleted file mode 100644 index d8d688604..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveInstance.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.simibubi.create.content.contraptions.fluids.pipes; - -import com.jozufozu.flywheel.api.MaterialManager; -import com.jozufozu.flywheel.api.instance.DynamicInstance; -import com.jozufozu.flywheel.core.Materials; -import com.jozufozu.flywheel.core.materials.model.ModelData; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.content.contraptions.relays.encased.ShaftInstance; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; - -import net.minecraft.core.Direction; -import net.minecraft.util.Mth; - -public class FluidValveInstance extends ShaftInstance implements DynamicInstance { - - private final FluidValveTileEntity tile; - protected ModelData pointer; - - protected final double xRot; - protected final double yRot; - protected final int pointerRotationOffset; - - public FluidValveInstance(MaterialManager dispatcher, KineticTileEntity tile) { - super(dispatcher, tile); - this.tile = (FluidValveTileEntity) tile; - - Direction facing = blockState.getValue(FluidValveBlock.FACING); - - yRot = AngleHelper.horizontalAngle(facing); - xRot = facing == Direction.UP ? 0 : facing == Direction.DOWN ? 180 : 90; - - Direction.Axis pipeAxis = FluidValveBlock.getPipeAxis(blockState); - Direction.Axis shaftAxis = KineticTileEntityRenderer.getRotationAxisOf(tile); - - boolean twist = pipeAxis.isHorizontal() && shaftAxis == Direction.Axis.X || pipeAxis.isVertical(); - pointerRotationOffset = twist ? 90 : 0; - - pointer = materialManager.defaultSolid() - .material(Materials.TRANSFORMED) - .getModel(AllBlockPartials.FLUID_VALVE_POINTER, blockState).createInstance(); - - transformPointer(); - } - - @Override - public void beginFrame() { - if (tile.pointer.settled()) return; - - transformPointer(); - } - - private void transformPointer() { - float pointerRotation = Mth.lerp(tile.pointer.getValue(AnimationTickHolder.getPartialTicks()), 0, -90); - - pointer.loadIdentity() - .translate(getInstancePosition()) - .centre() - .rotateY(yRot) - .rotateX(xRot) - .rotateY(pointerRotationOffset + pointerRotation) - .unCentre(); - } - - @Override - public void updateLight() { - super.updateLight(); - relight(pos, pointer); - } - - @Override - public void remove() { - super.remove(); - pointer.delete(); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveRenderer.java deleted file mode 100644 index 2b6404cfe..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveRenderer.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.simibubi.create.content.contraptions.fluids.pipes; - -import com.jozufozu.flywheel.backend.Backend; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.util.Mth; -import net.minecraft.world.level.block.state.BlockState; - -public class FluidValveRenderer extends KineticTileEntityRenderer { - - public FluidValveRenderer(BlockEntityRendererProvider.Context context) { - super(context); - } - - @Override - protected void renderSafe(KineticTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - - if (Backend.canUseInstancing(te.getLevel())) return; - - super.renderSafe(te, partialTicks, ms, buffer, light, overlay); - BlockState blockState = te.getBlockState(); - SuperByteBuffer pointer = CachedBufferer.partial(AllBlockPartials.FLUID_VALVE_POINTER, blockState); - Direction facing = blockState.getValue(FluidValveBlock.FACING); - - if (!(te instanceof FluidValveTileEntity valve)) - return; - - float pointerRotation = Mth.lerp(valve.pointer.getValue(partialTicks), 0, -90); - Axis pipeAxis = FluidValveBlock.getPipeAxis(blockState); - Axis shaftAxis = KineticTileEntityRenderer.getRotationAxisOf(te); - - int pointerRotationOffset = 0; - if (pipeAxis.isHorizontal() && shaftAxis == Axis.X || pipeAxis.isVertical()) - pointerRotationOffset = 90; - - pointer.centre() - .rotateY(AngleHelper.horizontalAngle(facing)) - .rotateX(facing == Direction.UP ? 0 : facing == Direction.DOWN ? 180 : 90) - .rotateY(pointerRotationOffset + pointerRotation) - .unCentre() - .light(light) - .renderInto(ms, buffer.getBuffer(RenderType.solid())); - } - - @Override - protected BlockState getRenderedBlockState(KineticTileEntity te) { - return KineticTileEntityRenderer.shaft(KineticTileEntityRenderer.getRotationAxisOf(te)); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveTileEntity.java deleted file mode 100644 index 93d76fb9f..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveTileEntity.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.simibubi.create.content.contraptions.fluids.pipes; - -import java.util.List; - -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.fluids.FluidPropagator; -import com.simibubi.create.content.contraptions.fluids.pipes.StraightPipeTileEntity.StraightPipeFluidTransportBehaviour; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.util.Mth; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.fluids.FluidStack; - -public class FluidValveTileEntity extends KineticTileEntity { - - LerpedFloat pointer; - - public FluidValveTileEntity(BlockEntityType typeIn, BlockPos pos, BlockState state) { - super(typeIn, pos, state); - pointer = LerpedFloat.linear() - .startWithValue(0) - .chase(0, 0, Chaser.LINEAR); - } - - @Override - public void onSpeedChanged(float previousSpeed) { - super.onSpeedChanged(previousSpeed); - float speed = getSpeed(); - pointer.chase(speed > 0 ? 1 : 0, getChaseSpeed(), Chaser.LINEAR); - sendData(); - } - - @Override - public void tick() { - super.tick(); - pointer.tickChaser(); - - if (level.isClientSide) - return; - - BlockState blockState = getBlockState(); - if (!(blockState.getBlock() instanceof FluidValveBlock)) - return; - boolean stateOpen = blockState.getValue(FluidValveBlock.ENABLED); - - if (stateOpen && pointer.getValue() == 0) { - switchToBlockState(level, worldPosition, blockState.setValue(FluidValveBlock.ENABLED, false)); - return; - } - if (!stateOpen && pointer.getValue() == 1) { - switchToBlockState(level, worldPosition, blockState.setValue(FluidValveBlock.ENABLED, true)); - return; - } - } - - private float getChaseSpeed() { - return Mth.clamp(Math.abs(getSpeed()) / 16 / 20, 0, 1); - } - - @Override - protected void write(CompoundTag compound, boolean clientPacket) { - super.write(compound, clientPacket); - compound.put("Pointer", pointer.writeNBT()); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - super.read(compound, clientPacket); - pointer.readNBT(compound.getCompound("Pointer"), clientPacket); - } - - @Override - public void addBehaviours(List behaviours) { - behaviours.add(new ValvePipeBehaviour(this)); - registerAwardables(behaviours, FluidPropagator.getSharedTriggers()); - } - - class ValvePipeBehaviour extends StraightPipeFluidTransportBehaviour { - - public ValvePipeBehaviour(SmartTileEntity te) { - super(te); - } - - @Override - public boolean canHaveFlowToward(BlockState state, Direction direction) { - return FluidValveBlock.getPipeAxis(state) == direction.getAxis(); - } - - @Override - public boolean canPullFluidFrom(FluidStack fluid, BlockState state, Direction direction) { - if (state.hasProperty(FluidValveBlock.ENABLED) && state.getValue(FluidValveBlock.ENABLED)) - return super.canPullFluidFrom(fluid, state, direction); - return false; - } - - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/SmartFluidPipeTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/SmartFluidPipeTileEntity.java deleted file mode 100644 index b00346367..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/SmartFluidPipeTileEntity.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.simibubi.create.content.contraptions.fluids.pipes; - -import java.util.List; - -import com.jozufozu.flywheel.util.transform.TransformStack; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.content.contraptions.fluids.FluidPropagator; -import com.simibubi.create.content.contraptions.fluids.pipes.StraightPipeTileEntity.StraightPipeFluidTransportBehaviour; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform; -import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.AttachFace; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.fluids.FluidStack; - -public class SmartFluidPipeTileEntity extends SmartTileEntity { - - private FilteringBehaviour filter; - - public SmartFluidPipeTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - @Override - public void addBehaviours(List behaviours) { - behaviours.add(new SmartPipeBehaviour(this)); - behaviours.add(filter = new FilteringBehaviour(this, new SmartPipeFilterSlot()).forFluids() - .withCallback(this::onFilterChanged)); - registerAwardables(behaviours, FluidPropagator.getSharedTriggers()); - } - - private void onFilterChanged(ItemStack newFilter) { - if (level.isClientSide) - return; - FluidPropagator.propagateChangedPipe(level, worldPosition, getBlockState()); - } - - class SmartPipeBehaviour extends StraightPipeFluidTransportBehaviour { - - public SmartPipeBehaviour(SmartTileEntity te) { - super(te); - } - - @Override - public boolean canPullFluidFrom(FluidStack fluid, BlockState state, Direction direction) { - if (fluid.isEmpty() || filter != null && filter.test(fluid)) - return super.canPullFluidFrom(fluid, state, direction); - return false; - } - - @Override - public boolean canHaveFlowToward(BlockState state, Direction direction) { - return state.getBlock() instanceof SmartFluidPipeBlock - && SmartFluidPipeBlock.getPipeAxis(state) == direction.getAxis(); - } - - } - - class SmartPipeFilterSlot extends ValueBoxTransform { - - @Override - protected Vec3 getLocalOffset(BlockState state) { - AttachFace face = state.getValue(SmartFluidPipeBlock.FACE); - float y = face == AttachFace.CEILING ? 0.3f : face == AttachFace.WALL ? 11.3f : 15.3f; - float z = face == AttachFace.CEILING ? 4.6f : face == AttachFace.WALL ? 0.6f : 4.6f; - return VecHelper.rotateCentered(VecHelper.voxelSpace(8, y, z), angleY(state), Axis.Y); - } - - @Override - protected void rotate(BlockState state, PoseStack ms) { - AttachFace face = state.getValue(SmartFluidPipeBlock.FACE); - TransformStack.cast(ms) - .rotateY(angleY(state)) - .rotateX(face == AttachFace.CEILING ? -45 : 45); - } - - protected float angleY(BlockState state) { - AttachFace face = state.getValue(SmartFluidPipeBlock.FACE); - float horizontalAngle = AngleHelper.horizontalAngle(state.getValue(SmartFluidPipeBlock.FACING)); - if (face == AttachFace.WALL) - horizontalAngle += 180; - return horizontalAngle; - } - - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/StraightPipeTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/StraightPipeTileEntity.java deleted file mode 100644 index ec4101a09..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/StraightPipeTileEntity.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.simibubi.create.content.contraptions.fluids.pipes; - -import java.util.List; - -import com.simibubi.create.content.contraptions.fluids.FluidPropagator; -import com.simibubi.create.content.contraptions.fluids.FluidTransportBehaviour; -import com.simibubi.create.content.contraptions.relays.elementary.BracketedTileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.world.level.BlockAndTintGetter; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; - -public class StraightPipeTileEntity extends SmartTileEntity { - - public StraightPipeTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - @Override - public void addBehaviours(List behaviours) { - behaviours.add(new StraightPipeFluidTransportBehaviour(this)); - behaviours.add(new BracketedTileEntityBehaviour(this)); - registerAwardables(behaviours, FluidPropagator.getSharedTriggers()); - } - - static class StraightPipeFluidTransportBehaviour extends FluidTransportBehaviour { - - public StraightPipeFluidTransportBehaviour(SmartTileEntity te) { - super(te); - } - - @Override - public boolean canHaveFlowToward(BlockState state, Direction direction) { - return state.hasProperty(AxisPipeBlock.AXIS) && state.getValue(AxisPipeBlock.AXIS) == direction.getAxis(); - } - - @Override - public AttachmentTypes getRenderedRimAttachment(BlockAndTintGetter world, BlockPos pos, BlockState state, - Direction direction) { - AttachmentTypes attachment = super.getRenderedRimAttachment(world, pos, state, direction); - BlockState otherState = world.getBlockState(pos.relative(direction)); - - Axis axis = IAxisPipe.getAxisOf(state); - Axis otherAxis = IAxisPipe.getAxisOf(otherState); - - if (attachment == AttachmentTypes.RIM && state.getBlock() instanceof FluidValveBlock) - return AttachmentTypes.NONE; - if (attachment == AttachmentTypes.RIM && FluidPipeBlock.isPipe(otherState)) - return AttachmentTypes.PARTIAL_RIM; - if (axis == otherAxis && axis != null) - return AttachmentTypes.NONE; - - if (otherState.getBlock() instanceof FluidValveBlock - && FluidValveBlock.getPipeAxis(otherState) == direction.getAxis()) - return AttachmentTypes.NONE; - - return attachment.withoutConnector(); - } - - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/TransparentStraightPipeRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/TransparentStraightPipeRenderer.java deleted file mode 100644 index 76ed62dc4..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/TransparentStraightPipeRenderer.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.simibubi.create.content.contraptions.fluids.pipes; - -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.content.contraptions.fluids.FluidTransportBehaviour; -import com.simibubi.create.content.contraptions.fluids.PipeConnection.Flow; -import com.simibubi.create.foundation.fluid.FluidRenderer; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.Direction; -import net.minecraftforge.fluids.FluidStack; - -public class TransparentStraightPipeRenderer extends SafeTileEntityRenderer { - - public TransparentStraightPipeRenderer(BlockEntityRendererProvider.Context context) { - } - - @Override - protected void renderSafe(StraightPipeTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - FluidTransportBehaviour pipe = te.getBehaviour(FluidTransportBehaviour.TYPE); - if (pipe == null) - return; - - for (Direction side : Iterate.directions) { - - Flow flow = pipe.getFlow(side); - if (flow == null) - continue; - FluidStack fluidStack = flow.fluid; - if (fluidStack.isEmpty()) - continue; - LerpedFloat progress = flow.progress; - if (progress == null) - continue; - - float value = progress.getValue(partialTicks); - boolean inbound = flow.inbound; - if (value == 1) { - if (inbound) { - Flow opposite = pipe.getFlow(side.getOpposite()); - if (opposite == null) - value -= 1e-6f; - } else { - FluidTransportBehaviour adjacent = TileEntityBehaviour.get(te.getLevel(), te.getBlockPos() - .relative(side), FluidTransportBehaviour.TYPE); - if (adjacent == null) - value -= 1e-6f; - else { - Flow other = adjacent.getFlow(side.getOpposite()); - if (other == null || !other.inbound && !other.complete) - value -= 1e-6f; - } - } - } - - FluidRenderer.renderFluidStream(fluidStack, side, 3 / 16f, value, inbound, buffer, ms, light); - } - - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/CreativeFluidTankTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/CreativeFluidTankTileEntity.java deleted file mode 100644 index cae5e65b5..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/CreativeFluidTankTileEntity.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.simibubi.create.content.contraptions.fluids.tank; - -import java.util.List; -import java.util.function.Consumer; - -import com.simibubi.create.foundation.fluid.SmartFluidTank; - -import net.minecraft.core.BlockPos; -import net.minecraft.network.chat.Component; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.fluids.FluidStack; - -public class CreativeFluidTankTileEntity extends FluidTankTileEntity { - - public CreativeFluidTankTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - @Override - protected SmartFluidTank createInventory() { - return new CreativeSmartFluidTank(getCapacityMultiplier(), this::onFluidStackChanged); - } - - @Override - public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { - return false; - } - - public static class CreativeSmartFluidTank extends SmartFluidTank { - - public CreativeSmartFluidTank(int capacity, Consumer updateCallback) { - super(capacity, updateCallback); - } - - @Override - public int getFluidAmount() { - return getFluid().isEmpty() ? 0 : getTankCapacity(0); - } - - public void setContainedFluid(FluidStack fluidStack) { - fluid = fluidStack.copy(); - if (!fluidStack.isEmpty()) - fluid.setAmount(getTankCapacity(0)); - onContentsChanged(); - } - - @Override - public int fill(FluidStack resource, FluidAction action) { - return resource.getAmount(); - } - - @Override - public FluidStack drain(FluidStack resource, FluidAction action) { - return super.drain(resource, FluidAction.SIMULATE); - } - - @Override - public FluidStack drain(int maxDrain, FluidAction action) { - return super.drain(maxDrain, FluidAction.SIMULATE); - } - - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankRenderer.java deleted file mode 100644 index db4712241..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankRenderer.java +++ /dev/null @@ -1,119 +0,0 @@ -package com.simibubi.create.content.contraptions.fluids.tank; - -import com.jozufozu.flywheel.util.transform.TransformStack; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.foundation.fluid.FluidRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.Direction; -import net.minecraft.util.Mth; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.capability.templates.FluidTank; - -public class FluidTankRenderer extends SafeTileEntityRenderer { - - public FluidTankRenderer(BlockEntityRendererProvider.Context context) {} - - @Override - protected void renderSafe(FluidTankTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - if (!te.isController()) - return; - if (!te.window) { - if (te.boiler.isActive()) - renderAsBoiler(te, partialTicks, ms, buffer, light, overlay); - return; - } - - LerpedFloat fluidLevel = te.getFluidLevel(); - if (fluidLevel == null) - return; - - float capHeight = 1 / 4f; - float tankHullWidth = 1 / 16f + 1 / 128f; - float minPuddleHeight = 1 / 16f; - float totalHeight = te.height - 2 * capHeight - minPuddleHeight; - - float level = fluidLevel.getValue(partialTicks); - if (level < 1 / (512f * totalHeight)) - return; - float clampedLevel = Mth.clamp(level * totalHeight, 0, totalHeight); - - FluidTank tank = te.tankInventory; - FluidStack fluidStack = tank.getFluid(); - - if (fluidStack.isEmpty()) - return; - - boolean top = fluidStack.getFluid() - .getFluidType() - .isLighterThanAir(); - - float xMin = tankHullWidth; - float xMax = xMin + te.width - 2 * tankHullWidth; - float yMin = totalHeight + capHeight + minPuddleHeight - clampedLevel; - float yMax = yMin + clampedLevel; - - if (top) { - yMin += totalHeight - clampedLevel; - yMax += totalHeight - clampedLevel; - } - - float zMin = tankHullWidth; - float zMax = zMin + te.width - 2 * tankHullWidth; - - ms.pushPose(); - ms.translate(0, clampedLevel - totalHeight, 0); - FluidRenderer.renderFluidBox(fluidStack, xMin, yMin, zMin, xMax, yMax, zMax, buffer, ms, light, false); - ms.popPose(); - } - - protected void renderAsBoiler(FluidTankTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - BlockState blockState = te.getBlockState(); - VertexConsumer vb = buffer.getBuffer(RenderType.solid()); - ms.pushPose(); - TransformStack msr = TransformStack.cast(ms); - msr.translate(te.width / 2f, 0.5, te.width / 2f); - - float dialPivot = 5.75f / 16; - float progress = te.boiler.gauge.getValue(partialTicks); - - for (Direction d : Iterate.horizontalDirections) { - ms.pushPose(); - CachedBufferer.partial(AllBlockPartials.BOILER_GAUGE, blockState) - .rotateY(d.toYRot()) - .unCentre() - .translate(te.width / 2f - 6 / 16f, 0, 0) - .light(light) - .renderInto(ms, vb); - CachedBufferer.partial(AllBlockPartials.BOILER_GAUGE_DIAL, blockState) - .rotateY(d.toYRot()) - .unCentre() - .translate(te.width / 2f - 6 / 16f, 0, 0) - .translate(0, dialPivot, dialPivot) - .rotateX(-90 * progress) - .translate(0, -dialPivot, -dialPivot) - .light(light) - .renderInto(ms, vb); - ms.popPose(); - } - - ms.popPose(); - } - - @Override - public boolean shouldRenderOffScreen(FluidTankTileEntity te) { - return te.isController(); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankTileEntity.java deleted file mode 100644 index 1c9be238b..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankTileEntity.java +++ /dev/null @@ -1,628 +0,0 @@ -package com.simibubi.create.content.contraptions.fluids.tank; - -import static java.lang.Math.abs; - -import java.util.List; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import com.simibubi.create.api.connectivity.ConnectivityHandler; -import com.simibubi.create.content.contraptions.fluids.tank.FluidTankBlock.Shape; -import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation; -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.fluid.SmartFluidTank; -import com.simibubi.create.foundation.tileEntity.IMultiTileContainer; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtUtils; -import net.minecraft.network.chat.Component; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.AABB; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.FluidType; -import net.minecraftforge.fluids.IFluidTank; -import net.minecraftforge.fluids.capability.CapabilityFluidHandler; -import net.minecraftforge.fluids.capability.IFluidHandler; -import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction; -import net.minecraftforge.fluids.capability.templates.FluidTank; - -public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleInformation, IMultiTileContainer.Fluid { - - private static final int MAX_SIZE = 3; - - protected LazyOptional fluidCapability; - protected boolean forceFluidLevelUpdate; - protected FluidTank tankInventory; - protected BlockPos controller; - protected BlockPos lastKnownPos; - protected boolean updateConnectivity; - protected boolean window; - protected int luminosity; - protected int width; - protected int height; - - public BoilerData boiler; - - private static final int SYNC_RATE = 8; - protected int syncCooldown; - protected boolean queuedSync; - - // For rendering purposes only - private LerpedFloat fluidLevel; - - public FluidTankTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - tankInventory = createInventory(); - fluidCapability = LazyOptional.of(() -> tankInventory); - forceFluidLevelUpdate = true; - updateConnectivity = false; - window = true; - height = 1; - width = 1; - boiler = new BoilerData(); - refreshCapability(); - } - - protected SmartFluidTank createInventory() { - return new SmartFluidTank(getCapacityMultiplier(), this::onFluidStackChanged); - } - - protected void updateConnectivity() { - updateConnectivity = false; - if (level.isClientSide) - return; - if (!isController()) - return; - ConnectivityHandler.formMulti(this); - } - - @Override - public void tick() { - super.tick(); - if (syncCooldown > 0) { - syncCooldown--; - if (syncCooldown == 0 && queuedSync) - sendData(); - } - - if (lastKnownPos == null) - lastKnownPos = getBlockPos(); - else if (!lastKnownPos.equals(worldPosition) && worldPosition != null) { - onPositionChanged(); - return; - } - - if (updateConnectivity) - updateConnectivity(); - if (fluidLevel != null) - fluidLevel.tickChaser(); - if (isController()) - boiler.tick(this); - } - - @Override - public BlockPos getLastKnownPos() { - return lastKnownPos; - } - - @Override - public boolean isController() { - return controller == null || worldPosition.getX() == controller.getX() - && worldPosition.getY() == controller.getY() && worldPosition.getZ() == controller.getZ(); - } - - @Override - public void initialize() { - super.initialize(); - sendData(); - if (level.isClientSide) - invalidateRenderBoundingBox(); - } - - private void onPositionChanged() { - removeController(true); - lastKnownPos = worldPosition; - } - - protected void onFluidStackChanged(FluidStack newFluidStack) { - if (!hasLevel()) - return; - - FluidType attributes = newFluidStack.getFluid() - .getFluidType(); - int luminosity = (int) (attributes.getLightLevel(newFluidStack) / 1.2f); - boolean reversed = attributes.isLighterThanAir(); - int maxY = (int) ((getFillState() * height) + 1); - - for (int yOffset = 0; yOffset < height; yOffset++) { - boolean isBright = reversed ? (height - yOffset <= maxY) : (yOffset < maxY); - int actualLuminosity = isBright ? luminosity : luminosity > 0 ? 1 : 0; - - for (int xOffset = 0; xOffset < width; xOffset++) { - for (int zOffset = 0; zOffset < width; zOffset++) { - BlockPos pos = this.worldPosition.offset(xOffset, yOffset, zOffset); - FluidTankTileEntity tankAt = ConnectivityHandler.partAt(getType(), level, pos); - if (tankAt == null) - continue; - level.updateNeighbourForOutputSignal(pos, tankAt.getBlockState() - .getBlock()); - if (tankAt.luminosity == actualLuminosity) - continue; - tankAt.setLuminosity(actualLuminosity); - } - } - } - - if (!level.isClientSide) { - setChanged(); - sendData(); - } - - if (isVirtual()) { - if (fluidLevel == null) - fluidLevel = LerpedFloat.linear() - .startWithValue(getFillState()); - fluidLevel.chase(getFillState(), .5f, Chaser.EXP); - } - } - - protected void setLuminosity(int luminosity) { - if (level.isClientSide) - return; - if (this.luminosity == luminosity) - return; - this.luminosity = luminosity; - sendData(); - } - - @SuppressWarnings("unchecked") - @Override - public FluidTankTileEntity getControllerTE() { - if (isController()) - return this; - BlockEntity tileEntity = level.getBlockEntity(controller); - if (tileEntity instanceof FluidTankTileEntity) - return (FluidTankTileEntity) tileEntity; - return null; - } - - public void applyFluidTankSize(int blocks) { - tankInventory.setCapacity(blocks * getCapacityMultiplier()); - int overflow = tankInventory.getFluidAmount() - tankInventory.getCapacity(); - if (overflow > 0) - tankInventory.drain(overflow, FluidAction.EXECUTE); - forceFluidLevelUpdate = true; - } - - public void removeController(boolean keepFluids) { - if (level.isClientSide) - return; - updateConnectivity = true; - if (!keepFluids) - applyFluidTankSize(1); - controller = null; - width = 1; - height = 1; - boiler.clear(); - onFluidStackChanged(tankInventory.getFluid()); - - BlockState state = getBlockState(); - if (FluidTankBlock.isTank(state)) { - state = state.setValue(FluidTankBlock.BOTTOM, true); - state = state.setValue(FluidTankBlock.TOP, true); - state = state.setValue(FluidTankBlock.SHAPE, window ? Shape.WINDOW : Shape.PLAIN); - getLevel().setBlock(worldPosition, state, 22); - } - - refreshCapability(); - setChanged(); - sendData(); - } - - public void toggleWindows() { - FluidTankTileEntity te = getControllerTE(); - if (te == null) - return; - if (te.boiler.isActive()) - return; - te.setWindows(!te.window); - } - - public void updateBoilerTemperature() { - FluidTankTileEntity te = getControllerTE(); - if (te == null) - return; - if (!te.boiler.isActive()) - return; - te.boiler.needsHeatLevelUpdate = true; - } - - public void sendDataImmediately() { - syncCooldown = 0; - queuedSync = false; - sendData(); - } - - @Override - public void sendData() { - if (syncCooldown > 0) { - queuedSync = true; - return; - } - super.sendData(); - queuedSync = false; - syncCooldown = SYNC_RATE; - } - - public void setWindows(boolean window) { - this.window = window; - for (int yOffset = 0; yOffset < height; yOffset++) { - for (int xOffset = 0; xOffset < width; xOffset++) { - for (int zOffset = 0; zOffset < width; zOffset++) { - - BlockPos pos = this.worldPosition.offset(xOffset, yOffset, zOffset); - BlockState blockState = level.getBlockState(pos); - if (!FluidTankBlock.isTank(blockState)) - continue; - - Shape shape = Shape.PLAIN; - if (window) { - // SIZE 1: Every tank has a window - if (width == 1) - shape = Shape.WINDOW; - // SIZE 2: Every tank has a corner window - if (width == 2) - shape = xOffset == 0 ? zOffset == 0 ? Shape.WINDOW_NW : Shape.WINDOW_SW - : zOffset == 0 ? Shape.WINDOW_NE : Shape.WINDOW_SE; - // SIZE 3: Tanks in the center have a window - if (width == 3 && abs(abs(xOffset) - abs(zOffset)) == 1) - shape = Shape.WINDOW; - } - - level.setBlock(pos, blockState.setValue(FluidTankBlock.SHAPE, shape), 22); - level.getChunkSource() - .getLightEngine() - .checkBlock(pos); - } - } - } - } - - public void updateBoilerState() { - if (!isController()) - return; - - boolean wasBoiler = boiler.isActive(); - boolean changed = boiler.evaluate(this); - - if (wasBoiler != boiler.isActive()) { - if (boiler.isActive()) - setWindows(false); - - for (int yOffset = 0; yOffset < height; yOffset++) - for (int xOffset = 0; xOffset < width; xOffset++) - for (int zOffset = 0; zOffset < width; zOffset++) - if (level.getBlockEntity( - worldPosition.offset(xOffset, yOffset, zOffset)) instanceof FluidTankTileEntity fte) - fte.refreshCapability(); - } - - if (changed) { - notifyUpdate(); - boiler.checkPipeOrganAdvancement(this); - } - } - - @Override - public void setController(BlockPos controller) { - if (level.isClientSide && !isVirtual()) - return; - if (controller.equals(this.controller)) - return; - this.controller = controller; - refreshCapability(); - setChanged(); - sendData(); - } - - private void refreshCapability() { - LazyOptional oldCap = fluidCapability; - fluidCapability = LazyOptional.of(() -> handlerForCapability()); - oldCap.invalidate(); - } - - private IFluidHandler handlerForCapability() { - return isController() ? boiler.isActive() ? boiler.createHandler() : tankInventory - : getControllerTE() != null ? getControllerTE().handlerForCapability() : new FluidTank(0); - } - - @Override - public BlockPos getController() { - return isController() ? worldPosition : controller; - } - - @Override - protected AABB createRenderBoundingBox() { - if (isController()) - return super.createRenderBoundingBox().expandTowards(width - 1, height - 1, width - 1); - else - return super.createRenderBoundingBox(); - } - - @Nullable - public FluidTankTileEntity getOtherFluidTankTileEntity(Direction direction) { - BlockEntity otherTE = level.getBlockEntity(worldPosition.relative(direction)); - if (otherTE instanceof FluidTankTileEntity) - return (FluidTankTileEntity) otherTE; - return null; - } - - @Override - public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { - FluidTankTileEntity controllerTE = getControllerTE(); - if (controllerTE == null) - return false; - if (controllerTE.boiler.addToGoggleTooltip(tooltip, isPlayerSneaking, controllerTE.getTotalTankSize())) - return true; - return containedFluidTooltip(tooltip, isPlayerSneaking, - controllerTE.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY)); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - super.read(compound, clientPacket); - - BlockPos controllerBefore = controller; - int prevSize = width; - int prevHeight = height; - int prevLum = luminosity; - - updateConnectivity = compound.contains("Uninitialized"); - luminosity = compound.getInt("Luminosity"); - controller = null; - lastKnownPos = null; - - if (compound.contains("LastKnownPos")) - lastKnownPos = NbtUtils.readBlockPos(compound.getCompound("LastKnownPos")); - if (compound.contains("Controller")) - controller = NbtUtils.readBlockPos(compound.getCompound("Controller")); - - if (isController()) { - window = compound.getBoolean("Window"); - width = compound.getInt("Size"); - height = compound.getInt("Height"); - tankInventory.setCapacity(getTotalTankSize() * getCapacityMultiplier()); - tankInventory.readFromNBT(compound.getCompound("TankContent")); - if (tankInventory.getSpace() < 0) - tankInventory.drain(-tankInventory.getSpace(), FluidAction.EXECUTE); - } - - boiler.read(compound.getCompound("Boiler"), width * width * height); - - if (compound.contains("ForceFluidLevel") || fluidLevel == null) - fluidLevel = LerpedFloat.linear() - .startWithValue(getFillState()); - - if (!clientPacket) - return; - - boolean changeOfController = - controllerBefore == null ? controller != null : !controllerBefore.equals(controller); - if (changeOfController || prevSize != width || prevHeight != height) { - if (hasLevel()) - level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 16); - if (isController()) - tankInventory.setCapacity(getCapacityMultiplier() * getTotalTankSize()); - invalidateRenderBoundingBox(); - } - if (isController()) { - float fillState = getFillState(); - if (compound.contains("ForceFluidLevel") || fluidLevel == null) - fluidLevel = LerpedFloat.linear() - .startWithValue(fillState); - fluidLevel.chase(fillState, 0.5f, Chaser.EXP); - } - if (luminosity != prevLum && hasLevel()) - level.getChunkSource() - .getLightEngine() - .checkBlock(worldPosition); - - if (compound.contains("LazySync")) - fluidLevel.chase(fluidLevel.getChaseTarget(), 0.125f, Chaser.EXP); - } - - public float getFillState() { - return (float) tankInventory.getFluidAmount() / tankInventory.getCapacity(); - } - - @Override - public void write(CompoundTag compound, boolean clientPacket) { - if (updateConnectivity) - compound.putBoolean("Uninitialized", true); - compound.put("Boiler", boiler.write()); - if (lastKnownPos != null) - compound.put("LastKnownPos", NbtUtils.writeBlockPos(lastKnownPos)); - if (!isController()) - compound.put("Controller", NbtUtils.writeBlockPos(controller)); - if (isController()) { - compound.putBoolean("Window", window); - compound.put("TankContent", tankInventory.writeToNBT(new CompoundTag())); - compound.putInt("Size", width); - compound.putInt("Height", height); - } - compound.putInt("Luminosity", luminosity); - super.write(compound, clientPacket); - - if (!clientPacket) - return; - if (forceFluidLevelUpdate) - compound.putBoolean("ForceFluidLevel", true); - if (queuedSync) - compound.putBoolean("LazySync", true); - forceFluidLevelUpdate = false; - } - - @Nonnull - @Override - public LazyOptional getCapability(@Nonnull Capability cap, @Nullable Direction side) { - if (!fluidCapability.isPresent()) - refreshCapability(); - if (cap == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) - return fluidCapability.cast(); - return super.getCapability(cap, side); - } - - @Override - public void invalidate() { - super.invalidate(); - } - - @Override - public void addBehaviours(List behaviours) { - registerAwardables(behaviours, AllAdvancements.STEAM_ENGINE_MAXED, AllAdvancements.PIPE_ORGAN); - } - - public IFluidTank getTankInventory() { - return tankInventory; - } - - public int getTotalTankSize() { - return width * width * height; - } - - public static int getMaxSize() { - return MAX_SIZE; - } - - public static int getCapacityMultiplier() { - return AllConfigs.SERVER.fluids.fluidTankCapacity.get() * 1000; - } - - public static int getMaxHeight() { - return AllConfigs.SERVER.fluids.fluidTankMaxHeight.get(); - } - - public LerpedFloat getFluidLevel() { - return fluidLevel; - } - - public void setFluidLevel(LerpedFloat fluidLevel) { - this.fluidLevel = fluidLevel; - } - - @Override - public void preventConnectivityUpdate() { - updateConnectivity = false; - } - - @Override - public void notifyMultiUpdated() { - BlockState state = this.getBlockState(); - if (FluidTankBlock.isTank(state)) { // safety - state = state.setValue(FluidTankBlock.BOTTOM, getController().getY() == getBlockPos().getY()); - state = state.setValue(FluidTankBlock.TOP, getController().getY() + height - 1 == getBlockPos().getY()); - level.setBlock(getBlockPos(), state, 6); - } - if (isController()) - setWindows(window); - onFluidStackChanged(tankInventory.getFluid()); - updateBoilerState(); - setChanged(); - } - - @Override - public void setExtraData(@Nullable Object data) { - if (data instanceof Boolean) - window = (boolean) data; - } - - @Override - @Nullable - public Object getExtraData() { - return window; - } - - @Override - public Object modifyExtraData(Object data) { - if (data instanceof Boolean windows) { - windows |= window; - return windows; - } - return data; - } - - @Override - public Direction.Axis getMainConnectionAxis() { - return Direction.Axis.Y; - } - - @Override - public int getMaxLength(Direction.Axis longAxis, int width) { - if (longAxis == Direction.Axis.Y) - return getMaxHeight(); - return getMaxWidth(); - } - - @Override - public int getMaxWidth() { - return MAX_SIZE; - } - - @Override - public int getHeight() { - return height; - } - - @Override - public void setHeight(int height) { - this.height = height; - } - - @Override - public int getWidth() { - return width; - } - - @Override - public void setWidth(int width) { - this.width = width; - } - - @Override - public boolean hasTank() { - return true; - } - - @Override - public int getTankSize(int tank) { - return getCapacityMultiplier(); - } - - @Override - public void setTankSize(int tank, int blocks) { - applyFluidTankSize(blocks); - } - - @Override - public IFluidTank getTank(int tank) { - return tankInventory; - } - - @Override - public FluidStack getFluid(int tank) { - return tankInventory.getFluid() - .copy(); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageBlock.java b/src/main/java/com/simibubi/create/content/contraptions/gantry/GantryCarriageBlock.java similarity index 84% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageBlock.java rename to src/main/java/com/simibubi/create/content/contraptions/gantry/GantryCarriageBlock.java index 71ae146fc..84b4a9c4d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/gantry/GantryCarriageBlock.java @@ -1,11 +1,11 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.gantry; +package com.simibubi.create.content.contraptions.gantry; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.DirectionalAxisKineticBlock; -import com.simibubi.create.content.contraptions.base.IRotate; -import com.simibubi.create.content.contraptions.relays.advanced.GantryShaftBlock; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.content.kinetics.base.DirectionalAxisKineticBlock; +import com.simibubi.create.content.kinetics.base.IRotate; +import com.simibubi.create.content.kinetics.gantry.GantryShaftBlock; +import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.utility.Iterate; import net.minecraft.core.BlockPos; @@ -23,7 +23,7 @@ import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; -public class GantryCarriageBlock extends DirectionalAxisKineticBlock implements ITE { +public class GantryCarriageBlock extends DirectionalAxisKineticBlock implements IBE { public GantryCarriageBlock(Properties properties) { super(properties); @@ -40,7 +40,7 @@ public class GantryCarriageBlock extends DirectionalAxisKineticBlock implements @Override public void updateIndirectNeighbourShapes(BlockState stateIn, LevelAccessor worldIn, BlockPos pos, int flags, int count) { super.updateIndirectNeighbourShapes(stateIn, worldIn, pos, flags, count); - withTileEntityDo(worldIn, pos, GantryCarriageTileEntity::checkValidGantryShaft); + withBlockEntityDo(worldIn, pos, GantryCarriageBlockEntity::checkValidGantryShaft); } @Override @@ -59,7 +59,7 @@ public class GantryCarriageBlock extends DirectionalAxisKineticBlock implements return InteractionResult.PASS; if (player.getItemInHand(handIn) .isEmpty()) { - withTileEntityDo(worldIn, pos, te -> te.checkValidGantryShaft()); + withBlockEntityDo(worldIn, pos, be -> be.checkValidGantryShaft()); return InteractionResult.SUCCESS; } return InteractionResult.PASS; @@ -130,13 +130,13 @@ public class GantryCarriageBlock extends DirectionalAxisKineticBlock implements } @Override - public Class getTileEntityClass() { - return GantryCarriageTileEntity.class; + public Class getBlockEntityClass() { + return GantryCarriageBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.GANTRY_PINION.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.GANTRY_PINION.get(); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/gantry/GantryCarriageBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/gantry/GantryCarriageBlockEntity.java new file mode 100644 index 000000000..540ba53ab --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/gantry/GantryCarriageBlockEntity.java @@ -0,0 +1,192 @@ +package com.simibubi.create.content.contraptions.gantry; + +import java.util.List; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.content.contraptions.AssemblyException; +import com.simibubi.create.content.contraptions.ContraptionCollider; +import com.simibubi.create.content.contraptions.IDisplayAssemblyExceptions; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.gantry.GantryShaftBlock; +import com.simibubi.create.content.kinetics.gantry.GantryShaftBlockEntity; +import com.simibubi.create.content.kinetics.transmission.sequencer.SequencerInstructions; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.nbt.CompoundTag; +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 class GantryCarriageBlockEntity extends KineticBlockEntity implements IDisplayAssemblyExceptions { + + boolean assembleNextTick; + protected AssemblyException lastException; + + public GantryCarriageBlockEntity(BlockEntityType typeIn, BlockPos pos, BlockState state) { + super(typeIn, pos, state); + } + + @Override + public void addBehaviours(List behaviours) { + super.addBehaviours(behaviours); + registerAwardables(behaviours, AllAdvancements.CONTRAPTION_ACTORS); + } + + @Override + public void onSpeedChanged(float previousSpeed) { + super.onSpeedChanged(previousSpeed); + } + + public void checkValidGantryShaft() { + if (shouldAssemble()) + queueAssembly(); + } + + @Override + public void initialize() { + super.initialize(); + if (!getBlockState().canSurvive(level, worldPosition)) + level.destroyBlock(worldPosition, true); + } + + public void queueAssembly() { + assembleNextTick = true; + } + + @Override + public void tick() { + super.tick(); + + if (level.isClientSide) + return; + + if (assembleNextTick) { + tryAssemble(); + assembleNextTick = false; + } + } + + @Override + public AssemblyException getLastAssemblyException() { + return lastException; + } + + private void tryAssemble() { + BlockState blockState = getBlockState(); + if (!(blockState.getBlock() instanceof GantryCarriageBlock)) + return; + + Direction direction = blockState.getValue(GantryCarriageBlock.FACING); + GantryContraption contraption = new GantryContraption(direction); + + BlockEntity blockEntity = level.getBlockEntity(worldPosition.relative(direction.getOpposite())); + if (!(blockEntity instanceof GantryShaftBlockEntity shaftBE)) + return; + BlockState shaftState = shaftBE.getBlockState(); + if (!AllBlocks.GANTRY_SHAFT.has(shaftState)) + return; + + float pinionMovementSpeed = shaftBE.getPinionMovementSpeed(); + Direction shaftOrientation = shaftState.getValue(GantryShaftBlock.FACING); + Direction movementDirection = shaftOrientation; + if (pinionMovementSpeed < 0) + movementDirection = movementDirection.getOpposite(); + + try { + lastException = null; + if (!contraption.assemble(level, worldPosition)) + return; + + sendData(); + } catch (AssemblyException e) { + lastException = e; + sendData(); + return; + } + if (ContraptionCollider.isCollidingWithWorld(level, contraption, worldPosition.relative(movementDirection), + movementDirection)) + return; + + if (contraption.containsBlockBreakers()) + award(AllAdvancements.CONTRAPTION_ACTORS); + + contraption.removeBlocksFromWorld(level, BlockPos.ZERO); + GantryContraptionEntity movedContraption = + GantryContraptionEntity.create(level, contraption, shaftOrientation); + BlockPos anchor = worldPosition; + movedContraption.setPos(anchor.getX(), anchor.getY(), anchor.getZ()); + AllSoundEvents.CONTRAPTION_ASSEMBLE.playOnServer(level, worldPosition); + level.addFreshEntity(movedContraption); + + if (shaftBE.sequenceContext != null + && shaftBE.sequenceContext.instruction() == SequencerInstructions.TURN_DISTANCE) + movedContraption.limitMovement(shaftBE.sequenceContext.getEffectiveValue(shaftBE.getTheoreticalSpeed())); + } + + @Override + protected void write(CompoundTag compound, boolean clientPacket) { + AssemblyException.write(compound, lastException); + super.write(compound, clientPacket); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + lastException = AssemblyException.read(compound); + super.read(compound, clientPacket); + } + + @Override + public float propagateRotationTo(KineticBlockEntity target, BlockState stateFrom, BlockState stateTo, BlockPos diff, + boolean connectedViaAxes, boolean connectedViaCogs) { + float defaultModifier = + super.propagateRotationTo(target, stateFrom, stateTo, diff, connectedViaAxes, connectedViaCogs); + + if (connectedViaAxes) + return defaultModifier; + if (!AllBlocks.GANTRY_SHAFT.has(stateTo)) + return defaultModifier; + if (!stateTo.getValue(GantryShaftBlock.POWERED)) + return defaultModifier; + + Direction direction = Direction.getNearest(diff.getX(), diff.getY(), diff.getZ()); + if (stateFrom.getValue(GantryCarriageBlock.FACING) != direction.getOpposite()) + return defaultModifier; + return getGantryPinionModifier(stateTo.getValue(GantryShaftBlock.FACING), stateFrom.getValue(GantryCarriageBlock.FACING)); + } + + public static float getGantryPinionModifier(Direction shaft, Direction pinionDirection) { + Axis shaftAxis = shaft.getAxis(); + float directionModifier = shaft.getAxisDirection() + .getStep(); + if (shaftAxis == Axis.Y) + if (pinionDirection == Direction.NORTH || pinionDirection == Direction.EAST) + return -directionModifier; + if (shaftAxis == Axis.X) + if (pinionDirection == Direction.DOWN || pinionDirection == Direction.SOUTH) + return -directionModifier; + if (shaftAxis == Axis.Z) + if (pinionDirection == Direction.UP || pinionDirection == Direction.WEST) + return -directionModifier; + return directionModifier; + } + + private boolean shouldAssemble() { + BlockState blockState = getBlockState(); + if (!(blockState.getBlock() instanceof GantryCarriageBlock)) + return false; + Direction facing = blockState.getValue(GantryCarriageBlock.FACING) + .getOpposite(); + BlockState shaftState = level.getBlockState(worldPosition.relative(facing)); + if (!(shaftState.getBlock() instanceof GantryShaftBlock)) + return false; + if (shaftState.getValue(GantryShaftBlock.POWERED)) + return false; + BlockEntity be = level.getBlockEntity(worldPosition.relative(facing)); + return be instanceof GantryShaftBlockEntity && ((GantryShaftBlockEntity) be).canAssembleOn(); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageInstance.java b/src/main/java/com/simibubi/create/content/contraptions/gantry/GantryCarriageInstance.java similarity index 75% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageInstance.java rename to src/main/java/com/simibubi/create/content/contraptions/gantry/GantryCarriageInstance.java index f84270b53..e37f9ff40 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/gantry/GantryCarriageInstance.java @@ -1,12 +1,11 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.gantry; +package com.simibubi.create.content.contraptions.gantry; import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.api.instance.DynamicInstance; import com.jozufozu.flywheel.core.materials.model.ModelData; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.content.contraptions.relays.encased.ShaftInstance; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.content.kinetics.base.ShaftInstance; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.Iterate; @@ -14,7 +13,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.util.Mth; -public class GantryCarriageInstance extends ShaftInstance implements DynamicInstance { +public class GantryCarriageInstance extends ShaftInstance implements DynamicInstance { private final ModelData gantryCogs; @@ -26,21 +25,21 @@ public class GantryCarriageInstance extends ShaftInstance implements DynamicInst private float lastAngle = Float.NaN; - public GantryCarriageInstance(MaterialManager dispatcher, KineticTileEntity tile) { - super(dispatcher, tile); + public GantryCarriageInstance(MaterialManager materialManager, GantryCarriageBlockEntity blockEntity) { + super(materialManager, blockEntity); gantryCogs = getTransformMaterial() - .getModel(AllBlockPartials.GANTRY_COGS, blockState) + .getModel(AllPartialModels.GANTRY_COGS, blockState) .createInstance(); facing = blockState.getValue(GantryCarriageBlock.FACING); alongFirst = blockState.getValue(GantryCarriageBlock.AXIS_ALONG_FIRST_COORDINATE); - rotationAxis = KineticTileEntityRenderer.getRotationAxisOf(tile); + rotationAxis = KineticBlockEntityRenderer.getRotationAxisOf(blockEntity); rotationMult = getRotationMultiplier(getGantryAxis(), facing); - visualPos = facing.getAxisDirection() == Direction.AxisDirection.POSITIVE ? tile.getBlockPos() - : tile.getBlockPos() + visualPos = facing.getAxisDirection() == Direction.AxisDirection.POSITIVE ? blockEntity.getBlockPos() + : blockEntity.getBlockPos() .relative(facing.getOpposite()); animateCogs(getCogAngle()); @@ -56,7 +55,7 @@ public class GantryCarriageInstance extends ShaftInstance implements DynamicInst } private float getCogAngle() { - return GantryCarriageRenderer.getAngleForTe(blockEntity, visualPos, rotationAxis) * rotationMult; + return GantryCarriageRenderer.getAngleForBE(blockEntity, visualPos, rotationAxis) * rotationMult; } private void animateCogs(float cogAngle) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/gantry/GantryCarriageRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/gantry/GantryCarriageRenderer.java new file mode 100644 index 000000000..f99fe8794 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/gantry/GantryCarriageRenderer.java @@ -0,0 +1,83 @@ +package com.simibubi.create.content.contraptions.gantry; + +import com.jozufozu.flywheel.backend.Backend; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.Iterate; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.world.level.block.state.BlockState; + +public class GantryCarriageRenderer extends KineticBlockEntityRenderer { + + public GantryCarriageRenderer(BlockEntityRendererProvider.Context context) { + super(context); + } + + @Override + protected void renderSafe(GantryCarriageBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + super.renderSafe(be, partialTicks, ms, buffer, light, overlay); + + if (Backend.canUseInstancing(be.getLevel())) return; + + BlockState state = be.getBlockState(); + Direction facing = state.getValue(GantryCarriageBlock.FACING); + Boolean alongFirst = state.getValue(GantryCarriageBlock.AXIS_ALONG_FIRST_COORDINATE); + Axis rotationAxis = getRotationAxisOf(be); + BlockPos visualPos = facing.getAxisDirection() == AxisDirection.POSITIVE ? be.getBlockPos() + : be.getBlockPos() + .relative(facing.getOpposite()); + float angleForBE = getAngleForBE(be, visualPos, rotationAxis); + + Axis gantryAxis = Axis.X; + for (Axis axis : Iterate.axes) + if (axis != rotationAxis && axis != facing.getAxis()) + gantryAxis = axis; + + if (gantryAxis == Axis.X) + if (facing == Direction.UP) + angleForBE *= -1; + if (gantryAxis == Axis.Y) + if (facing == Direction.NORTH || facing == Direction.EAST) + angleForBE *= -1; + + SuperByteBuffer cogs = CachedBufferer.partial(AllPartialModels.GANTRY_COGS, state); + cogs.centre() + .rotateY(AngleHelper.horizontalAngle(facing)) + .rotateX(facing == Direction.UP ? 0 : facing == Direction.DOWN ? 180 : 90) + .rotateY(alongFirst ^ facing.getAxis() == Axis.X ? 0 : 90) + .translate(0, -9 / 16f, 0) + .rotateX(-angleForBE) + .translate(0, 9 / 16f, 0) + .unCentre(); + + cogs.light(light) + .renderInto(ms, buffer.getBuffer(RenderType.solid())); + + } + + public static float getAngleForBE(KineticBlockEntity be, final BlockPos pos, Axis axis) { + float time = AnimationTickHolder.getRenderTime(be.getLevel()); + float offset = getRotationOffsetForPosition(be, pos, axis); + return (time * be.getSpeed() * 3f / 20 + offset) % 360; + } + + @Override + protected BlockState getRenderedBlockState(GantryCarriageBlockEntity be) { + return shaft(getRotationAxisOf(be)); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/gantry/GantryContraption.java b/src/main/java/com/simibubi/create/content/contraptions/gantry/GantryContraption.java new file mode 100644 index 000000000..5b66790d9 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/gantry/GantryContraption.java @@ -0,0 +1,73 @@ +package com.simibubi.create.content.contraptions.gantry; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.contraptions.AssemblyException; +import com.simibubi.create.content.contraptions.ContraptionType; +import com.simibubi.create.content.contraptions.TranslatingContraption; +import com.simibubi.create.content.contraptions.render.ContraptionLighter; +import com.simibubi.create.content.contraptions.render.NonStationaryLighter; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public class GantryContraption extends TranslatingContraption { + + protected Direction facing; + + public GantryContraption() {} + + public GantryContraption(Direction facing) { + this.facing = facing; + } + + @Override + public boolean assemble(Level world, BlockPos pos) throws AssemblyException { + if (!searchMovedStructure(world, pos, null)) + return false; + startMoving(world); + return true; + } + + @Override + public CompoundTag writeNBT(boolean spawnPacket) { + CompoundTag tag = super.writeNBT(spawnPacket); + tag.putInt("Facing", facing.get3DDataValue()); + return tag; + } + + @Override + public void readNBT(Level world, CompoundTag tag, boolean spawnData) { + facing = Direction.from3DDataValue(tag.getInt("Facing")); + super.readNBT(world, tag, spawnData); + } + + @Override + protected boolean isAnchoringBlockAt(BlockPos pos) { + return super.isAnchoringBlockAt(pos.relative(facing)); + } + + @Override + public ContraptionType getType() { + return ContraptionType.GANTRY; + } + + public Direction getFacing() { + return facing; + } + + @Override + protected boolean shouldUpdateAfterMovement(StructureBlockInfo info) { + return super.shouldUpdateAfterMovement(info) && !AllBlocks.GANTRY_CARRIAGE.has(info.state); + } + + @Override + @OnlyIn(Dist.CLIENT) + public ContraptionLighter makeLighter() { + return new NonStationaryLighter<>(this); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/gantry/GantryContraptionEntity.java b/src/main/java/com/simibubi/create/content/contraptions/gantry/GantryContraptionEntity.java new file mode 100644 index 000000000..36e18726b --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/gantry/GantryContraptionEntity.java @@ -0,0 +1,241 @@ +package com.simibubi.create.content.contraptions.gantry; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllEntityTypes; +import com.simibubi.create.AllPackets; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.contraptions.ContraptionCollider; +import com.simibubi.create.content.contraptions.StructureTransform; +import com.simibubi.create.content.kinetics.gantry.GantryShaftBlock; +import com.simibubi.create.content.kinetics.gantry.GantryShaftBlockEntity; +import com.simibubi.create.foundation.utility.NBTHelper; +import com.simibubi.create.foundation.utility.ServerSpeedProvider; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +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.Vec3; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.network.PacketDistributor; + +public class GantryContraptionEntity extends AbstractContraptionEntity { + + Direction movementAxis; + double clientOffsetDiff; + double axisMotion; + + public double sequencedOffsetLimit; + + public GantryContraptionEntity(EntityType entityTypeIn, Level worldIn) { + super(entityTypeIn, worldIn); + sequencedOffsetLimit = -1; + } + + public static GantryContraptionEntity create(Level world, Contraption contraption, Direction movementAxis) { + GantryContraptionEntity entity = new GantryContraptionEntity(AllEntityTypes.GANTRY_CONTRAPTION.get(), world); + entity.setContraption(contraption); + entity.movementAxis = movementAxis; + return entity; + } + + public void limitMovement(double maxOffset) { + sequencedOffsetLimit = maxOffset; + } + + @Override + protected void tickContraption() { + if (!(contraption instanceof GantryContraption)) + return; + + double prevAxisMotion = axisMotion; + if (level.isClientSide) { + clientOffsetDiff *= .75f; + updateClientMotion(); + } + + checkPinionShaft(); + tickActors(); + Vec3 movementVec = getDeltaMovement(); + + if (ContraptionCollider.collideBlocks(this)) { + if (!level.isClientSide) + disassemble(); + return; + } + + if (!isStalled() && tickCount > 2) { + if (sequencedOffsetLimit >= 0) + movementVec = VecHelper.clampComponentWise(movementVec, (float) sequencedOffsetLimit); + move(movementVec.x, movementVec.y, movementVec.z); + if (sequencedOffsetLimit > 0) + sequencedOffsetLimit = Math.max(0, sequencedOffsetLimit - movementVec.length()); + } + + if (Math.signum(prevAxisMotion) != Math.signum(axisMotion) && prevAxisMotion != 0) + contraption.stop(level); + if (!level.isClientSide && (prevAxisMotion != axisMotion || tickCount % 3 == 0)) + sendPacket(); + } + + @Override + public void disassemble() { + sequencedOffsetLimit = -1; + super.disassemble(); + } + + protected void checkPinionShaft() { + Vec3 movementVec; + Direction facing = ((GantryContraption) contraption).getFacing(); + Vec3 currentPosition = getAnchorVec().add(.5, .5, .5); + BlockPos gantryShaftPos = new BlockPos(currentPosition).relative(facing.getOpposite()); + + BlockEntity be = level.getBlockEntity(gantryShaftPos); + if (!(be instanceof GantryShaftBlockEntity) || !AllBlocks.GANTRY_SHAFT.has(be.getBlockState())) { + if (!level.isClientSide) { + setContraptionMotion(Vec3.ZERO); + disassemble(); + } + return; + } + + BlockState blockState = be.getBlockState(); + Direction direction = blockState.getValue(GantryShaftBlock.FACING); + GantryShaftBlockEntity gantryShaftBlockEntity = (GantryShaftBlockEntity) be; + + float pinionMovementSpeed = gantryShaftBlockEntity.getPinionMovementSpeed(); + if (blockState.getValue(GantryShaftBlock.POWERED) || pinionMovementSpeed == 0) { + setContraptionMotion(Vec3.ZERO); + if (!level.isClientSide) + disassemble(); + return; + } + + if (sequencedOffsetLimit >= 0) + pinionMovementSpeed = (float) Mth.clamp(pinionMovementSpeed, -sequencedOffsetLimit, sequencedOffsetLimit); + movementVec = Vec3.atLowerCornerOf(direction.getNormal()) + .scale(pinionMovementSpeed); + + Vec3 nextPosition = currentPosition.add(movementVec); + double currentCoord = direction.getAxis() + .choose(currentPosition.x, currentPosition.y, currentPosition.z); + double nextCoord = direction.getAxis() + .choose(nextPosition.x, nextPosition.y, nextPosition.z); + + if ((Mth.floor(currentCoord) + .5f < nextCoord != (pinionMovementSpeed * direction.getAxisDirection() + .getStep() < 0))) + if (!gantryShaftBlockEntity.canAssembleOn()) { + setContraptionMotion(Vec3.ZERO); + if (!level.isClientSide) + disassemble(); + return; + } + + if (level.isClientSide) + return; + + axisMotion = pinionMovementSpeed; + setContraptionMotion(movementVec); + } + + @Override + protected void writeAdditional(CompoundTag compound, boolean spawnPacket) { + NBTHelper.writeEnum(compound, "GantryAxis", movementAxis); + if (sequencedOffsetLimit >= 0) + compound.putDouble("SequencedOffsetLimit", sequencedOffsetLimit); + super.writeAdditional(compound, spawnPacket); + } + + protected void readAdditional(CompoundTag compound, boolean spawnData) { + movementAxis = NBTHelper.readEnum(compound, "GantryAxis", Direction.class); + sequencedOffsetLimit = + compound.contains("SequencedOffsetLimit") ? compound.getDouble("SequencedOffsetLimit") : -1; + super.readAdditional(compound, spawnData); + } + + @Override + public Vec3 applyRotation(Vec3 localPos, float partialTicks) { + return localPos; + } + + @Override + public Vec3 reverseRotation(Vec3 localPos, float partialTicks) { + return localPos; + } + + @Override + protected StructureTransform makeStructureTransform() { + return new StructureTransform(new BlockPos(getAnchorVec().add(.5, .5, .5)), 0, 0, 0); + } + + @Override + protected float getStalledAngle() { + return 0; + } + + @Override + public void teleportTo(double p_70634_1_, double p_70634_3_, double p_70634_5_) {} + + @Override + @OnlyIn(Dist.CLIENT) + public void lerpTo(double x, double y, double z, float yw, float pt, int inc, boolean t) {} + + @Override + protected void handleStallInformation(double x, double y, double z, float angle) { + setPosRaw(x, y, z); + clientOffsetDiff = 0; + } + + @Override + public ContraptionRotationState getRotationState() { + return ContraptionRotationState.NONE; + } + + @Override + @OnlyIn(Dist.CLIENT) + public void applyLocalTransforms(PoseStack matrixStack, float partialTicks) {} + + public void updateClientMotion() { + float modifier = movementAxis.getAxisDirection() + .getStep(); + Vec3 motion = Vec3.atLowerCornerOf(movementAxis.getNormal()) + .scale((axisMotion + clientOffsetDiff * modifier / 2f) * ServerSpeedProvider.get()); + if (sequencedOffsetLimit >= 0) + motion = VecHelper.clampComponentWise(motion, (float) sequencedOffsetLimit); + setContraptionMotion(motion); + } + + public double getAxisCoord() { + Vec3 anchorVec = getAnchorVec(); + return movementAxis.getAxis() + .choose(anchorVec.x, anchorVec.y, anchorVec.z); + } + + public void sendPacket() { + AllPackets.getChannel() + .send(PacketDistributor.TRACKING_ENTITY.with(() -> this), + new GantryContraptionUpdatePacket(getId(), getAxisCoord(), axisMotion, sequencedOffsetLimit)); + } + + @OnlyIn(Dist.CLIENT) + public static void handlePacket(GantryContraptionUpdatePacket packet) { + Entity entity = Minecraft.getInstance().level.getEntity(packet.entityID); + if (!(entity instanceof GantryContraptionEntity)) + return; + GantryContraptionEntity ce = (GantryContraptionEntity) entity; + ce.axisMotion = packet.motion; + ce.clientOffsetDiff = packet.coord - ce.getAxisCoord(); + ce.sequencedOffsetLimit = packet.sequenceLimit; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/gantry/GantryContraptionUpdatePacket.java b/src/main/java/com/simibubi/create/content/contraptions/gantry/GantryContraptionUpdatePacket.java new file mode 100644 index 000000000..0ef5e7850 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/gantry/GantryContraptionUpdatePacket.java @@ -0,0 +1,46 @@ +package com.simibubi.create.content.contraptions.gantry; + +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.network.NetworkEvent.Context; + +public class GantryContraptionUpdatePacket extends SimplePacketBase { + + int entityID; + double coord; + double motion; + double sequenceLimit; + + public GantryContraptionUpdatePacket(int entityID, double coord, double motion, double sequenceLimit) { + this.entityID = entityID; + this.coord = coord; + this.motion = motion; + this.sequenceLimit = sequenceLimit; + } + + public GantryContraptionUpdatePacket(FriendlyByteBuf buffer) { + entityID = buffer.readInt(); + coord = buffer.readFloat(); + motion = buffer.readFloat(); + sequenceLimit = buffer.readFloat(); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeInt(entityID); + buffer.writeFloat((float) coord); + buffer.writeFloat((float) motion); + buffer.writeFloat((float) sequenceLimit); + } + + @Override + public boolean handle(Context context) { + context.enqueueWork( + () -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> GantryContraptionEntity.handlePacket(this))); + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/glue/GlueEffectPacket.java b/src/main/java/com/simibubi/create/content/contraptions/glue/GlueEffectPacket.java new file mode 100644 index 000000000..817cdf963 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/glue/GlueEffectPacket.java @@ -0,0 +1,53 @@ +package com.simibubi.create.content.contraptions.glue; + +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.network.NetworkEvent.Context; + +public class GlueEffectPacket extends SimplePacketBase { + + private BlockPos pos; + private Direction direction; + private boolean fullBlock; + + public GlueEffectPacket(BlockPos pos, Direction direction, boolean fullBlock) { + this.pos = pos; + this.direction = direction; + this.fullBlock = fullBlock; + } + + public GlueEffectPacket(FriendlyByteBuf buffer) { + pos = buffer.readBlockPos(); + direction = Direction.from3DDataValue(buffer.readByte()); + fullBlock = buffer.readBoolean(); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeBlockPos(pos); + buffer.writeByte(direction.get3DDataValue()); + buffer.writeBoolean(fullBlock); + } + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> this::handleClient)); + return true; + } + + @OnlyIn(Dist.CLIENT) + public void handleClient() { + Minecraft mc = Minecraft.getInstance(); + if (!mc.player.blockPosition().closerThan(pos, 100)) + return; + SuperGlueItem.spawnParticles(mc.level, pos, direction, fullBlock); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueEntity.java b/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueEntity.java similarity index 94% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueEntity.java rename to src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueEntity.java index a2dacd6c9..5c7c036ad 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueEntity.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.glue; +package com.simibubi.create.content.contraptions.glue; import java.util.ArrayList; import java.util.List; @@ -8,13 +8,13 @@ import com.simibubi.create.AllBlocks; import com.simibubi.create.AllEntityTypes; import com.simibubi.create.AllItems; import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.BlockMovementChecks; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.BearingBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.chassis.AbstractChassisBlock; -import com.simibubi.create.content.schematics.ISpecialEntityItemRequirement; -import com.simibubi.create.content.schematics.ItemRequirement; -import com.simibubi.create.content.schematics.ItemRequirement.ItemUseType; +import com.simibubi.create.content.contraptions.BlockMovementChecks; +import com.simibubi.create.content.contraptions.bearing.BearingBlock; +import com.simibubi.create.content.contraptions.chassis.AbstractChassisBlock; +import com.simibubi.create.content.kinetics.base.DirectionalKineticBlock; +import com.simibubi.create.content.schematics.requirement.ISpecialEntityItemRequirement; +import com.simibubi.create.content.schematics.requirement.ItemRequirement; +import com.simibubi.create.content.schematics.requirement.ItemRequirement.ItemUseType; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.VecHelper; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueHandler.java b/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueHandler.java similarity index 88% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueHandler.java rename to src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueHandler.java index b0ed3ca3a..87f060847 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueHandler.java @@ -1,13 +1,13 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.glue; +package com.simibubi.create.content.contraptions.glue; import java.util.HashSet; import java.util.Set; import com.simibubi.create.AllItems; -import com.simibubi.create.content.contraptions.components.structureMovement.BlockMovementChecks; -import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.AllPackets; +import com.simibubi.create.content.contraptions.BlockMovementChecks; +import com.simibubi.create.foundation.placement.IPlacementHelper; import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.placement.IPlacementHelper; import com.simibubi.create.foundation.utility.worldWrappers.RayTraceWorld; import net.minecraft.core.BlockPos; @@ -50,7 +50,7 @@ public class SuperGlueHandler { BlockPos relative = pos.relative(direction); if (SuperGlueEntity.isGlued(world, pos, direction, cached) && BlockMovementChecks.isMovementNecessary(world.getBlockState(relative), entity.level, relative)) - AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY_AND_SELF.with(() -> entity), + AllPackets.getChannel().send(PacketDistributor.TRACKING_ENTITY_AND_SELF.with(() -> entity), new GlueEffectPacket(pos, direction, true)); } @@ -101,7 +101,7 @@ public class SuperGlueHandler { if (SuperGlueEntity.isValidFace(world, gluePos, face)) { if (!world.isClientSide) { world.addFreshEntity(entity); - AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> entity), + AllPackets.getChannel().send(PacketDistributor.TRACKING_ENTITY.with(() -> entity), new GlueEffectPacket(gluePos, face, true)); } itemstack.hurtAndBreak(1, placer, SuperGlueItem::onBroken); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueItem.java b/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueItem.java similarity index 93% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueItem.java rename to src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueItem.java index ee3b0ff27..753c3cf31 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueItem.java +++ b/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueItem.java @@ -1,6 +1,6 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.glue; +package com.simibubi.create.content.contraptions.glue; -import com.simibubi.create.content.contraptions.components.structureMovement.chassis.AbstractChassisBlock; +import com.simibubi.create.content.contraptions.chassis.AbstractChassisBlock; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.core.BlockPos; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueRemovalPacket.java b/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueRemovalPacket.java similarity index 80% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueRemovalPacket.java rename to src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueRemovalPacket.java index cab9c41cd..2611c5cf0 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueRemovalPacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueRemovalPacket.java @@ -1,6 +1,4 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.glue; - -import java.util.function.Supplier; +package com.simibubi.create.content.contraptions.glue; import com.simibubi.create.AllSoundEvents; import com.simibubi.create.foundation.networking.SimplePacketBase; @@ -33,10 +31,9 @@ public class SuperGlueRemovalPacket extends SimplePacketBase { } @Override - public void handle(Supplier context) { - Context ctx = context.get(); - ctx.enqueueWork(() -> { - ServerPlayer player = ctx.getSender(); + public boolean handle(Context context) { + context.enqueueWork(() -> { + ServerPlayer player = context.getSender(); Entity entity = player.level.getEntity(entityId); if (!(entity instanceof SuperGlueEntity superGlue)) return; @@ -47,7 +44,7 @@ public class SuperGlueRemovalPacket extends SimplePacketBase { superGlue.spawnParticles(); entity.discard(); }); - ctx.setPacketHandled(true); + return true; } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueRenderer.java similarity index 89% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueRenderer.java rename to src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueRenderer.java index 8c6beab89..748ec9e0f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueRenderer.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.glue; +package com.simibubi.create.content.contraptions.glue; import net.minecraft.client.renderer.culling.Frustum; import net.minecraft.client.renderer.entity.EntityRenderer; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueSelectionHandler.java b/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueSelectionHandler.java similarity index 93% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueSelectionHandler.java rename to src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueSelectionHandler.java index b6ecc76de..13ba07060 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueSelectionHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueSelectionHandler.java @@ -1,15 +1,15 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.glue; +package com.simibubi.create.content.contraptions.glue; import java.util.List; import java.util.Optional; import java.util.Set; import com.google.common.base.Objects; +import com.simibubi.create.AllPackets; import com.simibubi.create.AllSoundEvents; import com.simibubi.create.AllSpecialTextures; import com.simibubi.create.CreateClient; -import com.simibubi.create.content.contraptions.components.structureMovement.chassis.AbstractChassisBlock; -import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.content.contraptions.chassis.AbstractChassisBlock; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.RaycastHelper; @@ -100,7 +100,7 @@ public class SuperGlueSelectionHandler { CreateClient.OUTLINER.showAABB(glueEntity, glueEntity.getBoundingBox()) .colored(h ? HIGHLIGHT : PASSIVE) .withFaceTextures(faceTex, faceTex) - .disableNormals() + .disableLineNormals() .lineWidth(h ? 1 / 16f : 1 / 64f); } } @@ -155,12 +155,12 @@ public class SuperGlueSelectionHandler { CreateClient.OUTLINER.showAABB(bbOutlineSlot, currentSelectionBox) .colored(canReach && canAfford && !cancel ? HIGHLIGHT : FAIL) .withFaceTextures(AllSpecialTextures.GLUE, AllSpecialTextures.GLUE) - .disableNormals() + .disableLineNormals() .lineWidth(1 / 16f); CreateClient.OUTLINER.showCluster(clusterOutlineSlot, currentCluster) .colored(0x4D9162) - .disableNormals() + .disableLineNormals() .lineWidth(1 / 64f); } @@ -193,7 +193,7 @@ public class SuperGlueSelectionHandler { if (attack) { if (selected == null) return false; - AllPackets.channel.sendToServer(new SuperGlueRemovalPacket(selected.getId(), soundSourceForRemoval)); + AllPackets.getChannel().sendToServer(new SuperGlueRemovalPacket(selected.getId(), soundSourceForRemoval)); selected = null; clusterCooldown = 0; return true; @@ -251,7 +251,7 @@ public class SuperGlueSelectionHandler { public void confirm() { LocalPlayer player = Minecraft.getInstance().player; - AllPackets.channel.sendToServer(new SuperGlueSelectionPacket(firstPos, hoveredPos)); + AllPackets.getChannel().sendToServer(new SuperGlueSelectionPacket(firstPos, hoveredPos)); AllSoundEvents.SLIME_ADDED.playAt(player.level, hoveredPos, 0.5F, 0.95F, false); player.level.playSound(player, hoveredPos, SoundEvents.ITEM_FRAME_ADD_ITEM, SoundSource.BLOCKS, 0.75f, 1); @@ -259,7 +259,7 @@ public class SuperGlueSelectionHandler { CreateClient.OUTLINER.showCluster(clusterOutlineSlot, currentCluster) .colored(0xB5F2C6) .withFaceTextures(AllSpecialTextures.GLUE, AllSpecialTextures.HIGHLIGHT_CHECKERED) - .disableNormals() + .disableLineNormals() .lineWidth(1 / 24f); discard(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueSelectionHelper.java b/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueSelectionHelper.java similarity index 93% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueSelectionHelper.java rename to src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueSelectionHelper.java index 4089269d5..70436fd76 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueSelectionHelper.java +++ b/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueSelectionHelper.java @@ -1,11 +1,11 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.glue; +package com.simibubi.create.content.contraptions.glue; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; -import com.simibubi.create.content.contraptions.components.structureMovement.BlockMovementChecks; +import com.simibubi.create.content.contraptions.BlockMovementChecks; import com.simibubi.create.foundation.utility.Iterate; import net.minecraft.core.BlockPos; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueSelectionPacket.java b/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueSelectionPacket.java similarity index 85% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueSelectionPacket.java rename to src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueSelectionPacket.java index ddc5b49ea..b1c3713fa 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueSelectionPacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/glue/SuperGlueSelectionPacket.java @@ -1,7 +1,6 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.glue; +package com.simibubi.create.content.contraptions.glue; import java.util.Set; -import java.util.function.Supplier; import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.networking.SimplePacketBase; @@ -36,10 +35,9 @@ public class SuperGlueSelectionPacket extends SimplePacketBase { } @Override - public void handle(Supplier context) { - Context ctx = context.get(); - ctx.enqueueWork(() -> { - ServerPlayer player = ctx.getSender(); + public boolean handle(Context context) { + context.enqueueWork(() -> { + ServerPlayer player = context.getSender(); double range = player.getAttribute(ForgeMod.REACH_DISTANCE.get()) .getValue() + 2; @@ -64,7 +62,7 @@ public class SuperGlueSelectionPacket extends SimplePacketBase { AllAdvancements.SUPER_GLUE.awardTo(player); }); - ctx.setPacketHandled(true); + return true; } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/goggles/IHaveHoveringInformation.java b/src/main/java/com/simibubi/create/content/contraptions/goggles/IHaveHoveringInformation.java deleted file mode 100644 index 061ab7e6b..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/goggles/IHaveHoveringInformation.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.simibubi.create.content.contraptions.goggles; - -import java.util.List; - -import net.minecraft.network.chat.Component; - -/* -* Implement this Interface in the TileEntity class that wants to add info to the screen -* */ -public interface IHaveHoveringInformation { - - default boolean addToTooltip(List tooltip, boolean isPlayerSneaking) { - return false; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/minecart/CouplingCreationPacket.java b/src/main/java/com/simibubi/create/content/contraptions/minecart/CouplingCreationPacket.java new file mode 100644 index 000000000..4e2889232 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/minecart/CouplingCreationPacket.java @@ -0,0 +1,40 @@ +package com.simibubi.create.content.contraptions.minecart; + +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraftforge.network.NetworkEvent.Context; + +public class CouplingCreationPacket extends SimplePacketBase { + + int id1, id2; + + public CouplingCreationPacket(AbstractMinecart cart1, AbstractMinecart cart2) { + id1 = cart1.getId(); + id2 = cart2.getId(); + } + + public CouplingCreationPacket(FriendlyByteBuf buffer) { + id1 = buffer.readInt(); + id2 = buffer.readInt(); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeInt(id1); + buffer.writeInt(id2); + } + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> { + ServerPlayer sender = context.getSender(); + if (sender != null) + CouplingHandler.tryToCoupleCarts(sender, sender.level, id1, id2); + }); + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingHandler.java b/src/main/java/com/simibubi/create/content/contraptions/minecart/CouplingHandler.java similarity index 91% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingHandler.java rename to src/main/java/com/simibubi/create/content/contraptions/minecart/CouplingHandler.java index d833d5a29..22abc9b40 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/minecart/CouplingHandler.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.train; +package com.simibubi.create.content.contraptions.minecart; import java.util.Set; import java.util.UUID; @@ -8,13 +8,13 @@ import javax.annotation.Nullable; import com.simibubi.create.AllItems; import com.simibubi.create.Create; -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.CapabilityMinecartController; -import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.MinecartController; -import com.simibubi.create.foundation.config.AllConfigs; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.minecart.capability.CapabilityMinecartController; +import com.simibubi.create.content.contraptions.minecart.capability.MinecartController; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.Entity; @@ -90,7 +90,7 @@ public class CouplingHandler { distanceTo = 2; } - if (distanceTo > AllConfigs.SERVER.kinetics.maxCartCouplingLength.get()) { + if (distanceTo > AllConfigs.server().kinetics.maxCartCouplingLength.get()) { status(player, tooFar); return false; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingHandlerClient.java b/src/main/java/com/simibubi/create/content/contraptions/minecart/CouplingHandlerClient.java similarity index 90% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingHandlerClient.java rename to src/main/java/com/simibubi/create/content/contraptions/minecart/CouplingHandlerClient.java index 57488883a..5f7f8c052 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingHandlerClient.java +++ b/src/main/java/com/simibubi/create/content/contraptions/minecart/CouplingHandlerClient.java @@ -1,9 +1,9 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.train; +package com.simibubi.create.content.contraptions.minecart; import org.joml.Vector3f; import com.simibubi.create.AllItems; -import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.AllPackets; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.client.Minecraft; @@ -45,7 +45,7 @@ public class CouplingHandlerClient { return; } spawnSelectionParticles(entity.getBoundingBox(), true); - AllPackets.channel.sendToServer(new CouplingCreationPacket(selectedCart, entity)); + AllPackets.getChannel().sendToServer(new CouplingCreationPacket(selectedCart, entity)); selectedCart = null; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingPhysics.java b/src/main/java/com/simibubi/create/content/contraptions/minecart/CouplingPhysics.java similarity index 96% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingPhysics.java rename to src/main/java/com/simibubi/create/content/contraptions/minecart/CouplingPhysics.java index d4c02314a..6031c7ea2 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingPhysics.java +++ b/src/main/java/com/simibubi/create/content/contraptions/minecart/CouplingPhysics.java @@ -1,6 +1,6 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.train; +package com.simibubi.create.content.contraptions.minecart; -import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.MinecartController; +import com.simibubi.create.content.contraptions.minecart.capability.MinecartController; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.VecHelper; diff --git a/src/main/java/com/simibubi/create/content/contraptions/minecart/CouplingRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/minecart/CouplingRenderer.java new file mode 100644 index 000000000..bb71ac3f2 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/minecart/CouplingRenderer.java @@ -0,0 +1,240 @@ +package com.simibubi.create.content.contraptions.minecart; + +import static net.minecraft.util.Mth.lerp; + +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.CreateClient; +import com.simibubi.create.content.contraptions.minecart.capability.MinecartController; +import com.simibubi.create.content.kinetics.KineticDebugger; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.Color; +import com.simibubi.create.foundation.utility.Couple; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.renderer.LevelRenderer; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class CouplingRenderer { + + public static void renderAll(PoseStack ms, MultiBufferSource buffer, Vec3 camera) { + CouplingHandler.forEachLoadedCoupling(Minecraft.getInstance().level, c -> { + if (c.getFirst() + .hasContraptionCoupling(true)) + return; + CouplingRenderer.renderCoupling(ms, buffer, camera, c.map(MinecartController::cart)); + }); + } + + public static void tickDebugModeRenders() { + if (KineticDebugger.isActive()) + CouplingHandler.forEachLoadedCoupling(Minecraft.getInstance().level, CouplingRenderer::doDebugRender); + } + + public static void renderCoupling(PoseStack ms, MultiBufferSource buffer, Vec3 camera, Couple carts) { + ClientLevel world = Minecraft.getInstance().level; + + if (carts.getFirst() == null || carts.getSecond() == null) + return; + + Couple lightValues = carts.map(c -> LevelRenderer.getLightColor(world, new BlockPos(c.getBoundingBox() + .getCenter()))); + + Vec3 center = carts.getFirst() + .position() + .add(carts.getSecond() + .position()) + .scale(.5f); + + Couple transforms = carts.map(c -> getSuitableCartEndpoint(c, center)); + + BlockState renderState = Blocks.AIR.defaultBlockState(); + VertexConsumer builder = buffer.getBuffer(RenderType.solid()); + SuperByteBuffer attachment = CachedBufferer.partial(AllPartialModels.COUPLING_ATTACHMENT, renderState); + SuperByteBuffer ring = CachedBufferer.partial(AllPartialModels.COUPLING_RING, renderState); + SuperByteBuffer connector = CachedBufferer.partial(AllPartialModels.COUPLING_CONNECTOR, renderState); + + Vec3 zero = Vec3.ZERO; + Vec3 firstEndpoint = transforms.getFirst() + .apply(zero); + Vec3 secondEndpoint = transforms.getSecond() + .apply(zero); + Vec3 endPointDiff = secondEndpoint.subtract(firstEndpoint); + double connectorYaw = -Math.atan2(endPointDiff.z, endPointDiff.x) * 180.0D / Math.PI; + double connectorPitch = Math.atan2(endPointDiff.y, endPointDiff.multiply(1, 0, 1) + .length()) * 180 / Math.PI; + + TransformStack msr = TransformStack.cast(ms); + carts.forEachWithContext((cart, isFirst) -> { + CartEndpoint cartTransform = transforms.get(isFirst); + + ms.pushPose(); + cartTransform.apply(ms, camera); + attachment.light(lightValues.get(isFirst)) + .renderInto(ms, builder); + msr.rotateY(connectorYaw - cartTransform.yaw); + ring.light(lightValues.get(isFirst)) + .renderInto(ms, builder); + ms.popPose(); + }); + + int l1 = lightValues.getFirst(); + int l2 = lightValues.getSecond(); + int meanBlockLight = (((l1 >> 4) & 0xf) + ((l2 >> 4) & 0xf)) / 2; + int meanSkyLight = (((l1 >> 20) & 0xf) + ((l2 >> 20) & 0xf)) / 2; + + ms.pushPose(); + msr.translate(firstEndpoint.subtract(camera)) + .rotateY(connectorYaw) + .rotateZ(connectorPitch); + ms.scale((float) endPointDiff.length(), 1, 1); + + connector.light(meanSkyLight << 20 | meanBlockLight << 4) + .renderInto(ms, builder); + ms.popPose(); + } + + private static CartEndpoint getSuitableCartEndpoint(AbstractMinecart cart, Vec3 centerOfCoupling) { + long i = cart.getId() * 493286711L; + i = i * i * 4392167121L + i * 98761L; + double x = (((float) (i >> 16 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F; + double y = (((float) (i >> 20 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F + 0.375F; + double z = (((float) (i >> 24 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F; + + float pt = AnimationTickHolder.getPartialTicks(); + + double xIn = lerp(pt, cart.xOld, cart.getX()); + double yIn = lerp(pt, cart.yOld, cart.getY()); + double zIn = lerp(pt, cart.zOld, cart.getZ()); + + float yaw = lerp(pt, cart.yRotO, cart.getYRot()); + float pitch = lerp(pt, cart.xRotO, cart.getXRot()); + float roll = cart.getHurtTime() - pt; + + float rollAmplifier = cart.getDamage() - pt; + if (rollAmplifier < 0.0F) + rollAmplifier = 0.0F; + roll = roll > 0 ? Mth.sin(roll) * roll * rollAmplifier / 10.0F * cart.getHurtDir() : 0; + + Vec3 positionVec = new Vec3(xIn, yIn, zIn); + Vec3 frontVec = positionVec.add(VecHelper.rotate(new Vec3(.5, 0, 0), 180 - yaw, Direction.Axis.Y)); + Vec3 backVec = positionVec.add(VecHelper.rotate(new Vec3(-.5, 0, 0), 180 - yaw, Direction.Axis.Y)); + + Vec3 railVecOfPos = cart.getPos(xIn, yIn, zIn); + boolean flip = false; + + if (railVecOfPos != null) { + frontVec = cart.getPosOffs(xIn, yIn, zIn, (double) 0.3F); + backVec = cart.getPosOffs(xIn, yIn, zIn, (double) -0.3F); + if (frontVec == null) + frontVec = railVecOfPos; + if (backVec == null) + backVec = railVecOfPos; + + x += railVecOfPos.x; + y += (frontVec.y + backVec.y) / 2; + z += railVecOfPos.z; + + Vec3 endPointDiff = backVec.add(-frontVec.x, -frontVec.y, -frontVec.z); + if (endPointDiff.length() != 0.0D) { + endPointDiff = endPointDiff.normalize(); + yaw = (float) (Math.atan2(endPointDiff.z, endPointDiff.x) * 180.0D / Math.PI); + pitch = (float) (Math.atan(endPointDiff.y) * 73.0D); + } + } else { + x += xIn; + y += yIn; + z += zIn; + } + + final float offsetMagnitude = 13 / 16f; + boolean isBackFaceCloser = frontVec.distanceToSqr(centerOfCoupling) > backVec.distanceToSqr(centerOfCoupling); + flip = isBackFaceCloser; + float offset = isBackFaceCloser ? -offsetMagnitude : offsetMagnitude; + + return new CartEndpoint(x, y + 2 / 16f, z, 180 - yaw, -pitch, roll, offset, flip); + } + + static class CartEndpoint { + + double x; + double y; + double z; + float yaw; + float pitch; + float roll; + float offset; + boolean flip; + + public CartEndpoint(double x, double y, double z, float yaw, float pitch, float roll, float offset, boolean flip) { + this.x = x; + this.y = y; + this.z = z; + this.yaw = yaw; + this.pitch = pitch; + this.roll = roll; + this.offset = offset; + this.flip = flip; + } + + public Vec3 apply(Vec3 vec) { + vec = vec.add(offset, 0, 0); + vec = VecHelper.rotate(vec, roll, Direction.Axis.X); + vec = VecHelper.rotate(vec, pitch, Direction.Axis.Z); + vec = VecHelper.rotate(vec, yaw, Direction.Axis.Y); + return vec.add(x, y, z); + } + + public void apply(PoseStack ms, Vec3 camera) { + TransformStack.cast(ms) + .translate(camera.scale(-1) + .add(x, y, z)) + .rotateY(yaw) + .rotateZ(pitch) + .rotateX(roll) + .translate(offset, 0, 0) + .rotateY(flip ? 180 : 0); + } + + } + + public static void doDebugRender(Couple c) { + int yOffset = 1; + MinecartController first = c.getFirst(); + AbstractMinecart mainCart = first.cart(); + Vec3 mainCenter = mainCart.position() + .add(0, yOffset, 0); + Vec3 connectedCenter = c.getSecond() + .cart() + .position() + .add(0, yOffset, 0); + + int color = Color.mixColors(0xabf0e9, 0xee8572, (float) Mth + .clamp(Math.abs(first.getCouplingLength(true) - connectedCenter.distanceTo(mainCenter)) * 8, 0, 1)); + + CreateClient.OUTLINER.showLine(mainCart.getId() + "", mainCenter, connectedCenter) + .colored(color) + .lineWidth(1 / 8f); + + Vec3 point = mainCart.position() + .add(0, yOffset, 0); + CreateClient.OUTLINER.showLine(mainCart.getId() + "_dot", point, point.add(0, 1 / 128f, 0)) + .colored(0xffffff) + .lineWidth(1 / 4f); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/MinecartCouplingItem.java b/src/main/java/com/simibubi/create/content/contraptions/minecart/MinecartCouplingItem.java similarity index 91% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/MinecartCouplingItem.java rename to src/main/java/com/simibubi/create/content/contraptions/minecart/MinecartCouplingItem.java index ed8094cdb..e55cbaeda 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/MinecartCouplingItem.java +++ b/src/main/java/com/simibubi/create/content/contraptions/minecart/MinecartCouplingItem.java @@ -1,8 +1,8 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.train; +package com.simibubi.create.content.contraptions.minecart; import com.simibubi.create.AllItems; -import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.CapabilityMinecartController; -import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.MinecartController; +import com.simibubi.create.content.contraptions.minecart.capability.CapabilityMinecartController; +import com.simibubi.create.content.contraptions.minecart.capability.MinecartController; import com.simibubi.create.foundation.utility.Iterate; import net.minecraft.world.InteractionResult; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/MinecartSim2020.java b/src/main/java/com/simibubi/create/content/contraptions/minecart/MinecartSim2020.java similarity index 95% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/MinecartSim2020.java rename to src/main/java/com/simibubi/create/content/contraptions/minecart/MinecartSim2020.java index ebdfd34c5..f10eab8f7 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/MinecartSim2020.java +++ b/src/main/java/com/simibubi/create/content/contraptions/minecart/MinecartSim2020.java @@ -1,11 +1,11 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.train; +package com.simibubi.create.content.contraptions.minecart; import java.util.Map; import com.google.common.collect.Maps; import com.mojang.datafixers.util.Pair; -import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.CapabilityMinecartController; -import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.MinecartController; +import com.simibubi.create.content.contraptions.minecart.capability.CapabilityMinecartController; +import com.simibubi.create.content.contraptions.minecart.capability.MinecartController; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.Util; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/TrainCargoManager.java b/src/main/java/com/simibubi/create/content/contraptions/minecart/TrainCargoManager.java similarity index 90% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/TrainCargoManager.java rename to src/main/java/com/simibubi/create/content/contraptions/minecart/TrainCargoManager.java index 5d8561369..6b045b69a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/TrainCargoManager.java +++ b/src/main/java/com/simibubi/create/content/contraptions/minecart/TrainCargoManager.java @@ -1,12 +1,12 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.train; +package com.simibubi.create.content.contraptions.minecart; import java.util.Arrays; import java.util.Collection; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; -import com.simibubi.create.content.contraptions.components.structureMovement.Contraption.ContraptionInvWrapper; -import com.simibubi.create.content.contraptions.components.structureMovement.MountedStorageManager; +import com.simibubi.create.content.contraptions.Contraption.ContraptionInvWrapper; +import com.simibubi.create.content.contraptions.MountedStorageManager; import com.simibubi.create.foundation.fluid.CombinedTankWrapper; import net.minecraft.core.BlockPos; @@ -51,8 +51,8 @@ public class TrainCargoManager extends MountedStorageManager { } @Override - public void read(CompoundTag nbt, Map presentTileEntities, boolean clientPacket) { - super.read(nbt, presentTileEntities, clientPacket); + public void read(CompoundTag nbt, Map presentBlockEntities, boolean clientPacket) { + super.read(nbt, presentBlockEntities, clientPacket); ticksSinceLastExchange = nbt.getInt("TicksSinceLastExchange"); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/capability/CapabilityMinecartController.java b/src/main/java/com/simibubi/create/content/contraptions/minecart/capability/CapabilityMinecartController.java similarity index 97% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/capability/CapabilityMinecartController.java rename to src/main/java/com/simibubi/create/content/contraptions/minecart/capability/CapabilityMinecartController.java index a3fbf8c69..24f172f4a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/capability/CapabilityMinecartController.java +++ b/src/main/java/com/simibubi/create/content/contraptions/minecart/capability/CapabilityMinecartController.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.train.capability; +package com.simibubi.create.content.contraptions.minecart.capability; import java.util.ArrayList; import java.util.HashMap; @@ -13,7 +13,7 @@ import javax.annotation.Nullable; import com.simibubi.create.AllItems; import com.simibubi.create.Create; -import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingHandler; +import com.simibubi.create.content.contraptions.minecart.CouplingHandler; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.WorldAttached; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/capability/MinecartController.java b/src/main/java/com/simibubi/create/content/contraptions/minecart/capability/MinecartController.java similarity index 95% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/capability/MinecartController.java rename to src/main/java/com/simibubi/create/content/contraptions/minecart/capability/MinecartController.java index df2f10db0..77677dfdb 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/capability/MinecartController.java +++ b/src/main/java/com/simibubi/create/content/contraptions/minecart/capability/MinecartController.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.train.capability; +package com.simibubi.create.content.contraptions.minecart.capability; import java.lang.ref.WeakReference; import java.util.ArrayList; @@ -10,11 +10,11 @@ import javax.annotation.Nullable; import org.apache.commons.lang3.mutable.MutableBoolean; +import com.simibubi.create.AllPackets; import com.simibubi.create.Create; -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingHandler; -import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.OrientedContraptionEntity; +import com.simibubi.create.content.contraptions.minecart.CouplingHandler; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.NBTHelper; @@ -292,7 +292,7 @@ public class MinecartController implements INBTSerializable { public void sendData() { if (getWorld().isClientSide) return; - AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(this::cart), + AllPackets.getChannel().send(PacketDistributor.TRACKING_ENTITY.with(this::cart), new MinecartControllerUpdatePacket(this)); } @@ -404,7 +404,7 @@ public class MinecartController implements INBTSerializable { } void tick(AbstractMinecart entity) { - entity.setPos(position.x, position.y, position.z); +// entity.setPos(position.x, position.y, position.z); entity.setDeltaMovement(Vec3.ZERO); entity.setYRot(yaw); entity.setXRot(pitch); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/capability/MinecartControllerUpdatePacket.java b/src/main/java/com/simibubi/create/content/contraptions/minecart/capability/MinecartControllerUpdatePacket.java similarity index 80% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/capability/MinecartControllerUpdatePacket.java rename to src/main/java/com/simibubi/create/content/contraptions/minecart/capability/MinecartControllerUpdatePacket.java index 81e749bc5..009edc376 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/capability/MinecartControllerUpdatePacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/minecart/capability/MinecartControllerUpdatePacket.java @@ -1,6 +1,4 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.train.capability; - -import java.util.function.Supplier; +package com.simibubi.create.content.contraptions.minecart.capability; import com.simibubi.create.foundation.networking.SimplePacketBase; @@ -37,11 +35,9 @@ public class MinecartControllerUpdatePacket extends SimplePacketBase { } @Override - public void handle(Supplier context) { - context.get() - .enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> this::handleCL)); - context.get() - .setPacketHandled(true); + public boolean handle(Context context) { + context.enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> this::handleCL)); + return true; } @OnlyIn(Dist.CLIENT) diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssembleRailType.java b/src/main/java/com/simibubi/create/content/contraptions/mounted/CartAssembleRailType.java similarity index 93% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssembleRailType.java rename to src/main/java/com/simibubi/create/content/contraptions/mounted/CartAssembleRailType.java index 0810b6a34..bca741cc7 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssembleRailType.java +++ b/src/main/java/com/simibubi/create/content/contraptions/mounted/CartAssembleRailType.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.mounted; +package com.simibubi.create.content.contraptions.mounted; import java.util.function.Supplier; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssemblerBlock.java b/src/main/java/com/simibubi/create/content/contraptions/mounted/CartAssemblerBlock.java similarity index 93% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssemblerBlock.java rename to src/main/java/com/simibubi/create/content/contraptions/mounted/CartAssemblerBlock.java index 9f54717cf..90c760339 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssemblerBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/mounted/CartAssemblerBlock.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.mounted; +package com.simibubi.create.content.contraptions.mounted; import java.util.ArrayList; import java.util.List; @@ -6,15 +6,15 @@ import java.util.List; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.components.tracks.ControllerRailBlock; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; -import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement; -import com.simibubi.create.content.schematics.ItemRequirement; -import com.simibubi.create.content.schematics.ItemRequirement.ItemUseType; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.content.redstone.rail.ControllerRailBlock; +import com.simibubi.create.content.schematics.requirement.ISpecialBlockItemRequirement; +import com.simibubi.create.content.schematics.requirement.ItemRequirement; +import com.simibubi.create.content.schematics.requirement.ItemRequirement.ItemUseType; +import com.simibubi.create.foundation.block.IBE; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -60,7 +60,7 @@ import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; public class CartAssemblerBlock extends BaseRailBlock - implements ITE, IWrenchable, ISpecialBlockItemRequirement { + implements IBE, IWrenchable, ISpecialBlockItemRequirement { public static final BooleanProperty POWERED = BlockStateProperties.POWERED; public static final BooleanProperty BACKWARDS = BooleanProperty.create("backwards"); @@ -120,7 +120,7 @@ public class CartAssemblerBlock extends BaseRailBlock if (world.isClientSide) return; - withTileEntityDo(world, pos, te -> te.assembleNextTick(cart)); + withBlockEntityDo(world, pos, be -> be.assembleNextTick(cart)); } public enum CartAssemblerAction { @@ -239,13 +239,13 @@ public class CartAssemblerBlock extends BaseRailBlock } @Override - public Class getTileEntityClass() { - return CartAssemblerTileEntity.class; + public Class getBlockEntityClass() { + return CartAssemblerBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.CART_ASSEMBLER.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.CART_ASSEMBLER.get(); } @Override @@ -254,7 +254,7 @@ public class CartAssemblerBlock extends BaseRailBlock } @Override - public ItemRequirement getRequiredItems(BlockState state, BlockEntity te) { + public ItemRequirement getRequiredItems(BlockState state, BlockEntity be) { ArrayList requiredItems = new ArrayList<>(); requiredItems.add(new ItemStack(getRailItem(state))); requiredItems.add(new ItemStack(asItem())); diff --git a/src/main/java/com/simibubi/create/content/contraptions/mounted/CartAssemblerBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/mounted/CartAssemblerBlockEntity.java new file mode 100644 index 000000000..f7de3c401 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/mounted/CartAssemblerBlockEntity.java @@ -0,0 +1,324 @@ +package com.simibubi.create.content.contraptions.mounted; + +import java.util.List; +import java.util.UUID; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.contraptions.AssemblyException; +import com.simibubi.create.content.contraptions.IDisplayAssemblyExceptions; +import com.simibubi.create.content.contraptions.OrientedContraptionEntity; +import com.simibubi.create.content.contraptions.minecart.CouplingHandler; +import com.simibubi.create.content.contraptions.minecart.capability.CapabilityMinecartController; +import com.simibubi.create.content.contraptions.minecart.capability.MinecartController; +import com.simibubi.create.content.redstone.rail.ControllerRailBlock; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.CenteredSideValueBoxTransform; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; +import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.INamedIconOptions; +import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollOptionBehaviour; +import com.simibubi.create.foundation.gui.AllIcons; +import com.simibubi.create.foundation.utility.Couple; +import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.Vec3i; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.MinecartFurnace; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.RailShape; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; + +@EventBusSubscriber +public class CartAssemblerBlockEntity extends SmartBlockEntity implements IDisplayAssemblyExceptions { + private static final int assemblyCooldown = 8; + + protected ScrollOptionBehaviour movementMode; + private int ticksSinceMinecartUpdate; + protected AssemblyException lastException; + protected AbstractMinecart cartToAssemble; + + public CartAssemblerBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + ticksSinceMinecartUpdate = assemblyCooldown; + } + + @Override + public void tick() { + super.tick(); + if (ticksSinceMinecartUpdate < assemblyCooldown) { + ticksSinceMinecartUpdate++; + } + + tryAssemble(cartToAssemble); + cartToAssemble = null; + } + + public void tryAssemble(AbstractMinecart cart) { + if (cart == null) + return; + + if (!isMinecartUpdateValid()) + return; + resetTicksSinceMinecartUpdate(); + + BlockState state = level.getBlockState(worldPosition); + if (!AllBlocks.CART_ASSEMBLER.has(state)) + return; + CartAssemblerBlock block = (CartAssemblerBlock) state.getBlock(); + + CartAssemblerBlock.CartAssemblerAction action = CartAssemblerBlock.getActionForCart(state, cart); + if (action.shouldAssemble()) + assemble(level, worldPosition, cart); + if (action.shouldDisassemble()) + disassemble(level, worldPosition, cart); + if (action == CartAssemblerBlock.CartAssemblerAction.ASSEMBLE_ACCELERATE) { + if (cart.getDeltaMovement() + .length() > 1 / 128f) { + Direction facing = cart.getMotionDirection(); + RailShape railShape = state.getValue(CartAssemblerBlock.RAIL_SHAPE); + for (Direction d : Iterate.directionsInAxis(railShape == RailShape.EAST_WEST ? Axis.X : Axis.Z)) + if (level.getBlockState(worldPosition.relative(d)) + .isRedstoneConductor(level, worldPosition.relative(d))) + facing = d.getOpposite(); + + float speed = block.getRailMaxSpeed(state, level, worldPosition, cart); + cart.setDeltaMovement(facing.getStepX() * speed, facing.getStepY() * speed, facing.getStepZ() * speed); + } + } + if (action == CartAssemblerBlock.CartAssemblerAction.ASSEMBLE_ACCELERATE_DIRECTIONAL) { + Vec3i accelerationVector = + ControllerRailBlock.getAccelerationVector(AllBlocks.CONTROLLER_RAIL.getDefaultState() + .setValue(ControllerRailBlock.SHAPE, state.getValue(CartAssemblerBlock.RAIL_SHAPE)) + .setValue(ControllerRailBlock.BACKWARDS, state.getValue(CartAssemblerBlock.BACKWARDS))); + float speed = block.getRailMaxSpeed(state, level, worldPosition, cart); + cart.setDeltaMovement(Vec3.atLowerCornerOf(accelerationVector) + .scale(speed)); + } + if (action == CartAssemblerBlock.CartAssemblerAction.DISASSEMBLE_BRAKE) { + Vec3 diff = VecHelper.getCenterOf(worldPosition) + .subtract(cart.position()); + cart.setDeltaMovement(diff.x / 16f, 0, diff.z / 16f); + } + } + + protected void assemble(Level world, BlockPos pos, AbstractMinecart cart) { + if (!cart.getPassengers() + .isEmpty()) + return; + + LazyOptional optional = + cart.getCapability(CapabilityMinecartController.MINECART_CONTROLLER_CAPABILITY); + if (optional.isPresent() && optional.orElse(null) + .isCoupledThroughContraption()) + return; + + CartMovementMode mode = CartMovementMode.values()[movementMode.value]; + + MountedContraption contraption = new MountedContraption(mode); + try { + if (!contraption.assemble(world, pos)) + return; + + lastException = null; + sendData(); + } catch (AssemblyException e) { + lastException = e; + sendData(); + return; + } + + boolean couplingFound = contraption.connectedCart != null; + Direction initialOrientation = CartAssemblerBlock.getHorizontalDirection(getBlockState()); + + if (couplingFound) { + cart.setPos(pos.getX() + .5f, pos.getY(), pos.getZ() + .5f); + if (!CouplingHandler.tryToCoupleCarts(null, world, cart.getId(), + contraption.connectedCart.getId())) + return; + } + + contraption.removeBlocksFromWorld(world, BlockPos.ZERO); + contraption.startMoving(world); + contraption.expandBoundsAroundAxis(Axis.Y); + + if (couplingFound) { + Vec3 diff = contraption.connectedCart.position() + .subtract(cart.position()); + initialOrientation = Direction.fromYRot(Mth.atan2(diff.z, diff.x) * 180 / Math.PI); + } + + OrientedContraptionEntity entity = OrientedContraptionEntity.create(world, contraption, initialOrientation); + if (couplingFound) + entity.setCouplingId(cart.getUUID()); + entity.setPos(pos.getX() + .5, pos.getY(), pos.getZ() + .5); + world.addFreshEntity(entity); + entity.startRiding(cart); + + if (cart instanceof MinecartFurnace) { + CompoundTag nbt = cart.serializeNBT(); + nbt.putDouble("PushZ", 0); + nbt.putDouble("PushX", 0); + cart.deserializeNBT(nbt); + } + + if (contraption.containsBlockBreakers()) + award(AllAdvancements.CONTRAPTION_ACTORS); + } + + protected void disassemble(Level world, BlockPos pos, AbstractMinecart cart) { + if (cart.getPassengers() + .isEmpty()) + return; + Entity entity = cart.getPassengers() + .get(0); + if (!(entity instanceof OrientedContraptionEntity)) + return; + OrientedContraptionEntity contraption = (OrientedContraptionEntity) entity; + UUID couplingId = contraption.getCouplingId(); + + if (couplingId == null) { + contraption.yaw = CartAssemblerBlock.getHorizontalDirection(getBlockState()) + .toYRot(); + disassembleCart(cart); + return; + } + + Couple coupledCarts = contraption.getCoupledCartsIfPresent(); + if (coupledCarts == null) + return; + + // Make sure connected cart is present and being disassembled + for (boolean current : Iterate.trueAndFalse) { + MinecartController minecartController = coupledCarts.get(current); + if (minecartController.cart() == cart) + continue; + BlockPos otherPos = minecartController.cart() + .blockPosition(); + BlockState blockState = world.getBlockState(otherPos); + if (!AllBlocks.CART_ASSEMBLER.has(blockState)) + return; + if (!CartAssemblerBlock.getActionForCart(blockState, minecartController.cart()) + .shouldDisassemble()) + return; + } + + for (boolean current : Iterate.trueAndFalse) + coupledCarts.get(current) + .removeConnection(current); + disassembleCart(cart); + } + + protected void disassembleCart(AbstractMinecart cart) { + cart.ejectPassengers(); + if (cart instanceof MinecartFurnace) { + CompoundTag nbt = cart.serializeNBT(); + nbt.putDouble("PushZ", cart.getDeltaMovement().x); + nbt.putDouble("PushX", cart.getDeltaMovement().z); + cart.deserializeNBT(nbt); + } + } + + @Override + public void addBehaviours(List behaviours) { + movementMode = new ScrollOptionBehaviour<>(CartMovementMode.class, + Lang.translateDirect("contraptions.cart_movement_mode"), this, getMovementModeSlot()); + behaviours.add(movementMode); + registerAwardables(behaviours, AllAdvancements.CONTRAPTION_ACTORS); + } + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + AssemblyException.write(compound, lastException); + super.write(compound, clientPacket); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + lastException = AssemblyException.read(compound); + super.read(compound, clientPacket); + } + + @Override + public AssemblyException getLastAssemblyException() { + return lastException; + } + + protected ValueBoxTransform getMovementModeSlot() { + return new CartAssemblerValueBoxTransform(); + } + + private class CartAssemblerValueBoxTransform extends CenteredSideValueBoxTransform { + + public CartAssemblerValueBoxTransform() { + super((state, d) -> { + if (d.getAxis() + .isVertical()) + return false; + if (!state.hasProperty(CartAssemblerBlock.RAIL_SHAPE)) + return false; + RailShape railShape = state.getValue(CartAssemblerBlock.RAIL_SHAPE); + return (d.getAxis() == Axis.X) == (railShape == RailShape.NORTH_SOUTH); + }); + } + + @Override + protected Vec3 getSouthLocation() { + return VecHelper.voxelSpace(8, 7, 17.5); + } + + } + + public enum CartMovementMode implements INamedIconOptions { + + ROTATE(AllIcons.I_CART_ROTATE), + ROTATE_PAUSED(AllIcons.I_CART_ROTATE_PAUSED), + ROTATION_LOCKED(AllIcons.I_CART_ROTATE_LOCKED), + + ; + + private String translationKey; + private AllIcons icon; + + CartMovementMode(AllIcons icon) { + this.icon = icon; + translationKey = "contraptions.cart_movement_mode." + Lang.asId(name()); + } + + @Override + public AllIcons getIcon() { + return icon; + } + + @Override + public String getTranslationKey() { + return translationKey; + } + } + + public void resetTicksSinceMinecartUpdate() { + ticksSinceMinecartUpdate = 0; + } + + public void assembleNextTick(AbstractMinecart cart) { + if (cartToAssemble == null) + cartToAssemble = cart; + } + + public boolean isMinecartUpdateValid() { + return ticksSinceMinecartUpdate >= assemblyCooldown; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssemblerBlockItem.java b/src/main/java/com/simibubi/create/content/contraptions/mounted/CartAssemblerBlockItem.java similarity index 94% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssemblerBlockItem.java rename to src/main/java/com/simibubi/create/content/contraptions/mounted/CartAssemblerBlockItem.java index 7482573da..b7fc2ea08 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssemblerBlockItem.java +++ b/src/main/java/com/simibubi/create/content/contraptions/mounted/CartAssemblerBlockItem.java @@ -1,9 +1,9 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.mounted; +package com.simibubi.create.content.contraptions.mounted; import javax.annotation.Nonnull; import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.components.tracks.ControllerRailBlock; +import com.simibubi.create.content.redstone.rail.ControllerRailBlock; import com.simibubi.create.foundation.advancement.AdvancementBehaviour; import com.simibubi.create.foundation.utility.Lang; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/ItemHandlerModifiableFromIInventory.java b/src/main/java/com/simibubi/create/content/contraptions/mounted/ItemHandlerModifiableFromIInventory.java similarity index 97% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/ItemHandlerModifiableFromIInventory.java rename to src/main/java/com/simibubi/create/content/contraptions/mounted/ItemHandlerModifiableFromIInventory.java index f70ee51f9..326e08ee3 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/ItemHandlerModifiableFromIInventory.java +++ b/src/main/java/com/simibubi/create/content/contraptions/mounted/ItemHandlerModifiableFromIInventory.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.mounted; +package com.simibubi.create.content.contraptions.mounted; import javax.annotation.Nonnull; import javax.annotation.ParametersAreNonnullByDefault; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/MinecartContraptionItem.java b/src/main/java/com/simibubi/create/content/contraptions/mounted/MinecartContraptionItem.java similarity index 90% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/MinecartContraptionItem.java rename to src/main/java/com/simibubi/create/content/contraptions/mounted/MinecartContraptionItem.java index 293186f9f..8574efbc7 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/MinecartContraptionItem.java +++ b/src/main/java/com/simibubi/create/content/contraptions/mounted/MinecartContraptionItem.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.mounted; +package com.simibubi.create.content.contraptions.mounted; import java.util.List; @@ -8,18 +8,18 @@ import org.apache.commons.lang3.tuple.MutablePair; import com.simibubi.create.AllItems; import com.simibubi.create.AllMovementBehaviours; -import com.simibubi.create.content.contraptions.components.actors.PortableStorageInterfaceMovement; -import com.simibubi.create.content.contraptions.components.deployer.DeployerFakePlayer; -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; -import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.contraptions.ContraptionData; +import com.simibubi.create.content.contraptions.ContraptionMovementSetting; +import com.simibubi.create.content.contraptions.OrientedContraptionEntity; +import com.simibubi.create.content.contraptions.actors.psi.PortableStorageInterfaceMovement; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.kinetics.deployer.DeployerFakePlayer; import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.config.ContraptionMovementSetting; -import com.simibubi.create.foundation.utility.ContraptionData; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.NBTHelper; +import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; @@ -68,7 +68,7 @@ public class MinecartContraptionItem extends Item { @Override public boolean canFitInsideContainerItems() { - return AllConfigs.SERVER.kinetics.minecartContraptionInContainers.get(); + return AllConfigs.server().kinetics.minecartContraptionInContainers.get(); } private MinecartContraptionItem(Type minecartTypeIn, Properties builder) { @@ -204,7 +204,7 @@ public class MinecartContraptionItem extends Item { Player player = event.getEntity(); if (player == null || entity == null) return; - if (!AllConfigs.SERVER.kinetics.survivalContraptionPickup.get() && !player.isCreative()) + if (!AllConfigs.server().kinetics.survivalContraptionPickup.get() && !player.isCreative()) return; ItemStack wrench = player.getItemInHand(event.getHand()); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/MountedContraption.java b/src/main/java/com/simibubi/create/content/contraptions/mounted/MountedContraption.java similarity index 85% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/MountedContraption.java rename to src/main/java/com/simibubi/create/content/contraptions/mounted/MountedContraption.java index 90f30b4ec..87c5a9232 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/MountedContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/mounted/MountedContraption.java @@ -1,18 +1,18 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.mounted; +package com.simibubi.create.content.contraptions.mounted; -import static com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerBlock.RAIL_SHAPE; +import static com.simibubi.create.content.contraptions.mounted.CartAssemblerBlock.RAIL_SHAPE; import java.util.Queue; import org.apache.commons.lang3.tuple.Pair; import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException; -import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; -import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType; -import com.simibubi.create.content.contraptions.components.structureMovement.NonStationaryLighter; -import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerTileEntity.CartMovementMode; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionLighter; +import com.simibubi.create.content.contraptions.AssemblyException; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.contraptions.ContraptionType; +import com.simibubi.create.content.contraptions.mounted.CartAssemblerBlockEntity.CartMovementMode; +import com.simibubi.create.content.contraptions.render.ContraptionLighter; +import com.simibubi.create.content.contraptions.render.NonStationaryLighter; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.VecHelper; @@ -50,7 +50,7 @@ public class MountedContraption extends Contraption { } @Override - protected ContraptionType getType() { + public ContraptionType getType() { return ContraptionType.MOUNTED; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/particle/HeaterParticle.java b/src/main/java/com/simibubi/create/content/contraptions/particle/HeaterParticle.java deleted file mode 100644 index 3d02e32ea..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/particle/HeaterParticle.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.simibubi.create.content.contraptions.particle; - -import javax.annotation.ParametersAreNonnullByDefault; - -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.particle.Particle; -import net.minecraft.client.particle.ParticleProvider; -import net.minecraft.client.particle.ParticleRenderType; -import net.minecraft.client.particle.SimpleAnimatedParticle; -import net.minecraft.client.particle.SpriteSet; -import net.minecraft.util.Mth; - -@ParametersAreNonnullByDefault -@MethodsReturnNonnullByDefault -public class HeaterParticle extends SimpleAnimatedParticle { - - private final SpriteSet animatedSprite; - - public HeaterParticle(ClientLevel worldIn, float r, float g, float b, double x, double y, double z, double vx, double vy, - double vz, SpriteSet spriteSet) { - super(worldIn, x, y, z, spriteSet, worldIn.random.nextFloat() * .5f); - - this.animatedSprite = spriteSet; - - this.xd = this.xd * (double) 0.01F + vx; - this.yd = this.yd * (double) 0.01F + vy; - this.zd = this.zd * (double) 0.01F + vz; - - this.rCol = r; - this.gCol = g; - this.bCol = b; - - this.x += (this.random.nextFloat() - this.random.nextFloat()) * 0.05F; - this.y += (this.random.nextFloat() - this.random.nextFloat()) * 0.05F; - this.z += (this.random.nextFloat() - this.random.nextFloat()) * 0.05F; - - this.lifetime = (int) (8.0D / (Math.random() * 0.8D + 0.2D)) + 4; - this.quadSize *= 1.875F; - this.setSpriteFromAge(animatedSprite); - - } - - @Override - public ParticleRenderType getRenderType() { - return ParticleRenderType.PARTICLE_SHEET_LIT; - } - - @Override - public float getQuadSize(float p_217561_1_) { - float f = ((float) this.age + p_217561_1_) / (float) this.lifetime; - return this.quadSize * (1.0F - f * f * 0.5F); - } - - @Override - public void move(double x, double y, double z) { - this.setBoundingBox(this.getBoundingBox() - .move(x, y, z)); - this.setLocationFromBoundingbox(); - } - - @Override - public int getLightColor(float p_189214_1_) { - float f = ((float) this.age + p_189214_1_) / (float) this.lifetime; - f = Mth.clamp(f, 0.0F, 1.0F); - int i = super.getLightColor(p_189214_1_); - int j = i & 255; - int k = i >> 16 & 255; - j = j + (int) (f * 15.0F * 16.0F); - if (j > 240) { - j = 240; - } - - return j | k << 16; - } - - @Override - public void tick() { - this.xo = this.x; - this.yo = this.y; - this.zo = this.z; - if (this.age++ >= this.lifetime) { - this.remove(); - } else { - this.setSpriteFromAge(animatedSprite); - this.move(this.xd, this.yd, this.zd); - this.xd *= (double) 0.96F; - this.yd *= (double) 0.96F; - this.zd *= (double) 0.96F; - if (this.onGround) { - this.xd *= (double) 0.7F; - this.zd *= (double) 0.7F; - } - } - } - - public static class Factory implements ParticleProvider { - private final SpriteSet spriteSet; - - public Factory(SpriteSet animatedSprite) { - this.spriteSet = animatedSprite; - } - - @Override - public Particle createParticle(HeaterParticleData data, ClientLevel worldIn, double x, double y, double z, double vx, - double vy, double vz) { - return new HeaterParticle(worldIn, data.r, data.g, data.b, x, y, z, vx, vy, vz, this.spriteSet); - } - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/particle/HeaterParticleData.java b/src/main/java/com/simibubi/create/content/contraptions/particle/HeaterParticleData.java deleted file mode 100644 index bcaebea9b..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/particle/HeaterParticleData.java +++ /dev/null @@ -1,99 +0,0 @@ -package com.simibubi.create.content.contraptions.particle; - -import java.util.Locale; - -import javax.annotation.ParametersAreNonnullByDefault; - -import com.mojang.brigadier.StringReader; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import com.mojang.serialization.Codec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import com.simibubi.create.AllParticleTypes; - -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.client.particle.ParticleEngine.SpriteParticleRegistration; -import net.minecraft.core.particles.ParticleOptions; -import net.minecraft.core.particles.ParticleType; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -@ParametersAreNonnullByDefault -@MethodsReturnNonnullByDefault -public class HeaterParticleData implements ParticleOptions, ICustomParticleDataWithSprite { - - public static final Codec CODEC = RecordCodecBuilder.create(i -> - i.group( - Codec.FLOAT.fieldOf("r").forGetter(p -> p.r), - Codec.FLOAT.fieldOf("g").forGetter(p -> p.g), - Codec.FLOAT.fieldOf("b").forGetter(p -> p.b)) - .apply(i, HeaterParticleData::new)); - - public static final ParticleOptions.Deserializer DESERIALIZER = - new ParticleOptions.Deserializer() { - @Override - public HeaterParticleData fromCommand(ParticleType arg0, StringReader reader) - throws CommandSyntaxException { - reader.expect(' '); - float r = reader.readFloat(); - reader.expect(' '); - float g = reader.readFloat(); - reader.expect(' '); - float b = reader.readFloat(); - return new HeaterParticleData(r, g, b); - } - - @Override - public HeaterParticleData fromNetwork(ParticleType type, FriendlyByteBuf buffer) { - return new HeaterParticleData(buffer.readFloat(), buffer.readFloat(), buffer.readFloat()); - } - }; - - final float r; - final float g; - final float b; - - public HeaterParticleData(float r, float g, float b) { - this.r = r; - this.g = g; - this.b = b; - } - - public HeaterParticleData() { - this(0, 0, 0); - } - - @Override - public Deserializer getDeserializer() { - return DESERIALIZER; - } - - @Override - public Codec getCodec(ParticleType type) { - return CODEC; - } - - @Override - @OnlyIn(Dist.CLIENT) - public SpriteParticleRegistration getMetaFactory() { - return HeaterParticle.Factory::new; - } - - @Override - public String writeToString() { - return String.format(Locale.ROOT, "%s %f %f %f", AllParticleTypes.HEATER_PARTICLE.parameter(), r, g, b); - } - - @Override - public ParticleType getType() { - return AllParticleTypes.HEATER_PARTICLE.get(); - } - - @Override - public void writeToNetwork(FriendlyByteBuf buffer) { - buffer.writeFloat(r); - buffer.writeFloat(g); - buffer.writeFloat(b); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/piston/LinearActuatorBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/piston/LinearActuatorBlockEntity.java new file mode 100644 index 000000000..7f627f7d3 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/piston/LinearActuatorBlockEntity.java @@ -0,0 +1,387 @@ +package com.simibubi.create.content.contraptions.piston; + +import java.util.List; + +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.AssemblyException; +import com.simibubi.create.content.contraptions.ContraptionCollider; +import com.simibubi.create.content.contraptions.ControlledContraptionEntity; +import com.simibubi.create.content.contraptions.IControlContraption; +import com.simibubi.create.content.contraptions.IDisplayAssemblyExceptions; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.transmission.sequencer.SequencerInstructions; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; +import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollOptionBehaviour; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.ServerSpeedProvider; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.Mth; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public abstract class LinearActuatorBlockEntity extends KineticBlockEntity + implements IControlContraption, IDisplayAssemblyExceptions { + + public float offset; + public boolean running; + public boolean assembleNextTick; + public boolean needsContraption; + public AbstractContraptionEntity movedContraption; + protected boolean forceMove; + protected ScrollOptionBehaviour movementMode; + protected boolean waitingForSpeedChange; + protected AssemblyException lastException; + protected double sequencedOffsetLimit; + + // Custom position sync + protected float clientOffsetDiff; + + public LinearActuatorBlockEntity(BlockEntityType typeIn, BlockPos pos, BlockState state) { + super(typeIn, pos, state); + setLazyTickRate(3); + forceMove = true; + needsContraption = true; + sequencedOffsetLimit = -1; + } + + @Override + public void addBehaviours(List behaviours) { + super.addBehaviours(behaviours); + movementMode = new ScrollOptionBehaviour<>(MovementMode.class, Lang.translateDirect("contraptions.movement_mode"), + this, getMovementModeSlot()); + movementMode.withCallback(t -> waitingForSpeedChange = false); + behaviours.add(movementMode); + registerAwardables(behaviours, AllAdvancements.CONTRAPTION_ACTORS); + } + + @Override + protected boolean syncSequenceContext() { + return true; + } + + @Override + public void tick() { + super.tick(); + + if (movedContraption != null) + if (!movedContraption.isAlive()) + movedContraption = null; + + if (isPassive()) + return; + + if (level.isClientSide) + clientOffsetDiff *= .75f; + + if (waitingForSpeedChange) { + if (movedContraption != null) { + if (level.isClientSide) { + float syncSpeed = clientOffsetDiff / 2f; + offset += syncSpeed; + movedContraption.setContraptionMotion(toMotionVector(syncSpeed)); + return; + } + movedContraption.setContraptionMotion(Vec3.ZERO); + } + return; + } + + if (!level.isClientSide && assembleNextTick) { + assembleNextTick = false; + if (running) { + if (getSpeed() == 0) + tryDisassemble(); + else + sendData(); + return; + } else { + if (getSpeed() != 0) + try { + assemble(); + lastException = null; + } catch (AssemblyException e) { + lastException = e; + } + sendData(); + } + return; + } + + if (!running) + return; + + boolean contraptionPresent = movedContraption != null; + if (needsContraption && !contraptionPresent) + return; + + float movementSpeed = getMovementSpeed(); + boolean locked = false; + if (sequencedOffsetLimit > 0) { + sequencedOffsetLimit = Math.max(0, sequencedOffsetLimit - Math.abs(movementSpeed)); + locked = sequencedOffsetLimit == 0; + } + float newOffset = offset + movementSpeed; + if ((int) newOffset != (int) offset) + visitNewPosition(); + + if (locked) { + forceMove = true; + resetContraptionToOffset(); + sendData(); + } + + if (contraptionPresent) { + if (moveAndCollideContraption()) { + movedContraption.setContraptionMotion(Vec3.ZERO); + offset = getGridOffset(offset); + resetContraptionToOffset(); + collided(); + return; + } + } + + if (!contraptionPresent || !movedContraption.isStalled()) + offset = newOffset; + + int extensionRange = getExtensionRange(); + if (offset <= 0 || offset >= extensionRange) { + offset = offset <= 0 ? 0 : extensionRange; + if (!level.isClientSide) { + moveAndCollideContraption(); + resetContraptionToOffset(); + tryDisassemble(); + if (waitingForSpeedChange) { + forceMove = true; + sendData(); + } + } + return; + } + } + + protected boolean isPassive() { + return false; + } + + @Override + public void lazyTick() { + super.lazyTick(); + if (movedContraption != null && !level.isClientSide) + sendData(); + } + + protected int getGridOffset(float offset) { + return Mth.clamp((int) (offset + .5f), 0, getExtensionRange()); + } + + public float getInterpolatedOffset(float partialTicks) { + float interpolatedOffset = + Mth.clamp(offset + (partialTicks - .5f) * getMovementSpeed(), 0, getExtensionRange()); + return interpolatedOffset; + } + + @Override + public void onSpeedChanged(float prevSpeed) { + super.onSpeedChanged(prevSpeed); + sequencedOffsetLimit = -1; + + if (isPassive()) + return; + + assembleNextTick = true; + waitingForSpeedChange = false; + + if (movedContraption != null && Math.signum(prevSpeed) != Math.signum(getSpeed()) && prevSpeed != 0) { + if (!movedContraption.isStalled()) { + offset = Math.round(offset * 16) / 16; + resetContraptionToOffset(); + } + movedContraption.getContraption() + .stop(level); + } + + if (sequenceContext != null && sequenceContext.instruction() == SequencerInstructions.TURN_DISTANCE) + sequencedOffsetLimit = sequenceContext.getEffectiveValue(getTheoreticalSpeed()); + } + + @Override + public void remove() { + this.remove = true; + if (!level.isClientSide) + disassemble(); + super.remove(); + } + + @Override + protected void write(CompoundTag compound, boolean clientPacket) { + compound.putBoolean("Running", running); + compound.putBoolean("Waiting", waitingForSpeedChange); + compound.putFloat("Offset", offset); + if (sequencedOffsetLimit >= 0) + compound.putDouble("SequencedOffsetLimit", sequencedOffsetLimit); + AssemblyException.write(compound, lastException); + super.write(compound, clientPacket); + + if (clientPacket && forceMove) { + compound.putBoolean("ForceMovement", forceMove); + forceMove = false; + } + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + boolean forceMovement = compound.contains("ForceMovement"); + float offsetBefore = offset; + + running = compound.getBoolean("Running"); + waitingForSpeedChange = compound.getBoolean("Waiting"); + offset = compound.getFloat("Offset"); + sequencedOffsetLimit = + compound.contains("SequencedOffsetLimit") ? compound.getDouble("SequencedOffsetLimit") : -1; + lastException = AssemblyException.read(compound); + super.read(compound, clientPacket); + + if (!clientPacket) + return; + if (forceMovement) + resetContraptionToOffset(); + else if (running) { + clientOffsetDiff = offset - offsetBefore; + offset = offsetBefore; + } + if (!running) + movedContraption = null; + } + + @Override + public AssemblyException getLastAssemblyException() { + return lastException; + } + + public abstract void disassemble(); + + protected abstract void assemble() throws AssemblyException; + + protected abstract int getExtensionRange(); + + protected abstract int getInitialOffset(); + + protected abstract ValueBoxTransform getMovementModeSlot(); + + protected abstract Vec3 toMotionVector(float speed); + + protected abstract Vec3 toPosition(float offset); + + protected void visitNewPosition() {} + + protected void tryDisassemble() { + if (remove) { + disassemble(); + return; + } + if (getMovementMode() == MovementMode.MOVE_NEVER_PLACE) { + waitingForSpeedChange = true; + return; + } + int initial = getInitialOffset(); + if ((int) (offset + .5f) != initial && getMovementMode() == MovementMode.MOVE_PLACE_RETURNED) { + waitingForSpeedChange = true; + return; + } + disassemble(); + } + + protected MovementMode getMovementMode() { + return movementMode.get(); + } + + protected boolean moveAndCollideContraption() { + if (movedContraption == null) + return false; + if (movedContraption.isStalled()) { + movedContraption.setContraptionMotion(Vec3.ZERO); + return false; + } + + Vec3 motion = getMotionVector(); + movedContraption.setContraptionMotion(getMotionVector()); + movedContraption.move(motion.x, motion.y, motion.z); + return ContraptionCollider.collideBlocks(movedContraption); + } + + protected void collided() { + if (level.isClientSide) { + waitingForSpeedChange = true; + return; + } + offset = getGridOffset(offset - getMovementSpeed()); + resetContraptionToOffset(); + tryDisassemble(); + } + + protected void resetContraptionToOffset() { + if (movedContraption == null) + return; + if (!movedContraption.isAlive()) + return; + Vec3 vec = toPosition(offset); + movedContraption.setPos(vec.x, vec.y, vec.z); + if (getSpeed() == 0 || waitingForSpeedChange) + movedContraption.setContraptionMotion(Vec3.ZERO); + } + + public float getMovementSpeed() { + float movementSpeed = Mth.clamp(convertToLinear(getSpeed()), -.49f, .49f) + clientOffsetDiff / 2f; + if (level.isClientSide) + movementSpeed *= ServerSpeedProvider.get(); + if (sequencedOffsetLimit >= 0) + movementSpeed = (float) Mth.clamp(movementSpeed, -sequencedOffsetLimit, sequencedOffsetLimit); + return movementSpeed; + } + + public Vec3 getMotionVector() { + return toMotionVector(getMovementSpeed()); + } + + @Override + public void onStall() { + if (!level.isClientSide) { + forceMove = true; + sendData(); + } + } + + public void onLengthBroken() { + offset = 0; + sendData(); + } + + @Override + public boolean isValid() { + return !isRemoved(); + } + + @Override + public void attach(ControlledContraptionEntity contraption) { + this.movedContraption = contraption; + if (!level.isClientSide) { + this.running = true; + sendData(); + } + } + + @Override + public boolean isAttachedTo(AbstractContraptionEntity contraption) { + return movedContraption == contraption; + } + + @Override + public BlockPos getBlockPosition() { + return worldPosition; + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonBlock.java b/src/main/java/com/simibubi/create/content/contraptions/piston/MechanicalPistonBlock.java similarity index 89% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonBlock.java rename to src/main/java/com/simibubi/create/content/contraptions/piston/MechanicalPistonBlock.java index 6da40fd85..a30a17c09 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/piston/MechanicalPistonBlock.java @@ -1,13 +1,13 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.piston; +package com.simibubi.create.content.contraptions.piston; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.DirectionalAxisKineticBlock; -import com.simibubi.create.foundation.block.ITE; -import com.simibubi.create.foundation.config.AllConfigs; +import com.simibubi.create.content.kinetics.base.DirectionalAxisKineticBlock; +import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -34,7 +34,7 @@ import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraftforge.common.Tags; -public class MechanicalPistonBlock extends DirectionalAxisKineticBlock implements ITE { +public class MechanicalPistonBlock extends DirectionalAxisKineticBlock implements IBE { public static final EnumProperty STATE = EnumProperty.create("state", PistonState.class); protected boolean isSticky; @@ -71,7 +71,7 @@ public class MechanicalPistonBlock extends DirectionalAxisKineticBlock implement .is(Tags.Items.SLIMEBALLS)) { if (player.getItemInHand(handIn) .isEmpty()) { - withTileEntityDo(worldIn, pos, te -> te.assembleNextTick = true); + withBlockEntityDo(worldIn, pos, be -> be.assembleNextTick = true); return InteractionResult.SUCCESS; } return InteractionResult.PASS; @@ -118,11 +118,11 @@ public class MechanicalPistonBlock extends DirectionalAxisKineticBlock implement if (pole.getValue(PistonExtensionPoleBlock.FACING) .getAxis() != direction.getAxis()) return; - withTileEntityDo(worldIn, pos, te -> { - if (te.lastException == null) + withBlockEntityDo(worldIn, pos, be -> { + if (be.lastException == null) return; - te.lastException = null; - te.sendData(); + be.lastException = null; + be.sendData(); }); } @@ -188,7 +188,7 @@ public class MechanicalPistonBlock extends DirectionalAxisKineticBlock implement } public static int maxAllowedPistonPoles() { - return AllConfigs.SERVER.kinetics.maxPistonPoles.get(); + return AllConfigs.server().kinetics.maxPistonPoles.get(); } @Override @@ -204,13 +204,13 @@ public class MechanicalPistonBlock extends DirectionalAxisKineticBlock implement } @Override - public Class getTileEntityClass() { - return MechanicalPistonTileEntity.class; + public Class getBlockEntityClass() { + return MechanicalPistonBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.MECHANICAL_PISTON.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.MECHANICAL_PISTON.get(); } public static boolean isPiston(BlockState state) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/piston/MechanicalPistonBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/piston/MechanicalPistonBlockEntity.java new file mode 100644 index 000000000..454be0101 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/piston/MechanicalPistonBlockEntity.java @@ -0,0 +1,180 @@ +package com.simibubi.create.content.contraptions.piston; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.content.contraptions.AssemblyException; +import com.simibubi.create.content.contraptions.ContraptionCollider; +import com.simibubi.create.content.contraptions.ControlledContraptionEntity; +import com.simibubi.create.content.contraptions.DirectionalExtenderScrollOptionSlot; +import com.simibubi.create.content.contraptions.piston.MechanicalPistonBlock.PistonState; +import com.simibubi.create.content.kinetics.base.IRotate; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; +import com.simibubi.create.foundation.utility.ServerSpeedProvider; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.Mth; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.phys.Vec3; + +public class MechanicalPistonBlockEntity extends LinearActuatorBlockEntity { + + protected boolean hadCollisionWithOtherPiston; + protected int extensionLength; + + public MechanicalPistonBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + extensionLength = compound.getInt("ExtensionLength"); + super.read(compound, clientPacket); + } + + @Override + protected void write(CompoundTag tag, boolean clientPacket) { + tag.putInt("ExtensionLength", extensionLength); + super.write(tag, clientPacket); + } + + @Override + public void assemble() throws AssemblyException { + if (!(level.getBlockState(worldPosition) + .getBlock() instanceof MechanicalPistonBlock)) + return; + + Direction direction = getBlockState().getValue(BlockStateProperties.FACING); + + // Collect Construct + PistonContraption contraption = new PistonContraption(direction, getMovementSpeed() < 0); + if (!contraption.assemble(level, worldPosition)) + return; + + Direction positive = Direction.get(AxisDirection.POSITIVE, direction.getAxis()); + Direction movementDirection = + getSpeed() > 0 ^ direction.getAxis() != Axis.Z ? positive : positive.getOpposite(); + + BlockPos anchor = contraption.anchor.relative(direction, contraption.initialExtensionProgress); + if (ContraptionCollider.isCollidingWithWorld(level, contraption, anchor.relative(movementDirection), + movementDirection)) + return; + + // Check if not at limit already + extensionLength = contraption.extensionLength; + float resultingOffset = contraption.initialExtensionProgress + Math.signum(getMovementSpeed()) * .5f; + if (resultingOffset <= 0 || resultingOffset >= extensionLength) { + return; + } + + // Run + running = true; + offset = contraption.initialExtensionProgress; + sendData(); + clientOffsetDiff = 0; + + BlockPos startPos = BlockPos.ZERO.relative(direction, contraption.initialExtensionProgress); + contraption.removeBlocksFromWorld(level, startPos); + movedContraption = ControlledContraptionEntity.create(getLevel(), this, contraption); + resetContraptionToOffset(); + forceMove = true; + level.addFreshEntity(movedContraption); + + AllSoundEvents.CONTRAPTION_ASSEMBLE.playOnServer(level, worldPosition); + + if (contraption.containsBlockBreakers()) + award(AllAdvancements.CONTRAPTION_ACTORS); + } + + @Override + public void disassemble() { + if (!running && movedContraption == null) + return; + if (!remove) + getLevel().setBlock(worldPosition, getBlockState().setValue(MechanicalPistonBlock.STATE, PistonState.EXTENDED), + 3 | 16); + if (movedContraption != null) { + resetContraptionToOffset(); + movedContraption.disassemble(); + AllSoundEvents.CONTRAPTION_DISASSEMBLE.playOnServer(level, worldPosition); + } + running = false; + movedContraption = null; + sendData(); + + if (remove) + AllBlocks.MECHANICAL_PISTON.get() + .playerWillDestroy(level, worldPosition, getBlockState(), null); + } + + @Override + protected void collided() { + super.collided(); + if (!running && getMovementSpeed() > 0) + assembleNextTick = true; + } + + @Override + public float getMovementSpeed() { + float movementSpeed = Mth.clamp(convertToLinear(getSpeed()), -.49f, .49f); + if (level.isClientSide) + movementSpeed *= ServerSpeedProvider.get(); + Direction pistonDirection = getBlockState().getValue(BlockStateProperties.FACING); + int movementModifier = pistonDirection.getAxisDirection() + .getStep() * (pistonDirection.getAxis() == Axis.Z ? -1 : 1); + movementSpeed = movementSpeed * -movementModifier + clientOffsetDiff / 2f; + + int extensionRange = getExtensionRange(); + movementSpeed = Mth.clamp(movementSpeed, 0 - offset, extensionRange - offset); + if (sequencedOffsetLimit >= 0) + movementSpeed = (float) Mth.clamp(movementSpeed, -sequencedOffsetLimit, sequencedOffsetLimit); + return movementSpeed; + } + + @Override + protected int getExtensionRange() { + return extensionLength; + } + + @Override + protected void visitNewPosition() {} + + @Override + protected Vec3 toMotionVector(float speed) { + Direction pistonDirection = getBlockState().getValue(BlockStateProperties.FACING); + return Vec3.atLowerCornerOf(pistonDirection.getNormal()) + .scale(speed); + } + + @Override + protected Vec3 toPosition(float offset) { + Vec3 position = Vec3.atLowerCornerOf(getBlockState().getValue(BlockStateProperties.FACING) + .getNormal()) + .scale(offset); + return position.add(Vec3.atLowerCornerOf(movedContraption.getContraption().anchor)); + } + + @Override + protected ValueBoxTransform getMovementModeSlot() { + return new DirectionalExtenderScrollOptionSlot((state, d) -> { + Axis axis = d.getAxis(); + Axis extensionAxis = state.getValue(MechanicalPistonBlock.FACING) + .getAxis(); + Axis shaftAxis = ((IRotate) state.getBlock()).getRotationAxis(state); + return extensionAxis != axis && shaftAxis != axis; + }); + } + + @Override + protected int getInitialOffset() { + return movedContraption == null ? 0 + : ((PistonContraption) movedContraption.getContraption()).initialExtensionProgress; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonGenerator.java b/src/main/java/com/simibubi/create/content/contraptions/piston/MechanicalPistonGenerator.java similarity index 90% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonGenerator.java rename to src/main/java/com/simibubi/create/content/contraptions/piston/MechanicalPistonGenerator.java index 2483e8ac1..f28a426d0 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonGenerator.java +++ b/src/main/java/com/simibubi/create/content/contraptions/piston/MechanicalPistonGenerator.java @@ -1,6 +1,6 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.piston; +package com.simibubi.create.content.contraptions.piston; -import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.PistonState; +import com.simibubi.create.content.contraptions.piston.MechanicalPistonBlock.PistonState; import com.simibubi.create.foundation.data.SpecialBlockStateGen; import com.tterrag.registrate.providers.DataGenContext; import com.tterrag.registrate.providers.RegistrateBlockstateProvider; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonHeadBlock.java b/src/main/java/com/simibubi/create/content/contraptions/piston/MechanicalPistonHeadBlock.java similarity index 93% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonHeadBlock.java rename to src/main/java/com/simibubi/create/content/contraptions/piston/MechanicalPistonHeadBlock.java index 202a8ffa9..cecd5a2ab 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonHeadBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/piston/MechanicalPistonHeadBlock.java @@ -1,10 +1,10 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.piston; +package com.simibubi.create.content.contraptions.piston; -import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isExtensionPole; +import static com.simibubi.create.content.contraptions.piston.MechanicalPistonBlock.isExtensionPole; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; -import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.PistonState; +import com.simibubi.create.content.contraptions.piston.MechanicalPistonBlock.PistonState; import com.simibubi.create.foundation.block.WrenchableDirectionalBlock; import net.minecraft.core.BlockPos; diff --git a/src/main/java/com/simibubi/create/content/contraptions/piston/MechanicalPistonRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/piston/MechanicalPistonRenderer.java new file mode 100644 index 000000000..e1ec5901d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/piston/MechanicalPistonRenderer.java @@ -0,0 +1,19 @@ +package com.simibubi.create.content.contraptions.piston; + +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; + +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.world.level.block.state.BlockState; + +public class MechanicalPistonRenderer extends KineticBlockEntityRenderer { + + public MechanicalPistonRenderer(BlockEntityRendererProvider.Context context) { + super(context); + } + + @Override + protected BlockState getRenderedBlockState(MechanicalPistonBlockEntity be) { + return shaft(getRotationAxisOf(be)); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/PistonContraption.java b/src/main/java/com/simibubi/create/content/contraptions/piston/PistonContraption.java similarity index 85% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/PistonContraption.java rename to src/main/java/com/simibubi/create/content/contraptions/piston/PistonContraption.java index 7413928c2..4f435fc32 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/PistonContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/piston/PistonContraption.java @@ -1,11 +1,11 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.piston; +package com.simibubi.create.content.contraptions.piston; import static com.simibubi.create.AllBlocks.MECHANICAL_PISTON_HEAD; import static com.simibubi.create.AllBlocks.PISTON_EXTENSION_POLE; -import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isExtensionPole; -import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isPiston; -import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isPistonHead; -import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isStickyPiston; +import static com.simibubi.create.content.contraptions.piston.MechanicalPistonBlock.isExtensionPole; +import static com.simibubi.create.content.contraptions.piston.MechanicalPistonBlock.isPiston; +import static com.simibubi.create.content.contraptions.piston.MechanicalPistonBlock.isPistonHead; +import static com.simibubi.create.content.contraptions.piston.MechanicalPistonBlock.isStickyPiston; import static net.minecraft.world.level.block.state.properties.BlockStateProperties.FACING; import java.util.ArrayList; @@ -14,14 +14,14 @@ import java.util.Queue; import org.apache.commons.lang3.tuple.Pair; -import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException; -import com.simibubi.create.content.contraptions.components.structureMovement.BlockMovementChecks; -import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType; -import com.simibubi.create.content.contraptions.components.structureMovement.TranslatingContraption; -import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.PistonState; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionLighter; -import com.simibubi.create.foundation.config.AllConfigs; +import com.simibubi.create.content.contraptions.AssemblyException; +import com.simibubi.create.content.contraptions.BlockMovementChecks; +import com.simibubi.create.content.contraptions.ContraptionType; +import com.simibubi.create.content.contraptions.TranslatingContraption; +import com.simibubi.create.content.contraptions.piston.MechanicalPistonBlock.PistonState; +import com.simibubi.create.content.contraptions.render.ContraptionLighter; import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -49,7 +49,7 @@ public class PistonContraption extends TranslatingContraption { private boolean retract; @Override - protected ContraptionType getType() { + public ContraptionType getType() { return ContraptionType.PISTON; } @@ -160,7 +160,7 @@ public class PistonContraption extends TranslatingContraption { boolean retracting = direction != orientation; if (retracting && !sticky) return true; - for (int offset = 0; offset <= AllConfigs.SERVER.kinetics.maxChassisRange.get(); offset++) { + for (int offset = 0; offset <= AllConfigs.server().kinetics.maxChassisRange.get(); offset++) { if (offset == 1 && retracting) return true; BlockPos currentPos = pos.relative(orientation, offset + initialExtensionProgress); @@ -204,9 +204,9 @@ public class PistonContraption extends TranslatingContraption { protected boolean customBlockPlacement(LevelAccessor world, BlockPos pos, BlockState state) { BlockPos pistonPos = anchor.relative(orientation, -1); BlockState pistonState = world.getBlockState(pistonPos); - BlockEntity te = world.getBlockEntity(pistonPos); + BlockEntity be = world.getBlockEntity(pistonPos); if (pos.equals(pistonPos)) { - if (te == null || te.isRemoved()) + if (be == null || be.isRemoved()) return true; if (!isExtensionPole(state) && isPiston(pistonState)) world.setBlock(pistonPos, pistonState.setValue(MechanicalPistonBlock.STATE, PistonState.RETRACTED), diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/PistonExtensionPoleBlock.java b/src/main/java/com/simibubi/create/content/contraptions/piston/PistonExtensionPoleBlock.java similarity index 85% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/PistonExtensionPoleBlock.java rename to src/main/java/com/simibubi/create/content/contraptions/piston/PistonExtensionPoleBlock.java index e0f63749a..76d0bcf13 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/PistonExtensionPoleBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/piston/PistonExtensionPoleBlock.java @@ -1,19 +1,19 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.piston; +package com.simibubi.create.content.contraptions.piston; -import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isExtensionPole; -import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isPiston; -import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isPistonHead; +import static com.simibubi.create.content.contraptions.piston.MechanicalPistonBlock.isExtensionPole; +import static com.simibubi.create.content.contraptions.piston.MechanicalPistonBlock.isPiston; +import static com.simibubi.create.content.contraptions.piston.MechanicalPistonBlock.isPistonHead; import java.util.function.Predicate; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; -import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.PistonState; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; +import com.simibubi.create.content.contraptions.piston.MechanicalPistonBlock.PistonState; +import com.simibubi.create.content.equipment.wrench.IWrenchable; import com.simibubi.create.foundation.block.WrenchableDirectionalBlock; -import com.simibubi.create.foundation.utility.placement.IPlacementHelper; -import com.simibubi.create.foundation.utility.placement.PlacementHelpers; -import com.simibubi.create.foundation.utility.placement.util.PoleHelper; +import com.simibubi.create.foundation.placement.IPlacementHelper; +import com.simibubi.create.foundation.placement.PlacementHelpers; +import com.simibubi.create.foundation.placement.PoleHelper; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; @@ -98,11 +98,11 @@ public class PistonExtensionPoleBlock extends WrenchableDirectionalBlock impleme worldIn.setBlockAndUpdate(basePos, worldIn.getBlockState(basePos) .setValue(MechanicalPistonBlock.STATE, PistonState.RETRACTED)); - BlockEntity te = worldIn.getBlockEntity(basePos); - if (te instanceof MechanicalPistonTileEntity) { - MechanicalPistonTileEntity baseTE = (MechanicalPistonTileEntity) te; - baseTE.offset = 0; - baseTE.onLengthBroken(); + BlockEntity be = worldIn.getBlockEntity(basePos); + if (be instanceof MechanicalPistonBlockEntity) { + MechanicalPistonBlockEntity baseBE = (MechanicalPistonBlockEntity) be; + baseBE.offset = 0; + baseBE.onLengthBroken(); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/PistonLighter.java b/src/main/java/com/simibubi/create/content/contraptions/piston/PistonLighter.java similarity index 84% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/PistonLighter.java rename to src/main/java/com/simibubi/create/content/contraptions/piston/PistonLighter.java index cf1b2f961..b21c79505 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/PistonLighter.java +++ b/src/main/java/com/simibubi/create/content/contraptions/piston/PistonLighter.java @@ -1,7 +1,7 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.piston; +package com.simibubi.create.content.contraptions.piston; import com.jozufozu.flywheel.util.box.GridAlignedBB; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionLighter; +import com.simibubi.create.content.contraptions.render.ContraptionLighter; import net.minecraft.core.Vec3i; diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/BasinMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/processing/BasinMovementBehaviour.java deleted file mode 100644 index 3d590017a..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/BasinMovementBehaviour.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.simibubi.create.content.contraptions.processing; - -import java.util.HashMap; -import java.util.Map; - -import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; - -import net.minecraft.core.Direction; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.items.ItemStackHandler; - -public class BasinMovementBehaviour implements MovementBehaviour { - public Map getOrReadInventory(MovementContext context) { - Map map = new HashMap<>(); - map.put("InputItems", new ItemStackHandler(9)); - map.put("OutputItems", new ItemStackHandler(8)); - map.forEach((s, h) -> h.deserializeNBT(context.tileData.getCompound(s))); - return map; - } - - @Override - public boolean renderAsNormalTileEntity() { - return true; - } - - @Override - public void tick(MovementContext context) { - MovementBehaviour.super.tick(context); - if (context.temporaryData == null || (boolean) context.temporaryData) { - Vec3 facingVec = context.rotation.apply(Vec3.atLowerCornerOf(Direction.UP.getNormal())); - facingVec.normalize(); - if (Direction.getNearest(facingVec.x, facingVec.y, facingVec.z) == Direction.DOWN) - dump(context, facingVec); - } - } - - private void dump(MovementContext context, Vec3 facingVec) { - getOrReadInventory(context).forEach((key, itemStackHandler) -> { - for (int i = 0; i < itemStackHandler.getSlots(); i++) { - if (itemStackHandler.getStackInSlot(i) - .isEmpty()) - continue; - ItemEntity itemEntity = new ItemEntity(context.world, context.position.x, context.position.y, - context.position.z, itemStackHandler.getStackInSlot(i)); - itemEntity.setDeltaMovement(facingVec.scale(.05)); - context.world.addFreshEntity(itemEntity); - itemStackHandler.setStackInSlot(i, ItemStack.EMPTY); - } - context.tileData.put(key, itemStackHandler.serializeNBT()); - }); - BlockEntity tileEntity = context.contraption.presentTileEntities.get(context.localPos); - if (tileEntity instanceof BasinTileEntity) - ((BasinTileEntity) tileEntity).readOnlyItems(context.tileData); - context.temporaryData = false; // did already dump, so can't any more - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/BasinOperatingTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/processing/BasinOperatingTileEntity.java deleted file mode 100644 index 925853aa2..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/BasinOperatingTileEntity.java +++ /dev/null @@ -1,155 +0,0 @@ -package com.simibubi.create.content.contraptions.processing; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; - -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.foundation.advancement.CreateAdvancement; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.simple.DeferralBehaviour; -import com.simibubi.create.foundation.utility.recipe.RecipeFinder; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.Container; -import net.minecraft.world.item.crafting.Recipe; -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 BasinOperatingTileEntity extends KineticTileEntity { - - public DeferralBehaviour basinChecker; - public boolean basinRemoved; - protected Recipe currentRecipe; - - public BasinOperatingTileEntity(BlockEntityType typeIn, BlockPos pos, BlockState state) { - super(typeIn, pos, state); - } - - @Override - public void addBehaviours(List behaviours) { - super.addBehaviours(behaviours); - basinChecker = new DeferralBehaviour(this, this::updateBasin); - behaviours.add(basinChecker); - } - - @Override - public void onSpeedChanged(float prevSpeed) { - super.onSpeedChanged(prevSpeed); - if (getSpeed() == 0) - basinRemoved = true; - basinRemoved = false; - basinChecker.scheduleUpdate(); - } - - @Override - public void tick() { - if (basinRemoved) { - basinRemoved = false; - onBasinRemoved(); - sendData(); - return; - } - - super.tick(); - } - - protected boolean updateBasin() { - if (!isSpeedRequirementFulfilled()) - return true; - if (getSpeed() == 0) - return true; - if (isRunning()) - return true; - if (level == null || level.isClientSide) - return true; - Optional basin = getBasin(); - if (!basin.filter(BasinTileEntity::canContinueProcessing) - .isPresent()) - return true; - - List> recipes = getMatchingRecipes(); - if (recipes.isEmpty()) - return true; - currentRecipe = recipes.get(0); - startProcessingBasin(); - sendData(); - return true; - } - - protected abstract boolean isRunning(); - - public void startProcessingBasin() {} - - public boolean continueWithPreviousRecipe() { - return true; - } - - protected boolean matchBasinRecipe(Recipe recipe) { - if (recipe == null) - return false; - Optional basin = getBasin(); - if (!basin.isPresent()) - return false; - return BasinRecipe.match(basin.get(), recipe); - } - - protected void applyBasinRecipe() { - if (currentRecipe == null) - return; - - Optional optionalBasin = getBasin(); - if (!optionalBasin.isPresent()) - return; - BasinTileEntity basin = optionalBasin.get(); - boolean wasEmpty = basin.canContinueProcessing(); - if (!BasinRecipe.apply(basin, currentRecipe)) - return; - getProcessedRecipeTrigger().ifPresent(this::award); - basin.inputTank.sendDataImmediately(); - - // Continue mixing - if (wasEmpty && matchBasinRecipe(currentRecipe)) { - continueWithPreviousRecipe(); - sendData(); - } - - basin.notifyChangeOfContents(); - } - - protected List> getMatchingRecipes() { - if (getBasin().map(BasinTileEntity::isEmpty) - .orElse(true)) - return new ArrayList<>(); - - List> list = RecipeFinder.get(getRecipeCacheKey(), level, this::matchStaticFilters); - return list.stream() - .filter(this::matchBasinRecipe) - .sorted((r1, r2) -> r2.getIngredients() - .size() - - r1.getIngredients() - .size()) - .collect(Collectors.toList()); - } - - protected abstract void onBasinRemoved(); - - protected Optional getBasin() { - if (level == null) - return Optional.empty(); - BlockEntity basinTE = level.getBlockEntity(worldPosition.below(2)); - if (!(basinTE instanceof BasinTileEntity)) - return Optional.empty(); - return Optional.of((BasinTileEntity) basinTE); - } - - protected Optional getProcessedRecipeTrigger() { - return Optional.empty(); - } - - protected abstract boolean matchStaticFilters(Recipe recipe); - - protected abstract Object getRecipeCacheKey(); -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/BasinTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/processing/BasinTileEntity.java deleted file mode 100644 index 3b0c86881..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/BasinTileEntity.java +++ /dev/null @@ -1,753 +0,0 @@ -package com.simibubi.create.content.contraptions.processing; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.Optional; - -import javax.annotation.Nonnull; - -import com.google.common.collect.ImmutableList; -import com.simibubi.create.AllParticleTypes; -import com.simibubi.create.AllTags; -import com.simibubi.create.content.contraptions.components.mixer.MechanicalMixerTileEntity; -import com.simibubi.create.content.contraptions.fluids.FluidFX; -import com.simibubi.create.content.contraptions.fluids.particle.FluidParticleData; -import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation; -import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock; -import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.HeatLevel; -import com.simibubi.create.foundation.fluid.CombinedTankWrapper; -import com.simibubi.create.foundation.item.ItemHelper; -import com.simibubi.create.foundation.item.SmartInventory; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour.TankSegment; -import com.simibubi.create.foundation.tileEntity.behaviour.inventory.InvManipulationBehaviour; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.IntAttached; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.core.particles.ParticleOptions; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.StringTag; -import net.minecraft.nbt.Tag; -import net.minecraft.network.chat.Component; -import net.minecraft.util.Mth; -import net.minecraft.util.RandomSource; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.capability.CapabilityFluidHandler; -import net.minecraftforge.fluids.capability.IFluidHandler; -import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction; -import net.minecraftforge.items.CapabilityItemHandler; -import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.ItemHandlerHelper; -import net.minecraftforge.items.wrapper.CombinedInvWrapper; - -public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInformation { - - private boolean areFluidsMoving; - LerpedFloat ingredientRotationSpeed; - LerpedFloat ingredientRotation; - - public BasinInventory inputInventory; - public SmartFluidTankBehaviour inputTank; - protected SmartInventory outputInventory; - protected SmartFluidTankBehaviour outputTank; - private FilteringBehaviour filtering; - private boolean contentsChanged; - - private Couple invs; - private Couple tanks; - - protected LazyOptional itemCapability; - protected LazyOptional fluidCapability; - - List disabledSpoutputs; - Direction preferredSpoutput; - protected List spoutputBuffer; - protected List spoutputFluidBuffer; - int recipeBackupCheck; - - public static final int OUTPUT_ANIMATION_TIME = 10; - List> visualizedOutputItems; - List> visualizedOutputFluids; - - public BasinTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - inputInventory = new BasinInventory(9, this); - inputInventory.whenContentsChanged($ -> contentsChanged = true); - outputInventory = new BasinInventory(9, this).forbidInsertion() - .withMaxStackSize(64); - areFluidsMoving = false; - itemCapability = LazyOptional.of(() -> new CombinedInvWrapper(inputInventory, outputInventory)); - contentsChanged = true; - ingredientRotation = LerpedFloat.angular() - .startWithValue(0); - ingredientRotationSpeed = LerpedFloat.linear() - .startWithValue(0); - - invs = Couple.create(inputInventory, outputInventory); - tanks = Couple.create(inputTank, outputTank); - visualizedOutputItems = Collections.synchronizedList(new ArrayList<>()); - visualizedOutputFluids = Collections.synchronizedList(new ArrayList<>()); - disabledSpoutputs = new ArrayList<>(); - preferredSpoutput = null; - spoutputBuffer = new ArrayList<>(); - spoutputFluidBuffer = new ArrayList<>(); - recipeBackupCheck = 20; - } - - @Override - public void addBehaviours(List behaviours) { - behaviours.add(new DirectBeltInputBehaviour(this)); - filtering = new FilteringBehaviour(this, new BasinValueBox()).moveText(new Vec3(2, -8, 0)) - .withCallback(newFilter -> contentsChanged = true) - .forRecipes(); - behaviours.add(filtering); - - inputTank = new SmartFluidTankBehaviour(SmartFluidTankBehaviour.INPUT, this, 2, 1000, true) - .whenFluidUpdates(() -> contentsChanged = true); - outputTank = new SmartFluidTankBehaviour(SmartFluidTankBehaviour.OUTPUT, this, 2, 1000, true) - .whenFluidUpdates(() -> contentsChanged = true) - .forbidInsertion(); - behaviours.add(inputTank); - behaviours.add(outputTank); - - fluidCapability = LazyOptional.of(() -> { - LazyOptional inputCap = inputTank.getCapability(); - LazyOptional outputCap = outputTank.getCapability(); - return new CombinedTankWrapper(outputCap.orElse(null), inputCap.orElse(null)); - }); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - super.read(compound, clientPacket); - inputInventory.deserializeNBT(compound.getCompound("InputItems")); - outputInventory.deserializeNBT(compound.getCompound("OutputItems")); - - preferredSpoutput = null; - if (compound.contains("PreferredSpoutput")) - preferredSpoutput = NBTHelper.readEnum(compound, "PreferredSpoutput", Direction.class); - disabledSpoutputs.clear(); - ListTag disabledList = compound.getList("DisabledSpoutput", Tag.TAG_STRING); - disabledList.forEach(d -> disabledSpoutputs.add(Direction.valueOf(((StringTag) d).getAsString()))); - spoutputBuffer = NBTHelper.readItemList(compound.getList("Overflow", Tag.TAG_COMPOUND)); - spoutputFluidBuffer = NBTHelper.readCompoundList(compound.getList("FluidOverflow", Tag.TAG_COMPOUND), - FluidStack::loadFluidStackFromNBT); - - if (!clientPacket) - return; - - NBTHelper.iterateCompoundList(compound.getList("VisualizedItems", Tag.TAG_COMPOUND), - c -> visualizedOutputItems.add(IntAttached.with(OUTPUT_ANIMATION_TIME, ItemStack.of(c)))); - NBTHelper.iterateCompoundList(compound.getList("VisualizedFluids", Tag.TAG_COMPOUND), - c -> visualizedOutputFluids - .add(IntAttached.with(OUTPUT_ANIMATION_TIME, FluidStack.loadFluidStackFromNBT(c)))); - } - - @Override - public void write(CompoundTag compound, boolean clientPacket) { - super.write(compound, clientPacket); - compound.put("InputItems", inputInventory.serializeNBT()); - compound.put("OutputItems", outputInventory.serializeNBT()); - - if (preferredSpoutput != null) - NBTHelper.writeEnum(compound, "PreferredSpoutput", preferredSpoutput); - ListTag disabledList = new ListTag(); - disabledSpoutputs.forEach(d -> disabledList.add(StringTag.valueOf(d.name()))); - compound.put("DisabledSpoutput", disabledList); - compound.put("Overflow", NBTHelper.writeItemList(spoutputBuffer)); - compound.put("FluidOverflow", - NBTHelper.writeCompoundList(spoutputFluidBuffer, fs -> fs.writeToNBT(new CompoundTag()))); - - if (!clientPacket) - return; - - compound.put("VisualizedItems", NBTHelper.writeCompoundList(visualizedOutputItems, ia -> ia.getValue() - .serializeNBT())); - compound.put("VisualizedFluids", NBTHelper.writeCompoundList(visualizedOutputFluids, ia -> ia.getValue() - .writeToNBT(new CompoundTag()))); - visualizedOutputItems.clear(); - visualizedOutputFluids.clear(); - } - - @Override - public void destroy() { - super.destroy(); - ItemHelper.dropContents(level, worldPosition, inputInventory); - ItemHelper.dropContents(level, worldPosition, outputInventory); - spoutputBuffer.forEach(is -> Block.popResource(level, worldPosition, is)); - } - - @Override - public void remove() { - super.remove(); - onEmptied(); - } - - public void onEmptied() { - getOperator().ifPresent(te -> te.basinRemoved = true); - } - - @Override - public void invalidate() { - super.invalidate(); - itemCapability.invalidate(); - fluidCapability.invalidate(); - } - - @Nonnull - @Override - public LazyOptional getCapability(@Nonnull Capability cap, Direction side) { - if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) - return itemCapability.cast(); - if (cap == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) - return fluidCapability.cast(); - return super.getCapability(cap, side); - } - - @Override - public void notifyUpdate() { - super.notifyUpdate(); - } - - @Override - public void lazyTick() { - super.lazyTick(); - - if (!level.isClientSide) { - updateSpoutput(); - if (recipeBackupCheck-- > 0) - return; - recipeBackupCheck = 20; - if (isEmpty()) - return; - notifyChangeOfContents(); - return; - } - - BlockEntity tileEntity = level.getBlockEntity(worldPosition.above(2)); - if (!(tileEntity instanceof MechanicalMixerTileEntity)) { - setAreFluidsMoving(false); - return; - } - - MechanicalMixerTileEntity mixer = (MechanicalMixerTileEntity) tileEntity; - setAreFluidsMoving(mixer.running && mixer.runningTicks <= 20); - } - - public boolean isEmpty() { - return inputInventory.isEmpty() && outputInventory.isEmpty() && inputTank.isEmpty() && outputTank.isEmpty(); - } - - public void onWrenched(Direction face) { - BlockState blockState = getBlockState(); - Direction currentFacing = blockState.getValue(BasinBlock.FACING); - - disabledSpoutputs.remove(face); - if (currentFacing == face) { - if (preferredSpoutput == face) - preferredSpoutput = null; - disabledSpoutputs.add(face); - } else - preferredSpoutput = face; - - updateSpoutput(); - } - - private void updateSpoutput() { - BlockState blockState = getBlockState(); - Direction currentFacing = blockState.getValue(BasinBlock.FACING); - Direction newFacing = Direction.DOWN; - for (Direction test : Iterate.horizontalDirections) { - boolean canOutputTo = BasinBlock.canOutputTo(level, worldPosition, test); - if (canOutputTo && !disabledSpoutputs.contains(test)) - newFacing = test; - } - - if (preferredSpoutput != null && BasinBlock.canOutputTo(level, worldPosition, preferredSpoutput) - && preferredSpoutput != Direction.UP) - newFacing = preferredSpoutput; - - if (newFacing == currentFacing) - return; - - level.setBlockAndUpdate(worldPosition, blockState.setValue(BasinBlock.FACING, newFacing)); - - if (newFacing.getAxis() - .isVertical()) - return; - - for (int slot = 0; slot < outputInventory.getSlots(); slot++) { - ItemStack extractItem = outputInventory.extractItem(slot, 64, true); - if (extractItem.isEmpty()) - continue; - if (acceptOutputs(ImmutableList.of(extractItem), Collections.emptyList(), true)) - acceptOutputs(ImmutableList.of(outputInventory.extractItem(slot, 64, false)), Collections.emptyList(), - false); - } - - IFluidHandler handler = outputTank.getCapability() - .orElse(null); - for (int slot = 0; slot < handler.getTanks(); slot++) { - FluidStack fs = handler.getFluidInTank(slot) - .copy(); - if (fs.isEmpty()) - continue; - if (acceptOutputs(Collections.emptyList(), ImmutableList.of(fs), true)) { - handler.drain(fs, FluidAction.EXECUTE); - acceptOutputs(Collections.emptyList(), ImmutableList.of(fs), false); - } - } - - notifyChangeOfContents(); - notifyUpdate(); - } - - @Override - public void tick() { - super.tick(); - if (level.isClientSide) { - createFluidParticles(); - tickVisualizedOutputs(); - ingredientRotationSpeed.tickChaser(); - ingredientRotation.setValue(ingredientRotation.getValue() + ingredientRotationSpeed.getValue()); - } - - if ((!spoutputBuffer.isEmpty() || !spoutputFluidBuffer.isEmpty()) && !level.isClientSide) - tryClearingSpoutputOverflow(); - if (!contentsChanged) - return; - - contentsChanged = false; - getOperator().ifPresent(te -> te.basinChecker.scheduleUpdate()); - - for (Direction offset : Iterate.horizontalDirections) { - BlockPos toUpdate = worldPosition.above() - .relative(offset); - BlockState stateToUpdate = level.getBlockState(toUpdate); - if (stateToUpdate.getBlock() instanceof BasinBlock - && stateToUpdate.getValue(BasinBlock.FACING) == offset.getOpposite()) { - BlockEntity te = level.getBlockEntity(toUpdate); - if (te instanceof BasinTileEntity) - ((BasinTileEntity) te).contentsChanged = true; - } - } - } - - private void tryClearingSpoutputOverflow() { - BlockState blockState = getBlockState(); - if (!(blockState.getBlock() instanceof BasinBlock)) - return; - Direction direction = blockState.getValue(BasinBlock.FACING); - BlockEntity te = level.getBlockEntity(worldPosition.below() - .relative(direction)); - - FilteringBehaviour filter = null; - InvManipulationBehaviour inserter = null; - if (te != null) { - filter = TileEntityBehaviour.get(level, te.getBlockPos(), FilteringBehaviour.TYPE); - inserter = TileEntityBehaviour.get(level, te.getBlockPos(), InvManipulationBehaviour.TYPE); - } - - IItemHandler targetInv = te == null ? null - : te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, direction.getOpposite()) - .orElse(inserter == null ? null : inserter.getInventory()); - - IFluidHandler targetTank = te == null ? null - : te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, direction.getOpposite()) - .orElse(null); - - boolean update = false; - - for (Iterator iterator = spoutputBuffer.iterator(); iterator.hasNext();) { - ItemStack itemStack = iterator.next(); - - if (direction == Direction.DOWN) { - Block.popResource(level, worldPosition, itemStack); - iterator.remove(); - update = true; - continue; - } - - if (targetInv == null) - break; - if (!ItemHandlerHelper.insertItemStacked(targetInv, itemStack, true) - .isEmpty()) - continue; - if (filter != null && !filter.test(itemStack)) - continue; - - update = true; - ItemHandlerHelper.insertItemStacked(targetInv, itemStack.copy(), false); - iterator.remove(); - visualizedOutputItems.add(IntAttached.withZero(itemStack)); - } - - for (Iterator iterator = spoutputFluidBuffer.iterator(); iterator.hasNext();) { - FluidStack fluidStack = iterator.next(); - - if (direction == Direction.DOWN) { - iterator.remove(); - update = true; - continue; - } - - if (targetTank == null) - break; - - for (boolean simulate : Iterate.trueAndFalse) { - FluidAction action = simulate ? FluidAction.SIMULATE : FluidAction.EXECUTE; - int fill = targetTank instanceof SmartFluidTankBehaviour.InternalFluidHandler - ? ((SmartFluidTankBehaviour.InternalFluidHandler) targetTank).forceFill(fluidStack.copy(), action) - : targetTank.fill(fluidStack.copy(), action); - if (fill != fluidStack.getAmount()) - break; - if (simulate) - continue; - - update = true; - iterator.remove(); - visualizedOutputFluids.add(IntAttached.withZero(fluidStack)); - } - } - - if (update) { - notifyChangeOfContents(); - sendData(); - } - } - - public float getTotalFluidUnits(float partialTicks) { - int renderedFluids = 0; - float totalUnits = 0; - - for (SmartFluidTankBehaviour behaviour : getTanks()) { - if (behaviour == null) - continue; - for (TankSegment tankSegment : behaviour.getTanks()) { - if (tankSegment.getRenderedFluid() - .isEmpty()) - continue; - float units = tankSegment.getTotalUnits(partialTicks); - if (units < 1) - continue; - totalUnits += units; - renderedFluids++; - } - } - - if (renderedFluids == 0) - return 0; - if (totalUnits < 1) - return 0; - return totalUnits; - } - - private Optional getOperator() { - if (level == null) - return Optional.empty(); - BlockEntity te = level.getBlockEntity(worldPosition.above(2)); - if (te instanceof BasinOperatingTileEntity) - return Optional.of((BasinOperatingTileEntity) te); - return Optional.empty(); - } - - public FilteringBehaviour getFilter() { - return filtering; - } - - public void notifyChangeOfContents() { - contentsChanged = true; - } - - public SmartInventory getInputInventory() { - return inputInventory; - } - - public SmartInventory getOutputInventory() { - return outputInventory; - } - - public boolean canContinueProcessing() { - return spoutputBuffer.isEmpty() && spoutputFluidBuffer.isEmpty(); - } - - public boolean acceptOutputs(List outputItems, List outputFluids, boolean simulate) { - outputInventory.allowInsertion(); - outputTank.allowInsertion(); - boolean acceptOutputsInner = acceptOutputsInner(outputItems, outputFluids, simulate); - outputInventory.forbidInsertion(); - outputTank.forbidInsertion(); - return acceptOutputsInner; - } - - private boolean acceptOutputsInner(List outputItems, List outputFluids, boolean simulate) { - BlockState blockState = getBlockState(); - if (!(blockState.getBlock() instanceof BasinBlock)) - return false; - - Direction direction = blockState.getValue(BasinBlock.FACING); - if (direction != Direction.DOWN) { - - BlockEntity te = level.getBlockEntity(worldPosition.below() - .relative(direction)); - - InvManipulationBehaviour inserter = - te == null ? null : TileEntityBehaviour.get(level, te.getBlockPos(), InvManipulationBehaviour.TYPE); - IItemHandler targetInv = te == null ? null - : te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, direction.getOpposite()) - .orElse(inserter == null ? null : inserter.getInventory()); - IFluidHandler targetTank = te == null ? null - : te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, direction.getOpposite()) - .orElse(null); - boolean externalTankNotPresent = targetTank == null; - - if (!outputItems.isEmpty() && targetInv == null) - return false; - if (!outputFluids.isEmpty() && externalTankNotPresent) { - // Special case - fluid outputs but output only accepts items - targetTank = outputTank.getCapability() - .orElse(null); - if (targetTank == null) - return false; - if (!acceptFluidOutputsIntoBasin(outputFluids, simulate, targetTank)) - return false; - } - - if (simulate) - return true; - for (ItemStack itemStack : outputItems) { - if (itemStack.hasCraftingRemainingItem() && itemStack.getCraftingRemainingItem() - .sameItem(itemStack)) - continue; - spoutputBuffer.add(itemStack.copy()); - } - if (!externalTankNotPresent) - for (FluidStack fluidStack : outputFluids) - spoutputFluidBuffer.add(fluidStack.copy()); - return true; - } - - IItemHandler targetInv = outputInventory; - IFluidHandler targetTank = outputTank.getCapability() - .orElse(null); - - if (targetInv == null && !outputItems.isEmpty()) - return false; - if (!acceptItemOutputsIntoBasin(outputItems, simulate, targetInv)) - return false; - if (outputFluids.isEmpty()) - return true; - if (targetTank == null) - return false; - if (!acceptFluidOutputsIntoBasin(outputFluids, simulate, targetTank)) - return false; - - return true; - } - - private boolean acceptFluidOutputsIntoBasin(List outputFluids, boolean simulate, - IFluidHandler targetTank) { - for (FluidStack fluidStack : outputFluids) { - FluidAction action = simulate ? FluidAction.SIMULATE : FluidAction.EXECUTE; - int fill = targetTank instanceof SmartFluidTankBehaviour.InternalFluidHandler - ? ((SmartFluidTankBehaviour.InternalFluidHandler) targetTank).forceFill(fluidStack.copy(), action) - : targetTank.fill(fluidStack.copy(), action); - if (fill != fluidStack.getAmount()) - return false; - } - return true; - } - - private boolean acceptItemOutputsIntoBasin(List outputItems, boolean simulate, IItemHandler targetInv) { - for (ItemStack itemStack : outputItems) { - // Catalyst items are never consumed - if (itemStack.hasCraftingRemainingItem() && itemStack.getCraftingRemainingItem() - .sameItem(itemStack)) - continue; - if (!ItemHandlerHelper.insertItemStacked(targetInv, itemStack.copy(), simulate) - .isEmpty()) - return false; - } - return true; - } - - public void readOnlyItems(CompoundTag compound) { - inputInventory.deserializeNBT(compound.getCompound("InputItems")); - outputInventory.deserializeNBT(compound.getCompound("OutputItems")); - } - - public static HeatLevel getHeatLevelOf(BlockState state) { - if (state.hasProperty(BlazeBurnerBlock.HEAT_LEVEL)) - return state.getValue(BlazeBurnerBlock.HEAT_LEVEL); - return AllTags.AllBlockTags.PASSIVE_BOILER_HEATERS.matches(state) ? HeatLevel.SMOULDERING : HeatLevel.NONE; - } - - public Couple getTanks() { - return tanks; - } - - public Couple getInvs() { - return invs; - } - - // client things - - private void tickVisualizedOutputs() { - visualizedOutputFluids.forEach(IntAttached::decrement); - visualizedOutputItems.forEach(IntAttached::decrement); - visualizedOutputFluids.removeIf(IntAttached::isOrBelowZero); - visualizedOutputItems.removeIf(IntAttached::isOrBelowZero); - } - - private void createFluidParticles() { - RandomSource r = level.random; - - if (!visualizedOutputFluids.isEmpty()) - createOutputFluidParticles(r); - - if (!areFluidsMoving && r.nextFloat() > 1 / 8f) - return; - - int segments = 0; - for (SmartFluidTankBehaviour behaviour : getTanks()) { - if (behaviour == null) - continue; - for (TankSegment tankSegment : behaviour.getTanks()) - if (!tankSegment.isEmpty(0)) - segments++; - } - if (segments < 2) - return; - - float totalUnits = getTotalFluidUnits(0); - if (totalUnits == 0) - return; - float fluidLevel = Mth.clamp(totalUnits / 2000, 0, 1); - float rim = 2 / 16f; - float space = 12 / 16f; - float surface = worldPosition.getY() + rim + space * fluidLevel + 1 / 32f; - - if (areFluidsMoving) { - createMovingFluidParticles(surface, segments); - return; - } - - for (SmartFluidTankBehaviour behaviour : getTanks()) { - if (behaviour == null) - continue; - for (TankSegment tankSegment : behaviour.getTanks()) { - if (tankSegment.isEmpty(0)) - continue; - float x = worldPosition.getX() + rim + space * r.nextFloat(); - float z = worldPosition.getZ() + rim + space * r.nextFloat(); - level.addAlwaysVisibleParticle( - new FluidParticleData(AllParticleTypes.BASIN_FLUID.get(), tankSegment.getRenderedFluid()), x, - surface, z, 0, 0, 0); - } - } - } - - private void createOutputFluidParticles(RandomSource r) { - BlockState blockState = getBlockState(); - if (!(blockState.getBlock() instanceof BasinBlock)) - return; - Direction direction = blockState.getValue(BasinBlock.FACING); - if (direction == Direction.DOWN) - return; - Vec3 directionVec = Vec3.atLowerCornerOf(direction.getNormal()); - Vec3 outVec = VecHelper.getCenterOf(worldPosition) - .add(directionVec.scale(.65) - .subtract(0, 1 / 4f, 0)); - Vec3 outMotion = directionVec.scale(1 / 16f) - .add(0, -1 / 16f, 0); - - for (int i = 0; i < 2; i++) { - visualizedOutputFluids.forEach(ia -> { - FluidStack fluidStack = ia.getValue(); - ParticleOptions fluidParticle = FluidFX.getFluidParticle(fluidStack); - Vec3 m = VecHelper.offsetRandomly(outMotion, r, 1 / 16f); - level.addAlwaysVisibleParticle(fluidParticle, outVec.x, outVec.y, outVec.z, m.x, m.y, m.z); - }); - } - } - - private void createMovingFluidParticles(float surface, int segments) { - Vec3 pointer = new Vec3(1, 0, 0).scale(1 / 16f); - float interval = 360f / segments; - Vec3 centerOf = VecHelper.getCenterOf(worldPosition); - float intervalOffset = (AnimationTickHolder.getTicks() * 18) % 360; - - int currentSegment = 0; - for (SmartFluidTankBehaviour behaviour : getTanks()) { - if (behaviour == null) - continue; - for (TankSegment tankSegment : behaviour.getTanks()) { - if (tankSegment.isEmpty(0)) - continue; - float angle = interval * (1 + currentSegment) + intervalOffset; - Vec3 vec = centerOf.add(VecHelper.rotate(pointer, angle, Axis.Y)); - level.addAlwaysVisibleParticle( - new FluidParticleData(AllParticleTypes.BASIN_FLUID.get(), tankSegment.getRenderedFluid()), vec.x(), - surface, vec.z(), 1, 0, 0); - currentSegment++; - } - } - } - - public boolean areFluidsMoving() { - return areFluidsMoving; - } - - public boolean setAreFluidsMoving(boolean areFluidsMoving) { - this.areFluidsMoving = areFluidsMoving; - ingredientRotationSpeed.chase(areFluidsMoving ? 20 : 0, .1f, Chaser.EXP); - return areFluidsMoving; - } - - @Override - public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { - return containedFluidTooltip(tooltip, isPlayerSneaking, - getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY)); - } - - class BasinValueBox extends ValueBoxTransform.Sided { - - @Override - protected Vec3 getSouthLocation() { - return VecHelper.voxelSpace(8, 12, 15.75); - } - - @Override - protected boolean isSideActive(BlockState state, Direction direction) { - return direction.getAxis() - .isHorizontal(); - } - - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/EmptyingByBasin.java b/src/main/java/com/simibubi/create/content/contraptions/processing/EmptyingByBasin.java deleted file mode 100644 index 1a29725af..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/EmptyingByBasin.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.simibubi.create.content.contraptions.processing; - -import java.util.List; -import java.util.Optional; - -import com.simibubi.create.AllRecipeTypes; -import com.simibubi.create.content.contraptions.fluids.potion.PotionFluidHandler; -import com.simibubi.create.foundation.utility.Pair; - -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.PotionItem; -import net.minecraft.world.item.crafting.Recipe; -import net.minecraft.world.level.Level; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.capability.CapabilityFluidHandler; -import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction; -import net.minecraftforge.fluids.capability.IFluidHandlerItem; -import net.minecraftforge.items.ItemStackHandler; -import net.minecraftforge.items.wrapper.RecipeWrapper; - -public class EmptyingByBasin { - - static RecipeWrapper wrapper = new RecipeWrapper(new ItemStackHandler(1)); - - public static boolean canItemBeEmptied(Level world, ItemStack stack) { - if (stack.getItem() instanceof PotionItem) - return true; - - wrapper.setItem(0, stack); - if (AllRecipeTypes.EMPTYING.find(wrapper, world) - .isPresent()) - return true; - - LazyOptional capability = - stack.getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY); - IFluidHandlerItem tank = capability.orElse(null); - if (tank == null) - return false; - for (int i = 0; i < tank.getTanks(); i++) { - if (tank.getFluidInTank(i) - .getAmount() > 0) - return true; - } - return false; - } - - public static Pair emptyItem(Level world, ItemStack stack, boolean simulate) { - FluidStack resultingFluid = FluidStack.EMPTY; - ItemStack resultingItem = ItemStack.EMPTY; - - if (stack.getItem() instanceof PotionItem) - return PotionFluidHandler.emptyPotion(stack, simulate); - - wrapper.setItem(0, stack); - Optional> recipe = AllRecipeTypes.EMPTYING.find(wrapper, world); - if (recipe.isPresent()) { - EmptyingRecipe emptyingRecipe = (EmptyingRecipe) recipe.get(); - List results = emptyingRecipe.rollResults(); - if (!simulate) - stack.shrink(1); - resultingItem = results.isEmpty() ? ItemStack.EMPTY : results.get(0); - resultingFluid = emptyingRecipe.getResultingFluid(); - return Pair.of(resultingFluid, resultingItem); - } - - ItemStack split = stack.copy(); - split.setCount(1); - LazyOptional capability = - split.getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY); - IFluidHandlerItem tank = capability.orElse(null); - if (tank == null) - return Pair.of(resultingFluid, resultingItem); - resultingFluid = tank.drain(1000, simulate ? FluidAction.SIMULATE : FluidAction.EXECUTE); - resultingItem = tank.getContainer() - .copy(); - if (!simulate) - stack.shrink(1); - - return Pair.of(resultingFluid, resultingItem); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/InWorldProcessing.java b/src/main/java/com/simibubi/create/content/contraptions/processing/InWorldProcessing.java deleted file mode 100644 index c6d787d8c..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/InWorldProcessing.java +++ /dev/null @@ -1,506 +0,0 @@ -package com.simibubi.create.content.contraptions.processing; - -import static com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.getHeatLevelOf; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Optional; - -import org.joml.Vector3f; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllRecipeTypes; -import com.simibubi.create.content.contraptions.components.deployer.ManualApplicationRecipe; -import com.simibubi.create.content.contraptions.components.fan.HauntingRecipe; -import com.simibubi.create.content.contraptions.components.fan.SplashingRecipe; -import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock; -import com.simibubi.create.content.contraptions.processing.burner.LitBlazeBurnerBlock; -import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.item.ItemHelper; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour.TransportedResult; -import com.simibubi.create.foundation.utility.Color; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.particles.DustParticleOptions; -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.tags.BlockTags; -import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.effect.MobEffects; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.animal.horse.Horse; -import net.minecraft.world.entity.animal.horse.SkeletonHorse; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.entity.monster.EnderMan; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.BlastingRecipe; -import net.minecraft.world.item.crafting.Recipe; -import net.minecraft.world.item.crafting.RecipeType; -import net.minecraft.world.item.crafting.SmeltingRecipe; -import net.minecraft.world.item.crafting.SmokingRecipe; -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.Blocks; -import net.minecraft.world.level.block.CampfireBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.FluidState; -import net.minecraft.world.level.material.Fluids; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.items.ItemHandlerHelper; -import net.minecraftforge.items.ItemStackHandler; -import net.minecraftforge.items.wrapper.RecipeWrapper; - -public class InWorldProcessing { - - private static final DamageSource FIRE_DAMAGE_SOURCE = new DamageSource("create.fan_fire").setScalesWithDifficulty() - .setIsFire(); - private static final DamageSource LAVA_DAMAGE_SOURCE = new DamageSource("create.fan_lava").setScalesWithDifficulty() - .setIsFire(); - - private static final RecipeWrapper RECIPE_WRAPPER = new RecipeWrapper(new ItemStackHandler(1)); - private static final SplashingWrapper SPLASHING_WRAPPER = new SplashingWrapper(); - private static final HauntingWrapper HAUNTING_WRAPPER = new HauntingWrapper(); - - public static boolean canProcess(ItemEntity entity, Type type) { - if (entity.getPersistentData() - .contains("CreateData")) { - CompoundTag compound = entity.getPersistentData() - .getCompound("CreateData"); - if (compound.contains("Processing")) { - CompoundTag processing = compound.getCompound("Processing"); - - if (Type.valueOf(processing.getString("Type")) != type) - return type.canProcess(entity.getItem(), entity.level); - else if (processing.getInt("Time") >= 0) - return true; - else if (processing.getInt("Time") == -1) - return false; - } - } - return type.canProcess(entity.getItem(), entity.level); - } - - public static boolean isWashable(ItemStack stack, Level world) { - SPLASHING_WRAPPER.setItem(0, stack); - Optional recipe = AllRecipeTypes.SPLASHING.find(SPLASHING_WRAPPER, world); - return recipe.isPresent(); - } - - public static boolean isHauntable(ItemStack stack, Level world) { - HAUNTING_WRAPPER.setItem(0, stack); - Optional recipe = AllRecipeTypes.HAUNTING.find(HAUNTING_WRAPPER, world); - return recipe.isPresent(); - } - - public static boolean applyProcessing(ItemEntity entity, Type type) { - if (decrementProcessingTime(entity, type) != 0) - return false; - List stacks = process(entity.getItem(), type, entity.level); - if (stacks == null) - return false; - if (stacks.isEmpty()) { - entity.discard(); - return false; - } - entity.setItem(stacks.remove(0)); - for (ItemStack additional : stacks) { - ItemEntity entityIn = new ItemEntity(entity.level, entity.getX(), entity.getY(), entity.getZ(), additional); - entityIn.setDeltaMovement(entity.getDeltaMovement()); - entity.level.addFreshEntity(entityIn); - } - return true; - } - - public static TransportedResult applyProcessing(TransportedItemStack transported, Level world, Type type) { - TransportedResult ignore = TransportedResult.doNothing(); - if (transported.processedBy != type) { - transported.processedBy = type; - int timeModifierForStackSize = ((transported.stack.getCount() - 1) / 16) + 1; - int processingTime = - (int) (AllConfigs.SERVER.kinetics.inWorldProcessingTime.get() * timeModifierForStackSize) + 1; - transported.processingTime = processingTime; - if (!type.canProcess(transported.stack, world)) - transported.processingTime = -1; - return ignore; - } - if (transported.processingTime == -1) - return ignore; - if (transported.processingTime-- > 0) - return ignore; - - List stacks = process(transported.stack, type, world); - if (stacks == null) - return ignore; - - List transportedStacks = new ArrayList<>(); - for (ItemStack additional : stacks) { - TransportedItemStack newTransported = transported.getSimilar(); - newTransported.stack = additional.copy(); - transportedStacks.add(newTransported); - } - return TransportedResult.convertTo(transportedStacks); - } - - private static List process(ItemStack stack, Type type, Level world) { - if (type == Type.SPLASHING) { - SPLASHING_WRAPPER.setItem(0, stack); - Optional recipe = AllRecipeTypes.SPLASHING.find(SPLASHING_WRAPPER, world); - if (recipe.isPresent()) - return applyRecipeOn(stack, recipe.get()); - return null; - } - if (type == Type.HAUNTING) { - HAUNTING_WRAPPER.setItem(0, stack); - Optional recipe = AllRecipeTypes.HAUNTING.find(HAUNTING_WRAPPER, world); - if (recipe.isPresent()) - return applyRecipeOn(stack, recipe.get()); - return null; - } - - RECIPE_WRAPPER.setItem(0, stack); - Optional smokingRecipe = world.getRecipeManager() - .getRecipeFor(RecipeType.SMOKING, RECIPE_WRAPPER, world); - - if (type == Type.BLASTING) { - if (!smokingRecipe.isPresent()) { - RECIPE_WRAPPER.setItem(0, stack); - Optional smeltingRecipe = world.getRecipeManager() - .getRecipeFor(RecipeType.SMELTING, RECIPE_WRAPPER, world); - - if (smeltingRecipe.isPresent()) - return applyRecipeOn(stack, smeltingRecipe.get()); - - RECIPE_WRAPPER.setItem(0, stack); - Optional blastingRecipe = world.getRecipeManager() - .getRecipeFor(RecipeType.BLASTING, RECIPE_WRAPPER, world); - - if (blastingRecipe.isPresent()) - return applyRecipeOn(stack, blastingRecipe.get()); - } - - return Collections.emptyList(); - } - - if (type == Type.SMOKING && smokingRecipe.isPresent()) - return applyRecipeOn(stack, smokingRecipe.get()); - - return null; - } - - private static int decrementProcessingTime(ItemEntity entity, Type type) { - CompoundTag nbt = entity.getPersistentData(); - - if (!nbt.contains("CreateData")) - nbt.put("CreateData", new CompoundTag()); - CompoundTag createData = nbt.getCompound("CreateData"); - - if (!createData.contains("Processing")) - createData.put("Processing", new CompoundTag()); - CompoundTag processing = createData.getCompound("Processing"); - - if (!processing.contains("Type") || Type.valueOf(processing.getString("Type")) != type) { - processing.putString("Type", type.name()); - int timeModifierForStackSize = ((entity.getItem() - .getCount() - 1) / 16) + 1; - int processingTime = - (int) (AllConfigs.SERVER.kinetics.inWorldProcessingTime.get() * timeModifierForStackSize) + 1; - processing.putInt("Time", processingTime); - } - - int value = processing.getInt("Time") - 1; - processing.putInt("Time", value); - return value; - } - - public static void applyRecipeOn(ItemEntity entity, Recipe recipe) { - List stacks = applyRecipeOn(entity.getItem(), recipe); - if (stacks == null) - return; - if (stacks.isEmpty()) { - entity.discard(); - return; - } - entity.setItem(stacks.remove(0)); - for (ItemStack additional : stacks) { - ItemEntity entityIn = new ItemEntity(entity.level, entity.getX(), entity.getY(), entity.getZ(), additional); - entityIn.setDeltaMovement(entity.getDeltaMovement()); - entity.level.addFreshEntity(entityIn); - } - } - - public static List applyRecipeOn(ItemStack stackIn, Recipe recipe) { - List stacks; - - if (recipe instanceof ProcessingRecipe pr) { - stacks = new ArrayList<>(); - for (int i = 0; i < stackIn.getCount(); i++) { - List outputs = - pr instanceof ManualApplicationRecipe mar ? mar.getRollableResults() : pr.getRollableResults(); - for (ItemStack stack : pr.rollResults(outputs)) { - for (ItemStack previouslyRolled : stacks) { - if (stack.isEmpty()) - continue; - if (!ItemHandlerHelper.canItemStacksStack(stack, previouslyRolled)) - continue; - int amount = Math.min(previouslyRolled.getMaxStackSize() - previouslyRolled.getCount(), - stack.getCount()); - previouslyRolled.grow(amount); - stack.shrink(amount); - } - - if (stack.isEmpty()) - continue; - - stacks.add(stack); - } - } - } else { - ItemStack out = recipe.getResultItem() - .copy(); - stacks = ItemHelper.multipliedOutput(stackIn, out); - } - - return stacks; - } - - public enum Type { - SPLASHING { - @Override - public void spawnParticlesForProcessing(Level level, Vec3 pos) { - if (level.random.nextInt(8) != 0) - return; - Vector3f color = new Color(0x0055FF).asVectorF(); - level.addParticle(new DustParticleOptions(color, 1), pos.x + (level.random.nextFloat() - .5f) * .5f, - pos.y + .5f, pos.z + (level.random.nextFloat() - .5f) * .5f, 0, 1 / 8f, 0); - level.addParticle(ParticleTypes.SPIT, pos.x + (level.random.nextFloat() - .5f) * .5f, pos.y + .5f, - pos.z + (level.random.nextFloat() - .5f) * .5f, 0, 1 / 8f, 0); - } - - @Override - public void affectEntity(Entity entity, Level level) { - if (level.isClientSide) - return; - - if (entity instanceof EnderMan || entity.getType() == EntityType.SNOW_GOLEM - || entity.getType() == EntityType.BLAZE) { - entity.hurt(DamageSource.DROWN, 2); - } - if (entity.isOnFire()) { - entity.clearFire(); - level.playSound(null, entity.blockPosition(), SoundEvents.GENERIC_EXTINGUISH_FIRE, - SoundSource.NEUTRAL, 0.7F, 1.6F + (level.random.nextFloat() - level.random.nextFloat()) * 0.4F); - } - } - - @Override - public boolean canProcess(ItemStack stack, Level level) { - return isWashable(stack, level); - } - }, - SMOKING { - @Override - public void spawnParticlesForProcessing(Level level, Vec3 pos) { - if (level.random.nextInt(8) != 0) - return; - level.addParticle(ParticleTypes.POOF, pos.x, pos.y + .25f, pos.z, 0, 1 / 16f, 0); - } - - @Override - public void affectEntity(Entity entity, Level level) { - if (level.isClientSide) - return; - - if (!entity.fireImmune()) { - entity.setSecondsOnFire(2); - entity.hurt(FIRE_DAMAGE_SOURCE, 2); - } - } - - @Override - public boolean canProcess(ItemStack stack, Level level) { - RECIPE_WRAPPER.setItem(0, stack); - Optional recipe = level.getRecipeManager() - .getRecipeFor(RecipeType.SMOKING, RECIPE_WRAPPER, level); - return recipe.isPresent(); - } - }, - HAUNTING { - @Override - public void spawnParticlesForProcessing(Level level, Vec3 pos) { - if (level.random.nextInt(8) != 0) - return; - pos = pos.add(VecHelper.offsetRandomly(Vec3.ZERO, level.random, 1) - .multiply(1, 0.05f, 1) - .normalize() - .scale(0.15f)); - level.addParticle(ParticleTypes.SOUL_FIRE_FLAME, pos.x, pos.y + .45f, pos.z, 0, 0, 0); - if (level.random.nextInt(2) == 0) - level.addParticle(ParticleTypes.SMOKE, pos.x, pos.y + .25f, pos.z, 0, 0, 0); - } - - @Override - public void affectEntity(Entity entity, Level level) { - if (level.isClientSide) { - if (entity instanceof Horse) { - Vec3 p = entity.getPosition(0); - Vec3 v = p.add(0, 0.5f, 0) - .add(VecHelper.offsetRandomly(Vec3.ZERO, level.random, 1) - .multiply(1, 0.2f, 1) - .normalize() - .scale(1f)); - level.addParticle(ParticleTypes.SOUL_FIRE_FLAME, v.x, v.y, v.z, 0, 0.1f, 0); - if (level.random.nextInt(3) == 0) - level.addParticle(ParticleTypes.LARGE_SMOKE, p.x, p.y + .5f, p.z, - (level.random.nextFloat() - .5f) * .5f, 0.1f, (level.random.nextFloat() - .5f) * .5f); - } - return; - } - - if (entity instanceof LivingEntity livingEntity) { - livingEntity.addEffect(new MobEffectInstance(MobEffects.BLINDNESS, 30, 0, false, false)); - livingEntity.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, 20, 1, false, false)); - } - if (entity instanceof Horse horse) { - int progress = horse.getPersistentData() - .getInt("CreateHaunting"); - if (progress < 100) { - if (progress % 10 == 0) { - level.playSound(null, entity.blockPosition(), SoundEvents.SOUL_ESCAPE, SoundSource.NEUTRAL, - 1f, 1.5f * progress / 100f); - } - horse.getPersistentData() - .putInt("CreateHaunting", progress + 1); - return; - } - - level.playSound(null, entity.blockPosition(), SoundEvents.GENERIC_EXTINGUISH_FIRE, - SoundSource.NEUTRAL, 1.25f, 0.65f); - - SkeletonHorse skeletonHorse = EntityType.SKELETON_HORSE.create(level); - CompoundTag serializeNBT = horse.saveWithoutId(new CompoundTag()); - serializeNBT.remove("UUID"); - if (!horse.getArmor() - .isEmpty()) - horse.spawnAtLocation(horse.getArmor()); - - skeletonHorse.deserializeNBT(serializeNBT); - skeletonHorse.setPos(horse.getPosition(0)); - level.addFreshEntity(skeletonHorse); - horse.discard(); - } - } - - @Override - public boolean canProcess(ItemStack stack, Level level) { - return isHauntable(stack, level); - } - }, - BLASTING { - @Override - public void spawnParticlesForProcessing(Level level, Vec3 pos) { - if (level.random.nextInt(8) != 0) - return; - level.addParticle(ParticleTypes.LARGE_SMOKE, pos.x, pos.y + .25f, pos.z, 0, 1 / 16f, 0); - } - - @Override - public void affectEntity(Entity entity, Level level) { - if (level.isClientSide) - return; - - if (!entity.fireImmune()) { - entity.setSecondsOnFire(10); - entity.hurt(LAVA_DAMAGE_SOURCE, 4); - } - } - - @Override - public boolean canProcess(ItemStack stack, Level level) { - RECIPE_WRAPPER.setItem(0, stack); - Optional smeltingRecipe = level.getRecipeManager() - .getRecipeFor(RecipeType.SMELTING, RECIPE_WRAPPER, level); - - if (smeltingRecipe.isPresent()) - return true; - - RECIPE_WRAPPER.setItem(0, stack); - Optional blastingRecipe = level.getRecipeManager() - .getRecipeFor(RecipeType.BLASTING, RECIPE_WRAPPER, level); - - if (blastingRecipe.isPresent()) - return true; - - return !stack.getItem() - .isFireResistant(); - } - }, - NONE { - @Override - public void spawnParticlesForProcessing(Level level, Vec3 pos) {} - - @Override - public void affectEntity(Entity entity, Level level) {} - - @Override - public boolean canProcess(ItemStack stack, Level level) { - return false; - } - }; - - public abstract boolean canProcess(ItemStack stack, Level level); - - public abstract void spawnParticlesForProcessing(Level level, Vec3 pos); - - public abstract void affectEntity(Entity entity, Level level); - - public static Type byBlock(BlockGetter reader, BlockPos pos) { - FluidState fluidState = reader.getFluidState(pos); - if (fluidState.getType() == Fluids.WATER || fluidState.getType() == Fluids.FLOWING_WATER) - return Type.SPLASHING; - BlockState blockState = reader.getBlockState(pos); - Block block = blockState.getBlock(); - if (block == Blocks.SOUL_FIRE - || block == Blocks.SOUL_CAMPFIRE && blockState.getOptionalValue(CampfireBlock.LIT) - .orElse(false) - || AllBlocks.LIT_BLAZE_BURNER.has(blockState) - && blockState.getOptionalValue(LitBlazeBurnerBlock.FLAME_TYPE) - .map(flame -> flame == LitBlazeBurnerBlock.FlameType.SOUL) - .orElse(false)) - return Type.HAUNTING; - if (block == Blocks.FIRE - || blockState.is(BlockTags.CAMPFIRES) && blockState.getOptionalValue(CampfireBlock.LIT) - .orElse(false) - || AllBlocks.LIT_BLAZE_BURNER.has(blockState) - && blockState.getOptionalValue(LitBlazeBurnerBlock.FLAME_TYPE) - .map(flame -> flame == LitBlazeBurnerBlock.FlameType.REGULAR) - .orElse(false) - || getHeatLevelOf(blockState) == BlazeBurnerBlock.HeatLevel.SMOULDERING) - return Type.SMOKING; - if (block == Blocks.LAVA || getHeatLevelOf(blockState).isAtLeast(BlazeBurnerBlock.HeatLevel.FADING)) - return Type.BLASTING; - return Type.NONE; - } - } - - public static class SplashingWrapper extends RecipeWrapper { - public SplashingWrapper() { - super(new ItemStackHandler(1)); - } - } - - public static class HauntingWrapper extends RecipeWrapper { - public HauntingWrapper() { - super(new ItemStackHandler(1)); - } - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerTileEntity.java deleted file mode 100644 index ee081438f..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerTileEntity.java +++ /dev/null @@ -1,352 +0,0 @@ -package com.simibubi.create.content.contraptions.processing.burner; - -import java.util.List; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllItems; -import com.simibubi.create.AllTags.AllItemTags; -import com.simibubi.create.content.contraptions.fluids.tank.FluidTankBlock; -import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.HeatLevel; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.player.LocalPlayer; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.util.Mth; -import net.minecraft.util.RandomSource; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.common.ForgeHooks; - -public class BlazeBurnerTileEntity extends SmartTileEntity { - - public static final int MAX_HEAT_CAPACITY = 10000; - public static final int INSERTION_THRESHOLD = 500; - - protected FuelType activeFuel; - protected int remainingBurnTime; - protected LerpedFloat headAnimation; - protected LerpedFloat headAngle; - protected boolean isCreative; - protected boolean goggles; - protected boolean hat; - - public BlazeBurnerTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - activeFuel = FuelType.NONE; - remainingBurnTime = 0; - headAnimation = LerpedFloat.linear(); - headAngle = LerpedFloat.angular(); - isCreative = false; - goggles = false; - - headAngle.startWithValue((AngleHelper.horizontalAngle(state.getOptionalValue(BlazeBurnerBlock.FACING) - .orElse(Direction.SOUTH)) + 180) % 360); - } - - public FuelType getActiveFuel() { - return activeFuel; - } - - public int getRemainingBurnTime() { - return remainingBurnTime; - } - - public boolean isCreative() { - return isCreative; - } - - @Override - public void tick() { - super.tick(); - - if (level.isClientSide) { - tickAnimation(); - if (!isVirtual()) - spawnParticles(getHeatLevelFromBlock(), 1); - return; - } - - if (isCreative) - return; - - if (remainingBurnTime > 0) - remainingBurnTime--; - - if (activeFuel == FuelType.NORMAL) - updateBlockState(); - if (remainingBurnTime > 0) - return; - - if (activeFuel == FuelType.SPECIAL) { - activeFuel = FuelType.NORMAL; - remainingBurnTime = MAX_HEAT_CAPACITY / 2; - } else - activeFuel = FuelType.NONE; - - updateBlockState(); - } - - @OnlyIn(Dist.CLIENT) - private void tickAnimation() { - boolean active = getHeatLevelFromBlock().isAtLeast(HeatLevel.FADING) && isValidBlockAbove(); - - if (!active) { - float target = 0; - LocalPlayer player = Minecraft.getInstance().player; - if (player != null && !player.isInvisible()) { - double x; - double z; - if (isVirtual()) { - x = -4; - z = -10; - } else { - x = player.getX(); - z = player.getZ(); - } - double dx = x - (getBlockPos().getX() + 0.5); - double dz = z - (getBlockPos().getZ() + 0.5); - target = AngleHelper.deg(-Mth.atan2(dz, dx)) - 90; - } - target = headAngle.getValue() + AngleHelper.getShortestAngleDiff(headAngle.getValue(), target); - headAngle.chase(target, .25f, Chaser.exp(5)); - headAngle.tickChaser(); - } else { - headAngle.chase((AngleHelper.horizontalAngle(getBlockState().getOptionalValue(BlazeBurnerBlock.FACING) - .orElse(Direction.SOUTH)) + 180) % 360, .125f, Chaser.EXP); - headAngle.tickChaser(); - } - - headAnimation.chase(active ? 1 : 0, .25f, Chaser.exp(.25f)); - headAnimation.tickChaser(); - } - - @Override - public void addBehaviours(List behaviours) {} - - @Override - public void write(CompoundTag compound, boolean clientPacket) { - if (!isCreative) { - compound.putInt("fuelLevel", activeFuel.ordinal()); - compound.putInt("burnTimeRemaining", remainingBurnTime); - } else - compound.putBoolean("isCreative", true); - if (goggles) - compound.putBoolean("Goggles", true); - if (hat) - compound.putBoolean("TrainHat", true); - super.write(compound, clientPacket); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - activeFuel = FuelType.values()[compound.getInt("fuelLevel")]; - remainingBurnTime = compound.getInt("burnTimeRemaining"); - isCreative = compound.getBoolean("isCreative"); - goggles = compound.contains("Goggles"); - hat = compound.contains("TrainHat"); - super.read(compound, clientPacket); - } - - public BlazeBurnerBlock.HeatLevel getHeatLevelFromBlock() { - return BlazeBurnerBlock.getHeatLevelOf(getBlockState()); - } - - public void updateBlockState() { - setBlockHeat(getHeatLevel()); - } - - protected void setBlockHeat(HeatLevel heat) { - HeatLevel inBlockState = getHeatLevelFromBlock(); - if (inBlockState == heat) - return; - level.setBlockAndUpdate(worldPosition, getBlockState().setValue(BlazeBurnerBlock.HEAT_LEVEL, heat)); - notifyUpdate(); - } - - /** - * @return true if the heater updated its burn time and an item should be - * consumed - */ - protected boolean tryUpdateFuel(ItemStack itemStack, boolean forceOverflow, boolean simulate) { - if (isCreative) - return false; - - FuelType newFuel = FuelType.NONE; - int newBurnTime; - - if (AllItemTags.BLAZE_BURNER_FUEL_SPECIAL.matches(itemStack)) { - newBurnTime = 3200; - newFuel = FuelType.SPECIAL; - } else { - newBurnTime = ForgeHooks.getBurnTime(itemStack, null); - if (newBurnTime > 0) { - newFuel = FuelType.NORMAL; - } else if (AllItemTags.BLAZE_BURNER_FUEL_REGULAR.matches(itemStack)) { - newBurnTime = 1600; // Same as coal - newFuel = FuelType.NORMAL; - } - } - - if (newFuel == FuelType.NONE) - return false; - if (newFuel.ordinal() < activeFuel.ordinal()) - return false; - - if (newFuel == activeFuel) { - if (remainingBurnTime <= INSERTION_THRESHOLD) { - newBurnTime += remainingBurnTime; - } else if (forceOverflow && newFuel == FuelType.NORMAL) { - if (remainingBurnTime < MAX_HEAT_CAPACITY) { - newBurnTime = Math.min(remainingBurnTime + newBurnTime, MAX_HEAT_CAPACITY); - } else { - newBurnTime = remainingBurnTime; - } - } else { - return false; - } - } - - if (simulate) - return true; - - activeFuel = newFuel; - remainingBurnTime = newBurnTime; - - if (level.isClientSide) { - spawnParticleBurst(activeFuel == FuelType.SPECIAL); - return true; - } - - HeatLevel prev = getHeatLevelFromBlock(); - playSound(); - updateBlockState(); - - if (prev != getHeatLevelFromBlock()) - level.playSound(null, worldPosition, SoundEvents.BLAZE_AMBIENT, SoundSource.BLOCKS, - .125f + level.random.nextFloat() * .125f, 1.15f - level.random.nextFloat() * .25f); - - return true; - } - - protected void applyCreativeFuel() { - activeFuel = FuelType.NONE; - remainingBurnTime = 0; - isCreative = true; - - HeatLevel next = getHeatLevelFromBlock().nextActiveLevel(); - - if (level.isClientSide) { - spawnParticleBurst(next.isAtLeast(HeatLevel.SEETHING)); - return; - } - - playSound(); - if (next == HeatLevel.FADING) - next = next.nextActiveLevel(); - setBlockHeat(next); - } - - public boolean isCreativeFuel(ItemStack stack) { - return AllItems.CREATIVE_BLAZE_CAKE.isIn(stack); - } - - public boolean isValidBlockAbove() { - BlockState blockState = level.getBlockState(worldPosition.above()); - return AllBlocks.BASIN.has(blockState) || blockState.getBlock() instanceof FluidTankBlock; - } - - protected void playSound() { - level.playSound(null, worldPosition, SoundEvents.BLAZE_SHOOT, SoundSource.BLOCKS, - .125f + level.random.nextFloat() * .125f, .75f - level.random.nextFloat() * .25f); - } - - protected HeatLevel getHeatLevel() { - HeatLevel level = HeatLevel.SMOULDERING; - switch (activeFuel) { - case SPECIAL: - level = HeatLevel.SEETHING; - break; - case NORMAL: - boolean lowPercent = (double) remainingBurnTime / MAX_HEAT_CAPACITY < 0.0125; - level = lowPercent ? HeatLevel.FADING : HeatLevel.KINDLED; - break; - default: - case NONE: - break; - } - return level; - } - - protected void spawnParticles(HeatLevel heatLevel, double burstMult) { - if (level == null) - return; - if (heatLevel == BlazeBurnerBlock.HeatLevel.NONE) - return; - - RandomSource r = level.getRandom(); - - Vec3 c = VecHelper.getCenterOf(worldPosition); - Vec3 v = c.add(VecHelper.offsetRandomly(Vec3.ZERO, r, .125f) - .multiply(1, 0, 1)); - - if (r.nextInt(4) != 0) - return; - - boolean empty = level.getBlockState(worldPosition.above()) - .getCollisionShape(level, worldPosition.above()) - .isEmpty(); - - if (empty || r.nextInt(8) == 0) - level.addParticle(ParticleTypes.LARGE_SMOKE, v.x, v.y, v.z, 0, 0, 0); - - double yMotion = empty ? .0625f : r.nextDouble() * .0125f; - Vec3 v2 = c.add(VecHelper.offsetRandomly(Vec3.ZERO, r, .5f) - .multiply(1, .25f, 1) - .normalize() - .scale((empty ? .25f : .5) + r.nextDouble() * .125f)) - .add(0, .5, 0); - - if (heatLevel.isAtLeast(HeatLevel.SEETHING)) { - level.addParticle(ParticleTypes.SOUL_FIRE_FLAME, v2.x, v2.y, v2.z, 0, yMotion, 0); - } else if (heatLevel.isAtLeast(HeatLevel.FADING)) { - level.addParticle(ParticleTypes.FLAME, v2.x, v2.y, v2.z, 0, yMotion, 0); - } - return; - } - - public void spawnParticleBurst(boolean soulFlame) { - Vec3 c = VecHelper.getCenterOf(worldPosition); - RandomSource r = level.random; - for (int i = 0; i < 20; i++) { - Vec3 offset = VecHelper.offsetRandomly(Vec3.ZERO, r, .5f) - .multiply(1, .25f, 1) - .normalize(); - Vec3 v = c.add(offset.scale(.5 + r.nextDouble() * .125f)) - .add(0, .125, 0); - Vec3 m = offset.scale(1 / 32f); - - level.addParticle(soulFlame ? ParticleTypes.SOUL_FIRE_FLAME : ParticleTypes.FLAME, v.x, v.y, v.z, m.x, m.y, - m.z); - } - } - - public enum FuelType { - NONE, NORMAL, SPECIAL - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/AbstractPulleyInstance.java b/src/main/java/com/simibubi/create/content/contraptions/pulley/AbstractPulleyInstance.java similarity index 91% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/AbstractPulleyInstance.java rename to src/main/java/com/simibubi/create/content/contraptions/pulley/AbstractPulleyInstance.java index f2e37bd82..522b81c2a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/AbstractPulleyInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/pulley/AbstractPulleyInstance.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.pulley; +package com.simibubi.create.content.contraptions.pulley; import com.jozufozu.flywheel.api.Instancer; import com.jozufozu.flywheel.api.MaterialManager; @@ -13,14 +13,14 @@ import com.jozufozu.flywheel.light.TickingLightListener; import com.jozufozu.flywheel.util.box.GridAlignedBB; import com.jozufozu.flywheel.util.box.ImmutableBox; import com.mojang.math.Axis; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.relays.encased.ShaftInstance; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.base.ShaftInstance; import net.minecraft.core.Direction; import net.minecraft.util.Mth; import net.minecraft.world.level.LightLayer; -public abstract class AbstractPulleyInstance extends ShaftInstance implements DynamicInstance, TickingLightListener { +public abstract class AbstractPulleyInstance extends ShaftInstance implements DynamicInstance, TickingLightListener { final OrientedData coil; final SelectInstance magnet; @@ -34,8 +34,8 @@ public abstract class AbstractPulleyInstance extends ShaftInstance implements Dy private final GridAlignedBB volume = new GridAlignedBB(); private final LightVolume light; - public AbstractPulleyInstance(MaterialManager dispatcher, KineticTileEntity tile) { - super(dispatcher, tile); + public AbstractPulleyInstance(MaterialManager dispatcher, T blockEntity) { + super(dispatcher, blockEntity); rotatingAbout = Direction.get(Direction.AxisDirection.POSITIVE, axis); rotationAxis = Axis.of(rotatingAbout.step()); diff --git a/src/main/java/com/simibubi/create/content/contraptions/pulley/AbstractPulleyRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/pulley/AbstractPulleyRenderer.java new file mode 100644 index 000000000..7983fd0ee --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/pulley/AbstractPulleyRenderer.java @@ -0,0 +1,120 @@ +package com.simibubi.create.content.contraptions.pulley; + +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.core.PartialModel; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.simibubi.create.content.kinetics.base.IRotate; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.AngleHelper; + +import net.minecraft.client.renderer.LevelRenderer; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.state.BlockState; + +public abstract class AbstractPulleyRenderer extends KineticBlockEntityRenderer { + + private PartialModel halfRope; + private PartialModel halfMagnet; + + public AbstractPulleyRenderer(BlockEntityRendererProvider.Context context, PartialModel halfRope, + PartialModel halfMagnet) { + super(context); + this.halfRope = halfRope; + this.halfMagnet = halfMagnet; + } + + @Override + public boolean shouldRenderOffScreen(T p_188185_1_) { + return true; + } + + @Override + protected void renderSafe(T be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + + if (Backend.canUseInstancing(be.getLevel())) + return; + + super.renderSafe(be, partialTicks, ms, buffer, light, overlay); + float offset = getOffset(be, partialTicks); + boolean running = isRunning(be); + + Axis rotationAxis = ((IRotate) be.getBlockState() + .getBlock()).getRotationAxis(be.getBlockState()); + kineticRotationTransform(getRotatedCoil(be), be, rotationAxis, AngleHelper.rad(offset * 180), light) + .renderInto(ms, buffer.getBuffer(RenderType.solid())); + + Level world = be.getLevel(); + BlockState blockState = be.getBlockState(); + BlockPos pos = be.getBlockPos(); + + SuperByteBuffer halfMagnet = CachedBufferer.partial(this.halfMagnet, blockState); + SuperByteBuffer halfRope = CachedBufferer.partial(this.halfRope, blockState); + SuperByteBuffer magnet = renderMagnet(be); + SuperByteBuffer rope = renderRope(be); + + VertexConsumer vb = buffer.getBuffer(RenderType.solid()); + if (running || offset == 0) + renderAt(world, offset > .25f ? magnet : halfMagnet, offset, pos, ms, vb); + + float f = offset % 1; + if (offset > .75f && (f < .25f || f > .75f)) + renderAt(world, halfRope, f > .75f ? f - 1 : f, pos, ms, vb); + + if (!running) + return; + + for (int i = 0; i < offset - 1.25f; i++) + renderAt(world, rope, offset - i - 1, pos, ms, vb); + } + + public static void renderAt(LevelAccessor world, SuperByteBuffer partial, float offset, BlockPos pulleyPos, + PoseStack ms, VertexConsumer buffer) { + BlockPos actualPos = pulleyPos.below((int) offset); + int light = LevelRenderer.getLightColor(world, world.getBlockState(actualPos), actualPos); + partial.translate(0, -offset, 0) + .light(light) + .renderInto(ms, buffer); + } + + protected abstract Axis getShaftAxis(T be); + + protected abstract PartialModel getCoil(); + + protected abstract SuperByteBuffer renderRope(T be); + + protected abstract SuperByteBuffer renderMagnet(T be); + + protected abstract float getOffset(T be, float partialTicks); + + protected abstract boolean isRunning(T be); + + @Override + protected BlockState getRenderedBlockState(T be) { + return shaft(getShaftAxis(be)); + } + + protected SuperByteBuffer getRotatedCoil(T be) { + BlockState blockState = be.getBlockState(); + return CachedBufferer.partialFacing(getCoil(), blockState, + Direction.get(AxisDirection.POSITIVE, getShaftAxis(be))); + } + + @Override + public int getViewDistance() { + return 256; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/pulley/HosePulleyInstance.java b/src/main/java/com/simibubi/create/content/contraptions/pulley/HosePulleyInstance.java new file mode 100644 index 000000000..862954199 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/pulley/HosePulleyInstance.java @@ -0,0 +1,48 @@ +package com.simibubi.create.content.contraptions.pulley; + +import com.jozufozu.flywheel.api.Instancer; +import com.jozufozu.flywheel.api.MaterialManager; +import com.jozufozu.flywheel.core.Materials; +import com.jozufozu.flywheel.core.materials.oriented.OrientedData; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.fluids.hosePulley.HosePulleyBlockEntity; +import com.simibubi.create.foundation.utility.AnimationTickHolder; + +public class HosePulleyInstance extends AbstractPulleyInstance { + + public HosePulleyInstance(MaterialManager dispatcher, HosePulleyBlockEntity blockEntity) { + super(dispatcher, blockEntity); + } + + protected Instancer getRopeModel() { + return getOrientedMaterial().getModel(AllPartialModels.HOSE, blockState); + } + + protected Instancer getMagnetModel() { + return materialManager.defaultCutout() + .material(Materials.ORIENTED) + .getModel(AllPartialModels.HOSE_MAGNET, blockState); + } + + protected Instancer getHalfMagnetModel() { + return materialManager.defaultCutout() + .material(Materials.ORIENTED) + .getModel(AllPartialModels.HOSE_HALF_MAGNET, blockState); + } + + protected Instancer getCoilModel() { + return getOrientedMaterial().getModel(AllPartialModels.HOSE_COIL, blockState, rotatingAbout); + } + + protected Instancer getHalfRopeModel() { + return getOrientedMaterial().getModel(AllPartialModels.HOSE_HALF, blockState); + } + + protected float getOffset() { + return blockEntity.getInterpolatedOffset(AnimationTickHolder.getPartialTicks()); + } + + protected boolean isRunning() { + return true; + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyBlock.java b/src/main/java/com/simibubi/create/content/contraptions/pulley/PulleyBlock.java similarity index 90% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyBlock.java rename to src/main/java/com/simibubi/create/content/contraptions/pulley/PulleyBlock.java index 85e1bd250..79e327794 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/pulley/PulleyBlock.java @@ -1,10 +1,10 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.pulley; +package com.simibubi.create.content.contraptions.pulley; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.HorizontalAxisKineticBlock; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.content.kinetics.base.HorizontalAxisKineticBlock; +import com.simibubi.create.foundation.block.IBE; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -32,16 +32,16 @@ import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; -public class PulleyBlock extends HorizontalAxisKineticBlock implements ITE { +public class PulleyBlock extends HorizontalAxisKineticBlock implements IBE { public PulleyBlock(Properties properties) { super(properties); } private static void onRopeBroken(Level world, BlockPos pulleyPos) { - BlockEntity te = world.getBlockEntity(pulleyPos); - if (te instanceof PulleyTileEntity) { - PulleyTileEntity pulley = (PulleyTileEntity) te; + BlockEntity be = world.getBlockEntity(pulleyPos); + if (be instanceof PulleyBlockEntity) { + PulleyBlockEntity pulley = (PulleyBlockEntity) be; pulley.initialOffset = 0; pulley.onLengthBroken(); } @@ -67,7 +67,7 @@ public class PulleyBlock extends HorizontalAxisKineticBlock implements ITE te.assembleNextTick = true); + withBlockEntityDo(worldIn, pos, be -> be.assembleNextTick = true); return InteractionResult.SUCCESS; } return InteractionResult.PASS; @@ -79,13 +79,13 @@ public class PulleyBlock extends HorizontalAxisKineticBlock implements ITE getTileEntityClass() { - return PulleyTileEntity.class; + public Class getBlockEntityClass() { + return PulleyBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.ROPE_PULLEY.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.ROPE_PULLEY.get(); } private static class RopeBlockBase extends Block implements SimpleWaterloggedBlock { diff --git a/src/main/java/com/simibubi/create/content/contraptions/pulley/PulleyBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/pulley/PulleyBlockEntity.java new file mode 100644 index 000000000..c0a70d75f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/pulley/PulleyBlockEntity.java @@ -0,0 +1,382 @@ +package com.simibubi.create.content.contraptions.pulley; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.List; + +import javax.annotation.Nullable; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.AssemblyException; +import com.simibubi.create.content.contraptions.BlockMovementChecks; +import com.simibubi.create.content.contraptions.ContraptionCollider; +import com.simibubi.create.content.contraptions.ControlledContraptionEntity; +import com.simibubi.create.content.contraptions.piston.LinearActuatorBlockEntity; +import com.simibubi.create.content.redstone.thresholdSwitch.ThresholdSwitchObservable; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.CenteredSideValueBoxTransform; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; +import com.simibubi.create.foundation.utility.NBTHelper; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.nbt.Tag; +import net.minecraft.util.Mth; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.level.material.Fluids; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; + +public class PulleyBlockEntity extends LinearActuatorBlockEntity implements ThresholdSwitchObservable { + + protected int initialOffset; + private float prevAnimatedOffset; + + protected BlockPos mirrorParent; + protected List mirrorChildren; + public WeakReference sharedMirrorContraption; + + public PulleyBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + protected AABB createRenderBoundingBox() { + double expandY = -offset; + if (sharedMirrorContraption != null) { + AbstractContraptionEntity ace = sharedMirrorContraption.get(); + if (ace != null) + expandY = ace.getY() - worldPosition.getY(); + } + return super.createRenderBoundingBox().expandTowards(0, expandY, 0); + } + + @Override + public void addBehaviours(List behaviours) { + super.addBehaviours(behaviours); + registerAwardables(behaviours, AllAdvancements.PULLEY_MAXED); + } + + @Override + public void tick() { + float prevOffset = offset; + super.tick(); + + if (level.isClientSide() && mirrorParent != null) + if (sharedMirrorContraption == null || sharedMirrorContraption.get() == null + || !sharedMirrorContraption.get() + .isAlive()) { + sharedMirrorContraption = null; + if (level.getBlockEntity(mirrorParent)instanceof PulleyBlockEntity pte && pte.movedContraption != null) + sharedMirrorContraption = new WeakReference<>(pte.movedContraption); + } + + if (isVirtual()) + prevAnimatedOffset = offset; + invalidateRenderBoundingBox(); + + if (prevOffset < 200 && offset >= 200) + award(AllAdvancements.PULLEY_MAXED); + } + + @Override + protected boolean isPassive() { + return mirrorParent != null; + } + + @Nullable + public AbstractContraptionEntity getAttachedContraption() { + return mirrorParent != null && sharedMirrorContraption != null ? sharedMirrorContraption.get() + : movedContraption; + } + + @Override + protected void assemble() throws AssemblyException { + if (!(level.getBlockState(worldPosition) + .getBlock() instanceof PulleyBlock)) + return; + if (speed == 0 && mirrorParent == null) + return; + int maxLength = AllConfigs.server().kinetics.maxRopeLength.get(); + int i = 1; + while (i <= maxLength) { + BlockPos ropePos = worldPosition.below(i); + BlockState ropeState = level.getBlockState(ropePos); + if (!AllBlocks.ROPE.has(ropeState) && !AllBlocks.PULLEY_MAGNET.has(ropeState)) { + break; + } + ++i; + } + offset = i - 1; + if (offset >= getExtensionRange() && getSpeed() > 0) + return; + if (offset <= 0 && getSpeed() < 0) + return; + + // Collect Construct + if (!level.isClientSide && mirrorParent == null) { + needsContraption = false; + BlockPos anchor = worldPosition.below(Mth.floor(offset + 1)); + initialOffset = Mth.floor(offset); + PulleyContraption contraption = new PulleyContraption(initialOffset); + boolean canAssembleStructure = contraption.assemble(level, anchor); + + if (canAssembleStructure) { + Direction movementDirection = getSpeed() > 0 ? Direction.DOWN : Direction.UP; + if (ContraptionCollider.isCollidingWithWorld(level, contraption, anchor.relative(movementDirection), + movementDirection)) + canAssembleStructure = false; + } + + if (!canAssembleStructure && getSpeed() > 0) + return; + + removeRopes(); + + if (!contraption.getBlocks() + .isEmpty()) { + contraption.removeBlocksFromWorld(level, BlockPos.ZERO); + movedContraption = ControlledContraptionEntity.create(level, this, contraption); + movedContraption.setPos(anchor.getX(), anchor.getY(), anchor.getZ()); + level.addFreshEntity(movedContraption); + forceMove = true; + needsContraption = true; + + if (contraption.containsBlockBreakers()) + award(AllAdvancements.CONTRAPTION_ACTORS); + + for (BlockPos pos : contraption.createColliders(level, Direction.UP)) { + if (pos.getY() != 0) + continue; + pos = pos.offset(anchor); + if (level.getBlockEntity( + new BlockPos(pos.getX(), worldPosition.getY(), pos.getZ())) instanceof PulleyBlockEntity pbe) + pbe.startMirroringOther(worldPosition); + } + } + } + + if (mirrorParent != null) + removeRopes(); + + clientOffsetDiff = 0; + running = true; + sendData(); + } + + private void removeRopes() { + for (int i = ((int) offset); i > 0; i--) { + BlockPos offset = worldPosition.below(i); + BlockState oldState = level.getBlockState(offset); + level.setBlock(offset, oldState.getFluidState() + .createLegacyBlock(), 66); + } + } + + @Override + public void disassemble() { + if (!running && movedContraption == null && mirrorParent == null) + return; + offset = getGridOffset(offset); + if (movedContraption != null) + resetContraptionToOffset(); + + if (!level.isClientSide) { + if (shouldCreateRopes()) { + if (offset > 0) { + BlockPos magnetPos = worldPosition.below((int) offset); + FluidState ifluidstate = level.getFluidState(magnetPos); + level.destroyBlock(magnetPos, level.getBlockState(magnetPos) + .getCollisionShape(level, magnetPos) + .isEmpty()); + level.setBlock(magnetPos, AllBlocks.PULLEY_MAGNET.getDefaultState() + .setValue(BlockStateProperties.WATERLOGGED, + Boolean.valueOf(ifluidstate.getType() == Fluids.WATER)), + 66); + } + + boolean[] waterlog = new boolean[(int) offset]; + + for (int i = 1; i <= ((int) offset) - 1; i++) { + BlockPos ropePos = worldPosition.below(i); + FluidState ifluidstate = level.getFluidState(ropePos); + waterlog[i] = ifluidstate.getType() == Fluids.WATER; + level.destroyBlock(ropePos, level.getBlockState(ropePos) + .getCollisionShape(level, ropePos) + .isEmpty()); + } + for (int i = 1; i <= ((int) offset) - 1; i++) + level.setBlock(worldPosition.below(i), AllBlocks.ROPE.getDefaultState() + .setValue(BlockStateProperties.WATERLOGGED, waterlog[i]), 66); + } + + if (movedContraption != null && mirrorParent == null) + movedContraption.disassemble(); + notifyMirrorsOfDisassembly(); + } + + if (movedContraption != null) + movedContraption.discard(); + + movedContraption = null; + initialOffset = 0; + running = false; + sendData(); + } + + protected boolean shouldCreateRopes() { + return !remove; + } + + @Override + protected Vec3 toPosition(float offset) { + if (movedContraption.getContraption() instanceof PulleyContraption) { + PulleyContraption contraption = (PulleyContraption) movedContraption.getContraption(); + return Vec3.atLowerCornerOf(contraption.anchor) + .add(0, contraption.getInitialOffset() - offset, 0); + + } + return Vec3.ZERO; + } + + @Override + protected void visitNewPosition() { + super.visitNewPosition(); + if (level.isClientSide) + return; + if (movedContraption != null) + return; + if (getSpeed() <= 0) + return; + + BlockPos posBelow = worldPosition.below((int) (offset + getMovementSpeed()) + 1); + BlockState state = level.getBlockState(posBelow); + if (!BlockMovementChecks.isMovementNecessary(state, level, posBelow)) + return; + if (BlockMovementChecks.isBrittle(state)) + return; + + disassemble(); + assembleNextTick = true; + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + initialOffset = compound.getInt("InitialOffset"); + needsContraption = compound.getBoolean("NeedsContraption"); + super.read(compound, clientPacket); + + BlockPos prevMirrorParent = mirrorParent; + mirrorParent = null; + mirrorChildren = null; + + if (compound.contains("MirrorParent")) { + mirrorParent = NbtUtils.readBlockPos(compound.getCompound("MirrorParent")); + offset = 0; + if (prevMirrorParent == null || !prevMirrorParent.equals(mirrorParent)) + sharedMirrorContraption = null; + } + + if (compound.contains("MirrorChildren")) + mirrorChildren = NBTHelper.readCompoundList(compound.getList("MirrorChildren", Tag.TAG_COMPOUND), + NbtUtils::readBlockPos); + + if (mirrorParent == null) + sharedMirrorContraption = null; + } + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + compound.putInt("InitialOffset", initialOffset); + super.write(compound, clientPacket); + + if (mirrorParent != null) + compound.put("MirrorParent", NbtUtils.writeBlockPos(mirrorParent)); + if (mirrorChildren != null) + compound.put("MirrorChildren", NBTHelper.writeCompoundList(mirrorChildren, NbtUtils::writeBlockPos)); + } + + public void startMirroringOther(BlockPos parent) { + if (parent.equals(worldPosition)) + return; + if (!(level.getBlockEntity(parent) instanceof PulleyBlockEntity pbe)) + return; + if (pbe.getType() != getType()) + return; + if (pbe.mirrorChildren == null) + pbe.mirrorChildren = new ArrayList<>(); + pbe.mirrorChildren.add(worldPosition); + pbe.notifyUpdate(); + + mirrorParent = parent; + try { + assemble(); + } catch (AssemblyException e) { + } + notifyUpdate(); + } + + public void notifyMirrorsOfDisassembly() { + if (mirrorChildren == null) + return; + for (BlockPos blockPos : mirrorChildren) { + if (!(level.getBlockEntity(blockPos) instanceof PulleyBlockEntity pbe)) + continue; + pbe.offset = offset; + pbe.disassemble(); + pbe.mirrorParent = null; + pbe.notifyUpdate(); + } + mirrorChildren.clear(); + notifyUpdate(); + } + + @Override + protected int getExtensionRange() { + return Math.max(0, Math.min(AllConfigs.server().kinetics.maxRopeLength.get(), + (worldPosition.getY() - 1) - level.getMinBuildHeight())); + } + + @Override + protected int getInitialOffset() { + return initialOffset; + } + + @Override + protected Vec3 toMotionVector(float speed) { + return new Vec3(0, -speed, 0); + } + + @Override + protected ValueBoxTransform getMovementModeSlot() { + return new CenteredSideValueBoxTransform((state, d) -> d == Direction.UP); + } + + @Override + public float getInterpolatedOffset(float partialTicks) { + if (isVirtual()) + return Mth.lerp(partialTicks, prevAnimatedOffset, offset); + boolean moving = running && (movedContraption == null || !movedContraption.isStalled()); + return super.getInterpolatedOffset(moving ? partialTicks : 0.5f); + } + + public void animateOffset(float forcedOffset) { + offset = forcedOffset; + } + + @Override + public float getPercent() { + int distance = worldPosition.getY() - level.getMinBuildHeight(); + if (distance <= 0) + return 100; + return 100 * getInterpolatedOffset(.5f) / distance; + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/pulley/PulleyContraption.java b/src/main/java/com/simibubi/create/content/contraptions/pulley/PulleyContraption.java new file mode 100644 index 000000000..cc4eb19a4 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/pulley/PulleyContraption.java @@ -0,0 +1,69 @@ +package com.simibubi.create.content.contraptions.pulley; + +import com.simibubi.create.content.contraptions.AssemblyException; +import com.simibubi.create.content.contraptions.ContraptionType; +import com.simibubi.create.content.contraptions.TranslatingContraption; +import com.simibubi.create.content.contraptions.render.ContraptionLighter; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.Level; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public class PulleyContraption extends TranslatingContraption { + + int initialOffset; + + @Override + public ContraptionType getType() { + return ContraptionType.PULLEY; + } + + public PulleyContraption() {} + + public PulleyContraption(int initialOffset) { + this.initialOffset = initialOffset; + } + + @Override + public boolean assemble(Level world, BlockPos pos) throws AssemblyException { + if (!searchMovedStructure(world, pos, null)) + return false; + startMoving(world); + return true; + } + + @Override + protected boolean isAnchoringBlockAt(BlockPos pos) { + if (pos.getX() != anchor.getX() || pos.getZ() != anchor.getZ()) + return false; + int y = pos.getY(); + if (y <= anchor.getY() || y > anchor.getY() + initialOffset + 1) + return false; + return true; + } + + @Override + public CompoundTag writeNBT(boolean spawnPacket) { + CompoundTag tag = super.writeNBT(spawnPacket); + tag.putInt("InitialOffset", initialOffset); + return tag; + } + + @Override + public void readNBT(Level world, CompoundTag nbt, boolean spawnData) { + initialOffset = nbt.getInt("InitialOffset"); + super.readNBT(world, nbt, spawnData); + } + + @Override + @OnlyIn(Dist.CLIENT) + public ContraptionLighter makeLighter() { + return new PulleyLighter(this); + } + + public int getInitialOffset() { + return initialOffset; + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyLighter.java b/src/main/java/com/simibubi/create/content/contraptions/pulley/PulleyLighter.java similarity index 81% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyLighter.java rename to src/main/java/com/simibubi/create/content/contraptions/pulley/PulleyLighter.java index 01c9d289d..0b723c453 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyLighter.java +++ b/src/main/java/com/simibubi/create/content/contraptions/pulley/PulleyLighter.java @@ -1,8 +1,8 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.pulley; +package com.simibubi.create.content.contraptions.pulley; import com.jozufozu.flywheel.util.box.GridAlignedBB; import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionLighter; +import com.simibubi.create.content.contraptions.render.ContraptionLighter; import net.minecraft.core.BlockPos; import net.minecraft.world.level.Level; diff --git a/src/main/java/com/simibubi/create/content/contraptions/pulley/PulleyRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/pulley/PulleyRenderer.java new file mode 100644 index 000000000..0be9e3c42 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/pulley/PulleyRenderer.java @@ -0,0 +1,73 @@ +package com.simibubi.create.content.contraptions.pulley; + +import com.jozufozu.flywheel.core.PartialModel; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; + +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.core.Direction.Axis; +import net.minecraft.util.Mth; + +public class PulleyRenderer extends AbstractPulleyRenderer { + + public PulleyRenderer(BlockEntityRendererProvider.Context context) { + super(context, AllPartialModels.ROPE_HALF, AllPartialModels.ROPE_HALF_MAGNET); + } + + @Override + protected Axis getShaftAxis(PulleyBlockEntity be) { + return be.getBlockState() + .getValue(PulleyBlock.HORIZONTAL_AXIS); + } + + @Override + protected PartialModel getCoil() { + return AllPartialModels.ROPE_COIL; + } + + @Override + protected SuperByteBuffer renderRope(PulleyBlockEntity be) { + return CachedBufferer.block(AllBlocks.ROPE.getDefaultState()); + } + + @Override + protected SuperByteBuffer renderMagnet(PulleyBlockEntity be) { + return CachedBufferer.block(AllBlocks.PULLEY_MAGNET.getDefaultState()); + } + + @Override + protected float getOffset(PulleyBlockEntity be, float partialTicks) { + return getBlockEntityOffset(partialTicks, be); + } + + @Override + protected boolean isRunning(PulleyBlockEntity be) { + return isPulleyRunning(be); + } + + public static boolean isPulleyRunning(PulleyBlockEntity be) { + return be.running || be.mirrorParent != null || be.isVirtual(); + } + + public static float getBlockEntityOffset(float partialTicks, PulleyBlockEntity blockEntity) { + float offset = blockEntity.getInterpolatedOffset(partialTicks); + + AbstractContraptionEntity attachedContraption = blockEntity.getAttachedContraption(); + if (attachedContraption != null) { + PulleyContraption c = (PulleyContraption) attachedContraption.getContraption(); + double entityPos = Mth.lerp(partialTicks, attachedContraption.yOld, attachedContraption.getY()); + offset = (float) -(entityPos - c.anchor.getY() - c.getInitialOffset()); + } + + return offset; + } + + @Override + public int getViewDistance() { + return 128; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/pulley/RopePulleyInstance.java b/src/main/java/com/simibubi/create/content/contraptions/pulley/RopePulleyInstance.java new file mode 100644 index 000000000..70ce307ff --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/pulley/RopePulleyInstance.java @@ -0,0 +1,44 @@ +package com.simibubi.create.content.contraptions.pulley; + + +import com.jozufozu.flywheel.api.Instancer; +import com.jozufozu.flywheel.api.MaterialManager; +import com.jozufozu.flywheel.core.materials.oriented.OrientedData; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.foundation.utility.AnimationTickHolder; + +public class RopePulleyInstance extends AbstractPulleyInstance { + public RopePulleyInstance(MaterialManager materialManager, PulleyBlockEntity blockEntity) { + super(materialManager, blockEntity); + } + + protected Instancer getRopeModel() { + return getOrientedMaterial().getModel(AllBlocks.ROPE.getDefaultState()); + } + + protected Instancer getMagnetModel() { + return getOrientedMaterial().getModel(AllBlocks.PULLEY_MAGNET.getDefaultState()); + } + + protected Instancer getHalfMagnetModel() { + return getOrientedMaterial().getModel(AllPartialModels.ROPE_HALF_MAGNET, blockState); + } + + protected Instancer getCoilModel() { + return getOrientedMaterial().getModel(AllPartialModels.ROPE_COIL, blockState, rotatingAbout); + } + + protected Instancer getHalfRopeModel() { + return getOrientedMaterial().getModel(AllPartialModels.ROPE_HALF, blockState); + } + + protected float getOffset() { + float partialTicks = AnimationTickHolder.getPartialTicks(); + return PulleyRenderer.getBlockEntityOffset(partialTicks, blockEntity); + } + + protected boolean isRunning() { + return PulleyRenderer.isPulleyRunning(blockEntity); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/GantryShaftTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/GantryShaftTileEntity.java deleted file mode 100644 index 62a0f4200..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/GantryShaftTileEntity.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.advanced; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.gantry.GantryCarriageBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.gantry.GantryCarriageTileEntity; -import com.simibubi.create.foundation.utility.Iterate; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.util.Mth; -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 class GantryShaftTileEntity extends KineticTileEntity { - - public GantryShaftTileEntity(BlockEntityType typeIn, BlockPos pos, BlockState state) { - super(typeIn, pos, state); - } - - public void checkAttachedCarriageBlocks() { - if (!canAssembleOn()) - return; - for (Direction d : Iterate.directions) { - if (d.getAxis() == getBlockState().getValue(GantryShaftBlock.FACING) - .getAxis()) - continue; - BlockPos offset = worldPosition.relative(d); - BlockState pinionState = level.getBlockState(offset); - if (!AllBlocks.GANTRY_CARRIAGE.has(pinionState)) - continue; - if (pinionState.getValue(GantryCarriageBlock.FACING) != d) - continue; - BlockEntity tileEntity = level.getBlockEntity(offset); - if (tileEntity instanceof GantryCarriageTileEntity) - ((GantryCarriageTileEntity) tileEntity).queueAssembly(); - } - } - - @Override - public void onSpeedChanged(float previousSpeed) { - super.onSpeedChanged(previousSpeed); - checkAttachedCarriageBlocks(); - } - - @Override - public float propagateRotationTo(KineticTileEntity target, BlockState stateFrom, BlockState stateTo, BlockPos diff, - boolean connectedViaAxes, boolean connectedViaCogs) { - float defaultModifier = - super.propagateRotationTo(target, stateFrom, stateTo, diff, connectedViaAxes, connectedViaCogs); - - if (connectedViaAxes) - return defaultModifier; - if (!stateFrom.getValue(GantryShaftBlock.POWERED)) - return defaultModifier; - if (!AllBlocks.GANTRY_CARRIAGE.has(stateTo)) - return defaultModifier; - - Direction direction = Direction.getNearest(diff.getX(), diff.getY(), diff.getZ()); - if (stateTo.getValue(GantryCarriageBlock.FACING) != direction) - return defaultModifier; - return GantryCarriageTileEntity.getGantryPinionModifier(stateFrom.getValue(GantryShaftBlock.FACING), - stateTo.getValue(GantryCarriageBlock.FACING)); - } - - @Override - public boolean isCustomConnection(KineticTileEntity other, BlockState state, BlockState otherState) { - if (!AllBlocks.GANTRY_CARRIAGE.has(otherState)) - return false; - final BlockPos diff = other.getBlockPos() - .subtract(worldPosition); - Direction direction = Direction.getNearest(diff.getX(), diff.getY(), diff.getZ()); - return otherState.getValue(GantryCarriageBlock.FACING) == direction; - } - - public boolean canAssembleOn() { - BlockState blockState = getBlockState(); - if (!AllBlocks.GANTRY_SHAFT.has(blockState)) - return false; - if (blockState.getValue(GantryShaftBlock.POWERED)) - return false; - float speed = getPinionMovementSpeed(); - - switch (blockState.getValue(GantryShaftBlock.PART)) { - case END: - return speed < 0; - case MIDDLE: - return speed != 0; - case START: - return speed > 0; - case SINGLE: - default: - return false; - } - } - - public float getPinionMovementSpeed() { - BlockState blockState = getBlockState(); - if (!AllBlocks.GANTRY_SHAFT.has(blockState)) - return 0; - return Mth.clamp(convertToLinear(-getSpeed()), -.49f, .49f); - } - - @Override - protected boolean isNoisy() { - return false; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/SpeedControllerRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/SpeedControllerRenderer.java deleted file mode 100644 index a7043b05b..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/SpeedControllerRenderer.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.advanced; - -import com.jozufozu.flywheel.backend.Backend; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.tileEntity.renderer.SmartTileEntityRenderer; - -import net.minecraft.client.renderer.LevelRenderer; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; - -public class SpeedControllerRenderer extends SmartTileEntityRenderer { - - public SpeedControllerRenderer(BlockEntityRendererProvider.Context context) { - super(context); - } - - @Override - protected void renderSafe(SpeedControllerTileEntity tileEntityIn, float partialTicks, PoseStack ms, - MultiBufferSource buffer, int light, int overlay) { - super.renderSafe(tileEntityIn, partialTicks, ms, buffer, light, overlay); - - VertexConsumer builder = buffer.getBuffer(RenderType.solid()); - if (!Backend.canUseInstancing(tileEntityIn.getLevel())) { - KineticTileEntityRenderer.renderRotatingBuffer(tileEntityIn, getRotatedModel(tileEntityIn), ms, builder, light); - } - - if (!tileEntityIn.hasBracket) - return; - - BlockPos pos = tileEntityIn.getBlockPos(); - Level world = tileEntityIn.getLevel(); - BlockState blockState = tileEntityIn.getBlockState(); - boolean alongX = blockState.getValue(SpeedControllerBlock.HORIZONTAL_AXIS) == Axis.X; - - SuperByteBuffer bracket = CachedBufferer.partial(AllBlockPartials.SPEED_CONTROLLER_BRACKET, blockState); - bracket.translate(0, 1, 0); - bracket.rotateCentered(Direction.UP, - (float) (alongX ? Math.PI : Math.PI / 2)); - bracket.light(LevelRenderer.getLightColor(world, pos.above())); - bracket.renderInto(ms, builder); - } - - private SuperByteBuffer getRotatedModel(SpeedControllerTileEntity te) { - return CachedBufferer.block(KineticTileEntityRenderer.KINETIC_TILE, - KineticTileEntityRenderer.shaft(KineticTileEntityRenderer.getRotationAxisOf(te))); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/SpeedControllerTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/SpeedControllerTileEntity.java deleted file mode 100644 index 9238ed52e..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/SpeedControllerTileEntity.java +++ /dev/null @@ -1,152 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.advanced; - -import java.util.List; - -import com.simibubi.create.content.contraptions.RotationPropagator; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.components.motor.CreativeMotorTileEntity; -import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock; -import com.simibubi.create.content.contraptions.relays.elementary.ICogWheel; -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform; -import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueBehaviour; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; - -public class SpeedControllerTileEntity extends KineticTileEntity { - - public static final int DEFAULT_SPEED = 16; - protected ScrollValueBehaviour targetSpeed; - - boolean hasBracket; - - public SpeedControllerTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - hasBracket = false; - } - - @Override - public void lazyTick() { - super.lazyTick(); - updateBracket(); - } - - @Override - public void addBehaviours(List behaviours) { - super.addBehaviours(behaviours); - Integer max = AllConfigs.SERVER.kinetics.maxRotationSpeed.get(); - - targetSpeed = - new ScrollValueBehaviour(Lang.translateDirect("generic.speed"), this, new ControllerValueBoxTransform()); - targetSpeed.between(-max, max); - targetSpeed.value = DEFAULT_SPEED; - targetSpeed.moveText(new Vec3(9, 0, 10)); - targetSpeed.withUnit(i -> Lang.translateDirect("generic.unit.rpm")); - targetSpeed.withCallback(i -> this.updateTargetRotation()); - targetSpeed.withStepFunction(CreativeMotorTileEntity::step); - behaviours.add(targetSpeed); - - registerAwardables(behaviours, AllAdvancements.SPEED_CONTROLLER); - } - - private void updateTargetRotation() { - if (hasNetwork()) - getOrCreateNetwork().remove(this); - RotationPropagator.handleRemoved(level, worldPosition, this); - removeSource(); - attachKinetics(); - - if (isCogwheelPresent() && getSpeed() != 0) - award(AllAdvancements.SPEED_CONTROLLER); - } - - public static float getConveyedSpeed(KineticTileEntity cogWheel, KineticTileEntity speedControllerIn, - boolean targetingController) { - if (!(speedControllerIn instanceof SpeedControllerTileEntity)) - return 0; - - float speed = speedControllerIn.getTheoreticalSpeed(); - float wheelSpeed = cogWheel.getTheoreticalSpeed(); - float desiredOutputSpeed = getDesiredOutputSpeed(cogWheel, speedControllerIn, targetingController); - - float compareSpeed = targetingController ? speed : wheelSpeed; - if (desiredOutputSpeed >= 0 && compareSpeed >= 0) - return Math.max(desiredOutputSpeed, compareSpeed); - if (desiredOutputSpeed < 0 && compareSpeed < 0) - return Math.min(desiredOutputSpeed, compareSpeed); - - return desiredOutputSpeed; - } - - public static float getDesiredOutputSpeed(KineticTileEntity cogWheel, KineticTileEntity speedControllerIn, - boolean targetingController) { - SpeedControllerTileEntity speedController = (SpeedControllerTileEntity) speedControllerIn; - float targetSpeed = speedController.targetSpeed.getValue(); - float speed = speedControllerIn.getTheoreticalSpeed(); - float wheelSpeed = cogWheel.getTheoreticalSpeed(); - - if (targetSpeed == 0) - return 0; - if (targetingController && wheelSpeed == 0) - return 0; - if (!speedController.hasSource()) { - if (targetingController) - return targetSpeed; - return 0; - } - - boolean wheelPowersController = speedController.source.equals(cogWheel.getBlockPos()); - - if (wheelPowersController) { - if (targetingController) - return targetSpeed; - return wheelSpeed; - } - - if (targetingController) - return speed; - return targetSpeed; - } - - public void updateBracket() { - if (level != null && level.isClientSide) - hasBracket = isCogwheelPresent(); - } - - private boolean isCogwheelPresent() { - BlockState stateAbove = level.getBlockState(worldPosition.above()); - return ICogWheel.isDedicatedCogWheel(stateAbove.getBlock()) && ICogWheel.isLargeCog(stateAbove) - && stateAbove.getValue(CogWheelBlock.AXIS).isHorizontal(); - } - - private class ControllerValueBoxTransform extends ValueBoxTransform.Sided { - - @Override - protected Vec3 getSouthLocation() { - return VecHelper.voxelSpace(8, 11f, 16); - } - - @Override - protected boolean isSideActive(BlockState state, Direction direction) { - if (direction.getAxis() - .isVertical()) - return false; - return state.getValue(SpeedControllerBlock.HORIZONTAL_AXIS) != direction.getAxis(); - } - - @Override - protected float getScale() { - return 0.275f; - } - - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/ConfigureSequencedGearshiftPacket.java b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/ConfigureSequencedGearshiftPacket.java deleted file mode 100644 index 75fb4ca84..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/ConfigureSequencedGearshiftPacket.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.advanced.sequencer; - -import com.simibubi.create.foundation.networking.TileEntityConfigurationPacket; - -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.Tag; -import net.minecraft.network.FriendlyByteBuf; - -public class ConfigureSequencedGearshiftPacket extends TileEntityConfigurationPacket { - - private ListTag instructions; - - public ConfigureSequencedGearshiftPacket(BlockPos pos, ListTag instructions) { - super(pos); - this.instructions = instructions; - } - - public ConfigureSequencedGearshiftPacket(FriendlyByteBuf buffer) { - super(buffer); - } - - @Override - protected void readSettings(FriendlyByteBuf buffer) { - instructions = buffer.readNbt().getList("data", Tag.TAG_COMPOUND); - } - - @Override - protected void writeSettings(FriendlyByteBuf buffer) { - CompoundTag tag = new CompoundTag(); - tag.put("data", instructions); - buffer.writeNbt(tag); - } - - @Override - protected void applySettings(SequencedGearshiftTileEntity te) { - te.run(-1); - te.instructions = Instruction.deserializeAll(instructions); - te.sendData(); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/InstructionSpeedModifiers.java b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/InstructionSpeedModifiers.java deleted file mode 100644 index 93713d075..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/InstructionSpeedModifiers.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.advanced.sequencer; - -import java.util.ArrayList; -import java.util.List; - -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; - -import net.minecraft.network.chat.Component; - -public enum InstructionSpeedModifiers { - - FORWARD_FAST(2, ">>"), FORWARD(1, "->"), BACK(-1, "<-"), BACK_FAST(-2, "<<"), - - ; - - String translationKey; - int value; - Component label; - - private InstructionSpeedModifiers(int modifier, Component label) { - this.label = label; - translationKey = "gui.sequenced_gearshift.speed." + Lang.asId(name()); - value = modifier; - } - private InstructionSpeedModifiers(int modifier, String label) { - this.label = Components.literal(label); - translationKey = "gui.sequenced_gearshift.speed." + Lang.asId(name()); - value = modifier; - } - - static List getOptions() { - List options = new ArrayList<>(); - for (InstructionSpeedModifiers entry : values()) - options.add(Lang.translateDirect(entry.translationKey)); - return options; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/OnIsPoweredResult.java b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/OnIsPoweredResult.java deleted file mode 100644 index e942da652..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/OnIsPoweredResult.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.advanced.sequencer; - -public enum OnIsPoweredResult { - NOTHING, - CONTINUE -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftScreen.java b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftScreen.java deleted file mode 100644 index 7f2c86ab4..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftScreen.java +++ /dev/null @@ -1,203 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.advanced.sequencer; - -import java.util.Vector; - -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlocks; -import com.simibubi.create.foundation.gui.AbstractSimiScreen; -import com.simibubi.create.foundation.gui.AllGuiTextures; -import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.gui.element.GuiGameElement; -import com.simibubi.create.foundation.gui.widget.IconButton; -import com.simibubi.create.foundation.gui.widget.ScrollInput; -import com.simibubi.create.foundation.gui.widget.SelectionScrollInput; -import com.simibubi.create.foundation.networking.AllPackets; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; - -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.ListTag; -import net.minecraft.network.chat.Component; -import net.minecraft.world.item.ItemStack; - -public class SequencedGearshiftScreen extends AbstractSimiScreen { - - private final ItemStack renderedItem = AllBlocks.SEQUENCED_GEARSHIFT.asStack(); - private final AllGuiTextures background = AllGuiTextures.SEQUENCER; - private IconButton confirmButton; - - private ListTag compareTag; - private Vector instructions; - private BlockPos pos; - - private Vector> inputs; - - public SequencedGearshiftScreen(SequencedGearshiftTileEntity te) { - super(Lang.translateDirect("gui.sequenced_gearshift.title")); - this.instructions = te.instructions; - this.pos = te.getBlockPos(); - compareTag = Instruction.serializeAll(instructions); - } - - @Override - protected void init() { - setWindowSize(background.width, background.height); - setWindowOffset(-20, 0); - super.init(); - - int x = guiLeft; - int y = guiTop; - - inputs = new Vector<>(5); - for (int row = 0; row < inputs.capacity(); row++) - inputs.add(new Vector<>(3)); - - for (int row = 0; row < instructions.size(); row++) - initInputsOfRow(row, x, y); - - confirmButton = - new IconButton(x + background.width - 33, y + background.height - 24, AllIcons.I_CONFIRM); - confirmButton.withCallback(() -> { - onClose(); - }); - addRenderableWidget(confirmButton); - } - - public void initInputsOfRow(int row, int backgroundX, int backgroundY) { - int x = backgroundX + 30; - int y = backgroundY + 18; - int rowHeight = 22; - - Vector rowInputs = inputs.get(row); - removeWidgets(rowInputs); - rowInputs.clear(); - int index = row; - Instruction instruction = instructions.get(row); - - ScrollInput type = - new SelectionScrollInput(x, y + rowHeight * row, 50, 18).forOptions(SequencerInstructions.getOptions()) - .calling(state -> instructionUpdated(index, state)) - .setState(instruction.instruction.ordinal()) - .titled(Lang.translateDirect("gui.sequenced_gearshift.instruction")); - ScrollInput value = - new ScrollInput(x + 58, y + rowHeight * row, 28, 18).calling(state -> instruction.value = state); - ScrollInput direction = new SelectionScrollInput(x + 88, y + rowHeight * row, 28, 18) - .forOptions(InstructionSpeedModifiers.getOptions()) - .calling(state -> instruction.speedModifier = InstructionSpeedModifiers.values()[state]) - .titled(Lang.translateDirect("gui.sequenced_gearshift.speed")); - - rowInputs.add(type); - rowInputs.add(value); - rowInputs.add(direction); - - addRenderableWidgets(rowInputs); - updateParamsOfRow(row); - } - - public void updateParamsOfRow(int row) { - Instruction instruction = instructions.get(row); - Vector rowInputs = inputs.get(row); - SequencerInstructions def = instruction.instruction; - boolean hasValue = def.hasValueParameter; - boolean hasModifier = def.hasSpeedParameter; - - ScrollInput value = rowInputs.get(1); - value.active = value.visible = hasValue; - if (hasValue) - value.withRange(1, def.maxValue + 1) - .titled(Lang.translateDirect(def.parameterKey)) - .withShiftStep(def.shiftStep) - .setState(instruction.value) - .onChanged(); - if (def == SequencerInstructions.DELAY) { - value.withStepFunction(context -> { - int v = context.currentValue; - if (!context.forward) - v--; - if (v < 20) - return context.shift ? 20 : 1; - return context.shift ? 100 : 20; - }); - } else - value.withStepFunction(value.standardStep()); - - ScrollInput modifier = rowInputs.get(2); - modifier.active = modifier.visible = hasModifier; - if (hasModifier) - modifier.setState(instruction.speedModifier.ordinal()); - } - - @Override - protected void renderWindow(PoseStack ms, int mouseX, int mouseY, float partialTicks) { - int x = guiLeft; - int y = guiTop; - - background.render(ms, x, y, this); - - for (int row = 0; row < instructions.capacity(); row++) { - AllGuiTextures toDraw = AllGuiTextures.SEQUENCER_EMPTY; - int yOffset = toDraw.height * row; - if (row >= instructions.size()) { - toDraw.render(ms, x, y + 14 + yOffset, this); - continue; - } - - Instruction instruction = instructions.get(row); - SequencerInstructions def = instruction.instruction; - def.background.render(ms, x, y + 14 + yOffset, this); - - label(ms, 36, yOffset - 3, Lang.translateDirect(def.translationKey)); - if (def.hasValueParameter) { - String text = def.formatValue(instruction.value); - int stringWidth = font.width(text); - label(ms, 90 + (12 - stringWidth / 2), yOffset - 3, Components.literal(text)); - } - if (def.hasSpeedParameter) - label(ms, 127, yOffset - 3, instruction.speedModifier.label); - } - - drawCenteredString(ms, font, title, x + (background.width - 8) / 2, y + 3, 0xFFFFFF); - - GuiGameElement.of(renderedItem) - .at(x + background.width + 6, y + background.height - 56, -200) - .scale(5) - .render(ms); - } - - private void label(PoseStack ms, int x, int y, Component text) { - font.drawShadow(ms, text, guiLeft + x, guiTop + 26 + y, 0xFFFFEE); - } - - public void sendPacket() { - ListTag serialized = Instruction.serializeAll(instructions); - if (serialized.equals(compareTag)) - return; - AllPackets.channel.sendToServer(new ConfigureSequencedGearshiftPacket(pos, serialized)); - } - - @Override - public void removed() { - sendPacket(); - } - - private void instructionUpdated(int index, int state) { - SequencerInstructions newValue = SequencerInstructions.values()[state]; - instructions.get(index).instruction = newValue; - instructions.get(index).value = newValue.defaultValue; - updateParamsOfRow(index); - if (newValue == SequencerInstructions.END) { - for (int i = instructions.size() - 1; i > index; i--) { - instructions.remove(i); - Vector rowInputs = inputs.get(i); - removeWidgets(rowInputs); - rowInputs.clear(); - } - } else { - if (index + 1 < instructions.capacity() && index + 1 == instructions.size()) { - instructions.add(new Instruction(SequencerInstructions.END)); - initInputsOfRow(index + 1, guiLeft, guiTop); - } - } - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftTileEntity.java deleted file mode 100644 index 9c595af72..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftTileEntity.java +++ /dev/null @@ -1,174 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.advanced.sequencer; - -import java.util.Vector; - -import com.simibubi.create.content.contraptions.relays.encased.SplitShaftTileEntity; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.Tag; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; - -public class SequencedGearshiftTileEntity extends SplitShaftTileEntity { - - Vector instructions; - int currentInstruction; - int currentInstructionDuration; - float currentInstructionProgress; - int timer; - boolean poweredPreviously; - - public SequencedGearshiftTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - instructions = Instruction.createDefault(); - currentInstruction = -1; - currentInstructionDuration = -1; - currentInstructionProgress = 0; - timer = 0; - poweredPreviously = false; - } - - @Override - public void tick() { - super.tick(); - - if (isIdle()) - return; - if (level.isClientSide) - return; - if (currentInstructionDuration < 0) - return; - if (timer < currentInstructionDuration) { - timer++; - currentInstructionProgress += getInstruction(currentInstruction).getTickProgress(speed); - return; - } - run(currentInstruction + 1); - } - - @Override - public void onSpeedChanged(float previousSpeed) { - super.onSpeedChanged(previousSpeed); - if (isIdle()) - return; - float currentSpeed = Math.abs(speed); - if (Math.abs(previousSpeed) == currentSpeed) - return; - Instruction instruction = getInstruction(currentInstruction); - if (instruction == null) - return; - if (getSpeed() == 0) - run(-1); - - // Update instruction time with regards to new speed - currentInstructionDuration = instruction.getDuration(currentInstructionProgress, getTheoreticalSpeed()); - timer = 0; - } - - public boolean isIdle() { - return currentInstruction == -1; - } - - public void onRedstoneUpdate(boolean isPowered, boolean isRunning) { - if (!poweredPreviously && isPowered) - risingFlank(); - poweredPreviously = isPowered; - if (!isIdle()) - return; - if (isPowered == isRunning) - return; - if (!level.hasNeighborSignal(worldPosition)) { - level.setBlock(worldPosition, getBlockState().setValue(SequencedGearshiftBlock.STATE, 0), 3); - return; - } - if (getSpeed() == 0) - return; - run(0); - } - - public void risingFlank() { - Instruction instruction = getInstruction(currentInstruction); - if (instruction == null) - return; - if (poweredPreviously) - return; - poweredPreviously = true; - - switch (instruction.onRedstonePulse()) { - case CONTINUE: - run(currentInstruction + 1); - break; - default: - break; - } - } - - protected void run(int instructionIndex) { - Instruction instruction = getInstruction(instructionIndex); - if (instruction == null || instruction.instruction == SequencerInstructions.END) { - if (getModifier() != 0) - detachKinetics(); - currentInstruction = -1; - currentInstructionDuration = -1; - currentInstructionProgress = 0; - timer = 0; - if (!level.hasNeighborSignal(worldPosition)) - level.setBlock(worldPosition, getBlockState().setValue(SequencedGearshiftBlock.STATE, 0), 3); - else - sendData(); - return; - } - - detachKinetics(); - currentInstructionDuration = instruction.getDuration(0, getTheoreticalSpeed()); - currentInstruction = instructionIndex; - currentInstructionProgress = 0; - timer = 0; - level.setBlock(worldPosition, getBlockState().setValue(SequencedGearshiftBlock.STATE, instructionIndex + 1), 3); - } - - public Instruction getInstruction(int instructionIndex) { - return instructionIndex >= 0 && instructionIndex < instructions.size() ? instructions.get(instructionIndex) - : null; - } - - @Override - public void write(CompoundTag compound, boolean clientPacket) { - compound.putInt("InstructionIndex", currentInstruction); - compound.putInt("InstructionDuration", currentInstructionDuration); - compound.putFloat("InstructionProgress", currentInstructionProgress); - compound.putInt("Timer", timer); - compound.putBoolean("PrevPowered", poweredPreviously); - compound.put("Instructions", Instruction.serializeAll(instructions)); - super.write(compound, clientPacket); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - currentInstruction = compound.getInt("InstructionIndex"); - currentInstructionDuration = compound.getInt("InstructionDuration"); - currentInstructionProgress = compound.getFloat("InstructionProgress"); - poweredPreviously = compound.getBoolean("PrevPowered"); - timer = compound.getInt("Timer"); - instructions = Instruction.deserializeAll(compound.getList("Instructions", Tag.TAG_COMPOUND)); - super.read(compound, clientPacket); - } - - @Override - public float getRotationSpeedModifier(Direction face) { - if (isVirtual()) - return 1; - return (!hasSource() || face == getSourceFacing()) ? 1 : getModifier(); - } - - public int getModifier() { - if (currentInstruction >= instructions.size()) - return 0; - return isIdle() ? 0 - : instructions.get(currentInstruction) - .getSpeedModifier(); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltHelper.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltHelper.java deleted file mode 100644 index 4f0086b07..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltHelper.java +++ /dev/null @@ -1,101 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.belt; - -import com.simibubi.create.AllTags.AllItemTags; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Vec3i; -import net.minecraft.util.Mth; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.fluids.capability.CapabilityFluidHandler; - -public class BeltHelper { - - public static boolean isItemUpright(ItemStack stack) { - return stack.getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY) - .isPresent() || AllItemTags.UPRIGHT_ON_BELT.matches(stack); - } - - public static BeltTileEntity getSegmentTE(LevelAccessor world, BlockPos pos) { - if (world instanceof Level l && !l.isLoaded(pos)) - return null; - BlockEntity tileEntity = world.getBlockEntity(pos); - if (!(tileEntity instanceof BeltTileEntity)) - return null; - return (BeltTileEntity) tileEntity; - } - - public static BeltTileEntity getControllerTE(LevelAccessor world, BlockPos pos) { - BeltTileEntity segment = getSegmentTE(world, pos); - if (segment == null) - return null; - BlockPos controllerPos = segment.controller; - if (controllerPos == null) - return null; - return getSegmentTE(world, controllerPos); - } - - public static BeltTileEntity getBeltForOffset(BeltTileEntity controller, float offset) { - return getBeltAtSegment(controller, (int) Math.floor(offset)); - } - - public static BeltTileEntity getBeltAtSegment(BeltTileEntity controller, int segment) { - BlockPos pos = getPositionForOffset(controller, segment); - BlockEntity te = controller.getLevel() - .getBlockEntity(pos); - if (te == null || !(te instanceof BeltTileEntity)) - return null; - return (BeltTileEntity) te; - } - - public static BlockPos getPositionForOffset(BeltTileEntity controller, int offset) { - BlockPos pos = controller.getBlockPos(); - Vec3i vec = controller.getBeltFacing() - .getNormal(); - BeltSlope slope = controller.getBlockState() - .getValue(BeltBlock.SLOPE); - int verticality = slope == BeltSlope.DOWNWARD ? -1 : slope == BeltSlope.UPWARD ? 1 : 0; - - return pos.offset(offset * vec.getX(), Mth.clamp(offset, 0, controller.beltLength - 1) * verticality, - offset * vec.getZ()); - } - - public static Vec3 getVectorForOffset(BeltTileEntity controller, float offset) { - BeltSlope slope = controller.getBlockState() - .getValue(BeltBlock.SLOPE); - int verticality = slope == BeltSlope.DOWNWARD ? -1 : slope == BeltSlope.UPWARD ? 1 : 0; - float verticalMovement = verticality; - if (offset < .5) - verticalMovement = 0; - verticalMovement = verticalMovement * (Math.min(offset, controller.beltLength - .5f) - .5f); - Vec3 vec = VecHelper.getCenterOf(controller.getBlockPos()); - Vec3 horizontalMovement = Vec3.atLowerCornerOf(controller.getBeltFacing() - .getNormal()) - .scale(offset - .5f); - - if (slope == BeltSlope.VERTICAL) - horizontalMovement = Vec3.ZERO; - - vec = vec.add(horizontalMovement) - .add(0, verticalMovement, 0); - return vec; - } - - public static Vec3 getBeltVector(BlockState state) { - BeltSlope slope = state.getValue(BeltBlock.SLOPE); - int verticality = slope == BeltSlope.DOWNWARD ? -1 : slope == BeltSlope.UPWARD ? 1 : 0; - Vec3 horizontalMovement = Vec3.atLowerCornerOf(state.getValue(BeltBlock.HORIZONTAL_FACING) - .getNormal()); - if (slope == BeltSlope.VERTICAL) - return new Vec3(0, state.getValue(BeltBlock.HORIZONTAL_FACING) - .getAxisDirection() - .getStep(), 0); - return new Vec3(0, verticality, 0).add(horizontalMovement); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltModel.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltModel.java deleted file mode 100644 index e62d6bef4..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltModel.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.belt; - -import static com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity.CASING_PROPERTY; - -import java.util.ArrayList; -import java.util.List; - -import com.simibubi.create.AllSpriteShifts; -import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity.CasingType; -import com.simibubi.create.foundation.block.render.QuadHelper; -import com.simibubi.create.foundation.block.render.SpriteShiftEntry; - -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.block.model.BakedQuad; -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.level.block.state.BlockState; -import net.minecraftforge.client.model.BakedModelWrapper; -import net.minecraftforge.client.model.data.ModelData; - -public class BeltModel extends BakedModelWrapper { - - private static final SpriteShiftEntry SPRITE_SHIFT = AllSpriteShifts.ANDESIDE_BELT_CASING; - - public BeltModel(BakedModel template) { - super(template); - } - - @Override - public List getQuads(BlockState state, Direction side, RandomSource rand, ModelData extraData, RenderType renderType) { - List quads = super.getQuads(state, side, rand, extraData, renderType); - if (!extraData.has(CASING_PROPERTY)) - return quads; - CasingType type = extraData.get(CASING_PROPERTY); - if (type == CasingType.NONE || type == CasingType.BRASS) - return quads; - - quads = new ArrayList<>(quads); - - for (int i = 0; i < quads.size(); i++) { - BakedQuad quad = quads.get(i); - TextureAtlasSprite original = quad.getSprite(); - if (original != SPRITE_SHIFT.getOriginal()) - continue; - - BakedQuad newQuad = QuadHelper.clone(quad); - int[] vertexData = newQuad.getVertices(); - - for (int vertex = 0; vertex < 4; vertex++) { - float u = QuadHelper.getU(vertexData, vertex); - float v = QuadHelper.getV(vertexData, vertex); - QuadHelper.setU(vertexData, vertex, SPRITE_SHIFT.getTargetU(u)); - QuadHelper.setV(vertexData, vertex, SPRITE_SHIFT.getTargetV(v)); - } - - quads.set(i, newQuad); - } - - return quads; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltTileEntity.java deleted file mode 100644 index 563712d99..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltTileEntity.java +++ /dev/null @@ -1,656 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.belt; - -import static com.simibubi.create.content.contraptions.relays.belt.BeltPart.MIDDLE; -import static com.simibubi.create.content.contraptions.relays.belt.BeltSlope.HORIZONTAL; -import static net.minecraft.core.Direction.AxisDirection.NEGATIVE; -import static net.minecraft.core.Direction.AxisDirection.POSITIVE; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.function.Function; - -import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; -import com.jozufozu.flywheel.light.LightListener; -import com.jozufozu.flywheel.light.LightUpdater; -import com.jozufozu.flywheel.util.box.GridAlignedBB; -import com.jozufozu.flywheel.util.box.ImmutableBox; -import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.base.IRotate; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.relays.belt.transport.BeltInventory; -import com.simibubi.create.content.contraptions.relays.belt.transport.BeltMovementHandler; -import com.simibubi.create.content.contraptions.relays.belt.transport.BeltMovementHandler.TransportedEntityInfo; -import com.simibubi.create.content.contraptions.relays.belt.transport.BeltTunnelInteractionHandler; -import com.simibubi.create.content.contraptions.relays.belt.transport.ItemHandlerBeltSegment; -import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack; -import com.simibubi.create.content.logistics.block.belts.tunnel.BrassTunnelTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour.TransportedResult; -import com.simibubi.create.foundation.utility.NBTHelper; - -import net.minecraft.client.renderer.LightTexture; -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.core.Vec3i; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtUtils; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.item.DyeColor; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.LightLayer; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.client.model.data.ModelData; -import net.minecraftforge.client.model.data.ModelProperty; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.fml.DistExecutor; -import net.minecraftforge.items.CapabilityItemHandler; -import net.minecraftforge.items.IItemHandler; - -public class BeltTileEntity extends KineticTileEntity { - - public Map passengers; - public Optional color; - public int beltLength; - public int index; - public Direction lastInsert; - public CasingType casing; - - protected BlockPos controller; - protected BeltInventory inventory; - protected LazyOptional itemHandler; - - public CompoundTag trackerUpdateTag; - - @OnlyIn(Dist.CLIENT) - public BeltLighter lighter; - - public static enum CasingType { - NONE, ANDESITE, BRASS; - } - - public BeltTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - controller = BlockPos.ZERO; - itemHandler = LazyOptional.empty(); - casing = CasingType.NONE; - color = Optional.empty(); - } - - @Override - public void addBehaviours(List behaviours) { - super.addBehaviours(behaviours); - behaviours.add(new DirectBeltInputBehaviour(this).onlyInsertWhen(this::canInsertFrom) - .setInsertionHandler(this::tryInsertingFromSide)); - behaviours.add(new TransportedItemStackHandlerBehaviour(this, this::applyToAllItems) - .withStackPlacement(this::getWorldPositionOf)); - } - - @Override - public void tick() { - // Init belt - if (beltLength == 0) - BeltBlock.initBelt(level, worldPosition); - - super.tick(); - - if (!AllBlocks.BELT.has(level.getBlockState(worldPosition))) - return; - - initializeItemHandler(); - - // Move Items - if (!isController()) - return; - - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { - if (beltLength > 0 && lighter == null) { - lighter = new BeltLighter(); - } - }); - invalidateRenderBoundingBox(); - - getInventory().tick(); - - if (getSpeed() == 0) - return; - - // Move Entities - if (passengers == null) - passengers = new HashMap<>(); - - List toRemove = new ArrayList<>(); - passengers.forEach((entity, info) -> { - boolean canBeTransported = BeltMovementHandler.canBeTransported(entity); - boolean leftTheBelt = - info.getTicksSinceLastCollision() > ((getBlockState().getValue(BeltBlock.SLOPE) != HORIZONTAL) ? 3 : 1); - if (!canBeTransported || leftTheBelt) { - toRemove.add(entity); - return; - } - - info.tick(); - BeltMovementHandler.transportEntity(this, entity, info); - }); - toRemove.forEach(passengers::remove); - } - - @Override - public float calculateStressApplied() { - if (!isController()) - return 0; - return super.calculateStressApplied(); - } - - @Override - public AABB createRenderBoundingBox() { - if (!isController()) - return super.createRenderBoundingBox(); - else - return super.createRenderBoundingBox().inflate(beltLength + 1); - } - - protected void initializeItemHandler() { - if (level.isClientSide || itemHandler.isPresent()) - return; - if (beltLength == 0 || controller == null) - return; - if (!level.isLoaded(controller)) - return; - BlockEntity te = level.getBlockEntity(controller); - if (te == null || !(te instanceof BeltTileEntity)) - return; - BeltInventory inventory = ((BeltTileEntity) te).getInventory(); - if (inventory == null) - return; - IItemHandler handler = new ItemHandlerBeltSegment(inventory, index); - itemHandler = LazyOptional.of(() -> handler); - } - - @Override - public LazyOptional getCapability(Capability cap, Direction side) { - if (!isRemoved() && !itemHandler.isPresent()) - initializeItemHandler(); - if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) { - if (side == Direction.UP || BeltBlock.canAccessFromSide(side, getBlockState())) { - return itemHandler.cast(); - } - } - return super.getCapability(cap, side); - } - - @Override - public void destroy() { - super.destroy(); - if (isController()) - getInventory().ejectAll(); - } - - @Override - public void invalidate() { - super.invalidate(); - itemHandler.invalidate(); - } - - @Override - public void write(CompoundTag compound, boolean clientPacket) { - if (controller != null) - compound.put("Controller", NbtUtils.writeBlockPos(controller)); - compound.putBoolean("IsController", isController()); - compound.putInt("Length", beltLength); - compound.putInt("Index", index); - NBTHelper.writeEnum(compound, "Casing", casing); - - if (color.isPresent()) - NBTHelper.writeEnum(compound, "Dye", color.get()); - - if (isController()) - compound.put("Inventory", getInventory().write()); - super.write(compound, clientPacket); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - int prevBeltLength = beltLength; - super.read(compound, clientPacket); - - if (compound.getBoolean("IsController")) - controller = worldPosition; - - color = compound.contains("Dye") ? Optional.of(NBTHelper.readEnum(compound, "Dye", DyeColor.class)) - : Optional.empty(); - - if (!wasMoved) { - if (!isController()) - controller = NbtUtils.readBlockPos(compound.getCompound("Controller")); - trackerUpdateTag = compound; - index = compound.getInt("Index"); - beltLength = compound.getInt("Length"); - if (prevBeltLength != beltLength) { - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { - if (lighter != null) { - lighter.initializeLight(); - } - }); - } - } - - if (isController()) - getInventory().read(compound.getCompound("Inventory")); - - CasingType casingBefore = casing; - casing = NBTHelper.readEnum(compound, "Casing", CasingType.class); - - if (!clientPacket) - return; - - if (casingBefore == casing) - return; - if (!isVirtual()) - requestModelDataUpdate(); - if (hasLevel()) - level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 16); - } - - @Override - public void clearKineticInformation() { - super.clearKineticInformation(); - beltLength = 0; - index = 0; - controller = null; - trackerUpdateTag = new CompoundTag(); - } - - public void applyColor(DyeColor colorIn) { - if (colorIn == null) { - if (!color.isPresent()) - return; - } else if (color.isPresent() && color.get() == colorIn) - return; - - for (BlockPos blockPos : BeltBlock.getBeltChain(level, getController())) { - BeltTileEntity belt = BeltHelper.getSegmentTE(level, blockPos); - if (belt == null) - continue; - belt.color = Optional.ofNullable(colorIn); - belt.setChanged(); - belt.sendData(); - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(belt)); - } - } - - public BeltTileEntity getControllerTE() { - if (controller == null) - return null; - if (!level.isLoaded(controller)) - return null; - BlockEntity te = level.getBlockEntity(controller); - if (te == null || !(te instanceof BeltTileEntity)) - return null; - return (BeltTileEntity) te; - } - - public void setController(BlockPos controller) { - this.controller = controller; - } - - public BlockPos getController() { - return controller == null ? worldPosition : controller; - } - - public boolean isController() { - return controller != null && worldPosition.getX() == controller.getX() - && worldPosition.getY() == controller.getY() && worldPosition.getZ() == controller.getZ(); - } - - public float getBeltMovementSpeed() { - return getSpeed() / 480f; - } - - public float getDirectionAwareBeltMovementSpeed() { - int offset = getBeltFacing().getAxisDirection() - .getStep(); - if (getBeltFacing().getAxis() == Axis.X) - offset *= -1; - return getBeltMovementSpeed() * offset; - } - - public boolean hasPulley() { - if (!AllBlocks.BELT.has(getBlockState())) - return false; - return getBlockState().getValue(BeltBlock.PART) != MIDDLE; - } - - protected boolean isLastBelt() { - if (getSpeed() == 0) - return false; - - Direction direction = getBeltFacing(); - if (getBlockState().getValue(BeltBlock.SLOPE) == BeltSlope.VERTICAL) - return false; - - BeltPart part = getBlockState().getValue(BeltBlock.PART); - if (part == MIDDLE) - return false; - - boolean movingPositively = (getSpeed() > 0 == (direction.getAxisDirection() - .getStep() == 1)) ^ direction.getAxis() == Axis.X; - return part == BeltPart.START ^ movingPositively; - } - - public Vec3i getMovementDirection(boolean firstHalf) { - return this.getMovementDirection(firstHalf, false); - } - - public Vec3i getBeltChainDirection() { - return this.getMovementDirection(true, true); - } - - protected Vec3i getMovementDirection(boolean firstHalf, boolean ignoreHalves) { - if (getSpeed() == 0) - return BlockPos.ZERO; - - final BlockState blockState = getBlockState(); - final Direction beltFacing = blockState.getValue(BlockStateProperties.HORIZONTAL_FACING); - final BeltSlope slope = blockState.getValue(BeltBlock.SLOPE); - final BeltPart part = blockState.getValue(BeltBlock.PART); - final Axis axis = beltFacing.getAxis(); - - Direction movementFacing = Direction.get(axis == Axis.X ? NEGATIVE : POSITIVE, axis); - boolean notHorizontal = blockState.getValue(BeltBlock.SLOPE) != HORIZONTAL; - if (getSpeed() < 0) - movementFacing = movementFacing.getOpposite(); - Vec3i movement = movementFacing.getNormal(); - - boolean slopeBeforeHalf = (part == BeltPart.END) == (beltFacing.getAxisDirection() == POSITIVE); - boolean onSlope = notHorizontal && (part == MIDDLE || slopeBeforeHalf == firstHalf || ignoreHalves); - boolean movingUp = onSlope && slope == (movementFacing == beltFacing ? BeltSlope.UPWARD : BeltSlope.DOWNWARD); - - if (!onSlope) - return movement; - - return new Vec3i(movement.getX(), movingUp ? 1 : -1, movement.getZ()); - } - - public Direction getMovementFacing() { - Axis axis = getBeltFacing().getAxis(); - return Direction.fromAxisAndDirection(axis, getBeltMovementSpeed() < 0 ^ axis == Axis.X ? NEGATIVE : POSITIVE); - } - - protected Direction getBeltFacing() { - return getBlockState().getValue(BlockStateProperties.HORIZONTAL_FACING); - } - - public BeltInventory getInventory() { - if (!isController()) { - BeltTileEntity controllerTE = getControllerTE(); - if (controllerTE != null) - return controllerTE.getInventory(); - return null; - } - if (inventory == null) { - inventory = new BeltInventory(this); - } - return inventory; - } - - private void applyToAllItems(float maxDistanceFromCenter, - Function processFunction) { - BeltTileEntity controller = getControllerTE(); - if (controller == null) - return; - BeltInventory inventory = controller.getInventory(); - if (inventory != null) - inventory.applyToEachWithin(index + .5f, maxDistanceFromCenter, processFunction); - } - - private Vec3 getWorldPositionOf(TransportedItemStack transported) { - BeltTileEntity controllerTE = getControllerTE(); - if (controllerTE == null) - return Vec3.ZERO; - return BeltHelper.getVectorForOffset(controllerTE, transported.beltPosition); - } - - public void setCasingType(CasingType type) { - if (casing == type) - return; - if (casing != CasingType.NONE) - level.levelEvent(2001, worldPosition, - Block.getId(casing == CasingType.ANDESITE ? AllBlocks.ANDESITE_CASING.getDefaultState() - : AllBlocks.BRASS_CASING.getDefaultState())); - casing = type; - boolean shouldBlockHaveCasing = type != CasingType.NONE; - BlockState blockState = getBlockState(); - if (blockState.getValue(BeltBlock.CASING) != shouldBlockHaveCasing) - KineticTileEntity.switchToBlockState(level, worldPosition, - blockState.setValue(BeltBlock.CASING, shouldBlockHaveCasing)); - setChanged(); - sendData(); - } - - private boolean canInsertFrom(Direction side) { - if (getSpeed() == 0) - return false; - BlockState state = getBlockState(); - if (state.hasProperty(BeltBlock.SLOPE) && (state.getValue(BeltBlock.SLOPE) == BeltSlope.SIDEWAYS - || state.getValue(BeltBlock.SLOPE) == BeltSlope.VERTICAL)) - return false; - return getMovementFacing() != side.getOpposite(); - } - - private ItemStack tryInsertingFromSide(TransportedItemStack transportedStack, Direction side, boolean simulate) { - BeltTileEntity nextBeltController = getControllerTE(); - ItemStack inserted = transportedStack.stack; - ItemStack empty = ItemStack.EMPTY; - - if (nextBeltController == null) - return inserted; - BeltInventory nextInventory = nextBeltController.getInventory(); - if (nextInventory == null) - return inserted; - - BlockEntity teAbove = level.getBlockEntity(worldPosition.above()); - if (teAbove instanceof BrassTunnelTileEntity) { - BrassTunnelTileEntity tunnelTE = (BrassTunnelTileEntity) teAbove; - if (tunnelTE.hasDistributionBehaviour()) { - if (!tunnelTE.getStackToDistribute() - .isEmpty()) - return inserted; - if (!tunnelTE.testFlapFilter(side.getOpposite(), inserted)) - return inserted; - if (!simulate) { - BeltTunnelInteractionHandler.flapTunnel(nextInventory, index, side.getOpposite(), true); - tunnelTE.setStackToDistribute(inserted, side.getOpposite()); - } - return empty; - } - } - - if (getSpeed() == 0) - return inserted; - if (getMovementFacing() == side.getOpposite()) - return inserted; - if (!nextInventory.canInsertAtFromSide(index, side)) - return inserted; - if (simulate) - return empty; - - transportedStack = transportedStack.copy(); - transportedStack.beltPosition = index + .5f - Math.signum(getDirectionAwareBeltMovementSpeed()) / 16f; - - Direction movementFacing = getMovementFacing(); - if (!side.getAxis() - .isVertical()) { - if (movementFacing != side) { - transportedStack.sideOffset = side.getAxisDirection() - .getStep() * .35f; - if (side.getAxis() == Axis.X) - transportedStack.sideOffset *= -1; - } else - transportedStack.beltPosition = getDirectionAwareBeltMovementSpeed() > 0 ? index : index + 1; - } - - transportedStack.prevSideOffset = transportedStack.sideOffset; - transportedStack.insertedAt = index; - transportedStack.insertedFrom = side; - transportedStack.prevBeltPosition = transportedStack.beltPosition; - - BeltTunnelInteractionHandler.flapTunnel(nextInventory, index, side.getOpposite(), true); - - nextInventory.addItem(transportedStack); - nextBeltController.setChanged(); - nextBeltController.sendData(); - return empty; - } - - public static final ModelProperty CASING_PROPERTY = new ModelProperty<>(); - - @Override - public ModelData getModelData() { - return ModelData.builder().with(CASING_PROPERTY, casing) - .build(); - } - - @Override - protected boolean canPropagateDiagonally(IRotate block, BlockState state) { - return state.hasProperty(BeltBlock.SLOPE) && (state.getValue(BeltBlock.SLOPE) == BeltSlope.UPWARD - || state.getValue(BeltBlock.SLOPE) == BeltSlope.DOWNWARD); - } - - @Override - public float propagateRotationTo(KineticTileEntity target, BlockState stateFrom, BlockState stateTo, BlockPos diff, - boolean connectedViaAxes, boolean connectedViaCogs) { - if (target instanceof BeltTileEntity && !connectedViaAxes) - return getController().equals(((BeltTileEntity) target).getController()) ? 1 : 0; - return 0; - } - - public void invalidateItemHandler() { - itemHandler.invalidate(); - } - - public boolean shouldRenderNormally() { - if (level == null) - return isController(); - BlockState state = getBlockState(); - return state != null && state.hasProperty(BeltBlock.PART) && state.getValue(BeltBlock.PART) == BeltPart.START; - } - - /** - * Hide this behavior in an inner class to avoid loading LightListener on servers. - */ - @OnlyIn(Dist.CLIENT) - class BeltLighter implements LightListener { - private byte[] light; - - public BeltLighter() { - initializeLight(); - LightUpdater.get(level) - .addListener(this); - } - - /** - * Get the number of belt segments represented by the lighter. - * @return The number of segments. - */ - public int lightSegments() { - return light == null ? 0 : light.length / 2; - } - - /** - * Get the light value for a given segment. - * @param segment The segment to get the light value for. - * @return The light value. - */ - public int getPackedLight(int segment) { - return light == null ? 0 : LightTexture.pack(light[segment * 2], light[segment * 2 + 1]); - } - - @Override - public GridAlignedBB getVolume() { - BlockPos endPos = BeltHelper.getPositionForOffset(BeltTileEntity.this, beltLength - 1); - GridAlignedBB bb = GridAlignedBB.from(worldPosition, endPos); - bb.fixMinMax(); - return bb; - } - - @Override - public boolean isListenerInvalid() { - return remove; - } - - @Override - public void onLightUpdate(LightLayer type, ImmutableBox changed) { - if (remove) - return; - if (level == null) - return; - - GridAlignedBB beltVolume = getVolume(); - - if (beltVolume.intersects(changed)) { - if (type == LightLayer.BLOCK) - updateBlockLight(); - - if (type == LightLayer.SKY) - updateSkyLight(); - } - } - - private void initializeLight() { - light = new byte[beltLength * 2]; - - Vec3i vec = getBeltFacing().getNormal(); - BeltSlope slope = getBlockState().getValue(BeltBlock.SLOPE); - int verticality = slope == BeltSlope.DOWNWARD ? -1 : slope == BeltSlope.UPWARD ? 1 : 0; - - MutableBlockPos pos = new MutableBlockPos(controller.getX(), controller.getY(), controller.getZ()); - for (int i = 0; i < beltLength * 2; i += 2) { - light[i] = (byte) level.getBrightness(LightLayer.BLOCK, pos); - light[i + 1] = (byte) level.getBrightness(LightLayer.SKY, pos); - pos.move(vec.getX(), verticality, vec.getZ()); - } - } - - private void updateBlockLight() { - Vec3i vec = getBeltFacing().getNormal(); - BeltSlope slope = getBlockState().getValue(BeltBlock.SLOPE); - int verticality = slope == BeltSlope.DOWNWARD ? -1 : slope == BeltSlope.UPWARD ? 1 : 0; - - MutableBlockPos pos = new MutableBlockPos(controller.getX(), controller.getY(), controller.getZ()); - for (int i = 0; i < beltLength * 2; i += 2) { - light[i] = (byte) level.getBrightness(LightLayer.BLOCK, pos); - - pos.move(vec.getX(), verticality, vec.getZ()); - } - } - - private void updateSkyLight() { - Vec3i vec = getBeltFacing().getNormal(); - BeltSlope slope = getBlockState().getValue(BeltBlock.SLOPE); - int verticality = slope == BeltSlope.DOWNWARD ? -1 : slope == BeltSlope.UPWARD ? 1 : 0; - - MutableBlockPos pos = new MutableBlockPos(controller.getX(), controller.getY(), controller.getZ()); - for (int i = 1; i < beltLength * 2; i += 2) { - light[i] = (byte) level.getBrightness(LightLayer.SKY, pos); - - pos.move(vec.getX(), verticality, vec.getZ()); - } - } - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltFunnelInteractionHandler.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltFunnelInteractionHandler.java deleted file mode 100644 index 52f0cbe7a..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltFunnelInteractionHandler.java +++ /dev/null @@ -1,117 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.belt.transport; - -import com.simibubi.create.content.contraptions.relays.belt.BeltHelper; -import com.simibubi.create.content.logistics.block.funnel.BeltFunnelBlock; -import com.simibubi.create.content.logistics.block.funnel.BeltFunnelBlock.Shape; -import com.simibubi.create.content.logistics.block.funnel.FunnelTileEntity; -import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.inventory.InvManipulationBehaviour; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.util.Mth; -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.minecraftforge.items.ItemHandlerHelper; - -public class BeltFunnelInteractionHandler { - - public static boolean checkForFunnels(BeltInventory beltInventory, TransportedItemStack currentItem, - float nextOffset) { - boolean beltMovementPositive = beltInventory.beltMovementPositive; - int firstUpcomingSegment = (int) Math.floor(currentItem.beltPosition); - int step = beltMovementPositive ? 1 : -1; - firstUpcomingSegment = Mth.clamp(firstUpcomingSegment, 0, beltInventory.belt.beltLength - 1); - - for (int segment = firstUpcomingSegment; beltMovementPositive ? segment <= nextOffset - : segment + 1 >= nextOffset; segment += step) { - BlockPos funnelPos = BeltHelper.getPositionForOffset(beltInventory.belt, segment) - .above(); - Level world = beltInventory.belt.getLevel(); - BlockState funnelState = world.getBlockState(funnelPos); - if (!(funnelState.getBlock() instanceof BeltFunnelBlock)) - continue; - Direction funnelFacing = funnelState.getValue(BeltFunnelBlock.HORIZONTAL_FACING); - Direction movementFacing = beltInventory.belt.getMovementFacing(); - boolean blocking = funnelFacing == movementFacing.getOpposite(); - if (funnelFacing == movementFacing) - continue; - if (funnelState.getValue(BeltFunnelBlock.SHAPE) == Shape.PUSHING) - continue; - - float funnelEntry = segment + .5f; - if (funnelState.getValue(BeltFunnelBlock.SHAPE) == Shape.EXTENDED) - funnelEntry += .499f * (beltMovementPositive ? -1 : 1); - - boolean hasCrossed = nextOffset > funnelEntry && beltMovementPositive - || nextOffset < funnelEntry && !beltMovementPositive; - if (!hasCrossed) - return false; - if (blocking) - currentItem.beltPosition = funnelEntry; - - if (world.isClientSide || funnelState.getOptionalValue(BeltFunnelBlock.POWERED).orElse(false)) - if (blocking) - return true; - else - continue; - - BlockEntity te = world.getBlockEntity(funnelPos); - if (!(te instanceof FunnelTileEntity)) - return true; - - FunnelTileEntity funnelTE = (FunnelTileEntity) te; - InvManipulationBehaviour inserting = funnelTE.getBehaviour(InvManipulationBehaviour.TYPE); - FilteringBehaviour filtering = funnelTE.getBehaviour(FilteringBehaviour.TYPE); - - if (inserting == null || filtering != null && !filtering.test(currentItem.stack)) - if (blocking) - return true; - else - continue; - - int amountToExtract = funnelTE.getAmountToExtract(); - ItemStack toInsert = currentItem.stack.copy(); - if (amountToExtract > toInsert.getCount()) - if (blocking) - return true; - else - continue; - - if (amountToExtract != -1) { - toInsert.setCount(amountToExtract); - ItemStack remainder = inserting.simulate().insert(toInsert); - if (!remainder.isEmpty()) - if (blocking) - return true; - else - continue; - } - - ItemStack remainder = inserting.insert(toInsert); - if (toInsert.equals(remainder, false)) - if (blocking) - return true; - else - continue; - - int notFilled = currentItem.stack.getCount() - toInsert.getCount(); - if (!remainder.isEmpty()) { - remainder.grow(notFilled); - } else if (notFilled > 0) - remainder = ItemHandlerHelper.copyStackWithSize(currentItem.stack, notFilled); - - funnelTE.flap(true); - funnelTE.onTransfer(toInsert); - currentItem.stack = remainder; - beltInventory.belt.sendData(); - if (blocking) - return true; - } - - return false; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltTunnelInteractionHandler.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltTunnelInteractionHandler.java deleted file mode 100644 index 3a7143ac7..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltTunnelInteractionHandler.java +++ /dev/null @@ -1,160 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.belt.transport; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.relays.belt.BeltBlock; -import com.simibubi.create.content.contraptions.relays.belt.BeltHelper; -import com.simibubi.create.content.contraptions.relays.belt.BeltSlope; -import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity; -import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelBlock; -import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelTileEntity; -import com.simibubi.create.content.logistics.block.belts.tunnel.BrassTunnelBlock; -import com.simibubi.create.content.logistics.block.belts.tunnel.BrassTunnelTileEntity; -import com.simibubi.create.content.logistics.block.display.DisplayLinkBlock; -import com.simibubi.create.content.logistics.block.display.source.AccumulatedItemCountDisplaySource; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour; -import com.simibubi.create.foundation.utility.Iterate; - -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 net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.items.ItemHandlerHelper; - -public class BeltTunnelInteractionHandler { - - public static boolean flapTunnelsAndCheckIfStuck(BeltInventory beltInventory, TransportedItemStack current, - float nextOffset) { - - int currentSegment = (int) current.beltPosition; - int upcomingSegment = (int) nextOffset; - - Direction movementFacing = beltInventory.belt.getMovementFacing(); - if (!beltInventory.beltMovementPositive && nextOffset == 0) - upcomingSegment = -1; - if (currentSegment == upcomingSegment) - return false; - - if (stuckAtTunnel(beltInventory, upcomingSegment, current.stack, movementFacing)) { - current.beltPosition = currentSegment + (beltInventory.beltMovementPositive ? .99f : .01f); - return true; - } - - Level world = beltInventory.belt.getLevel(); - boolean onServer = !world.isClientSide || beltInventory.belt.isVirtual(); - boolean removed = false; - BeltTunnelTileEntity nextTunnel = getTunnelOnSegment(beltInventory, upcomingSegment); - int transferred = current.stack.getCount(); - - if (nextTunnel instanceof BrassTunnelTileEntity) { - BrassTunnelTileEntity brassTunnel = (BrassTunnelTileEntity) nextTunnel; - if (brassTunnel.hasDistributionBehaviour()) { - if (!brassTunnel.canTakeItems()) - return true; - if (onServer) { - brassTunnel.setStackToDistribute(current.stack, movementFacing.getOpposite()); - current.stack = ItemStack.EMPTY; - beltInventory.belt.sendData(); - beltInventory.belt.setChanged(); - } - removed = true; - } - } else if (nextTunnel != null) { - BlockState blockState = nextTunnel.getBlockState(); - if (current.stack.getCount() > 1 && AllBlocks.ANDESITE_TUNNEL.has(blockState) - && BeltTunnelBlock.isJunction(blockState) - && movementFacing.getAxis() == blockState.getValue(BeltTunnelBlock.HORIZONTAL_AXIS)) { - - for (Direction d : Iterate.horizontalDirections) { - if (d.getAxis() == blockState.getValue(BeltTunnelBlock.HORIZONTAL_AXIS)) - continue; - if (!nextTunnel.flaps.containsKey(d)) - continue; - BlockPos outpos = nextTunnel.getBlockPos() - .below() - .relative(d); - if (!world.isLoaded(outpos)) - return true; - DirectBeltInputBehaviour behaviour = - TileEntityBehaviour.get(world, outpos, DirectBeltInputBehaviour.TYPE); - if (behaviour == null) - continue; - if (!behaviour.canInsertFromSide(d)) - continue; - - ItemStack toinsert = ItemHandlerHelper.copyStackWithSize(current.stack, 1); - if (!behaviour.handleInsertion(toinsert, d, false) - .isEmpty()) - return true; - if (onServer) - flapTunnel(beltInventory, upcomingSegment, d, false); - - current.stack.shrink(1); - beltInventory.belt.sendData(); - if (current.stack.getCount() <= 1) - break; - } - } - } - - if (onServer) { - flapTunnel(beltInventory, currentSegment, movementFacing, false); - flapTunnel(beltInventory, upcomingSegment, movementFacing.getOpposite(), true); - - if (nextTunnel != null) - DisplayLinkBlock.sendToGatherers(world, nextTunnel.getBlockPos(), - (dgte, b) -> b.itemReceived(dgte, transferred), AccumulatedItemCountDisplaySource.class); - } - - if (removed) - return true; - - return false; - } - - public static boolean stuckAtTunnel(BeltInventory beltInventory, int offset, ItemStack stack, - Direction movementDirection) { - BeltTileEntity belt = beltInventory.belt; - BlockPos pos = BeltHelper.getPositionForOffset(belt, offset) - .above(); - if (!(belt.getLevel() - .getBlockState(pos) - .getBlock() instanceof BrassTunnelBlock)) - return false; - BlockEntity te = belt.getLevel() - .getBlockEntity(pos); - if (te == null || !(te instanceof BrassTunnelTileEntity)) - return false; - BrassTunnelTileEntity tunnel = (BrassTunnelTileEntity) te; - return !tunnel.canInsert(movementDirection.getOpposite(), stack); - } - - public static void flapTunnel(BeltInventory beltInventory, int offset, Direction side, boolean inward) { - BeltTunnelTileEntity te = getTunnelOnSegment(beltInventory, offset); - if (te == null) - return; - te.flap(side, inward); - } - - protected static BeltTunnelTileEntity getTunnelOnSegment(BeltInventory beltInventory, int offset) { - BeltTileEntity belt = beltInventory.belt; - if (belt.getBlockState() - .getValue(BeltBlock.SLOPE) != BeltSlope.HORIZONTAL) - return null; - return getTunnelOnPosition(belt.getLevel(), BeltHelper.getPositionForOffset(belt, offset)); - } - - public static BeltTunnelTileEntity getTunnelOnPosition(Level world, BlockPos pos) { - pos = pos.above(); - if (!(world.getBlockState(pos) - .getBlock() instanceof BeltTunnelBlock)) - return null; - BlockEntity te = world.getBlockEntity(pos); - if (te == null || !(te instanceof BeltTunnelTileEntity)) - return null; - return ((BeltTunnelTileEntity) te); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/AbstractSimpleShaftBlock.java b/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/AbstractSimpleShaftBlock.java deleted file mode 100644 index 32b1d0da9..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/AbstractSimpleShaftBlock.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.elementary; - -import java.util.Optional; - -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.wrench.IWrenchableWithBracket; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.context.UseOnContext; -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.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.PushReaction; - -public abstract class AbstractSimpleShaftBlock extends AbstractShaftBlock implements IWrenchableWithBracket { - - public AbstractSimpleShaftBlock(Properties properties) { - super(properties); - } - - @Override - public InteractionResult onWrenched(BlockState state, UseOnContext context) { - return IWrenchableWithBracket.super.onWrenched(state, context); - } - - @Override - public PushReaction getPistonPushReaction(BlockState state) { - return PushReaction.NORMAL; - } - - @Override - public void onRemove(BlockState state, Level world, BlockPos pos, BlockState newState, boolean isMoving) { - if (state != newState && !isMoving) - removeBracket(world, pos, true).ifPresent(stack -> Block.popResource(world, pos, stack)); - super.onRemove(state, world, pos, newState, isMoving); - } - - @Override - public Optional removeBracket(BlockGetter world, BlockPos pos, boolean inOnReplacedContext) { - BracketedTileEntityBehaviour behaviour = TileEntityBehaviour.get(world, pos, BracketedTileEntityBehaviour.TYPE); - if (behaviour == null) - return Optional.empty(); - BlockState bracket = behaviour.removeBracket(inOnReplacedContext); - if (bracket == null) - return Optional.empty(); - return Optional.of(new ItemStack(bracket.getBlock())); - } - - @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.BRACKETED_KINETIC.get(); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/BracketedKineticTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/BracketedKineticTileEntity.java deleted file mode 100644 index 14db8435b..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/BracketedKineticTileEntity.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.elementary; - -import java.util.List; - -import com.simibubi.create.content.contraptions.components.structureMovement.ITransformableTE; -import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; - -public class BracketedKineticTileEntity extends SimpleKineticTileEntity implements ITransformableTE { - - public BracketedKineticTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - @Override - public void addBehaviours(List behaviours) { - behaviours - .add(new BracketedTileEntityBehaviour(this, state -> state.getBlock() instanceof AbstractSimpleShaftBlock)); - super.addBehaviours(behaviours); - } - - @Override - public void transform(StructureTransform transform) { - BracketedTileEntityBehaviour bracketBehaviour = getBehaviour(BracketedTileEntityBehaviour.TYPE); - if (bracketBehaviour != null) { - bracketBehaviour.transformBracket(transform); - } - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/BracketedKineticTileInstance.java b/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/BracketedKineticTileInstance.java deleted file mode 100644 index 4d5de6265..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/BracketedKineticTileInstance.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.elementary; - -import com.jozufozu.flywheel.api.Instancer; -import com.jozufozu.flywheel.api.MaterialManager; -import com.jozufozu.flywheel.util.transform.TransformStack; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.math.Axis; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.content.contraptions.base.SingleRotatingInstance; -import com.simibubi.create.content.contraptions.base.flwdata.RotatingData; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.AxisDirection; - -public class BracketedKineticTileInstance extends SingleRotatingInstance { - - protected RotatingData additionalShaft; - - public BracketedKineticTileInstance(MaterialManager modelManager, KineticTileEntity tile) { - super(modelManager, tile); - } - - @Override - public void init() { - super.init(); - if (!ICogWheel.isLargeCog(blockEntity.getBlockState())) - return; - - // Large cogs sometimes have to offset their teeth by 11.25 degrees in order to - // mesh properly - - float speed = blockEntity.getSpeed(); - Direction.Axis axis = KineticTileEntityRenderer.getRotationAxisOf(blockEntity); - BlockPos pos = blockEntity.getBlockPos(); - float offset = BracketedKineticTileRenderer.getShaftAngleOffset(axis, pos); - Direction facing = Direction.fromAxisAndDirection(axis, AxisDirection.POSITIVE); - Instancer half = getRotatingMaterial().getModel(AllBlockPartials.COGWHEEL_SHAFT, blockState, - facing, () -> this.rotateToAxis(axis)); - - additionalShaft = setup(half.createInstance(), speed); - additionalShaft.setRotationOffset(offset); - } - - @Override - protected Instancer getModel() { - if (!ICogWheel.isLargeCog(blockEntity.getBlockState())) - return super.getModel(); - - Direction.Axis axis = KineticTileEntityRenderer.getRotationAxisOf(blockEntity); - Direction facing = Direction.fromAxisAndDirection(axis, AxisDirection.POSITIVE); - return getRotatingMaterial().getModel(AllBlockPartials.SHAFTLESS_LARGE_COGWHEEL, blockState, facing, - () -> this.rotateToAxis(axis)); - } - - private PoseStack rotateToAxis(Direction.Axis axis) { - Direction facing = Direction.fromAxisAndDirection(axis, AxisDirection.POSITIVE); - PoseStack poseStack = new PoseStack(); - TransformStack.cast(poseStack) - .centre() - .rotateToFace(facing) - .multiply(Axis.XN.rotationDegrees(-90)) - .unCentre(); - return poseStack; - } - - @Override - public void update() { - super.update(); - if (additionalShaft != null) { - updateRotation(additionalShaft); - additionalShaft.setRotationOffset(BracketedKineticTileRenderer.getShaftAngleOffset(axis, pos)); - } - } - - @Override - public void updateLight() { - super.updateLight(); - if (additionalShaft != null) - relight(pos, additionalShaft); - } - - @Override - public void remove() { - super.remove(); - if (additionalShaft != null) - additionalShaft.delete(); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/BracketedKineticTileRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/BracketedKineticTileRenderer.java deleted file mode 100644 index 8e0e86660..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/BracketedKineticTileRenderer.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.elementary; - -import com.jozufozu.flywheel.backend.Backend; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider.Context; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.core.Direction.AxisDirection; - -public class BracketedKineticTileRenderer extends KineticTileEntityRenderer { - - public BracketedKineticTileRenderer(Context context) { - super(context); - } - - @Override - protected void renderSafe(KineticTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - - if (Backend.canUseInstancing(te.getLevel())) - return; - - if (!AllBlocks.LARGE_COGWHEEL.has(te.getBlockState())) { - super.renderSafe(te, partialTicks, ms, buffer, light, overlay); - return; - } - - // Large cogs sometimes have to offset their teeth by 11.25 degrees in order to - // mesh properly - - Axis axis = getRotationAxisOf(te); - BlockPos pos = te.getBlockPos(); - - Direction facing = Direction.fromAxisAndDirection(axis, AxisDirection.POSITIVE); - renderRotatingBuffer(te, - CachedBufferer.partialFacingVertical(AllBlockPartials.SHAFTLESS_LARGE_COGWHEEL, te.getBlockState(), facing), - ms, buffer.getBuffer(RenderType.solid()), light); - - float offset = getShaftAngleOffset(axis, pos); - float time = AnimationTickHolder.getRenderTime(te.getLevel()); - float angle = ((time * te.getSpeed() * 3f / 10 + offset) % 360) / 180 * (float) Math.PI; - - SuperByteBuffer shaft = - CachedBufferer.partialFacingVertical(AllBlockPartials.COGWHEEL_SHAFT, te.getBlockState(), facing); - kineticRotationTransform(shaft, te, axis, angle, light); - shaft.renderInto(ms, buffer.getBuffer(RenderType.solid())); - - } - - public static float getShaftAngleOffset(Axis axis, BlockPos pos) { - float offset = 0; - double d = (((axis == Axis.X) ? 0 : pos.getX()) + ((axis == Axis.Y) ? 0 : pos.getY()) - + ((axis == Axis.Z) ? 0 : pos.getZ())) % 2; - if (d == 0) - offset = 22.5f; - return offset; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/BracketedTileEntityBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/BracketedTileEntityBehaviour.java deleted file mode 100644 index 0989cc8dd..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/BracketedTileEntityBehaviour.java +++ /dev/null @@ -1,133 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.elementary; - -import java.util.function.Predicate; - -import org.jetbrains.annotations.Nullable; - -import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform; -import com.simibubi.create.content.schematics.ItemRequirement; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType; -import com.simibubi.create.foundation.utility.NBTHelper; - -import net.minecraft.core.registries.Registries; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtUtils; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; - -public class BracketedTileEntityBehaviour extends TileEntityBehaviour { - - public static final BehaviourType TYPE = new BehaviourType<>(); - - private BlockState bracket; - private boolean reRender; - - private Predicate pred; - - public BracketedTileEntityBehaviour(SmartTileEntity te) { - this(te, state -> true); - } - - public BracketedTileEntityBehaviour(SmartTileEntity te, Predicate pred) { - super(te); - this.pred = pred; - } - - @Override - public BehaviourType getType() { - return TYPE; - } - - public void applyBracket(BlockState state) { - this.bracket = state; - reRender = true; - tileEntity.notifyUpdate(); - Level world = getWorld(); - if (world.isClientSide) - return; - tileEntity.getBlockState() - .updateNeighbourShapes(world, getPos(), 3); - } - - public void transformBracket(StructureTransform transform) { - if (isBracketPresent()) { - BlockState transformedBracket = transform.apply(bracket); - applyBracket(transformedBracket); - } - } - - @Nullable - public BlockState removeBracket(boolean inOnReplacedContext) { - if (bracket == null) { - return null; - } - - BlockState removed = this.bracket; - Level world = getWorld(); - if (!world.isClientSide) - world.levelEvent(2001, getPos(), Block.getId(bracket)); - this.bracket = null; - reRender = true; - if (inOnReplacedContext) { - tileEntity.sendData(); - return removed; - } - tileEntity.notifyUpdate(); - if (world.isClientSide) - return removed; - tileEntity.getBlockState() - .updateNeighbourShapes(world, getPos(), 3); - return removed; - } - - public boolean isBracketPresent() { - return bracket != null; - } - - @Nullable - public BlockState getBracket() { - return bracket; - } - - public boolean canHaveBracket() { - return pred.test(tileEntity.getBlockState()); - } - - @Override - public ItemRequirement getRequiredItems() { - if (!isBracketPresent()) { - return ItemRequirement.NONE; - } - return ItemRequirement.of(bracket, null); - } - - @Override - public boolean isSafeNBT() { - return true; - } - - @Override - public void write(CompoundTag nbt, boolean clientPacket) { - if (isBracketPresent()) { - nbt.put("Bracket", NbtUtils.writeBlockState(bracket)); - } - if (clientPacket && reRender) { - NBTHelper.putMarker(nbt, "Redraw"); - reRender = false; - } - super.write(nbt, clientPacket); - } - - @Override - public void read(CompoundTag nbt, boolean clientPacket) { - if (nbt.contains("Bracket")) - bracket = NbtUtils.readBlockState(getWorld().holderLookup(Registries.BLOCK), nbt.getCompound("Bracket")); - if (clientPacket && nbt.contains("Redraw")) - getWorld().sendBlockUpdated(getPos(), tileEntity.getBlockState(), tileEntity.getBlockState(), 16); - super.read(nbt, clientPacket); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/SimpleKineticTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/SimpleKineticTileEntity.java deleted file mode 100644 index 87c9243d2..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/SimpleKineticTileEntity.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.elementary; - -import java.util.List; - -import com.simibubi.create.content.contraptions.base.IRotate; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.AABB; - -public class SimpleKineticTileEntity extends KineticTileEntity { - - public SimpleKineticTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - @Override - protected AABB createRenderBoundingBox() { - return new AABB(worldPosition).inflate(1); - } - - @Override - public List addPropagationLocations(IRotate block, BlockState state, List neighbours) { - if (!ICogWheel.isLargeCog(state)) - return super.addPropagationLocations(block, state, neighbours); - - BlockPos.betweenClosedStream(new BlockPos(-1, -1, -1), new BlockPos(1, 1, 1)) - .forEach(offset -> { - if (offset.distSqr(BlockPos.ZERO) == 2) - neighbours.add(worldPosition.offset(offset)); - }); - return neighbours; - } - - @Override - protected boolean isNoisy() { - return false; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/AdjustablePulleyBlock.java b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/AdjustablePulleyBlock.java deleted file mode 100644 index 9c02eb563..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/AdjustablePulleyBlock.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.encased; - -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition.Builder; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.block.state.properties.BooleanProperty; - -public class AdjustablePulleyBlock extends EncasedBeltBlock { - - public static BooleanProperty POWERED = BlockStateProperties.POWERED; - - public AdjustablePulleyBlock(Properties properties) { - super(properties); - registerDefaultState(defaultBlockState().setValue(POWERED, false)); - } - - @Override - protected void createBlockStateDefinition(Builder builder) { - super.createBlockStateDefinition(builder.add(POWERED)); - } - - @Override - public void onPlace(BlockState state, Level worldIn, BlockPos pos, BlockState oldState, boolean isMoving) { - super.onPlace(state, worldIn, pos, oldState, isMoving); - if (oldState.getBlock() == state.getBlock()) - return; - withTileEntityDo(worldIn, pos, kte -> ((AdjustablePulleyTileEntity) kte).neighbourChanged()); - } - - @Override - public BlockState getStateForPlacement(BlockPlaceContext context) { - return super.getStateForPlacement(context).setValue(POWERED, context.getLevel() - .hasNeighborSignal(context.getClickedPos())); - } - - @Override - protected boolean areStatesKineticallyEquivalent(BlockState oldState, BlockState newState) { - return super.areStatesKineticallyEquivalent(oldState, newState) - && oldState.getValue(POWERED) == newState.getValue(POWERED); - } - - @Override - public void neighborChanged(BlockState state, Level worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, - boolean isMoving) { - if (worldIn.isClientSide) - return; - - withTileEntityDo(worldIn, pos, kte -> ((AdjustablePulleyTileEntity) kte).neighbourChanged()); - - boolean previouslyPowered = state.getValue(POWERED); - if (previouslyPowered != worldIn.hasNeighborSignal(pos)) - worldIn.setBlock(pos, state.cycle(POWERED), 18); - } - - @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.ADJUSTABLE_PULLEY.get(); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/AdjustablePulleyTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/AdjustablePulleyTileEntity.java deleted file mode 100644 index 886456a31..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/AdjustablePulleyTileEntity.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.encased; - -import com.simibubi.create.content.contraptions.base.KineticTileEntity; - -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; - -public class AdjustablePulleyTileEntity extends KineticTileEntity { - - int signal; - boolean signalChanged; - - public AdjustablePulleyTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - signal = 0; - setLazyTickRate(40); - } - - @Override - public void write(CompoundTag compound, boolean clientPacket) { - compound.putInt("Signal", signal); - super.write(compound, clientPacket); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - signal = compound.getInt("Signal"); - super.read(compound, clientPacket); - } - - public float getModifier() { - return getModifierForSignal(signal); - } - - public void neighbourChanged() { - if (!hasLevel()) - return; - int power = level.getBestNeighborSignal(worldPosition); - if (power != signal) - signalChanged = true; - } - - @Override - public void lazyTick() { - super.lazyTick(); - neighbourChanged(); - } - - @Override - public void tick() { - super.tick(); - if (level.isClientSide) - return; - if (signalChanged) { - signalChanged = false; - analogSignalChanged(level.getBestNeighborSignal(worldPosition)); - } - } - - protected void analogSignalChanged(int newSignal) { - detachKinetics(); - removeSource(); - signal = newSignal; - attachKinetics(); - } - - protected float getModifierForSignal(int newPower) { - if (newPower == 0) - return 1; - return 1 + ((newPower + 1) / 16f); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/ClutchTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/ClutchTileEntity.java deleted file mode 100644 index 23fade805..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/ClutchTileEntity.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.encased; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; - -public class ClutchTileEntity extends SplitShaftTileEntity { - - public ClutchTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - @Override - public float getRotationSpeedModifier(Direction face) { - if (hasSource()) { - if (face != getSourceFacing() && getBlockState().getValue(BlockStateProperties.POWERED)) - return 0; - } - return 1; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/DirectionalShaftHalvesTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/DirectionalShaftHalvesTileEntity.java deleted file mode 100644 index 04f9f6b35..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/DirectionalShaftHalvesTileEntity.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.encased; - -import com.simibubi.create.content.contraptions.base.KineticTileEntity; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; - -public class DirectionalShaftHalvesTileEntity extends KineticTileEntity { - - public DirectionalShaftHalvesTileEntity(BlockEntityType typeIn, BlockPos pos, BlockState state) { - super(typeIn, pos, state); - } - - public Direction getSourceFacing() { - BlockPos localSource = source.subtract(getBlockPos()); - return Direction.getNearest(localSource.getX(), localSource.getY(), localSource.getZ()); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/EncasedBeltBlock.java b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/EncasedBeltBlock.java deleted file mode 100644 index a4c585b9a..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/EncasedBeltBlock.java +++ /dev/null @@ -1,221 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.encased; - -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.DirectionalAxisKineticBlock; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock; -import com.simibubi.create.foundation.block.ITE; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Lang; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.core.Direction.AxisDirection; -import net.minecraft.util.StringRepresentable; -import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.item.context.UseOnContext; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition.Builder; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.block.state.properties.BooleanProperty; -import net.minecraft.world.level.block.state.properties.EnumProperty; -import net.minecraft.world.level.block.state.properties.Property; -import net.minecraft.world.level.material.PushReaction; - -public class EncasedBeltBlock extends RotatedPillarKineticBlock implements ITE { - - public static final Property PART = EnumProperty.create("part", Part.class); - public static final BooleanProperty CONNECTED_ALONG_FIRST_COORDINATE = - DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE; - - public EncasedBeltBlock(Properties properties) { - super(properties); - registerDefaultState(defaultBlockState().setValue(PART, Part.NONE)); - } - - @Override - public boolean shouldCheckWeakPower(BlockState state, LevelReader world, BlockPos pos, Direction side) { - return false; - } - - @Override - public PushReaction getPistonPushReaction(BlockState state) { - return PushReaction.NORMAL; - } - - @Override - protected void createBlockStateDefinition(Builder builder) { - super.createBlockStateDefinition(builder.add(PART, CONNECTED_ALONG_FIRST_COORDINATE)); - } - - @Override - public BlockState getStateForPlacement(BlockPlaceContext context) { - Axis placedAxis = context.getNearestLookingDirection() - .getAxis(); - Axis axis = context.getPlayer() != null && context.getPlayer() - .isShiftKeyDown() ? placedAxis : getPreferredAxis(context); - if (axis == null) - axis = placedAxis; - - BlockState state = defaultBlockState().setValue(AXIS, axis); - for (Direction facing : Iterate.directions) { - if (facing.getAxis() == axis) - continue; - BlockPos pos = context.getClickedPos(); - BlockPos offset = pos.relative(facing); - state = updateShape(state, facing, context.getLevel() - .getBlockState(offset), context.getLevel(), pos, offset); - } - return state; - } - - @Override - public BlockState updateShape(BlockState stateIn, Direction face, BlockState neighbour, LevelAccessor worldIn, - BlockPos currentPos, BlockPos facingPos) { - Part part = stateIn.getValue(PART); - Axis axis = stateIn.getValue(AXIS); - boolean connectionAlongFirst = stateIn.getValue(CONNECTED_ALONG_FIRST_COORDINATE); - Axis connectionAxis = - connectionAlongFirst ? (axis == Axis.X ? Axis.Y : Axis.X) : (axis == Axis.Z ? Axis.Y : Axis.Z); - - Axis faceAxis = face.getAxis(); - boolean facingAlongFirst = axis == Axis.X ? faceAxis.isVertical() : faceAxis == Axis.X; - boolean positive = face.getAxisDirection() == AxisDirection.POSITIVE; - - if (axis == faceAxis) - return stateIn; - - if (!(neighbour.getBlock() instanceof EncasedBeltBlock)) { - if (facingAlongFirst != connectionAlongFirst || part == Part.NONE) - return stateIn; - if (part == Part.MIDDLE) - return stateIn.setValue(PART, positive ? Part.END : Part.START); - if ((part == Part.START) == positive) - return stateIn.setValue(PART, Part.NONE); - return stateIn; - } - - Part otherPart = neighbour.getValue(PART); - Axis otherAxis = neighbour.getValue(AXIS); - boolean otherConnection = neighbour.getValue(CONNECTED_ALONG_FIRST_COORDINATE); - Axis otherConnectionAxis = - otherConnection ? (otherAxis == Axis.X ? Axis.Y : Axis.X) : (otherAxis == Axis.Z ? Axis.Y : Axis.Z); - - if (neighbour.getValue(AXIS) == faceAxis) - return stateIn; - if (otherPart != Part.NONE && otherConnectionAxis != faceAxis) - return stateIn; - - if (part == Part.NONE) { - part = positive ? Part.START : Part.END; - connectionAlongFirst = axis == Axis.X ? faceAxis.isVertical() : faceAxis == Axis.X; - } else if (connectionAxis != faceAxis) { - return stateIn; - } - - if ((part == Part.START) != positive) - part = Part.MIDDLE; - - return stateIn.setValue(PART, part) - .setValue(CONNECTED_ALONG_FIRST_COORDINATE, connectionAlongFirst); - } - - @Override - public BlockState getRotatedBlockState(BlockState originalState, Direction targetedFace) { - if (originalState.getValue(PART) == Part.NONE) - return super.getRotatedBlockState(originalState, targetedFace); - return super.getRotatedBlockState(originalState, - Direction.get(AxisDirection.POSITIVE, getConnectionAxis(originalState))); - } - - @Override - public BlockState updateAfterWrenched(BlockState newState, UseOnContext context) { -// Blocks.AIR.getDefaultState() -// .updateNeighbors(context.getWorld(), context.getPos(), 1); - Axis axis = newState.getValue(AXIS); - newState = defaultBlockState().setValue(AXIS, axis); - if (newState.hasProperty(BlockStateProperties.POWERED)) - newState = newState.setValue(BlockStateProperties.POWERED, context.getLevel() - .hasNeighborSignal(context.getClickedPos())); - for (Direction facing : Iterate.directions) { - if (facing.getAxis() == axis) - continue; - BlockPos pos = context.getClickedPos(); - BlockPos offset = pos.relative(facing); - newState = updateShape(newState, facing, context.getLevel() - .getBlockState(offset), context.getLevel(), pos, offset); - } -// newState.updateNeighbors(context.getWorld(), context.getPos(), 1 | 2); - return newState; - } - - @Override - public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) { - return face.getAxis() == state.getValue(AXIS); - } - - @Override - public Axis getRotationAxis(BlockState state) { - return state.getValue(AXIS); - } - - public static boolean areBlocksConnected(BlockState state, BlockState other, Direction facing) { - Part part = state.getValue(PART); - Axis connectionAxis = getConnectionAxis(state); - Axis otherConnectionAxis = getConnectionAxis(other); - - if (otherConnectionAxis != connectionAxis) - return false; - if (facing.getAxis() != connectionAxis) - return false; - if (facing.getAxisDirection() == AxisDirection.POSITIVE && (part == Part.MIDDLE || part == Part.START)) - return true; - if (facing.getAxisDirection() == AxisDirection.NEGATIVE && (part == Part.MIDDLE || part == Part.END)) - return true; - - return false; - } - - protected static Axis getConnectionAxis(BlockState state) { - Axis axis = state.getValue(AXIS); - boolean connectionAlongFirst = state.getValue(CONNECTED_ALONG_FIRST_COORDINATE); - Axis connectionAxis = - connectionAlongFirst ? (axis == Axis.X ? Axis.Y : Axis.X) : (axis == Axis.Z ? Axis.Y : Axis.Z); - return connectionAxis; - } - - public static float getRotationSpeedModifier(KineticTileEntity from, KineticTileEntity to) { - float fromMod = 1; - float toMod = 1; - if (from instanceof AdjustablePulleyTileEntity) - fromMod = ((AdjustablePulleyTileEntity) from).getModifier(); - if (to instanceof AdjustablePulleyTileEntity) - toMod = ((AdjustablePulleyTileEntity) to).getModifier(); - return fromMod / toMod; - } - - public enum Part implements StringRepresentable { - START, MIDDLE, END, NONE; - - @Override - public String getSerializedName() { - return Lang.asId(name()); - } - } - - @Override - public Class getTileEntityClass() { - return KineticTileEntity.class; - } - - @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.ENCASED_SHAFT.get(); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/EncasedBeltGenerator.java b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/EncasedBeltGenerator.java deleted file mode 100644 index 933f2dd9d..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/EncasedBeltGenerator.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.encased; - -import java.util.function.BiFunction; - -import com.simibubi.create.content.contraptions.relays.encased.EncasedBeltBlock.Part; -import com.simibubi.create.foundation.data.SpecialBlockStateGen; -import com.tterrag.registrate.providers.DataGenContext; -import com.tterrag.registrate.providers.RegistrateBlockstateProvider; - -import net.minecraft.core.Direction.Axis; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.client.model.generators.ModelFile; - -public class EncasedBeltGenerator extends SpecialBlockStateGen { - - private BiFunction modelFunc; - - public EncasedBeltGenerator(BiFunction modelFunc) { - this.modelFunc = modelFunc; - } - - @Override - protected int getXRotation(BlockState state) { - EncasedBeltBlock.Part part = state.getValue(EncasedBeltBlock.PART); - boolean connectedAlongFirst = state.getValue(EncasedBeltBlock.CONNECTED_ALONG_FIRST_COORDINATE); - Axis axis = state.getValue(EncasedBeltBlock.AXIS); - - if (part == Part.NONE) - return axis == Axis.Y ? 90 : 0; - if (axis == Axis.X) - return (connectedAlongFirst ? 90 : 0) + (part == Part.START ? 180 : 0); - if (axis == Axis.Z) - return (connectedAlongFirst ? 0 : (part == Part.START ? 270 : 90)); - return 0; - } - - @Override - protected int getYRotation(BlockState state) { - EncasedBeltBlock.Part part = state.getValue(EncasedBeltBlock.PART); - boolean connectedAlongFirst = state.getValue(EncasedBeltBlock.CONNECTED_ALONG_FIRST_COORDINATE); - Axis axis = state.getValue(EncasedBeltBlock.AXIS); - - if (part == Part.NONE) - return axis == Axis.X ? 90 : 0; - if (axis == Axis.Z) - return (connectedAlongFirst && part == Part.END ? 270 : 90); - boolean flip = part == Part.END && !connectedAlongFirst || part == Part.START && connectedAlongFirst; - if (axis == Axis.Y) - return (connectedAlongFirst ? 90 : 0) + (flip ? 180 : 0); - return 0; - } - - @Override - public ModelFile getModel(DataGenContext ctx, RegistrateBlockstateProvider prov, - BlockState state) { - return modelFunc.apply(state, getModelSuffix(state)); - } - - protected String getModelSuffix(BlockState state) { - EncasedBeltBlock.Part part = state.getValue(EncasedBeltBlock.PART); - Axis axis = state.getValue(EncasedBeltBlock.AXIS); - - if (part == Part.NONE) - return "single"; - - String orientation = axis == Axis.Y ? "vertical" : "horizontal"; - String section = part == Part.MIDDLE ? "middle" : "end"; - return section + "_" + orientation; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/EncasedCogInstance.java b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/EncasedCogInstance.java deleted file mode 100644 index 3a2f3f506..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/EncasedCogInstance.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.encased; - -import java.util.Optional; - -import com.jozufozu.flywheel.api.InstanceData; -import com.jozufozu.flywheel.api.Instancer; -import com.jozufozu.flywheel.api.MaterialManager; -import com.jozufozu.flywheel.core.PartialModel; -import com.jozufozu.flywheel.util.transform.TransformStack; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.math.Axis; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.IRotate; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.KineticTileInstance; -import com.simibubi.create.content.contraptions.base.flwdata.RotatingData; -import com.simibubi.create.foundation.utility.Iterate; - -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.AxisDirection; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; - -public class EncasedCogInstance extends KineticTileInstance { - - private boolean large; - - protected RotatingData rotatingModel; - protected Optional rotatingTopShaft; - protected Optional rotatingBottomShaft; - - public static EncasedCogInstance small(MaterialManager modelManager, KineticTileEntity tile) { - return new EncasedCogInstance(modelManager, tile, false); - } - - public static EncasedCogInstance large(MaterialManager modelManager, KineticTileEntity tile) { - return new EncasedCogInstance(modelManager, tile, true); - } - - public EncasedCogInstance(MaterialManager modelManager, KineticTileEntity tile, boolean large) { - super(modelManager, tile); - this.large = large; - } - - @Override - public void init() { - rotatingModel = setup(getCogModel().createInstance()); - - Block block = blockState.getBlock(); - if (!(block instanceof IRotate)) - return; - - IRotate def = (IRotate) block; - rotatingTopShaft = Optional.empty(); - rotatingBottomShaft = Optional.empty(); - - for (Direction d : Iterate.directionsInAxis(axis)) { - if (!def.hasShaftTowards(blockEntity.getLevel(), blockEntity.getBlockPos(), blockState, d)) - continue; - RotatingData data = setup(getRotatingMaterial().getModel(AllBlockPartials.SHAFT_HALF, blockState, d) - .createInstance()); - if (d.getAxisDirection() == AxisDirection.POSITIVE) - rotatingTopShaft = Optional.of(data); - else - rotatingBottomShaft = Optional.of(data); - } - } - - @Override - public void update() { - updateRotation(rotatingModel); - rotatingTopShaft.ifPresent(this::updateRotation); - rotatingBottomShaft.ifPresent(this::updateRotation); - } - - @Override - public void updateLight() { - relight(pos, rotatingModel); - rotatingTopShaft.ifPresent(d -> relight(pos, d)); - rotatingBottomShaft.ifPresent(d -> relight(pos, d)); - } - - @Override - public void remove() { - rotatingModel.delete(); - rotatingTopShaft.ifPresent(InstanceData::delete); - rotatingBottomShaft.ifPresent(InstanceData::delete); - } - - protected Instancer getCogModel() { - BlockState referenceState = blockEntity.getBlockState(); - Direction facing = - Direction.fromAxisAndDirection(referenceState.getValue(BlockStateProperties.AXIS), AxisDirection.POSITIVE); - PartialModel partial = large ? AllBlockPartials.SHAFTLESS_LARGE_COGWHEEL : AllBlockPartials.SHAFTLESS_COGWHEEL; - - return getRotatingMaterial().getModel(partial, referenceState, facing, () -> { - PoseStack poseStack = new PoseStack(); - TransformStack.cast(poseStack) - .centre() - .rotateToFace(facing) - .multiply(Axis.XN.rotationDegrees(90)) - .unCentre(); - return poseStack; - }); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/EncasedCogRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/EncasedCogRenderer.java deleted file mode 100644 index 74445ff1f..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/EncasedCogRenderer.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.encased; - -import com.jozufozu.flywheel.backend.Backend; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.IRotate; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.Iterate; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.AxisDirection; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; - -public class EncasedCogRenderer extends KineticTileEntityRenderer { - - private boolean large; - - public static EncasedCogRenderer small(BlockEntityRendererProvider.Context context) { - return new EncasedCogRenderer(context, false); - } - - public static EncasedCogRenderer large(BlockEntityRendererProvider.Context context) { - return new EncasedCogRenderer(context, true); - } - - public EncasedCogRenderer(BlockEntityRendererProvider.Context context, boolean large) { - super(context); - this.large = large; - } - - @Override - protected void renderSafe(KineticTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - super.renderSafe(te, partialTicks, ms, buffer, light, overlay); - if (Backend.canUseInstancing(te.getLevel())) - return; - - BlockState blockState = te.getBlockState(); - Block block = blockState.getBlock(); - if (!(block instanceof IRotate)) - return; - IRotate def = (IRotate) block; - - for (Direction d : Iterate.directionsInAxis(getRotationAxisOf(te))) { - if (!def.hasShaftTowards(te.getLevel(), te.getBlockPos(), blockState, d)) - continue; - renderRotatingBuffer(te, CachedBufferer.partialFacing(AllBlockPartials.SHAFT_HALF, te.getBlockState(), d), - ms, buffer.getBuffer(RenderType.solid()), light); - } - } - - @Override - protected SuperByteBuffer getRotatedModel(KineticTileEntity te, BlockState state) { - return CachedBufferer.partialFacingVertical( - large ? AllBlockPartials.SHAFTLESS_LARGE_COGWHEEL : AllBlockPartials.SHAFTLESS_COGWHEEL, state, - Direction.fromAxisAndDirection(state.getValue(EncasedCogwheelBlock.AXIS), AxisDirection.POSITIVE)); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/EncasedShaftBlock.java b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/EncasedShaftBlock.java deleted file mode 100644 index b1fdba51f..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/EncasedShaftBlock.java +++ /dev/null @@ -1,85 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.encased; - -import java.util.function.Supplier; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock; -import com.simibubi.create.content.contraptions.relays.elementary.EncasedBlock; -import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement; -import com.simibubi.create.content.schematics.ItemRequirement; -import com.simibubi.create.foundation.block.ITE; - -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.item.ItemStack; -import net.minecraft.world.item.context.UseOnContext; -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.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.world.phys.HitResult; - -public class EncasedShaftBlock extends AbstractEncasedShaftBlock - implements ITE, ISpecialBlockItemRequirement, EncasedBlock { - - private final Supplier casing; - - public EncasedShaftBlock(Properties properties, Supplier casing) { - super(properties); - this.casing = casing; - } - - @Override - public InteractionResult onSneakWrenched(BlockState state, UseOnContext context) { - if (context.getLevel().isClientSide) - return InteractionResult.SUCCESS; - context.getLevel() - .levelEvent(2001, context.getClickedPos(), Block.getId(state)); - KineticTileEntity.switchToBlockState(context.getLevel(), context.getClickedPos(), - AllBlocks.SHAFT.getDefaultState() - .setValue(AXIS, state.getValue(AXIS))); - return InteractionResult.SUCCESS; - } - - @Override - public ItemStack getCloneItemStack(BlockState state, HitResult target, BlockGetter world, BlockPos pos, Player player) { - if (target instanceof BlockHitResult) - return ((BlockHitResult) target).getDirection() - .getAxis() == getRotationAxis(state) ? AllBlocks.SHAFT.asStack() : getCasing().asItem().getDefaultInstance(); - return super.getCloneItemStack(state, target, world, pos, player); - } - - @Override - public ItemRequirement getRequiredItems(BlockState state, BlockEntity te) { - return ItemRequirement.of(AllBlocks.SHAFT.getDefaultState(), te); - } - - @Override - public Class getTileEntityClass() { - return KineticTileEntity.class; - } - - @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.ENCASED_SHAFT.get(); - } - - @Override - public Block getCasing() { - return casing.get(); - } - - @Override - public void handleEncasing(BlockState state, Level level, BlockPos pos, ItemStack heldItem, Player player, InteractionHand hand, - BlockHitResult ray) { - KineticTileEntity.switchToBlockState(level, pos, defaultBlockState() - .setValue(RotatedPillarKineticBlock.AXIS, state.getValue(RotatedPillarKineticBlock.AXIS))); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/GearshiftBlock.java b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/GearshiftBlock.java deleted file mode 100644 index 4d19ec27a..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/GearshiftBlock.java +++ /dev/null @@ -1,85 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.encased; - -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.RotationPropagator; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.foundation.block.ITE; - -import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.util.RandomSource; -import net.minecraft.world.item.context.BlockPlaceContext; -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.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition.Builder; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.block.state.properties.BooleanProperty; -import net.minecraft.world.ticks.TickPriority; - -public class GearshiftBlock extends AbstractEncasedShaftBlock implements ITE { - - public static final BooleanProperty POWERED = BlockStateProperties.POWERED; - - public GearshiftBlock(Properties properties) { - super(properties); - registerDefaultState(defaultBlockState().setValue(POWERED, false)); - } - - @Override - protected void createBlockStateDefinition(Builder builder) { - builder.add(POWERED); - super.createBlockStateDefinition(builder); - } - - @Override - public BlockState getStateForPlacement(BlockPlaceContext context) { - return super.getStateForPlacement(context).setValue(POWERED, - context.getLevel().hasNeighborSignal(context.getClickedPos())); - } - - @Override - public void neighborChanged(BlockState state, Level worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, - boolean isMoving) { - if (worldIn.isClientSide) - return; - - boolean previouslyPowered = state.getValue(POWERED); - if (previouslyPowered != worldIn.hasNeighborSignal(pos)) { - detachKinetics(worldIn, pos, true); - worldIn.setBlock(pos, state.cycle(POWERED), 2); - } - } - - @Override - public Class getTileEntityClass() { - return SplitShaftTileEntity.class; - } - - @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.GEARSHIFT.get(); - } - - public void detachKinetics(Level worldIn, BlockPos pos, boolean reAttachNextTick) { - BlockEntity te = worldIn.getBlockEntity(pos); - if (te == null || !(te instanceof KineticTileEntity)) - return; - RotationPropagator.handleRemoved(worldIn, pos, (KineticTileEntity) te); - - // Re-attach next tick - if (reAttachNextTick) - worldIn.scheduleTick(pos, this, 0, TickPriority.EXTREMELY_HIGH); - } - - @Override - public void tick(BlockState state, ServerLevel worldIn, BlockPos pos, RandomSource random) { - BlockEntity te = worldIn.getBlockEntity(pos); - if (te == null || !(te instanceof KineticTileEntity)) - return; - KineticTileEntity kte = (KineticTileEntity) te; - RotationPropagator.handleAdded(worldIn, pos, kte); - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/ShaftInstance.java b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/ShaftInstance.java deleted file mode 100644 index dee669b33..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/ShaftInstance.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.encased; - -import com.jozufozu.flywheel.api.MaterialManager; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.SingleRotatingInstance; - -import net.minecraft.world.level.block.state.BlockState; - -public class ShaftInstance extends SingleRotatingInstance { - - public ShaftInstance(MaterialManager dispatcher, KineticTileEntity tile) { - super(dispatcher, tile); - } - - @Override - protected BlockState getRenderedBlockState() { - return shaft(); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/ShaftRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/ShaftRenderer.java deleted file mode 100644 index b70afbf45..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/ShaftRenderer.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.encased; - -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; - -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.world.level.block.state.BlockState; - -public class ShaftRenderer extends KineticTileEntityRenderer { - - public ShaftRenderer(BlockEntityRendererProvider.Context context) { - super(context); - } - - @Override - protected BlockState getRenderedBlockState(KineticTileEntity te) { - return shaft(getRotationAxisOf(te)); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/SplitShaftInstance.java b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/SplitShaftInstance.java deleted file mode 100644 index d6ded2749..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/SplitShaftInstance.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.encased; - -import java.util.ArrayList; - -import com.jozufozu.flywheel.api.InstanceData; -import com.jozufozu.flywheel.api.Instancer; -import com.jozufozu.flywheel.api.Material; -import com.jozufozu.flywheel.api.MaterialManager; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.IRotate; -import com.simibubi.create.content.contraptions.base.KineticTileInstance; -import com.simibubi.create.content.contraptions.base.flwdata.RotatingData; -import com.simibubi.create.foundation.utility.Iterate; - -import net.minecraft.core.Direction; -import net.minecraft.world.level.block.Block; - -public class SplitShaftInstance extends KineticTileInstance { - - protected final ArrayList keys; - - public SplitShaftInstance(MaterialManager modelManager, SplitShaftTileEntity tile) { - super(modelManager, tile); - - keys = new ArrayList<>(2); - - float speed = tile.getSpeed(); - - Material rotatingMaterial = getRotatingMaterial(); - - for (Direction dir : Iterate.directionsInAxis(getRotationAxis())) { - - Instancer half = rotatingMaterial.getModel(AllBlockPartials.SHAFT_HALF, blockState, dir); - - float splitSpeed = speed * tile.getRotationSpeedModifier(dir); - - keys.add(setup(half.createInstance(), splitSpeed)); - } - } - - @Override - public void update() { - Block block = blockState.getBlock(); - final Direction.Axis boxAxis = ((IRotate) block).getRotationAxis(blockState); - - Direction[] directions = Iterate.directionsInAxis(boxAxis); - - for (int i : Iterate.zeroAndOne) { - updateRotation(keys.get(i), blockEntity.getSpeed() * blockEntity.getRotationSpeedModifier(directions[i])); - } - } - - @Override - public void updateLight() { - relight(pos, keys.stream()); - } - - @Override - public void remove() { - keys.forEach(InstanceData::delete); - keys.clear(); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/SplitShaftRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/SplitShaftRenderer.java deleted file mode 100644 index ba38d1481..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/SplitShaftRenderer.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.encased; - -import com.jozufozu.flywheel.backend.Backend; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.IRotate; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.Iterate; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.world.level.block.Block; - -public class SplitShaftRenderer extends KineticTileEntityRenderer { - - public SplitShaftRenderer(BlockEntityRendererProvider.Context context) { - super(context); - } - - @Override - protected void renderSafe(KineticTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - if (Backend.canUseInstancing(te.getLevel())) return; - - Block block = te.getBlockState().getBlock(); - final Axis boxAxis = ((IRotate) block).getRotationAxis(te.getBlockState()); - final BlockPos pos = te.getBlockPos(); - float time = AnimationTickHolder.getRenderTime(te.getLevel()); - - for (Direction direction : Iterate.directions) { - Axis axis = direction.getAxis(); - if (boxAxis != axis) - continue; - - float offset = getRotationOffsetForPosition(te, pos, axis); - float angle = (time * te.getSpeed() * 3f / 10) % 360; - float modifier = 1; - - if (te instanceof SplitShaftTileEntity) - modifier = ((SplitShaftTileEntity) te).getRotationSpeedModifier(direction); - - angle *= modifier; - angle += offset; - angle = angle / 180f * (float) Math.PI; - - SuperByteBuffer superByteBuffer = - CachedBufferer.partialFacing(AllBlockPartials.SHAFT_HALF, te.getBlockState(), direction); - kineticRotationTransform(superByteBuffer, te, axis, angle, light); - superByteBuffer.renderInto(ms, buffer.getBuffer(RenderType.solid())); - } - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/SplitShaftTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/SplitShaftTileEntity.java deleted file mode 100644 index 82ba0dfc9..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/SplitShaftTileEntity.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.encased; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; - -public abstract class SplitShaftTileEntity extends DirectionalShaftHalvesTileEntity { - - public SplitShaftTileEntity(BlockEntityType typeIn, BlockPos pos, BlockState state) { - super(typeIn, pos, state); - } - - public abstract float getRotationSpeedModifier(Direction face); - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeObservedPacket.java b/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeObservedPacket.java deleted file mode 100644 index 8a9a85245..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeObservedPacket.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.gauge; - -import com.simibubi.create.foundation.networking.TileEntityConfigurationPacket; - -import net.minecraft.core.BlockPos; -import net.minecraft.network.FriendlyByteBuf; - -public class GaugeObservedPacket extends TileEntityConfigurationPacket { - - public GaugeObservedPacket(BlockPos pos) { - super(pos); - } - - public GaugeObservedPacket(FriendlyByteBuf buffer) { - super(buffer); - } - - @Override - protected void writeSettings(FriendlyByteBuf buffer) {} - - @Override - protected void readSettings(FriendlyByteBuf buffer) {} - - @Override - protected void applySettings(StressGaugeTileEntity te) { - te.onObserved(); - } - - @Override - protected boolean causeUpdate() { - return false; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeRenderer.java deleted file mode 100644 index a5872e8b3..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeRenderer.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.gauge; - -import com.jozufozu.flywheel.backend.Backend; -import com.jozufozu.flywheel.core.PartialModel; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.content.contraptions.relays.gauge.GaugeBlock.Type; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.Iterate; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.Direction; -import net.minecraft.util.Mth; -import net.minecraft.world.level.block.state.BlockState; - -public class GaugeRenderer extends KineticTileEntityRenderer { - - protected GaugeBlock.Type type; - - public static GaugeRenderer speed(BlockEntityRendererProvider.Context context) { - return new GaugeRenderer(context, Type.SPEED); - } - - public static GaugeRenderer stress(BlockEntityRendererProvider.Context context) { - return new GaugeRenderer(context, Type.STRESS); - } - - protected GaugeRenderer(BlockEntityRendererProvider.Context context, GaugeBlock.Type type) { - super(context); - this.type = type; - } - - @Override - protected void renderSafe(KineticTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - if (Backend.canUseInstancing(te.getLevel())) return; - - super.renderSafe(te, partialTicks, ms, buffer, light, overlay); - - BlockState gaugeState = te.getBlockState(); - GaugeTileEntity gaugeTE = (GaugeTileEntity) te; - - PartialModel partialModel = (type == Type.SPEED ? AllBlockPartials.GAUGE_HEAD_SPEED : AllBlockPartials.GAUGE_HEAD_STRESS); - SuperByteBuffer headBuffer = - CachedBufferer.partial(partialModel, gaugeState); - SuperByteBuffer dialBuffer = CachedBufferer.partial(AllBlockPartials.GAUGE_DIAL, gaugeState); - - float dialPivot = 5.75f / 16; - float progress = Mth.lerp(partialTicks, gaugeTE.prevDialState, gaugeTE.dialState); - - for (Direction facing : Iterate.directions) { - if (!((GaugeBlock) gaugeState.getBlock()).shouldRenderHeadOnFace(te.getLevel(), te.getBlockPos(), gaugeState, - facing)) - continue; - - VertexConsumer vb = buffer.getBuffer(RenderType.solid()); - rotateBufferTowards(dialBuffer, facing).translate(0, dialPivot, dialPivot) - .rotate(Direction.EAST, (float) (Math.PI / 2 * -progress)) - .translate(0, -dialPivot, -dialPivot) - .light(light) - .renderInto(ms, vb); - rotateBufferTowards(headBuffer, facing).light(light) - .renderInto(ms, vb); - } - } - - @Override - protected BlockState getRenderedBlockState(KineticTileEntity te) { - return shaft(getRotationAxisOf(te)); - } - - protected SuperByteBuffer rotateBufferTowards(SuperByteBuffer buffer, Direction target) { - return buffer.rotateCentered(Direction.UP, (float) ((-target.toYRot() - 90) / 180 * Math.PI)); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeTileEntity.java deleted file mode 100644 index bdd77ba69..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeTileEntity.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.gauge; - -import java.util.List; - -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation; -import com.simibubi.create.foundation.utility.Lang; - -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; - -public class GaugeTileEntity extends KineticTileEntity implements IHaveGoggleInformation { - - public float dialTarget; - public float dialState; - public float prevDialState; - public int color; - - public GaugeTileEntity(BlockEntityType typeIn, BlockPos pos, BlockState state) { - super(typeIn, pos, state); - } - - @Override - public void write(CompoundTag compound, boolean clientPacket) { - compound.putFloat("Value", dialTarget); - compound.putInt("Color", color); - super.write(compound, clientPacket); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - dialTarget = compound.getFloat("Value"); - color = compound.getInt("Color"); - super.read(compound, clientPacket); - } - - @Override - public void tick() { - super.tick(); - prevDialState = dialState; - dialState += (dialTarget - dialState) * .125f; - if (dialState > 1 && level.random.nextFloat() < 1 / 2f) - dialState -= (dialState - 1) * level.random.nextFloat(); - } - - @Override - public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { - tooltip.add(componentSpacing.plainCopy().append(Lang.translateDirect("gui.gauge.info_header"))); - - return true; - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/SpeedGaugeTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/SpeedGaugeTileEntity.java deleted file mode 100644 index fb48c7209..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/SpeedGaugeTileEntity.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.gauge; - -import java.util.List; - -import com.simibubi.create.content.contraptions.base.IRotate.SpeedLevel; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.utility.Color; -import com.simibubi.create.foundation.utility.Lang; - -import net.minecraft.ChatFormatting; -import net.minecraft.core.BlockPos; -import net.minecraft.network.chat.Component; -import net.minecraft.util.Mth; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; - -public class SpeedGaugeTileEntity extends GaugeTileEntity { - - public SpeedGaugeTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - @Override - public void onSpeedChanged(float prevSpeed) { - super.onSpeedChanged(prevSpeed); - float speed = Math.abs(getSpeed()); - - dialTarget = getDialTarget(speed); - color = Color.mixColors(SpeedLevel.of(speed) - .getColor(), 0xffffff, .25f); - - setChanged(); - } - - public static float getDialTarget(float speed) { - speed = Math.abs(speed); - float medium = AllConfigs.SERVER.kinetics.mediumSpeed.get() - .floatValue(); - float fast = AllConfigs.SERVER.kinetics.fastSpeed.get() - .floatValue(); - float max = AllConfigs.SERVER.kinetics.maxRotationSpeed.get() - .floatValue(); - float target = 0; - if (speed == 0) - target = 0; - else if (speed < medium) - target = Mth.lerp(speed / medium, 0, .45f); - else if (speed < fast) - target = Mth.lerp((speed - medium) / (fast - medium), .45f, .75f); - else - target = Mth.lerp((speed - fast) / (max - fast), .75f, 1.125f); - return target; - } - - @Override - public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { - super.addToGoggleTooltip(tooltip, isPlayerSneaking); - Lang.translate("gui.speedometer.title") - .style(ChatFormatting.GRAY) - .forGoggles(tooltip); - SpeedLevel.getFormattedSpeedText(speed, isOverStressed()) - .forGoggles(tooltip); - return true; - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/StressGaugeTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/StressGaugeTileEntity.java deleted file mode 100644 index 665226cb1..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/StressGaugeTileEntity.java +++ /dev/null @@ -1,144 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.gauge; - -import java.util.List; - -import com.simibubi.create.content.contraptions.base.IRotate.StressImpact; -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.item.ItemDescription; -import com.simibubi.create.foundation.networking.AllPackets; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.utility.Color; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.LangBuilder; - -import net.minecraft.ChatFormatting; -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.util.Mth; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; - -public class StressGaugeTileEntity extends GaugeTileEntity { - - static BlockPos lastSent; - - public StressGaugeTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - @Override - public void addBehaviours(List behaviours) { - super.addBehaviours(behaviours); - registerAwardables(behaviours, AllAdvancements.STRESSOMETER, AllAdvancements.STRESSOMETER_MAXED); - } - - @Override - public void updateFromNetwork(float maxStress, float currentStress, int networkSize) { - super.updateFromNetwork(maxStress, currentStress, networkSize); - - if (!StressImpact.isEnabled()) - dialTarget = 0; - else if (isOverStressed()) - dialTarget = 1.125f; - else if (maxStress == 0) - dialTarget = 0; - else - dialTarget = currentStress / maxStress; - - if (dialTarget > 0) { - if (dialTarget < .5f) - color = Color.mixColors(0x00FF00, 0xFFFF00, dialTarget * 2); - else if (dialTarget < 1) - color = Color.mixColors(0xFFFF00, 0xFF0000, (dialTarget) * 2 - 1); - else - color = 0xFF0000; - } - - sendData(); - setChanged(); - } - - @Override - public void onSpeedChanged(float prevSpeed) { - super.onSpeedChanged(prevSpeed); - if (getSpeed() == 0) { - dialTarget = 0; - setChanged(); - return; - } - - updateFromNetwork(capacity, stress, getOrCreateNetwork().getSize()); - } - - @Override - public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { - if (!StressImpact.isEnabled()) - return false; - - super.addToGoggleTooltip(tooltip, isPlayerSneaking); - - double capacity = getNetworkCapacity(); - double stressFraction = getNetworkStress() / (capacity == 0 ? 1 : capacity); - - Lang.translate("gui.stressometer.title") - .style(ChatFormatting.GRAY) - .forGoggles(tooltip); - - if (getTheoreticalSpeed() == 0) - Lang.text(ItemDescription.makeProgressBar(3, 0)) - .translate("gui.stressometer.no_rotation") - .style(ChatFormatting.DARK_GRAY) - .forGoggles(tooltip); - else { - StressImpact.getFormattedStressText(stressFraction) - .forGoggles(tooltip); - Lang.translate("gui.stressometer.capacity") - .style(ChatFormatting.GRAY) - .forGoggles(tooltip); - - double remainingCapacity = capacity - getNetworkStress(); - - LangBuilder su = Lang.translate("generic.unit.stress"); - LangBuilder stressTip = Lang.number(remainingCapacity) - .add(su) - .style(StressImpact.of(stressFraction) - .getRelativeColor()); - - if (remainingCapacity != capacity) - stressTip.text(ChatFormatting.GRAY, " / ") - .add(Lang.number(capacity) - .add(su) - .style(ChatFormatting.DARK_GRAY)); - - stressTip.forGoggles(tooltip, 1); - } - - if (!worldPosition.equals(lastSent)) - AllPackets.channel.sendToServer(new GaugeObservedPacket(lastSent = worldPosition)); - - return true; - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - super.read(compound, clientPacket); - if (clientPacket && worldPosition != null && worldPosition.equals(lastSent)) - lastSent = null; - } - - public float getNetworkStress() { - return stress; - } - - public float getNetworkCapacity() { - return capacity; - } - - public void onObserved() { - award(AllAdvancements.STRESSOMETER); - if (Mth.equal(dialTarget, 1)) - award(AllAdvancements.STRESSOMETER_MAXED); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxRenderer.java deleted file mode 100644 index 04671bcad..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxRenderer.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.gearbox; - -import com.jozufozu.flywheel.backend.Backend; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.Iterate; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; - -public class GearboxRenderer extends KineticTileEntityRenderer { - - public GearboxRenderer(BlockEntityRendererProvider.Context context) { - super(context); - } - - @Override - protected void renderSafe(KineticTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - if (Backend.canUseInstancing(te.getLevel())) return; - - final Axis boxAxis = te.getBlockState().getValue(BlockStateProperties.AXIS); - final BlockPos pos = te.getBlockPos(); - float time = AnimationTickHolder.getRenderTime(te.getLevel()); - - for (Direction direction : Iterate.directions) { - final Axis axis = direction.getAxis(); - if (boxAxis == axis) - continue; - - SuperByteBuffer shaft = CachedBufferer.partialFacing(AllBlockPartials.SHAFT_HALF, te.getBlockState(), direction); - float offset = getRotationOffsetForPosition(te, pos, axis); - float angle = (time * te.getSpeed() * 3f / 10) % 360; - - if (te.getSpeed() != 0 && te.hasSource()) { - BlockPos source = te.source.subtract(te.getBlockPos()); - Direction sourceFacing = Direction.getNearest(source.getX(), source.getY(), source.getZ()); - if (sourceFacing.getAxis() == direction.getAxis()) - angle *= sourceFacing == direction ? 1 : -1; - else if (sourceFacing.getAxisDirection() == direction.getAxisDirection()) - angle *= -1; - } - - angle += offset; - angle = angle / 180f * (float) Math.PI; - - kineticRotationTransform(shaft, te, axis, angle, light); - shaft.renderInto(ms, buffer.getBuffer(RenderType.solid())); - } - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxTileEntity.java deleted file mode 100644 index d7b1a3ca2..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxTileEntity.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.gearbox; - -import com.simibubi.create.content.contraptions.relays.encased.DirectionalShaftHalvesTileEntity; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; - -public class GearboxTileEntity extends DirectionalShaftHalvesTileEntity { - - public GearboxTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - @Override - protected boolean isNoisy() { - return false; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearshiftTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearshiftTileEntity.java deleted file mode 100644 index cb96e271d..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearshiftTileEntity.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.gearbox; - -import com.simibubi.create.content.contraptions.relays.encased.SplitShaftTileEntity; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; - -public class GearshiftTileEntity extends SplitShaftTileEntity { - - public GearshiftTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - @Override - public float getRotationSpeedModifier(Direction face) { - if (hasSource()) { - if (face != getSourceFacing() && getBlockState().getValue(BlockStateProperties.POWERED)) - return -1; - } - return 1; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ActorInstance.java b/src/main/java/com/simibubi/create/content/contraptions/render/ActorInstance.java similarity index 81% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ActorInstance.java rename to src/main/java/com/simibubi/create/content/contraptions/render/ActorInstance.java index 0097df6e5..ff37307d8 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ActorInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/render/ActorInstance.java @@ -1,8 +1,8 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.render; +package com.simibubi.create.content.contraptions.render; import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; import net.minecraft.world.level.LightLayer; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionEntityRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionEntityRenderer.java similarity index 82% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionEntityRenderer.java rename to src/main/java/com/simibubi/create/content/contraptions/render/ContraptionEntityRenderer.java index 9a9a965c5..9005060ae 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionEntityRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionEntityRenderer.java @@ -1,8 +1,8 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.render; +package com.simibubi.create.content.contraptions.render; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.Contraption; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.culling.Frustum; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionGroup.java b/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionGroup.java similarity index 90% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionGroup.java rename to src/main/java/com/simibubi/create/content/contraptions/render/ContraptionGroup.java index a51193ecd..17a92c880 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionGroup.java +++ b/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionGroup.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.render; +package com.simibubi.create.content.contraptions.render; import com.jozufozu.flywheel.backend.instancing.instancing.InstancedMaterialGroup; import com.jozufozu.flywheel.backend.instancing.instancing.InstancingEngine; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionInstanceManager.java b/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionInstanceManager.java similarity index 86% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionInstanceManager.java rename to src/main/java/com/simibubi/create/content/contraptions/render/ContraptionInstanceManager.java index e23505303..adec03d1e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionInstanceManager.java +++ b/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionInstanceManager.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.render; +package com.simibubi.create.content.contraptions.render; import java.util.ArrayList; @@ -12,9 +12,9 @@ import com.jozufozu.flywheel.backend.instancing.TaskEngine; import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstanceManager; import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; import com.simibubi.create.AllMovementBehaviours; -import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; import net.minecraft.client.Camera; import net.minecraft.world.level.block.entity.BlockEntity; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionLighter.java b/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionLighter.java similarity index 90% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionLighter.java rename to src/main/java/com/simibubi/create/content/contraptions/render/ContraptionLighter.java index 4ecd4c3cd..d1abc1719 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionLighter.java +++ b/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionLighter.java @@ -1,11 +1,11 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.render; +package com.simibubi.create.content.contraptions.render; import com.jozufozu.flywheel.light.GPULightVolume; import com.jozufozu.flywheel.light.LightListener; import com.jozufozu.flywheel.light.LightUpdater; import com.jozufozu.flywheel.util.box.GridAlignedBB; import com.jozufozu.flywheel.util.box.ImmutableBox; -import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; +import com.simibubi.create.content.contraptions.Contraption; import net.minecraft.world.level.LightLayer; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionMatrices.java b/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionMatrices.java similarity index 92% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionMatrices.java rename to src/main/java/com/simibubi/create/content/contraptions/render/ContraptionMatrices.java index a2343a979..2bee34e8d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionMatrices.java +++ b/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionMatrices.java @@ -1,9 +1,9 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.render; +package com.simibubi.create.content.contraptions.render; import org.joml.Matrix4f; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; import com.simibubi.create.foundation.utility.AnimationTickHolder; import net.minecraft.util.Mth; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionProgram.java b/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionProgram.java similarity index 93% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionProgram.java rename to src/main/java/com/simibubi/create/content/contraptions/render/ContraptionProgram.java index acbd2afde..c1eb10ad2 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionProgram.java +++ b/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionProgram.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.render; +package com.simibubi.create.content.contraptions.render; import org.joml.Matrix4f; import org.lwjgl.opengl.GL20; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderDispatcher.java b/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionRenderDispatcher.java similarity index 87% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderDispatcher.java rename to src/main/java/com/simibubi/create/content/contraptions/render/ContraptionRenderDispatcher.java index 891de4d75..547ba8059 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderDispatcher.java +++ b/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionRenderDispatcher.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.render; +package com.simibubi.create.content.contraptions.render; import java.util.Collection; @@ -18,13 +18,13 @@ import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.BufferBuilder.RenderedBuffer; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllMovementBehaviours; -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; -import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionWorld; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.contraptions.ContraptionWorld; +import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.foundation.render.BlockEntityRenderHelper; import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.render.TileEntityRenderHelper; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.LevelRenderer; @@ -106,7 +106,7 @@ public class ContraptionRenderDispatcher { VirtualRenderWorld renderWorld = renderInfo.renderWorld; - renderTileEntities(world, renderWorld, contraption, matrices, buffers); + renderBlockEntities(world, renderWorld, contraption, matrices, buffers); if (buffers instanceof MultiBufferSource.BufferSource) ((MultiBufferSource.BufferSource) buffers).endBatch(); @@ -127,7 +127,7 @@ public class ContraptionRenderDispatcher { } }; - renderWorld.setBlockEntities(c.presentTileEntities.values()); + renderWorld.setBlockEntities(c.presentBlockEntities.values()); for (StructureTemplate.StructureBlockInfo info : c.getBlocks() .values()) // Skip individual lighting updates to prevent lag with large contraptions @@ -137,9 +137,9 @@ public class ContraptionRenderDispatcher { return renderWorld; } - public static void renderTileEntities(Level world, VirtualRenderWorld renderWorld, Contraption c, + public static void renderBlockEntities(Level world, VirtualRenderWorld renderWorld, Contraption c, ContraptionMatrices matrices, MultiBufferSource buffer) { - TileEntityRenderHelper.renderTileEntities(world, renderWorld, c.getSpecialRenderedTEs(), + BlockEntityRenderHelper.renderBlockEntities(world, renderWorld, c.getSpecialRenderedTEs(), matrices.getModelViewProjection(), matrices.getLight(), buffer); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderInfo.java b/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionRenderInfo.java similarity index 87% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderInfo.java rename to src/main/java/com/simibubi/create/content/contraptions/render/ContraptionRenderInfo.java index 857a1ec4b..ff3ebf3e3 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderInfo.java +++ b/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionRenderInfo.java @@ -1,10 +1,10 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.render; +package com.simibubi.create.content.contraptions.render; import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; import com.jozufozu.flywheel.event.BeginFrameEvent; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.Contraption; import com.simibubi.create.foundation.utility.AnimationTickHolder; import net.minecraft.util.Mth; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderingWorld.java b/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionRenderingWorld.java similarity index 87% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderingWorld.java rename to src/main/java/com/simibubi/create/content/contraptions/render/ContraptionRenderingWorld.java index f09549fa5..de71b0d94 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderingWorld.java +++ b/src/main/java/com/simibubi/create/content/contraptions/render/ContraptionRenderingWorld.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.render; +package com.simibubi.create.content.contraptions.render; import java.lang.ref.Reference; import java.util.List; @@ -7,9 +7,9 @@ import java.util.Objects; import com.jozufozu.flywheel.event.BeginFrameEvent; import com.jozufozu.flywheel.event.RenderLayerEvent; -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; -import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionHandler; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.contraptions.ContraptionHandler; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; diff --git a/src/main/java/com/simibubi/create/content/contraptions/render/EmptyLighter.java b/src/main/java/com/simibubi/create/content/contraptions/render/EmptyLighter.java new file mode 100644 index 000000000..6ff1e1bd8 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/render/EmptyLighter.java @@ -0,0 +1,16 @@ +package com.simibubi.create.content.contraptions.render; + +import com.jozufozu.flywheel.util.box.GridAlignedBB; +import com.simibubi.create.content.contraptions.Contraption; + +// so other contraptions don't crash before they have a lighter +public class EmptyLighter extends ContraptionLighter { + public EmptyLighter(Contraption contraption) { + super(contraption); + } + + @Override + public GridAlignedBB getContraptionBounds() { + return new GridAlignedBB(0, 0, 0, 1, 1, 1); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/FlwContraption.java b/src/main/java/com/simibubi/create/content/contraptions/render/FlwContraption.java similarity index 83% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/FlwContraption.java rename to src/main/java/com/simibubi/create/content/contraptions/render/FlwContraption.java index 1a4286b9d..186bf619f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/FlwContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/render/FlwContraption.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.render; +package com.simibubi.create.content.contraptions.render; import java.util.Collection; import java.util.HashMap; @@ -21,8 +21,8 @@ import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; import com.jozufozu.flywheel.event.BeginFrameEvent; import com.jozufozu.flywheel.event.RenderLayerEvent; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.Contraption; import com.simibubi.create.foundation.render.CreateContexts; import com.simibubi.create.foundation.utility.AnimationTickHolder; @@ -55,7 +55,7 @@ public class FlwContraption extends ContraptionRenderInfo { var restoreState = GlStateTracker.getRestoreState(); buildLayers(); if (ContraptionRenderDispatcher.canInstance()) { - buildInstancedTiles(); + buildInstancedBlockEntities(); buildActors(); } restoreState.restore(); @@ -96,7 +96,7 @@ public class FlwContraption extends ContraptionRenderInfo { if (!isVisible()) return; - instanceWorld.tileInstanceManager.beginFrame(SerialTaskEngine.INSTANCE, event.getCamera()); + instanceWorld.blockEntityInstanceManager.beginFrame(SerialTaskEngine.INSTANCE, event.getCamera()); Vec3 cameraPos = event.getCameraPos(); @@ -151,21 +151,21 @@ public class FlwContraption extends ContraptionRenderInfo { } } - private void buildInstancedTiles() { - for (BlockEntity te : contraption.maybeInstancedTileEntities) { - if (!InstancedRenderRegistry.canInstance(te.getType())) { + private void buildInstancedBlockEntities() { + for (BlockEntity be : contraption.maybeInstancedBlockEntities) { + if (!InstancedRenderRegistry.canInstance(be.getType())) { continue; } - Level world = te.getLevel(); - te.setLevel(renderWorld); - instanceWorld.tileInstanceManager.add(te); - te.setLevel(world); + Level world = be.getLevel(); + be.setLevel(renderWorld); + instanceWorld.blockEntityInstanceManager.add(be); + be.setLevel(world); } } private void buildActors() { - contraption.getActors().forEach(instanceWorld.tileInstanceManager::createActor); + contraption.getActors().forEach(instanceWorld.blockEntityInstanceManager::createActor); } public static void setupModelViewPartial(Matrix4f matrix, Matrix4f modelMatrix, AbstractContraptionEntity entity, double camX, double camY, double camZ, float pt) { @@ -177,13 +177,13 @@ public class FlwContraption extends ContraptionRenderInfo { } public void tick() { - instanceWorld.tileInstanceManager.tick(); + instanceWorld.blockEntityInstanceManager.tick(); } public static class ContraptionInstanceWorld { private final Engine engine; - private final ContraptionInstanceManager tileInstanceManager; + private final ContraptionInstanceManager blockEntityInstanceManager; public ContraptionInstanceWorld(FlwContraption parent) { switch (Backend.getBackendType()) { @@ -192,14 +192,14 @@ public class FlwContraption extends ContraptionRenderInfo { .setGroupFactory(ContraptionGroup.forContraption(parent)) .setIgnoreOriginCoordinate(true) .build(); - tileInstanceManager = new ContraptionInstanceManager(engine, parent.renderWorld, parent.contraption); - engine.addListener(tileInstanceManager); + blockEntityInstanceManager = new ContraptionInstanceManager(engine, parent.renderWorld, parent.contraption); + engine.addListener(blockEntityInstanceManager); this.engine = engine; } case BATCHING -> { engine = new BatchingEngine(); - tileInstanceManager = new ContraptionInstanceManager(engine, parent.renderWorld, parent.contraption); + blockEntityInstanceManager = new ContraptionInstanceManager(engine, parent.renderWorld, parent.contraption); } default -> throw new IllegalArgumentException("Unknown engine type"); } @@ -207,7 +207,7 @@ public class FlwContraption extends ContraptionRenderInfo { public void delete() { engine.delete(); - tileInstanceManager.invalidate(); + blockEntityInstanceManager.invalidate(); } } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/FlwContraptionManager.java b/src/main/java/com/simibubi/create/content/contraptions/render/FlwContraptionManager.java similarity index 94% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/FlwContraptionManager.java rename to src/main/java/com/simibubi/create/content/contraptions/render/FlwContraptionManager.java index 3c44caea7..47a58f380 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/FlwContraptionManager.java +++ b/src/main/java/com/simibubi/create/content/contraptions/render/FlwContraptionManager.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.render; +package com.simibubi.create.content.contraptions.render; import static org.lwjgl.opengl.GL11.glBindTexture; import static org.lwjgl.opengl.GL12.GL_TEXTURE_3D; @@ -14,7 +14,7 @@ import com.jozufozu.flywheel.core.compile.ProgramContext; import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; import com.jozufozu.flywheel.event.RenderLayerEvent; import com.jozufozu.flywheel.util.Textures; -import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; +import com.simibubi.create.content.contraptions.Contraption; import com.simibubi.create.foundation.render.CreateContexts; import net.minecraft.world.level.LevelAccessor; diff --git a/src/main/java/com/simibubi/create/content/contraptions/render/NonStationaryLighter.java b/src/main/java/com/simibubi/create/content/contraptions/render/NonStationaryLighter.java new file mode 100644 index 000000000..d339258fd --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/render/NonStationaryLighter.java @@ -0,0 +1,40 @@ +package com.simibubi.create.content.contraptions.render; + +import com.jozufozu.flywheel.light.TickingLightListener; +import com.jozufozu.flywheel.util.box.GridAlignedBB; +import com.jozufozu.flywheel.util.box.ImmutableBox; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.infrastructure.config.AllConfigs; + +public class NonStationaryLighter extends ContraptionLighter implements TickingLightListener { + public NonStationaryLighter(C contraption) { + super(contraption); + } + + @Override + public boolean tickLightListener() { + if (getVolume().volume() > AllConfigs.client().maxContraptionLightVolume.get()) + return false; + + ImmutableBox contraptionBounds = getContraptionBounds(); + + if (bounds.sameAs(contraptionBounds, 2)) { + return false; + } + bounds.assign(contraptionBounds); + growBoundsForEdgeData(bounds); + + lightVolume.move(bounds); + + return true; + } + + @Override + public GridAlignedBB getContraptionBounds() { + GridAlignedBB bb = GridAlignedBB.from(contraption.bounds); + + bb.translate(contraption.entity.blockPosition()); + + return bb; + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/OrientedContraptionEntityRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/render/OrientedContraptionEntityRenderer.java similarity index 79% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/OrientedContraptionEntityRenderer.java rename to src/main/java/com/simibubi/create/content/contraptions/render/OrientedContraptionEntityRenderer.java index 0789157fa..53b8e89af 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/OrientedContraptionEntityRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/render/OrientedContraptionEntityRenderer.java @@ -1,6 +1,7 @@ -package com.simibubi.create.content.contraptions.components.structureMovement; +package com.simibubi.create.content.contraptions.render; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionEntityRenderer; +import com.simibubi.create.content.contraptions.ContraptionType; +import com.simibubi.create.content.contraptions.OrientedContraptionEntity; import net.minecraft.client.renderer.culling.Frustum; import net.minecraft.client.renderer.entity.EntityRendererProvider; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/SBBContraptionManager.java b/src/main/java/com/simibubi/create/content/contraptions/render/SBBContraptionManager.java similarity index 92% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/SBBContraptionManager.java rename to src/main/java/com/simibubi/create/content/contraptions/render/SBBContraptionManager.java index ce34578b3..2a779d7aa 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/SBBContraptionManager.java +++ b/src/main/java/com/simibubi/create/content/contraptions/render/SBBContraptionManager.java @@ -1,10 +1,10 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.render; +package com.simibubi.create.content.contraptions.render; import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; import com.jozufozu.flywheel.event.RenderLayerEvent; import com.mojang.blaze3d.vertex.VertexConsumer; import com.simibubi.create.CreateClient; -import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; +import com.simibubi.create.content.contraptions.Contraption; import com.simibubi.create.foundation.render.SuperByteBuffer; import com.simibubi.create.foundation.render.SuperByteBufferCache; import com.simibubi.create.foundation.utility.Pair; diff --git a/src/main/java/com/simibubi/create/content/contraptions/render/package-info.java b/src/main/java/com/simibubi/create/content/contraptions/render/package-info.java new file mode 100644 index 000000000..7c51e431d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/render/package-info.java @@ -0,0 +1,6 @@ +@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault +package com.simibubi.create.content.contraptions.render; + +import javax.annotation.ParametersAreNonnullByDefault; + +import net.minecraft.MethodsReturnNonnullByDefault; diff --git a/src/main/java/com/simibubi/create/content/contraptions/sync/ClientMotionPacket.java b/src/main/java/com/simibubi/create/content/contraptions/sync/ClientMotionPacket.java new file mode 100644 index 000000000..8b98a2a16 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/sync/ClientMotionPacket.java @@ -0,0 +1,60 @@ +package com.simibubi.create.content.contraptions.sync; + +import com.simibubi.create.AllPackets; +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.network.NetworkEvent.Context; +import net.minecraftforge.network.PacketDistributor; + +public class ClientMotionPacket extends SimplePacketBase { + + private Vec3 motion; + private boolean onGround; + private float limbSwing; + + public ClientMotionPacket(Vec3 motion, boolean onGround, float limbSwing) { + this.motion = motion; + this.onGround = onGround; + this.limbSwing = limbSwing; + } + + public ClientMotionPacket(FriendlyByteBuf buffer) { + motion = new Vec3(buffer.readFloat(), buffer.readFloat(), buffer.readFloat()); + onGround = buffer.readBoolean(); + limbSwing = buffer.readFloat(); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeFloat((float) motion.x); + buffer.writeFloat((float) motion.y); + buffer.writeFloat((float) motion.z); + buffer.writeBoolean(onGround); + buffer.writeFloat(limbSwing); + } + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> { + ServerPlayer sender = context.getSender(); + if (sender == null) + return; + sender.setDeltaMovement(motion); + sender.setOnGround(onGround); + if (onGround) { + sender.causeFallDamage(sender.fallDistance, 1, DamageSource.FALL); + sender.fallDistance = 0; + sender.connection.aboveGroundTickCount = 0; + sender.connection.aboveGroundVehicleTickCount = 0; + } + AllPackets.getChannel().send(PacketDistributor.TRACKING_ENTITY.with(() -> sender), + new LimbSwingUpdatePacket(sender.getId(), sender.position(), limbSwing)); + }); + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/sync/ContraptionFluidPacket.java b/src/main/java/com/simibubi/create/content/contraptions/sync/ContraptionFluidPacket.java new file mode 100644 index 000000000..2c94225b8 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/sync/ContraptionFluidPacket.java @@ -0,0 +1,49 @@ +package com.simibubi.create.content.contraptions.sync; + +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.entity.Entity; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.network.NetworkEvent.Context; + +public class ContraptionFluidPacket extends SimplePacketBase { + + private int entityId; + private BlockPos localPos; + private FluidStack containedFluid; + + public ContraptionFluidPacket(int entityId, BlockPos localPos, FluidStack containedFluid) { + this.entityId = entityId; + this.localPos = localPos; + this.containedFluid = containedFluid; + } + + public ContraptionFluidPacket(FriendlyByteBuf buffer) { + entityId = buffer.readInt(); + localPos = buffer.readBlockPos(); + containedFluid = FluidStack.readFromPacket(buffer); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeInt(entityId); + buffer.writeBlockPos(localPos); + containedFluid.writeToPacket(buffer); + } + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> { + Entity entityByID = Minecraft.getInstance().level.getEntity(entityId); + if (!(entityByID instanceof AbstractContraptionEntity)) + return; + AbstractContraptionEntity contraptionEntity = (AbstractContraptionEntity) entityByID; + contraptionEntity.getContraption().handleContraptionFluidPacket(localPos, containedFluid); + }); + return true; + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/ContraptionInteractionPacket.java b/src/main/java/com/simibubi/create/content/contraptions/sync/ContraptionInteractionPacket.java similarity index 84% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/ContraptionInteractionPacket.java rename to src/main/java/com/simibubi/create/content/contraptions/sync/ContraptionInteractionPacket.java index 4d4492ca1..51dab433e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/sync/ContraptionInteractionPacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/sync/ContraptionInteractionPacket.java @@ -1,8 +1,6 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.sync; +package com.simibubi.create.content.contraptions.sync; -import java.util.function.Supplier; - -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; import com.simibubi.create.foundation.networking.SimplePacketBase; import net.minecraft.core.BlockPos; @@ -46,9 +44,9 @@ public class ContraptionInteractionPacket extends SimplePacketBase { } @Override - public void handle(Supplier context) { - context.get().enqueueWork(() -> { - ServerPlayer sender = context.get().getSender(); + public boolean handle(Context context) { + context.enqueueWork(() -> { + ServerPlayer sender = context.getSender(); if (sender == null) return; Entity entityByID = sender.getLevel().getEntity(target); @@ -66,7 +64,7 @@ public class ContraptionInteractionPacket extends SimplePacketBase { if (contraptionEntity.handlePlayerInteraction(sender, localPos, face, interactionHand)) sender.swing(interactionHand, true); }); - context.get().setPacketHandled(true); + return true; } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/sync/ContraptionSeatMappingPacket.java b/src/main/java/com/simibubi/create/content/contraptions/sync/ContraptionSeatMappingPacket.java new file mode 100644 index 000000000..0e2937560 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/sync/ContraptionSeatMappingPacket.java @@ -0,0 +1,77 @@ +package com.simibubi.create.content.contraptions.sync; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.foundation.networking.SimplePacketBase; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.client.Minecraft; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.network.NetworkEvent.Context; + +public class ContraptionSeatMappingPacket extends SimplePacketBase { + + private Map mapping; + private int entityID; + private int dismountedID; + + public ContraptionSeatMappingPacket(int entityID, Map mapping) { + this(entityID, mapping, -1); + } + + public ContraptionSeatMappingPacket(int entityID, Map mapping, int dismountedID) { + this.entityID = entityID; + this.mapping = mapping; + this.dismountedID = dismountedID; + } + + public ContraptionSeatMappingPacket(FriendlyByteBuf buffer) { + entityID = buffer.readInt(); + dismountedID = buffer.readInt(); + mapping = new HashMap<>(); + short size = buffer.readShort(); + for (int i = 0; i < size; i++) + mapping.put(buffer.readUUID(), (int) buffer.readShort()); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeInt(entityID); + buffer.writeInt(dismountedID); + buffer.writeShort(mapping.size()); + mapping.forEach((k, v) -> { + buffer.writeUUID(k); + buffer.writeShort(v); + }); + } + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> { + Entity entityByID = Minecraft.getInstance().level.getEntity(entityID); + if (!(entityByID instanceof AbstractContraptionEntity)) + return; + AbstractContraptionEntity contraptionEntity = (AbstractContraptionEntity) entityByID; + + if (dismountedID != -1) { + Entity dismountedByID = Minecraft.getInstance().level.getEntity(dismountedID); + if (Minecraft.getInstance().player != dismountedByID) + return; + Vec3 transformedVector = contraptionEntity.getPassengerPosition(dismountedByID, 1); + if (transformedVector != null) + dismountedByID.getPersistentData() + .put("ContraptionDismountLocation", VecHelper.writeNBT(transformedVector)); + } + + contraptionEntity.getContraption() + .setSeatMapping(mapping); + }); + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/sync/LimbSwingUpdatePacket.java b/src/main/java/com/simibubi/create/content/contraptions/sync/LimbSwingUpdatePacket.java new file mode 100644 index 000000000..cfde843d6 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/sync/LimbSwingUpdatePacket.java @@ -0,0 +1,58 @@ +package com.simibubi.create.content.contraptions.sync; + +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.network.NetworkEvent.Context; + +public class LimbSwingUpdatePacket extends SimplePacketBase { + + private int entityId; + private Vec3 position; + private float limbSwing; + + public LimbSwingUpdatePacket(int entityId, Vec3 position, float limbSwing) { + this.entityId = entityId; + this.position = position; + this.limbSwing = limbSwing; + } + + public LimbSwingUpdatePacket(FriendlyByteBuf buffer) { + entityId = buffer.readInt(); + position = new Vec3(buffer.readDouble(), buffer.readDouble(), buffer.readDouble()); + limbSwing = buffer.readFloat(); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeInt(entityId); + buffer.writeDouble(position.x); + buffer.writeDouble(position.y); + buffer.writeDouble(position.z); + buffer.writeFloat(limbSwing); + } + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> { + ClientLevel world = Minecraft.getInstance().level; + if (world == null) + return; + Entity entity = world.getEntity(entityId); + if (entity == null) + return; + CompoundTag data = entity.getPersistentData(); + data.putInt("LastOverrideLimbSwingUpdate", 0); + data.putFloat("OverrideLimbSwing", limbSwing); + entity.lerpTo(position.x, position.y, position.z, entity.getYRot(), + entity.getXRot(), 2, false); + }); + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/wrench/WrenchItemRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/wrench/WrenchItemRenderer.java deleted file mode 100644 index fc0d24e17..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/wrench/WrenchItemRenderer.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.simibubi.create.content.contraptions.wrench; - -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.math.Axis; -import com.simibubi.create.foundation.item.render.CustomRenderedItemModelRenderer; -import com.simibubi.create.foundation.item.render.PartialItemModelRenderer; -import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueHandler; -import com.simibubi.create.foundation.utility.AnimationTickHolder; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.block.model.ItemTransforms; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.world.item.ItemStack; - -public class WrenchItemRenderer extends CustomRenderedItemModelRenderer { - - @Override - protected void render(ItemStack stack, WrenchModel model, PartialItemModelRenderer renderer, ItemTransforms.TransformType transformType, - PoseStack ms, MultiBufferSource buffer, int light, int overlay) { - renderer.render(model.getOriginalModel(), light); - - float xOffset = -1/16f; - ms.translate(-xOffset, 0, 0); - ms.mulPose(Axis.YP.rotationDegrees(ScrollValueHandler.getScroll(AnimationTickHolder.getPartialTicks()))); - ms.translate(xOffset, 0, 0); - - renderer.render(model.getPartial("gear"), light); - } - - @Override - public WrenchModel createModel(BakedModel originalModel) { - return new WrenchModel(originalModel); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/wrench/WrenchModel.java b/src/main/java/com/simibubi/create/content/contraptions/wrench/WrenchModel.java deleted file mode 100644 index c1901c3ef..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/wrench/WrenchModel.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.simibubi.create.content.contraptions.wrench; - -import com.simibubi.create.foundation.item.render.CreateCustomRenderedItemModel; - -import net.minecraft.client.resources.model.BakedModel; - -public class WrenchModel extends CreateCustomRenderedItemModel { - - public WrenchModel(BakedModel template) { - super(template, "wrench"); - addPartials("gear"); - } - -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/armor/BackTankUtil.java b/src/main/java/com/simibubi/create/content/curiosities/armor/BackTankUtil.java deleted file mode 100644 index d0ade7c05..000000000 --- a/src/main/java/com/simibubi/create/content/curiosities/armor/BackTankUtil.java +++ /dev/null @@ -1,145 +0,0 @@ -package com.simibubi.create.content.curiosities.armor; - -import com.simibubi.create.AllEnchantments; -import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.AllTags; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; - -import net.minecraft.ChatFormatting; -import net.minecraft.client.Minecraft; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.network.protocol.game.ClientboundSetSubtitleTextPacket; -import net.minecraft.network.protocol.game.ClientboundSetTitleTextPacket; -import net.minecraft.network.protocol.game.ClientboundSetTitlesAnimationPacket; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.util.Mth; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.fml.DistExecutor; - -public class BackTankUtil { - - public static ItemStack get(LivingEntity entity) { - for (ItemStack itemStack : entity.getArmorSlots()) - if (AllTags.AllItemTags.PRESSURIZED_AIR_SOURCES.matches(itemStack)) - return itemStack; - return ItemStack.EMPTY; - } - - public static boolean hasAirRemaining(ItemStack backtank) { - return getAir(backtank) > 0; - } - - public static float getAir(ItemStack backtank) { - CompoundTag tag = backtank.getOrCreateTag(); - return Math.min(tag.getFloat("Air"), maxAir(backtank)); - } - - public static void consumeAir(LivingEntity entity, ItemStack backtank, float i) { - CompoundTag tag = backtank.getOrCreateTag(); - int maxAir = maxAir(backtank); - float air = getAir(backtank); - float newAir = air - i; - tag.putFloat("Air", Math.min(newAir, maxAir)); - backtank.setTag(tag); - - if (!(entity instanceof ServerPlayer player)) - return; - sendWarning(player, air, newAir, maxAir / 10f); - sendWarning(player, air, newAir, 1); - } - - private static void sendWarning(ServerPlayer player, float air, float newAir, float threshold) { - if (newAir > threshold) - return; - if (air <= threshold) - return; - - boolean depleted = threshold == 1; - MutableComponent component = Lang.translateDirect(depleted ? "backtank.depleted" : "backtank.low"); - - AllSoundEvents.DENY.play(player.level, null, player.blockPosition(), 1, 1.25f); - AllSoundEvents.STEAM.play(player.level, null, player.blockPosition(), .5f, .5f); - - player.connection.send(new ClientboundSetTitlesAnimationPacket(10, 40, 10)); - player.connection.send(new ClientboundSetSubtitleTextPacket( - Components.literal("\u26A0 ").withStyle(depleted ? ChatFormatting.RED : ChatFormatting.GOLD) - .append(component.withStyle(ChatFormatting.GRAY)))); - player.connection.send(new ClientboundSetTitleTextPacket(Components.immutableEmpty())); - } - - public static int maxAir(ItemStack backtank) { - return maxAir(backtank.getEnchantmentLevel(AllEnchantments.CAPACITY.get())); - } - - public static int maxAir(int enchantLevel) { - return AllConfigs.SERVER.curiosities.airInBacktank.get() - + AllConfigs.SERVER.curiosities.enchantedBacktankCapacity.get() * enchantLevel; - } - - public static int maxAirWithoutEnchants() { - return AllConfigs.SERVER.curiosities.airInBacktank.get(); - } - - public static boolean canAbsorbDamage(LivingEntity entity, int usesPerTank) { - if (usesPerTank == 0) - return true; - if (entity instanceof Player && ((Player) entity).isCreative()) - return true; - ItemStack backtank = get(entity); - if (backtank.isEmpty()) - return false; - if (!hasAirRemaining(backtank)) - return false; - float cost = ((float) maxAirWithoutEnchants()) / usesPerTank; - consumeAir(entity, backtank, cost); - return true; - } - - // For Air-using tools - - public static boolean isBarVisible(ItemStack stack, int usesPerTank) { - if (usesPerTank == 0) - return false; - Player player = DistExecutor.unsafeCallWhenOn(Dist.CLIENT, () -> () -> Minecraft.getInstance().player); - if (player == null) - return false; - ItemStack backtank = get(player); - if (backtank.isEmpty() || !hasAirRemaining(backtank)) - return stack.isDamaged(); - return true; - } - - public static int getBarWidth(ItemStack stack, int usesPerTank) { - if (usesPerTank == 0) - return 13; - Player player = DistExecutor.unsafeCallWhenOn(Dist.CLIENT, () -> () -> Minecraft.getInstance().player); - if (player == null) - return 13; - ItemStack backtank = get(player); - if (backtank.isEmpty() || !hasAirRemaining(backtank)) - return Math.round(13.0F - (float) stack.getDamageValue() / stack.getMaxDamage() * 13.0F); - return backtank.getItem() - .getBarWidth(backtank); - } - - public static int getBarColor(ItemStack stack, int usesPerTank) { - if (usesPerTank == 0) - return 0; - Player player = DistExecutor.unsafeCallWhenOn(Dist.CLIENT, () -> () -> Minecraft.getInstance().player); - if (player == null) - return 0; - ItemStack backtank = get(player); - if (backtank.isEmpty() || !hasAirRemaining(backtank)) - return Mth.hsvToRgb(Math.max(0.0F, 1.0F - (float) stack.getDamageValue() / stack.getMaxDamage()) / 3.0F, - 1.0F, 1.0F); - return backtank.getItem() - .getBarColor(backtank); - } - -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/armor/CapacityEnchantment.java b/src/main/java/com/simibubi/create/content/curiosities/armor/CapacityEnchantment.java deleted file mode 100644 index 531e1bf4e..000000000 --- a/src/main/java/com/simibubi/create/content/curiosities/armor/CapacityEnchantment.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.simibubi.create.content.curiosities.armor; - -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.enchantment.Enchantment; -import net.minecraft.world.item.enchantment.EnchantmentCategory; - -public class CapacityEnchantment extends Enchantment { - - public CapacityEnchantment(Rarity p_i46731_1_, EnchantmentCategory p_i46731_2_, EquipmentSlot[] p_i46731_3_) { - super(p_i46731_1_, p_i46731_2_, p_i46731_3_); - } - - @Override - public int getMaxLevel() { - return 3; - } - - @Override - public boolean canApplyAtEnchantingTable(ItemStack stack) { - return stack.getItem() instanceof ICapacityEnchantable; - } - - public interface ICapacityEnchantable { - } - -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/armor/CopperArmorItem.java b/src/main/java/com/simibubi/create/content/curiosities/armor/CopperArmorItem.java deleted file mode 100644 index 8b3220ad1..000000000 --- a/src/main/java/com/simibubi/create/content/curiosities/armor/CopperArmorItem.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.simibubi.create.content.curiosities.armor; - -import com.simibubi.create.Create; - -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ArmorItem; -import net.minecraft.world.item.ItemStack; - -public class CopperArmorItem extends ArmorItem { - - public static final ResourceLocation TEXTURE = Create.asResource("textures/models/armor/copper.png"); - private static final String TEXTURE_STRING = TEXTURE.toString(); - - public CopperArmorItem(EquipmentSlot p_i48534_2_, Properties p_i48534_3_) { - super(AllArmorMaterials.COPPER, p_i48534_2_, p_i48534_3_.stacksTo(1)); - } - - public boolean isWornBy(Entity entity) { - if (!(entity instanceof LivingEntity)) - return false; - LivingEntity livingEntity = (LivingEntity) entity; - return livingEntity.getItemBySlot(slot).getItem() == this; - } - - @Override - public String getArmorTexture(ItemStack stack, Entity entity, EquipmentSlot slot, String type) { - return TEXTURE_STRING; - } - -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/armor/CopperBacktankArmorLayer.java b/src/main/java/com/simibubi/create/content/curiosities/armor/CopperBacktankArmorLayer.java deleted file mode 100644 index d2d156c68..000000000 --- a/src/main/java/com/simibubi/create/content/curiosities/armor/CopperBacktankArmorLayer.java +++ /dev/null @@ -1,145 +0,0 @@ -package com.simibubi.create.content.curiosities.armor; - -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllItems; -import com.simibubi.create.foundation.gui.element.GuiGameElement; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.Color; -import com.simibubi.create.foundation.utility.Components; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.model.EntityModel; -import net.minecraft.client.model.HumanoidModel; -import net.minecraft.client.player.LocalPlayer; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.Sheets; -import net.minecraft.client.renderer.entity.EntityRenderDispatcher; -import net.minecraft.client.renderer.entity.EntityRenderer; -import net.minecraft.client.renderer.entity.LivingEntityRenderer; -import net.minecraft.client.renderer.entity.RenderLayerParent; -import net.minecraft.client.renderer.entity.layers.RenderLayer; -import net.minecraft.core.Direction; -import net.minecraft.network.chat.Component; -import net.minecraft.util.StringUtil; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.Pose; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.level.GameType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.client.gui.overlay.ForgeGui; -import net.minecraftforge.client.gui.overlay.IGuiOverlay; -import net.minecraftforge.common.ForgeMod; - -public class CopperBacktankArmorLayer> extends RenderLayer { - - public static final IGuiOverlay REMAINING_AIR_OVERLAY = CopperBacktankArmorLayer::renderRemainingAirOverlay; - - public CopperBacktankArmorLayer(RenderLayerParent renderer) { - super(renderer); - } - - @Override - public void render(PoseStack ms, MultiBufferSource buffer, int light, LivingEntity entity, float yaw, float pitch, - float pt, float p_225628_8_, float p_225628_9_, float p_225628_10_) { - if (entity.getPose() == Pose.SLEEPING) - return; - if (!AllItems.COPPER_BACKTANK.get() - .isWornBy(entity)) - return; - - M entityModel = getParentModel(); - if (!(entityModel instanceof HumanoidModel)) - return; - - HumanoidModel model = (HumanoidModel) entityModel; - RenderType renderType = Sheets.cutoutBlockSheet(); - BlockState renderedState = AllBlocks.COPPER_BACKTANK.getDefaultState() - .setValue(CopperBacktankBlock.HORIZONTAL_FACING, Direction.SOUTH); - SuperByteBuffer backtank = CachedBufferer.block(renderedState); - SuperByteBuffer cogs = CachedBufferer.partial(AllBlockPartials.COPPER_BACKTANK_COGS, renderedState); - - ms.pushPose(); - - model.body.translateAndRotate(ms); - ms.translate(-1 / 2f, 10 / 16f, 1f); - ms.scale(1, -1, -1); - - backtank.forEntityRender() - .light(light) - .renderInto(ms, buffer.getBuffer(renderType)); - - cogs.centre() - .rotateY(180) - .unCentre() - .translate(0, 6.5f / 16, 11f / 16) - .rotate(Direction.EAST, AngleHelper.rad(2 * AnimationTickHolder.getRenderTime(entity.level) % 360)) - .translate(0, -6.5f / 16, -11f / 16); - - cogs.forEntityRender() - .light(light) - .renderInto(ms, buffer.getBuffer(renderType)); - - ms.popPose(); - } - - public static void registerOnAll(EntityRenderDispatcher renderManager) { - for (EntityRenderer renderer : renderManager.getSkinMap().values()) - registerOn(renderer); - for (EntityRenderer renderer : renderManager.renderers.values()) - registerOn(renderer); - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - public static void registerOn(EntityRenderer entityRenderer) { - if (!(entityRenderer instanceof LivingEntityRenderer)) - return; - LivingEntityRenderer livingRenderer = (LivingEntityRenderer) entityRenderer; - if (!(livingRenderer.getModel() instanceof HumanoidModel)) - return; - CopperBacktankArmorLayer layer = new CopperBacktankArmorLayer<>(livingRenderer); - livingRenderer.addLayer((CopperBacktankArmorLayer) layer); - } - - public static void renderRemainingAirOverlay(ForgeGui gui, PoseStack poseStack, float partialTicks, int width, int height) { - Minecraft mc = Minecraft.getInstance(); - if (mc.options.hideGui || mc.gameMode.getPlayerMode() == GameType.SPECTATOR) - return; - - LocalPlayer player = mc.player; - if (player == null) - return; - if (player.isCreative()) - return; - if (!player.getPersistentData() - .contains("VisualBacktankAir")) - return; - if (!player.isEyeInFluidType(ForgeMod.WATER_TYPE.get())) - return; - - int timeLeft = player.getPersistentData() - .getInt("VisualBacktankAir"); - - poseStack.pushPose(); - - poseStack.translate(width / 2 + 90, height - 53, 0); - - Component text = Components.literal(StringUtil.formatTickDuration(timeLeft * 20)); - GuiGameElement.of(AllItems.COPPER_BACKTANK.asStack()) - .at(0, 0) - .render(poseStack); - int color = 0xFF_FFFFFF; - if (timeLeft < 60 && timeLeft % 2 == 0) { - color = Color.mixColors(0xFF_FF0000, color, Math.max(timeLeft / 60f, .25f)); - } - Minecraft.getInstance().font.drawShadow(poseStack, text, 16, 5, color); - - poseStack.popPose(); - } - -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/armor/CopperBacktankBlock.java b/src/main/java/com/simibubi/create/content/curiosities/armor/CopperBacktankBlock.java deleted file mode 100644 index f84513345..000000000 --- a/src/main/java/com/simibubi/create/content/curiosities/armor/CopperBacktankBlock.java +++ /dev/null @@ -1,190 +0,0 @@ -package com.simibubi.create.content.curiosities.armor; - -import java.util.Optional; - -import com.simibubi.create.AllEnchantments; -import com.simibubi.create.AllItems; -import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.HorizontalKineticBlock; -import com.simibubi.create.foundation.block.ITE; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.network.chat.Component; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.ItemStack; -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.LevelReader; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.SimpleWaterloggedBlock; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition.Builder; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -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.BlockHitResult; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.VoxelShape; -import net.minecraftforge.common.util.FakePlayer; - -public class CopperBacktankBlock extends HorizontalKineticBlock - implements ITE, SimpleWaterloggedBlock { - - public CopperBacktankBlock(Properties properties) { - super(properties); - registerDefaultState(super.defaultBlockState().setValue(BlockStateProperties.WATERLOGGED, false)); - } - - @Override - public FluidState getFluidState(BlockState state) { - return state.getValue(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getSource(false) - : Fluids.EMPTY.defaultFluidState(); - } - - @Override - protected void createBlockStateDefinition(Builder builder) { - builder.add(BlockStateProperties.WATERLOGGED); - super.createBlockStateDefinition(builder); - } - - @Override - public boolean hasAnalogOutputSignal(BlockState p_149740_1_) { - return true; - } - - @Override - public int getAnalogOutputSignal(BlockState p_180641_1_, Level world, BlockPos pos) { - return getTileEntityOptional(world, pos).map(CopperBacktankTileEntity::getComparatorOutput) - .orElse(0); - } - - @Override - public BlockState updateShape(BlockState state, Direction direction, BlockState neighbourState, - LevelAccessor world, BlockPos pos, BlockPos neighbourPos) { - if (state.getValue(BlockStateProperties.WATERLOGGED)) - world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world)); - return state; - } - - @Override - public BlockState getStateForPlacement(BlockPlaceContext context) { - FluidState ifluidstate = context.getLevel() - .getFluidState(context.getClickedPos()); - return super.getStateForPlacement(context).setValue(BlockStateProperties.WATERLOGGED, - Boolean.valueOf(ifluidstate.getType() == Fluids.WATER)); - } - - @Override - public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) { - return face == Direction.UP; - } - - @Override - public Axis getRotationAxis(BlockState state) { - return Axis.Y; - } - - @Override - public void setPlacedBy(Level worldIn, BlockPos pos, BlockState state, LivingEntity placer, ItemStack stack) { - super.setPlacedBy(worldIn, pos, state, placer, stack); - if (worldIn.isClientSide) - return; - if (stack == null) - return; - withTileEntityDo(worldIn, pos, te -> { - te.setCapacityEnchantLevel(stack.getEnchantmentLevel(AllEnchantments.CAPACITY.get())); - te.setAirLevel(stack.getOrCreateTag() - .getInt("Air")); - if (stack.isEnchanted()) - te.setEnchantmentTag(stack.getEnchantmentTags()); - if (stack.hasCustomHoverName()) - te.setCustomName(stack.getHoverName()); - }); - } - - @Override - public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand p_225533_5_, - BlockHitResult p_225533_6_) { - if (player == null) - return InteractionResult.PASS; - if (player instanceof FakePlayer) - return InteractionResult.PASS; - if (player.isShiftKeyDown()) - return InteractionResult.PASS; - if (player.getMainHandItem() - .getItem() instanceof BlockItem) - return InteractionResult.PASS; - if (!player.getItemBySlot(EquipmentSlot.CHEST) - .isEmpty()) - return InteractionResult.PASS; - if (!world.isClientSide) { - world.playSound(null, pos, SoundEvents.ITEM_PICKUP, SoundSource.PLAYERS, .75f, 1); - player.setItemSlot(EquipmentSlot.CHEST, getCloneItemStack(world, pos, state)); - world.destroyBlock(pos, false); - } - return InteractionResult.SUCCESS; - } - - @Override - public ItemStack getCloneItemStack(BlockGetter p_185473_1_, BlockPos p_185473_2_, BlockState p_185473_3_) { - ItemStack item = AllItems.COPPER_BACKTANK.asStack(); - Optional tileEntityOptional = getTileEntityOptional(p_185473_1_, p_185473_2_); - - int air = tileEntityOptional.map(CopperBacktankTileEntity::getAirLevel) - .orElse(0); - CompoundTag tag = item.getOrCreateTag(); - tag.putInt("Air", air); - - ListTag enchants = tileEntityOptional.map(CopperBacktankTileEntity::getEnchantmentTag) - .orElse(new ListTag()); - if (!enchants.isEmpty()) { - ListTag enchantmentTagList = item.getEnchantmentTags(); - enchantmentTagList.addAll(enchants); - tag.put("Enchantments", enchantmentTagList); - } - - Component customName = tileEntityOptional.map(CopperBacktankTileEntity::getCustomName) - .orElse(null); - if (customName != null) - item.setHoverName(customName); - return item; - } - - @Override - public VoxelShape getShape(BlockState p_220053_1_, BlockGetter p_220053_2_, BlockPos p_220053_3_, - CollisionContext p_220053_4_) { - return AllShapes.BACKTANK; - } - - @Override - public Class getTileEntityClass() { - return CopperBacktankTileEntity.class; - } - - @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.COPPER_BACKTANK.get(); - } - - @Override - public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) { - return false; - } - -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/armor/CopperBacktankInstance.java b/src/main/java/com/simibubi/create/content/curiosities/armor/CopperBacktankInstance.java deleted file mode 100644 index 26d1b9139..000000000 --- a/src/main/java/com/simibubi/create/content/curiosities/armor/CopperBacktankInstance.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.simibubi.create.content.curiosities.armor; - -import com.jozufozu.flywheel.api.Instancer; -import com.jozufozu.flywheel.api.MaterialManager; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.SingleRotatingInstance; -import com.simibubi.create.content.contraptions.base.flwdata.RotatingData; - -public class CopperBacktankInstance extends SingleRotatingInstance { - - public CopperBacktankInstance(MaterialManager modelManager, KineticTileEntity tile) { - super(modelManager, tile); - } - - @Override - protected Instancer getModel() { - return getRotatingMaterial().getModel(AllBlockPartials.COPPER_BACKTANK_SHAFT, blockState); - } - -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/armor/CopperBacktankItem.java b/src/main/java/com/simibubi/create/content/curiosities/armor/CopperBacktankItem.java deleted file mode 100644 index 9fb95d3ae..000000000 --- a/src/main/java/com/simibubi/create/content/curiosities/armor/CopperBacktankItem.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.simibubi.create.content.curiosities.armor; - -import com.simibubi.create.content.curiosities.armor.CapacityEnchantment.ICapacityEnchantable; -import com.tterrag.registrate.util.entry.ItemEntry; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.util.Mth; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.context.UseOnContext; -import net.minecraft.world.level.block.Block; - -public class CopperBacktankItem extends CopperArmorItem implements ICapacityEnchantable { - - public static final int DURABILITY_BAR = 0xEFEFEF; - private ItemEntry blockItem; - - public CopperBacktankItem(Properties p_i48534_3_, ItemEntry copperBacktankPlaceable) { - super(EquipmentSlot.CHEST, p_i48534_3_); - this.blockItem = copperBacktankPlaceable; - } - - @Override - public InteractionResult useOn(UseOnContext p_195939_1_) { - return blockItem.get() - .useOn(p_195939_1_); - } - - @Override - public boolean canBeDepleted() { - return false; - } - - @Override - public boolean isEnchantable(ItemStack p_77616_1_) { - return true; - } - - @Override - public boolean isBarVisible(ItemStack stack) { - return true; - } - - @Override - public int getBarWidth(ItemStack stack) { - return Math.round(13.0F * Mth.clamp(getRemainingAir(stack) / ((float) BackTankUtil.maxAir(stack)), 0, 1)); - } - - @Override - public int getBarColor(ItemStack stack) { - return DURABILITY_BAR; - } - - public static int getRemainingAir(ItemStack stack) { - CompoundTag orCreateTag = stack.getOrCreateTag(); - return orCreateTag.getInt("Air"); - } - - public static class CopperBacktankBlockItem extends BlockItem { - - public CopperBacktankBlockItem(Block pBlock, Properties pProperties) { - super(pBlock, pProperties); - } - - @Override - public String getDescriptionId() { - return this.getOrCreateDescriptionId(); - } - - } - -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/armor/CopperBacktankRenderer.java b/src/main/java/com/simibubi/create/content/curiosities/armor/CopperBacktankRenderer.java deleted file mode 100644 index fc7b1d87a..000000000 --- a/src/main/java/com/simibubi/create/content/curiosities/armor/CopperBacktankRenderer.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.simibubi.create.content.curiosities.armor; - -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.Direction; -import net.minecraft.world.level.block.state.BlockState; - -public class CopperBacktankRenderer extends KineticTileEntityRenderer { - - public CopperBacktankRenderer(BlockEntityRendererProvider.Context context) { - super(context); - } - - @Override - protected void renderSafe(KineticTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - super.renderSafe(te, partialTicks, ms, buffer, light, overlay); - - BlockState blockState = te.getBlockState(); - SuperByteBuffer cogs = CachedBufferer.partial(AllBlockPartials.COPPER_BACKTANK_COGS, blockState); - cogs.centre() - .rotateY(180 + AngleHelper.horizontalAngle(blockState.getValue(CopperBacktankBlock.HORIZONTAL_FACING))) - .unCentre() - .translate(0, 6.5f / 16, 11f / 16) - .rotate(Direction.EAST, - AngleHelper.rad(te.getSpeed() / 4f * AnimationTickHolder.getRenderTime(te.getLevel()) % 360)) - .translate(0, -6.5f / 16, -11f / 16); - cogs.light(light) - .renderInto(ms, buffer.getBuffer(RenderType.solid())); - } - - @Override - protected SuperByteBuffer getRotatedModel(KineticTileEntity te, BlockState state) { - return CachedBufferer.partial(AllBlockPartials.COPPER_BACKTANK_SHAFT, state); - } - -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/armor/CopperBacktankTileEntity.java b/src/main/java/com/simibubi/create/content/curiosities/armor/CopperBacktankTileEntity.java deleted file mode 100644 index 181dbc866..000000000 --- a/src/main/java/com/simibubi/create/content/curiosities/armor/CopperBacktankTileEntity.java +++ /dev/null @@ -1,175 +0,0 @@ -package com.simibubi.create.content.curiosities.armor; - -import java.util.List; - -import com.simibubi.create.AllItems; -import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.particle.AirParticleData; -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.tileEntity.ComparatorUtil; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction.Axis; -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.Tag; -import net.minecraft.network.chat.Component; -import net.minecraft.util.Mth; -import net.minecraft.world.Nameable; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.block.state.properties.BooleanProperty; -import net.minecraft.world.phys.Vec3; - -public class CopperBacktankTileEntity extends KineticTileEntity implements Nameable { - - public int airLevel; - public int airLevelTimer; - private Component customName; - - private int capacityEnchantLevel; - private ListTag enchantmentTag; - - public CopperBacktankTileEntity(BlockEntityType typeIn, BlockPos pos, BlockState state) { - super(typeIn, pos, state); - enchantmentTag = new ListTag(); - } - - @Override - public void addBehaviours(List behaviours) { - super.addBehaviours(behaviours); - registerAwardables(behaviours, AllAdvancements.BACKTANK); - } - - @Override - public void onSpeedChanged(float previousSpeed) { - super.onSpeedChanged(previousSpeed); - if (getSpeed() != 0) - award(AllAdvancements.BACKTANK); - } - - @Override - public void tick() { - super.tick(); - if (getSpeed() == 0) - return; - - BlockState state = getBlockState(); - BooleanProperty waterProperty = BlockStateProperties.WATERLOGGED; - if (state.hasProperty(waterProperty) && state.getValue(waterProperty)) - return; - - if (airLevelTimer > 0) { - airLevelTimer--; - return; - } - - int max = BackTankUtil.maxAir(capacityEnchantLevel); - if (level.isClientSide) { - Vec3 centerOf = VecHelper.getCenterOf(worldPosition); - Vec3 v = VecHelper.offsetRandomly(centerOf, level.random, .65f); - Vec3 m = centerOf.subtract(v); - if (airLevel != max) - level.addParticle(new AirParticleData(1, .05f), v.x, v.y, v.z, m.x, m.y, m.z); - return; - } - - if (airLevel == max) - return; - - int prevComparatorLevel = getComparatorOutput(); - float abs = Math.abs(getSpeed()); - int increment = Mth.clamp(((int) abs - 100) / 20, 1, 5); - airLevel = Math.min(max, airLevel + increment); - if (getComparatorOutput() != prevComparatorLevel && !level.isClientSide) - level.updateNeighbourForOutputSignal(worldPosition, state.getBlock()); - if (airLevel == max) - sendData(); - airLevelTimer = Mth.clamp((int) (128f - abs / 5f) - 108, 0, 20); - } - - public int getComparatorOutput() { - int max = BackTankUtil.maxAir(capacityEnchantLevel); - return ComparatorUtil.fractionToRedstoneLevel(airLevel / (float) max); - } - - @Override - protected void write(CompoundTag compound, boolean clientPacket) { - super.write(compound, clientPacket); - compound.putInt("Air", airLevel); - compound.putInt("Timer", airLevelTimer); - compound.putInt("CapacityEnchantment", capacityEnchantLevel); - if (this.customName != null) - compound.putString("CustomName", Component.Serializer.toJson(this.customName)); - compound.put("Enchantments", enchantmentTag); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - super.read(compound, clientPacket); - int prev = airLevel; - capacityEnchantLevel = compound.getInt("CapacityEnchantment"); - airLevel = compound.getInt("Air"); - airLevelTimer = compound.getInt("Timer"); - enchantmentTag = compound.getList("Enchantments", Tag.TAG_COMPOUND); - if (compound.contains("CustomName", 8)) - this.customName = Component.Serializer.fromJson(compound.getString("CustomName")); - if (prev != 0 && prev != airLevel && airLevel == BackTankUtil.maxAir(capacityEnchantLevel) && clientPacket) - playFilledEffect(); - } - - protected void playFilledEffect() { - AllSoundEvents.CONFIRM.playAt(level, worldPosition, 0.4f, 1, true); - Vec3 baseMotion = new Vec3(.25, 0.1, 0); - Vec3 baseVec = VecHelper.getCenterOf(worldPosition); - for (int i = 0; i < 360; i += 10) { - Vec3 m = VecHelper.rotate(baseMotion, i, Axis.Y); - Vec3 v = baseVec.add(m.normalize() - .scale(.25f)); - - level.addParticle(ParticleTypes.SPIT, v.x, v.y, v.z, m.x, m.y, m.z); - } - } - - @Override - public Component getName() { - return this.customName != null ? this.customName - : AllItems.COPPER_BACKTANK.get() - .getDescription(); - } - - public int getAirLevel() { - return airLevel; - } - - public void setAirLevel(int airLevel) { - this.airLevel = airLevel; - sendData(); - } - - public void setCustomName(Component customName) { - this.customName = customName; - } - - public Component getCustomName() { - return customName; - } - - public ListTag getEnchantmentTag() { - return enchantmentTag; - } - - public void setEnchantmentTag(ListTag enchantmentTag) { - this.enchantmentTag = enchantmentTag; - } - - public void setCapacityEnchantLevel(int capacityEnchantLevel) { - this.capacityEnchantLevel = capacityEnchantLevel; - } - -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/armor/DivingBootsItem.java b/src/main/java/com/simibubi/create/content/curiosities/armor/DivingBootsItem.java deleted file mode 100644 index 06c796e51..000000000 --- a/src/main/java/com/simibubi/create/content/curiosities/armor/DivingBootsItem.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.simibubi.create.content.curiosities.armor; - -import com.simibubi.create.AllItems; -import com.simibubi.create.foundation.utility.NBTHelper; - -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.Pose; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.event.entity.living.LivingEvent.LivingTickEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod.EventBusSubscriber; - -@EventBusSubscriber -public class DivingBootsItem extends CopperArmorItem { - - public DivingBootsItem(Properties p_i48534_3_) { - super(EquipmentSlot.FEET, p_i48534_3_); - } - - @SubscribeEvent - public static void accellerateDescentUnderwater(LivingTickEvent event) { - LivingEntity entity = event.getEntity(); - if (!affects(entity)) - return; - - Vec3 motion = entity.getDeltaMovement(); - boolean isJumping = entity.jumping; - entity.setOnGround(entity.isOnGround() || entity.verticalCollision); - - if (isJumping && entity.isOnGround()) { - motion = motion.add(0, .5f, 0); - entity.setOnGround(false); - } else { - motion = motion.add(0, -0.05f, 0); - } - - float multiplier = 1.3f; - if (motion.multiply(1, 0, 1) - .length() < 0.145f && (entity.zza > 0 || entity.xxa != 0) && !entity.isShiftKeyDown()) - motion = motion.multiply(multiplier, 1, multiplier); - entity.setDeltaMovement(motion); - } - - protected static boolean affects(LivingEntity entity) { - if (!AllItems.DIVING_BOOTS.get() - .isWornBy(entity)) { - entity.getPersistentData() - .remove("HeavyBoots"); - return false; - } - - NBTHelper.putMarker(entity.getPersistentData(), "HeavyBoots"); - if (!entity.isInWater()) - return false; - if (entity.getPose() == Pose.SWIMMING) - return false; - if (entity instanceof Player) { - Player playerEntity = (Player) entity; - if (playerEntity.getAbilities().flying) - return false; - } - return true; - } - -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/armor/DivingHelmetItem.java b/src/main/java/com/simibubi/create/content/curiosities/armor/DivingHelmetItem.java deleted file mode 100644 index 2dbfb2e1a..000000000 --- a/src/main/java/com/simibubi/create/content/curiosities/armor/DivingHelmetItem.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.simibubi.create.content.curiosities.armor; - -import com.simibubi.create.AllItems; -import com.simibubi.create.foundation.advancement.AllAdvancements; - -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.effect.MobEffects; -import net.minecraft.world.entity.EquipmentSlot; -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.minecraftforge.common.ForgeMod; -import net.minecraftforge.event.entity.living.LivingEvent.LivingTickEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod.EventBusSubscriber; - -@EventBusSubscriber -public class DivingHelmetItem extends CopperArmorItem { - - public DivingHelmetItem(Properties p_i48534_3_) { - super(EquipmentSlot.HEAD, p_i48534_3_); - } - - @SubscribeEvent - public static void breatheUnderwater(LivingTickEvent event) { - LivingEntity entity = event.getEntity(); - Level world = entity.level; - boolean second = world.getGameTime() % 20 == 0; - boolean drowning = entity.getAirSupply() == 0; - - if (world.isClientSide) - entity.getPersistentData() - .remove("VisualBacktankAir"); - - if (!AllItems.DIVING_HELMET.get() - .isWornBy(entity)) - return; - - boolean lavaDiving = entity.isEyeInFluidType(ForgeMod.LAVA_TYPE.get()); - if (!entity.canDrownInFluidType(entity.getEyeInFluidType()) && !lavaDiving) - return; - if (entity instanceof Player && ((Player) entity).isCreative()) - return; - - ItemStack backtank = BackTankUtil.get(entity); - if (backtank.isEmpty()) - return; - if (!BackTankUtil.hasAirRemaining(backtank)) - return; - - if (lavaDiving) { - if (entity instanceof ServerPlayer sp) - AllAdvancements.DIVING_SUIT_LAVA.awardTo(sp); - return; - } - - if (drowning) - entity.setAirSupply(10); - - if (world.isClientSide) - entity.getPersistentData() - .putInt("VisualBacktankAir", (int) BackTankUtil.getAir(backtank)); - - if (!second) - return; - - if (entity instanceof ServerPlayer sp) - AllAdvancements.DIVING_SUIT.awardTo(sp); - - entity.setAirSupply(Math.min(entity.getMaxAirSupply(), entity.getAirSupply() + 10)); - entity.addEffect(new MobEffectInstance(MobEffects.WATER_BREATHING, 30, 0, true, false, true)); - BackTankUtil.consumeAir(entity, backtank, 1); - } - -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/bell/AbstractBellTileEntity.java b/src/main/java/com/simibubi/create/content/curiosities/bell/AbstractBellTileEntity.java deleted file mode 100644 index 98aceda43..000000000 --- a/src/main/java/com/simibubi/create/content/curiosities/bell/AbstractBellTileEntity.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.simibubi.create.content.curiosities.bell; - -import java.util.List; - -import com.jozufozu.flywheel.core.PartialModel; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.utility.NBTHelper; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -public abstract class AbstractBellTileEntity extends SmartTileEntity { - - public static final int RING_DURATION = 74; - - public boolean isRinging; - public int ringingTicks; - public Direction ringDirection; - - public AbstractBellTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - @Override - public void addBehaviours(List behaviours) { } - - public boolean ring(Level world, BlockPos pos, Direction direction) { - isRinging = true; - ringingTicks = 0; - ringDirection = direction; - sendData(); - return true; - }; - - @Override - public void tick() { - super.tick(); - - if (isRinging) { - ++ringingTicks; - } - - if (ringingTicks >= RING_DURATION) { - isRinging = false; - ringingTicks = 0; - } - } - - @Override - protected void write(CompoundTag tag, boolean clientPacket) { - super.write(tag, clientPacket); - if (!clientPacket || ringingTicks != 0 || !isRinging) - return; - NBTHelper.writeEnum(tag, "Ringing", ringDirection); - } - - @Override - protected void read(CompoundTag tag, boolean clientPacket) { - super.read(tag, clientPacket); - if (!clientPacket || !tag.contains("Ringing")) - return; - ringDirection = NBTHelper.readEnum(tag, "Ringing", Direction.class); - ringingTicks = 0; - isRinging = true; - } - - @OnlyIn(Dist.CLIENT) - public abstract PartialModel getBellModel(); - -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/bell/BellRenderer.java b/src/main/java/com/simibubi/create/content/curiosities/bell/BellRenderer.java deleted file mode 100644 index 291a236fd..000000000 --- a/src/main/java/com/simibubi/create/content/curiosities/bell/BellRenderer.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.simibubi.create.content.curiosities.bell; - -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; -import com.simibubi.create.foundation.utility.AngleHelper; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.Direction; -import net.minecraft.util.Mth; -import net.minecraft.world.level.block.BellBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BellAttachType; - -public class BellRenderer extends SafeTileEntityRenderer { - - public BellRenderer(BlockEntityRendererProvider.Context context) { - } - - @Override - protected void renderSafe(TE te, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light, int overlay) { - BlockState state = te.getBlockState(); - Direction facing = state.getValue(BellBlock.FACING); - BellAttachType attachment = state.getValue(BellBlock.ATTACHMENT); - - SuperByteBuffer bell = CachedBufferer.partial(te.getBellModel(), state); - - if (te.isRinging) - bell.rotateCentered(te.ringDirection.getCounterClockWise(), getSwingAngle(te.ringingTicks + partialTicks)); - - float rY = AngleHelper.horizontalAngle(facing); - if (attachment == BellAttachType.SINGLE_WALL || attachment == BellAttachType.DOUBLE_WALL) - rY += 90; - bell.rotateCentered(Direction.UP, AngleHelper.rad(rY)); - - bell.light(light) - .renderInto(ms, buffer.getBuffer(RenderType.cutout())); - } - - public static float getSwingAngle(float time) { - float t = time / 1.5f; - return 1.2f * Mth.sin(t / (float) Math.PI) / (2.5f + t / 3.0f); - } - -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/bell/HauntedBellBlock.java b/src/main/java/com/simibubi/create/content/curiosities/bell/HauntedBellBlock.java deleted file mode 100644 index 4813daa13..000000000 --- a/src/main/java/com/simibubi/create/content/curiosities/bell/HauntedBellBlock.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.simibubi.create.content.curiosities.bell; - -import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.foundation.advancement.AllAdvancements; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; - -public class HauntedBellBlock extends AbstractBellBlock { - - public HauntedBellBlock(Properties properties) { - super(properties); - } - - @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.HAUNTED_BELL.get(); - } - - @Override - protected boolean ring(Level world, BlockPos pos, Direction direction, Player player) { - boolean ring = super.ring(world, pos, direction, player); - if (ring) - AllAdvancements.HAUNTED_BELL.awardTo(player); - return ring; - } - - @Override - public Class getTileEntityClass() { - return HauntedBellTileEntity.class; - } - - @Override - public void playSound(Level world, BlockPos pos) { - AllSoundEvents.HAUNTED_BELL_USE.playOnServer(world, pos, 4f, 1f); - } - - @Override - public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean isMoving) { - if (oldState.getBlock() != this && !world.isClientSide) - withTileEntityDo(world, pos, hbte -> { - hbte.effectTicks = HauntedBellTileEntity.EFFECT_TICKS; - hbte.sendData(); - }); - } - -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/bell/HauntedBellMovementBehaviour.java b/src/main/java/com/simibubi/create/content/curiosities/bell/HauntedBellMovementBehaviour.java deleted file mode 100644 index 4eeec2f61..000000000 --- a/src/main/java/com/simibubi/create/content/curiosities/bell/HauntedBellMovementBehaviour.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.simibubi.create.content.curiosities.bell; - -import com.simibubi.create.content.contraptions.components.actors.BellMovementBehaviour; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; - -import net.minecraft.core.BlockPos; - -public class HauntedBellMovementBehaviour extends BellMovementBehaviour { - - public static final int DISTANCE = 3; - - @Override - public void tick(MovementContext context) { - int recharge = getRecharge(context); - if (recharge > 0) - setRecharge(context, recharge - 1); - } - - @Override - public void visitNewPosition(MovementContext context, BlockPos pos) { - if (!context.world.isClientSide && getRecharge(context) == 0) { - HauntedBellPulser.sendPulse(context.world, pos, DISTANCE, false); - setRecharge(context, HauntedBellTileEntity.RECHARGE_TICKS); - playSound(context); - } - } - - @Override - public void writeExtraData(MovementContext context) { - context.tileData.putInt("Recharge", getRecharge(context)); - } - - private int getRecharge(MovementContext context) { - if (!(context.temporaryData instanceof Integer) && context.world != null) { - context.temporaryData = context.tileData.getInt("Recharge"); - } - return (Integer) context.temporaryData; - } - - private void setRecharge(MovementContext context, int value) { - context.temporaryData = value; - } - -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/bell/HauntedBellTileEntity.java b/src/main/java/com/simibubi/create/content/curiosities/bell/HauntedBellTileEntity.java deleted file mode 100644 index da99e9285..000000000 --- a/src/main/java/com/simibubi/create/content/curiosities/bell/HauntedBellTileEntity.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.simibubi.create.content.curiosities.bell; - -import com.jozufozu.flywheel.core.PartialModel; -import com.simibubi.create.AllBlockPartials; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.util.RandomSource; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -public class HauntedBellTileEntity extends AbstractBellTileEntity { - - public static final int DISTANCE = 10; - public static final int RECHARGE_TICKS = 65; - public static final int EFFECT_TICKS = 20; - - public int effectTicks = 0; - - public HauntedBellTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - @Override - @OnlyIn(Dist.CLIENT) - public PartialModel getBellModel() { - return AllBlockPartials.HAUNTED_BELL; - } - - @Override - public boolean ring(Level world, BlockPos pos, Direction direction) { - if (isRinging && ringingTicks < RECHARGE_TICKS) - return false; - HauntedBellPulser.sendPulse(world, pos, DISTANCE, false); - effectTicks = EFFECT_TICKS; - return super.ring(world, pos, direction); - } - - @Override - protected void write(CompoundTag compound, boolean clientPacket) { - super.write(compound, clientPacket); - compound.putInt("EffectTicks", effectTicks); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - super.read(compound, clientPacket); - effectTicks = compound.getInt("EffectTicks"); - } - - @Override - public void tick() { - super.tick(); - - if (effectTicks <= 0) - return; - effectTicks--; - - if (!level.isClientSide) - return; - - RandomSource rand = level.getRandom(); - if (rand.nextFloat() > 0.25f) - return; - - spawnParticle(rand); - playSound(rand); - } - - protected void spawnParticle(RandomSource rand) { - double x = worldPosition.getX() + rand.nextDouble(); - double y = worldPosition.getY() + 0.5; - double z = worldPosition.getZ() + rand.nextDouble(); - double vx = rand.nextDouble() * 0.04 - 0.02; - double vy = 0.1; - double vz = rand.nextDouble() * 0.04 - 0.02; - level.addParticle(ParticleTypes.SOUL, x, y, z, vx, vy, vz); - } - - protected void playSound(RandomSource rand) { - float vol = rand.nextFloat() * 0.4F + rand.nextFloat() > 0.9F ? 0.6F : 0.0F; - float pitch = 0.6F + rand.nextFloat() * 0.4F; - level.playSound(null, worldPosition, SoundEvents.SOUL_ESCAPE, SoundSource.BLOCKS, vol, pitch); - } - -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/bell/PeculiarBellTileEntity.java b/src/main/java/com/simibubi/create/content/curiosities/bell/PeculiarBellTileEntity.java deleted file mode 100644 index 07c521de9..000000000 --- a/src/main/java/com/simibubi/create/content/curiosities/bell/PeculiarBellTileEntity.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.simibubi.create.content.curiosities.bell; - -import com.jozufozu.flywheel.core.PartialModel; -import com.simibubi.create.AllBlockPartials; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -public class PeculiarBellTileEntity extends AbstractBellTileEntity { - - public PeculiarBellTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - @Override - @OnlyIn(Dist.CLIENT) - public PartialModel getBellModel() { - return AllBlockPartials.PECULIAR_BELL; - } - -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/deco/PlacardTileEntity.java b/src/main/java/com/simibubi/create/content/curiosities/deco/PlacardTileEntity.java deleted file mode 100644 index 23ddd47c1..000000000 --- a/src/main/java/com/simibubi/create/content/curiosities/deco/PlacardTileEntity.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.simibubi.create.content.curiosities.deco; - -import java.util.List; - -import org.joml.Vector3f; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.particles.DustParticleOptions; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; - -public class PlacardTileEntity extends SmartTileEntity { - - ItemStack heldItem; - int poweredTicks; - - public PlacardTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - heldItem = ItemStack.EMPTY; - poweredTicks = 0; - } - - @Override - public void tick() { - super.tick(); - if (level.isClientSide) - return; - if (poweredTicks == 0) - return; - - poweredTicks--; - if (poweredTicks > 0) - return; - - BlockState blockState = getBlockState(); - level.setBlock(worldPosition, blockState.setValue(PlacardBlock.POWERED, false), 3); - PlacardBlock.updateNeighbours(blockState, level, worldPosition); - } - - public ItemStack getHeldItem() { - return heldItem; - } - - public void setHeldItem(ItemStack heldItem) { - this.heldItem = heldItem; - notifyUpdate(); - } - - @Override - protected void write(CompoundTag tag, boolean clientPacket) { - tag.putInt("PoweredTicks", poweredTicks); - tag.put("Item", heldItem.serializeNBT()); - super.write(tag, clientPacket); - } - - @Override - protected void read(CompoundTag tag, boolean clientPacket) { - int prevTicks = poweredTicks; - poweredTicks = tag.getInt("PoweredTicks"); - heldItem = ItemStack.of(tag.getCompound("Item")); - super.read(tag, clientPacket); - - if (clientPacket && prevTicks < poweredTicks) - spawnParticles(); - } - - private void spawnParticles() { - BlockState blockState = getBlockState(); - if (!AllBlocks.PLACARD.has(blockState)) - return; - - DustParticleOptions pParticleData = new DustParticleOptions(new Vector3f(1, .2f, 0), 1); - Vec3 centerOf = VecHelper.getCenterOf(worldPosition); - Vec3 normal = Vec3.atLowerCornerOf(PlacardBlock.connectedDirection(blockState) - .getNormal()); - Vec3 offset = VecHelper.axisAlingedPlaneOf(normal); - - for (int i = 0; i < 10; i++) { - Vec3 v = VecHelper.offsetRandomly(Vec3.ZERO, level.random, .5f) - .multiply(offset) - .normalize() - .scale(.45f) - .add(normal.scale(-.45f)) - .add(centerOf); - level.addParticle(pParticleData, v.x, v.y, v.z, 0, 0, 0); - } - } - - @Override - public void addBehaviours(List behaviours) {} - -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/deco/SlidingDoorMovementBehaviour.java b/src/main/java/com/simibubi/create/content/curiosities/deco/SlidingDoorMovementBehaviour.java deleted file mode 100644 index 5e42e9b1a..000000000 --- a/src/main/java/com/simibubi/create/content/curiosities/deco/SlidingDoorMovementBehaviour.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.simibubi.create.content.curiosities.deco; - -import java.util.Map; - -import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; -import com.simibubi.create.content.logistics.trains.entity.CarriageContraptionEntity; -import com.simibubi.create.content.logistics.trains.entity.CarriageSyncData; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; - -import net.minecraft.core.BlockPos; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.world.level.block.DoorBlock; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; - -public class SlidingDoorMovementBehaviour implements MovementBehaviour { - - @Override - public boolean renderAsNormalTileEntity() { - return true; - } - - @Override - public void tick(MovementContext context) { - StructureBlockInfo structureBlockInfo = context.contraption.getBlocks() - .get(context.localPos); - if (structureBlockInfo == null) - return; - boolean open = SlidingDoorTileEntity.isOpen(structureBlockInfo.state); - - if (!context.world.isClientSide()) - tickOpen(context, open); - - Map tes = context.contraption.presentTileEntities; - if (!(tes.get(context.localPos) instanceof SlidingDoorTileEntity doorTE)) - return; - boolean wasSettled = doorTE.animation.settled(); - doorTE.animation.chase(open ? 1 : 0, .15f, Chaser.LINEAR); - doorTE.animation.tickChaser(); - - if (!wasSettled && doorTE.animation.settled() && !open) - context.world.playLocalSound(context.position.x, context.position.y, context.position.z, - SoundEvents.IRON_DOOR_CLOSE, SoundSource.BLOCKS, .125f, 1, false); - } - - protected void tickOpen(MovementContext context, boolean currentlyOpen) { - boolean shouldOpen = shouldOpen(context); - if (!shouldUpdate(context, shouldOpen)) - return; - if (currentlyOpen == shouldOpen) - return; - - BlockPos pos = context.localPos; - Contraption contraption = context.contraption; - - StructureBlockInfo info = contraption.getBlocks() - .get(pos); - if (info == null || !info.state.hasProperty(DoorBlock.OPEN)) - return; - - toggleDoor(pos, contraption, info); - - if (shouldOpen) - context.world.playSound(null, new BlockPos(context.position), SoundEvents.IRON_DOOR_OPEN, - SoundSource.BLOCKS, .125f, 1); - } - - private void toggleDoor(BlockPos pos, Contraption contraption, StructureBlockInfo info) { - BlockState newState = info.state.cycle(DoorBlock.OPEN); - contraption.entity.setBlock(pos, new StructureBlockInfo(info.pos, newState, info.nbt)); - - BlockPos otherPos = newState.getValue(DoorBlock.HALF) == DoubleBlockHalf.LOWER ? pos.above() : pos.below(); - info = contraption.getBlocks() - .get(otherPos); - if (info != null && info.state.hasProperty(DoorBlock.OPEN)) { - newState = info.state.cycle(DoorBlock.OPEN); - contraption.entity.setBlock(otherPos, new StructureBlockInfo(info.pos, newState, info.nbt)); - contraption.invalidateColliders(); - } - } - - protected boolean shouldUpdate(MovementContext context, boolean shouldOpen) { - if (context.firstMovement && shouldOpen) - return false; - if (!context.data.contains("Open")) { - context.data.putBoolean("Open", shouldOpen); - return true; - } - boolean wasOpen = context.data.getBoolean("Open"); - context.data.putBoolean("Open", shouldOpen); - return wasOpen != shouldOpen; - } - - protected boolean shouldOpen(MovementContext context) { - if (context.contraption.entity instanceof CarriageContraptionEntity cce) { - CarriageSyncData carriageData = cce.getCarriageData(); - if (Math.abs(carriageData.distanceToDestination) > 1) - return false; - } - return context.motion.length() < 1 / 128f && !context.contraption.entity.isStalled(); - } - -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/deco/SlidingDoorRenderer.java b/src/main/java/com/simibubi/create/content/curiosities/deco/SlidingDoorRenderer.java deleted file mode 100644 index 0b9ca3d86..000000000 --- a/src/main/java/com/simibubi/create/content/curiosities/deco/SlidingDoorRenderer.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.simibubi.create.content.curiosities.deco; - -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider.Context; -import net.minecraft.core.Direction; -import net.minecraft.util.Mth; -import net.minecraft.world.level.block.DoorBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.DoorHingeSide; -import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; -import net.minecraft.world.phys.Vec3; - -public class SlidingDoorRenderer extends SafeTileEntityRenderer { - - public SlidingDoorRenderer(Context context) {} - - @Override - protected void renderSafe(SlidingDoorTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - BlockState blockState = te.getBlockState(); - if (!te.shouldRenderSpecial(blockState)) - return; - - Direction facing = blockState.getValue(DoorBlock.FACING); - Direction movementDirection = facing.getClockWise(); - - if (blockState.getValue(DoorBlock.HINGE) == DoorHingeSide.LEFT) - movementDirection = movementDirection.getOpposite(); - - float value = te.animation.getValue(partialTicks); - float value2 = Mth.clamp(value * 10, 0, 1); - - Vec3 offset = Vec3.atLowerCornerOf(movementDirection.getNormal()) - .scale(value * value * 13 / 16f) - .add(Vec3.atLowerCornerOf(facing.getNormal()) - .scale(value2 * 1 / 32f)); - - VertexConsumer vb = buffer.getBuffer(RenderType.cutoutMipped()); - for (DoubleBlockHalf half : DoubleBlockHalf.values()) { - CachedBufferer.block(blockState.setValue(DoorBlock.OPEN, false) - .setValue(DoorBlock.HALF, half)) - .translate(0, half == DoubleBlockHalf.UPPER ? 1 - 1 / 512f : 0, 0) - .translate(offset) - .light(light) - .renderInto(ms, vb); - } - - } - -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/deco/SlidingDoorTileEntity.java b/src/main/java/com/simibubi/create/content/curiosities/deco/SlidingDoorTileEntity.java deleted file mode 100644 index 98d9f93f8..000000000 --- a/src/main/java/com/simibubi/create/content/curiosities/deco/SlidingDoorTileEntity.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.simibubi.create.content.curiosities.deco; - -import java.util.List; - -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; - -import net.minecraft.core.BlockPos; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.DoorBlock; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.AABB; - -public class SlidingDoorTileEntity extends SmartTileEntity { - - LerpedFloat animation; - int bridgeTicks; - boolean deferUpdate; - - public SlidingDoorTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - animation = LerpedFloat.linear() - .startWithValue(isOpen(state) ? 1 : 0); - } - - @Override - public void tick() { - if (deferUpdate && !level.isClientSide()) { - deferUpdate = false; - BlockState blockState = getBlockState(); - blockState.neighborChanged(level, worldPosition, Blocks.AIR, worldPosition, false); - } - - super.tick(); - boolean open = isOpen(getBlockState()); - boolean wasSettled = animation.settled(); - animation.chase(open ? 1 : 0, .15f, Chaser.LINEAR); - animation.tickChaser(); - - if (level.isClientSide()) { - if (bridgeTicks < 2 && open) - bridgeTicks++; - else if (bridgeTicks > 0 && !open && isVisible(getBlockState())) - bridgeTicks--; - return; - } - - if (!open && !wasSettled && animation.settled() && !isVisible(getBlockState())) - showBlockModel(); - } - - @Override - protected AABB createRenderBoundingBox() { - return super.createRenderBoundingBox().inflate(1); - } - - protected boolean isVisible(BlockState state) { - return state.getOptionalValue(SlidingDoorBlock.VISIBLE) - .orElse(true); - } - - protected boolean shouldRenderSpecial(BlockState state) { - return !isVisible(state) || bridgeTicks != 0; - } - - protected void showBlockModel() { - level.setBlock(worldPosition, getBlockState().setValue(SlidingDoorBlock.VISIBLE, true), 3); - level.playSound(null, worldPosition, SoundEvents.IRON_DOOR_CLOSE, SoundSource.BLOCKS, .5f, 1); - } - - @Override - public void addBehaviours(List behaviours) {} - - public static boolean isOpen(BlockState state) { - return state.getOptionalValue(DoorBlock.OPEN) - .orElse(false); - } - -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/symmetry/client/SymmetryWandItemRenderer.java b/src/main/java/com/simibubi/create/content/curiosities/symmetry/client/SymmetryWandItemRenderer.java deleted file mode 100644 index 11c5d1ebd..000000000 --- a/src/main/java/com/simibubi/create/content/curiosities/symmetry/client/SymmetryWandItemRenderer.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.simibubi.create.content.curiosities.symmetry.client; - -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.math.Axis; -import com.simibubi.create.foundation.item.render.CustomRenderedItemModelRenderer; -import com.simibubi.create.foundation.item.render.PartialItemModelRenderer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; - -import net.minecraft.client.renderer.LightTexture; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.block.model.ItemTransforms; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.util.Mth; -import net.minecraft.world.item.ItemStack; - -public class SymmetryWandItemRenderer extends CustomRenderedItemModelRenderer { - - @Override - protected void render(ItemStack stack, SymmetryWandModel model, PartialItemModelRenderer renderer, ItemTransforms.TransformType transformType, - PoseStack ms, MultiBufferSource buffer, int light, int overlay) { - float worldTime = AnimationTickHolder.getRenderTime() / 20; - int maxLight = LightTexture.FULL_BRIGHT; - - renderer.render(model.getOriginalModel(), light); - renderer.renderSolidGlowing(model.getPartial("core"), maxLight); - renderer.renderGlowing(model.getPartial("core_glow"), maxLight); - - float floating = Mth.sin(worldTime) * .05f; - float angle = worldTime * -10 % 360; - - ms.translate(0, floating, 0); - ms.mulPose(Axis.YP.rotationDegrees(angle)); - - renderer.renderGlowing(model.getPartial("bits"), maxLight); - } - - @Override - public SymmetryWandModel createModel(BakedModel originalModel) { - return new SymmetryWandModel(originalModel); - } - -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/symmetry/client/SymmetryWandModel.java b/src/main/java/com/simibubi/create/content/curiosities/symmetry/client/SymmetryWandModel.java deleted file mode 100644 index 233914a75..000000000 --- a/src/main/java/com/simibubi/create/content/curiosities/symmetry/client/SymmetryWandModel.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.simibubi.create.content.curiosities.symmetry.client; - -import com.simibubi.create.foundation.item.render.CreateCustomRenderedItemModel; - -import net.minecraft.client.resources.model.BakedModel; - -public class SymmetryWandModel extends CreateCustomRenderedItemModel { - - public SymmetryWandModel(BakedModel template) { - super(template, "wand_of_symmetry"); - addPartials("bits", "core", "core_glow"); - } - -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxContainer.java b/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxContainer.java deleted file mode 100644 index c7b5ddfe6..000000000 --- a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxContainer.java +++ /dev/null @@ -1,159 +0,0 @@ -package com.simibubi.create.content.curiosities.toolbox; - -import static com.simibubi.create.content.curiosities.toolbox.ToolboxInventory.STACKS_PER_COMPARTMENT; - -import com.simibubi.create.AllContainerTypes; -import com.simibubi.create.foundation.gui.container.ContainerBase; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.entity.player.Player; -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.minecraft.world.level.block.entity.BlockEntity; -import net.minecraftforge.items.SlotItemHandler; - -public class ToolboxContainer extends ContainerBase { - - public ToolboxContainer(MenuType type, int id, Inventory inv, FriendlyByteBuf extraData) { - super(type, id, inv, extraData); - } - - public ToolboxContainer(MenuType type, int id, Inventory inv, ToolboxTileEntity te) { - super(type, id, inv, te); - te.startOpen(player); - } - - public static ToolboxContainer create(int id, Inventory inv, ToolboxTileEntity te) { - return new ToolboxContainer(AllContainerTypes.TOOLBOX.get(), id, inv, te); - } - - @Override - protected ToolboxTileEntity createOnClient(FriendlyByteBuf extraData) { - BlockPos readBlockPos = extraData.readBlockPos(); - CompoundTag readNbt = extraData.readNbt(); - - ClientLevel world = Minecraft.getInstance().level; - BlockEntity tileEntity = world.getBlockEntity(readBlockPos); - if (tileEntity instanceof ToolboxTileEntity) { - ToolboxTileEntity toolbox = (ToolboxTileEntity) tileEntity; - toolbox.readClient(readNbt); - return toolbox; - } - - return null; - } - - @Override - public ItemStack quickMoveStack(Player player, int index) { - Slot clickedSlot = getSlot(index); - if (!clickedSlot.hasItem()) - return ItemStack.EMPTY; - - ItemStack stack = clickedSlot.getItem(); - int size = contentHolder.inventory.getSlots(); - boolean success = false; - if (index < size) { - success = !moveItemStackTo(stack, size, slots.size(), false); - contentHolder.inventory.onContentsChanged(index); - } else - success = !moveItemStackTo(stack, 0, size - 1, false); - - return success ? ItemStack.EMPTY : stack; - } - - @Override - protected void initAndReadInventory(ToolboxTileEntity contentHolder) { - - } - - @Override - public void clicked(int index, int flags, ClickType type, Player player) { - int size = contentHolder.inventory.getSlots(); - - if (index >= 0 && index < size) { - ItemStack itemInClickedSlot = getSlot(index).getItem(); - ItemStack carried = getCarried(); - - if (type == ClickType.PICKUP && !carried.isEmpty() && !itemInClickedSlot.isEmpty() - && ToolboxInventory.canItemsShareCompartment(itemInClickedSlot, carried)) { - int subIndex = index % STACKS_PER_COMPARTMENT; - if (subIndex != STACKS_PER_COMPARTMENT - 1) { - clicked(index - subIndex + STACKS_PER_COMPARTMENT - 1, flags, type, player); - return; - } - } - - if (type == ClickType.PICKUP && carried.isEmpty() && itemInClickedSlot.isEmpty()) - if (!player.level.isClientSide) { - contentHolder.inventory.filters.set(index / STACKS_PER_COMPARTMENT, ItemStack.EMPTY); - contentHolder.sendData(); - } - - } - super.clicked(index, flags, type, player); - } - - @Override - public boolean canDragTo(Slot slot) { - return slot.index > contentHolder.inventory.getSlots() && super.canDragTo(slot); - } - - public ItemStack getFilter(int compartment) { - return contentHolder.inventory.filters.get(compartment); - } - - public int totalCountInCompartment(int compartment) { - int count = 0; - int baseSlot = compartment * STACKS_PER_COMPARTMENT; - for (int i = 0; i < STACKS_PER_COMPARTMENT; i++) - count += getSlot(baseSlot + i).getItem() - .getCount(); - return count; - } - - public boolean renderPass; - - @Override - protected void addSlots() { - ToolboxInventory inventory = contentHolder.inventory; - - int x = 79; - int y = 37; - - int[] xOffsets = { x, x + 33, x + 66, x + 66 + 6, x + 66, x + 33, x, x - 6 }; - int[] yOffsets = { y, y - 6, y, y + 33, y + 66, y + 66 + 6, y + 66, y + 33 }; - - for (int compartment = 0; compartment < 8; compartment++) { - int baseIndex = compartment * STACKS_PER_COMPARTMENT; - - // Representative Slots - addSlot(new ToolboxSlot(this, inventory, baseIndex, xOffsets[compartment], yOffsets[compartment])); - - // Hidden Slots - for (int i = 1; i < STACKS_PER_COMPARTMENT; i++) - addSlot(new SlotItemHandler(inventory, baseIndex + i, -10000, -10000)); - } - - addPlayerSlots(8, 165); - } - - @Override - protected void saveData(ToolboxTileEntity contentHolder) { - - } - - @Override - public void removed(Player playerIn) { - super.removed(playerIn); - if (!playerIn.level.isClientSide) - contentHolder.stopOpen(playerIn); - } - -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxRenderer.java b/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxRenderer.java deleted file mode 100644 index 86912a652..000000000 --- a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxRenderer.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.simibubi.create.content.curiosities.toolbox; - -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.tileEntity.renderer.SmartTileEntityRenderer; -import com.simibubi.create.foundation.utility.Iterate; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.Direction; -import net.minecraft.world.level.block.state.BlockState; - -public class ToolboxRenderer extends SmartTileEntityRenderer { - - public ToolboxRenderer(BlockEntityRendererProvider.Context context) { - super(context); - } - - @Override - protected void renderSafe(ToolboxTileEntity tileEntityIn, float partialTicks, PoseStack ms, - MultiBufferSource buffer, int light, int overlay) { - - BlockState blockState = tileEntityIn.getBlockState(); - Direction facing = blockState.getValue(ToolboxBlock.FACING) - .getOpposite(); - SuperByteBuffer lid = - CachedBufferer.partial(AllBlockPartials.TOOLBOX_LIDS.get(tileEntityIn.getColor()), blockState); - SuperByteBuffer drawer = CachedBufferer.partial(AllBlockPartials.TOOLBOX_DRAWER, blockState); - - float lidAngle = tileEntityIn.lid.getValue(partialTicks); - float drawerOffset = tileEntityIn.drawers.getValue(partialTicks); - - VertexConsumer builder = buffer.getBuffer(RenderType.cutoutMipped()); - lid.centre() - .rotateY(-facing.toYRot()) - .unCentre() - .translate(0, 6 / 16f, 12 / 16f) - .rotateX(135 * lidAngle) - .translate(0, -6 / 16f, -12 / 16f) - .light(light) - .renderInto(ms, builder); - - for (int offset : Iterate.zeroAndOne) { - drawer.centre() - .rotateY(-facing.toYRot()) - .unCentre() - .translate(0, offset * 1 / 8f, -drawerOffset * .175f * (2 - offset)) - .light(light) - .renderInto(ms, builder); - } - - } - -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxSlot.java b/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxSlot.java deleted file mode 100644 index b14d0573f..000000000 --- a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxSlot.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.simibubi.create.content.curiosities.toolbox; - -import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.SlotItemHandler; - -public class ToolboxSlot extends SlotItemHandler { - - private ToolboxContainer toolboxMenu; - - public ToolboxSlot(ToolboxContainer container, IItemHandler itemHandler, int index, int xPosition, int yPosition) { - super(itemHandler, index, xPosition, yPosition); - this.toolboxMenu = container; - } - - @Override - public boolean isActive() { - return !toolboxMenu.renderPass && super.isActive(); - } - -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxTileEntity.java b/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxTileEntity.java deleted file mode 100644 index 489ad92b4..000000000 --- a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxTileEntity.java +++ /dev/null @@ -1,421 +0,0 @@ -package com.simibubi.create.content.curiosities.toolbox; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.UUID; -import java.util.WeakHashMap; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.utility.ResetableLazy; -import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; - -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.ServerPlayer; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.world.MenuProvider; -import net.minecraft.world.Nameable; -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.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.ItemHandlerHelper; - -public class ToolboxTileEntity extends SmartTileEntity implements MenuProvider, Nameable { - - public LerpedFloat lid = LerpedFloat.linear() - .startWithValue(0); - - public LerpedFloat drawers = LerpedFloat.linear() - .startWithValue(0); - - UUID uniqueId; - ToolboxInventory inventory; - LazyOptional inventoryProvider; - ResetableLazy colorProvider; - protected int openCount; - - Map> connectedPlayers; - - private Component customName; - - public ToolboxTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - connectedPlayers = new HashMap<>(); - inventory = new ToolboxInventory(this); - inventoryProvider = LazyOptional.of(() -> inventory); - colorProvider = ResetableLazy.of(() -> { - BlockState blockState = getBlockState(); - if (blockState != null && blockState.getBlock() instanceof ToolboxBlock) - return ((ToolboxBlock) blockState.getBlock()).getColor(); - return DyeColor.BROWN; - }); - setLazyTickRate(10); - } - - public DyeColor getColor() { - return colorProvider.get(); - } - - @Override - public void addBehaviours(List behaviours) {} - - @Override - public void initialize() { - super.initialize(); - ToolboxHandler.onLoad(this); - } - - @Override - public void invalidate() { - super.invalidate(); - ToolboxHandler.onUnload(this); - } - - @Override - public void tick() { - super.tick(); - - if (level.isClientSide) - tickAudio(); - if (!level.isClientSide) - tickPlayers(); - - lid.chase(openCount > 0 ? 1 : 0, 0.2f, Chaser.LINEAR); - drawers.chase(openCount > 0 ? 1 : 0, 0.2f, Chaser.EXP); - lid.tickChaser(); - drawers.tickChaser(); - } - - private void tickPlayers() { - boolean update = false; - - for (Iterator>> toolboxSlots = connectedPlayers.entrySet() - .iterator(); toolboxSlots.hasNext();) { - - Entry> toolboxSlotEntry = toolboxSlots.next(); - WeakHashMap set = toolboxSlotEntry.getValue(); - int slot = toolboxSlotEntry.getKey(); - - ItemStack referenceItem = inventory.filters.get(slot); - boolean clear = referenceItem.isEmpty(); - - for (Iterator> playerEntries = set.entrySet() - .iterator(); playerEntries.hasNext();) { - Entry playerEntry = playerEntries.next(); - - Player player = playerEntry.getKey(); - int hotbarSlot = playerEntry.getValue(); - - if (!clear && !ToolboxHandler.withinRange(player, this)) - continue; - - Inventory playerInv = player.getInventory(); - ItemStack playerStack = playerInv.getItem(hotbarSlot); - - if (clear || !playerStack.isEmpty() - && !ToolboxInventory.canItemsShareCompartment(playerStack, referenceItem)) { - player.getPersistentData() - .getCompound("CreateToolboxData") - .remove(String.valueOf(hotbarSlot)); - playerEntries.remove(); - if (player instanceof ServerPlayer) - ToolboxHandler.syncData(player); - continue; - } - - int count = playerStack.getCount(); - int targetAmount = (referenceItem.getMaxStackSize() + 1) / 2; - - if (count < targetAmount) { - int amountToReplenish = targetAmount - count; - - if (isOpenInContainer(player)) { - ItemStack extracted = inventory.takeFromCompartment(amountToReplenish, slot, true); - if (!extracted.isEmpty()) { - ToolboxHandler.unequip(player, hotbarSlot, false); - ToolboxHandler.syncData(player); - continue; - } - } - - ItemStack extracted = inventory.takeFromCompartment(amountToReplenish, slot, false); - if (!extracted.isEmpty()) { - update = true; - ItemStack template = playerStack.isEmpty() ? extracted : playerStack; - playerInv.setItem(hotbarSlot, - ItemHandlerHelper.copyStackWithSize(template, count + extracted.getCount())); - } - } - - if (count > targetAmount) { - int amountToDeposit = count - targetAmount; - ItemStack toDistribute = ItemHandlerHelper.copyStackWithSize(playerStack, amountToDeposit); - - if (isOpenInContainer(player)) { - int deposited = amountToDeposit - inventory.distributeToCompartment(toDistribute, slot, true) - .getCount(); - if (deposited > 0) { - ToolboxHandler.unequip(player, hotbarSlot, true); - ToolboxHandler.syncData(player); - continue; - } - } - - int deposited = amountToDeposit - inventory.distributeToCompartment(toDistribute, slot, false) - .getCount(); - if (deposited > 0) { - update = true; - playerInv.setItem(hotbarSlot, - ItemHandlerHelper.copyStackWithSize(playerStack, count - deposited)); - } - } - } - - if (clear) - toolboxSlots.remove(); - } - - if (update) - - sendData(); - - } - - private boolean isOpenInContainer(Player player) { - return player.containerMenu instanceof ToolboxContainer - && ((ToolboxContainer) player.containerMenu).contentHolder == this; - } - - public void unequipTracked() { - if (level.isClientSide) - return; - - Set affected = new HashSet<>(); - - for (Iterator>> toolboxSlots = connectedPlayers.entrySet() - .iterator(); toolboxSlots.hasNext();) { - - Entry> toolboxSlotEntry = toolboxSlots.next(); - WeakHashMap set = toolboxSlotEntry.getValue(); - - for (Iterator> playerEntries = set.entrySet() - .iterator(); playerEntries.hasNext();) { - Entry playerEntry = playerEntries.next(); - - Player player = playerEntry.getKey(); - int hotbarSlot = playerEntry.getValue(); - - ToolboxHandler.unequip(player, hotbarSlot, false); - if (player instanceof ServerPlayer) - affected.add((ServerPlayer) player); - } - } - - for (ServerPlayer player : affected) - ToolboxHandler.syncData(player); - connectedPlayers.clear(); - } - - public void unequip(int slot, Player player, int hotbarSlot, boolean keepItems) { - if (!connectedPlayers.containsKey(slot)) - return; - connectedPlayers.get(slot) - .remove(player); - if (keepItems) - return; - - Inventory playerInv = player.getInventory(); - ItemStack playerStack = playerInv.getItem(hotbarSlot); - ItemStack toInsert = ToolboxInventory.cleanItemNBT(playerStack.copy()); - ItemStack remainder = inventory.distributeToCompartment(toInsert, slot, false); - - if (remainder.getCount() != toInsert.getCount()) - playerInv.setItem(hotbarSlot, remainder); - } - - private void tickAudio() { - Vec3 vec = VecHelper.getCenterOf(worldPosition); - if (lid.settled()) { - if (openCount > 0 && lid.getChaseTarget() == 0) { - level.playLocalSound(vec.x, vec.y, vec.z, SoundEvents.IRON_DOOR_OPEN, SoundSource.BLOCKS, 0.25F, - level.random.nextFloat() * 0.1F + 1.2F, true); - level.playLocalSound(vec.x, vec.y, vec.z, SoundEvents.CHEST_OPEN, SoundSource.BLOCKS, 0.1F, - level.random.nextFloat() * 0.1F + 1.1F, true); - } - if (openCount == 0 && lid.getChaseTarget() == 1) - level.playLocalSound(vec.x, vec.y, vec.z, SoundEvents.CHEST_CLOSE, SoundSource.BLOCKS, 0.1F, - level.random.nextFloat() * 0.1F + 1.1F, true); - - } else if (openCount == 0 && lid.getChaseTarget() == 0 && lid.getValue(0) > 1 / 16f - && lid.getValue(1) < 1 / 16f) - level.playLocalSound(vec.x, vec.y, vec.z, SoundEvents.IRON_DOOR_CLOSE, SoundSource.BLOCKS, 0.25F, - level.random.nextFloat() * 0.1F + 1.2F, true); - } - - @Override - public LazyOptional getCapability(Capability cap, Direction side) { - if (isItemHandlerCap(cap)) - return inventoryProvider.cast(); - return super.getCapability(cap, side); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - inventory.deserializeNBT(compound.getCompound("Inventory")); - super.read(compound, clientPacket); - if (compound.contains("UniqueId", 11)) - this.uniqueId = compound.getUUID("UniqueId"); - if (compound.contains("CustomName", 8)) - this.customName = Component.Serializer.fromJson(compound.getString("CustomName")); - if (clientPacket) - openCount = compound.getInt("OpenCount"); - } - - @Override - protected void write(CompoundTag compound, boolean clientPacket) { - if (uniqueId == null) - uniqueId = UUID.randomUUID(); - - compound.put("Inventory", inventory.serializeNBT()); - compound.putUUID("UniqueId", uniqueId); - - if (customName != null) - compound.putString("CustomName", Component.Serializer.toJson(customName)); - super.write(compound, clientPacket); - if (clientPacket) - compound.putInt("OpenCount", openCount); - } - - @Override - public AbstractContainerMenu createMenu(int id, Inventory inv, Player player) { - return ToolboxContainer.create(id, inv, this); - } - - @Override - public void lazyTick() { - updateOpenCount(); - // keep re-advertising active TEs - ToolboxHandler.onLoad(this); - super.lazyTick(); - } - - void updateOpenCount() { - if (level.isClientSide) - return; - if (openCount == 0) - return; - - int prevOpenCount = openCount; - openCount = 0; - - for (Player playerentity : level.getEntitiesOfClass(Player.class, new AABB(worldPosition).inflate(8))) - if (playerentity.containerMenu instanceof ToolboxContainer - && ((ToolboxContainer) playerentity.containerMenu).contentHolder == this) - openCount++; - - if (prevOpenCount != openCount) - sendData(); - } - - public void startOpen(Player player) { - if (player.isSpectator()) - return; - if (openCount < 0) - openCount = 0; - openCount++; - sendData(); - } - - public void stopOpen(Player player) { - if (player.isSpectator()) - return; - openCount--; - sendData(); - } - - public void connectPlayer(int slot, Player player, int hotbarSlot) { - if (level.isClientSide) - return; - WeakHashMap map = connectedPlayers.computeIfAbsent(slot, WeakHashMap::new); - Integer previous = map.get(player); - if (previous != null) { - if (previous == hotbarSlot) - return; - ToolboxHandler.unequip(player, previous, false); - } - map.put(player, hotbarSlot); - } - - public void readInventory(CompoundTag compound) { - inventory.deserializeNBT(compound); - } - - public void setUniqueId(UUID uniqueId) { - this.uniqueId = uniqueId; - } - - public UUID getUniqueId() { - return uniqueId; - } - - public boolean isFullyInitialized() { - // returns true when uniqueId has been initialized - return uniqueId != null; - } - - public void setCustomName(Component customName) { - this.customName = customName; - } - - @Override - public Component getDisplayName() { - return customName != null ? customName - : AllBlocks.TOOLBOXES.get(getColor()) - .get() - .getName(); - } - - @Override - public Component getCustomName() { - return customName; - } - - @Override - public boolean hasCustomName() { - return customName != null; - } - - @Override - public Component getName() { - return customName; - } - - @SuppressWarnings("deprecation") - @Override - public void setBlockState(BlockState state) { - super.setBlockState(state); - colorProvider.reset(); - } - -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintAssignCompleteRecipePacket.java b/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintAssignCompleteRecipePacket.java deleted file mode 100644 index ec87a05c6..000000000 --- a/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintAssignCompleteRecipePacket.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.simibubi.create.content.curiosities.tools; - -import java.util.function.Supplier; - -import com.simibubi.create.foundation.networking.SimplePacketBase; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerPlayer; -import net.minecraftforge.network.NetworkEvent.Context; - -public class BlueprintAssignCompleteRecipePacket extends SimplePacketBase { - - private ResourceLocation recipeID; - - public BlueprintAssignCompleteRecipePacket(ResourceLocation recipeID) { - this.recipeID = recipeID; - } - - public BlueprintAssignCompleteRecipePacket(FriendlyByteBuf buffer) { - recipeID = buffer.readResourceLocation(); - } - - @Override - public void write(FriendlyByteBuf buffer) { - buffer.writeResourceLocation(recipeID); - } - - @Override - public void handle(Supplier context) { - context.get() - .enqueueWork(() -> { - ServerPlayer player = context.get() - .getSender(); - if (player == null) - return; - if (player.containerMenu instanceof BlueprintContainer) { - BlueprintContainer c = (BlueprintContainer) player.containerMenu; - player.getLevel() - .getRecipeManager() - .byKey(recipeID) - .ifPresent(r -> BlueprintItem.assignCompleteRecipe(c.ghostInventory, r)); - } - }); - context.get() - .setPacketHandled(true); - } - -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintContainer.java b/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintContainer.java deleted file mode 100644 index 78c43e52c..000000000 --- a/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintContainer.java +++ /dev/null @@ -1,179 +0,0 @@ -package com.simibubi.create.content.curiosities.tools; - -import java.util.Optional; - -import com.simibubi.create.AllContainerTypes; -import com.simibubi.create.content.curiosities.tools.BlueprintEntity.BlueprintSection; -import com.simibubi.create.foundation.gui.container.GhostItemContainer; - -import net.minecraft.client.Minecraft; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.Entity; -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.CraftingContainer; -import net.minecraft.world.inventory.MenuType; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.CraftingRecipe; -import net.minecraft.world.item.crafting.RecipeType; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.ItemStackHandler; -import net.minecraftforge.items.SlotItemHandler; - -public class BlueprintContainer extends GhostItemContainer { - - public BlueprintContainer(MenuType type, int id, Inventory inv, FriendlyByteBuf extraData) { - super(type, id, inv, extraData); - } - - public BlueprintContainer(MenuType type, int id, Inventory inv, BlueprintSection section) { - super(type, id, inv, section); - } - - public static BlueprintContainer create(int id, Inventory inv, BlueprintSection section) { - return new BlueprintContainer(AllContainerTypes.CRAFTING_BLUEPRINT.get(), id, inv, section); - } - - @Override - protected boolean allowRepeats() { - return true; - } - - @Override - protected void addSlots() { - addPlayerSlots(8, 131); - - int x = 29; - int y = 21; - int index = 0; - for (int row = 0; row < 3; ++row) - for (int col = 0; col < 3; ++col) - this.addSlot(new BlueprintCraftSlot(ghostInventory, index++, x + col * 18, y + row * 18)); - - addSlot(new BlueprintCraftSlot(ghostInventory, index++, 123, 40)); - addSlot(new SlotItemHandler(ghostInventory, index++, 135, 57)); - } - - public void onCraftMatrixChanged() { - if (contentHolder.getBlueprintWorld().isClientSide) - return; - - ServerPlayer serverplayerentity = (ServerPlayer) player; - CraftingContainer craftingInventory = new BlueprintCraftingInventory(this, ghostInventory); - Optional optional = player.getServer() - .getRecipeManager() - .getRecipeFor(RecipeType.CRAFTING, craftingInventory, player.getCommandSenderWorld()); - - if (!optional.isPresent()) { - if (ghostInventory.getStackInSlot(9) - .isEmpty()) - return; - if (!contentHolder.inferredIcon) - return; - - ghostInventory.setStackInSlot(9, ItemStack.EMPTY); - serverplayerentity.connection.send(new ClientboundContainerSetSlotPacket(containerId, incrementStateId(), 36 + 9, ItemStack.EMPTY)); - contentHolder.inferredIcon = false; - return; - } - - CraftingRecipe icraftingrecipe = optional.get(); - ItemStack itemstack = icraftingrecipe.assemble(craftingInventory); - ghostInventory.setStackInSlot(9, itemstack); - contentHolder.inferredIcon = true; - ItemStack toSend = itemstack.copy(); - toSend.getOrCreateTag() - .putBoolean("InferredFromRecipe", true); - serverplayerentity.connection.send(new ClientboundContainerSetSlotPacket(containerId, incrementStateId(), 36 + 9, toSend)); - } - - @Override - public void setItem(int slotId, int stateId, ItemStack stack) { - if (slotId == 36 + 9) { - if (stack.hasTag()) { - contentHolder.inferredIcon = stack.getTag() - .getBoolean("InferredFromRecipe"); - stack.getTag() - .remove("InferredFromRecipe"); - } else - contentHolder.inferredIcon = false; - } - super.setItem(slotId, stateId, stack); - } - - @Override - protected ItemStackHandler createGhostInventory() { - return contentHolder.getItems(); - } - - @Override - protected void initAndReadInventory(BlueprintSection contentHolder) { - super.initAndReadInventory(contentHolder); - } - - @Override - protected void saveData(BlueprintSection contentHolder) { - contentHolder.save(ghostInventory); - } - - @Override - @OnlyIn(Dist.CLIENT) - protected BlueprintSection createOnClient(FriendlyByteBuf extraData) { - int entityID = extraData.readVarInt(); - int section = extraData.readVarInt(); - Entity entityByID = Minecraft.getInstance().level.getEntity(entityID); - if (!(entityByID instanceof BlueprintEntity)) - return null; - BlueprintEntity blueprintEntity = (BlueprintEntity) entityByID; - BlueprintSection blueprintSection = blueprintEntity.getSection(section); - return blueprintSection; - } - - @Override - public boolean stillValid(Player player) { - return contentHolder != null && contentHolder.canPlayerUse(player); - } - - static class BlueprintCraftingInventory extends CraftingContainer { - - public BlueprintCraftingInventory(AbstractContainerMenu container, ItemStackHandler items) { - super(container, 3, 3); - for (int y = 0; y < 3; y++) { - for (int x = 0; x < 3; x++) { - ItemStack stack = items.getStackInSlot(y * 3 + x); - setItem(y * 3 + x, stack == null ? ItemStack.EMPTY : stack.copy()); - } - } - } - - } - - class BlueprintCraftSlot extends SlotItemHandler { - - private int index; - - public BlueprintCraftSlot(IItemHandler itemHandler, int index, int xPosition, int yPosition) { - super(itemHandler, index, xPosition, yPosition); - this.index = index; - } - - @Override - public void setChanged() { - super.setChanged(); - if (index == 9 && hasItem() && !contentHolder.getBlueprintWorld().isClientSide) { - contentHolder.inferredIcon = false; - ServerPlayer serverplayerentity = (ServerPlayer) player; - serverplayerentity.connection.send(new ClientboundContainerSetSlotPacket(containerId, incrementStateId(), 36 + 9, getItem())); - } - if (index < 9) - onCraftMatrixChanged(); - } - - } - -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripInteractionPacket.java b/src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripInteractionPacket.java deleted file mode 100644 index cf57bd455..000000000 --- a/src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripInteractionPacket.java +++ /dev/null @@ -1,85 +0,0 @@ -package com.simibubi.create.content.curiosities.tools; - -import java.util.function.Supplier; - -import com.simibubi.create.foundation.networking.SimplePacketBase; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.common.ForgeMod; -import net.minecraftforge.network.NetworkEvent.Context; - -public class ExtendoGripInteractionPacket extends SimplePacketBase { - - private InteractionHand interactionHand; - private int target; - private Vec3 specificPoint; - - public ExtendoGripInteractionPacket(Entity target) { - this(target, null); - } - - public ExtendoGripInteractionPacket(Entity target, InteractionHand hand) { - this(target, hand, null); - } - - public ExtendoGripInteractionPacket(Entity target, InteractionHand hand, Vec3 specificPoint) { - interactionHand = hand; - this.specificPoint = specificPoint; - this.target = target.getId(); - } - - public ExtendoGripInteractionPacket(FriendlyByteBuf buffer) { - target = buffer.readInt(); - int handId = buffer.readInt(); - interactionHand = handId == -1 ? null : InteractionHand.values()[handId]; - if (buffer.readBoolean()) - specificPoint = new Vec3(buffer.readDouble(), buffer.readDouble(), buffer.readDouble()); - } - - @Override - public void write(FriendlyByteBuf buffer) { - buffer.writeInt(target); - buffer.writeInt(interactionHand == null ? -1 : interactionHand.ordinal()); - buffer.writeBoolean(specificPoint != null); - if (specificPoint != null) { - buffer.writeDouble(specificPoint.x); - buffer.writeDouble(specificPoint.y); - buffer.writeDouble(specificPoint.z); - } - } - - @Override - public void handle(Supplier context) { - context.get() - .enqueueWork(() -> { - ServerPlayer sender = context.get() - .getSender(); - if (sender == null) - return; - Entity entityByID = sender.getLevel() - .getEntity(target); - if (entityByID != null && ExtendoGripItem.isHoldingExtendoGrip(sender)) { - double d = sender.getAttribute(ForgeMod.REACH_DISTANCE.get()) - .getValue(); - if (!sender.hasLineOfSight(entityByID)) - d -= 3; - d *= d; - if (sender.distanceToSqr(entityByID) > d) - return; - if (interactionHand == null) - sender.attack(entityByID); - else if (specificPoint == null) - sender.interactOn(entityByID, interactionHand); - else - entityByID.interactAt(sender, specificPoint, interactionHand); - } - }); - context.get() - .setPacketHandled(true); - } - -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripItemRenderer.java b/src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripItemRenderer.java deleted file mode 100644 index 4a5169e3e..000000000 --- a/src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripItemRenderer.java +++ /dev/null @@ -1,116 +0,0 @@ -package com.simibubi.create.content.curiosities.tools; - -import com.jozufozu.flywheel.util.transform.TransformStack; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.foundation.item.render.CustomRenderedItemModelRenderer; -import com.simibubi.create.foundation.item.render.PartialItemModelRenderer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.block.model.ItemTransforms.TransformType; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.util.Mth; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.phys.Vec3; - -public class ExtendoGripItemRenderer extends CustomRenderedItemModelRenderer { - - private static final Vec3 rotationOffset = new Vec3(0, 1 / 2f, 1 / 2f); - private static final Vec3 cogRotationOffset = new Vec3(0, 1 / 16f, 0); - - @Override - protected void render(ItemStack stack, ExtendoGripModel model, PartialItemModelRenderer renderer, TransformType transformType, - PoseStack ms, MultiBufferSource buffer, int light, int overlay) { - TransformStack stacker = TransformStack.cast(ms); - float animation = 0.25f; - boolean leftHand = transformType == TransformType.FIRST_PERSON_LEFT_HAND; - boolean rightHand = transformType == TransformType.FIRST_PERSON_RIGHT_HAND; - if (leftHand || rightHand) - animation = Mth.lerp(AnimationTickHolder.getPartialTicks(), - ExtendoGripRenderHandler.lastMainHandAnimation, - ExtendoGripRenderHandler.mainHandAnimation); - - animation = animation * animation * animation; - float extensionAngle = Mth.lerp(animation, 24f, 156f); - float halfAngle = extensionAngle / 2; - float oppositeAngle = 180 - extensionAngle; - - // grip - renderer.renderSolid(model.getOriginalModel(), light); - - // bits - ms.pushPose(); - ms.translate(0, 1 / 16f, -7 / 16f); - ms.scale(1, 1, 1 + animation); - ms.pushPose(); - stacker.rotateX(-halfAngle) - .translate(rotationOffset); - renderer.renderSolid(model.getPartial("thin_short"), light); - stacker.translateBack(rotationOffset); - - ms.translate(0, 5.5f / 16f, 0); - stacker.rotateX(-oppositeAngle) - .translate(rotationOffset); - renderer.renderSolid(model.getPartial("wide_long"), light); - stacker.translateBack(rotationOffset); - - ms.translate(0, 11 / 16f, 0); - stacker.rotateX(oppositeAngle) - .translate(rotationOffset); - ms.translate(0, 0.5f / 16f, 0); - renderer.renderSolid(model.getPartial("thin_short"), light); - stacker.translateBack(rotationOffset); - - ms.popPose(); - ms.pushPose(); - - stacker.rotateX(-180 + halfAngle) - .translate(rotationOffset); - renderer.renderSolid(model.getPartial("wide_short"), light); - stacker.translateBack(rotationOffset); - - ms.translate(0, 5.5f / 16f, 0); - stacker.rotateX(oppositeAngle) - .translate(rotationOffset); - renderer.renderSolid(model.getPartial("thin_long"), light); - stacker.translateBack(rotationOffset); - - ms.translate(0, 11 / 16f, 0); - stacker.rotateX(-oppositeAngle) - .translate(rotationOffset); - ms.translate(0, 0.5f / 16f, 0); - renderer.renderSolid(model.getPartial("wide_short"), light); - stacker.translateBack(rotationOffset); - - // hand - ms.translate(0, 5.5f / 16f, 0); - stacker.rotateX(180 - halfAngle) - .rotateY(180); - ms.translate(0, 0, -4 / 16f); - ms.scale(1, 1, 1 / (1 + animation)); - renderer.renderSolid((leftHand || rightHand) ? ExtendoGripRenderHandler.pose.get() - : AllBlockPartials.DEPLOYER_HAND_POINTING.get(), light); - ms.popPose(); - - ms.popPose(); - - // cog - ms.pushPose(); - float angle = AnimationTickHolder.getRenderTime() * -2; - if (leftHand || rightHand) - angle += 360 * animation; - angle %= 360; - stacker.translate(cogRotationOffset) - .rotateZ(angle) - .translateBack(cogRotationOffset); - renderer.renderSolid(model.getPartial("cog"), light); - ms.popPose(); - } - - @Override - public ExtendoGripModel createModel(BakedModel originalModel) { - return new ExtendoGripModel(originalModel); - } - -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripModel.java b/src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripModel.java deleted file mode 100644 index d09815874..000000000 --- a/src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripModel.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.simibubi.create.content.curiosities.tools; - -import com.simibubi.create.foundation.item.render.CreateCustomRenderedItemModel; - -import net.minecraft.client.resources.model.BakedModel; - -public class ExtendoGripModel extends CreateCustomRenderedItemModel { - - public ExtendoGripModel(BakedModel template) { - super(template, "extendo_grip"); - addPartials("cog", "thin_short", "wide_short", "thin_long", "wide_long"); - } - -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonModel.java b/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonModel.java deleted file mode 100644 index 12ed5200c..000000000 --- a/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonModel.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.simibubi.create.content.curiosities.weapons; - -import com.simibubi.create.foundation.item.render.CreateCustomRenderedItemModel; - -import net.minecraft.client.resources.model.BakedModel; - -public class PotatoCannonModel extends CreateCustomRenderedItemModel { - - public PotatoCannonModel(BakedModel template) { - super(template, "potato_cannon"); - addPartials("cog"); - } - -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/ShootGadgetPacket.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/ShootGadgetPacket.java deleted file mode 100644 index e5a7384ef..000000000 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/ShootGadgetPacket.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.simibubi.create.content.curiosities.zapper; - -import java.util.function.Supplier; - -import com.simibubi.create.foundation.networking.SimplePacketBase; - -import net.minecraft.client.Minecraft; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.network.NetworkEvent.Context; - -public abstract class ShootGadgetPacket extends SimplePacketBase { - - public Vec3 location; - public InteractionHand hand; - public boolean self; - - public ShootGadgetPacket(Vec3 location, InteractionHand hand, boolean self) { - this.location = location; - this.hand = hand; - this.self = self; - } - - public ShootGadgetPacket(FriendlyByteBuf buffer) { - hand = buffer.readBoolean() ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND; - self = buffer.readBoolean(); - location = new Vec3(buffer.readDouble(), buffer.readDouble(), buffer.readDouble()); - readAdditional(buffer); - } - - public final void write(FriendlyByteBuf buffer) { - buffer.writeBoolean(hand == InteractionHand.MAIN_HAND); - buffer.writeBoolean(self); - buffer.writeDouble(location.x); - buffer.writeDouble(location.y); - buffer.writeDouble(location.z); - writeAdditional(buffer); - } - - protected abstract void readAdditional(FriendlyByteBuf buffer); - - protected abstract void writeAdditional(FriendlyByteBuf buffer); - - @OnlyIn(Dist.CLIENT) - protected abstract void handleAdditional(); - - @OnlyIn(Dist.CLIENT) - protected abstract ShootableGadgetRenderHandler getHandler(); - - @Override - @OnlyIn(Dist.CLIENT) - public final void handle(Supplier context) { - context.get() - .enqueueWork(() -> { - Entity renderViewEntity = Minecraft.getInstance() - .getCameraEntity(); - if (renderViewEntity == null) - return; - if (renderViewEntity.position() - .distanceTo(location) > 100) - return; - - ShootableGadgetRenderHandler handler = getHandler(); - handleAdditional(); - if (self) - handler.shoot(hand, location); - else - handler.playSound(hand, location); - }); - context.get() - .setPacketHandled(true); - } - -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperItemRenderer.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperItemRenderer.java deleted file mode 100644 index 18728f550..000000000 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperItemRenderer.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.simibubi.create.content.curiosities.zapper.terrainzapper; - -import static java.lang.Math.max; - -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.math.Axis; -import com.simibubi.create.content.curiosities.zapper.ZapperItemRenderer; -import com.simibubi.create.foundation.item.render.PartialItemModelRenderer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.player.LocalPlayer; -import net.minecraft.client.renderer.LightTexture; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.block.model.ItemTransforms; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.util.Mth; -import net.minecraft.world.entity.HumanoidArm; -import net.minecraft.world.item.ItemStack; - -public class WorldshaperItemRenderer extends ZapperItemRenderer { - - @Override - protected void render(ItemStack stack, WorldshaperModel model, PartialItemModelRenderer renderer, ItemTransforms.TransformType transformType, - PoseStack ms, MultiBufferSource buffer, int light, int overlay) { - super.render(stack, model, renderer, transformType, ms, buffer, light, overlay); - - float pt = AnimationTickHolder.getPartialTicks(); - float worldTime = AnimationTickHolder.getRenderTime() / 20; - - renderer.renderSolid(model.getOriginalModel(), light); - - LocalPlayer player = Minecraft.getInstance().player; - boolean leftHanded = player.getMainArm() == HumanoidArm.LEFT; - boolean mainHand = player.getMainHandItem() == stack; - boolean offHand = player.getOffhandItem() == stack; - float animation = getAnimationProgress(pt, leftHanded, mainHand); - - // Core glows - float multiplier; - if (mainHand || offHand) - multiplier = animation; - else - multiplier = Mth.sin(worldTime * 5); - - int lightItensity = (int) (15 * Mth.clamp(multiplier, 0, 1)); - int glowLight = LightTexture.pack(lightItensity, max(lightItensity, 4)); - renderer.renderSolidGlowing(model.getPartial("core"), glowLight); - renderer.renderGlowing(model.getPartial("core_glow"), glowLight); - - // Accelerator spins - float angle = worldTime * -25; - if (mainHand || offHand) - angle += 360 * animation; - - angle %= 360; - float offset = -.155f; - ms.translate(0, offset, 0); - ms.mulPose(Axis.ZP.rotationDegrees(angle)); - ms.translate(0, -offset, 0); - renderer.render(model.getPartial("accelerator"), light); - } - - @Override - public WorldshaperModel createModel(BakedModel originalModel) { - return new WorldshaperModel(originalModel); - } - -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperModel.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperModel.java deleted file mode 100644 index 3253e3990..000000000 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperModel.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.simibubi.create.content.curiosities.zapper.terrainzapper; - -import com.simibubi.create.foundation.item.render.CreateCustomRenderedItemModel; - -import net.minecraft.client.resources.model.BakedModel; - -public class WorldshaperModel extends CreateCustomRenderedItemModel { - - public WorldshaperModel(BakedModel template) { - super(template, "handheld_worldshaper"); - addPartials("core", "core_glow", "accelerator"); - } - -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/deco/MetalLadderBlock.java b/src/main/java/com/simibubi/create/content/decoration/MetalLadderBlock.java similarity index 87% rename from src/main/java/com/simibubi/create/content/curiosities/deco/MetalLadderBlock.java rename to src/main/java/com/simibubi/create/content/decoration/MetalLadderBlock.java index a5c44f180..937ee38d1 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/deco/MetalLadderBlock.java +++ b/src/main/java/com/simibubi/create/content/decoration/MetalLadderBlock.java @@ -1,13 +1,13 @@ -package com.simibubi.create.content.curiosities.deco; +package com.simibubi.create.content.decoration; import java.util.function.Predicate; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; -import com.simibubi.create.content.curiosities.tools.ExtendoGripItem; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.utility.placement.IPlacementHelper; -import com.simibubi.create.foundation.utility.placement.PlacementHelpers; -import com.simibubi.create.foundation.utility.placement.PlacementOffset; +import com.simibubi.create.content.equipment.extendoGrip.ExtendoGripItem; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.foundation.placement.IPlacementHelper; +import com.simibubi.create.foundation.placement.PlacementHelpers; +import com.simibubi.create.foundation.placement.PlacementOffset; +import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; @@ -90,7 +90,7 @@ public class MetalLadderBlock extends LadderBlock implements IWrenchable { BlockHitResult ray) { Direction dir = player.getXRot() < 0 ? Direction.UP : Direction.DOWN; - int range = AllConfigs.SERVER.curiosities.placementAssistRange.get(); + int range = AllConfigs.server().equipment.placementAssistRange.get(); if (player != null) { AttributeInstance reach = player.getAttribute(ForgeMod.REACH_DISTANCE.get()); if (reach != null && reach.hasModifier(ExtendoGripItem.singleRangeAttributeModifier)) diff --git a/src/main/java/com/simibubi/create/content/decoration/MetalScaffoldingBlock.java b/src/main/java/com/simibubi/create/content/decoration/MetalScaffoldingBlock.java new file mode 100644 index 000000000..023af808a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/decoration/MetalScaffoldingBlock.java @@ -0,0 +1,87 @@ +package com.simibubi.create.content.decoration; + +import com.simibubi.create.AllShapes; +import com.simibubi.create.content.equipment.wrench.IWrenchable; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.ScaffoldingBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; + +public class MetalScaffoldingBlock extends ScaffoldingBlock implements IWrenchable { + + public MetalScaffoldingBlock(Properties pProperties) { + super(pProperties); + } + + @Override + public void tick(BlockState pState, ServerLevel pLevel, BlockPos pPos, RandomSource pRand) {} + + @Override + public boolean canSurvive(BlockState pState, LevelReader pLevel, BlockPos pPos) { + return true; + } + + @Override + public VoxelShape getCollisionShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, + CollisionContext pContext) { + if (pState.getValue(BOTTOM)) + return AllShapes.SCAFFOLD_HALF; + return super.getCollisionShape(pState, pLevel, pPos, pContext); + } + + @Override + public boolean isScaffolding(BlockState state, LevelReader level, BlockPos pos, LivingEntity entity) { + return true; + } + + @Override + public VoxelShape getShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, CollisionContext pContext) { + if (pState.getValue(BOTTOM)) + return AllShapes.SCAFFOLD_HALF; + if (!pContext.isHoldingItem(pState.getBlock() + .asItem())) + return AllShapes.SCAFFOLD_FULL; + return Shapes.block(); + } + + @Override + public VoxelShape getInteractionShape(BlockState pState, BlockGetter pLevel, BlockPos pPos) { + return Shapes.block(); + } + + @Override + public BlockState updateShape(BlockState pState, Direction pFacing, BlockState pFacingState, LevelAccessor pLevel, + BlockPos pCurrentPos, BlockPos pFacingPos) { + super.updateShape(pState, pFacing, pFacingState, pLevel, pCurrentPos, pFacingPos); + BlockState stateBelow = pLevel.getBlockState(pCurrentPos.below()); + return pFacing == Direction.DOWN ? pState.setValue(BOTTOM, + !stateBelow.is(this) && !stateBelow.isFaceSturdy(pLevel, pCurrentPos.below(), Direction.UP)) : pState; + } + + @Override + public boolean supportsExternalFaceHiding(BlockState state) { + return true; + } + + @Override + public boolean hidesNeighborFace(BlockGetter level, BlockPos pos, BlockState state, BlockState neighborState, + Direction dir) { + if (!(neighborState.getBlock() instanceof MetalScaffoldingBlock)) + return false; + if (!neighborState.getValue(BOTTOM) && state.getValue(BOTTOM)) + return false; + return dir.getAxis() != Axis.Y; + } + +} diff --git a/src/main/java/com/simibubi/create/content/decoration/MetalScaffoldingBlockItem.java b/src/main/java/com/simibubi/create/content/decoration/MetalScaffoldingBlockItem.java new file mode 100644 index 000000000..a8f45795f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/decoration/MetalScaffoldingBlockItem.java @@ -0,0 +1,72 @@ +package com.simibubi.create.content.decoration; + +import javax.annotation.Nullable; + +import net.minecraft.ChatFormatting; +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.entity.player.Player; +import net.minecraft.world.item.ScaffoldingBlockItem; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; + +public class MetalScaffoldingBlockItem extends ScaffoldingBlockItem { + + public MetalScaffoldingBlockItem(Block pBlock, Properties pProperties) { + super(pBlock, pProperties); + } + + @Nullable + public BlockPlaceContext updatePlacementContext(BlockPlaceContext pContext) { // TODO replace with placement helper + BlockPos blockpos = pContext.getClickedPos(); + Level level = pContext.getLevel(); + BlockState blockstate = level.getBlockState(blockpos); + Block block = this.getBlock(); + if (!blockstate.is(block)) + return pContext; + + Direction direction; + if (pContext.isSecondaryUseActive()) { + direction = pContext.isInside() ? pContext.getClickedFace() + .getOpposite() : pContext.getClickedFace(); + } else { + direction = pContext.getClickedFace() == Direction.UP ? pContext.getHorizontalDirection() : Direction.UP; + } + + int i = 0; + BlockPos.MutableBlockPos blockpos$mutableblockpos = blockpos.mutable() + .move(direction); + + while (i < 7) { + if (!level.isClientSide && !level.isInWorldBounds(blockpos$mutableblockpos)) { + Player player = pContext.getPlayer(); + int j = level.getMaxBuildHeight(); + if (player instanceof ServerPlayer sp && blockpos$mutableblockpos.getY() >= j) + sp.sendSystemMessage(Component.translatable("build.tooHigh", j - 1) + .withStyle(ChatFormatting.RED), true); + break; + } + + blockstate = level.getBlockState(blockpos$mutableblockpos); + if (!blockstate.is(this.getBlock())) { + if (blockstate.canBeReplaced(pContext)) { + return BlockPlaceContext.at(pContext, blockpos$mutableblockpos, direction); + } + break; + } + + blockpos$mutableblockpos.move(direction); + if (direction.getAxis() + .isHorizontal()) { + ++i; + } + } + + return null; + } + +} diff --git a/src/main/java/com/simibubi/create/content/decoration/MetalScaffoldingCTBehaviour.java b/src/main/java/com/simibubi/create/content/decoration/MetalScaffoldingCTBehaviour.java new file mode 100644 index 000000000..a85e7d2e1 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/decoration/MetalScaffoldingCTBehaviour.java @@ -0,0 +1,50 @@ +package com.simibubi.create.content.decoration; + +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry; +import com.simibubi.create.foundation.block.connected.HorizontalCTBehaviour; + +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.state.BlockState; + +public class MetalScaffoldingCTBehaviour extends HorizontalCTBehaviour { + + protected CTSpriteShiftEntry insideShift; + + public MetalScaffoldingCTBehaviour(CTSpriteShiftEntry outsideShift, CTSpriteShiftEntry insideShift, + CTSpriteShiftEntry topShift) { + super(outsideShift, topShift); + this.insideShift = insideShift; + } + + @Override + public boolean buildContextForOccludedDirections() { + return true; + } + + @Override + protected boolean isBeingBlocked(BlockState state, BlockAndTintGetter reader, BlockPos pos, BlockPos otherPos, + Direction face) { + return face.getAxis() == Axis.Y && super.isBeingBlocked(state, reader, pos, otherPos, face); + } + + @Override + public CTSpriteShiftEntry getShift(BlockState state, Direction direction, @Nullable TextureAtlasSprite sprite) { + if (direction.getAxis() != Axis.Y && sprite == insideShift.getOriginal()) + return insideShift; + return super.getShift(state, direction, sprite); + } + + @Override + public boolean connectsTo(BlockState state, BlockState other, BlockAndTintGetter reader, BlockPos pos, + BlockPos otherPos, Direction face) { + return super.connectsTo(state, other, reader, pos, otherPos, face) + && state.getValue(MetalScaffoldingBlock.BOTTOM) && other.getValue(MetalScaffoldingBlock.BOTTOM); + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/deco/TrainTrapdoorBlock.java b/src/main/java/com/simibubi/create/content/decoration/TrainTrapdoorBlock.java similarity index 89% rename from src/main/java/com/simibubi/create/content/curiosities/deco/TrainTrapdoorBlock.java rename to src/main/java/com/simibubi/create/content/decoration/TrainTrapdoorBlock.java index 7dd0f14d1..46795c69f 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/deco/TrainTrapdoorBlock.java +++ b/src/main/java/com/simibubi/create/content/decoration/TrainTrapdoorBlock.java @@ -1,6 +1,6 @@ -package com.simibubi.create.content.curiosities.deco; +package com.simibubi.create.content.decoration; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; +import com.simibubi.create.content.equipment.wrench.IWrenchable; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -38,8 +38,10 @@ public class TrainTrapdoorBlock extends TrapDoorBlock implements IWrenchable { } public static boolean isConnected(BlockState state, BlockState other, Direction pDirection) { - state = state.setValue(WATERLOGGED, false); - other = other.setValue(WATERLOGGED, false); + state = state.setValue(WATERLOGGED, false) + .setValue(POWERED, false); + other = other.setValue(WATERLOGGED, false) + .setValue(POWERED, false); boolean open = state.getValue(OPEN); Half half = state.getValue(HALF); diff --git a/src/main/java/com/simibubi/create/content/curiosities/deco/TrapdoorCTBehaviour.java b/src/main/java/com/simibubi/create/content/decoration/TrapdoorCTBehaviour.java similarity index 95% rename from src/main/java/com/simibubi/create/content/curiosities/deco/TrapdoorCTBehaviour.java rename to src/main/java/com/simibubi/create/content/decoration/TrapdoorCTBehaviour.java index 8856fa52e..1b1ea63cf 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/deco/TrapdoorCTBehaviour.java +++ b/src/main/java/com/simibubi/create/content/decoration/TrapdoorCTBehaviour.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.deco; +package com.simibubi.create.content.decoration; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/BracketBlock.java b/src/main/java/com/simibubi/create/content/decoration/bracket/BracketBlock.java similarity index 84% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/BracketBlock.java rename to src/main/java/com/simibubi/create/content/decoration/bracket/BracketBlock.java index 2d663dd90..52071130b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/BracketBlock.java +++ b/src/main/java/com/simibubi/create/content/decoration/bracket/BracketBlock.java @@ -1,12 +1,12 @@ -package com.simibubi.create.content.contraptions.fluids.pipes; +package com.simibubi.create.content.decoration.bracket; import java.util.Optional; -import com.simibubi.create.content.contraptions.base.DirectionalAxisKineticBlock; -import com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock; -import com.simibubi.create.content.contraptions.fluids.FluidPropagator; -import com.simibubi.create.content.contraptions.relays.elementary.AbstractSimpleShaftBlock; -import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock; +import com.simibubi.create.content.fluids.FluidPropagator; +import com.simibubi.create.content.kinetics.base.DirectionalAxisKineticBlock; +import com.simibubi.create.content.kinetics.base.RotatedPillarKineticBlock; +import com.simibubi.create.content.kinetics.simpleRelays.AbstractSimpleShaftBlock; +import com.simibubi.create.content.kinetics.simpleRelays.CogWheelBlock; import com.simibubi.create.foundation.block.WrenchableDirectionalBlock; import com.simibubi.create.foundation.utility.Lang; diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/BracketBlockItem.java b/src/main/java/com/simibubi/create/content/decoration/bracket/BracketBlockItem.java similarity index 86% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/BracketBlockItem.java rename to src/main/java/com/simibubi/create/content/decoration/bracket/BracketBlockItem.java index 71cfe2755..18ecd1522 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/BracketBlockItem.java +++ b/src/main/java/com/simibubi/create/content/decoration/bracket/BracketBlockItem.java @@ -1,9 +1,8 @@ -package com.simibubi.create.content.contraptions.fluids.pipes; +package com.simibubi.create.content.decoration.bracket; import java.util.Optional; -import com.simibubi.create.content.contraptions.relays.elementary.BracketedTileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -31,7 +30,7 @@ public class BracketBlockItem extends BlockItem { BracketBlock bracketBlock = getBracketBlock(); Player player = context.getPlayer(); - BracketedTileEntityBehaviour behaviour = TileEntityBehaviour.get(world, pos, BracketedTileEntityBehaviour.TYPE); + BracketedBlockEntityBehaviour behaviour = BlockEntityBehaviour.get(world, pos, BracketedBlockEntityBehaviour.TYPE); if (behaviour == null) return InteractionResult.FAIL; diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/BracketGenerator.java b/src/main/java/com/simibubi/create/content/decoration/bracket/BracketGenerator.java similarity index 96% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/BracketGenerator.java rename to src/main/java/com/simibubi/create/content/decoration/bracket/BracketGenerator.java index 4b11ad2c0..30a2b0142 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/BracketGenerator.java +++ b/src/main/java/com/simibubi/create/content/decoration/bracket/BracketGenerator.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.fluids.pipes; +package com.simibubi.create.content.decoration.bracket; import com.simibubi.create.foundation.data.DirectionalAxisBlockStateGen; import com.tterrag.registrate.builders.ItemBuilder; diff --git a/src/main/java/com/simibubi/create/content/decoration/bracket/BracketedBlockEntityBehaviour.java b/src/main/java/com/simibubi/create/content/decoration/bracket/BracketedBlockEntityBehaviour.java new file mode 100644 index 000000000..1e9a8c1d0 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/decoration/bracket/BracketedBlockEntityBehaviour.java @@ -0,0 +1,133 @@ +package com.simibubi.create.content.decoration.bracket; + +import java.util.function.Predicate; + +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.content.contraptions.StructureTransform; +import com.simibubi.create.content.schematics.requirement.ItemRequirement; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.NBTHelper; + +import net.minecraft.core.registries.Registries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; + +public class BracketedBlockEntityBehaviour extends BlockEntityBehaviour { + + public static final BehaviourType TYPE = new BehaviourType<>(); + + private BlockState bracket; + private boolean reRender; + + private Predicate pred; + + public BracketedBlockEntityBehaviour(SmartBlockEntity be) { + this(be, state -> true); + } + + public BracketedBlockEntityBehaviour(SmartBlockEntity be, Predicate pred) { + super(be); + this.pred = pred; + } + + @Override + public BehaviourType getType() { + return TYPE; + } + + public void applyBracket(BlockState state) { + this.bracket = state; + reRender = true; + blockEntity.notifyUpdate(); + Level world = getWorld(); + if (world.isClientSide) + return; + blockEntity.getBlockState() + .updateNeighbourShapes(world, getPos(), 3); + } + + public void transformBracket(StructureTransform transform) { + if (isBracketPresent()) { + BlockState transformedBracket = transform.apply(bracket); + applyBracket(transformedBracket); + } + } + + @Nullable + public BlockState removeBracket(boolean inOnReplacedContext) { + if (bracket == null) { + return null; + } + + BlockState removed = this.bracket; + Level world = getWorld(); + if (!world.isClientSide) + world.levelEvent(2001, getPos(), Block.getId(bracket)); + this.bracket = null; + reRender = true; + if (inOnReplacedContext) { + blockEntity.sendData(); + return removed; + } + blockEntity.notifyUpdate(); + if (world.isClientSide) + return removed; + blockEntity.getBlockState() + .updateNeighbourShapes(world, getPos(), 3); + return removed; + } + + public boolean isBracketPresent() { + return bracket != null; + } + + @Nullable + public BlockState getBracket() { + return bracket; + } + + public boolean canHaveBracket() { + return pred.test(blockEntity.getBlockState()); + } + + @Override + public ItemRequirement getRequiredItems() { + if (!isBracketPresent()) { + return ItemRequirement.NONE; + } + return ItemRequirement.of(bracket, null); + } + + @Override + public boolean isSafeNBT() { + return true; + } + + @Override + public void write(CompoundTag nbt, boolean clientPacket) { + if (isBracketPresent()) { + nbt.put("Bracket", NbtUtils.writeBlockState(bracket)); + } + if (clientPacket && reRender) { + NBTHelper.putMarker(nbt, "Redraw"); + reRender = false; + } + super.write(nbt, clientPacket); + } + + @Override + public void read(CompoundTag nbt, boolean clientPacket) { + if (nbt.contains("Bracket")) + bracket = NbtUtils.readBlockState(getWorld().holderLookup(Registries.BLOCK), nbt.getCompound("Bracket")); + if (clientPacket && nbt.contains("Redraw")) + getWorld().sendBlockUpdated(getPos(), blockEntity.getBlockState(), blockEntity.getBlockState(), 16); + super.read(nbt, clientPacket); + } + +} diff --git a/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatBarsModel.java b/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatBarsModel.java new file mode 100644 index 000000000..19c56d283 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatBarsModel.java @@ -0,0 +1,71 @@ +package com.simibubi.create.content.decoration.copycat; + +import java.util.ArrayList; +import java.util.List; + +import com.simibubi.create.foundation.block.render.SpriteShiftEntry; +import com.simibubi.create.foundation.model.BakedQuadHelper; + +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.client.model.data.ModelData; + +public class CopycatBarsModel extends CopycatModel { + + public CopycatBarsModel(BakedModel originalModel) { + super(originalModel); + } + + @Override + public boolean useAmbientOcclusion() { + return false; + } + + @Override + protected List getCroppedQuads(BlockState state, Direction side, RandomSource rand, BlockState material, + ModelData wrappedData, RenderType renderType) { + BakedModel model = getModelOf(material); + List templateQuads = model.getQuads(material, null, rand, wrappedData, renderType); + List superQuads = originalModel.getQuads(state, side, rand, wrappedData, renderType); + List quads = new ArrayList<>(); + TextureAtlasSprite targetSprite = model.getParticleIcon(wrappedData); + + boolean vertical = state.getValue(CopycatPanelBlock.FACING) + .getAxis() == Axis.Y; + + if (side != null && (vertical || side.getAxis() == Axis.Y)) + for (int i = 0; i < templateQuads.size(); i++) { + BakedQuad quad = templateQuads.get(i); + if (quad.getDirection() != Direction.UP) + continue; + targetSprite = quad.getSprite(); + break; + } + + if (targetSprite == null) + return superQuads; + + for (int i = 0; i < superQuads.size(); i++) { + BakedQuad quad = superQuads.get(i); + TextureAtlasSprite original = quad.getSprite(); + BakedQuad newQuad = BakedQuadHelper.clone(quad); + int[] vertexData = newQuad.getVertices(); + for (int vertex = 0; vertex < 4; vertex++) { + BakedQuadHelper.setU(vertexData, vertex, targetSprite + .getU(SpriteShiftEntry.getUnInterpolatedU(original, BakedQuadHelper.getU(vertexData, vertex)))); + BakedQuadHelper.setV(vertexData, vertex, targetSprite + .getV(SpriteShiftEntry.getUnInterpolatedV(original, BakedQuadHelper.getV(vertexData, vertex)))); + } + quads.add(newQuad); + } + + return quads; + } + +} diff --git a/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatBlock.java b/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatBlock.java new file mode 100644 index 000000000..bcaef4350 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatBlock.java @@ -0,0 +1,385 @@ +package com.simibubi.create.content.decoration.copycat; + +import javax.annotation.Nullable; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllTags.AllBlockTags; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.foundation.block.IBE; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.color.block.BlockColor; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.SpawnPlacements.Type; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.UseOnContext; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Explosion; +import net.minecraft.world.level.GrassColor; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelReader; +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.SoundType; +import net.minecraft.world.level.block.StairBlock; +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.properties.BlockStateProperties; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.client.model.data.ModelDataManager; + +public abstract class CopycatBlock extends Block implements IBE, IWrenchable { + + public CopycatBlock(Properties pProperties) { + super(pProperties); + } + + @Nullable + @Override + public BlockEntityTicker getTicker(Level p_153212_, BlockState p_153213_, + BlockEntityType p_153214_) { + return null; + } + + @Override + public InteractionResult onSneakWrenched(BlockState state, UseOnContext context) { + onWrenched(state, context); + return IWrenchable.super.onSneakWrenched(state, context); + } + + @Override + public InteractionResult onWrenched(BlockState state, UseOnContext context) { + return onBlockEntityUse(context.getLevel(), context.getClickedPos(), ufte -> { + ItemStack consumedItem = ufte.getConsumedItem(); + if (!ufte.hasCustomMaterial()) + return InteractionResult.PASS; + Player player = context.getPlayer(); + if (!player.isCreative()) + player.getInventory() + .placeItemBackInInventory(consumedItem); + context.getLevel() + .levelEvent(2001, context.getClickedPos(), Block.getId(ufte.getBlockState())); + ufte.setMaterial(AllBlocks.COPYCAT_BASE.getDefaultState()); + ufte.setConsumedItem(ItemStack.EMPTY); + return InteractionResult.SUCCESS; + }); + } + + @Override + public InteractionResult use(BlockState pState, Level pLevel, BlockPos pPos, Player pPlayer, InteractionHand pHand, + BlockHitResult pHit) { + + if (pPlayer == null) + return InteractionResult.PASS; + + Direction face = pHit.getDirection(); + ItemStack itemInHand = pPlayer.getItemInHand(pHand); + BlockState materialIn = getAcceptedBlockState(pLevel, pPos, itemInHand, face); + + if (materialIn != null) + materialIn = prepareMaterial(pLevel, pPos, pState, pPlayer, pHand, pHit, materialIn); + if (materialIn == null) + return InteractionResult.PASS; + + BlockState material = materialIn; + return onBlockEntityUse(pLevel, pPos, ufte -> { + if (ufte.getMaterial() + .is(material.getBlock())) { + if (!ufte.cycleMaterial()) + return InteractionResult.PASS; + ufte.getLevel() + .playSound(null, ufte.getBlockPos(), SoundEvents.ITEM_FRAME_ADD_ITEM, SoundSource.BLOCKS, .75f, + .95f); + return InteractionResult.SUCCESS; + } + if (ufte.hasCustomMaterial()) + return InteractionResult.PASS; + if (pLevel.isClientSide()) + return InteractionResult.SUCCESS; + + ufte.setMaterial(material); + ufte.setConsumedItem(itemInHand); + ufte.getLevel() + .playSound(null, ufte.getBlockPos(), material.getSoundType() + .getPlaceSound(), SoundSource.BLOCKS, 1, .75f); + + if (pPlayer.isCreative()) + return InteractionResult.SUCCESS; + + itemInHand.shrink(1); + if (itemInHand.isEmpty()) + pPlayer.setItemInHand(pHand, ItemStack.EMPTY); + return InteractionResult.SUCCESS; + }); + } + + @Override + public void setPlacedBy(Level pLevel, BlockPos pPos, BlockState pState, LivingEntity pPlacer, ItemStack pStack) { + if (pPlacer == null) + return; + ItemStack offhandItem = pPlacer.getItemInHand(InteractionHand.OFF_HAND); + BlockState appliedState = + getAcceptedBlockState(pLevel, pPos, offhandItem, Direction.orderedByNearest(pPlacer)[0]); + + if (appliedState == null) + return; + withBlockEntityDo(pLevel, pPos, ufte -> { + if (ufte.hasCustomMaterial()) + return; + + ufte.setMaterial(appliedState); + ufte.setConsumedItem(offhandItem); + + if (pPlacer instanceof Player player && player.isCreative()) + return; + offhandItem.shrink(1); + if (offhandItem.isEmpty()) + pPlacer.setItemInHand(InteractionHand.OFF_HAND, ItemStack.EMPTY); + }); + } + + @Nullable + public BlockState getAcceptedBlockState(Level pLevel, BlockPos pPos, ItemStack item, Direction face) { + if (!(item.getItem() instanceof BlockItem bi)) + return null; + + Block block = bi.getBlock(); + if (block instanceof CopycatBlock) + return null; + + BlockState appliedState = block.defaultBlockState(); + boolean hardCodedAllow = isAcceptedRegardless(appliedState); + + if (!AllBlockTags.COPYCAT_ALLOW.matches(block) && !hardCodedAllow) { + + if (AllBlockTags.COPYCAT_DENY.matches(block)) + return null; + if (block instanceof EntityBlock) + return null; + if (block instanceof StairBlock) + return null; + + if (pLevel != null) { + VoxelShape shape = appliedState.getShape(pLevel, pPos); + if (shape.isEmpty() || !shape.bounds() + .equals(Shapes.block() + .bounds())) + return null; + + VoxelShape collisionShape = appliedState.getCollisionShape(pLevel, pPos); + if (collisionShape.isEmpty()) + return null; + } + } + + if (face != null) { + Axis axis = face.getAxis(); + + if (appliedState.hasProperty(BlockStateProperties.FACING)) + appliedState = appliedState.setValue(BlockStateProperties.FACING, face); + if (appliedState.hasProperty(BlockStateProperties.HORIZONTAL_FACING) && axis != Axis.Y) + appliedState = appliedState.setValue(BlockStateProperties.HORIZONTAL_FACING, face); + if (appliedState.hasProperty(BlockStateProperties.AXIS)) + appliedState = appliedState.setValue(BlockStateProperties.AXIS, axis); + if (appliedState.hasProperty(BlockStateProperties.HORIZONTAL_AXIS) && axis != Axis.Y) + appliedState = appliedState.setValue(BlockStateProperties.HORIZONTAL_AXIS, axis); + } + + return appliedState; + } + + public boolean isAcceptedRegardless(BlockState material) { + return false; + } + + public BlockState prepareMaterial(Level pLevel, BlockPos pPos, BlockState pState, Player pPlayer, + InteractionHand pHand, BlockHitResult pHit, BlockState material) { + return material; + } + + @Override + public void onRemove(BlockState pState, Level pLevel, BlockPos pPos, BlockState pNewState, boolean pIsMoving) { + if (!pState.hasBlockEntity() || pState.getBlock() == pNewState.getBlock()) + return; + if (!pIsMoving) + withBlockEntityDo(pLevel, pPos, ufte -> Block.popResource(pLevel, pPos, ufte.getConsumedItem())); + pLevel.removeBlockEntity(pPos); + } + + @Override + public void playerWillDestroy(Level pLevel, BlockPos pPos, BlockState pState, Player pPlayer) { + super.playerWillDestroy(pLevel, pPos, pState, pPlayer); + if (pPlayer.isCreative()) + withBlockEntityDo(pLevel, pPos, ufte -> ufte.setConsumedItem(ItemStack.EMPTY)); + } + + @Override + public Class getBlockEntityClass() { + return CopycatBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.COPYCAT.get(); + } + + // Connected Textures + + @Override + @OnlyIn(Dist.CLIENT) + public BlockState getAppearance(BlockState state, BlockAndTintGetter level, BlockPos pos, Direction side, + BlockState queryState, BlockPos queryPos) { + + if (isIgnoredConnectivitySide(level, state, side, pos, queryPos)) + return state; + + ModelDataManager modelDataManager = level.getModelDataManager(); + if (modelDataManager == null) + return getMaterial(level, pos); + return CopycatModel.getMaterial(modelDataManager.getAt(pos)); + } + + public boolean isIgnoredConnectivitySide(BlockAndTintGetter reader, BlockState state, Direction face, + BlockPos fromPos, BlockPos toPos) { + return false; + } + + public abstract boolean canConnectTexturesToward(BlockAndTintGetter reader, BlockPos fromPos, BlockPos toPos, + BlockState state); + + // + + public static BlockState getMaterial(BlockGetter reader, BlockPos targetPos) { + if (reader.getBlockEntity(targetPos) instanceof CopycatBlockEntity cbe) + return cbe.getMaterial(); + return Blocks.AIR.defaultBlockState(); + } + + public boolean canFaceBeOccluded(BlockState state, Direction face) { + return false; + } + + public boolean shouldFaceAlwaysRender(BlockState state, Direction face) { + return false; + } + + // Wrapped properties + + @Override + public SoundType getSoundType(BlockState state, LevelReader level, BlockPos pos, Entity entity) { + return getMaterial(level, pos).getSoundType(); + } + + @Override + public float getFriction(BlockState state, LevelReader level, BlockPos pos, Entity entity) { + return getMaterial(level, pos).getFriction(level, pos, entity); + } + + @Override + public int getLightEmission(BlockState state, BlockGetter level, BlockPos pos) { + return getMaterial(level, pos).getLightEmission(level, pos); + } + + @Override + public boolean canHarvestBlock(BlockState state, BlockGetter level, BlockPos pos, Player player) { + return getMaterial(level, pos).canHarvestBlock(level, pos, player); + } + + @Override + public float getExplosionResistance(BlockState state, BlockGetter level, BlockPos pos, Explosion explosion) { + return getMaterial(level, pos).getExplosionResistance(level, pos, explosion); + } + + @Override + public ItemStack getCloneItemStack(BlockState state, HitResult target, BlockGetter level, BlockPos pos, + Player player) { + BlockState material = getMaterial(level, pos); + if (AllBlocks.COPYCAT_BASE.has(material) || player != null && player.isSteppingCarefully()) + return new ItemStack(this); + return material.getCloneItemStack(target, level, pos, player); + } + + @Override + public boolean addLandingEffects(BlockState state1, ServerLevel level, BlockPos pos, BlockState state2, + LivingEntity entity, int numberOfParticles) { + return getMaterial(level, pos).addLandingEffects(level, pos, state2, entity, numberOfParticles); + } + + @Override + public boolean addRunningEffects(BlockState state, Level level, BlockPos pos, Entity entity) { + return getMaterial(level, pos).addRunningEffects(level, pos, entity); + } + + @Override + public float getEnchantPowerBonus(BlockState state, LevelReader level, BlockPos pos) { + return getMaterial(level, pos).getEnchantPowerBonus(level, pos); + } + + @Override + public boolean canEntityDestroy(BlockState state, BlockGetter level, BlockPos pos, Entity entity) { + return getMaterial(level, pos).canEntityDestroy(level, pos, entity); + } + + @Override + public boolean isValidSpawn(BlockState state, BlockGetter level, BlockPos pos, Type type, + EntityType entityType) { + return false; + } + + @Override + public void fallOn(Level pLevel, BlockState pState, BlockPos pPos, Entity pEntity, float p_152430_) { + BlockState material = getMaterial(pLevel, pPos); + material.getBlock() + .fallOn(pLevel, material, pPos, pEntity, p_152430_); + } + + @Override + public float getDestroyProgress(BlockState pState, Player pPlayer, BlockGetter pLevel, BlockPos pPos) { + return getMaterial(pLevel, pPos).getDestroyProgress(pPlayer, pLevel, pPos); + } + + // + + @OnlyIn(Dist.CLIENT) + public static BlockColor wrappedColor() { + return new WrappedBlockColor(); + } + + @OnlyIn(Dist.CLIENT) + public static class WrappedBlockColor implements BlockColor { + + @Override + public int getColor(BlockState pState, @Nullable BlockAndTintGetter pLevel, @Nullable BlockPos pPos, + int pTintIndex) { + if (pLevel == null || pPos == null) + return GrassColor.get(0.5D, 1.0D); + return Minecraft.getInstance() + .getBlockColors() + .getColor(getMaterial(pLevel, pPos), pLevel, pPos, pTintIndex); + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatBlockEntity.java b/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatBlockEntity.java new file mode 100644 index 000000000..a8179e758 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatBlockEntity.java @@ -0,0 +1,196 @@ +package com.simibubi.create.content.decoration.copycat; + +import java.util.List; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.contraptions.ITransformableBlockEntity; +import com.simibubi.create.content.contraptions.StructureTransform; +import com.simibubi.create.content.redstone.RoseQuartzLampBlock; +import com.simibubi.create.content.schematics.requirement.ISpecialBlockEntityItemRequirement; +import com.simibubi.create.content.schematics.requirement.ItemRequirement; +import com.simibubi.create.content.schematics.requirement.ItemRequirement.ItemUseType; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.IPartialSafeNBT; +import com.simibubi.create.foundation.utility.Iterate; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.registries.Registries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.TrapDoorBlock; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraftforge.client.model.data.ModelData; +import net.minecraftforge.items.ItemHandlerHelper; + +public class CopycatBlockEntity extends SmartBlockEntity + implements ISpecialBlockEntityItemRequirement, ITransformableBlockEntity, IPartialSafeNBT { + + private BlockState material; + private ItemStack consumedItem; + + public CopycatBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + material = AllBlocks.COPYCAT_BASE.getDefaultState(); + consumedItem = ItemStack.EMPTY; + } + + public BlockState getMaterial() { + return material; + } + + public boolean hasCustomMaterial() { + return !AllBlocks.COPYCAT_BASE.has(getMaterial()); + } + + public void setMaterial(BlockState blockState) { + BlockState wrapperState = getBlockState(); + + if (!material.is(blockState.getBlock())) + for (Direction side : Iterate.directions) { + BlockPos neighbour = worldPosition.relative(side); + BlockState neighbourState = level.getBlockState(neighbour); + if (neighbourState != wrapperState) + continue; + if (!(level.getBlockEntity(neighbour)instanceof CopycatBlockEntity cbe)) + continue; + BlockState otherMaterial = cbe.getMaterial(); + if (!otherMaterial.is(blockState.getBlock())) + continue; + blockState = otherMaterial; + break; + } + + material = blockState; + if (!level.isClientSide()) { + notifyUpdate(); + return; + } + redraw(); + } + + public boolean cycleMaterial() { + if (material.hasProperty(TrapDoorBlock.HALF) && material.getOptionalValue(TrapDoorBlock.OPEN) + .orElse(false)) + setMaterial(material.cycle(TrapDoorBlock.HALF)); + else if (material.hasProperty(BlockStateProperties.FACING)) + setMaterial(material.cycle(BlockStateProperties.FACING)); + else if (material.hasProperty(BlockStateProperties.HORIZONTAL_FACING)) + setMaterial(material.setValue(BlockStateProperties.HORIZONTAL_FACING, + material.getValue(BlockStateProperties.HORIZONTAL_FACING) + .getClockWise())); + else if (material.hasProperty(BlockStateProperties.AXIS)) + setMaterial(material.cycle(BlockStateProperties.AXIS)); + else if (material.hasProperty(BlockStateProperties.HORIZONTAL_AXIS)) + setMaterial(material.cycle(BlockStateProperties.HORIZONTAL_AXIS)); + else if (material.hasProperty(BlockStateProperties.LIT)) + setMaterial(material.cycle(BlockStateProperties.LIT)); + else if (material.hasProperty(RoseQuartzLampBlock.POWERING)) + setMaterial(material.cycle(RoseQuartzLampBlock.POWERING)); + else + return false; + + return true; + } + + public ItemStack getConsumedItem() { + return consumedItem; + } + + public void setConsumedItem(ItemStack stack) { + consumedItem = ItemHandlerHelper.copyStackWithSize(stack, 1); + setChanged(); + } + + private void redraw() { + if (!isVirtual()) + requestModelDataUpdate(); + if (hasLevel()) { + level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 16); + level.getChunkSource() + .getLightEngine() + .checkBlock(worldPosition); + } + } + + @Override + public void addBehaviours(List behaviours) {} + + @Override + public ItemRequirement getRequiredItems(BlockState state) { + if (consumedItem.isEmpty()) + return ItemRequirement.NONE; + return new ItemRequirement(ItemUseType.CONSUME, consumedItem); + } + + @Override + public void transform(StructureTransform transform) { + material = transform.apply(material); + notifyUpdate(); + } + + @Override + protected void read(CompoundTag tag, boolean clientPacket) { + super.read(tag, clientPacket); + + consumedItem = ItemStack.of(tag.getCompound("Item")); + + BlockState prevMaterial = material; + if (!tag.contains("Material")) { + consumedItem = ItemStack.EMPTY; + return; + } + + material = NbtUtils.readBlockState(level.holderLookup(Registries.BLOCK), tag.getCompound("Material")); + + // Validate Material + if (material != null && !clientPacket) { + BlockState blockState = getBlockState(); + if (blockState == null) + return; + if (!(blockState.getBlock() instanceof CopycatBlock cb)) + return; + BlockState acceptedBlockState = cb.getAcceptedBlockState(level, worldPosition, consumedItem, null); + if (acceptedBlockState != null && material.is(acceptedBlockState.getBlock())) + return; + consumedItem = ItemStack.EMPTY; + material = AllBlocks.COPYCAT_BASE.getDefaultState(); + } + + if (clientPacket && prevMaterial != material) + redraw(); + } + + @Override + public void writeSafe(CompoundTag tag) { + super.writeSafe(tag); + + ItemStack stackWithoutNBT = consumedItem.copy(); + stackWithoutNBT.setTag(null); + + write(tag, stackWithoutNBT, material); + } + + @Override + protected void write(CompoundTag tag, boolean clientPacket) { + super.write(tag, clientPacket); + write(tag, consumedItem, material); + } + + protected void write(CompoundTag tag, ItemStack stack, BlockState material) { + tag.put("Item", stack.serializeNBT()); + tag.put("Material", NbtUtils.writeBlockState(material)); + } + + @Override + public ModelData getModelData() { + return ModelData.builder() + .with(CopycatModel.MATERIAL_PROPERTY, material) + .build(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatModel.java b/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatModel.java new file mode 100644 index 000000000..7bd452d99 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatModel.java @@ -0,0 +1,166 @@ +package com.simibubi.create.content.decoration.copycat; + +import java.util.Collections; +import java.util.List; + +import javax.annotation.Nullable; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.foundation.model.BakedModelWrapperWithData; +import com.simibubi.create.foundation.utility.Iterate; + +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.TextureAtlasSprite; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.client.model.data.ModelData; +import net.minecraftforge.client.model.data.ModelData.Builder; +import net.minecraftforge.client.model.data.ModelProperty; + +public abstract class CopycatModel extends BakedModelWrapperWithData { + + public static final ModelProperty MATERIAL_PROPERTY = new ModelProperty<>(); + private static final ModelProperty OCCLUSION_PROPERTY = new ModelProperty<>(); + private static final ModelProperty WRAPPED_DATA_PROPERTY = new ModelProperty<>(); + + public CopycatModel(BakedModel originalModel) { + super(originalModel); + } + + @Override + protected Builder gatherModelData(Builder builder, BlockAndTintGetter world, BlockPos pos, BlockState state, + ModelData blockEntityData) { + BlockState material = getMaterial(blockEntityData); + if (material == null) + return builder; + + builder.with(MATERIAL_PROPERTY, material); + + if (!(state.getBlock() instanceof CopycatBlock copycatBlock)) + return builder; + + OcclusionData occlusionData = new OcclusionData(); + gatherOcclusionData(world, pos, state, material, occlusionData, copycatBlock); + builder.with(OCCLUSION_PROPERTY, occlusionData); + + ModelData wrappedData = getModelOf(material).getModelData( + new FilteredBlockAndTintGetter(world, + targetPos -> copycatBlock.canConnectTexturesToward(world, pos, targetPos, state)), + pos, material, ModelData.EMPTY); + return builder.with(WRAPPED_DATA_PROPERTY, wrappedData); + } + + private void gatherOcclusionData(BlockAndTintGetter world, BlockPos pos, BlockState state, BlockState material, + OcclusionData occlusionData, CopycatBlock copycatBlock) { + MutableBlockPos mutablePos = new MutableBlockPos(); + for (Direction face : Iterate.directions) { + + // Rubidium: Run an additional IForgeBlock.hidesNeighborFace check because it + // seems to be missing in Block.shouldRenderFace + MutableBlockPos neighbourPos = mutablePos.setWithOffset(pos, face); + BlockState neighbourState = world.getBlockState(neighbourPos); + if (state.supportsExternalFaceHiding() + && neighbourState.hidesNeighborFace(world, neighbourPos, state, face.getOpposite())) { + occlusionData.occlude(face); + continue; + } + + if (!copycatBlock.canFaceBeOccluded(state, face)) + continue; + if (!Block.shouldRenderFace(material, world, pos, face, neighbourPos)) + occlusionData.occlude(face); + } + } + + @Override + public List getQuads(BlockState state, Direction side, RandomSource rand, ModelData data, RenderType renderType) { + + // Rubidium: see below + if (side != null && state.getBlock() instanceof CopycatBlock ccb && ccb.shouldFaceAlwaysRender(state, side)) + return Collections.emptyList(); + + BlockState material = getMaterial(data); + + if (material == null) + return super.getQuads(state, side, rand, data, renderType); + + OcclusionData occlusionData = data.get(OCCLUSION_PROPERTY); + if (occlusionData != null && occlusionData.isOccluded(side)) + return super.getQuads(state, side, rand, data, renderType); + + ModelData wrappedData = data.get(WRAPPED_DATA_PROPERTY); + if (wrappedData == null) + wrappedData = ModelData.EMPTY; + if (renderType != null && !Minecraft.getInstance() + .getBlockRenderer() + .getBlockModel(material) + .getRenderTypes(material, rand, wrappedData) + .contains(renderType)) + return super.getQuads(state, side, rand, data, renderType); + + List croppedQuads = getCroppedQuads(state, side, rand, material, wrappedData, renderType); + + // Rubidium: render side!=null versions of the base material during side==null, + // to avoid getting culled away + if (side == null && state.getBlock() instanceof CopycatBlock ccb) + for (Direction nonOcclusionSide : Iterate.directions) + if (ccb.shouldFaceAlwaysRender(state, nonOcclusionSide)) + croppedQuads.addAll(getCroppedQuads(state, nonOcclusionSide, rand, material, wrappedData, renderType)); + + return croppedQuads; + } + + protected abstract List getCroppedQuads(BlockState state, Direction side, RandomSource rand, + BlockState material, ModelData wrappedData, RenderType renderType); + + @Override + public TextureAtlasSprite getParticleIcon(ModelData data) { + BlockState material = getMaterial(data); + + if (material == null) + return super.getParticleIcon(data); + + ModelData wrappedData = data.get(WRAPPED_DATA_PROPERTY); + if (wrappedData == null) + wrappedData = ModelData.EMPTY; + + return getModelOf(material).getParticleIcon(wrappedData); + } + + @Nullable + public static BlockState getMaterial(ModelData data) { + BlockState material = data.get(MATERIAL_PROPERTY); + return material == null ? AllBlocks.COPYCAT_BASE.getDefaultState() : material; + } + + public static BakedModel getModelOf(BlockState state) { + return Minecraft.getInstance() + .getBlockRenderer() + .getBlockModel(state); + } + + private static class OcclusionData { + private final boolean[] occluded; + + public OcclusionData() { + occluded = new boolean[6]; + } + + public void occlude(Direction face) { + occluded[face.get3DDataValue()] = true; + } + + public boolean isOccluded(Direction face) { + return face == null ? false : occluded[face.get3DDataValue()]; + } + } + +} diff --git a/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatPanelBlock.java b/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatPanelBlock.java new file mode 100644 index 000000000..a3d22fae3 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatPanelBlock.java @@ -0,0 +1,240 @@ +package com.simibubi.create.content.decoration.copycat; + +import java.util.List; +import java.util.function.Predicate; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllShapes; +import com.simibubi.create.foundation.placement.IPlacementHelper; +import com.simibubi.create.foundation.placement.PlacementHelpers; +import com.simibubi.create.foundation.placement.PlacementOffset; + +import net.minecraft.MethodsReturnNonnullByDefault; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.BlockAndTintGetter; +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.Mirror; +import net.minecraft.world.level.block.Rotation; +import net.minecraft.world.level.block.TrapDoorBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition.Builder; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.DirectionProperty; +import net.minecraft.world.level.block.state.properties.Half; +import net.minecraft.world.level.pathfinder.PathComputationType; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +public class CopycatPanelBlock extends WaterloggedCopycatBlock { + + public static final DirectionProperty FACING = BlockStateProperties.FACING; + + private static final int placementHelperId = PlacementHelpers.register(new PlacementHelper()); + + public CopycatPanelBlock(Properties pProperties) { + super(pProperties); + registerDefaultState(defaultBlockState().setValue(FACING, Direction.UP)); + } + + @Override + public boolean isAcceptedRegardless(BlockState material) { + return CopycatSpecialCases.isBarsMaterial(material) || CopycatSpecialCases.isTrapdoorMaterial(material); + } + + @Override + public BlockState prepareMaterial(Level pLevel, BlockPos pPos, BlockState pState, Player pPlayer, + InteractionHand pHand, BlockHitResult pHit, BlockState material) { + if (!CopycatSpecialCases.isTrapdoorMaterial(material)) + return super.prepareMaterial(pLevel, pPos, pState, pPlayer, pHand, pHit, material); + + Direction panelFacing = pState.getValue(FACING); + if (panelFacing == Direction.DOWN) + material = material.setValue(TrapDoorBlock.HALF, Half.TOP); + if (panelFacing.getAxis() == Axis.Y) + return material.setValue(TrapDoorBlock.FACING, pPlayer.getDirection()) + .setValue(TrapDoorBlock.OPEN, false); + + boolean clickedNearTop = pHit.getLocation().y - .5 > pPos.getY(); + return material.setValue(TrapDoorBlock.OPEN, true) + .setValue(TrapDoorBlock.HALF, clickedNearTop ? Half.TOP : Half.BOTTOM) + .setValue(TrapDoorBlock.FACING, panelFacing); + } + + @Override + public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, + BlockHitResult ray) { + + if (!player.isShiftKeyDown() && player.mayBuild()) { + ItemStack heldItem = player.getItemInHand(hand); + IPlacementHelper placementHelper = PlacementHelpers.get(placementHelperId); + if (placementHelper.matchesItem(heldItem)) { + placementHelper.getOffset(player, world, state, pos, ray) + .placeInWorld(world, (BlockItem) heldItem.getItem(), player, hand, ray); + return InteractionResult.SUCCESS; + } + } + + return super.use(state, world, pos, player, hand, ray); + } + + @Override + public boolean isIgnoredConnectivitySide(BlockAndTintGetter reader, BlockState state, Direction face, + BlockPos fromPos, BlockPos toPos) { + Direction facing = state.getValue(FACING); + BlockState toState = reader.getBlockState(toPos); + + if (!toState.is(this)) + return facing != face.getOpposite(); + + BlockPos diff = fromPos.subtract(toPos); + int coord = facing.getAxis() + .choose(diff.getX(), diff.getY(), diff.getZ()); + return facing == toState.getValue(FACING) + .getOpposite() + && !(coord != 0 && coord == facing.getAxisDirection() + .getStep()); + } + + @Override + public boolean canConnectTexturesToward(BlockAndTintGetter reader, BlockPos fromPos, BlockPos toPos, + BlockState state) { + Direction facing = state.getValue(FACING); + BlockState toState = reader.getBlockState(toPos); + + if (toPos.equals(fromPos.relative(facing))) + return false; + + BlockPos diff = fromPos.subtract(toPos); + int coord = facing.getAxis() + .choose(diff.getX(), diff.getY(), diff.getZ()); + + if (!toState.is(this)) + return coord != -facing.getAxisDirection() + .getStep(); + + if (isOccluded(state, toState, facing)) + return true; + if (toState.setValue(WATERLOGGED, false) == state.setValue(WATERLOGGED, false) && coord == 0) + return true; + + return false; + } + + @Override + public boolean canFaceBeOccluded(BlockState state, Direction face) { + return state.getValue(FACING) + .getOpposite() == face; + } + + @Override + public boolean shouldFaceAlwaysRender(BlockState state, Direction face) { + return canFaceBeOccluded(state, face.getOpposite()); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext pContext) { + BlockState stateForPlacement = super.getStateForPlacement(pContext); + return stateForPlacement.setValue(FACING, pContext.getNearestLookingDirection() + .getOpposite()); + } + + @Override + protected void createBlockStateDefinition(Builder pBuilder) { + super.createBlockStateDefinition(pBuilder.add(FACING)); + } + + @Override + public VoxelShape getShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, CollisionContext pContext) { + return AllShapes.CASING_3PX.get(pState.getValue(FACING)); + } + + @Override + public boolean isPathfindable(BlockState pState, BlockGetter pLevel, BlockPos pPos, PathComputationType pType) { + return false; + } + + @Override + public boolean supportsExternalFaceHiding(BlockState state) { + return true; + } + + @Override + public boolean hidesNeighborFace(BlockGetter level, BlockPos pos, BlockState state, BlockState neighborState, + Direction dir) { + if (state.is(this) == neighborState.is(this)) { + if (CopycatSpecialCases.isBarsMaterial(getMaterial(level, pos)) + && CopycatSpecialCases.isBarsMaterial(getMaterial(level, pos.relative(dir)))) + return state.getValue(FACING) == neighborState.getValue(FACING); + if (getMaterial(level, pos).skipRendering(getMaterial(level, pos.relative(dir)), dir.getOpposite())) + return isOccluded(state, neighborState, dir.getOpposite()); + } + + return state.getValue(FACING) == dir.getOpposite() + && getMaterial(level, pos).skipRendering(neighborState, dir.getOpposite()); + } + + public static boolean isOccluded(BlockState state, BlockState other, Direction pDirection) { + state = state.setValue(WATERLOGGED, false); + other = other.setValue(WATERLOGGED, false); + Direction facing = state.getValue(FACING); + if (facing.getOpposite() == other.getValue(FACING) && pDirection == facing) + return true; + if (other.getValue(FACING) != facing) + return false; + return pDirection.getAxis() != facing.getAxis(); + } + + @Override + public BlockState rotate(BlockState state, Rotation rot) { + return state.setValue(FACING, rot.rotate(state.getValue(FACING))); + } + + @Override + @SuppressWarnings("deprecation") + public BlockState mirror(BlockState state, Mirror mirrorIn) { + return state.rotate(mirrorIn.getRotation(state.getValue(FACING))); + } + + @MethodsReturnNonnullByDefault + private static class PlacementHelper implements IPlacementHelper { + @Override + public Predicate getItemPredicate() { + return AllBlocks.COPYCAT_PANEL::isIn; + } + + @Override + public Predicate getStatePredicate() { + return AllBlocks.COPYCAT_PANEL::has; + } + + @Override + public PlacementOffset getOffset(Player player, Level world, BlockState state, BlockPos pos, + BlockHitResult ray) { + List directions = IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getLocation(), + state.getValue(FACING) + .getAxis(), + dir -> world.getBlockState(pos.relative(dir)) + .getMaterial() + .isReplaceable()); + + if (directions.isEmpty()) + return PlacementOffset.fail(); + else { + return PlacementOffset.success(pos.relative(directions.get(0)), + s -> s.setValue(FACING, state.getValue(FACING))); + } + } + } + +} diff --git a/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatPanelModel.java b/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatPanelModel.java new file mode 100644 index 000000000..3bd5c298d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatPanelModel.java @@ -0,0 +1,90 @@ +package com.simibubi.create.content.decoration.copycat; + +import java.util.ArrayList; +import java.util.List; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.foundation.model.BakedModelHelper; +import com.simibubi.create.foundation.model.BakedQuadHelper; +import com.simibubi.create.foundation.utility.Iterate; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.block.BlockRenderDispatcher; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.block.DirectionalBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.client.model.data.ModelData; + +public class CopycatPanelModel extends CopycatModel { + + protected static final AABB CUBE_AABB = new AABB(BlockPos.ZERO); + + public CopycatPanelModel(BakedModel originalModel) { + super(originalModel); + } + + @Override + protected List getCroppedQuads(BlockState state, Direction side, RandomSource rand, BlockState material, + ModelData wrappedData, RenderType renderType) { + Direction facing = state.getOptionalValue(CopycatPanelBlock.FACING) + .orElse(Direction.UP); + BlockRenderDispatcher blockRenderer = Minecraft.getInstance() + .getBlockRenderer(); + + BlockState specialCopycatModelState = null; + if (CopycatSpecialCases.isBarsMaterial(material)) + specialCopycatModelState = AllBlocks.COPYCAT_BARS.getDefaultState(); + if (CopycatSpecialCases.isTrapdoorMaterial(material)) + return blockRenderer.getBlockModel(material) + .getQuads(state, side, rand, wrappedData, renderType); + + if (specialCopycatModelState != null) { + BakedModel blockModel = + blockRenderer.getBlockModel(specialCopycatModelState.setValue(DirectionalBlock.FACING, facing)); + if (blockModel instanceof CopycatModel cm) + return cm.getCroppedQuads(state, side, rand, material, wrappedData, renderType); + } + + BakedModel model = getModelOf(material); + List templateQuads = model.getQuads(material, side, rand, wrappedData, renderType); + int size = templateQuads.size(); + + List quads = new ArrayList<>(); + + Vec3 normal = Vec3.atLowerCornerOf(facing.getNormal()); + Vec3 normalScaled14 = normal.scale(14 / 16f); + + // 2 Pieces + for (boolean front : Iterate.trueAndFalse) { + Vec3 normalScaledN13 = normal.scale(front ? 0 : -13 / 16f); + float contract = 16 - (front ? 1 : 2); + AABB bb = CUBE_AABB.contract(normal.x * contract / 16, normal.y * contract / 16, normal.z * contract / 16); + if (!front) + bb = bb.move(normalScaled14); + + for (int i = 0; i < size; i++) { + BakedQuad quad = templateQuads.get(i); + Direction direction = quad.getDirection(); + + if (front && direction == facing) + continue; + if (!front && direction == facing.getOpposite()) + continue; + + quads.add(BakedQuadHelper.cloneWithCustomGeometry(quad, + BakedModelHelper.cropAndMove(quad.getVertices(), quad.getSprite(), bb, normalScaledN13))); + } + + } + + return quads; + } + +} diff --git a/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatSpecialCases.java b/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatSpecialCases.java new file mode 100644 index 000000000..a7ba28e3d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatSpecialCases.java @@ -0,0 +1,22 @@ +package com.simibubi.create.content.decoration.copycat; + +import com.simibubi.create.content.decoration.palettes.GlassPaneBlock; + +import net.minecraft.world.level.block.IronBarsBlock; +import net.minecraft.world.level.block.StainedGlassPaneBlock; +import net.minecraft.world.level.block.TrapDoorBlock; +import net.minecraft.world.level.block.state.BlockState; + +public class CopycatSpecialCases { + + public static boolean isBarsMaterial(BlockState material) { + return material.getBlock() instanceof IronBarsBlock && !(material.getBlock() instanceof GlassPaneBlock) + && !(material.getBlock() instanceof StainedGlassPaneBlock); + } + + public static boolean isTrapdoorMaterial(BlockState material) { + return material.getBlock() instanceof TrapDoorBlock && material.hasProperty(TrapDoorBlock.HALF) + && material.hasProperty(TrapDoorBlock.OPEN) && material.hasProperty(TrapDoorBlock.FACING); + } + +} diff --git a/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatStepBlock.java b/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatStepBlock.java new file mode 100644 index 000000000..b5237aec3 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatStepBlock.java @@ -0,0 +1,218 @@ +package com.simibubi.create.content.decoration.copycat; + +import java.util.function.Predicate; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllShapes; +import com.simibubi.create.foundation.placement.IPlacementHelper; +import com.simibubi.create.foundation.placement.PlacementHelpers; +import com.simibubi.create.foundation.placement.PoleHelper; +import com.simibubi.create.foundation.utility.VoxelShaper; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.BlockAndTintGetter; +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.Mirror; +import net.minecraft.world.level.block.Rotation; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition.Builder; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.DirectionProperty; +import net.minecraft.world.level.block.state.properties.EnumProperty; +import net.minecraft.world.level.block.state.properties.Half; +import net.minecraft.world.level.pathfinder.PathComputationType; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +public class CopycatStepBlock extends WaterloggedCopycatBlock { + + public static final EnumProperty HALF = BlockStateProperties.HALF; + public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING; + + private static final int placementHelperId = PlacementHelpers.register(new PlacementHelper()); + + public CopycatStepBlock(Properties pProperties) { + super(pProperties); + registerDefaultState(defaultBlockState().setValue(HALF, Half.BOTTOM) + .setValue(FACING, Direction.SOUTH)); + } + + @Override + public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, + BlockHitResult ray) { + + if (!player.isShiftKeyDown() && player.mayBuild()) { + ItemStack heldItem = player.getItemInHand(hand); + IPlacementHelper helper = PlacementHelpers.get(placementHelperId); + if (helper.matchesItem(heldItem)) + return helper.getOffset(player, world, state, pos, ray) + .placeInWorld(world, (BlockItem) heldItem.getItem(), player, hand, ray); + } + + return super.use(state, world, pos, player, hand, ray); + } + + @Override + public boolean isIgnoredConnectivitySide(BlockAndTintGetter reader, BlockState state, Direction face, + BlockPos fromPos, BlockPos toPos) { + BlockState toState = reader.getBlockState(toPos); + + if (!toState.is(this)) + return true; + + Direction facing = state.getValue(FACING); + BlockPos diff = fromPos.subtract(toPos); + int coord = facing.getAxis() + .choose(diff.getX(), diff.getY(), diff.getZ()); + + Half half = state.getValue(HALF); + if (half != toState.getValue(HALF)) + return diff.getY() == 0; + + return facing == toState.getValue(FACING) + .getOpposite() + && !(coord != 0 && coord != facing.getAxisDirection() + .getStep()); + } + + @Override + public boolean canConnectTexturesToward(BlockAndTintGetter reader, BlockPos fromPos, BlockPos toPos, + BlockState state) { + Direction facing = state.getValue(FACING); + BlockState toState = reader.getBlockState(toPos); + BlockPos diff = fromPos.subtract(toPos); + + if (fromPos.equals(toPos.relative(facing))) + return false; + if (!toState.is(this)) + return false; + + if (diff.getY() != 0) { + if (isOccluded(toState, state, diff.getY() > 0 ? Direction.UP : Direction.DOWN)) + return true; + return false; + } + + if (isOccluded(state, toState, facing)) + return true; + + int coord = facing.getAxis() + .choose(diff.getX(), diff.getY(), diff.getZ()); + if (state.setValue(WATERLOGGED, false) == toState.setValue(WATERLOGGED, false) && coord == 0) + return true; + + return false; + } + + @Override + public boolean canFaceBeOccluded(BlockState state, Direction face) { + if (face.getAxis() == Axis.Y) + return (state.getValue(HALF) == Half.TOP) == (face == Direction.UP); + return state.getValue(FACING) == face; + } + + @Override + public boolean shouldFaceAlwaysRender(BlockState state, Direction face) { + return canFaceBeOccluded(state, face.getOpposite()); + } + + @Override + public boolean isPathfindable(BlockState pState, BlockGetter pLevel, BlockPos pPos, PathComputationType pType) { + return false; + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext pContext) { + BlockState stateForPlacement = + super.getStateForPlacement(pContext).setValue(FACING, pContext.getHorizontalDirection()); + Direction direction = pContext.getClickedFace(); + if (direction == Direction.UP) + return stateForPlacement; + if (direction == Direction.DOWN || (pContext.getClickLocation().y - pContext.getClickedPos() + .getY() > 0.5D)) + return stateForPlacement.setValue(HALF, Half.TOP); + return stateForPlacement; + } + + @Override + protected void createBlockStateDefinition(Builder pBuilder) { + super.createBlockStateDefinition(pBuilder.add(HALF, FACING)); + } + + @Override + public VoxelShape getShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, CollisionContext pContext) { + VoxelShaper voxelShaper = pState.getValue(HALF) == Half.BOTTOM ? AllShapes.STEP_BOTTOM : AllShapes.STEP_TOP; + return voxelShaper.get(pState.getValue(FACING)); + } + + @Override + public boolean supportsExternalFaceHiding(BlockState state) { + return true; + } + + @Override + public boolean hidesNeighborFace(BlockGetter level, BlockPos pos, BlockState state, BlockState neighborState, + Direction dir) { + if (state.is(this) == neighborState.is(this) + && getMaterial(level, pos).skipRendering(getMaterial(level, pos.relative(dir)), dir.getOpposite())) + return isOccluded(state, neighborState, dir); + return false; + } + + public static boolean isOccluded(BlockState state, BlockState other, Direction pDirection) { + state = state.setValue(WATERLOGGED, false); + other = other.setValue(WATERLOGGED, false); + + Half half = state.getValue(HALF); + boolean vertical = pDirection.getAxis() == Axis.Y; + if (half != other.getValue(HALF)) + return vertical && (pDirection == Direction.UP) == (half == Half.TOP); + if (vertical) + return false; + + Direction facing = state.getValue(FACING); + if (facing.getOpposite() == other.getValue(FACING) && pDirection == facing) + return true; + if (other.getValue(FACING) != facing) + return false; + return pDirection.getAxis() != facing.getAxis(); + } + + @Override + public BlockState rotate(BlockState pState, Rotation pRot) { + return pState.setValue(FACING, pRot.rotate(pState.getValue(FACING))); + } + + @Override + @SuppressWarnings("deprecation") + public BlockState mirror(BlockState pState, Mirror pMirror) { + return pState.rotate(pMirror.getRotation(pState.getValue(FACING))); + } + + private static class PlacementHelper extends PoleHelper { + + public PlacementHelper() { + super(AllBlocks.COPYCAT_STEP::has, state -> state.getValue(FACING) + .getClockWise() + .getAxis(), FACING); + } + + @Override + public Predicate getItemPredicate() { + return AllBlocks.COPYCAT_STEP::isIn; + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatStepModel.java b/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatStepModel.java new file mode 100644 index 000000000..673c27cf3 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/decoration/copycat/CopycatStepModel.java @@ -0,0 +1,91 @@ +package com.simibubi.create.content.decoration.copycat; + +import java.util.ArrayList; +import java.util.List; + +import com.simibubi.create.foundation.model.BakedModelHelper; +import com.simibubi.create.foundation.model.BakedQuadHelper; +import com.simibubi.create.foundation.utility.Iterate; + +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.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.Half; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.client.model.data.ModelData; + +public class CopycatStepModel extends CopycatModel { + + protected static final Vec3 VEC_Y_3 = new Vec3(0, .75, 0); + protected static final Vec3 VEC_Y_2 = new Vec3(0, .5, 0); + protected static final Vec3 VEC_Y_N2 = new Vec3(0, -.5, 0); + protected static final AABB CUBE_AABB = new AABB(BlockPos.ZERO); + + public CopycatStepModel(BakedModel originalModel) { + super(originalModel); + } + + @Override + protected List getCroppedQuads(BlockState state, Direction side, RandomSource rand, BlockState material, + ModelData wrappedData, RenderType renderType) { + Direction facing = state.getOptionalValue(CopycatStepBlock.FACING) + .orElse(Direction.SOUTH); + boolean upperHalf = state.getOptionalValue(CopycatStepBlock.HALF) + .orElse(Half.BOTTOM) == Half.TOP; + + BakedModel model = getModelOf(material); + List templateQuads = model.getQuads(material, side, rand, wrappedData, renderType); + int size = templateQuads.size(); + + List quads = new ArrayList<>(); + + Vec3 normal = Vec3.atLowerCornerOf(facing.getNormal()); + Vec3 normalScaled2 = normal.scale(.5); + Vec3 normalScaledN3 = normal.scale(-.75); + AABB bb = CUBE_AABB.contract(-normal.x * .75, .75, -normal.z * .75); + + // 4 Pieces + for (boolean top : Iterate.trueAndFalse) { + for (boolean front : Iterate.trueAndFalse) { + + AABB bb1 = bb; + if (front) + bb1 = bb1.move(normalScaledN3); + if (top) + bb1 = bb1.move(VEC_Y_3); + + Vec3 offset = Vec3.ZERO; + if (front) + offset = offset.add(normalScaled2); + if (top != upperHalf) + offset = offset.add(upperHalf ? VEC_Y_2 : VEC_Y_N2); + + for (int i = 0; i < size; i++) { + BakedQuad quad = templateQuads.get(i); + Direction direction = quad.getDirection(); + + if (front && direction == facing) + continue; + if (!front && direction == facing.getOpposite()) + continue; + if (!top && direction == Direction.UP) + continue; + if (top && direction == Direction.DOWN) + continue; + + quads.add(BakedQuadHelper.cloneWithCustomGeometry(quad, + BakedModelHelper.cropAndMove(quad.getVertices(), quad.getSprite(), bb1, offset))); + } + + } + } + + return quads; + } + +} diff --git a/src/main/java/com/simibubi/create/content/decoration/copycat/FilteredBlockAndTintGetter.java b/src/main/java/com/simibubi/create/content/decoration/copycat/FilteredBlockAndTintGetter.java new file mode 100644 index 000000000..a2f58340b --- /dev/null +++ b/src/main/java/com/simibubi/create/content/decoration/copycat/FilteredBlockAndTintGetter.java @@ -0,0 +1,74 @@ +package com.simibubi.create.content.decoration.copycat; + +import java.util.function.Predicate; + +import org.jetbrains.annotations.Nullable; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.ColorResolver; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.lighting.LevelLightEngine; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.level.material.Fluids; +import net.minecraftforge.client.model.data.ModelDataManager; + +public class FilteredBlockAndTintGetter implements BlockAndTintGetter { + + private BlockAndTintGetter wrapped; + private Predicate filter; + + public FilteredBlockAndTintGetter(BlockAndTintGetter wrapped, Predicate filter) { + this.wrapped = wrapped; + this.filter = filter; + } + + @Override + public BlockEntity getBlockEntity(BlockPos pPos) { + return filter.test(pPos) ? wrapped.getBlockEntity(pPos) : null; + } + + @Override + public BlockState getBlockState(BlockPos pPos) { + return filter.test(pPos) ? wrapped.getBlockState(pPos) : Blocks.AIR.defaultBlockState(); + } + + @Override + public FluidState getFluidState(BlockPos pPos) { + return filter.test(pPos) ? wrapped.getFluidState(pPos) : Fluids.EMPTY.defaultFluidState(); + } + + @Override + public int getHeight() { + return wrapped.getHeight(); + } + + @Override + public int getMinBuildHeight() { + return wrapped.getMinBuildHeight(); + } + + @Override + public float getShade(Direction pDirection, boolean pShade) { + return wrapped.getShade(pDirection, pShade); + } + + @Override + public LevelLightEngine getLightEngine() { + return wrapped.getLightEngine(); + } + + @Override + public int getBlockTint(BlockPos pBlockPos, ColorResolver pColorResolver) { + return wrapped.getBlockTint(pBlockPos, pColorResolver); + } + + @Override + public @Nullable ModelDataManager getModelDataManager() { + return wrapped.getModelDataManager(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/decoration/copycat/SpecialCopycatPanelBlockState.java b/src/main/java/com/simibubi/create/content/decoration/copycat/SpecialCopycatPanelBlockState.java new file mode 100644 index 000000000..3cf375ace --- /dev/null +++ b/src/main/java/com/simibubi/create/content/decoration/copycat/SpecialCopycatPanelBlockState.java @@ -0,0 +1,46 @@ +package com.simibubi.create.content.decoration.copycat; + +import com.simibubi.create.foundation.data.SpecialBlockStateGen; +import com.tterrag.registrate.providers.DataGenContext; +import com.tterrag.registrate.providers.RegistrateBlockstateProvider; + +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.DirectionalBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.client.model.generators.BlockModelProvider; +import net.minecraftforge.client.model.generators.ModelFile; + +public class SpecialCopycatPanelBlockState extends SpecialBlockStateGen { + + private String name; + + public SpecialCopycatPanelBlockState(String name) { + this.name = name; + } + + @Override + protected int getXRotation(BlockState state) { + return facing(state) == Direction.UP ? 0 : facing(state) == Direction.DOWN ? 180 : 0; + } + + @Override + protected int getYRotation(BlockState state) { + return horizontalAngle(facing(state)); + } + + private Direction facing(BlockState state) { + return state.getValue(DirectionalBlock.FACING); + } + + @Override + public ModelFile getModel(DataGenContext ctx, RegistrateBlockstateProvider prov, + BlockState state) { + BlockModelProvider models = prov.models(); + return facing(state).getAxis() == Axis.Y + ? models.getExistingFile(prov.modLoc("block/copycat_panel/" + name + "_vertical")) + : models.getExistingFile(prov.modLoc("block/copycat_panel/" + name)); + } + +} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/content/decoration/copycat/WaterloggedCopycatBlock.java b/src/main/java/com/simibubi/create/content/decoration/copycat/WaterloggedCopycatBlock.java new file mode 100644 index 000000000..a82f162ab --- /dev/null +++ b/src/main/java/com/simibubi/create/content/decoration/copycat/WaterloggedCopycatBlock.java @@ -0,0 +1,43 @@ +package com.simibubi.create.content.decoration.copycat; + +import com.simibubi.create.foundation.block.ProperWaterloggedBlock; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition.Builder; +import net.minecraft.world.level.material.FluidState; + +public abstract class WaterloggedCopycatBlock extends CopycatBlock implements ProperWaterloggedBlock { + + public WaterloggedCopycatBlock(Properties pProperties) { + super(pProperties); + registerDefaultState(defaultBlockState().setValue(WATERLOGGED, false)); + } + + @Override + protected void createBlockStateDefinition(Builder pBuilder) { + super.createBlockStateDefinition(pBuilder.add(WATERLOGGED)); + } + + @Override + public FluidState getFluidState(BlockState pState) { + return fluidState(pState); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext pContext) { + return withWater(super.getStateForPlacement(pContext), pContext); + } + + @Override + public BlockState updateShape(BlockState pState, Direction pDirection, BlockState pNeighborState, + LevelAccessor pLevel, BlockPos pCurrentPos, BlockPos pNeighborPos) { + updateWater(pLevel, pState, pCurrentPos); + return pState; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/CasingBlock.java b/src/main/java/com/simibubi/create/content/decoration/encasing/CasingBlock.java similarity index 79% rename from src/main/java/com/simibubi/create/content/contraptions/base/CasingBlock.java rename to src/main/java/com/simibubi/create/content/decoration/encasing/CasingBlock.java index 8514e61f8..2868ee220 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/CasingBlock.java +++ b/src/main/java/com/simibubi/create/content/decoration/encasing/CasingBlock.java @@ -1,6 +1,6 @@ -package com.simibubi.create.content.contraptions.base; +package com.simibubi.create.content.decoration.encasing; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; +import com.simibubi.create.content.equipment.wrench.IWrenchable; import net.minecraft.world.InteractionResult; import net.minecraft.world.item.context.UseOnContext; diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/CasingConnectivity.java b/src/main/java/com/simibubi/create/content/decoration/encasing/CasingConnectivity.java similarity index 95% rename from src/main/java/com/simibubi/create/content/contraptions/relays/encased/CasingConnectivity.java rename to src/main/java/com/simibubi/create/content/decoration/encasing/CasingConnectivity.java index d35261713..04405ac91 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/CasingConnectivity.java +++ b/src/main/java/com/simibubi/create/content/decoration/encasing/CasingConnectivity.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.relays.encased; +package com.simibubi.create.content.decoration.encasing; import java.util.IdentityHashMap; import java.util.Map; diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/EncasableBlock.java b/src/main/java/com/simibubi/create/content/decoration/encasing/EncasableBlock.java similarity index 95% rename from src/main/java/com/simibubi/create/content/contraptions/relays/elementary/EncasableBlock.java rename to src/main/java/com/simibubi/create/content/decoration/encasing/EncasableBlock.java index a09a20703..6c31ae78c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/EncasableBlock.java +++ b/src/main/java/com/simibubi/create/content/decoration/encasing/EncasableBlock.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.relays.elementary; +package com.simibubi.create.content.decoration.encasing; import java.util.List; diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/EncasedBlock.java b/src/main/java/com/simibubi/create/content/decoration/encasing/EncasedBlock.java similarity index 92% rename from src/main/java/com/simibubi/create/content/contraptions/relays/elementary/EncasedBlock.java rename to src/main/java/com/simibubi/create/content/decoration/encasing/EncasedBlock.java index 64f6c167c..acaca578d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/EncasedBlock.java +++ b/src/main/java/com/simibubi/create/content/decoration/encasing/EncasedBlock.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.relays.elementary; +package com.simibubi.create.content.decoration.encasing; import net.minecraft.core.BlockPos; import net.minecraft.world.InteractionHand; diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/EncasedCTBehaviour.java b/src/main/java/com/simibubi/create/content/decoration/encasing/EncasedCTBehaviour.java similarity index 95% rename from src/main/java/com/simibubi/create/content/contraptions/relays/encased/EncasedCTBehaviour.java rename to src/main/java/com/simibubi/create/content/decoration/encasing/EncasedCTBehaviour.java index 9afdaacb9..7c3d046bd 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/EncasedCTBehaviour.java +++ b/src/main/java/com/simibubi/create/content/decoration/encasing/EncasedCTBehaviour.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.relays.encased; +package com.simibubi.create.content.decoration.encasing; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/EncasingRegistry.java b/src/main/java/com/simibubi/create/content/decoration/encasing/EncasingRegistry.java similarity index 94% rename from src/main/java/com/simibubi/create/content/contraptions/relays/elementary/EncasingRegistry.java rename to src/main/java/com/simibubi/create/content/decoration/encasing/EncasingRegistry.java index f7eb759fd..7021664c5 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/EncasingRegistry.java +++ b/src/main/java/com/simibubi/create/content/decoration/encasing/EncasingRegistry.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.relays.elementary; +package com.simibubi.create.content.decoration.encasing; import java.util.ArrayList; import java.util.Collections; diff --git a/src/main/java/com/simibubi/create/content/curiosities/girder/ConnectedGirderModel.java b/src/main/java/com/simibubi/create/content/decoration/girder/ConnectedGirderModel.java similarity index 78% rename from src/main/java/com/simibubi/create/content/curiosities/girder/ConnectedGirderModel.java rename to src/main/java/com/simibubi/create/content/decoration/girder/ConnectedGirderModel.java index 74af59b9f..b8878f6b1 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/girder/ConnectedGirderModel.java +++ b/src/main/java/com/simibubi/create/content/decoration/girder/ConnectedGirderModel.java @@ -1,10 +1,10 @@ -package com.simibubi.create.content.curiosities.girder; +package com.simibubi.create.content.decoration.girder; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.AllPartialModels; import com.simibubi.create.foundation.block.connected.CTModel; import com.simibubi.create.foundation.utility.Iterate; @@ -22,18 +22,20 @@ import net.minecraftforge.client.model.data.ModelProperty; public class ConnectedGirderModel extends CTModel { - protected static ModelProperty CONNECTION_PROPERTY = new ModelProperty<>(); + protected static final ModelProperty CONNECTION_PROPERTY = new ModelProperty<>(); public ConnectedGirderModel(BakedModel originalModel) { super(originalModel, new GirderCTBehaviour()); } @Override - protected Builder gatherModelData(Builder builder, BlockAndTintGetter world, BlockPos pos, BlockState state) { + protected ModelData.Builder gatherModelData(Builder builder, BlockAndTintGetter world, BlockPos pos, BlockState state, + ModelData blockEntityData) { + super.gatherModelData(builder, world, pos, state, blockEntityData); ConnectionData connectionData = new ConnectionData(); for (Direction d : Iterate.horizontalDirections) connectionData.setConnected(d, GirderBlock.isConnected(world, pos, state, d)); - return super.gatherModelData(builder, world, pos, state).with(CONNECTION_PROPERTY, connectionData); + return builder.with(CONNECTION_PROPERTY, connectionData); } @Override @@ -45,13 +47,13 @@ public class ConnectedGirderModel extends CTModel { ConnectionData data = extraData.get(CONNECTION_PROPERTY); for (Direction d : Iterate.horizontalDirections) if (data.isConnected(d)) - quads.addAll(AllBlockPartials.METAL_GIRDER_BRACKETS.get(d) + quads.addAll(AllPartialModels.METAL_GIRDER_BRACKETS.get(d) .get() .getQuads(state, side, rand, extraData, renderType)); return quads; } - private class ConnectionData { + private static class ConnectionData { boolean[] connectedFaces; public ConnectionData() { diff --git a/src/main/java/com/simibubi/create/content/curiosities/girder/GirderBlock.java b/src/main/java/com/simibubi/create/content/decoration/girder/GirderBlock.java similarity index 91% rename from src/main/java/com/simibubi/create/content/curiosities/girder/GirderBlock.java rename to src/main/java/com/simibubi/create/content/decoration/girder/GirderBlock.java index 8d9454342..078f209bd 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/girder/GirderBlock.java +++ b/src/main/java/com/simibubi/create/content/decoration/girder/GirderBlock.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.girder; +package com.simibubi.create.content.decoration.girder; import static net.minecraft.world.level.block.FaceAttachedHorizontalDirectionalBlock.FACE; import static net.minecraft.world.level.block.state.properties.BlockStateProperties.WATERLOGGED; @@ -6,20 +6,21 @@ import static net.minecraft.world.level.block.state.properties.BlockStatePropert import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; import com.simibubi.create.AllShapes; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.fluids.pipes.BracketBlock; -import com.simibubi.create.content.contraptions.relays.elementary.BracketedTileEntityBehaviour; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; -import com.simibubi.create.content.curiosities.deco.PlacardBlock; -import com.simibubi.create.content.logistics.block.chute.AbstractChuteBlock; -import com.simibubi.create.content.logistics.block.redstone.NixieTubeBlock; -import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayBlock; -import com.simibubi.create.content.logistics.trains.track.TrackBlock; -import com.simibubi.create.content.logistics.trains.track.TrackShape; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; +import com.simibubi.create.AllTags; +import com.simibubi.create.content.decoration.bracket.BracketBlock; +import com.simibubi.create.content.decoration.bracket.BracketedBlockEntityBehaviour; +import com.simibubi.create.content.decoration.placard.PlacardBlock; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.logistics.chute.AbstractChuteBlock; +import com.simibubi.create.content.redstone.nixieTube.NixieTubeBlock; +import com.simibubi.create.content.trains.display.FlapDisplayBlock; +import com.simibubi.create.content.trains.track.TrackBlock; +import com.simibubi.create.content.trains.track.TrackShape; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.placement.IPlacementHelper; +import com.simibubi.create.foundation.placement.PlacementHelpers; import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.placement.IPlacementHelper; -import com.simibubi.create.foundation.utility.placement.PlacementHelpers; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -102,7 +103,7 @@ public class GirderBlock extends Block implements SimpleWaterloggedBlock, IWrenc ItemStack itemInHand = pPlayer.getItemInHand(pHand); if (AllBlocks.SHAFT.isIn(itemInHand)) { - KineticTileEntity.switchToBlockState(pLevel, pPos, AllBlocks.METAL_GIRDER_ENCASED_SHAFT.getDefaultState() + KineticBlockEntity.switchToBlockState(pLevel, pPos, AllBlocks.METAL_GIRDER_ENCASED_SHAFT.getDefaultState() .setValue(WATERLOGGED, pState.getValue(WATERLOGGED)) .setValue(TOP, pState.getValue(TOP)) .setValue(BOTTOM, pState.getValue(BOTTOM)) @@ -223,7 +224,7 @@ public class GirderBlock extends Block implements SimpleWaterloggedBlock, IWrenc for (Direction d2 : Iterate.directionsInAxis(axis == Axis.X ? Axis.Z : Axis.X)) { BlockState above = level.getBlockState(pos.above() .relative(d2)); - if (AllBlocks.TRACK.has(above)) { + if (AllTags.AllBlockTags.GIRDABLE_TRACKS.matches(above)) { TrackShape shape = above.getValue(TrackBlock.SHAPE); if (shape == (axis == Axis.X ? TrackShape.XO : TrackShape.ZO)) state = state.setValue(updateProperty, true); @@ -235,9 +236,9 @@ public class GirderBlock extends Block implements SimpleWaterloggedBlock, IWrenc public static boolean isFacingBracket(BlockAndTintGetter level, BlockPos pos, Direction d) { BlockEntity blockEntity = level.getBlockEntity(pos.relative(d)); - if (!(blockEntity instanceof SmartTileEntity ste)) + if (!(blockEntity instanceof SmartBlockEntity sbe)) return false; - BracketedTileEntityBehaviour behaviour = ste.getBehaviour(BracketedTileEntityBehaviour.TYPE); + BracketedBlockEntityBehaviour behaviour = sbe.getBehaviour(BracketedBlockEntityBehaviour.TYPE); if (behaviour == null) return false; BlockState bracket = behaviour.getBracket(); diff --git a/src/main/java/com/simibubi/create/content/curiosities/girder/GirderBlockStateGenerator.java b/src/main/java/com/simibubi/create/content/decoration/girder/GirderBlockStateGenerator.java similarity index 97% rename from src/main/java/com/simibubi/create/content/curiosities/girder/GirderBlockStateGenerator.java rename to src/main/java/com/simibubi/create/content/decoration/girder/GirderBlockStateGenerator.java index 1c387539c..72f3a181c 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/girder/GirderBlockStateGenerator.java +++ b/src/main/java/com/simibubi/create/content/decoration/girder/GirderBlockStateGenerator.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.girder; +package com.simibubi.create.content.decoration.girder; import com.simibubi.create.foundation.data.AssetLookup; import com.simibubi.create.foundation.utility.Iterate; diff --git a/src/main/java/com/simibubi/create/content/curiosities/girder/GirderCTBehaviour.java b/src/main/java/com/simibubi/create/content/decoration/girder/GirderCTBehaviour.java similarity index 95% rename from src/main/java/com/simibubi/create/content/curiosities/girder/GirderCTBehaviour.java rename to src/main/java/com/simibubi/create/content/decoration/girder/GirderCTBehaviour.java index 31eb029c1..55d09ea61 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/girder/GirderCTBehaviour.java +++ b/src/main/java/com/simibubi/create/content/decoration/girder/GirderCTBehaviour.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.girder; +package com.simibubi.create.content.decoration.girder; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/com/simibubi/create/content/curiosities/girder/GirderEncasedShaftBlock.java b/src/main/java/com/simibubi/create/content/decoration/girder/GirderEncasedShaftBlock.java similarity index 81% rename from src/main/java/com/simibubi/create/content/curiosities/girder/GirderEncasedShaftBlock.java rename to src/main/java/com/simibubi/create/content/decoration/girder/GirderEncasedShaftBlock.java index 0a74a1a29..4a46cae8f 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/girder/GirderEncasedShaftBlock.java +++ b/src/main/java/com/simibubi/create/content/decoration/girder/GirderEncasedShaftBlock.java @@ -1,16 +1,16 @@ -package com.simibubi.create.content.curiosities.girder; +package com.simibubi.create.content.decoration.girder; import static net.minecraft.world.level.block.state.properties.BlockStateProperties.WATERLOGGED; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.HorizontalAxisKineticBlock; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; -import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement; -import com.simibubi.create.content.schematics.ItemRequirement; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.content.kinetics.base.HorizontalAxisKineticBlock; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.schematics.requirement.ISpecialBlockItemRequirement; +import com.simibubi.create.content.schematics.requirement.ItemRequirement; +import com.simibubi.create.foundation.block.IBE; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -37,13 +37,17 @@ import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; public class GirderEncasedShaftBlock extends HorizontalAxisKineticBlock - implements ITE, SimpleWaterloggedBlock, IWrenchable, ISpecialBlockItemRequirement { + implements IBE, SimpleWaterloggedBlock, IWrenchable, ISpecialBlockItemRequirement { public static final BooleanProperty TOP = GirderBlock.TOP; public static final BooleanProperty BOTTOM = GirderBlock.BOTTOM; public GirderEncasedShaftBlock(Properties properties) { super(properties); + registerDefaultState(super.defaultBlockState() + .setValue(WATERLOGGED, false) + .setValue(TOP, false) + .setValue(BOTTOM, false)); } @Override @@ -84,13 +88,13 @@ public class GirderEncasedShaftBlock extends HorizontalAxisKineticBlock } @Override - public Class getTileEntityClass() { - return KineticTileEntity.class; + public Class getBlockEntityClass() { + return KineticBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.ENCASED_SHAFT.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.ENCASED_SHAFT.get(); } @Override @@ -127,9 +131,9 @@ public class GirderEncasedShaftBlock extends HorizontalAxisKineticBlock } @Override - public ItemRequirement getRequiredItems(BlockState state, BlockEntity te) { - return ItemRequirement.of(AllBlocks.SHAFT.getDefaultState(), te) - .union(ItemRequirement.of(AllBlocks.METAL_GIRDER.getDefaultState(), te)); + public ItemRequirement getRequiredItems(BlockState state, BlockEntity be) { + return ItemRequirement.of(AllBlocks.SHAFT.getDefaultState(), be) + .union(ItemRequirement.of(AllBlocks.METAL_GIRDER.getDefaultState(), be)); } } diff --git a/src/main/java/com/simibubi/create/content/curiosities/girder/GirderPlacementHelper.java b/src/main/java/com/simibubi/create/content/decoration/girder/GirderPlacementHelper.java similarity index 89% rename from src/main/java/com/simibubi/create/content/curiosities/girder/GirderPlacementHelper.java rename to src/main/java/com/simibubi/create/content/decoration/girder/GirderPlacementHelper.java index 154a476bf..217753ddf 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/girder/GirderPlacementHelper.java +++ b/src/main/java/com/simibubi/create/content/decoration/girder/GirderPlacementHelper.java @@ -1,14 +1,14 @@ -package com.simibubi.create.content.curiosities.girder; +package com.simibubi.create.content.decoration.girder; import java.util.List; import java.util.function.Predicate; import com.google.common.base.Predicates; import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.curiosities.tools.ExtendoGripItem; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.utility.placement.IPlacementHelper; -import com.simibubi.create.foundation.utility.placement.PlacementOffset; +import com.simibubi.create.content.equipment.extendoGrip.ExtendoGripItem; +import com.simibubi.create.foundation.placement.IPlacementHelper; +import com.simibubi.create.foundation.placement.PlacementOffset; +import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -79,7 +79,7 @@ public class GirderPlacementHelper implements IPlacementHelper { List directions = IPlacementHelper.orderedByDistance(pos, ray.getLocation(), dir -> canExtendToward(state, dir)); for (Direction dir : directions) { - int range = AllConfigs.SERVER.curiosities.placementAssistRange.get(); + int range = AllConfigs.server().equipment.placementAssistRange.get(); if (player != null) { AttributeInstance reach = player.getAttribute(ForgeMod.REACH_DISTANCE.get()); if (reach != null && reach.hasModifier(ExtendoGripItem.singleRangeAttributeModifier)) diff --git a/src/main/java/com/simibubi/create/content/curiosities/girder/GirderWrenchBehavior.java b/src/main/java/com/simibubi/create/content/decoration/girder/GirderWrenchBehavior.java similarity index 98% rename from src/main/java/com/simibubi/create/content/curiosities/girder/GirderWrenchBehavior.java rename to src/main/java/com/simibubi/create/content/decoration/girder/GirderWrenchBehavior.java index dd8fe7a89..d9e68cf6b 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/girder/GirderWrenchBehavior.java +++ b/src/main/java/com/simibubi/create/content/decoration/girder/GirderWrenchBehavior.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.girder; +package com.simibubi.create.content.decoration.girder; import java.util.Arrays; import java.util.Collections; @@ -9,11 +9,11 @@ import org.jetbrains.annotations.Nullable; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; import com.simibubi.create.CreateClient; +import com.simibubi.create.foundation.placement.IPlacementHelper; import com.simibubi.create.foundation.utility.Color; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Pair; import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.foundation.utility.placement.IPlacementHelper; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; diff --git a/src/main/java/com/simibubi/create/content/palettes/AllPaletteBlocks.java b/src/main/java/com/simibubi/create/content/decoration/palettes/AllPaletteBlocks.java similarity index 95% rename from src/main/java/com/simibubi/create/content/palettes/AllPaletteBlocks.java rename to src/main/java/com/simibubi/create/content/decoration/palettes/AllPaletteBlocks.java index 0e3286466..3fa386acc 100644 --- a/src/main/java/com/simibubi/create/content/palettes/AllPaletteBlocks.java +++ b/src/main/java/com/simibubi/create/content/decoration/palettes/AllPaletteBlocks.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.palettes; +package com.simibubi.create.content.decoration.palettes; import static com.simibubi.create.Create.REGISTRATE; import static com.simibubi.create.foundation.data.WindowGen.customWindowBlock; @@ -10,7 +10,6 @@ import static com.simibubi.create.foundation.data.WindowGen.woodenWindowPane; import com.simibubi.create.AllSpriteShifts; import com.simibubi.create.Create; -import com.simibubi.create.content.AllSections; import com.simibubi.create.foundation.block.connected.HorizontalCTBehaviour; import com.simibubi.create.foundation.block.connected.SimpleCTBehaviour; import com.simibubi.create.foundation.data.BlockStateGen; @@ -31,11 +30,6 @@ import net.minecraftforge.common.Tags; public class AllPaletteBlocks { - static { - REGISTRATE - .startSection(AllSections.PALETTES); - } - // Windows and Glass public static final BlockEntry TILED_GLASS = REGISTRATE.block("tiled_glass", GlassBlock::new) @@ -74,6 +68,7 @@ public class AllPaletteBlocks { JUNGLE_WINDOW = woodenWindowBlock(WoodType.JUNGLE, Blocks.JUNGLE_PLANKS), ACACIA_WINDOW = woodenWindowBlock(WoodType.ACACIA, Blocks.ACACIA_PLANKS), DARK_OAK_WINDOW = woodenWindowBlock(WoodType.DARK_OAK, Blocks.DARK_OAK_PLANKS), + MANGROVE_WINDOW = woodenWindowBlock(WoodType.MANGROVE, Blocks.MANGROVE_PLANKS), CRIMSON_WINDOW = woodenWindowBlock(WoodType.CRIMSON, Blocks.CRIMSON_PLANKS), WARPED_WINDOW = woodenWindowBlock(WoodType.WARPED, Blocks.WARPED_PLANKS), ORNATE_IRON_WINDOW = @@ -87,6 +82,7 @@ public class AllPaletteBlocks { JUNGLE_WINDOW_PANE = woodenWindowPane(WoodType.JUNGLE, JUNGLE_WINDOW), ACACIA_WINDOW_PANE = woodenWindowPane(WoodType.ACACIA, ACACIA_WINDOW), DARK_OAK_WINDOW_PANE = woodenWindowPane(WoodType.DARK_OAK, DARK_OAK_WINDOW), + MANGROVE_WINDOW_PANE = woodenWindowPane(WoodType.MANGROVE, MANGROVE_WINDOW), CRIMSON_WINDOW_PANE = woodenWindowPane(WoodType.CRIMSON, CRIMSON_WINDOW), WARPED_WINDOW_PANE = woodenWindowPane(WoodType.WARPED, WARPED_WINDOW), ORNATE_IRON_WINDOW_PANE = customWindowPane("ornate_iron_window", ORNATE_IRON_WINDOW, diff --git a/src/main/java/com/simibubi/create/content/palettes/AllPaletteStoneTypes.java b/src/main/java/com/simibubi/create/content/decoration/palettes/AllPaletteStoneTypes.java similarity index 86% rename from src/main/java/com/simibubi/create/content/palettes/AllPaletteStoneTypes.java rename to src/main/java/com/simibubi/create/content/decoration/palettes/AllPaletteStoneTypes.java index c39513849..13142b06e 100644 --- a/src/main/java/com/simibubi/create/content/palettes/AllPaletteStoneTypes.java +++ b/src/main/java/com/simibubi/create/content/decoration/palettes/AllPaletteStoneTypes.java @@ -1,7 +1,7 @@ -package com.simibubi.create.content.palettes; +package com.simibubi.create.content.decoration.palettes; -import static com.simibubi.create.content.palettes.PaletteBlockPattern.STANDARD_RANGE; -import static com.simibubi.create.content.palettes.PaletteBlockPattern.VANILLA_RANGE; +import static com.simibubi.create.content.decoration.palettes.PaletteBlockPattern.STANDARD_RANGE; +import static com.simibubi.create.content.decoration.palettes.PaletteBlockPattern.VANILLA_RANGE; import java.util.function.Function; @@ -28,35 +28,35 @@ public enum AllPaletteStoneTypes { DEEPSLATE(VANILLA_RANGE, r -> () -> Blocks.DEEPSLATE), TUFF(VANILLA_RANGE, r -> () -> Blocks.TUFF), - ASURINE(STANDARD_RANGE, r -> r.paletteStoneBlock("asurine", () -> Blocks.DEEPSLATE, true) + ASURINE(STANDARD_RANGE, r -> r.paletteStoneBlock("asurine", () -> Blocks.DEEPSLATE, true, true) .properties(p -> p.destroyTime(1.25f) .color(MaterialColor.COLOR_BLUE)) .register()), - CRIMSITE(STANDARD_RANGE, r -> r.paletteStoneBlock("crimsite", () -> Blocks.DEEPSLATE, true) + CRIMSITE(STANDARD_RANGE, r -> r.paletteStoneBlock("crimsite", () -> Blocks.DEEPSLATE, true, true) .properties(p -> p.destroyTime(1.25f) .color(MaterialColor.COLOR_RED)) .register()), - LIMESTONE(STANDARD_RANGE, r -> r.paletteStoneBlock("limestone", () -> Blocks.SANDSTONE, true) + LIMESTONE(STANDARD_RANGE, r -> r.paletteStoneBlock("limestone", () -> Blocks.SANDSTONE, true, false) .properties(p -> p.destroyTime(1.25f) .color(MaterialColor.SAND)) .register()), - OCHRUM(STANDARD_RANGE, r -> r.paletteStoneBlock("ochrum", () -> Blocks.CALCITE, true) + OCHRUM(STANDARD_RANGE, r -> r.paletteStoneBlock("ochrum", () -> Blocks.CALCITE, true, true) .properties(p -> p.destroyTime(1.25f) .color(MaterialColor.TERRACOTTA_YELLOW)) .register()), - SCORIA(STANDARD_RANGE, r -> r.paletteStoneBlock("scoria", () -> Blocks.BLACKSTONE, true) + SCORIA(STANDARD_RANGE, r -> r.paletteStoneBlock("scoria", () -> Blocks.BLACKSTONE, true, false) .properties(p -> p.color(MaterialColor.COLOR_BROWN)) .register()), - SCORCHIA(STANDARD_RANGE, r -> r.paletteStoneBlock("scorchia", () -> Blocks.BLACKSTONE, true) + SCORCHIA(STANDARD_RANGE, r -> r.paletteStoneBlock("scorchia", () -> Blocks.BLACKSTONE, true, false) .properties(p -> p.color(MaterialColor.TERRACOTTA_GRAY)) .register()), - VERIDIUM(STANDARD_RANGE, r -> r.paletteStoneBlock("veridium", () -> Blocks.TUFF, true) + VERIDIUM(STANDARD_RANGE, r -> r.paletteStoneBlock("veridium", () -> Blocks.TUFF, true, true) .properties(p -> p.destroyTime(1.25f) .color(MaterialColor.WARPED_NYLIUM)) .register()) diff --git a/src/main/java/com/simibubi/create/content/palettes/ConnectedGlassBlock.java b/src/main/java/com/simibubi/create/content/decoration/palettes/ConnectedGlassBlock.java similarity index 94% rename from src/main/java/com/simibubi/create/content/palettes/ConnectedGlassBlock.java rename to src/main/java/com/simibubi/create/content/decoration/palettes/ConnectedGlassBlock.java index d961a0aff..378137545 100644 --- a/src/main/java/com/simibubi/create/content/palettes/ConnectedGlassBlock.java +++ b/src/main/java/com/simibubi/create/content/decoration/palettes/ConnectedGlassBlock.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.palettes; +package com.simibubi.create.content.decoration.palettes; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; diff --git a/src/main/java/com/simibubi/create/content/palettes/ConnectedGlassPaneBlock.java b/src/main/java/com/simibubi/create/content/decoration/palettes/ConnectedGlassPaneBlock.java similarity index 91% rename from src/main/java/com/simibubi/create/content/palettes/ConnectedGlassPaneBlock.java rename to src/main/java/com/simibubi/create/content/decoration/palettes/ConnectedGlassPaneBlock.java index e789ac515..8a67e55f6 100644 --- a/src/main/java/com/simibubi/create/content/palettes/ConnectedGlassPaneBlock.java +++ b/src/main/java/com/simibubi/create/content/decoration/palettes/ConnectedGlassPaneBlock.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.palettes; +package com.simibubi.create.content.decoration.palettes; import net.minecraft.core.Direction; import net.minecraft.world.level.block.state.BlockState; diff --git a/src/main/java/com/simibubi/create/content/palettes/ConnectedPillarBlock.java b/src/main/java/com/simibubi/create/content/decoration/palettes/ConnectedPillarBlock.java similarity index 99% rename from src/main/java/com/simibubi/create/content/palettes/ConnectedPillarBlock.java rename to src/main/java/com/simibubi/create/content/decoration/palettes/ConnectedPillarBlock.java index a8d7c192a..8c2d4ce60 100644 --- a/src/main/java/com/simibubi/create/content/palettes/ConnectedPillarBlock.java +++ b/src/main/java/com/simibubi/create/content/decoration/palettes/ConnectedPillarBlock.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.palettes; +package com.simibubi.create.content.decoration.palettes; import com.simibubi.create.foundation.utility.Iterate; diff --git a/src/main/java/com/simibubi/create/content/palettes/GlassPaneBlock.java b/src/main/java/com/simibubi/create/content/decoration/palettes/GlassPaneBlock.java similarity index 75% rename from src/main/java/com/simibubi/create/content/palettes/GlassPaneBlock.java rename to src/main/java/com/simibubi/create/content/decoration/palettes/GlassPaneBlock.java index ce07f4aee..b9e1f6bc5 100644 --- a/src/main/java/com/simibubi/create/content/palettes/GlassPaneBlock.java +++ b/src/main/java/com/simibubi/create/content/decoration/palettes/GlassPaneBlock.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.palettes; +package com.simibubi.create.content.decoration.palettes; import net.minecraft.world.level.block.IronBarsBlock; diff --git a/src/main/java/com/simibubi/create/content/palettes/LayeredBlock.java b/src/main/java/com/simibubi/create/content/decoration/palettes/LayeredBlock.java similarity index 93% rename from src/main/java/com/simibubi/create/content/palettes/LayeredBlock.java rename to src/main/java/com/simibubi/create/content/decoration/palettes/LayeredBlock.java index e2f84ef33..8bc7f63e9 100644 --- a/src/main/java/com/simibubi/create/content/palettes/LayeredBlock.java +++ b/src/main/java/com/simibubi/create/content/decoration/palettes/LayeredBlock.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.palettes; +package com.simibubi.create.content.decoration.palettes; import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.level.block.RotatedPillarBlock; diff --git a/src/main/java/com/simibubi/create/content/palettes/PaletteBlockPartial.java b/src/main/java/com/simibubi/create/content/decoration/palettes/PaletteBlockPartial.java similarity index 97% rename from src/main/java/com/simibubi/create/content/palettes/PaletteBlockPartial.java rename to src/main/java/com/simibubi/create/content/decoration/palettes/PaletteBlockPartial.java index ab43ccc55..fb500ce31 100644 --- a/src/main/java/com/simibubi/create/content/palettes/PaletteBlockPartial.java +++ b/src/main/java/com/simibubi/create/content/decoration/palettes/PaletteBlockPartial.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.palettes; +package com.simibubi.create.content.decoration.palettes; import static com.simibubi.create.foundation.data.TagGen.pickaxeOnly; @@ -136,7 +136,6 @@ public abstract class PaletteBlockPartial { RecipeCategory category = RecipeCategory.BUILDING_BLOCKS; p.stairs(DataIngredient.items(patternBlock.get()), category, c::get, c.getName(), false); p.stonecutting(DataIngredient.tag(type.materialTag), category, c::get, 1); - p.stonecutting(DataIngredient.items(type.getBaseBlock()), category, c::get, 1); } } @@ -200,7 +199,6 @@ public abstract class PaletteBlockPartial { RecipeCategory category = RecipeCategory.BUILDING_BLOCKS; p.slab(DataIngredient.items(patternBlock.get()), category, c::get, c.getName(), false); p.stonecutting(DataIngredient.tag(type.materialTag), category, c::get, 2); - p.stonecutting(DataIngredient.items(type.getBaseBlock()), category, c::get, 2); DataIngredient ingredient = DataIngredient.items(c.get()); ShapelessRecipeBuilder.shapeless(category, patternBlock.get()) .requires(ingredient) @@ -258,7 +256,6 @@ public abstract class PaletteBlockPartial { DataGenContext c, RegistrateRecipeProvider p) { RecipeCategory category = RecipeCategory.BUILDING_BLOCKS; p.stonecutting(DataIngredient.tag(type.materialTag), category, c::get, 1); - p.stonecutting(DataIngredient.items(type.getBaseBlock()), category, c::get, 1); DataIngredient ingredient = DataIngredient.items(patternBlock.get()); ShapedRecipeBuilder.shaped(category, c.get(), 6) .pattern("XXX") diff --git a/src/main/java/com/simibubi/create/content/palettes/PaletteBlockPattern.java b/src/main/java/com/simibubi/create/content/decoration/palettes/PaletteBlockPattern.java similarity index 93% rename from src/main/java/com/simibubi/create/content/palettes/PaletteBlockPattern.java rename to src/main/java/com/simibubi/create/content/decoration/palettes/PaletteBlockPattern.java index 98419ea0e..7010c2fc7 100644 --- a/src/main/java/com/simibubi/create/content/palettes/PaletteBlockPattern.java +++ b/src/main/java/com/simibubi/create/content/decoration/palettes/PaletteBlockPattern.java @@ -1,10 +1,10 @@ -package com.simibubi.create.content.palettes; +package com.simibubi.create.content.decoration.palettes; -import static com.simibubi.create.content.palettes.PaletteBlockPartial.ALL_PARTIALS; -import static com.simibubi.create.content.palettes.PaletteBlockPartial.FOR_POLISHED; -import static com.simibubi.create.content.palettes.PaletteBlockPattern.PatternNameType.PREFIX; -import static com.simibubi.create.content.palettes.PaletteBlockPattern.PatternNameType.SUFFIX; -import static com.simibubi.create.content.palettes.PaletteBlockPattern.PatternNameType.WRAP; +import static com.simibubi.create.content.decoration.palettes.PaletteBlockPartial.ALL_PARTIALS; +import static com.simibubi.create.content.decoration.palettes.PaletteBlockPartial.FOR_POLISHED; +import static com.simibubi.create.content.decoration.palettes.PaletteBlockPattern.PatternNameType.PREFIX; +import static com.simibubi.create.content.decoration.palettes.PaletteBlockPattern.PatternNameType.SUFFIX; +import static com.simibubi.create.content.decoration.palettes.PaletteBlockPattern.PatternNameType.WRAP; import java.util.Optional; import java.util.function.Function; @@ -21,14 +21,12 @@ import com.simibubi.create.foundation.block.connected.RotatedPillarCTBehaviour; import com.tterrag.registrate.providers.DataGenContext; import com.tterrag.registrate.providers.RegistrateBlockstateProvider; import com.tterrag.registrate.providers.RegistrateRecipeProvider; -import com.tterrag.registrate.util.DataIngredient; import com.tterrag.registrate.util.nullness.NonNullBiConsumer; import com.tterrag.registrate.util.nullness.NonNullFunction; import com.tterrag.registrate.util.nullness.NonNullSupplier; import net.minecraft.client.renderer.RenderType; import net.minecraft.core.Direction.Axis; -import net.minecraft.data.recipes.RecipeCategory; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.TagKey; import net.minecraft.world.item.Item; @@ -130,7 +128,6 @@ public class PaletteBlockPattern { public void addRecipes(NonNullSupplier baseBlock, DataGenContext c, RegistrateRecipeProvider p) { - p.stonecutting(DataIngredient.items(baseBlock), RecipeCategory.BUILDING_BLOCKS, c::get); additionalRecipes.apply(baseBlock) .accept(c, p); } diff --git a/src/main/java/com/simibubi/create/content/palettes/PalettesVariantEntry.java b/src/main/java/com/simibubi/create/content/decoration/palettes/PalettesVariantEntry.java similarity index 83% rename from src/main/java/com/simibubi/create/content/palettes/PalettesVariantEntry.java rename to src/main/java/com/simibubi/create/content/decoration/palettes/PalettesVariantEntry.java index 7fb425f7e..14371e531 100644 --- a/src/main/java/com/simibubi/create/content/palettes/PalettesVariantEntry.java +++ b/src/main/java/com/simibubi/create/content/decoration/palettes/PalettesVariantEntry.java @@ -1,13 +1,15 @@ -package com.simibubi.create.content.palettes; +package com.simibubi.create.content.decoration.palettes; import static com.simibubi.create.Create.REGISTRATE; import static com.simibubi.create.foundation.data.CreateRegistrate.connectedTextures; import static com.simibubi.create.foundation.data.TagGen.pickaxeOnly; import com.google.common.collect.ImmutableList; +import com.simibubi.create.Create; import com.simibubi.create.foundation.data.CreateRegistrate; import com.tterrag.registrate.builders.BlockBuilder; import com.tterrag.registrate.builders.ItemBuilder; +import com.tterrag.registrate.providers.ProviderType; import com.tterrag.registrate.util.DataIngredient; import com.tterrag.registrate.util.entry.BlockEntry; import com.tterrag.registrate.util.nullness.NonNullSupplier; @@ -18,6 +20,7 @@ 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.minecraftforge.registries.ForgeRegistries; public class PalettesVariantEntry { @@ -69,6 +72,14 @@ public class PalettesVariantEntry { .register()); } + Create.REGISTRATE.addDataGenerator(ProviderType.RECIPE, + p -> p.stonecutting(DataIngredient.tag(paletteStoneVariants.materialTag), RecipeCategory.BUILDING_BLOCKS, + baseBlock)); + Create.REGISTRATE.addDataGenerator(ProviderType.ITEM_TAGS, p -> p.tag(paletteStoneVariants.materialTag) + .add(ForgeRegistries.ITEMS.getResourceKey(baseBlock.get() + .asItem()) + .get())); + this.registeredBlocks = registeredBlocks.build(); this.registeredPartials = registeredPartials.build(); } diff --git a/src/main/java/com/simibubi/create/content/palettes/WindowBlock.java b/src/main/java/com/simibubi/create/content/decoration/palettes/WindowBlock.java similarity index 94% rename from src/main/java/com/simibubi/create/content/palettes/WindowBlock.java rename to src/main/java/com/simibubi/create/content/decoration/palettes/WindowBlock.java index c7695ed2b..8c617a0cd 100644 --- a/src/main/java/com/simibubi/create/content/palettes/WindowBlock.java +++ b/src/main/java/com/simibubi/create/content/decoration/palettes/WindowBlock.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.palettes; +package com.simibubi.create.content.decoration.palettes; import net.minecraft.core.Direction; import net.minecraft.world.level.block.state.BlockState; diff --git a/src/main/java/com/simibubi/create/content/curiosities/deco/PlacardBlock.java b/src/main/java/com/simibubi/create/content/decoration/placard/PlacardBlock.java similarity index 86% rename from src/main/java/com/simibubi/create/content/curiosities/deco/PlacardBlock.java rename to src/main/java/com/simibubi/create/content/decoration/placard/PlacardBlock.java index 18b47c848..4b7012c4d 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/deco/PlacardBlock.java +++ b/src/main/java/com/simibubi/create/content/decoration/placard/PlacardBlock.java @@ -1,17 +1,17 @@ -package com.simibubi.create.content.curiosities.deco; +package com.simibubi.create.content.decoration.placard; import java.util.List; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; -import com.simibubi.create.content.logistics.item.filter.FilterItem; -import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement; -import com.simibubi.create.content.schematics.ItemRequirement; -import com.simibubi.create.content.schematics.ItemRequirement.ItemUseType; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.content.logistics.filter.FilterItem; +import com.simibubi.create.content.schematics.requirement.ISpecialBlockItemRequirement; +import com.simibubi.create.content.schematics.requirement.ItemRequirement; +import com.simibubi.create.content.schematics.requirement.ItemRequirement.ItemUseType; +import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.block.ProperWaterloggedBlock; import net.minecraft.core.BlockPos; @@ -43,7 +43,7 @@ import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraftforge.items.ItemHandlerHelper; public class PlacardBlock extends FaceAttachedHorizontalDirectionalBlock - implements ProperWaterloggedBlock, ITE, ISpecialBlockItemRequirement, IWrenchable { + implements ProperWaterloggedBlock, IBE, ISpecialBlockItemRequirement, IWrenchable { public static final BooleanProperty POWERED = BlockStateProperties.POWERED; @@ -122,7 +122,7 @@ public class PlacardBlock extends FaceAttachedHorizontalDirectionalBlock return InteractionResult.SUCCESS; ItemStack inHand = player.getItemInHand(pHand); - return onTileEntityUse(pLevel, pPos, pte -> { + return onBlockEntityUse(pLevel, pPos, pte -> { ItemStack inBlock = pte.getHeldItem(); if (!player.mayBuild() || inHand.isEmpty() || !inBlock.isEmpty()) { @@ -174,7 +174,7 @@ public class PlacardBlock extends FaceAttachedHorizontalDirectionalBlock if (pState.hasBlockEntity() && (blockChanged || !pNewState.hasBlockEntity())) { if (!pIsMoving) - withTileEntityDo(pLevel, pPos, te -> Block.popResource(pLevel, pPos, te.getHeldItem())); + withBlockEntityDo(pLevel, pPos, be -> Block.popResource(pLevel, pPos, be.getHeldItem())); pLevel.removeBlockEntity(pPos); } } @@ -188,7 +188,7 @@ public class PlacardBlock extends FaceAttachedHorizontalDirectionalBlock public void attack(BlockState pState, Level pLevel, BlockPos pPos, Player pPlayer) { if (pLevel.isClientSide) return; - withTileEntityDo(pLevel, pPos, pte -> { + withBlockEntityDo(pLevel, pPos, pte -> { ItemStack heldItem = pte.getHeldItem(); if (heldItem.isEmpty()) return; @@ -200,10 +200,10 @@ public class PlacardBlock extends FaceAttachedHorizontalDirectionalBlock } @Override - public ItemRequirement getRequiredItems(BlockState state, BlockEntity te) { + public ItemRequirement getRequiredItems(BlockState state, BlockEntity be) { ItemStack placardStack = AllBlocks.PLACARD.asStack(); - if (te instanceof PlacardTileEntity pte) { - ItemStack heldItem = pte.getHeldItem(); + if (be instanceof PlacardBlockEntity pbe) { + ItemStack heldItem = pbe.getHeldItem(); if (!heldItem.isEmpty()) { return new ItemRequirement(List.of( new ItemRequirement.StackRequirement(placardStack, ItemUseType.CONSUME), @@ -215,13 +215,13 @@ public class PlacardBlock extends FaceAttachedHorizontalDirectionalBlock } @Override - public Class getTileEntityClass() { - return PlacardTileEntity.class; + public Class getBlockEntityClass() { + return PlacardBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.PLACARD.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.PLACARD.get(); } } diff --git a/src/main/java/com/simibubi/create/content/decoration/placard/PlacardBlockEntity.java b/src/main/java/com/simibubi/create/content/decoration/placard/PlacardBlockEntity.java new file mode 100644 index 000000000..208bd385e --- /dev/null +++ b/src/main/java/com/simibubi/create/content/decoration/placard/PlacardBlockEntity.java @@ -0,0 +1,100 @@ +package com.simibubi.create.content.decoration.placard; + +import java.util.List; + +import org.joml.Vector3f; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.particles.DustParticleOptions; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class PlacardBlockEntity extends SmartBlockEntity { + + ItemStack heldItem; + int poweredTicks; + + public PlacardBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + heldItem = ItemStack.EMPTY; + poweredTicks = 0; + } + + @Override + public void tick() { + super.tick(); + if (level.isClientSide) + return; + if (poweredTicks == 0) + return; + + poweredTicks--; + if (poweredTicks > 0) + return; + + BlockState blockState = getBlockState(); + level.setBlock(worldPosition, blockState.setValue(PlacardBlock.POWERED, false), 3); + PlacardBlock.updateNeighbours(blockState, level, worldPosition); + } + + public ItemStack getHeldItem() { + return heldItem; + } + + public void setHeldItem(ItemStack heldItem) { + this.heldItem = heldItem; + notifyUpdate(); + } + + @Override + protected void write(CompoundTag tag, boolean clientPacket) { + tag.putInt("PoweredTicks", poweredTicks); + tag.put("Item", heldItem.serializeNBT()); + super.write(tag, clientPacket); + } + + @Override + protected void read(CompoundTag tag, boolean clientPacket) { + int prevTicks = poweredTicks; + poweredTicks = tag.getInt("PoweredTicks"); + heldItem = ItemStack.of(tag.getCompound("Item")); + super.read(tag, clientPacket); + + if (clientPacket && prevTicks < poweredTicks) + spawnParticles(); + } + + private void spawnParticles() { + BlockState blockState = getBlockState(); + if (!AllBlocks.PLACARD.has(blockState)) + return; + + DustParticleOptions pParticleData = new DustParticleOptions(new Vector3f(1, .2f, 0), 1); + Vec3 centerOf = VecHelper.getCenterOf(worldPosition); + Vec3 normal = Vec3.atLowerCornerOf(PlacardBlock.connectedDirection(blockState) + .getNormal()); + Vec3 offset = VecHelper.axisAlingedPlaneOf(normal); + + for (int i = 0; i < 10; i++) { + Vec3 v = VecHelper.offsetRandomly(Vec3.ZERO, level.random, .5f) + .multiply(offset) + .normalize() + .scale(.45f) + .add(normal.scale(-.45f)) + .add(centerOf); + level.addParticle(pParticleData, v.x, v.y, v.z, 0, 0, 0); + } + } + + @Override + public void addBehaviours(List behaviours) {} + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/deco/PlacardRenderer.java b/src/main/java/com/simibubi/create/content/decoration/placard/PlacardRenderer.java similarity index 79% rename from src/main/java/com/simibubi/create/content/curiosities/deco/PlacardRenderer.java rename to src/main/java/com/simibubi/create/content/decoration/placard/PlacardRenderer.java index 478ec22e4..7081b98ae 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/deco/PlacardRenderer.java +++ b/src/main/java/com/simibubi/create/content/decoration/placard/PlacardRenderer.java @@ -1,8 +1,8 @@ -package com.simibubi.create.content.curiosities.deco; +package com.simibubi.create.content.decoration.placard; import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; +import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; import com.simibubi.create.foundation.utility.AngleHelper; import net.minecraft.client.Minecraft; @@ -16,18 +16,18 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.AttachFace; -public class PlacardRenderer extends SafeTileEntityRenderer { +public class PlacardRenderer extends SafeBlockEntityRenderer { public PlacardRenderer(BlockEntityRendererProvider.Context context) {} @Override - protected void renderSafe(PlacardTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, + protected void renderSafe(PlacardBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light, int overlay) { - ItemStack heldItem = te.getHeldItem(); + ItemStack heldItem = be.getHeldItem(); if (heldItem.isEmpty()) return; - BlockState blockState = te.getBlockState(); + BlockState blockState = be.getBlockState(); Direction facing = blockState.getValue(PlacardBlock.FACING); AttachFace face = blockState.getValue(PlacardBlock.FACE); diff --git a/src/main/java/com/simibubi/create/content/decoration/slidingDoor/DoorControl.java b/src/main/java/com/simibubi/create/content/decoration/slidingDoor/DoorControl.java new file mode 100644 index 000000000..7c23e4c38 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/decoration/slidingDoor/DoorControl.java @@ -0,0 +1,76 @@ +package com.simibubi.create.content.decoration.slidingDoor; + +import java.util.Arrays; +import java.util.function.Consumer; + +import com.simibubi.create.foundation.gui.widget.Label; +import com.simibubi.create.foundation.gui.widget.ScrollInput; +import com.simibubi.create.foundation.gui.widget.SelectionScrollInput; +import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.Pair; + +import net.minecraft.client.Minecraft; +import net.minecraft.core.Direction; +import net.minecraft.world.entity.Entity; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public enum DoorControl { + + ALL, NORTH, EAST, SOUTH, WEST, NONE; + + private static String[] valuesAsString() { + DoorControl[] values = values(); + return Arrays.stream(values) + .map(dc -> Lang.asId(dc.name())) + .toList() + .toArray(new String[values.length]); + } + + public boolean matches(Direction doorDirection) { + return switch (this) { + case ALL -> true; + case NORTH -> doorDirection == Direction.NORTH; + case EAST -> doorDirection == Direction.EAST; + case SOUTH -> doorDirection == Direction.SOUTH; + case WEST -> doorDirection == Direction.WEST; + default -> false; + }; + } + + @OnlyIn(Dist.CLIENT) + public static Pair createWidget(int x, int y, Consumer callback, + DoorControl initial) { + + DoorControl playerFacing = NONE; + Entity cameraEntity = Minecraft.getInstance().cameraEntity; + if (cameraEntity != null) { + Direction direction = cameraEntity.getDirection(); + if (direction == Direction.EAST) + playerFacing = EAST; + if (direction == Direction.WEST) + playerFacing = WEST; + if (direction == Direction.NORTH) + playerFacing = NORTH; + if (direction == Direction.SOUTH) + playerFacing = SOUTH; + } + + Label label = new Label(x + 4, y + 6, Components.empty()).withShadow(); + ScrollInput input = new SelectionScrollInput(x, y, 53, 16) + .forOptions(Lang.translatedOptions("contraption.door_control", valuesAsString())) + .titled(Lang.translateDirect("contraption.door_control")) + .calling(s -> { + DoorControl mode = values()[s]; + label.text = Lang.translateDirect("contraption.door_control." + Lang.asId(mode.name()) + ".short"); + callback.accept(mode); + }) + .addHint(Lang.translateDirect("contraption.door_control.player_facing", + Lang.translateDirect("contraption.door_control." + Lang.asId(playerFacing.name()) + ".short"))) + .setState(initial.ordinal()); + input.onChanged(); + return Pair.of(input, label); + } + +} diff --git a/src/main/java/com/simibubi/create/content/decoration/slidingDoor/DoorControlBehaviour.java b/src/main/java/com/simibubi/create/content/decoration/slidingDoor/DoorControlBehaviour.java new file mode 100644 index 000000000..755dca038 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/decoration/slidingDoor/DoorControlBehaviour.java @@ -0,0 +1,45 @@ +package com.simibubi.create.content.decoration.slidingDoor; + +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.NBTHelper; + +import net.minecraft.nbt.CompoundTag; + +public class DoorControlBehaviour extends BlockEntityBehaviour { + + public static final BehaviourType TYPE = new BehaviourType<>(); + + public DoorControl mode; + + public DoorControlBehaviour(SmartBlockEntity be) { + super(be); + mode = DoorControl.ALL; + } + + public void set(DoorControl mode) { + if (this.mode == mode) + return; + this.mode = mode; + blockEntity.notifyUpdate(); + } + + @Override + public void write(CompoundTag nbt, boolean clientPacket) { + NBTHelper.writeEnum(nbt, "DoorControl", mode); + super.write(nbt, clientPacket); + } + + @Override + public void read(CompoundTag nbt, boolean clientPacket) { + mode = NBTHelper.readEnum(nbt, "DoorControl", DoorControl.class); + super.read(nbt, clientPacket); + } + + @Override + public BehaviourType getType() { + return TYPE; + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/deco/SlidingDoorBlock.java b/src/main/java/com/simibubi/create/content/decoration/slidingDoor/SlidingDoorBlock.java similarity index 83% rename from src/main/java/com/simibubi/create/content/curiosities/deco/SlidingDoorBlock.java rename to src/main/java/com/simibubi/create/content/decoration/slidingDoor/SlidingDoorBlock.java index 69c694965..2f52de0dd 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/deco/SlidingDoorBlock.java +++ b/src/main/java/com/simibubi/create/content/decoration/slidingDoor/SlidingDoorBlock.java @@ -1,11 +1,11 @@ -package com.simibubi.create.content.curiosities.deco; +package com.simibubi.create.content.decoration.slidingDoor; import javax.annotation.Nullable; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionWorld; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.content.contraptions.ContraptionWorld; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.foundation.block.IBE; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -36,24 +36,18 @@ import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; -public class SlidingDoorBlock extends DoorBlock implements IWrenchable, ITE { - - protected static final VoxelShape SE_AABB = Block.box(0.0D, 0.0D, -13.0D, 3.0D, 16.0D, 3.0D); - protected static final VoxelShape ES_AABB = Block.box(-13.0D, 0.0D, 0.0D, 3.0D, 16.0D, 3.0D); - - protected static final VoxelShape NW_AABB = Block.box(13.0D, 0.0D, 13.0D, 16.0D, 16.0D, 29.0D); - protected static final VoxelShape WN_AABB = Block.box(13.0D, 0.0D, 13.0D, 29.0D, 16.0D, 16.0D); - - protected static final VoxelShape SW_AABB = Block.box(13.0D, 0.0D, -13.0D, 16.0D, 16.0D, 3.0D); - protected static final VoxelShape WS_AABB = Block.box(13.0D, 0.0D, 0.0D, 29.0D, 16.0D, 3.0D); - - protected static final VoxelShape NE_AABB = Block.box(0.0D, 0.0D, 13.0D, 3.0D, 16.0D, 29.0D); - protected static final VoxelShape EN_AABB = Block.box(-13.0D, 0.0D, 13.0D, 3.0D, 16.0D, 16.0D); +public class SlidingDoorBlock extends DoorBlock implements IWrenchable, IBE { public static final BooleanProperty VISIBLE = BooleanProperty.create("visible"); + private boolean folds; - public SlidingDoorBlock(Properties p_52737_) { + public SlidingDoorBlock(Properties p_52737_, boolean folds) { super(p_52737_, SoundEvents.IRON_DOOR_CLOSE, SoundEvents.IRON_DOOR_OPEN); + this.folds = folds; + } + + public boolean isFoldingDoor() { + return folds; } @Override @@ -68,13 +62,7 @@ public class SlidingDoorBlock extends DoorBlock implements IWrenchable, ITE (hinge ? ES_AABB : WS_AABB); - case WEST -> (hinge ? SW_AABB : NW_AABB); - case NORTH -> (hinge ? WN_AABB : EN_AABB); - default -> (hinge ? NE_AABB : SE_AABB); - }; + return SlidingDoorShapes.get(direction, hinge, isFoldingDoor()); } @Override @@ -152,8 +140,8 @@ public class SlidingDoorBlock extends DoorBlock implements IWrenchable, ITE sdte.deferUpdate = true); + withBlockEntityDo(level, pos, sdte -> sdte.deferUpdate = true); } public static boolean isDoubleDoor(BlockState pState, DoorHingeSide hinge, Direction facing, BlockState otherDoor) { @@ -248,17 +236,17 @@ public class SlidingDoorBlock extends DoorBlock implements IWrenchable, ITE getTileEntityClass() { - return SlidingDoorTileEntity.class; + public Class getBlockEntityClass() { + return SlidingDoorBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.SLIDING_DOOR.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.SLIDING_DOOR.get(); } } diff --git a/src/main/java/com/simibubi/create/content/decoration/slidingDoor/SlidingDoorBlockEntity.java b/src/main/java/com/simibubi/create/content/decoration/slidingDoor/SlidingDoorBlockEntity.java new file mode 100644 index 000000000..20d9b0be3 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/decoration/slidingDoor/SlidingDoorBlockEntity.java @@ -0,0 +1,84 @@ +package com.simibubi.create.content.decoration.slidingDoor; + +import java.util.List; + +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; + +import net.minecraft.core.BlockPos; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.DoorBlock; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; + +public class SlidingDoorBlockEntity extends SmartBlockEntity { + + LerpedFloat animation; + int bridgeTicks; + boolean deferUpdate; + + public SlidingDoorBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + animation = LerpedFloat.linear() + .startWithValue(isOpen(state) ? 1 : 0); + } + + @Override + public void tick() { + if (deferUpdate && !level.isClientSide()) { + deferUpdate = false; + BlockState blockState = getBlockState(); + blockState.neighborChanged(level, worldPosition, Blocks.AIR, worldPosition, false); + } + + super.tick(); + boolean open = isOpen(getBlockState()); + boolean wasSettled = animation.settled(); + animation.chase(open ? 1 : 0, .15f, Chaser.LINEAR); + animation.tickChaser(); + + if (level.isClientSide()) { + if (bridgeTicks < 2 && open) + bridgeTicks++; + else if (bridgeTicks > 0 && !open && isVisible(getBlockState())) + bridgeTicks--; + return; + } + + if (!open && !wasSettled && animation.settled() && !isVisible(getBlockState())) + showBlockModel(); + } + + @Override + protected AABB createRenderBoundingBox() { + return super.createRenderBoundingBox().inflate(1); + } + + protected boolean isVisible(BlockState state) { + return state.getOptionalValue(SlidingDoorBlock.VISIBLE) + .orElse(true); + } + + protected boolean shouldRenderSpecial(BlockState state) { + return !isVisible(state) || bridgeTicks != 0; + } + + protected void showBlockModel() { + level.setBlock(worldPosition, getBlockState().setValue(SlidingDoorBlock.VISIBLE, true), 3); + level.playSound(null, worldPosition, SoundEvents.IRON_DOOR_CLOSE, SoundSource.BLOCKS, .5f, 1); + } + + @Override + public void addBehaviours(List behaviours) {} + + public static boolean isOpen(BlockState state) { + return state.getOptionalValue(DoorBlock.OPEN) + .orElse(false); + } + +} diff --git a/src/main/java/com/simibubi/create/content/decoration/slidingDoor/SlidingDoorMovementBehaviour.java b/src/main/java/com/simibubi/create/content/decoration/slidingDoor/SlidingDoorMovementBehaviour.java new file mode 100644 index 000000000..8cd5a9c13 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/decoration/slidingDoor/SlidingDoorMovementBehaviour.java @@ -0,0 +1,206 @@ +package com.simibubi.create.content.decoration.slidingDoor; + +import java.lang.ref.WeakReference; +import java.util.Map; + +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.contraptions.elevator.ElevatorColumn; +import com.simibubi.create.content.contraptions.elevator.ElevatorColumn.ColumnCoords; +import com.simibubi.create.content.contraptions.elevator.ElevatorContraption; +import com.simibubi.create.content.trains.entity.Carriage; +import com.simibubi.create.content.trains.entity.CarriageContraptionEntity; +import com.simibubi.create.content.trains.station.GlobalStation; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.resources.ResourceKey; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.DoorBlock; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; +import net.minecraft.world.phys.Vec3; + +public class SlidingDoorMovementBehaviour implements MovementBehaviour { + + @Override + public boolean renderAsNormalBlockEntity() { + return true; + } + + @Override + public boolean mustTickWhileDisabled() { + return true; + } + + @Override + public void tick(MovementContext context) { + StructureBlockInfo structureBlockInfo = context.contraption.getBlocks() + .get(context.localPos); + if (structureBlockInfo == null) + return; + boolean open = SlidingDoorBlockEntity.isOpen(structureBlockInfo.state); + + if (!context.world.isClientSide()) + tickOpen(context, open); + + Map tes = context.contraption.presentBlockEntities; + if (!(tes.get(context.localPos) instanceof SlidingDoorBlockEntity sdbe)) + return; + boolean wasSettled = sdbe.animation.settled(); + sdbe.animation.chase(open ? 1 : 0, .15f, Chaser.LINEAR); + sdbe.animation.tickChaser(); + + if (!wasSettled && sdbe.animation.settled() && !open) + context.world.playLocalSound(context.position.x, context.position.y, context.position.z, + SoundEvents.IRON_DOOR_CLOSE, SoundSource.BLOCKS, .125f, 1, false); + } + + protected void tickOpen(MovementContext context, boolean currentlyOpen) { + boolean shouldOpen = shouldOpen(context); + if (!shouldUpdate(context, shouldOpen)) + return; + if (currentlyOpen == shouldOpen) + return; + + BlockPos pos = context.localPos; + Contraption contraption = context.contraption; + + StructureBlockInfo info = contraption.getBlocks() + .get(pos); + if (info == null || !info.state.hasProperty(DoorBlock.OPEN)) + return; + + toggleDoor(pos, contraption, info); + + if (shouldOpen) + context.world.playSound(null, new BlockPos(context.position), SoundEvents.IRON_DOOR_OPEN, + SoundSource.BLOCKS, .125f, 1); + } + + private void toggleDoor(BlockPos pos, Contraption contraption, StructureBlockInfo info) { + BlockState newState = info.state.cycle(DoorBlock.OPEN); + contraption.entity.setBlock(pos, new StructureBlockInfo(info.pos, newState, info.nbt)); + + BlockPos otherPos = newState.getValue(DoorBlock.HALF) == DoubleBlockHalf.LOWER ? pos.above() : pos.below(); + info = contraption.getBlocks() + .get(otherPos); + if (info != null && info.state.hasProperty(DoorBlock.OPEN)) { + newState = info.state.cycle(DoorBlock.OPEN); + contraption.entity.setBlock(otherPos, new StructureBlockInfo(info.pos, newState, info.nbt)); + contraption.invalidateColliders(); + } + } + + protected boolean shouldUpdate(MovementContext context, boolean shouldOpen) { + if (context.firstMovement && shouldOpen) + return false; + if (!context.data.contains("Open")) { + context.data.putBoolean("Open", shouldOpen); + return true; + } + boolean wasOpen = context.data.getBoolean("Open"); + context.data.putBoolean("Open", shouldOpen); + return wasOpen != shouldOpen; + } + + protected boolean shouldOpen(MovementContext context) { + if (context.disabled) + return false; + Contraption contraption = context.contraption; + boolean canOpen = context.motion.length() < 1 / 128f && !contraption.entity.isStalled() + || contraption instanceof ElevatorContraption ec && ec.arrived; + + if (!canOpen) { + context.temporaryData = null; + return false; + } + + if (context.temporaryData instanceof WeakReference wr && wr.get()instanceof DoorControlBehaviour dcb) + if (dcb.blockEntity != null && !dcb.blockEntity.isRemoved()) + return shouldOpenAt(dcb, context); + + context.temporaryData = null; + DoorControlBehaviour doorControls = null; + + if (contraption instanceof ElevatorContraption ec) + doorControls = getElevatorDoorControl(ec, context); + if (context.contraption.entity instanceof CarriageContraptionEntity cce) + doorControls = getTrainStationDoorControl(cce, context); + + if (doorControls == null) + return false; + + context.temporaryData = new WeakReference<>(doorControls); + return shouldOpenAt(doorControls, context); + } + + protected boolean shouldOpenAt(DoorControlBehaviour controller, MovementContext context) { + if (controller.mode == DoorControl.ALL) + return true; + if (controller.mode == DoorControl.NONE) + return false; + return controller.mode.matches(getDoorFacing(context)); + } + + protected DoorControlBehaviour getElevatorDoorControl(ElevatorContraption ec, MovementContext context) { + Integer currentTargetY = ec.getCurrentTargetY(context.world); + if (currentTargetY == null) + return null; + ColumnCoords columnCoords = ec.getGlobalColumn(); + if (columnCoords == null) + return null; + ElevatorColumn elevatorColumn = ElevatorColumn.get(context.world, columnCoords); + if (elevatorColumn == null) + return null; + return BlockEntityBehaviour.get(context.world, elevatorColumn.contactAt(currentTargetY), + DoorControlBehaviour.TYPE); + } + + protected DoorControlBehaviour getTrainStationDoorControl(CarriageContraptionEntity cce, MovementContext context) { + Carriage carriage = cce.getCarriage(); + if (carriage == null || carriage.train == null) + return null; + GlobalStation currentStation = carriage.train.getCurrentStation(); + if (currentStation == null) + return null; + + BlockPos stationPos = currentStation.getBlockEntityPos(); + ResourceKey stationDim = currentStation.getBlockEntityDimension(); + MinecraftServer server = context.world.getServer(); + if (server == null) + return null; + ServerLevel stationLevel = server.getLevel(stationDim); + if (stationLevel == null || !stationLevel.isLoaded(stationPos)) + return null; + return BlockEntityBehaviour.get(stationLevel, stationPos, DoorControlBehaviour.TYPE); + } + + protected Direction getDoorFacing(MovementContext context) { + Direction stateFacing = context.state.getValue(DoorBlock.FACING); + Direction originalFacing = Direction.get(AxisDirection.POSITIVE, stateFacing.getAxis()); + Vec3 centerOfContraption = context.contraption.bounds.getCenter(); + Vec3 diff = Vec3.atCenterOf(context.localPos) + .add(Vec3.atLowerCornerOf(stateFacing.getNormal()) + .scale(-.45f)) + .subtract(centerOfContraption); + if (originalFacing.getAxis() + .choose(diff.x, diff.y, diff.z) < 0) + originalFacing = originalFacing.getOpposite(); + + Vec3 directionVec = Vec3.atLowerCornerOf(originalFacing.getNormal()); + directionVec = context.rotation.apply(directionVec); + return Direction.getNearest(directionVec.x, directionVec.y, directionVec.z); + } + +} diff --git a/src/main/java/com/simibubi/create/content/decoration/slidingDoor/SlidingDoorRenderer.java b/src/main/java/com/simibubi/create/content/decoration/slidingDoor/SlidingDoorRenderer.java new file mode 100644 index 000000000..5d1338066 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/decoration/slidingDoor/SlidingDoorRenderer.java @@ -0,0 +1,96 @@ +package com.simibubi.create.content.decoration.slidingDoor; + +import com.jozufozu.flywheel.core.PartialModel; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.Couple; +import com.simibubi.create.foundation.utility.Iterate; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider.Context; +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; +import net.minecraft.world.level.block.DoorBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.DoorHingeSide; +import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.registries.ForgeRegistries; + +public class SlidingDoorRenderer extends SafeBlockEntityRenderer { + + public SlidingDoorRenderer(Context context) {} + + @Override + protected void renderSafe(SlidingDoorBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + BlockState blockState = be.getBlockState(); + if (!be.shouldRenderSpecial(blockState)) + return; + + Direction facing = blockState.getValue(DoorBlock.FACING); + Direction movementDirection = facing.getClockWise(); + + if (blockState.getValue(DoorBlock.HINGE) == DoorHingeSide.LEFT) + movementDirection = movementDirection.getOpposite(); + + float value = be.animation.getValue(partialTicks); + float value2 = Mth.clamp(value * 10, 0, 1); + + VertexConsumer vb = buffer.getBuffer(RenderType.cutoutMipped()); + Vec3 offset = Vec3.atLowerCornerOf(movementDirection.getNormal()) + .scale(value * value * 13 / 16f) + .add(Vec3.atLowerCornerOf(facing.getNormal()) + .scale(value2 * 1 / 32f)); + + if (((SlidingDoorBlock) blockState.getBlock()).isFoldingDoor()) { + Couple partials = + AllPartialModels.FOLDING_DOORS.get(ForgeRegistries.BLOCKS.getKey(blockState.getBlock())); + + boolean flip = blockState.getValue(DoorBlock.HINGE) == DoorHingeSide.RIGHT; + for (boolean left : Iterate.trueAndFalse) { + SuperByteBuffer partial = CachedBufferer.partial(partials.get(left ^ flip), blockState); + float f = flip ? -1 : 1; + + partial.translate(0, -1 / 512f, 0) + .translate(Vec3.atLowerCornerOf(facing.getNormal()) + .scale(value2 * 1 / 32f)); + partial.rotateCentered(Direction.UP, + Mth.DEG_TO_RAD * AngleHelper.horizontalAngle(facing.getClockWise())); + + if (flip) + partial.translate(0, 0, 1); + partial.rotateY(91 * f * value * value); + + if (!left) + partial.translate(0, 0, f / 2f) + .rotateY(-181 * f * value * value); + + if (flip) + partial.translate(0, 0, -1 / 2f); + + partial.light(light) + .renderInto(ms, vb); + } + + return; + } + + for (DoubleBlockHalf half : DoubleBlockHalf.values()) { + CachedBufferer.block(blockState.setValue(DoorBlock.OPEN, false) + .setValue(DoorBlock.HALF, half)) + .translate(0, half == DoubleBlockHalf.UPPER ? 1 - 1 / 512f : 0, 0) + .translate(offset) + .light(light) + .renderInto(ms, vb); + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/decoration/slidingDoor/SlidingDoorShapes.java b/src/main/java/com/simibubi/create/content/decoration/slidingDoor/SlidingDoorShapes.java new file mode 100644 index 000000000..54697ac86 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/decoration/slidingDoor/SlidingDoorShapes.java @@ -0,0 +1,44 @@ +package com.simibubi.create.content.decoration.slidingDoor; + +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.phys.shapes.VoxelShape; + +public class SlidingDoorShapes { + + protected static final VoxelShape SE_AABB = Block.box(0.0D, 0.0D, -13.0D, 3.0D, 16.0D, 3.0D); + protected static final VoxelShape ES_AABB = Block.box(-13.0D, 0.0D, 0.0D, 3.0D, 16.0D, 3.0D); + protected static final VoxelShape NW_AABB = Block.box(13.0D, 0.0D, 13.0D, 16.0D, 16.0D, 29.0D); + protected static final VoxelShape WN_AABB = Block.box(13.0D, 0.0D, 13.0D, 29.0D, 16.0D, 16.0D); + protected static final VoxelShape SW_AABB = Block.box(13.0D, 0.0D, -13.0D, 16.0D, 16.0D, 3.0D); + protected static final VoxelShape WS_AABB = Block.box(13.0D, 0.0D, 0.0D, 29.0D, 16.0D, 3.0D); + protected static final VoxelShape NE_AABB = Block.box(0.0D, 0.0D, 13.0D, 3.0D, 16.0D, 29.0D); + protected static final VoxelShape EN_AABB = Block.box(-13.0D, 0.0D, 13.0D, 3.0D, 16.0D, 16.0D); + + protected static final VoxelShape SE_AABB_FOLD = Block.box(0.0D, 0.0D, -3.0D, 9.0D, 16.0D, 3.0D); + protected static final VoxelShape ES_AABB_FOLD = Block.box(-3.0D, 0.0D, 0.0D, 3.0D, 16.0D, 9.0D); + protected static final VoxelShape NW_AABB_FOLD = Block.box(7.0D, 0.0D, 13.0D, 16.0D, 16.0D, 19.0D); + protected static final VoxelShape WN_AABB_FOLD = Block.box(13.0D, 0.0D, 7.0D, 19.0D, 16.0D, 16.0D); + protected static final VoxelShape SW_AABB_FOLD = Block.box(7.0D, 0.0D, -3.0D, 16.0D, 16.0D, 3.0D); + protected static final VoxelShape WS_AABB_FOLD = Block.box(13.0D, 0.0D, 0.0D, 19.0D, 16.0D, 9.0D); + protected static final VoxelShape NE_AABB_FOLD = Block.box(0.0D, 0.0D, 13.0D, 9.0D, 16.0D, 19.0D); + protected static final VoxelShape EN_AABB_FOLD = Block.box(-3.0D, 0.0D, 7.0D, 3.0D, 16.0D, 16.0D); + + public static VoxelShape get(Direction facing, boolean hinge, boolean fold) { + if (fold) + return switch (facing) { + case SOUTH -> (hinge ? ES_AABB_FOLD : WS_AABB_FOLD); + case WEST -> (hinge ? SW_AABB_FOLD : NW_AABB_FOLD); + case NORTH -> (hinge ? WN_AABB_FOLD : EN_AABB_FOLD); + default -> (hinge ? NE_AABB_FOLD : SE_AABB_FOLD); + }; + + return switch (facing) { + case SOUTH -> (hinge ? ES_AABB : WS_AABB); + case WEST -> (hinge ? SW_AABB : NW_AABB); + case NORTH -> (hinge ? WN_AABB : EN_AABB); + default -> (hinge ? NE_AABB : SE_AABB); + }; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/steam/whistle/WhistleBlock.java b/src/main/java/com/simibubi/create/content/decoration/steamWhistle/WhistleBlock.java similarity index 91% rename from src/main/java/com/simibubi/create/content/contraptions/components/steam/whistle/WhistleBlock.java rename to src/main/java/com/simibubi/create/content/decoration/steamWhistle/WhistleBlock.java index e0160654d..5458e69af 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/steam/whistle/WhistleBlock.java +++ b/src/main/java/com/simibubi/create/content/decoration/steamWhistle/WhistleBlock.java @@ -1,13 +1,13 @@ -package com.simibubi.create.content.contraptions.components.steam.whistle; +package com.simibubi.create.content.decoration.steamWhistle; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.components.steam.whistle.WhistleExtenderBlock.WhistleExtenderShape; -import com.simibubi.create.content.contraptions.fluids.tank.FluidTankBlock; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; +import com.simibubi.create.content.decoration.steamWhistle.WhistleExtenderBlock.WhistleExtenderShape; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.content.fluids.tank.FluidTankBlock; import com.simibubi.create.foundation.advancement.AdvancementBehaviour; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.utility.Lang; import net.minecraft.core.BlockPos; @@ -46,7 +46,7 @@ import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; -public class WhistleBlock extends Block implements ITE, IWrenchable { +public class WhistleBlock extends Block implements IBE, IWrenchable { public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING; public static final BooleanProperty WALL = BooleanProperty.create("wall"); @@ -180,7 +180,7 @@ public class WhistleBlock extends Block implements ITE, IWren @Override public void tick(BlockState pState, ServerLevel pLevel, BlockPos pPos, RandomSource pRandom) { - withTileEntityDo(pLevel, pPos, WhistleTileEntity::updatePitch); + withBlockEntityDo(pLevel, pPos, WhistleBlockEntity::updatePitch); } @Override @@ -192,7 +192,7 @@ public class WhistleBlock extends Block implements ITE, IWren @Override public void onRemove(BlockState pState, Level pLevel, BlockPos pPos, BlockState pNewState, boolean pIsMoving) { - ITE.onRemove(pState, pLevel, pPos, pNewState); + IBE.onRemove(pState, pLevel, pPos, pNewState); FluidTankBlock.updateBoilerState(pState, pLevel, pPos.relative(getAttachedDirection(pState))); } @@ -234,13 +234,13 @@ public class WhistleBlock extends Block implements ITE, IWren } @Override - public Class getTileEntityClass() { - return WhistleTileEntity.class; + public Class getBlockEntityClass() { + return WhistleBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.STEAM_WHISTLE.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.STEAM_WHISTLE.get(); } @Override diff --git a/src/main/java/com/simibubi/create/content/decoration/steamWhistle/WhistleBlockEntity.java b/src/main/java/com/simibubi/create/content/decoration/steamWhistle/WhistleBlockEntity.java new file mode 100644 index 000000000..70b8fecce --- /dev/null +++ b/src/main/java/com/simibubi/create/content/decoration/steamWhistle/WhistleBlockEntity.java @@ -0,0 +1,197 @@ +package com.simibubi.create.content.decoration.steamWhistle; + +import java.lang.ref.WeakReference; +import java.util.List; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.content.decoration.steamWhistle.WhistleBlock.WhistleSize; +import com.simibubi.create.content.decoration.steamWhistle.WhistleExtenderBlock.WhistleExtenderShape; +import com.simibubi.create.content.equipment.goggles.IHaveGoggleInformation; +import com.simibubi.create.content.fluids.tank.FluidTankBlockEntity; +import com.simibubi.create.content.kinetics.steamEngine.SteamJetParticleData; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; + +import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.util.Mth; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.fml.DistExecutor; + +public class WhistleBlockEntity extends SmartBlockEntity implements IHaveGoggleInformation { + + public WeakReference source; + public LerpedFloat animation; + protected int pitch; + + public WhistleBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + source = new WeakReference<>(null); + animation = LerpedFloat.linear(); + } + + @Override + public void addBehaviours(List behaviours) { + registerAwardables(behaviours, AllAdvancements.STEAM_WHISTLE); + } + + public void updatePitch() { + BlockPos currentPos = worldPosition.above(); + int newPitch; + for (newPitch = 0; newPitch <= 24; newPitch += 2) { + BlockState blockState = level.getBlockState(currentPos); + if (!AllBlocks.STEAM_WHISTLE_EXTENSION.has(blockState)) + break; + if (blockState.getValue(WhistleExtenderBlock.SHAPE) == WhistleExtenderShape.SINGLE) { + newPitch++; + break; + } + currentPos = currentPos.above(); + } + if (pitch == newPitch) + return; + pitch = newPitch; + + notifyUpdate(); + + FluidTankBlockEntity tank = getTank(); + if (tank != null && tank.boiler != null) + tank.boiler.checkPipeOrganAdvancement(tank); + } + + @Override + public void tick() { + super.tick(); + if (!level.isClientSide()) { + if (isPowered()) + award(AllAdvancements.STEAM_WHISTLE); + return; + } + + FluidTankBlockEntity tank = getTank(); + boolean powered = isPowered() + && (tank != null && tank.boiler.isActive() && (tank.boiler.passiveHeat || tank.boiler.activeHeat > 0) + || isVirtual()); + animation.chase(powered ? 1 : 0, powered ? .5f : .4f, powered ? Chaser.EXP : Chaser.LINEAR); + animation.tickChaser(); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> this.tickAudio(getOctave(), powered)); + } + + @Override + protected void write(CompoundTag tag, boolean clientPacket) { + tag.putInt("Pitch", pitch); + super.write(tag, clientPacket); + } + + @Override + protected void read(CompoundTag tag, boolean clientPacket) { + pitch = tag.getInt("Pitch"); + super.read(tag, clientPacket); + } + + @Override + public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { + String[] pitches = Lang.translateDirect("generic.notes") + .getString() + .split(";"); + MutableComponent textComponent = Components.literal(spacing); + tooltip.add(textComponent.append(Lang.translateDirect("generic.pitch", pitches[pitch % pitches.length]))); + return true; + } + + protected boolean isPowered() { + return getBlockState().getOptionalValue(WhistleBlock.POWERED) + .orElse(false); + } + + protected WhistleSize getOctave() { + return getBlockState().getOptionalValue(WhistleBlock.SIZE) + .orElse(WhistleSize.MEDIUM); + } + + @OnlyIn(Dist.CLIENT) + protected WhistleSoundInstance soundInstance; + + @OnlyIn(Dist.CLIENT) + protected void tickAudio(WhistleSize size, boolean powered) { + if (!powered) { + if (soundInstance != null) { + soundInstance.fadeOut(); + soundInstance = null; + } + return; + } + + float f = (float) Math.pow(2, -pitch / 12.0); + boolean particle = level.getGameTime() % 8 == 0; + Vec3 eyePosition = Minecraft.getInstance().cameraEntity.getEyePosition(); + float maxVolume = (float) Mth.clamp((64 - eyePosition.distanceTo(Vec3.atCenterOf(worldPosition))) / 64, 0, 1); + + if (soundInstance == null || soundInstance.isStopped() || soundInstance.getOctave() != size) { + Minecraft.getInstance() + .getSoundManager() + .play(soundInstance = new WhistleSoundInstance(size, worldPosition)); + AllSoundEvents.WHISTLE_CHIFF.playAt(level, worldPosition, maxVolume * .175f, + size == WhistleSize.SMALL ? f + .75f : f, false); + particle = true; + } + + soundInstance.keepAlive(); + soundInstance.setPitch(f); + + if (!particle) + return; + + Direction facing = getBlockState().getOptionalValue(WhistleBlock.FACING) + .orElse(Direction.SOUTH); + float angle = 180 + AngleHelper.horizontalAngle(facing); + Vec3 sizeOffset = VecHelper.rotate(new Vec3(0, -0.4f, 1 / 16f * size.ordinal()), angle, Axis.Y); + Vec3 offset = VecHelper.rotate(new Vec3(0, 1, 0.75f), angle, Axis.Y); + Vec3 v = offset.scale(.45f) + .add(sizeOffset) + .add(Vec3.atCenterOf(worldPosition)); + Vec3 m = offset.subtract(Vec3.atLowerCornerOf(facing.getNormal()) + .scale(.75f)); + level.addParticle(new SteamJetParticleData(1), v.x, v.y, v.z, m.x, m.y, m.z); + } + + public int getPitchId() { + return pitch + 100 * getBlockState().getOptionalValue(WhistleBlock.SIZE) + .orElse(WhistleSize.MEDIUM) + .ordinal(); + } + + public FluidTankBlockEntity getTank() { + FluidTankBlockEntity tank = source.get(); + if (tank == null || tank.isRemoved()) { + if (tank != null) + source = new WeakReference<>(null); + Direction facing = WhistleBlock.getAttachedDirection(getBlockState()); + BlockEntity be = level.getBlockEntity(worldPosition.relative(facing)); + if (be instanceof FluidTankBlockEntity tankBe) + source = new WeakReference<>(tank = tankBe); + } + if (tank == null) + return null; + return tank.getControllerBE(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/steam/whistle/WhistleExtenderBlock.java b/src/main/java/com/simibubi/create/content/decoration/steamWhistle/WhistleExtenderBlock.java similarity index 96% rename from src/main/java/com/simibubi/create/content/contraptions/components/steam/whistle/WhistleExtenderBlock.java rename to src/main/java/com/simibubi/create/content/decoration/steamWhistle/WhistleExtenderBlock.java index 8fd4dd69a..9027d07d7 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/steam/whistle/WhistleExtenderBlock.java +++ b/src/main/java/com/simibubi/create/content/decoration/steamWhistle/WhistleExtenderBlock.java @@ -1,9 +1,9 @@ -package com.simibubi.create.content.contraptions.components.steam.whistle; +package com.simibubi.create.content.decoration.steamWhistle; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; -import com.simibubi.create.content.contraptions.components.steam.whistle.WhistleBlock.WhistleSize; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; +import com.simibubi.create.content.decoration.steamWhistle.WhistleBlock.WhistleSize; +import com.simibubi.create.content.equipment.wrench.IWrenchable; import com.simibubi.create.foundation.utility.Lang; import net.minecraft.core.BlockPos; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/steam/whistle/WhistleGenerator.java b/src/main/java/com/simibubi/create/content/decoration/steamWhistle/WhistleGenerator.java similarity index 95% rename from src/main/java/com/simibubi/create/content/contraptions/components/steam/whistle/WhistleGenerator.java rename to src/main/java/com/simibubi/create/content/decoration/steamWhistle/WhistleGenerator.java index 15317a1ca..2923980a7 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/steam/whistle/WhistleGenerator.java +++ b/src/main/java/com/simibubi/create/content/decoration/steamWhistle/WhistleGenerator.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.steam.whistle; +package com.simibubi.create.content.decoration.steamWhistle; import com.simibubi.create.Create; import com.simibubi.create.foundation.data.AssetLookup; diff --git a/src/main/java/com/simibubi/create/content/decoration/steamWhistle/WhistleRenderer.java b/src/main/java/com/simibubi/create/content/decoration/steamWhistle/WhistleRenderer.java new file mode 100644 index 000000000..78e9ea9c5 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/decoration/steamWhistle/WhistleRenderer.java @@ -0,0 +1,51 @@ +package com.simibubi.create.content.decoration.steamWhistle; + +import com.jozufozu.flywheel.core.PartialModel; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.decoration.steamWhistle.WhistleBlock.WhistleSize; +import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.AnimationTickHolder; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; +import net.minecraft.world.level.block.state.BlockState; + +public class WhistleRenderer extends SafeBlockEntityRenderer { + + public WhistleRenderer(BlockEntityRendererProvider.Context context) {} + + @Override + protected void renderSafe(WhistleBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + BlockState blockState = be.getBlockState(); + if (!(blockState.getBlock() instanceof WhistleBlock)) + return; + + Direction direction = blockState.getValue(WhistleBlock.FACING); + WhistleSize size = blockState.getValue(WhistleBlock.SIZE); + + PartialModel mouth = size == WhistleSize.LARGE ? AllPartialModels.WHISTLE_MOUTH_LARGE + : size == WhistleSize.MEDIUM ? AllPartialModels.WHISTLE_MOUTH_MEDIUM : AllPartialModels.WHISTLE_MOUTH_SMALL; + + float offset = be.animation.getValue(partialTicks); + if (be.animation.getChaseTarget() > 0 && be.animation.getValue() > 0.5f) { + float wiggleProgress = (AnimationTickHolder.getTicks(be.getLevel()) + partialTicks) / 8f; + offset -= Math.sin(wiggleProgress * (2 * Mth.PI) * (4 - size.ordinal())) / 16f; + } + + CachedBufferer.partial(mouth, blockState) + .centre() + .rotateY(AngleHelper.horizontalAngle(direction)) + .unCentre() + .translate(0, offset * 4 / 16f, 0) + .light(light) + .renderInto(ms, buffer.getBuffer(RenderType.solid())); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/steam/whistle/WhistleSoundInstance.java b/src/main/java/com/simibubi/create/content/decoration/steamWhistle/WhistleSoundInstance.java similarity index 89% rename from src/main/java/com/simibubi/create/content/contraptions/components/steam/whistle/WhistleSoundInstance.java rename to src/main/java/com/simibubi/create/content/decoration/steamWhistle/WhistleSoundInstance.java index f48202603..a768d1aeb 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/steam/whistle/WhistleSoundInstance.java +++ b/src/main/java/com/simibubi/create/content/decoration/steamWhistle/WhistleSoundInstance.java @@ -1,10 +1,10 @@ -package com.simibubi.create.content.contraptions.components.steam.whistle; +package com.simibubi.create.content.decoration.steamWhistle; import static com.simibubi.create.AllSoundEvents.WHISTLE_HIGH; import static com.simibubi.create.AllSoundEvents.WHISTLE_LOW; import static com.simibubi.create.AllSoundEvents.WHISTLE_MEDIUM; -import com.simibubi.create.content.contraptions.components.steam.whistle.WhistleBlock.WhistleSize; +import com.simibubi.create.content.decoration.steamWhistle.WhistleBlock.WhistleSize; import net.minecraft.client.resources.sounds.AbstractTickableSoundInstance; import net.minecraft.client.resources.sounds.SoundInstance; diff --git a/src/main/java/com/simibubi/create/content/curiosities/BuildersTeaItem.java b/src/main/java/com/simibubi/create/content/equipment/BuildersTeaItem.java similarity index 97% rename from src/main/java/com/simibubi/create/content/curiosities/BuildersTeaItem.java rename to src/main/java/com/simibubi/create/content/equipment/BuildersTeaItem.java index 15b25d3b6..caea8034c 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/BuildersTeaItem.java +++ b/src/main/java/com/simibubi/create/content/equipment/BuildersTeaItem.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities; +package com.simibubi.create.content.equipment; import net.minecraft.advancements.CriteriaTriggers; import net.minecraft.server.level.ServerPlayer; diff --git a/src/main/java/com/simibubi/create/content/curiosities/TreeFertilizerItem.java b/src/main/java/com/simibubi/create/content/equipment/TreeFertilizerItem.java similarity index 98% rename from src/main/java/com/simibubi/create/content/curiosities/TreeFertilizerItem.java rename to src/main/java/com/simibubi/create/content/equipment/TreeFertilizerItem.java index 4c1c9f48e..57e38aa90 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/TreeFertilizerItem.java +++ b/src/main/java/com/simibubi/create/content/equipment/TreeFertilizerItem.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities; +package com.simibubi.create.content.equipment; import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationServerWorld; diff --git a/src/main/java/com/simibubi/create/content/curiosities/armor/AllArmorMaterials.java b/src/main/java/com/simibubi/create/content/equipment/armor/AllArmorMaterials.java similarity index 90% rename from src/main/java/com/simibubi/create/content/curiosities/armor/AllArmorMaterials.java rename to src/main/java/com/simibubi/create/content/equipment/armor/AllArmorMaterials.java index 0937f2b7d..3064b5bcf 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/armor/AllArmorMaterials.java +++ b/src/main/java/com/simibubi/create/content/equipment/armor/AllArmorMaterials.java @@ -1,9 +1,10 @@ -package com.simibubi.create.content.curiosities.armor; +package com.simibubi.create.content.equipment.armor; import java.util.function.Supplier; import com.google.common.base.Suppliers; import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.Create; import net.minecraft.sounds.SoundEvent; import net.minecraft.world.entity.EquipmentSlot; @@ -13,7 +14,7 @@ import net.minecraft.world.item.crafting.Ingredient; public enum AllArmorMaterials implements ArmorMaterial { - COPPER("copper", 7, new int[] { 1, 3, 4, 2 }, 25, () -> AllSoundEvents.COPPER_ARMOR_EQUIP.getMainEvent(), 0.0F, 0.0F, + COPPER(Create.asResource("copper").toString(), 7, new int[] { 1, 3, 4, 2 }, 25, () -> AllSoundEvents.COPPER_ARMOR_EQUIP.getMainEvent(), 0.0F, 0.0F, () -> Ingredient.of(Items.COPPER_INGOT)) ; diff --git a/src/main/java/com/simibubi/create/content/equipment/armor/BacktankArmorLayer.java b/src/main/java/com/simibubi/create/content/equipment/armor/BacktankArmorLayer.java new file mode 100644 index 000000000..b75568278 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/armor/BacktankArmorLayer.java @@ -0,0 +1,94 @@ +package com.simibubi.create.content.equipment.armor; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.AnimationTickHolder; + +import net.minecraft.client.model.EntityModel; +import net.minecraft.client.model.HumanoidModel; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.Sheets; +import net.minecraft.client.renderer.entity.EntityRenderDispatcher; +import net.minecraft.client.renderer.entity.EntityRenderer; +import net.minecraft.client.renderer.entity.LivingEntityRenderer; +import net.minecraft.client.renderer.entity.RenderLayerParent; +import net.minecraft.client.renderer.entity.layers.RenderLayer; +import net.minecraft.core.Direction; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.Pose; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.block.state.BlockState; + +public class BacktankArmorLayer> extends RenderLayer { + + public BacktankArmorLayer(RenderLayerParent renderer) { + super(renderer); + } + + @Override + public void render(PoseStack ms, MultiBufferSource buffer, int light, LivingEntity entity, float yaw, float pitch, + float pt, float p_225628_8_, float p_225628_9_, float p_225628_10_) { + if (entity.getPose() == Pose.SLEEPING) + return; + + BacktankItem item = BacktankItem.getWornBy(entity); + if (item == null) + return; + + M entityModel = getParentModel(); + if (!(entityModel instanceof HumanoidModel)) + return; + + HumanoidModel model = (HumanoidModel) entityModel; + RenderType renderType = Sheets.cutoutBlockSheet(); + BlockState renderedState = item.getBlock().defaultBlockState() + .setValue(BacktankBlock.HORIZONTAL_FACING, Direction.SOUTH); + SuperByteBuffer backtank = CachedBufferer.block(renderedState); + SuperByteBuffer cogs = CachedBufferer.partial(BacktankRenderer.getCogsModel(renderedState), renderedState); + + ms.pushPose(); + + model.body.translateAndRotate(ms); + ms.translate(-1 / 2f, 10 / 16f, 1f); + ms.scale(1, -1, -1); + + backtank.forEntityRender() + .light(light) + .renderInto(ms, buffer.getBuffer(renderType)); + + cogs.centre() + .rotateY(180) + .unCentre() + .translate(0, 6.5f / 16, 11f / 16) + .rotate(Direction.EAST, AngleHelper.rad(2 * AnimationTickHolder.getRenderTime(entity.level) % 360)) + .translate(0, -6.5f / 16, -11f / 16); + + cogs.forEntityRender() + .light(light) + .renderInto(ms, buffer.getBuffer(renderType)); + + ms.popPose(); + } + + public static void registerOnAll(EntityRenderDispatcher renderManager) { + for (EntityRenderer renderer : renderManager.getSkinMap().values()) + registerOn(renderer); + for (EntityRenderer renderer : renderManager.renderers.values()) + registerOn(renderer); + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + public static void registerOn(EntityRenderer entityRenderer) { + if (!(entityRenderer instanceof LivingEntityRenderer)) + return; + LivingEntityRenderer livingRenderer = (LivingEntityRenderer) entityRenderer; + if (!(livingRenderer.getModel() instanceof HumanoidModel)) + return; + BacktankArmorLayer layer = new BacktankArmorLayer<>(livingRenderer); + livingRenderer.addLayer((BacktankArmorLayer) layer); + } + +} diff --git a/src/main/java/com/simibubi/create/content/equipment/armor/BacktankBlock.java b/src/main/java/com/simibubi/create/content/equipment/armor/BacktankBlock.java new file mode 100644 index 000000000..755584be7 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/armor/BacktankBlock.java @@ -0,0 +1,195 @@ +package com.simibubi.create.content.equipment.armor; + +import java.util.Optional; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllEnchantments; +import com.simibubi.create.AllShapes; +import com.simibubi.create.content.kinetics.base.HorizontalKineticBlock; +import com.simibubi.create.foundation.block.IBE; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.network.chat.Component; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +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.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.SimpleWaterloggedBlock; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition.Builder; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +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.BlockHitResult; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; +import net.minecraftforge.common.util.FakePlayer; + +public class BacktankBlock extends HorizontalKineticBlock + implements IBE, SimpleWaterloggedBlock { + + public BacktankBlock(Properties properties) { + super(properties); + registerDefaultState(defaultBlockState().setValue(BlockStateProperties.WATERLOGGED, false)); + } + + @Override + public FluidState getFluidState(BlockState state) { + return state.getValue(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getSource(false) + : Fluids.EMPTY.defaultFluidState(); + } + + @Override + protected void createBlockStateDefinition(Builder builder) { + builder.add(BlockStateProperties.WATERLOGGED); + super.createBlockStateDefinition(builder); + } + + @Override + public boolean hasAnalogOutputSignal(BlockState p_149740_1_) { + return true; + } + + @Override + public int getAnalogOutputSignal(BlockState state, Level world, BlockPos pos) { + return getBlockEntityOptional(world, pos).map(BacktankBlockEntity::getComparatorOutput) + .orElse(0); + } + + @Override + public BlockState updateShape(BlockState state, Direction direction, BlockState neighbourState, + LevelAccessor world, BlockPos pos, BlockPos neighbourPos) { + if (state.getValue(BlockStateProperties.WATERLOGGED)) + world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world)); + return state; + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext context) { + FluidState fluidState = context.getLevel() + .getFluidState(context.getClickedPos()); + return super.getStateForPlacement(context).setValue(BlockStateProperties.WATERLOGGED, + fluidState.getType() == Fluids.WATER); + } + + @Override + public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) { + return face == Direction.UP; + } + + @Override + public Axis getRotationAxis(BlockState state) { + return Axis.Y; + } + + @Override + public void setPlacedBy(Level worldIn, BlockPos pos, BlockState state, LivingEntity placer, ItemStack stack) { + super.setPlacedBy(worldIn, pos, state, placer, stack); + if (worldIn.isClientSide) + return; + if (stack == null) + return; + withBlockEntityDo(worldIn, pos, be -> { + be.setCapacityEnchantLevel(stack.getEnchantmentLevel(AllEnchantments.CAPACITY.get())); + be.setAirLevel(stack.getOrCreateTag() + .getInt("Air")); + if (stack.isEnchanted()) + be.setEnchantmentTag(stack.getEnchantmentTags()); + if (stack.hasCustomHoverName()) + be.setCustomName(stack.getHoverName()); + }); + } + + @Override + public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, + BlockHitResult hit) { + if (player == null) + return InteractionResult.PASS; + if (player instanceof FakePlayer) + return InteractionResult.PASS; + if (player.isShiftKeyDown()) + return InteractionResult.PASS; + if (player.getMainHandItem() + .getItem() instanceof BlockItem) + return InteractionResult.PASS; + if (!player.getItemBySlot(EquipmentSlot.CHEST) + .isEmpty()) + return InteractionResult.PASS; + if (!world.isClientSide) { + world.playSound(null, pos, SoundEvents.ITEM_PICKUP, SoundSource.PLAYERS, .75f, 1); + player.setItemSlot(EquipmentSlot.CHEST, getCloneItemStack(world, pos, state)); + world.destroyBlock(pos, false); + } + return InteractionResult.SUCCESS; + } + + @Override + public ItemStack getCloneItemStack(BlockGetter blockGetter, BlockPos pos, BlockState state) { + Item item = asItem(); + if (item instanceof BacktankItem.BacktankBlockItem placeable) { + item = placeable.getActualItem(); + } + + ItemStack stack = new ItemStack(item); + Optional blockEntityOptional = getBlockEntityOptional(blockGetter, pos); + + int air = blockEntityOptional.map(BacktankBlockEntity::getAirLevel) + .orElse(0); + CompoundTag tag = stack.getOrCreateTag(); + tag.putInt("Air", air); + + ListTag enchants = blockEntityOptional.map(BacktankBlockEntity::getEnchantmentTag) + .orElse(new ListTag()); + if (!enchants.isEmpty()) { + ListTag enchantmentTagList = stack.getEnchantmentTags(); + enchantmentTagList.addAll(enchants); + tag.put("Enchantments", enchantmentTagList); + } + + Component customName = blockEntityOptional.map(BacktankBlockEntity::getCustomName) + .orElse(null); + if (customName != null) + stack.setHoverName(customName); + return stack; + } + + @Override + public VoxelShape getShape(BlockState p_220053_1_, BlockGetter p_220053_2_, BlockPos p_220053_3_, + CollisionContext p_220053_4_) { + return AllShapes.BACKTANK; + } + + @Override + public Class getBlockEntityClass() { + return BacktankBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.BACKTANK.get(); + } + + @Override + public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) { + return false; + } + +} diff --git a/src/main/java/com/simibubi/create/content/equipment/armor/BacktankBlockEntity.java b/src/main/java/com/simibubi/create/content/equipment/armor/BacktankBlockEntity.java new file mode 100644 index 000000000..20f3c4518 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/armor/BacktankBlockEntity.java @@ -0,0 +1,185 @@ +package com.simibubi.create.content.equipment.armor; + +import java.util.List; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllItems; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.blockEntity.ComparatorUtil; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.particle.AirParticleData; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.Component; +import net.minecraft.util.Mth; +import net.minecraft.world.Nameable; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.phys.Vec3; + +public class BacktankBlockEntity extends KineticBlockEntity implements Nameable { + + public int airLevel; + public int airLevelTimer; + private Component defaultName; + private Component customName; + + private int capacityEnchantLevel; + private ListTag enchantmentTag; + + public BacktankBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + defaultName = getDefaultName(state); + enchantmentTag = new ListTag(); + } + + public static Component getDefaultName(BlockState state) { + if (AllBlocks.NETHERITE_BACKTANK.has(state)) { + AllItems.NETHERITE_BACKTANK.get().getDescription(); + } + + return AllItems.COPPER_BACKTANK.get().getDescription(); + } + + @Override + public void addBehaviours(List behaviours) { + super.addBehaviours(behaviours); + registerAwardables(behaviours, AllAdvancements.BACKTANK); + } + + @Override + public void onSpeedChanged(float previousSpeed) { + super.onSpeedChanged(previousSpeed); + if (getSpeed() != 0) + award(AllAdvancements.BACKTANK); + } + + @Override + public void tick() { + super.tick(); + if (getSpeed() == 0) + return; + + BlockState state = getBlockState(); + BooleanProperty waterProperty = BlockStateProperties.WATERLOGGED; + if (state.hasProperty(waterProperty) && state.getValue(waterProperty)) + return; + + if (airLevelTimer > 0) { + airLevelTimer--; + return; + } + + int max = BacktankUtil.maxAir(capacityEnchantLevel); + if (level.isClientSide) { + Vec3 centerOf = VecHelper.getCenterOf(worldPosition); + Vec3 v = VecHelper.offsetRandomly(centerOf, level.random, .65f); + Vec3 m = centerOf.subtract(v); + if (airLevel != max) + level.addParticle(new AirParticleData(1, .05f), v.x, v.y, v.z, m.x, m.y, m.z); + return; + } + + if (airLevel == max) + return; + + int prevComparatorLevel = getComparatorOutput(); + float abs = Math.abs(getSpeed()); + int increment = Mth.clamp(((int) abs - 100) / 20, 1, 5); + airLevel = Math.min(max, airLevel + increment); + if (getComparatorOutput() != prevComparatorLevel && !level.isClientSide) + level.updateNeighbourForOutputSignal(worldPosition, state.getBlock()); + if (airLevel == max) + sendData(); + airLevelTimer = Mth.clamp((int) (128f - abs / 5f) - 108, 0, 20); + } + + public int getComparatorOutput() { + int max = BacktankUtil.maxAir(capacityEnchantLevel); + return ComparatorUtil.fractionToRedstoneLevel(airLevel / (float) max); + } + + @Override + protected void write(CompoundTag compound, boolean clientPacket) { + super.write(compound, clientPacket); + compound.putInt("Air", airLevel); + compound.putInt("Timer", airLevelTimer); + compound.putInt("CapacityEnchantment", capacityEnchantLevel); + if (this.customName != null) + compound.putString("CustomName", Component.Serializer.toJson(this.customName)); + compound.put("Enchantments", enchantmentTag); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + super.read(compound, clientPacket); + int prev = airLevel; + capacityEnchantLevel = compound.getInt("CapacityEnchantment"); + airLevel = compound.getInt("Air"); + airLevelTimer = compound.getInt("Timer"); + enchantmentTag = compound.getList("Enchantments", Tag.TAG_COMPOUND); + if (compound.contains("CustomName", 8)) + this.customName = Component.Serializer.fromJson(compound.getString("CustomName")); + if (prev != 0 && prev != airLevel && airLevel == BacktankUtil.maxAir(capacityEnchantLevel) && clientPacket) + playFilledEffect(); + } + + protected void playFilledEffect() { + AllSoundEvents.CONFIRM.playAt(level, worldPosition, 0.4f, 1, true); + Vec3 baseMotion = new Vec3(.25, 0.1, 0); + Vec3 baseVec = VecHelper.getCenterOf(worldPosition); + for (int i = 0; i < 360; i += 10) { + Vec3 m = VecHelper.rotate(baseMotion, i, Axis.Y); + Vec3 v = baseVec.add(m.normalize() + .scale(.25f)); + + level.addParticle(ParticleTypes.SPIT, v.x, v.y, v.z, m.x, m.y, m.z); + } + } + + @Override + public Component getName() { + return this.customName != null ? this.customName + : defaultName; + } + + public int getAirLevel() { + return airLevel; + } + + public void setAirLevel(int airLevel) { + this.airLevel = airLevel; + sendData(); + } + + public void setCustomName(Component customName) { + this.customName = customName; + } + + public Component getCustomName() { + return customName; + } + + public ListTag getEnchantmentTag() { + return enchantmentTag; + } + + public void setEnchantmentTag(ListTag enchantmentTag) { + this.enchantmentTag = enchantmentTag; + } + + public void setCapacityEnchantLevel(int capacityEnchantLevel) { + this.capacityEnchantLevel = capacityEnchantLevel; + } + +} diff --git a/src/main/java/com/simibubi/create/content/equipment/armor/BacktankInstance.java b/src/main/java/com/simibubi/create/content/equipment/armor/BacktankInstance.java new file mode 100644 index 000000000..c382e3ff5 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/armor/BacktankInstance.java @@ -0,0 +1,19 @@ +package com.simibubi.create.content.equipment.armor; + +import com.jozufozu.flywheel.api.Instancer; +import com.jozufozu.flywheel.api.MaterialManager; +import com.simibubi.create.content.kinetics.base.SingleRotatingInstance; +import com.simibubi.create.content.kinetics.base.flwdata.RotatingData; + +public class BacktankInstance extends SingleRotatingInstance { + + public BacktankInstance(MaterialManager materialManager, BacktankBlockEntity blockEntity) { + super(materialManager, blockEntity); + } + + @Override + protected Instancer getModel() { + return getRotatingMaterial().getModel(BacktankRenderer.getShaftModel(blockState), blockState); + } + +} diff --git a/src/main/java/com/simibubi/create/content/equipment/armor/BacktankItem.java b/src/main/java/com/simibubi/create/content/equipment/armor/BacktankItem.java new file mode 100644 index 000000000..e59e6da02 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/armor/BacktankItem.java @@ -0,0 +1,115 @@ +package com.simibubi.create.content.equipment.armor; + +import java.util.Locale; +import java.util.function.Supplier; + +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.content.equipment.armor.CapacityEnchantment.ICapacityEnchantable; +import com.simibubi.create.foundation.item.LayeredArmorItem; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ArmorMaterial; +import net.minecraft.world.item.BlockItem; +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.Block; + +public class BacktankItem extends BaseArmorItem implements ICapacityEnchantable { + public static final EquipmentSlot SLOT = EquipmentSlot.CHEST; + public static final int BAR_COLOR = 0xEFEFEF; + + private final Supplier blockItem; + + public BacktankItem(ArmorMaterial material, Properties properties, ResourceLocation textureLoc, Supplier placeable) { + super(material, SLOT, properties, textureLoc); + this.blockItem = placeable; + } + + @Nullable + public static BacktankItem getWornBy(Entity entity) { + if (!(entity instanceof LivingEntity livingEntity)) { + return null; + } + if (!(livingEntity.getItemBySlot(SLOT).getItem() instanceof BacktankItem item)) { + return null; + } + return item; + } + + @Override + public InteractionResult useOn(UseOnContext ctx) { + return blockItem.get() + .useOn(ctx); + } + + @Override + public boolean canBeDepleted() { + return false; + } + + @Override + public boolean isEnchantable(ItemStack p_77616_1_) { + return true; + } + + @Override + public boolean isBarVisible(ItemStack stack) { + return true; + } + + @Override + public int getBarWidth(ItemStack stack) { + return Math.round(13.0F * Mth.clamp(getRemainingAir(stack) / ((float) BacktankUtil.maxAir(stack)), 0, 1)); + } + + @Override + public int getBarColor(ItemStack stack) { + return BAR_COLOR; + } + + public Block getBlock() { + return blockItem.get().getBlock(); + } + + public static int getRemainingAir(ItemStack stack) { + CompoundTag orCreateTag = stack.getOrCreateTag(); + return orCreateTag.getInt("Air"); + } + + public static class BacktankBlockItem extends BlockItem { + private final Supplier actualItem; + + public BacktankBlockItem(Block block, Supplier actualItem, Properties properties) { + super(block, properties); + this.actualItem = actualItem; + } + + @Override + public String getDescriptionId() { + return this.getOrCreateDescriptionId(); + } + + public Item getActualItem() { + return actualItem.get(); + } + } + + public static class Layered extends BacktankItem implements LayeredArmorItem { + public Layered(ArmorMaterial material, Properties properties, ResourceLocation textureLoc, Supplier placeable) { + super(material, properties, textureLoc, placeable); + } + + @Override + public String getArmorTextureLocation(LivingEntity entity, EquipmentSlot slot, ItemStack stack, int layer) { + return String.format(Locale.ROOT, "%s:textures/models/armor/%s_layer_%d.png", textureLoc.getNamespace(), textureLoc.getPath(), layer); + } + } +} diff --git a/src/main/java/com/simibubi/create/content/equipment/armor/BacktankRenderer.java b/src/main/java/com/simibubi/create/content/equipment/armor/BacktankRenderer.java new file mode 100644 index 000000000..11f52aab5 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/armor/BacktankRenderer.java @@ -0,0 +1,60 @@ +package com.simibubi.create.content.equipment.armor; + +import com.jozufozu.flywheel.core.PartialModel; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.AnimationTickHolder; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.state.BlockState; + +public class BacktankRenderer extends KineticBlockEntityRenderer { + public BacktankRenderer(BlockEntityRendererProvider.Context context) { + super(context); + } + + @Override + protected void renderSafe(BacktankBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + super.renderSafe(be, partialTicks, ms, buffer, light, overlay); + + BlockState blockState = be.getBlockState(); + SuperByteBuffer cogs = CachedBufferer.partial(getCogsModel(blockState), blockState); + cogs.centre() + .rotateY(180 + AngleHelper.horizontalAngle(blockState.getValue(BacktankBlock.HORIZONTAL_FACING))) + .unCentre() + .translate(0, 6.5f / 16, 11f / 16) + .rotate(Direction.EAST, + AngleHelper.rad(be.getSpeed() / 4f * AnimationTickHolder.getRenderTime(be.getLevel()) % 360)) + .translate(0, -6.5f / 16, -11f / 16); + cogs.light(light) + .renderInto(ms, buffer.getBuffer(RenderType.solid())); + } + + @Override + protected SuperByteBuffer getRotatedModel(BacktankBlockEntity be, BlockState state) { + return CachedBufferer.partial(getShaftModel(state), state); + } + + public static PartialModel getCogsModel(BlockState state) { + if (AllBlocks.NETHERITE_BACKTANK.has(state)) { + return AllPartialModels.NETHERITE_BACKTANK_COGS; + } + return AllPartialModels.COPPER_BACKTANK_COGS; + } + + public static PartialModel getShaftModel(BlockState state) { + if (AllBlocks.NETHERITE_BACKTANK.has(state)) { + return AllPartialModels.NETHERITE_BACKTANK_SHAFT; + } + return AllPartialModels.COPPER_BACKTANK_SHAFT; + } +} diff --git a/src/main/java/com/simibubi/create/content/equipment/armor/BacktankUtil.java b/src/main/java/com/simibubi/create/content/equipment/armor/BacktankUtil.java new file mode 100644 index 000000000..9eb73dc03 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/armor/BacktankUtil.java @@ -0,0 +1,145 @@ +package com.simibubi.create.content.equipment.armor; + +import com.simibubi.create.AllEnchantments; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.AllTags; +import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.network.protocol.game.ClientboundSetSubtitleTextPacket; +import net.minecraft.network.protocol.game.ClientboundSetTitleTextPacket; +import net.minecraft.network.protocol.game.ClientboundSetTitlesAnimationPacket; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; + +public class BacktankUtil { + + public static ItemStack get(LivingEntity entity) { + for (ItemStack itemStack : entity.getArmorSlots()) + if (AllTags.AllItemTags.PRESSURIZED_AIR_SOURCES.matches(itemStack)) + return itemStack; + return ItemStack.EMPTY; + } + + public static boolean hasAirRemaining(ItemStack backtank) { + return getAir(backtank) > 0; + } + + public static float getAir(ItemStack backtank) { + CompoundTag tag = backtank.getOrCreateTag(); + return Math.min(tag.getFloat("Air"), maxAir(backtank)); + } + + public static void consumeAir(LivingEntity entity, ItemStack backtank, float i) { + CompoundTag tag = backtank.getOrCreateTag(); + int maxAir = maxAir(backtank); + float air = getAir(backtank); + float newAir = air - i; + tag.putFloat("Air", Math.min(newAir, maxAir)); + backtank.setTag(tag); + + if (!(entity instanceof ServerPlayer player)) + return; + sendWarning(player, air, newAir, maxAir / 10f); + sendWarning(player, air, newAir, 1); + } + + private static void sendWarning(ServerPlayer player, float air, float newAir, float threshold) { + if (newAir > threshold) + return; + if (air <= threshold) + return; + + boolean depleted = threshold == 1; + MutableComponent component = Lang.translateDirect(depleted ? "backtank.depleted" : "backtank.low"); + + AllSoundEvents.DENY.play(player.level, null, player.blockPosition(), 1, 1.25f); + AllSoundEvents.STEAM.play(player.level, null, player.blockPosition(), .5f, .5f); + + player.connection.send(new ClientboundSetTitlesAnimationPacket(10, 40, 10)); + player.connection.send(new ClientboundSetSubtitleTextPacket( + Components.literal("\u26A0 ").withStyle(depleted ? ChatFormatting.RED : ChatFormatting.GOLD) + .append(component.withStyle(ChatFormatting.GRAY)))); + player.connection.send(new ClientboundSetTitleTextPacket(Components.immutableEmpty())); + } + + public static int maxAir(ItemStack backtank) { + return maxAir(backtank.getEnchantmentLevel(AllEnchantments.CAPACITY.get())); + } + + public static int maxAir(int enchantLevel) { + return AllConfigs.server().equipment.airInBacktank.get() + + AllConfigs.server().equipment.enchantedBacktankCapacity.get() * enchantLevel; + } + + public static int maxAirWithoutEnchants() { + return AllConfigs.server().equipment.airInBacktank.get(); + } + + public static boolean canAbsorbDamage(LivingEntity entity, int usesPerTank) { + if (usesPerTank == 0) + return true; + if (entity instanceof Player && ((Player) entity).isCreative()) + return true; + ItemStack backtank = get(entity); + if (backtank.isEmpty()) + return false; + if (!hasAirRemaining(backtank)) + return false; + float cost = ((float) maxAirWithoutEnchants()) / usesPerTank; + consumeAir(entity, backtank, cost); + return true; + } + + // For Air-using tools + + public static boolean isBarVisible(ItemStack stack, int usesPerTank) { + if (usesPerTank == 0) + return false; + Player player = DistExecutor.unsafeCallWhenOn(Dist.CLIENT, () -> () -> Minecraft.getInstance().player); + if (player == null) + return false; + ItemStack backtank = get(player); + if (backtank.isEmpty() || !hasAirRemaining(backtank)) + return stack.isDamaged(); + return true; + } + + public static int getBarWidth(ItemStack stack, int usesPerTank) { + if (usesPerTank == 0) + return 13; + Player player = DistExecutor.unsafeCallWhenOn(Dist.CLIENT, () -> () -> Minecraft.getInstance().player); + if (player == null) + return 13; + ItemStack backtank = get(player); + if (backtank.isEmpty() || !hasAirRemaining(backtank)) + return Math.round(13.0F - (float) stack.getDamageValue() / stack.getMaxDamage() * 13.0F); + return backtank.getItem() + .getBarWidth(backtank); + } + + public static int getBarColor(ItemStack stack, int usesPerTank) { + if (usesPerTank == 0) + return 0; + Player player = DistExecutor.unsafeCallWhenOn(Dist.CLIENT, () -> () -> Minecraft.getInstance().player); + if (player == null) + return 0; + ItemStack backtank = get(player); + if (backtank.isEmpty() || !hasAirRemaining(backtank)) + return Mth.hsvToRgb(Math.max(0.0F, 1.0F - (float) stack.getDamageValue() / stack.getMaxDamage()) / 3.0F, + 1.0F, 1.0F); + return backtank.getItem() + .getBarColor(backtank); + } + +} diff --git a/src/main/java/com/simibubi/create/content/equipment/armor/BaseArmorItem.java b/src/main/java/com/simibubi/create/content/equipment/armor/BaseArmorItem.java new file mode 100644 index 000000000..5c1fbeb14 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/armor/BaseArmorItem.java @@ -0,0 +1,24 @@ +package com.simibubi.create.content.equipment.armor; + +import java.util.Locale; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.item.ArmorItem; +import net.minecraft.world.item.ArmorMaterial; +import net.minecraft.world.item.ItemStack; + +public class BaseArmorItem extends ArmorItem { + protected final ResourceLocation textureLoc; + + public BaseArmorItem(ArmorMaterial armorMaterial, EquipmentSlot slot, Properties properties, ResourceLocation textureLoc) { + super(armorMaterial, slot, properties.stacksTo(1)); + this.textureLoc = textureLoc; + } + + @Override + public String getArmorTexture(ItemStack stack, Entity entity, EquipmentSlot slot, String type) { + return String.format(Locale.ROOT, "%s:textures/models/armor/%s_layer_%d%s.png", textureLoc.getNamespace(), textureLoc.getPath(), slot == EquipmentSlot.LEGS ? 2 : 1, type == null ? "" : String.format(Locale.ROOT, "_%s", type)); + } +} diff --git a/src/main/java/com/simibubi/create/content/equipment/armor/CapacityEnchantment.java b/src/main/java/com/simibubi/create/content/equipment/armor/CapacityEnchantment.java new file mode 100644 index 000000000..d1109caa2 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/armor/CapacityEnchantment.java @@ -0,0 +1,27 @@ +package com.simibubi.create.content.equipment.armor; + +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.enchantment.Enchantment; +import net.minecraft.world.item.enchantment.EnchantmentCategory; + +public class CapacityEnchantment extends Enchantment { + + public CapacityEnchantment(Rarity rarity, EnchantmentCategory category, EquipmentSlot[] slots) { + super(rarity, category, slots); + } + + @Override + public int getMaxLevel() { + return 3; + } + + @Override + public boolean canApplyAtEnchantingTable(ItemStack stack) { + return stack.getItem() instanceof ICapacityEnchantable; + } + + public interface ICapacityEnchantable { + } + +} diff --git a/src/main/java/com/simibubi/create/content/equipment/armor/DivingBootsItem.java b/src/main/java/com/simibubi/create/content/equipment/armor/DivingBootsItem.java new file mode 100644 index 000000000..1f7ae2965 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/armor/DivingBootsItem.java @@ -0,0 +1,112 @@ +package com.simibubi.create.content.equipment.armor; + +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.foundation.utility.NBTHelper; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.FluidTags; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.Pose; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ArmorMaterial; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.event.entity.living.LivingEvent.LivingTickEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; + +@EventBusSubscriber +public class DivingBootsItem extends BaseArmorItem { + public static final EquipmentSlot SLOT = EquipmentSlot.FEET; + + public DivingBootsItem(ArmorMaterial material, Properties properties, ResourceLocation textureLoc) { + super(material, SLOT, properties, textureLoc); + } + + public static boolean isWornBy(Entity entity) { + ItemStack stack = getWornItem(entity); + if (stack == null) { + return false; + } + return stack.getItem() instanceof DivingBootsItem; + } + + @Nullable + public static ItemStack getWornItem(Entity entity) { + if (!(entity instanceof LivingEntity livingEntity)) { + return null; + } + return livingEntity.getItemBySlot(SLOT); + } + + @SubscribeEvent + public static void accellerateDescentUnderwater(LivingTickEvent event) { + LivingEntity entity = event.getEntity(); + if (!affects(entity)) + return; + + Vec3 motion = entity.getDeltaMovement(); + boolean isJumping = entity.jumping; + entity.setOnGround(entity.isOnGround() || entity.verticalCollision); + + if (isJumping && entity.isOnGround()) { + motion = motion.add(0, .5f, 0); + entity.setOnGround(false); + } else { + motion = motion.add(0, -0.05f, 0); + } + + float multiplier = 1.3f; + if (motion.multiply(1, 0, 1) + .length() < 0.145f && (entity.zza > 0 || entity.xxa != 0) && !entity.isShiftKeyDown()) + motion = motion.multiply(multiplier, 1, multiplier); + entity.setDeltaMovement(motion); + } + + protected static boolean affects(LivingEntity entity) { + if (!isWornBy(entity)) { + entity.getPersistentData() + .remove("HeavyBoots"); + return false; + } + + NBTHelper.putMarker(entity.getPersistentData(), "HeavyBoots"); + if (!entity.isInWater()) + return false; + if (entity.getPose() == Pose.SWIMMING) + return false; + if (entity instanceof Player) { + Player playerEntity = (Player) entity; + if (playerEntity.getAbilities().flying) + return false; + } + return true; + } + + public static Vec3 getMovementMultiplier(LivingEntity entity) { + double yMotion = entity.getDeltaMovement().y; + double vMultiplier = yMotion < 0 ? Math.max(0, 2.5 - Math.abs(yMotion) * 2) : 1; + + if (!entity.isOnGround()) { + if (entity.jumping && entity.getPersistentData() + .contains("LavaGrounded")) { + boolean eyeInFluid = entity.isEyeInFluid(FluidTags.LAVA); + vMultiplier = yMotion == 0 ? 0 : (eyeInFluid ? 1 : 0.5) / yMotion; + } else if (yMotion > 0) + vMultiplier = 1.3; + + entity.getPersistentData() + .remove("LavaGrounded"); + return new Vec3(1.75, vMultiplier, 1.75); + } + + entity.getPersistentData() + .putBoolean("LavaGrounded", true); + double hMultiplier = entity.isSprinting() ? 1.85 : 1.75; + return new Vec3(hMultiplier, vMultiplier, hMultiplier); + } + +} diff --git a/src/main/java/com/simibubi/create/content/equipment/armor/DivingHelmetItem.java b/src/main/java/com/simibubi/create/content/equipment/armor/DivingHelmetItem.java new file mode 100644 index 000000000..1f97c047c --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/armor/DivingHelmetItem.java @@ -0,0 +1,130 @@ +package com.simibubi.create.content.equipment.armor; + +import java.util.Map; + +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.foundation.advancement.AllAdvancements; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ArmorMaterial; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.enchantment.Enchantment; +import net.minecraft.world.item.enchantment.Enchantments; +import net.minecraft.world.level.Level; +import net.minecraftforge.event.entity.living.LivingEvent.LivingTickEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; + +@EventBusSubscriber +public class DivingHelmetItem extends BaseArmorItem { + public static final EquipmentSlot SLOT = EquipmentSlot.HEAD; + + public DivingHelmetItem(ArmorMaterial material, Properties properties, ResourceLocation textureLoc) { + super(material, SLOT, properties, textureLoc); + } + + @Override + public boolean canApplyAtEnchantingTable(ItemStack stack, Enchantment enchantment) { + if (enchantment == Enchantments.AQUA_AFFINITY) { + return false; + } + return super.canApplyAtEnchantingTable(stack, enchantment); + } + + @Override + public int getEnchantmentLevel(ItemStack stack, Enchantment enchantment) { + if (enchantment == Enchantments.AQUA_AFFINITY) { + return 1; + } + return super.getEnchantmentLevel(stack, enchantment); + } + + @Override + public Map getAllEnchantments(ItemStack stack) { + Map map = super.getAllEnchantments(stack); + map.put(Enchantments.AQUA_AFFINITY, 1); + return map; + } + + public static boolean isWornBy(Entity entity, boolean fireproof) { + ItemStack stack = getWornItem(entity); + if (stack == null) + return false; + if (!stack.getItem() + .isFireResistant() && fireproof) + return false; + return stack.getItem() instanceof DivingHelmetItem; + } + + @Nullable + public static ItemStack getWornItem(Entity entity) { + if (!(entity instanceof LivingEntity livingEntity)) { + return null; + } + return livingEntity.getItemBySlot(SLOT); + } + + @SubscribeEvent + public static void breatheUnderwater(LivingTickEvent event) { + LivingEntity entity = event.getEntity(); + Level world = entity.level; + boolean second = world.getGameTime() % 20 == 0; + boolean drowning = entity.getAirSupply() == 0; + + if (world.isClientSide) + entity.getPersistentData() + .remove("VisualBacktankAir"); + + boolean lavaDiving = entity.isInLava(); + if (!isWornBy(entity, lavaDiving)) + return; + + if (!entity.canDrownInFluidType(entity.getEyeInFluidType()) && !lavaDiving) + return; + if (entity instanceof Player && ((Player) entity).isCreative()) + return; + + ItemStack backtank = BacktankUtil.get(entity); + if (backtank.isEmpty()) + return; + if (!BacktankUtil.hasAirRemaining(backtank)) + return; + + if (lavaDiving) { + if (entity instanceof ServerPlayer sp) + AllAdvancements.DIVING_SUIT_LAVA.awardTo(sp); + if (!backtank.getItem() + .isFireResistant()) + return; + } + + if (drowning) + entity.setAirSupply(10); + + if (world.isClientSide) + entity.getPersistentData() + .putInt("VisualBacktankAir", (int) BacktankUtil.getAir(backtank)); + + if (!second) + return; + + BacktankUtil.consumeAir(entity, backtank, 1); + + if (lavaDiving) + return; + + if (entity instanceof ServerPlayer sp) + AllAdvancements.DIVING_SUIT.awardTo(sp); + + entity.setAirSupply(Math.min(entity.getMaxAirSupply(), entity.getAirSupply() + 10)); + entity.addEffect(new MobEffectInstance(MobEffects.WATER_BREATHING, 30, 0, true, false, true)); + } +} diff --git a/src/main/java/com/simibubi/create/content/equipment/armor/NetheriteBacktankFirstPersonRenderer.java b/src/main/java/com/simibubi/create/content/equipment/armor/NetheriteBacktankFirstPersonRenderer.java new file mode 100644 index 000000000..9d995838a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/armor/NetheriteBacktankFirstPersonRenderer.java @@ -0,0 +1,63 @@ +package com.simibubi.create.content.equipment.armor; + +import com.simibubi.create.AllItems; +import com.simibubi.create.Create; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.model.PlayerModel; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.client.player.AbstractClientPlayer; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.entity.player.PlayerRenderer; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.HumanoidArm; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.client.event.RenderArmEvent; +import net.minecraftforge.eventbus.api.EventPriority; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; + +@EventBusSubscriber(value = Dist.CLIENT) +public class NetheriteBacktankFirstPersonRenderer { + + private static final ResourceLocation BACKTANK_ARMOR_LOCATION = + Create.asResource("textures/models/armor/netherite_diving_arm.png"); + + private static boolean rendererActive = false; + + public static void clientTick() { + Minecraft mc = Minecraft.getInstance(); + rendererActive = + mc.player != null && AllItems.NETHERITE_BACKTANK.isIn(mc.player.getItemBySlot(EquipmentSlot.CHEST)); + } + + @SubscribeEvent(priority = EventPriority.LOWEST) + public static void onRenderPlayerHand(RenderArmEvent event) { + if (!rendererActive) + return; + + Minecraft mc = Minecraft.getInstance(); + LocalPlayer player = mc.player; + MultiBufferSource buffer = event.getMultiBufferSource(); + if (!(mc.getEntityRenderDispatcher() + .getRenderer(player) instanceof PlayerRenderer pr)) + return; + + PlayerModel model = pr.getModel(); + model.attackTime = 0.0F; + model.crouching = false; + model.swimAmount = 0.0F; + model.setupAnim(player, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F); + ModelPart armPart = event.getArm() == HumanoidArm.LEFT ? model.leftSleeve : model.rightSleeve; + armPart.xRot = 0.0F; + armPart.render(event.getPoseStack(), buffer.getBuffer(RenderType.entitySolid(BACKTANK_ARMOR_LOCATION)), + LightTexture.FULL_BRIGHT, OverlayTexture.NO_OVERLAY); + event.setCanceled(true); + } + +} diff --git a/src/main/java/com/simibubi/create/content/equipment/armor/NetheriteDivingHandler.java b/src/main/java/com/simibubi/create/content/equipment/armor/NetheriteDivingHandler.java new file mode 100644 index 000000000..b3a223756 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/armor/NetheriteDivingHandler.java @@ -0,0 +1,92 @@ +package com.simibubi.create.content.equipment.armor; + +import com.simibubi.create.AllItems; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ArmorItem; +import net.minecraft.world.item.ArmorMaterials; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.event.entity.living.LivingEquipmentChangeEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; + +@EventBusSubscriber +public final class NetheriteDivingHandler { + public static final String NETHERITE_DIVING_BITS_KEY = "CreateNetheriteDivingBits"; + public static final String FIRE_IMMUNE_KEY = "CreateFireImmune"; + + @SubscribeEvent + public static void onLivingEquipmentChange(LivingEquipmentChangeEvent event) { + EquipmentSlot slot = event.getSlot(); + if (slot.getType() != EquipmentSlot.Type.ARMOR) { + return; + } + + LivingEntity entity = event.getEntity(); + ItemStack to = event.getTo(); + + if (slot == EquipmentSlot.HEAD) { + if (AllItems.NETHERITE_DIVING_HELMET.isIn(to)) { + setBit(entity, slot); + } else { + clearBit(entity, slot); + } + } else if (slot == EquipmentSlot.CHEST) { + if (AllItems.NETHERITE_BACKTANK.isIn(to) && BacktankUtil.hasAirRemaining(to)) { + setBit(entity, slot); + } else { + clearBit(entity, slot); + } + } else if (slot == EquipmentSlot.LEGS || slot == EquipmentSlot.FEET) { + if (isNetheriteArmor(to)) { + setBit(entity, slot); + } else { + clearBit(entity, slot); + } + } + } + + public static boolean isNetheriteArmor(ItemStack stack) { + return stack.getItem() instanceof ArmorItem armorItem && armorItem.getMaterial() == ArmorMaterials.NETHERITE; + } + + public static void setBit(LivingEntity entity, EquipmentSlot slot) { + CompoundTag nbt = entity.getPersistentData(); + byte bits = nbt.getByte(NETHERITE_DIVING_BITS_KEY); + if ((bits & 0b1111) == 0b1111) { + return; + } + + bits |= 1 << slot.getIndex(); + nbt.putByte(NETHERITE_DIVING_BITS_KEY, bits); + + if ((bits & 0b1111) == 0b1111) { + setFireImmune(entity, true); + } + } + + public static void clearBit(LivingEntity entity, EquipmentSlot slot) { + CompoundTag nbt = entity.getPersistentData(); + if (!nbt.contains(NETHERITE_DIVING_BITS_KEY)) { + return; + } + + byte bits = nbt.getByte(NETHERITE_DIVING_BITS_KEY); + boolean prevFullSet = (bits & 0b1111) == 0b1111; + bits &= ~(1 << slot.getIndex()); + nbt.putByte(NETHERITE_DIVING_BITS_KEY, bits); + + if (prevFullSet) { + setFireImmune(entity, false); + } + } + + // TODO: sync to the client + // The feature works without syncing because health and burning are calculated server-side and synced through vanilla code. + // This method will not be called when the entity is wearing a full diving set on creation because the NBT values are persistent. + public static void setFireImmune(LivingEntity entity, boolean fireImmune) { + entity.getPersistentData().putBoolean(FIRE_IMMUNE_KEY, fireImmune); + } +} diff --git a/src/main/java/com/simibubi/create/content/equipment/armor/RemainingAirOverlay.java b/src/main/java/com/simibubi/create/content/equipment/armor/RemainingAirOverlay.java new file mode 100644 index 000000000..d8924394d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/armor/RemainingAirOverlay.java @@ -0,0 +1,68 @@ +package com.simibubi.create.content.equipment.armor; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllItems; +import com.simibubi.create.foundation.gui.element.GuiGameElement; +import com.simibubi.create.foundation.utility.Color; +import com.simibubi.create.foundation.utility.Components; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.network.chat.Component; +import net.minecraft.tags.FluidTags; +import net.minecraft.util.StringUtil; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.GameType; +import net.minecraftforge.client.gui.overlay.ForgeGui; +import net.minecraftforge.client.gui.overlay.IGuiOverlay; + +public class RemainingAirOverlay implements IGuiOverlay { + public static final RemainingAirOverlay INSTANCE = new RemainingAirOverlay(); + + @Override + public void render(ForgeGui gui, PoseStack poseStack, float partialTick, int width, int height) { + Minecraft mc = Minecraft.getInstance(); + if (mc.options.hideGui || mc.gameMode.getPlayerMode() == GameType.SPECTATOR) + return; + + LocalPlayer player = mc.player; + if (player == null) + return; + if (player.isCreative()) + return; + if (!player.getPersistentData() + .contains("VisualBacktankAir")) + return; + if (!player.isEyeInFluid(FluidTags.WATER) && !player.isInLava()) + return; + + int timeLeft = player.getPersistentData() + .getInt("VisualBacktankAir"); + + poseStack.pushPose(); + + ItemStack backtank = getDisplayedBacktank(player); + poseStack.translate(width / 2 + 90, height - 53 + (backtank.getItem() + .isFireResistant() ? 9 : 0), 0); + + Component text = Components.literal(StringUtil.formatTickDuration(Math.max(0, timeLeft - 1) * 20)); + GuiGameElement.of(backtank) + .at(0, 0) + .render(poseStack); + int color = 0xFF_FFFFFF; + if (timeLeft < 60 && timeLeft % 2 == 0) { + color = Color.mixColors(0xFF_FF0000, color, Math.max(timeLeft / 60f, .25f)); + } + mc.font.drawShadow(poseStack, text, 16, 5, color); + + poseStack.popPose(); + } + + public static ItemStack getDisplayedBacktank(LocalPlayer player) { + ItemStack backtank = BacktankUtil.get(player); + if (!backtank.isEmpty()) { + return backtank; + } + return AllItems.COPPER_BACKTANK.asStack(); + } +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/bell/AbstractBellBlock.java b/src/main/java/com/simibubi/create/content/equipment/bell/AbstractBellBlock.java similarity index 89% rename from src/main/java/com/simibubi/create/content/curiosities/bell/AbstractBellBlock.java rename to src/main/java/com/simibubi/create/content/equipment/bell/AbstractBellBlock.java index 0e0c9cdad..5467bc403 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/bell/AbstractBellBlock.java +++ b/src/main/java/com/simibubi/create/content/equipment/bell/AbstractBellBlock.java @@ -1,9 +1,9 @@ -package com.simibubi.create.content.curiosities.bell; +package com.simibubi.create.content.equipment.bell; import javax.annotation.Nullable; import com.simibubi.create.AllShapes; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.foundation.block.IBE; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -23,7 +23,7 @@ import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; -public abstract class AbstractBellBlock extends BellBlock implements ITE { +public abstract class AbstractBellBlock extends BellBlock implements IBE { public AbstractBellBlock(Properties properties) { super(properties); @@ -76,10 +76,10 @@ public abstract class AbstractBellBlock exten } protected boolean ring(Level world, BlockPos pos, Direction direction, Player player) { - TE te = getTileEntity(world, pos); + BE be = getBlockEntity(world, pos); if (world.isClientSide) return true; - if (te == null || !te.ring(world, pos, direction)) + if (be == null || !be.ring(world, pos, direction)) return false; playSound(world, pos); if (player != null) @@ -109,13 +109,13 @@ public abstract class AbstractBellBlock exten @Nullable public BlockEntity newBlockEntity(BlockPos p_152198_, BlockState p_152199_) { - return ITE.super.newBlockEntity(p_152198_, p_152199_); + return IBE.super.newBlockEntity(p_152198_, p_152199_); } @Nullable public BlockEntityTicker getTicker(Level p_152194_, BlockState p_152195_, BlockEntityType p_152196_) { - return ITE.super.getTicker(p_152194_, p_152195_, p_152196_); + return IBE.super.getTicker(p_152194_, p_152195_, p_152196_); } public abstract void playSound(Level world, BlockPos pos); diff --git a/src/main/java/com/simibubi/create/content/equipment/bell/AbstractBellBlockEntity.java b/src/main/java/com/simibubi/create/content/equipment/bell/AbstractBellBlockEntity.java new file mode 100644 index 000000000..f5ecc5a1a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/bell/AbstractBellBlockEntity.java @@ -0,0 +1,77 @@ +package com.simibubi.create.content.equipment.bell; + +import java.util.List; + +import com.jozufozu.flywheel.core.PartialModel; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.NBTHelper; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public abstract class AbstractBellBlockEntity extends SmartBlockEntity { + + public static final int RING_DURATION = 74; + + public boolean isRinging; + public int ringingTicks; + public Direction ringDirection; + + public AbstractBellBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + public void addBehaviours(List behaviours) { } + + public boolean ring(Level world, BlockPos pos, Direction direction) { + isRinging = true; + ringingTicks = 0; + ringDirection = direction; + sendData(); + return true; + }; + + @Override + public void tick() { + super.tick(); + + if (isRinging) { + ++ringingTicks; + } + + if (ringingTicks >= RING_DURATION) { + isRinging = false; + ringingTicks = 0; + } + } + + @Override + protected void write(CompoundTag tag, boolean clientPacket) { + super.write(tag, clientPacket); + if (!clientPacket || ringingTicks != 0 || !isRinging) + return; + NBTHelper.writeEnum(tag, "Ringing", ringDirection); + } + + @Override + protected void read(CompoundTag tag, boolean clientPacket) { + super.read(tag, clientPacket); + if (!clientPacket || !tag.contains("Ringing")) + return; + ringDirection = NBTHelper.readEnum(tag, "Ringing", Direction.class); + ringingTicks = 0; + isRinging = true; + } + + @OnlyIn(Dist.CLIENT) + public abstract PartialModel getBellModel(); + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/bell/BasicParticleData.java b/src/main/java/com/simibubi/create/content/equipment/bell/BasicParticleData.java similarity index 94% rename from src/main/java/com/simibubi/create/content/curiosities/bell/BasicParticleData.java rename to src/main/java/com/simibubi/create/content/equipment/bell/BasicParticleData.java index 987168325..452042e7f 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/bell/BasicParticleData.java +++ b/src/main/java/com/simibubi/create/content/equipment/bell/BasicParticleData.java @@ -1,10 +1,10 @@ -package com.simibubi.create.content.curiosities.bell; +package com.simibubi.create.content.equipment.bell; import javax.annotation.ParametersAreNonnullByDefault; import com.mojang.brigadier.StringReader; import com.mojang.serialization.Codec; -import com.simibubi.create.content.contraptions.particle.ICustomParticleDataWithSprite; +import com.simibubi.create.foundation.particle.ICustomParticleDataWithSprite; import com.simibubi.create.foundation.utility.RegisteredObjects; import net.minecraft.MethodsReturnNonnullByDefault; diff --git a/src/main/java/com/simibubi/create/content/equipment/bell/BellRenderer.java b/src/main/java/com/simibubi/create/content/equipment/bell/BellRenderer.java new file mode 100644 index 000000000..9816e4f4f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/bell/BellRenderer.java @@ -0,0 +1,48 @@ +package com.simibubi.create.content.equipment.bell; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.AngleHelper; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; +import net.minecraft.world.level.block.BellBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BellAttachType; + +public class BellRenderer extends SafeBlockEntityRenderer { + + public BellRenderer(BlockEntityRendererProvider.Context context) { + } + + @Override + protected void renderSafe(BE be, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light, int overlay) { + BlockState state = be.getBlockState(); + Direction facing = state.getValue(BellBlock.FACING); + BellAttachType attachment = state.getValue(BellBlock.ATTACHMENT); + + SuperByteBuffer bell = CachedBufferer.partial(be.getBellModel(), state); + + if (be.isRinging) + bell.rotateCentered(be.ringDirection.getCounterClockWise(), getSwingAngle(be.ringingTicks + partialTicks)); + + float rY = AngleHelper.horizontalAngle(facing); + if (attachment == BellAttachType.SINGLE_WALL || attachment == BellAttachType.DOUBLE_WALL) + rY += 90; + bell.rotateCentered(Direction.UP, AngleHelper.rad(rY)); + + bell.light(light) + .renderInto(ms, buffer.getBuffer(RenderType.cutout())); + } + + public static float getSwingAngle(float time) { + float t = time / 1.5f; + return 1.2f * Mth.sin(t / (float) Math.PI) / (2.5f + t / 3.0f); + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/bell/CustomRotationParticle.java b/src/main/java/com/simibubi/create/content/equipment/bell/CustomRotationParticle.java similarity index 98% rename from src/main/java/com/simibubi/create/content/curiosities/bell/CustomRotationParticle.java rename to src/main/java/com/simibubi/create/content/equipment/bell/CustomRotationParticle.java index d53316123..8de532da4 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/bell/CustomRotationParticle.java +++ b/src/main/java/com/simibubi/create/content/equipment/bell/CustomRotationParticle.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.bell; +package com.simibubi.create.content.equipment.bell; import org.joml.Quaternionf; import org.joml.Vector3f; diff --git a/src/main/java/com/simibubi/create/content/equipment/bell/HauntedBellBlock.java b/src/main/java/com/simibubi/create/content/equipment/bell/HauntedBellBlock.java new file mode 100644 index 000000000..e7886ca61 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/bell/HauntedBellBlock.java @@ -0,0 +1,52 @@ +package com.simibubi.create.content.equipment.bell; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.foundation.advancement.AllAdvancements; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; + +public class HauntedBellBlock extends AbstractBellBlock { + + public HauntedBellBlock(Properties properties) { + super(properties); + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.HAUNTED_BELL.get(); + } + + @Override + protected boolean ring(Level world, BlockPos pos, Direction direction, Player player) { + boolean ring = super.ring(world, pos, direction, player); + if (ring) + AllAdvancements.HAUNTED_BELL.awardTo(player); + return ring; + } + + @Override + public Class getBlockEntityClass() { + return HauntedBellBlockEntity.class; + } + + @Override + public void playSound(Level world, BlockPos pos) { + AllSoundEvents.HAUNTED_BELL_USE.playOnServer(world, pos, 4f, 1f); + } + + @Override + public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean isMoving) { + if (oldState.getBlock() != this && !world.isClientSide) + withBlockEntityDo(world, pos, hbte -> { + hbte.effectTicks = HauntedBellBlockEntity.EFFECT_TICKS; + hbte.sendData(); + }); + } + +} diff --git a/src/main/java/com/simibubi/create/content/equipment/bell/HauntedBellBlockEntity.java b/src/main/java/com/simibubi/create/content/equipment/bell/HauntedBellBlockEntity.java new file mode 100644 index 000000000..0784107b8 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/bell/HauntedBellBlockEntity.java @@ -0,0 +1,93 @@ +package com.simibubi.create.content.equipment.bell; + +import com.jozufozu.flywheel.core.PartialModel; +import com.simibubi.create.AllPartialModels; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public class HauntedBellBlockEntity extends AbstractBellBlockEntity { + + public static final int DISTANCE = 10; + public static final int RECHARGE_TICKS = 65; + public static final int EFFECT_TICKS = 20; + + public int effectTicks = 0; + + public HauntedBellBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + @OnlyIn(Dist.CLIENT) + public PartialModel getBellModel() { + return AllPartialModels.HAUNTED_BELL; + } + + @Override + public boolean ring(Level world, BlockPos pos, Direction direction) { + if (isRinging && ringingTicks < RECHARGE_TICKS) + return false; + HauntedBellPulser.sendPulse(world, pos, DISTANCE, false); + effectTicks = EFFECT_TICKS; + return super.ring(world, pos, direction); + } + + @Override + protected void write(CompoundTag compound, boolean clientPacket) { + super.write(compound, clientPacket); + compound.putInt("EffectTicks", effectTicks); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + super.read(compound, clientPacket); + effectTicks = compound.getInt("EffectTicks"); + } + + @Override + public void tick() { + super.tick(); + + if (effectTicks <= 0) + return; + effectTicks--; + + if (!level.isClientSide) + return; + + RandomSource rand = level.getRandom(); + if (rand.nextFloat() > 0.25f) + return; + + spawnParticle(rand); + playSound(rand); + } + + protected void spawnParticle(RandomSource rand) { + double x = worldPosition.getX() + rand.nextDouble(); + double y = worldPosition.getY() + 0.5; + double z = worldPosition.getZ() + rand.nextDouble(); + double vx = rand.nextDouble() * 0.04 - 0.02; + double vy = 0.1; + double vz = rand.nextDouble() * 0.04 - 0.02; + level.addParticle(ParticleTypes.SOUL, x, y, z, vx, vy, vz); + } + + protected void playSound(RandomSource rand) { + float vol = rand.nextFloat() * 0.4F + rand.nextFloat() > 0.9F ? 0.6F : 0.0F; + float pitch = 0.6F + rand.nextFloat() * 0.4F; + level.playSound(null, worldPosition, SoundEvents.SOUL_ESCAPE, SoundSource.BLOCKS, vol, pitch); + } + +} diff --git a/src/main/java/com/simibubi/create/content/equipment/bell/HauntedBellMovementBehaviour.java b/src/main/java/com/simibubi/create/content/equipment/bell/HauntedBellMovementBehaviour.java new file mode 100644 index 000000000..239f8b924 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/bell/HauntedBellMovementBehaviour.java @@ -0,0 +1,44 @@ +package com.simibubi.create.content.equipment.bell; + +import com.simibubi.create.content.contraptions.behaviour.BellMovementBehaviour; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; + +import net.minecraft.core.BlockPos; + +public class HauntedBellMovementBehaviour extends BellMovementBehaviour { + + public static final int DISTANCE = 3; + + @Override + public void tick(MovementContext context) { + int recharge = getRecharge(context); + if (recharge > 0) + setRecharge(context, recharge - 1); + } + + @Override + public void visitNewPosition(MovementContext context, BlockPos pos) { + if (!context.world.isClientSide && getRecharge(context) == 0) { + HauntedBellPulser.sendPulse(context.world, pos, DISTANCE, false); + setRecharge(context, HauntedBellBlockEntity.RECHARGE_TICKS); + playSound(context); + } + } + + @Override + public void writeExtraData(MovementContext context) { + context.blockEntityData.putInt("Recharge", getRecharge(context)); + } + + private int getRecharge(MovementContext context) { + if (!(context.temporaryData instanceof Integer) && context.world != null) { + context.temporaryData = context.blockEntityData.getInt("Recharge"); + } + return (Integer) context.temporaryData; + } + + private void setRecharge(MovementContext context, int value) { + context.temporaryData = value; + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/bell/HauntedBellPulser.java b/src/main/java/com/simibubi/create/content/equipment/bell/HauntedBellPulser.java similarity index 91% rename from src/main/java/com/simibubi/create/content/curiosities/bell/HauntedBellPulser.java rename to src/main/java/com/simibubi/create/content/equipment/bell/HauntedBellPulser.java index d90c066ea..ec80317c0 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/bell/HauntedBellPulser.java +++ b/src/main/java/com/simibubi/create/content/equipment/bell/HauntedBellPulser.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.bell; +package com.simibubi.create.content.equipment.bell; import java.util.UUID; import java.util.concurrent.ExecutionException; @@ -7,7 +7,7 @@ import java.util.concurrent.TimeUnit; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.simibubi.create.AllBlocks; -import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.AllPackets; import com.simibubi.create.foundation.utility.IntAttached; import net.minecraft.core.BlockPos; @@ -62,7 +62,7 @@ public class HauntedBellPulser { public static void sendPulse(Level world, BlockPos pos, int distance, boolean canOverlap) { LevelChunk chunk = world.getChunkAt(pos); - AllPackets.channel.send(PacketDistributor.TRACKING_CHUNK.with(() -> chunk), + AllPackets.getChannel().send(PacketDistributor.TRACKING_CHUNK.with(() -> chunk), new SoulPulseEffectPacket(pos, distance, canOverlap)); } diff --git a/src/main/java/com/simibubi/create/content/curiosities/bell/PeculiarBellBlock.java b/src/main/java/com/simibubi/create/content/equipment/bell/PeculiarBellBlock.java similarity index 89% rename from src/main/java/com/simibubi/create/content/curiosities/bell/PeculiarBellBlock.java rename to src/main/java/com/simibubi/create/content/equipment/bell/PeculiarBellBlock.java index df6cebab2..eb220828e 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/bell/PeculiarBellBlock.java +++ b/src/main/java/com/simibubi/create/content/equipment/bell/PeculiarBellBlock.java @@ -1,8 +1,8 @@ -package com.simibubi.create.content.curiosities.bell; +package com.simibubi.create.content.equipment.bell; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.AllTileEntities; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -17,20 +17,20 @@ import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; -public class PeculiarBellBlock extends AbstractBellBlock { +public class PeculiarBellBlock extends AbstractBellBlock { public PeculiarBellBlock(Properties properties) { super(properties); } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.PECULIAR_BELL.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.PECULIAR_BELL.get(); } @Override - public Class getTileEntityClass() { - return PeculiarBellTileEntity.class; + public Class getBlockEntityClass() { + return PeculiarBellBlockEntity.class; } @Override diff --git a/src/main/java/com/simibubi/create/content/equipment/bell/PeculiarBellBlockEntity.java b/src/main/java/com/simibubi/create/content/equipment/bell/PeculiarBellBlockEntity.java new file mode 100644 index 000000000..6cb81e257 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/bell/PeculiarBellBlockEntity.java @@ -0,0 +1,24 @@ +package com.simibubi.create.content.equipment.bell; + +import com.jozufozu.flywheel.core.PartialModel; +import com.simibubi.create.AllPartialModels; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public class PeculiarBellBlockEntity extends AbstractBellBlockEntity { + + public PeculiarBellBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + @OnlyIn(Dist.CLIENT) + public PartialModel getBellModel() { + return AllPartialModels.PECULIAR_BELL; + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/bell/SoulBaseParticle.java b/src/main/java/com/simibubi/create/content/equipment/bell/SoulBaseParticle.java similarity index 96% rename from src/main/java/com/simibubi/create/content/curiosities/bell/SoulBaseParticle.java rename to src/main/java/com/simibubi/create/content/equipment/bell/SoulBaseParticle.java index ff811c76e..dbde04033 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/bell/SoulBaseParticle.java +++ b/src/main/java/com/simibubi/create/content/equipment/bell/SoulBaseParticle.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.bell; +package com.simibubi.create.content.equipment.bell; import org.joml.Quaternionf; diff --git a/src/main/java/com/simibubi/create/content/curiosities/bell/SoulParticle.java b/src/main/java/com/simibubi/create/content/equipment/bell/SoulParticle.java similarity index 99% rename from src/main/java/com/simibubi/create/content/curiosities/bell/SoulParticle.java rename to src/main/java/com/simibubi/create/content/equipment/bell/SoulParticle.java index 16b6694c4..1c22401f9 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/bell/SoulParticle.java +++ b/src/main/java/com/simibubi/create/content/equipment/bell/SoulParticle.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.bell; +package com.simibubi.create.content.equipment.bell; import org.joml.Quaternionf; diff --git a/src/main/java/com/simibubi/create/content/curiosities/bell/SoulPulseEffect.java b/src/main/java/com/simibubi/create/content/equipment/bell/SoulPulseEffect.java similarity index 97% rename from src/main/java/com/simibubi/create/content/curiosities/bell/SoulPulseEffect.java rename to src/main/java/com/simibubi/create/content/equipment/bell/SoulPulseEffect.java index 892020b1f..87c9cee98 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/bell/SoulPulseEffect.java +++ b/src/main/java/com/simibubi/create/content/equipment/bell/SoulPulseEffect.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.bell; +package com.simibubi.create.content.equipment.bell; import java.util.ArrayList; import java.util.List; @@ -6,7 +6,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import com.google.common.collect.Streams; -import com.simibubi.create.content.curiosities.bell.SoulParticle.ExpandingPerimeterData; +import com.simibubi.create.content.equipment.bell.SoulParticle.ExpandingPerimeterData; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.core.BlockPos; diff --git a/src/main/java/com/simibubi/create/content/curiosities/bell/SoulPulseEffectHandler.java b/src/main/java/com/simibubi/create/content/equipment/bell/SoulPulseEffectHandler.java similarity index 95% rename from src/main/java/com/simibubi/create/content/curiosities/bell/SoulPulseEffectHandler.java rename to src/main/java/com/simibubi/create/content/equipment/bell/SoulPulseEffectHandler.java index 99217687e..93224e6aa 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/bell/SoulPulseEffectHandler.java +++ b/src/main/java/com/simibubi/create/content/equipment/bell/SoulPulseEffectHandler.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.bell; +package com.simibubi.create.content.equipment.bell; import java.util.ArrayList; import java.util.HashSet; diff --git a/src/main/java/com/simibubi/create/content/curiosities/bell/SoulPulseEffectPacket.java b/src/main/java/com/simibubi/create/content/equipment/bell/SoulPulseEffectPacket.java similarity index 76% rename from src/main/java/com/simibubi/create/content/curiosities/bell/SoulPulseEffectPacket.java rename to src/main/java/com/simibubi/create/content/equipment/bell/SoulPulseEffectPacket.java index 57d8bbcce..74652139a 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/bell/SoulPulseEffectPacket.java +++ b/src/main/java/com/simibubi/create/content/equipment/bell/SoulPulseEffectPacket.java @@ -1,13 +1,11 @@ -package com.simibubi.create.content.curiosities.bell; - -import java.util.function.Supplier; +package com.simibubi.create.content.equipment.bell; import com.simibubi.create.CreateClient; import com.simibubi.create.foundation.networking.SimplePacketBase; import net.minecraft.core.BlockPos; import net.minecraft.network.FriendlyByteBuf; -import net.minecraftforge.network.NetworkEvent; +import net.minecraftforge.network.NetworkEvent.Context; public class SoulPulseEffectPacket extends SimplePacketBase { @@ -35,11 +33,11 @@ public class SoulPulseEffectPacket extends SimplePacketBase { } @Override - public void handle(Supplier context) { - context.get().enqueueWork(() -> { + public boolean handle(Context context) { + context.enqueueWork(() -> { CreateClient.SOUL_PULSE_EFFECT_HANDLER.addPulse(new SoulPulseEffect(pos, distance, canOverlap)); }); - context.get().setPacketHandled(true); + return true; } } diff --git a/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintAssignCompleteRecipePacket.java b/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintAssignCompleteRecipePacket.java new file mode 100644 index 000000000..707fb974f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintAssignCompleteRecipePacket.java @@ -0,0 +1,44 @@ +package com.simibubi.create.content.equipment.blueprint; + +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import net.minecraftforge.network.NetworkEvent.Context; + +public class BlueprintAssignCompleteRecipePacket extends SimplePacketBase { + + private ResourceLocation recipeID; + + public BlueprintAssignCompleteRecipePacket(ResourceLocation recipeID) { + this.recipeID = recipeID; + } + + public BlueprintAssignCompleteRecipePacket(FriendlyByteBuf buffer) { + recipeID = buffer.readResourceLocation(); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeResourceLocation(recipeID); + } + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> { + ServerPlayer player = context.getSender(); + if (player == null) + return; + if (player.containerMenu instanceof BlueprintMenu) { + BlueprintMenu c = (BlueprintMenu) player.containerMenu; + player.getLevel() + .getRecipeManager() + .byKey(recipeID) + .ifPresent(r -> BlueprintItem.assignCompleteRecipe(c.ghostInventory, r)); + } + }); + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintEntity.java b/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintEntity.java similarity index 97% rename from src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintEntity.java rename to src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintEntity.java index c215780af..566f7ff85 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintEntity.java +++ b/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintEntity.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.tools; +package com.simibubi.create.content.equipment.blueprint; import java.util.HashMap; import java.util.Map; @@ -12,10 +12,10 @@ import org.apache.commons.lang3.Validate; import com.simibubi.create.AllEntityTypes; import com.simibubi.create.AllItems; import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.item.filter.FilterItem; -import com.simibubi.create.content.schematics.ISpecialEntityItemRequirement; -import com.simibubi.create.content.schematics.ItemRequirement; -import com.simibubi.create.content.schematics.ItemRequirement.ItemUseType; +import com.simibubi.create.content.logistics.filter.FilterItem; +import com.simibubi.create.content.schematics.requirement.ISpecialEntityItemRequirement; +import com.simibubi.create.content.schematics.requirement.ItemRequirement; +import com.simibubi.create.content.schematics.requirement.ItemRequirement.ItemUseType; import com.simibubi.create.foundation.networking.ISyncPersistentData; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.IInteractionChecker; @@ -544,7 +544,7 @@ public class BlueprintEntity extends HangingEntity @Override public AbstractContainerMenu createMenu(int id, Inventory inv, Player player) { - return BlueprintContainer.create(id, inv, this); + return BlueprintMenu.create(id, inv, this); } @Override diff --git a/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintItem.java b/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintItem.java similarity index 94% rename from src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintItem.java rename to src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintItem.java index 0b278081c..fb9791da3 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintItem.java +++ b/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintItem.java @@ -1,11 +1,11 @@ -package com.simibubi.create.content.curiosities.tools; +package com.simibubi.create.content.equipment.blueprint; import java.util.Collection; import com.simibubi.create.AllItems; -import com.simibubi.create.content.logistics.item.filter.AttributeFilterContainer.WhitelistMode; -import com.simibubi.create.content.logistics.item.filter.FilterItem; -import com.simibubi.create.content.logistics.item.filter.ItemAttribute; +import com.simibubi.create.content.logistics.filter.AttributeFilterMenu.WhitelistMode; +import com.simibubi.create.content.logistics.filter.FilterItem; +import com.simibubi.create.content.logistics.filter.ItemAttribute; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; diff --git a/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintMenu.java b/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintMenu.java new file mode 100644 index 000000000..4aaf0bb39 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintMenu.java @@ -0,0 +1,179 @@ +package com.simibubi.create.content.equipment.blueprint; + +import java.util.Optional; + +import com.simibubi.create.AllMenuTypes; +import com.simibubi.create.content.equipment.blueprint.BlueprintEntity.BlueprintSection; +import com.simibubi.create.foundation.gui.menu.GhostItemMenu; + +import net.minecraft.client.Minecraft; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.Entity; +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.CraftingContainer; +import net.minecraft.world.inventory.MenuType; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.CraftingRecipe; +import net.minecraft.world.item.crafting.RecipeType; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemStackHandler; +import net.minecraftforge.items.SlotItemHandler; + +public class BlueprintMenu extends GhostItemMenu { + + public BlueprintMenu(MenuType type, int id, Inventory inv, FriendlyByteBuf extraData) { + super(type, id, inv, extraData); + } + + public BlueprintMenu(MenuType type, int id, Inventory inv, BlueprintSection section) { + super(type, id, inv, section); + } + + public static BlueprintMenu create(int id, Inventory inv, BlueprintSection section) { + return new BlueprintMenu(AllMenuTypes.CRAFTING_BLUEPRINT.get(), id, inv, section); + } + + @Override + protected boolean allowRepeats() { + return true; + } + + @Override + protected void addSlots() { + addPlayerSlots(8, 131); + + int x = 29; + int y = 21; + int index = 0; + for (int row = 0; row < 3; ++row) + for (int col = 0; col < 3; ++col) + this.addSlot(new BlueprintCraftSlot(ghostInventory, index++, x + col * 18, y + row * 18)); + + addSlot(new BlueprintCraftSlot(ghostInventory, index++, 123, 40)); + addSlot(new SlotItemHandler(ghostInventory, index++, 135, 57)); + } + + public void onCraftMatrixChanged() { + if (contentHolder.getBlueprintWorld().isClientSide) + return; + + ServerPlayer serverplayerentity = (ServerPlayer) player; + CraftingContainer craftingInventory = new BlueprintCraftingInventory(this, ghostInventory); + Optional optional = player.getServer() + .getRecipeManager() + .getRecipeFor(RecipeType.CRAFTING, craftingInventory, player.getCommandSenderWorld()); + + if (!optional.isPresent()) { + if (ghostInventory.getStackInSlot(9) + .isEmpty()) + return; + if (!contentHolder.inferredIcon) + return; + + ghostInventory.setStackInSlot(9, ItemStack.EMPTY); + serverplayerentity.connection.send(new ClientboundContainerSetSlotPacket(containerId, incrementStateId(), 36 + 9, ItemStack.EMPTY)); + contentHolder.inferredIcon = false; + return; + } + + CraftingRecipe icraftingrecipe = optional.get(); + ItemStack itemstack = icraftingrecipe.assemble(craftingInventory); + ghostInventory.setStackInSlot(9, itemstack); + contentHolder.inferredIcon = true; + ItemStack toSend = itemstack.copy(); + toSend.getOrCreateTag() + .putBoolean("InferredFromRecipe", true); + serverplayerentity.connection.send(new ClientboundContainerSetSlotPacket(containerId, incrementStateId(), 36 + 9, toSend)); + } + + @Override + public void setItem(int slotId, int stateId, ItemStack stack) { + if (slotId == 36 + 9) { + if (stack.hasTag()) { + contentHolder.inferredIcon = stack.getTag() + .getBoolean("InferredFromRecipe"); + stack.getTag() + .remove("InferredFromRecipe"); + } else + contentHolder.inferredIcon = false; + } + super.setItem(slotId, stateId, stack); + } + + @Override + protected ItemStackHandler createGhostInventory() { + return contentHolder.getItems(); + } + + @Override + protected void initAndReadInventory(BlueprintSection contentHolder) { + super.initAndReadInventory(contentHolder); + } + + @Override + protected void saveData(BlueprintSection contentHolder) { + contentHolder.save(ghostInventory); + } + + @Override + @OnlyIn(Dist.CLIENT) + protected BlueprintSection createOnClient(FriendlyByteBuf extraData) { + int entityID = extraData.readVarInt(); + int section = extraData.readVarInt(); + Entity entityByID = Minecraft.getInstance().level.getEntity(entityID); + if (!(entityByID instanceof BlueprintEntity)) + return null; + BlueprintEntity blueprintEntity = (BlueprintEntity) entityByID; + BlueprintSection blueprintSection = blueprintEntity.getSection(section); + return blueprintSection; + } + + @Override + public boolean stillValid(Player player) { + return contentHolder != null && contentHolder.canPlayerUse(player); + } + + static class BlueprintCraftingInventory extends CraftingContainer { + + public BlueprintCraftingInventory(AbstractContainerMenu menu, ItemStackHandler items) { + super(menu, 3, 3); + for (int y = 0; y < 3; y++) { + for (int x = 0; x < 3; x++) { + ItemStack stack = items.getStackInSlot(y * 3 + x); + setItem(y * 3 + x, stack == null ? ItemStack.EMPTY : stack.copy()); + } + } + } + + } + + class BlueprintCraftSlot extends SlotItemHandler { + + private int index; + + public BlueprintCraftSlot(IItemHandler itemHandler, int index, int xPosition, int yPosition) { + super(itemHandler, index, xPosition, yPosition); + this.index = index; + } + + @Override + public void setChanged() { + super.setChanged(); + if (index == 9 && hasItem() && !contentHolder.getBlueprintWorld().isClientSide) { + contentHolder.inferredIcon = false; + ServerPlayer serverplayerentity = (ServerPlayer) player; + serverplayerentity.connection.send(new ClientboundContainerSetSlotPacket(containerId, incrementStateId(), 36 + 9, getItem())); + } + if (index < 9) + onCraftMatrixChanged(); + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintOverlayRenderer.java b/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintOverlayRenderer.java similarity index 93% rename from src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintOverlayRenderer.java rename to src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintOverlayRenderer.java index a0deb1c22..7c252285e 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintOverlayRenderer.java +++ b/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintOverlayRenderer.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.tools; +package com.simibubi.create.content.equipment.blueprint; import java.util.ArrayList; import java.util.HashMap; @@ -9,14 +9,13 @@ import java.util.Optional; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; -import com.simibubi.create.content.curiosities.tools.BlueprintEntity.BlueprintCraftingInventory; -import com.simibubi.create.content.curiosities.tools.BlueprintEntity.BlueprintSection; -import com.simibubi.create.content.logistics.item.filter.AttributeFilterContainer.WhitelistMode; -import com.simibubi.create.content.logistics.item.filter.FilterItem; -import com.simibubi.create.content.logistics.item.filter.ItemAttribute; -import com.simibubi.create.content.logistics.trains.track.TrackPlacement.PlacementInfo; +import com.simibubi.create.content.equipment.blueprint.BlueprintEntity.BlueprintCraftingInventory; +import com.simibubi.create.content.equipment.blueprint.BlueprintEntity.BlueprintSection; +import com.simibubi.create.content.logistics.filter.AttributeFilterMenu.WhitelistMode; +import com.simibubi.create.content.logistics.filter.FilterItem; +import com.simibubi.create.content.logistics.filter.ItemAttribute; +import com.simibubi.create.content.trains.track.TrackPlacement.PlacementInfo; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.element.GuiGameElement; import com.simibubi.create.foundation.utility.AnimationTickHolder; @@ -106,7 +105,7 @@ public class BlueprintOverlayRenderer { int tracks = info.requiredTracks; while (tracks > 0) { - ingredients.add(Pair.of(AllBlocks.TRACK.asStack(Math.min(64, tracks)), info.hasRequiredTracks)); + ingredients.add(Pair.of(new ItemStack(info.trackMaterial.getBlock(), Math.min(64, tracks)), info.hasRequiredTracks)); tracks -= 64; } diff --git a/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintRenderer.java b/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintRenderer.java similarity index 90% rename from src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintRenderer.java rename to src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintRenderer.java index 8b9675eb1..a560e74ce 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintRenderer.java +++ b/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintRenderer.java @@ -1,12 +1,12 @@ -package com.simibubi.create.content.curiosities.tools; +package com.simibubi.create.content.equipment.blueprint; import org.joml.Matrix3f; import com.jozufozu.flywheel.core.PartialModel; import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.curiosities.tools.BlueprintEntity.BlueprintSection; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.equipment.blueprint.BlueprintEntity.BlueprintSection; import com.simibubi.create.foundation.render.CachedBufferer; import com.simibubi.create.foundation.render.SuperByteBuffer; import com.simibubi.create.foundation.utility.Couple; @@ -32,8 +32,8 @@ public class BlueprintRenderer extends EntityRenderer { @Override public void render(BlueprintEntity entity, float yaw, float pt, PoseStack ms, MultiBufferSource buffer, int light) { - PartialModel partialModel = entity.size == 3 ? AllBlockPartials.CRAFTING_BLUEPRINT_3x3 - : entity.size == 2 ? AllBlockPartials.CRAFTING_BLUEPRINT_2x2 : AllBlockPartials.CRAFTING_BLUEPRINT_1x1; + PartialModel partialModel = entity.size == 3 ? AllPartialModels.CRAFTING_BLUEPRINT_3x3 + : entity.size == 2 ? AllPartialModels.CRAFTING_BLUEPRINT_2x2 : AllPartialModels.CRAFTING_BLUEPRINT_1x1; SuperByteBuffer sbb = CachedBufferer.partial(partialModel, Blocks.AIR.defaultBlockState()); sbb.rotateY(-yaw) .rotateX(90.0F + entity.getXRot()) diff --git a/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintScreen.java b/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintScreen.java similarity index 88% rename from src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintScreen.java rename to src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintScreen.java index 3999c10dc..d64b3c927 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintScreen.java +++ b/src/main/java/com/simibubi/create/content/equipment/blueprint/BlueprintScreen.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.tools; +package com.simibubi.create.content.equipment.blueprint; import static com.simibubi.create.foundation.gui.AllGuiTextures.PLAYER_INVENTORY; @@ -8,15 +8,15 @@ import java.util.List; import com.google.common.collect.ImmutableList; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.logistics.item.filter.FilterScreenPacket; -import com.simibubi.create.content.logistics.item.filter.FilterScreenPacket.Option; +import com.simibubi.create.AllPackets; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.logistics.filter.FilterScreenPacket; +import com.simibubi.create.content.logistics.filter.FilterScreenPacket.Option; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.gui.container.AbstractSimiContainerScreen; import com.simibubi.create.foundation.gui.element.GuiGameElement; +import com.simibubi.create.foundation.gui.menu.AbstractSimiContainerScreen; import com.simibubi.create.foundation.gui.widget.IconButton; -import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.utility.Lang; import net.minecraft.ChatFormatting; @@ -25,7 +25,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.item.ItemStack; -public class BlueprintScreen extends AbstractSimiContainerScreen { +public class BlueprintScreen extends AbstractSimiContainerScreen { protected AllGuiTextures background; private List extraAreas = Collections.emptyList(); @@ -33,8 +33,8 @@ public class BlueprintScreen extends AbstractSimiContainerScreenat(x + background.width + 20, y + background.height - 32, 0) .rotate(45, -45, 22.5f) .scale(40) @@ -166,7 +166,7 @@ public class BlueprintScreen extends AbstractSimiContainerScreen, IWrenchable, ProperWaterloggedBlock { + + public static final BooleanProperty WRITTEN = BooleanProperty.create("written"); + + public ClipboardBlock(Properties pProperties) { + super(pProperties); + registerDefaultState(defaultBlockState().setValue(WATERLOGGED, false) + .setValue(WRITTEN, false)); + } + + @Override + protected void createBlockStateDefinition(Builder pBuilder) { + super.createBlockStateDefinition(pBuilder.add(WRITTEN, FACE, FACING, WATERLOGGED)); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext pContext) { + BlockState stateForPlacement = super.getStateForPlacement(pContext); + if (stateForPlacement == null) + return null; + if (stateForPlacement.getValue(FACE) != AttachFace.WALL) + stateForPlacement = stateForPlacement.setValue(FACING, stateForPlacement.getValue(FACING) + .getOpposite()); + return withWater(stateForPlacement, pContext).setValue(WRITTEN, pContext.getItemInHand() + .hasTag()); + } + + @Override + public VoxelShape getShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, CollisionContext pContext) { + return (switch (pState.getValue(FACE)) { + case FLOOR -> AllShapes.CLIPBOARD_FLOOR; + case CEILING -> AllShapes.CLIPBOARD_CEILING; + default -> AllShapes.CLIPBOARD_WALL; + }).get(pState.getValue(FACING)); + } + + public boolean canSurvive(BlockState pState, LevelReader pLevel, BlockPos pPos) { + return !pLevel.getBlockState(pPos.relative(getConnectedDirection(pState).getOpposite())) + .getMaterial() + .isReplaceable(); + } + + @Override + public InteractionResult use(BlockState pState, Level pLevel, BlockPos pPos, Player pPlayer, InteractionHand pHand, + BlockHitResult pHit) { + if (pPlayer.isSteppingCarefully()) { + breakAndCollect(pState, pLevel, pPos, pPlayer); + return InteractionResult.SUCCESS; + } + + return onBlockEntityUse(pLevel, pPos, cbe -> { + if (pLevel.isClientSide()) + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> openScreen(pPlayer, cbe.dataContainer, pPos)); + return InteractionResult.SUCCESS; + }); + } + + @OnlyIn(Dist.CLIENT) + private void openScreen(Player player, ItemStack stack, BlockPos pos) { + if (Minecraft.getInstance().player == player) + ScreenOpener.open(new ClipboardScreen(player.getInventory().selected, stack, pos)); + } + + @Override + public void attack(BlockState pState, Level pLevel, BlockPos pPos, Player pPlayer) { + breakAndCollect(pState, pLevel, pPos, pPlayer); + } + + private void breakAndCollect(BlockState pState, Level pLevel, BlockPos pPos, Player pPlayer) { + if (pPlayer instanceof FakePlayer) + return; + if (pLevel.isClientSide) + return; + ItemStack cloneItemStack = getCloneItemStack(pLevel, pPos, pState); + pLevel.destroyBlock(pPos, false); + if (pLevel.getBlockState(pPos) != pState) + pPlayer.getInventory() + .placeItemBackInInventory(cloneItemStack); + } + + @Override + public ItemStack getCloneItemStack(BlockGetter world, BlockPos pos, BlockState state) { + if (world.getBlockEntity(pos) instanceof ClipboardBlockEntity cbe) + return cbe.dataContainer; + return new ItemStack(this); + } + + @Override + public void playerWillDestroy(Level pLevel, BlockPos pPos, BlockState pState, Player pPlayer) { + if (!(pLevel.getBlockEntity(pPos) instanceof ClipboardBlockEntity cbe)) + return; + if (pLevel.isClientSide || pPlayer.isCreative()) + return; + Block.popResource(pLevel, pPos, cbe.dataContainer.copy()); + } + + @Override + @SuppressWarnings("deprecation") + public List getDrops(BlockState pState, LootContext.Builder pBuilder) { + if (!(pBuilder.getOptionalParameter(LootContextParams.BLOCK_ENTITY) instanceof ClipboardBlockEntity cbe)) + return super.getDrops(pState, pBuilder); + pBuilder.withDynamicDrop(ShulkerBoxBlock.CONTENTS, + (p_56218_, p_56219_) -> p_56219_.accept(cbe.dataContainer.copy())); + return ImmutableList.of(cbe.dataContainer.copy()); + } + + @Override + public FluidState getFluidState(BlockState pState) { + return fluidState(pState); + } + + @Override + public BlockState updateShape(BlockState pState, Direction pFacing, BlockState pFacingState, LevelAccessor pLevel, + BlockPos pCurrentPos, BlockPos pFacingPos) { + updateWater(pLevel, pState, pCurrentPos); + return super.updateShape(pState, pFacing, pFacingState, pLevel, pCurrentPos, pFacingPos); + } + + @Override + public Class getBlockEntityClass() { + return ClipboardBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.CLIPBOARD.get(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardBlockEntity.java b/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardBlockEntity.java new file mode 100644 index 000000000..7d1afe661 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardBlockEntity.java @@ -0,0 +1,89 @@ +package com.simibubi.create.content.equipment.clipboard; + +import java.util.List; +import java.util.UUID; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; + +import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.fml.DistExecutor; + +public class ClipboardBlockEntity extends SmartBlockEntity { + + public ItemStack dataContainer; + private UUID lastEdit; + + public ClipboardBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + dataContainer = AllBlocks.CLIPBOARD.asStack(); + } + + @Override + public void initialize() { + super.initialize(); + updateWrittenState(); + } + + public void onEditedBy(Player player) { + lastEdit = player.getUUID(); + notifyUpdate(); + updateWrittenState(); + } + + public void updateWrittenState() { + BlockState blockState = getBlockState(); + if (!AllBlocks.CLIPBOARD.has(blockState)) + return; + if (level.isClientSide()) + return; + boolean isWritten = blockState.getValue(ClipboardBlock.WRITTEN); + boolean shouldBeWritten = dataContainer.getTag() != null; + if (isWritten == shouldBeWritten) + return; + level.setBlockAndUpdate(worldPosition, blockState.setValue(ClipboardBlock.WRITTEN, shouldBeWritten)); + } + + @Override + public void addBehaviours(List behaviours) {} + + @Override + protected void write(CompoundTag tag, boolean clientPacket) { + super.write(tag, clientPacket); + tag.put("Item", dataContainer.serializeNBT()); + if (clientPacket && lastEdit != null) + tag.putUUID("LastEdit", lastEdit); + } + + @Override + protected void read(CompoundTag tag, boolean clientPacket) { + super.read(tag, clientPacket); + dataContainer = ItemStack.of(tag.getCompound("Item")); + + if (clientPacket) + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> readClientSide(tag)); + } + + @OnlyIn(Dist.CLIENT) + private void readClientSide(CompoundTag tag) { + Minecraft mc = Minecraft.getInstance(); + if (!(mc.screen instanceof ClipboardScreen cs)) + return; + if (tag.contains("LastEdit") && tag.getUUID("LastEdit") + .equals(mc.player.getUUID())) + return; + if (!worldPosition.equals(cs.targetedBlock)) + return; + cs.reopenWith(dataContainer); + } + +} diff --git a/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardBlockItem.java b/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardBlockItem.java new file mode 100644 index 000000000..58a0d4b10 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardBlockItem.java @@ -0,0 +1,81 @@ +package com.simibubi.create.content.equipment.clipboard; + +import javax.annotation.Nonnull; + +import com.simibubi.create.foundation.gui.ScreenOpener; + +import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +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.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.UseOnContext; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.items.ItemHandlerHelper; + +public class ClipboardBlockItem extends BlockItem { + + public ClipboardBlockItem(Block pBlock, Properties pProperties) { + super(pBlock, pProperties); + } + + @Nonnull + @Override + public InteractionResult useOn(UseOnContext context) { + Player player = context.getPlayer(); + if (player == null) + return InteractionResult.PASS; + if (player.isSteppingCarefully()) + return super.useOn(context); + return use(context.getLevel(), player, context.getHand()).getResult(); + } + + @Override + protected boolean updateCustomBlockEntityTag(BlockPos pPos, Level pLevel, Player pPlayer, ItemStack pStack, + BlockState pState) { + if (pLevel.isClientSide()) + return false; + if (!(pLevel.getBlockEntity(pPos) instanceof ClipboardBlockEntity cbe)) + return false; + cbe.dataContainer = ItemHandlerHelper.copyStackWithSize(pStack, 1); + cbe.notifyUpdate(); + return true; + } + + @Override + public InteractionResultHolder use(Level world, Player player, InteractionHand hand) { + ItemStack heldItem = player.getItemInHand(hand); + if (hand == InteractionHand.OFF_HAND) + return InteractionResultHolder.pass(heldItem); + + player.getCooldowns() + .addCooldown(heldItem.getItem(), 10); + if (world.isClientSide) + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> openScreen(player, heldItem)); + CompoundTag tag = heldItem.getOrCreateTag(); + tag.putInt("Type", ClipboardOverrides.ClipboardType.EDITING.ordinal()); + heldItem.setTag(tag); + + return InteractionResultHolder.success(heldItem); + } + + @OnlyIn(Dist.CLIENT) + private void openScreen(Player player, ItemStack stack) { + if (Minecraft.getInstance().player == player) + ScreenOpener.open(new ClipboardScreen(player.getInventory().selected, stack, null)); + } + + public void registerModelOverrides() { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> ClipboardOverrides.registerModelOverridesClient(this)); + } + +} diff --git a/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardCloneable.java b/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardCloneable.java new file mode 100644 index 000000000..fcd783b90 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardCloneable.java @@ -0,0 +1,15 @@ +package com.simibubi.create.content.equipment.clipboard; + +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.player.Player; + +public interface ClipboardCloneable { + + public String getClipboardKey(); + + public boolean writeToClipboard(CompoundTag tag, Direction side); + + public boolean readFromClipboard(CompoundTag tag, Player player, Direction side, boolean simulate); + +} diff --git a/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardEditPacket.java b/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardEditPacket.java new file mode 100644 index 000000000..85a92e8ce --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardEditPacket.java @@ -0,0 +1,72 @@ +package com.simibubi.create.content.equipment.clipboard; + +import javax.annotation.Nullable; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraftforge.network.NetworkEvent.Context; + +public class ClipboardEditPacket extends SimplePacketBase { + + private int hotbarSlot; + private CompoundTag data; + private BlockPos targetedBlock; + + public ClipboardEditPacket(int hotbarSlot, CompoundTag data, @Nullable BlockPos targetedBlock) { + this.hotbarSlot = hotbarSlot; + this.data = data; + this.targetedBlock = targetedBlock; + } + + public ClipboardEditPacket(FriendlyByteBuf buffer) { + hotbarSlot = buffer.readVarInt(); + data = buffer.readNbt(); + if (buffer.readBoolean()) + targetedBlock = buffer.readBlockPos(); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeVarInt(hotbarSlot); + buffer.writeNbt(data); + buffer.writeBoolean(targetedBlock != null); + if (targetedBlock != null) + buffer.writeBlockPos(targetedBlock); + } + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> { + ServerPlayer sender = context.getSender(); + + if (targetedBlock != null) { + Level world = sender.level; + if (world == null || !world.isLoaded(targetedBlock)) + return; + if (!targetedBlock.closerThan(sender.blockPosition(), 20)) + return; + if (world.getBlockEntity(targetedBlock) instanceof ClipboardBlockEntity cbe) { + cbe.dataContainer.setTag(data.isEmpty() ? null : data); + cbe.onEditedBy(sender); + } + return; + } + + ItemStack itemStack = sender.getInventory() + .getItem(hotbarSlot); + if (!AllBlocks.CLIPBOARD.isIn(itemStack)) + return; + itemStack.setTag(data.isEmpty() ? null : data); + }); + + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardEntry.java b/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardEntry.java new file mode 100644 index 000000000..480d4cdab --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardEntry.java @@ -0,0 +1,77 @@ +package com.simibubi.create.content.equipment.clipboard; + +import java.util.ArrayList; +import java.util.List; + +import com.simibubi.create.foundation.utility.NBTHelper; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.world.item.ItemStack; + +public class ClipboardEntry { + + public boolean checked; + public MutableComponent text; + public ItemStack icon; + + public ClipboardEntry(boolean checked, MutableComponent text) { + this.checked = checked; + this.text = text; + this.icon = ItemStack.EMPTY; + } + + public ClipboardEntry displayItem(ItemStack icon) { + this.icon = icon; + return this; + } + + public static List> readAll(ItemStack clipboardItem) { + CompoundTag tag = clipboardItem.getTag(); + if (tag == null) + return new ArrayList<>(); + return NBTHelper.readCompoundList(tag.getList("Pages", Tag.TAG_COMPOUND), pageTag -> NBTHelper + .readCompoundList(pageTag.getList("Entries", Tag.TAG_COMPOUND), ClipboardEntry::readNBT)); + } + + public static List getLastViewedEntries(ItemStack heldItem) { + List> pages = ClipboardEntry.readAll(heldItem); + if (pages.isEmpty()) + return new ArrayList<>(); + int page = heldItem.getTag() == null ? 0 + : Math.min(heldItem.getTag() + .getInt("PreviouslyOpenedPage"), pages.size() - 1); + List entries = pages.get(page); + return entries; + } + + public static void saveAll(List> entries, ItemStack clipboardItem) { + CompoundTag tag = clipboardItem.getOrCreateTag(); + tag.put("Pages", NBTHelper.writeCompoundList(entries, list -> { + CompoundTag pageTag = new CompoundTag(); + pageTag.put("Entries", NBTHelper.writeCompoundList(list, ClipboardEntry::writeNBT)); + return pageTag; + })); + } + + public CompoundTag writeNBT() { + CompoundTag nbt = new CompoundTag(); + nbt.putBoolean("Checked", checked); + nbt.putString("Text", Component.Serializer.toJson(text)); + if (icon.isEmpty()) + return nbt; + nbt.put("Icon", icon.serializeNBT()); + return nbt; + } + + public static ClipboardEntry readNBT(CompoundTag tag) { + ClipboardEntry clipboardEntry = + new ClipboardEntry(tag.getBoolean("Checked"), Component.Serializer.fromJson(tag.getString("Text"))); + if (tag.contains("Icon")) + clipboardEntry.displayItem(ItemStack.of(tag.getCompound("Icon"))); + return clipboardEntry; + } + +} diff --git a/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardOverrides.java b/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardOverrides.java new file mode 100644 index 000000000..5d8cf71fe --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardOverrides.java @@ -0,0 +1,57 @@ +package com.simibubi.create.content.equipment.clipboard; + +import com.simibubi.create.Create; +import com.tterrag.registrate.providers.DataGenContext; +import com.tterrag.registrate.providers.RegistrateItemModelProvider; + +import net.minecraft.client.renderer.item.ItemProperties; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.client.model.generators.ItemModelBuilder; +import net.minecraftforge.client.model.generators.ModelFile.UncheckedModelFile; + +public class ClipboardOverrides { + + public enum ClipboardType { + EMPTY("empty_clipboard"), WRITTEN("clipboard"), EDITING("clipboard_and_quill"); + + public String file; + public static ResourceLocation ID = Create.asResource("clipboard_type"); + + private ClipboardType(String file) { + this.file = file; + } + } + + public static void switchTo(ClipboardType type, ItemStack clipboardItem) { + CompoundTag tag = clipboardItem.getOrCreateTag(); + tag.putInt("Type", type.ordinal()); + } + + @OnlyIn(Dist.CLIENT) + public static void registerModelOverridesClient(ClipboardBlockItem item) { + ItemProperties.register(item, ClipboardType.ID, (pStack, pLevel, pEntity, pSeed) -> { + CompoundTag tag = pStack.getTag(); + return tag == null ? 0 : tag.getInt("Type"); + }); + } + + public static ItemModelBuilder addOverrideModels(DataGenContext c, + RegistrateItemModelProvider p) { + ItemModelBuilder builder = p.generated(() -> c.get()); + for (int i = 0; i < ClipboardType.values().length; i++) { + builder.override() + .predicate(ClipboardType.ID, i) + .model(p.getBuilder(c.getName() + "_" + i) + .parent(new UncheckedModelFile("item/generated")) + .texture("layer0", Create.asResource("item/" + ClipboardType.values()[i].file))) + .end(); + } + return builder; + } + +} diff --git a/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardScreen.java b/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardScreen.java new file mode 100644 index 000000000..696ba720f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardScreen.java @@ -0,0 +1,837 @@ +package com.simibubi.create.content.equipment.clipboard; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.annotation.Nullable; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.mutable.MutableBoolean; +import org.apache.commons.lang3.mutable.MutableInt; + +import com.google.common.collect.Lists; +import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.BufferBuilder; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.Tesselator; +import com.mojang.blaze3d.vertex.VertexFormat; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPackets; +import com.simibubi.create.content.equipment.clipboard.ClipboardOverrides.ClipboardType; +import com.simibubi.create.foundation.gui.AbstractSimiScreen; +import com.simibubi.create.foundation.gui.AllGuiTextures; +import com.simibubi.create.foundation.gui.AllIcons; +import com.simibubi.create.foundation.gui.widget.IconButton; +import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.Lang; + +import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntList; +import net.minecraft.SharedConstants; +import net.minecraft.Util; +import net.minecraft.client.StringSplitter; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiComponent; +import net.minecraft.client.gui.font.TextFieldHelper; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.gui.screens.inventory.PageButton; +import net.minecraft.client.multiplayer.ClientPacketListener; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.renderer.Rect2i; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.Style; +import net.minecraft.util.FormattedCharSequence; +import net.minecraft.util.Mth; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public class ClipboardScreen extends AbstractSimiScreen { + + public ItemStack item; + public BlockPos targetedBlock; + + List> pages; + List currentEntries; + int editingIndex; + int frameTick; + PageButton forward; + PageButton backward; + int currentPage; + long lastClickTime; + int lastIndex = -1; + + int hoveredEntry; + boolean hoveredCheck; + boolean readonly; + + DisplayCache displayCache = DisplayCache.EMPTY; + TextFieldHelper editContext; + + IconButton closeBtn; + IconButton clearBtn; + + private int targetSlot; + + public ClipboardScreen(int targetSlot, ItemStack item, @Nullable BlockPos pos) { + this.targetSlot = targetSlot; + this.targetedBlock = pos; + reopenWith(item); + } + + public void reopenWith(ItemStack clipboard) { + item = clipboard; + pages = ClipboardEntry.readAll(item); + if (pages.isEmpty()) + pages.add(new ArrayList<>()); + if (clearBtn == null) { + currentPage = item.getTag() == null ? 0 + : item.getTag() + .getInt("PreviouslyOpenedPage"); + currentPage = Mth.clamp(currentPage, 0, pages.size() - 1); + } + currentEntries = pages.get(currentPage); + boolean startEmpty = currentEntries.isEmpty(); + if (startEmpty) + currentEntries.add(new ClipboardEntry(false, Components.empty())); + editingIndex = 0; + editContext = new TextFieldHelper(this::getCurrentEntryText, this::setCurrentEntryText, this::getClipboard, + this::setClipboard, this::validateTextForEntry); + editingIndex = startEmpty ? 0 : -1; + readonly = item.getTag() != null && item.getTag() + .getBoolean("Readonly"); + if (readonly) + editingIndex = -1; + if (clearBtn != null) + init(); + } + + @Override + protected void init() { + setWindowSize(256, 256); + super.init(); + clearDisplayCache(); + + int x = guiLeft; + int y = guiTop - 8; + + clearWidgets(); + clearBtn = new IconButton(x + 234, y + 153, AllIcons.I_CLEAR_CHECKED).withCallback(() -> { + editingIndex = -1; + currentEntries.removeIf(ce -> ce.checked); + if (currentEntries.isEmpty()) + currentEntries.add(new ClipboardEntry(false, Components.empty())); + sendIfEditingBlock(); + }); + clearBtn.setToolTip(Lang.translateDirect("gui.clipboard.erase_checked")); + closeBtn = new IconButton(x + 234, y + 175, AllIcons.I_PRIORITY_VERY_LOW) + .withCallback(() -> minecraft.setScreen(null)); + closeBtn.setToolTip(Lang.translateDirect("station.close")); + addRenderableWidget(closeBtn); + addRenderableWidget(clearBtn); + + forward = new PageButton(x + 176, y + 229, true, $ -> changePage(true), true); + backward = new PageButton(x + 53, y + 229, false, $ -> changePage(false), true); + addRenderableWidget(forward); + addRenderableWidget(backward); + + forward.visible = currentPage < 50 && (!readonly || currentPage + 1 < pages.size()); + backward.visible = currentPage > 0; + } + + private int getNumPages() { + return pages.size(); + } + + public void tick() { + super.tick(); + frameTick++; + + if (targetedBlock != null) { + if (!minecraft.player.blockPosition() + .closerThan(targetedBlock, 10)) { + removed(); + return; + } + if (!AllBlocks.CLIPBOARD.has(minecraft.level.getBlockState(targetedBlock))) { + removed(); + return; + } + } + + int mx = (int) (this.minecraft.mouseHandler.xpos() * (double) this.minecraft.getWindow() + .getGuiScaledWidth() / (double) this.minecraft.getWindow() + .getScreenWidth()); + int my = (int) (this.minecraft.mouseHandler.ypos() * (double) this.minecraft.getWindow() + .getGuiScaledHeight() / (double) this.minecraft.getWindow() + .getScreenHeight()); + + mx -= guiLeft + 35; + my -= guiTop + 41; + + hoveredCheck = false; + hoveredEntry = -1; + + if (mx > 0 && mx < 183 && my > 0 && my < 190) { + hoveredCheck = mx < 20; + int totalHeight = 0; + for (int i = 0; i < currentEntries.size(); i++) { + ClipboardEntry clipboardEntry = currentEntries.get(i); + String text = clipboardEntry.text.getString(); + totalHeight += + Math.max(12, font.split(Components.literal(text), clipboardEntry.icon.isEmpty() ? 150 : 130) + .size() * 9 + 3); + + if (totalHeight > my) { + hoveredEntry = i; + return; + } + } + hoveredEntry = currentEntries.size(); + } + } + + private String getCurrentEntryText() { + return currentEntries.get(editingIndex).text.getString(); + } + + private void setCurrentEntryText(String text) { + currentEntries.get(editingIndex).text = Components.literal(text); + sendIfEditingBlock(); + } + + private void setClipboard(String p_98148_) { + if (minecraft != null) + TextFieldHelper.setClipboardContents(minecraft, p_98148_); + } + + private String getClipboard() { + return minecraft != null ? TextFieldHelper.getClipboardContents(minecraft) : ""; + } + + private boolean validateTextForEntry(String newText) { + int totalHeight = 0; + for (int i = 0; i < currentEntries.size(); i++) { + ClipboardEntry clipboardEntry = currentEntries.get(i); + String text = i == editingIndex ? newText : clipboardEntry.text.getString(); + totalHeight += Math.max(12, font.split(Components.literal(text), 150) + .size() * 9 + 3); + } + return totalHeight < 185; + } + + private int yOffsetOfEditingEntry() { + int totalHeight = 0; + for (int i = 0; i < currentEntries.size(); i++) { + if (i == editingIndex) + break; + ClipboardEntry clipboardEntry = currentEntries.get(i); + totalHeight += Math.max(12, font.split(clipboardEntry.text, 150) + .size() * 9 + 3); + } + return totalHeight; + } + + private void changePage(boolean next) { + int previously = currentPage; + currentPage = Mth.clamp(currentPage + (next ? 1 : -1), 0, 50); + if (currentPage == previously) + return; + editingIndex = -1; + if (pages.size() <= currentPage) { + if (readonly) { + currentPage = previously; + return; + } + pages.add(new ArrayList<>()); + } + currentEntries = pages.get(currentPage); + if (currentEntries.isEmpty()) { + currentEntries.add(new ClipboardEntry(false, Components.empty())); + if (!readonly) { + editingIndex = 0; + editContext.setCursorToEnd(); + clearDisplayCacheAfterChange(); + } + } + + forward.visible = currentPage < 50 && (!readonly || currentPage + 1 < pages.size()); + backward.visible = currentPage > 0; + + if (next) + return; + if (pages.get(currentPage + 1) + .stream() + .allMatch(ce -> ce.text.getString() + .isBlank())) + pages.remove(currentPage + 1); + } + + @Override + protected void renderWindow(PoseStack ms, int mouseX, int mouseY, float partialTicks) { + int x = guiLeft; + int y = guiTop - 8; + + AllGuiTextures.CLIPBOARD.render(ms, x, y); + font.draw(ms, Components.translatable("book.pageIndicator", currentPage + 1, getNumPages()), x + 150, y + 9, + 0x43ffffff); + + for (int i = 0; i < currentEntries.size(); i++) { + ClipboardEntry clipboardEntry = currentEntries.get(i); + boolean checked = clipboardEntry.checked; + int iconOffset = clipboardEntry.icon.isEmpty() ? 0 : 16; + + font.draw(ms, "\u25A1", x + 45, y + 51, checked ? 0x668D7F6B : 0xff8D7F6B); + if (checked) + font.draw(ms, "\u2714", x + 45, y + 50, 0x31B25D); + + List split = font.split(clipboardEntry.text, 150 - iconOffset); + if (split.isEmpty()) { + y += 12; + continue; + } + + if (!clipboardEntry.icon.isEmpty()) + itemRenderer.renderGuiItem(clipboardEntry.icon, x + 54, y + 50); + + for (FormattedCharSequence sequence : split) { + if (i != editingIndex) + font.draw(ms, sequence, x + 58 + iconOffset, y + 50, checked ? 0x31B25D : 0x311A00); + y += 9; + } + y += 3; + } + + if (editingIndex == -1) + return; + + boolean checked = currentEntries.get(editingIndex).checked; + + setFocused(null); + DisplayCache cache = getDisplayCache(); + + for (LineInfo line : cache.lines) + font.draw(ms, line.asComponent, line.x, line.y, checked ? 0x31B25D : 0x311A00); + + renderHighlight(cache.selection); + renderCursor(ms, cache.cursor, cache.cursorAtEnd); + } + + @Override + public void removed() { + pages.forEach(list -> list.removeIf(ce -> ce.text.getString() + .isBlank())); + pages.removeIf(List::isEmpty); + + for (int i = 0; i < pages.size(); i++) + if (pages.get(i) == currentEntries) + item.getOrCreateTag() + .putInt("PreviouslyOpenedPage", i); + + send(); + + super.removed(); + } + + private void sendIfEditingBlock() { + ClientPacketListener handler = minecraft.player.connection; + if (handler.getOnlinePlayers() + .size() > 1 && targetedBlock != null) + send(); + } + + private void send() { + ClipboardEntry.saveAll(pages, item); + ClipboardOverrides.switchTo(ClipboardType.WRITTEN, item); + if (pages.isEmpty()) + item.setTag(new CompoundTag()); + AllPackets.getChannel() + .sendToServer(new ClipboardEditPacket(targetSlot, item.getOrCreateTag(), targetedBlock)); + } + + @Override + public boolean isPauseScreen() { + return false; + } + + @Override + public boolean mouseScrolled(double pMouseX, double pMouseY, double pDelta) { + changePage(pDelta < 0); + return true; + } + + @Override + public boolean keyPressed(int pKeyCode, int pScanCode, int pModifiers) { + if (pKeyCode == 266) { + backward.onPress(); + return true; + } + if (pKeyCode == 267) { + forward.onPress(); + return true; + } + if (editingIndex != -1 && pKeyCode != 256) { + keyPressedWhileEditing(pKeyCode, pScanCode, pModifiers); + clearDisplayCache(); + return true; + } + if (super.keyPressed(pKeyCode, pScanCode, pModifiers)) + return true; + return true; + } + + @Override + public boolean charTyped(char pCodePoint, int pModifiers) { + if (super.charTyped(pCodePoint, pModifiers)) + return true; + if (!SharedConstants.isAllowedChatCharacter(pCodePoint)) + return false; + if (editingIndex == -1) + return false; + editContext.insertText(Character.toString(pCodePoint)); + clearDisplayCache(); + return true; + } + + private boolean keyPressedWhileEditing(int pKeyCode, int pScanCode, int pModifiers) { + if (Screen.isSelectAll(pKeyCode)) { + editContext.selectAll(); + return true; + } else if (Screen.isCopy(pKeyCode)) { + editContext.copy(); + return true; + } else if (Screen.isPaste(pKeyCode)) { + editContext.paste(); + return true; + } else if (Screen.isCut(pKeyCode)) { + editContext.cut(); + return true; + } else { + switch (pKeyCode) { + case 257: + case 335: + if (hasShiftDown()) { + editContext.insertText("\n"); + return true; + } else if (!hasControlDown()) { + if (currentEntries.size() <= editingIndex + 1 + || !currentEntries.get(editingIndex + 1).text.getString() + .isEmpty()) + currentEntries.add(editingIndex + 1, new ClipboardEntry(false, Components.empty())); + editingIndex += 1; + editContext.setCursorToEnd(); + if (validateTextForEntry(" ")) + return true; + currentEntries.remove(editingIndex); + editingIndex -= 1; + editContext.setCursorToEnd(); + return true; + } + editingIndex = -1; + return true; + case 259: + if (currentEntries.get(editingIndex).text.getString() + .isEmpty() && currentEntries.size() > 1) { + currentEntries.remove(editingIndex); + editingIndex = Math.max(0, editingIndex - 1); + editContext.setCursorToEnd(); + return true; + } else if (hasControlDown()) { + int prevPos = editContext.getCursorPos(); + editContext.moveByWords(-1); + if (prevPos != editContext.getCursorPos()) + editContext.removeCharsFromCursor(prevPos - editContext.getCursorPos()); + return true; + } + editContext.removeCharsFromCursor(-1); + return true; + case 261: + if (hasControlDown()) { + int prevPos = editContext.getCursorPos(); + editContext.moveByWords(1); + if (prevPos != editContext.getCursorPos()) + editContext.removeCharsFromCursor(prevPos - editContext.getCursorPos()); + return true; + } + editContext.removeCharsFromCursor(1); + return true; + case 262: + if (hasControlDown()) { + editContext.moveByWords(1, Screen.hasShiftDown()); + return true; + } + editContext.moveByChars(1, Screen.hasShiftDown()); + return true; + case 263: + if (hasControlDown()) { + editContext.moveByWords(-1, Screen.hasShiftDown()); + return true; + } + editContext.moveByChars(-1, Screen.hasShiftDown()); + return true; + case 264: + keyDown(); + return true; + case 265: + keyUp(); + return true; + case 268: + keyHome(); + return true; + case 269: + keyEnd(); + return true; + default: + return false; + } + } + } + + private void keyUp() { + changeLine(-1); + } + + private void keyDown() { + changeLine(1); + } + + private void changeLine(int pYChange) { + int i = editContext.getCursorPos(); + int j = getDisplayCache().changeLine(i, pYChange); + editContext.setCursorPos(j, Screen.hasShiftDown()); + } + + private void keyHome() { + int i = editContext.getCursorPos(); + int j = getDisplayCache().findLineStart(i); + editContext.setCursorPos(j, Screen.hasShiftDown()); + } + + private void keyEnd() { + DisplayCache cache = getDisplayCache(); + int i = editContext.getCursorPos(); + int j = cache.findLineEnd(i); + editContext.setCursorPos(j, Screen.hasShiftDown()); + } + + private void renderCursor(PoseStack pPoseStack, Pos2i pCursorPos, boolean pIsEndOfText) { + if (frameTick / 6 % 2 != 0) + return; + pCursorPos = convertLocalToScreen(pCursorPos); + if (!pIsEndOfText) { + GuiComponent.fill(pPoseStack, pCursorPos.x, pCursorPos.y - 1, pCursorPos.x + 1, pCursorPos.y + 9, + -16777216); + } else { + font.draw(pPoseStack, "_", (float) pCursorPos.x, (float) pCursorPos.y, 0); + } + } + + private void renderHighlight(Rect2i[] pSelected) { + Tesselator tesselator = Tesselator.getInstance(); + BufferBuilder bufferbuilder = tesselator.getBuilder(); + RenderSystem.setShader(GameRenderer::getPositionShader); + RenderSystem.setShaderColor(0.0F, 0.0F, 255.0F, 255.0F); + RenderSystem.disableTexture(); + RenderSystem.enableColorLogicOp(); + RenderSystem.logicOp(GlStateManager.LogicOp.OR_REVERSE); + bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION); + + for (Rect2i rect2i : pSelected) { + int i = rect2i.getX(); + int j = rect2i.getY(); + int k = i + rect2i.getWidth(); + int l = j + rect2i.getHeight(); + bufferbuilder.vertex((double) i, (double) l, 0.0D) + .endVertex(); + bufferbuilder.vertex((double) k, (double) l, 0.0D) + .endVertex(); + bufferbuilder.vertex((double) k, (double) j, 0.0D) + .endVertex(); + bufferbuilder.vertex((double) i, (double) j, 0.0D) + .endVertex(); + } + + tesselator.end(); + RenderSystem.disableColorLogicOp(); + RenderSystem.enableTexture(); + } + + private Pos2i convertScreenToLocal(Pos2i pScreenPos) { + return new Pos2i(pScreenPos.x - (width - 192) / 2 - 36 + 10, + pScreenPos.y - 32 - 24 - yOffsetOfEditingEntry() - guiTop + 14); + } + + private Pos2i convertLocalToScreen(Pos2i pLocalScreenPos) { + return new Pos2i(pLocalScreenPos.x + (width - 192) / 2 + 36 - 10, + pLocalScreenPos.y + 32 + 24 + yOffsetOfEditingEntry() + guiTop - 14); + } + + public boolean mouseClicked(double pMouseX, double pMouseY, int pButton) { + if (super.mouseClicked(pMouseX, pMouseY, pButton)) + return true; + if (pButton != 0) + return true; + + if (hoveredEntry != -1) { + if (hoveredCheck) { + editingIndex = -1; + if (hoveredEntry < currentEntries.size()) + currentEntries.get(hoveredEntry).checked ^= true; + sendIfEditingBlock(); + return true; + } + + if (hoveredEntry != editingIndex && !readonly) { + editingIndex = hoveredEntry; + if (hoveredEntry >= currentEntries.size()) { + currentEntries.add(new ClipboardEntry(false, Components.empty())); + if (!validateTextForEntry(" ")) { + currentEntries.remove(hoveredEntry); + editingIndex = -1; + return true; + } + } + clearDisplayCacheAfterChange(); + } + } + + if (editingIndex == -1) + return false; + + long i = Util.getMillis(); + DisplayCache cache = getDisplayCache(); + int j = cache.getIndexAtPosition(font, convertScreenToLocal(new Pos2i((int) pMouseX, (int) pMouseY))); + if (j >= 0) { + if (j == lastIndex && i - lastClickTime < 250L) { + if (!editContext.isSelecting()) { + selectWord(j); + } else { + editContext.selectAll(); + } + } else { + editContext.setCursorPos(j, Screen.hasShiftDown()); + } + + clearDisplayCache(); + } + + lastIndex = j; + lastClickTime = i; + return true; + } + + private void selectWord(int pIndex) { + String s = getCurrentEntryText(); + editContext.setSelectionRange(StringSplitter.getWordPosition(s, -1, pIndex, false), + StringSplitter.getWordPosition(s, 1, pIndex, false)); + } + + public boolean mouseDragged(double pMouseX, double pMouseY, int pButton, double pDragX, double pDragY) { + if (super.mouseDragged(pMouseX, pMouseY, pButton, pDragX, pDragY)) + return true; + if (pButton != 0) + return true; + if (editingIndex == -1) + return false; + + DisplayCache cache = getDisplayCache(); + int i = cache.getIndexAtPosition(font, convertScreenToLocal(new Pos2i((int) pMouseX, (int) pMouseY))); + editContext.setCursorPos(i, true); + clearDisplayCache(); + return true; + } + + private DisplayCache getDisplayCache() { + if (displayCache == null) + displayCache = rebuildDisplayCache(); + return displayCache; + } + + private void clearDisplayCache() { + displayCache = null; + } + + private void clearDisplayCacheAfterChange() { + editContext.setCursorToEnd(); + clearDisplayCache(); + } + + private DisplayCache rebuildDisplayCache() { + String s = getCurrentEntryText(); + if (s.isEmpty()) + return DisplayCache.EMPTY; + + int i = editContext.getCursorPos(); + int j = editContext.getSelectionPos(); + IntList intlist = new IntArrayList(); + List list = Lists.newArrayList(); + MutableInt mutableint = new MutableInt(); + MutableBoolean mutableboolean = new MutableBoolean(); + StringSplitter stringsplitter = font.getSplitter(); + stringsplitter.splitLines(s, 150, Style.EMPTY, true, (p_98132_, p_98133_, p_98134_) -> { + int k3 = mutableint.getAndIncrement(); + String s2 = s.substring(p_98133_, p_98134_); + mutableboolean.setValue(s2.endsWith("\n")); + String s3 = StringUtils.stripEnd(s2, " \n"); + int l3 = k3 * 9; + Pos2i pos1 = convertLocalToScreen(new Pos2i(0, l3)); + intlist.add(p_98133_); + list.add(new LineInfo(p_98132_, s3, pos1.x, pos1.y)); + }); + + int[] aint = intlist.toIntArray(); + boolean flag = i == s.length(); + Pos2i pos; + if (flag && mutableboolean.isTrue()) { + pos = new Pos2i(0, list.size() * 9); + } else { + int k = findLineFromPos(aint, i); + int l = font.width(s.substring(aint[k], i)); + pos = new Pos2i(l, k * 9); + } + + List list1 = Lists.newArrayList(); + if (i != j) { + int l2 = Math.min(i, j); + int i1 = Math.max(i, j); + int j1 = findLineFromPos(aint, l2); + int k1 = findLineFromPos(aint, i1); + if (j1 == k1) { + int l1 = j1 * 9; + int i2 = aint[j1]; + list1.add(createPartialLineSelection(s, stringsplitter, l2, i1, l1, i2)); + } else { + int i3 = j1 + 1 > aint.length ? s.length() : aint[j1 + 1]; + list1.add(createPartialLineSelection(s, stringsplitter, l2, i3, j1 * 9, aint[j1])); + + for (int j3 = j1 + 1; j3 < k1; ++j3) { + int j2 = j3 * 9; + String s1 = s.substring(aint[j3], aint[j3 + 1]); + int k2 = (int) stringsplitter.stringWidth(s1); + list1.add(createSelection(new Pos2i(0, j2), new Pos2i(k2, j2 + 9))); + } + + list1.add(createPartialLineSelection(s, stringsplitter, aint[k1], i1, k1 * 9, aint[k1])); + } + } + + return new DisplayCache(s, pos, flag, aint, list.toArray(new LineInfo[0]), list1.toArray(new Rect2i[0])); + } + + static int findLineFromPos(int[] pLineStarts, int pFind) { + int i = Arrays.binarySearch(pLineStarts, pFind); + return i < 0 ? -(i + 2) : i; + } + + private Rect2i createPartialLineSelection(String pInput, StringSplitter pSplitter, int p_98122_, int p_98123_, + int p_98124_, int p_98125_) { + String s = pInput.substring(p_98125_, p_98122_); + String s1 = pInput.substring(p_98125_, p_98123_); + Pos2i firstPos = new Pos2i((int) pSplitter.stringWidth(s), p_98124_); + Pos2i secondPos = new Pos2i((int) pSplitter.stringWidth(s1), p_98124_ + 9); + return createSelection(firstPos, secondPos); + } + + private Rect2i createSelection(Pos2i pCorner1, Pos2i pCorner2) { + Pos2i firstPos = convertLocalToScreen(pCorner1); + Pos2i secondPos = convertLocalToScreen(pCorner2); + int i = Math.min(firstPos.x, secondPos.x); + int j = Math.max(firstPos.x, secondPos.x); + int k = Math.min(firstPos.y, secondPos.y); + int l = Math.max(firstPos.y, secondPos.y); + return new Rect2i(i, k, j - i, l - k); + } + + @OnlyIn(Dist.CLIENT) + static class DisplayCache { + static final DisplayCache EMPTY = new DisplayCache("", new Pos2i(0, 0), true, new int[] { 0 }, + new LineInfo[] { new LineInfo(Style.EMPTY, "", 0, 0) }, new Rect2i[0]); + private final String fullText; + final Pos2i cursor; + final boolean cursorAtEnd; + private final int[] lineStarts; + final LineInfo[] lines; + final Rect2i[] selection; + + public DisplayCache(String pFullText, Pos2i pCursor, boolean pCursorAtEnd, int[] pLineStarts, LineInfo[] pLines, + Rect2i[] pSelection) { + fullText = pFullText; + cursor = pCursor; + cursorAtEnd = pCursorAtEnd; + lineStarts = pLineStarts; + lines = pLines; + selection = pSelection; + } + + public int getIndexAtPosition(Font pFont, Pos2i pCursorPosition) { + int i = pCursorPosition.y / 9; + if (i < 0) + return 0; + if (i >= lines.length) + return fullText.length(); + LineInfo line = lines[i]; + return lineStarts[i] + pFont.getSplitter() + .plainIndexAtWidth(line.contents, pCursorPosition.x, line.style); + } + + public int changeLine(int pXChange, int pYChange) { + int i = findLineFromPos(lineStarts, pXChange); + int j = i + pYChange; + int k; + if (0 <= j && j < lineStarts.length) { + int l = pXChange - lineStarts[i]; + int i1 = lines[j].contents.length(); + k = lineStarts[j] + Math.min(l, i1); + } else { + k = pXChange; + } + + return k; + } + + public int findLineStart(int pLine) { + int i = findLineFromPos(lineStarts, pLine); + return lineStarts[i]; + } + + public int findLineEnd(int pLine) { + int i = findLineFromPos(lineStarts, pLine); + return lineStarts[i] + lines[i].contents.length(); + } + } + + @OnlyIn(Dist.CLIENT) + static class LineInfo { + final Style style; + final String contents; + final Component asComponent; + final int x; + final int y; + + public LineInfo(Style pStyle, String pContents, int pX, int pY) { + style = pStyle; + contents = pContents; + x = pX; + y = pY; + asComponent = Components.literal(pContents) + .setStyle(pStyle); + } + } + + @OnlyIn(Dist.CLIENT) + static class Pos2i { + public final int x; + public final int y; + + Pos2i(int pX, int pY) { + x = pX; + y = pY; + } + } + +} diff --git a/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardValueSettingsHandler.java b/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardValueSettingsHandler.java new file mode 100644 index 000000000..a404c42de --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardValueSettingsHandler.java @@ -0,0 +1,214 @@ +package com.simibubi.create.content.equipment.clipboard; + +import java.util.ArrayList; +import java.util.List; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.CreateClient; +import com.simibubi.create.content.equipment.clipboard.ClipboardOverrides.ClipboardType; +import com.simibubi.create.content.trains.track.TrackBlockOutline; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.MutableComponent; +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.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.phys.shapes.VoxelShape; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.client.event.RenderHighlightEvent; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; + +@EventBusSubscriber +public class ClipboardValueSettingsHandler { + + @SubscribeEvent + @OnlyIn(Dist.CLIENT) + public static void drawCustomBlockSelection(RenderHighlightEvent.Block event) { + Minecraft mc = Minecraft.getInstance(); + BlockHitResult target = event.getTarget(); + BlockPos pos = target.getBlockPos(); + BlockState blockstate = mc.level.getBlockState(pos); + + if (mc.player == null || mc.player.isSpectator()) + return; + if (!mc.level.getWorldBorder() + .isWithinBounds(pos)) + return; + if (!AllBlocks.CLIPBOARD.isIn(mc.player.getMainHandItem())) + return; + if (!(mc.level.getBlockEntity(pos) instanceof SmartBlockEntity smartBE)) + return; + if (!smartBE.getAllBehaviours() + .stream() + .anyMatch(b -> b instanceof ClipboardCloneable cc + && cc.writeToClipboard(new CompoundTag(), target.getDirection()))) + return; + + VoxelShape shape = blockstate.getShape(mc.level, pos); + if (shape.isEmpty()) + return; + + VertexConsumer vb = event.getMultiBufferSource() + .getBuffer(RenderType.lines()); + Vec3 camPos = event.getCamera() + .getPosition(); + + PoseStack ms = event.getPoseStack(); + + ms.pushPose(); + ms.translate(pos.getX() - camPos.x, pos.getY() - camPos.y, pos.getZ() - camPos.z); + TrackBlockOutline.renderShape(shape, ms, vb, true); + event.setCanceled(true); + + ms.popPose(); + } + + @OnlyIn(Dist.CLIENT) + public static void clientTick() { + Minecraft mc = Minecraft.getInstance(); + if (!(mc.hitResult instanceof BlockHitResult target)) + return; + if (!AllBlocks.CLIPBOARD.isIn(mc.player.getMainHandItem())) + return; + BlockPos pos = target.getBlockPos(); + if (!(mc.level.getBlockEntity(pos) instanceof SmartBlockEntity smartBE)) + return; + + CompoundTag tagElement = mc.player.getMainHandItem() + .getTagElement("CopiedValues"); + + boolean canCopy = smartBE.getAllBehaviours() + .stream() + .anyMatch(b -> b instanceof ClipboardCloneable cc + && cc.writeToClipboard(new CompoundTag(), target.getDirection())) + || smartBE instanceof ClipboardCloneable ccbe + && ccbe.writeToClipboard(new CompoundTag(), target.getDirection()); + + boolean canPaste = tagElement != null && (smartBE.getAllBehaviours() + .stream() + .anyMatch(b -> b instanceof ClipboardCloneable cc && cc.readFromClipboard( + tagElement.getCompound(cc.getClipboardKey()), mc.player, target.getDirection(), true)) + || smartBE instanceof ClipboardCloneable ccbe && ccbe.readFromClipboard( + tagElement.getCompound(ccbe.getClipboardKey()), mc.player, target.getDirection(), true)); + + if (!canCopy && !canPaste) + return; + + List tip = new ArrayList<>(); + tip.add(Lang.translateDirect("clipboard.actions")); + if (canCopy) + tip.add(Lang.translateDirect("clipboard.to_copy", Components.keybind("key.use"))); + if (canPaste) + tip.add(Lang.translateDirect("clipboard.to_paste", Components.keybind("key.attack"))); + + CreateClient.VALUE_SETTINGS_HANDLER.showHoverTip(tip); + } + + @SubscribeEvent + public static void rightClickToCopy(PlayerInteractEvent.RightClickBlock event) { + interact(event, false); + } + + @SubscribeEvent + public static void leftClickToPaste(PlayerInteractEvent.LeftClickBlock event) { + interact(event, true); + } + + private static void interact(PlayerInteractEvent event, boolean paste) { + ItemStack itemStack = event.getItemStack(); + if (!AllBlocks.CLIPBOARD.isIn(itemStack)) + return; + + BlockPos pos = event.getPos(); + Level world = event.getLevel(); + Player player = event.getEntity(); + if (player != null && player.isSpectator()) + return; + if (player.isSteppingCarefully()) + return; + if (!(world.getBlockEntity(pos) instanceof SmartBlockEntity smartBE)) + return; + CompoundTag tag = itemStack.getTagElement("CopiedValues"); + if (paste && tag == null) + return; + if (!paste) + tag = new CompoundTag(); + + boolean anySuccess = false; + boolean anyValid = false; + for (BlockEntityBehaviour behaviour : smartBE.getAllBehaviours()) { + if (!(behaviour instanceof ClipboardCloneable cc)) + continue; + anyValid = true; + String clipboardKey = cc.getClipboardKey(); + if (paste) { + anySuccess |= + cc.readFromClipboard(tag.getCompound(clipboardKey), player, event.getFace(), world.isClientSide()); + continue; + } + CompoundTag compoundTag = new CompoundTag(); + boolean success = cc.writeToClipboard(compoundTag, event.getFace()); + anySuccess |= success; + if (success) + tag.put(clipboardKey, compoundTag); + } + + if (smartBE instanceof ClipboardCloneable ccbe) { + anyValid = true; + String clipboardKey = ccbe.getClipboardKey(); + if (paste) { + anySuccess |= ccbe.readFromClipboard(tag.getCompound(clipboardKey), player, event.getFace(), + world.isClientSide()); + } else { + CompoundTag compoundTag = new CompoundTag(); + boolean success = ccbe.writeToClipboard(compoundTag, event.getFace()); + anySuccess |= success; + if (success) + tag.put(clipboardKey, compoundTag); + } + } + + if (!anyValid) + return; + + event.setCanceled(true); + event.setCancellationResult(InteractionResult.SUCCESS); + + if (world.isClientSide()) + return; + if (!anySuccess) + return; + + player.displayClientMessage(Lang + .translate(paste ? "clipboard.pasted_to" : "clipboard.copied_from", world.getBlockState(pos) + .getBlock() + .getName() + .withStyle(ChatFormatting.WHITE)) + .style(ChatFormatting.GREEN) + .component(), true); + + if (!paste) { + ClipboardOverrides.switchTo(ClipboardType.WRITTEN, itemStack); + itemStack.getOrCreateTag() + .put("CopiedValues", tag); + } + } + +} diff --git a/src/main/java/com/simibubi/create/content/equipment/extendoGrip/ExtendoGripInteractionPacket.java b/src/main/java/com/simibubi/create/content/equipment/extendoGrip/ExtendoGripInteractionPacket.java new file mode 100644 index 000000000..9df32850a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/extendoGrip/ExtendoGripInteractionPacket.java @@ -0,0 +1,80 @@ +package com.simibubi.create.content.equipment.extendoGrip; + +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.common.ForgeMod; +import net.minecraftforge.network.NetworkEvent.Context; + +public class ExtendoGripInteractionPacket extends SimplePacketBase { + + private InteractionHand interactionHand; + private int target; + private Vec3 specificPoint; + + public ExtendoGripInteractionPacket(Entity target) { + this(target, null); + } + + public ExtendoGripInteractionPacket(Entity target, InteractionHand hand) { + this(target, hand, null); + } + + public ExtendoGripInteractionPacket(Entity target, InteractionHand hand, Vec3 specificPoint) { + interactionHand = hand; + this.specificPoint = specificPoint; + this.target = target.getId(); + } + + public ExtendoGripInteractionPacket(FriendlyByteBuf buffer) { + target = buffer.readInt(); + int handId = buffer.readInt(); + interactionHand = handId == -1 ? null : InteractionHand.values()[handId]; + if (buffer.readBoolean()) + specificPoint = new Vec3(buffer.readDouble(), buffer.readDouble(), buffer.readDouble()); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeInt(target); + buffer.writeInt(interactionHand == null ? -1 : interactionHand.ordinal()); + buffer.writeBoolean(specificPoint != null); + if (specificPoint != null) { + buffer.writeDouble(specificPoint.x); + buffer.writeDouble(specificPoint.y); + buffer.writeDouble(specificPoint.z); + } + } + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> { + ServerPlayer sender = context.getSender(); + if (sender == null) + return; + Entity entityByID = sender.getLevel() + .getEntity(target); + if (entityByID != null && ExtendoGripItem.isHoldingExtendoGrip(sender)) { + double d = sender.getAttribute(ForgeMod.REACH_DISTANCE.get()) + .getValue(); + if (!sender.hasLineOfSight(entityByID)) + d -= 3; + d *= d; + if (sender.distanceToSqr(entityByID) > d) + return; + if (interactionHand == null) + sender.attack(entityByID); + else if (specificPoint == null) + sender.interactOn(entityByID, interactionHand); + else + entityByID.interactAt(sender, specificPoint, interactionHand); + } + }); + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripItem.java b/src/main/java/com/simibubi/create/content/equipment/extendoGrip/ExtendoGripItem.java similarity index 94% rename from src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripItem.java rename to src/main/java/com/simibubi/create/content/equipment/extendoGrip/ExtendoGripItem.java index e711c77a3..0d1c46cb8 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripItem.java +++ b/src/main/java/com/simibubi/create/content/equipment/extendoGrip/ExtendoGripItem.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.tools; +package com.simibubi.create.content.equipment.extendoGrip; import java.util.UUID; import java.util.function.Consumer; @@ -8,12 +8,12 @@ import com.google.common.base.Suppliers; import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.Multimap; import com.simibubi.create.AllItems; -import com.simibubi.create.content.curiosities.armor.BackTankUtil; +import com.simibubi.create.AllPackets; +import com.simibubi.create.content.equipment.armor.BacktankUtil; import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.item.render.SimpleCustomRenderer; -import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; @@ -205,27 +205,27 @@ public class ExtendoGripItem extends Item { if (!AllItems.EXTENDO_GRIP.isIn(extendo)) return; final InteractionHand h = hand; - if (!BackTankUtil.canAbsorbDamage(player, maxUses())) + if (!BacktankUtil.canAbsorbDamage(player, maxUses())) extendo.hurtAndBreak(1, player, p -> p.broadcastBreakEvent(h)); } @Override public boolean isBarVisible(ItemStack stack) { - return BackTankUtil.isBarVisible(stack, maxUses()); + return BacktankUtil.isBarVisible(stack, maxUses()); } @Override public int getBarWidth(ItemStack stack) { - return BackTankUtil.getBarWidth(stack, maxUses()); + return BacktankUtil.getBarWidth(stack, maxUses()); } @Override public int getBarColor(ItemStack stack) { - return BackTankUtil.getBarColor(stack, maxUses()); + return BacktankUtil.getBarColor(stack, maxUses()); } private static int maxUses() { - return AllConfigs.SERVER.curiosities.maxExtendoGripActions.get(); + return AllConfigs.server().equipment.maxExtendoGripActions.get(); } @SubscribeEvent @@ -274,7 +274,7 @@ public class ExtendoGripItem extends Item { return; Player player = (Player) entity; if (isHoldingExtendoGrip(player)) - AllPackets.channel.sendToServer(new ExtendoGripInteractionPacket(target)); + AllPackets.getChannel().sendToServer(new ExtendoGripInteractionPacket(target)); } @SubscribeEvent @@ -286,7 +286,7 @@ public class ExtendoGripItem extends Item { return; Player player = (Player) entity; if (isHoldingExtendoGrip(player)) - AllPackets.channel.sendToServer(new ExtendoGripInteractionPacket(target, event.getHand())); + AllPackets.getChannel().sendToServer(new ExtendoGripInteractionPacket(target, event.getHand())); } @SubscribeEvent @@ -298,7 +298,7 @@ public class ExtendoGripItem extends Item { return; Player player = (Player) entity; if (isHoldingExtendoGrip(player)) - AllPackets.channel + AllPackets.getChannel() .sendToServer(new ExtendoGripInteractionPacket(target, event.getHand(), event.getLocalPos())); } diff --git a/src/main/java/com/simibubi/create/content/equipment/extendoGrip/ExtendoGripItemRenderer.java b/src/main/java/com/simibubi/create/content/equipment/extendoGrip/ExtendoGripItemRenderer.java new file mode 100644 index 000000000..e79655ef9 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/extendoGrip/ExtendoGripItemRenderer.java @@ -0,0 +1,119 @@ +package com.simibubi.create.content.equipment.extendoGrip; + +import com.jozufozu.flywheel.core.PartialModel; +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.Create; +import com.simibubi.create.foundation.item.render.CustomRenderedItemModel; +import com.simibubi.create.foundation.item.render.CustomRenderedItemModelRenderer; +import com.simibubi.create.foundation.item.render.PartialItemModelRenderer; +import com.simibubi.create.foundation.utility.AnimationTickHolder; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.block.model.ItemTransforms.TransformType; +import net.minecraft.util.Mth; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.Vec3; + +public class ExtendoGripItemRenderer extends CustomRenderedItemModelRenderer { + + protected static final PartialModel COG = new PartialModel(Create.asResource("item/extendo_grip/cog")); + protected static final PartialModel THIN_SHORT = new PartialModel(Create.asResource("item/extendo_grip/thin_short")); + protected static final PartialModel WIDE_SHORT = new PartialModel(Create.asResource("item/extendo_grip/wide_short")); + protected static final PartialModel THIN_LONG = new PartialModel(Create.asResource("item/extendo_grip/thin_long")); + protected static final PartialModel WIDE_LONG = new PartialModel(Create.asResource("item/extendo_grip/wide_long")); + + private static final Vec3 ROTATION_OFFSET = new Vec3(0, 1 / 2f, 1 / 2f); + private static final Vec3 COG_ROTATION_OFFSET = new Vec3(0, 1 / 16f, 0); + + @Override + protected void render(ItemStack stack, CustomRenderedItemModel model, PartialItemModelRenderer renderer, TransformType transformType, + PoseStack ms, MultiBufferSource buffer, int light, int overlay) { + TransformStack stacker = TransformStack.cast(ms); + float animation = 0.25f; + boolean leftHand = transformType == TransformType.FIRST_PERSON_LEFT_HAND; + boolean rightHand = transformType == TransformType.FIRST_PERSON_RIGHT_HAND; + if (leftHand || rightHand) + animation = Mth.lerp(AnimationTickHolder.getPartialTicks(), + ExtendoGripRenderHandler.lastMainHandAnimation, + ExtendoGripRenderHandler.mainHandAnimation); + + animation = animation * animation * animation; + float extensionAngle = Mth.lerp(animation, 24f, 156f); + float halfAngle = extensionAngle / 2; + float oppositeAngle = 180 - extensionAngle; + + // grip + renderer.renderSolid(model.getOriginalModel(), light); + + // bits + ms.pushPose(); + ms.translate(0, 1 / 16f, -7 / 16f); + ms.scale(1, 1, 1 + animation); + ms.pushPose(); + stacker.rotateX(-halfAngle) + .translate(ROTATION_OFFSET); + renderer.renderSolid(THIN_SHORT.get(), light); + stacker.translateBack(ROTATION_OFFSET); + + ms.translate(0, 5.5f / 16f, 0); + stacker.rotateX(-oppositeAngle) + .translate(ROTATION_OFFSET); + renderer.renderSolid(WIDE_LONG.get(), light); + stacker.translateBack(ROTATION_OFFSET); + + ms.translate(0, 11 / 16f, 0); + stacker.rotateX(oppositeAngle) + .translate(ROTATION_OFFSET); + ms.translate(0, 0.5f / 16f, 0); + renderer.renderSolid(THIN_SHORT.get(), light); + stacker.translateBack(ROTATION_OFFSET); + + ms.popPose(); + ms.pushPose(); + + stacker.rotateX(-180 + halfAngle) + .translate(ROTATION_OFFSET); + renderer.renderSolid(WIDE_SHORT.get(), light); + stacker.translateBack(ROTATION_OFFSET); + + ms.translate(0, 5.5f / 16f, 0); + stacker.rotateX(oppositeAngle) + .translate(ROTATION_OFFSET); + renderer.renderSolid(THIN_LONG.get(), light); + stacker.translateBack(ROTATION_OFFSET); + + ms.translate(0, 11 / 16f, 0); + stacker.rotateX(-oppositeAngle) + .translate(ROTATION_OFFSET); + ms.translate(0, 0.5f / 16f, 0); + renderer.renderSolid(WIDE_SHORT.get(), light); + stacker.translateBack(ROTATION_OFFSET); + + // hand + ms.translate(0, 5.5f / 16f, 0); + stacker.rotateX(180 - halfAngle) + .rotateY(180); + ms.translate(0, 0, -4 / 16f); + ms.scale(1, 1, 1 / (1 + animation)); + renderer.renderSolid((leftHand || rightHand) ? ExtendoGripRenderHandler.pose.get() + : AllPartialModels.DEPLOYER_HAND_POINTING.get(), light); + ms.popPose(); + + ms.popPose(); + + // cog + ms.pushPose(); + float angle = AnimationTickHolder.getRenderTime() * -2; + if (leftHand || rightHand) + angle += 360 * animation; + angle %= 360; + stacker.translate(COG_ROTATION_OFFSET) + .rotateZ(angle) + .translateBack(COG_ROTATION_OFFSET); + renderer.renderSolid(COG.get(), light); + ms.popPose(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripRenderHandler.java b/src/main/java/com/simibubi/create/content/equipment/extendoGrip/ExtendoGripRenderHandler.java similarity index 95% rename from src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripRenderHandler.java rename to src/main/java/com/simibubi/create/content/equipment/extendoGrip/ExtendoGripRenderHandler.java index 057b900b0..c79c8e7fe 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripRenderHandler.java +++ b/src/main/java/com/simibubi/create/content/equipment/extendoGrip/ExtendoGripRenderHandler.java @@ -1,11 +1,11 @@ -package com.simibubi.create.content.curiosities.tools; +package com.simibubi.create.content.equipment.extendoGrip; import com.jozufozu.flywheel.core.PartialModel; import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllItems; +import com.simibubi.create.AllPartialModels; import com.simibubi.create.foundation.utility.AnimationTickHolder; import net.minecraft.client.Minecraft; @@ -30,13 +30,13 @@ public class ExtendoGripRenderHandler { public static float mainHandAnimation; public static float lastMainHandAnimation; - public static PartialModel pose = AllBlockPartials.DEPLOYER_HAND_PUNCHING; + public static PartialModel pose = AllPartialModels.DEPLOYER_HAND_PUNCHING; public static void tick() { lastMainHandAnimation = mainHandAnimation; mainHandAnimation *= Mth.clamp(mainHandAnimation, 0.8f, 0.99f); - pose = AllBlockPartials.DEPLOYER_HAND_PUNCHING; + pose = AllPartialModels.DEPLOYER_HAND_PUNCHING; if (!AllItems.EXTENDO_GRIP.isIn(getRenderedOffHandStack())) return; ItemStack main = getRenderedMainHandStack(); @@ -49,7 +49,7 @@ public class ExtendoGripRenderHandler { .getModel(main, null, null, 0) .isGui3d()) return; - pose = AllBlockPartials.DEPLOYER_HAND_HOLDING; + pose = AllPartialModels.DEPLOYER_HAND_HOLDING; } @SubscribeEvent diff --git a/src/main/java/com/simibubi/create/content/contraptions/goggles/GoggleConfigScreen.java b/src/main/java/com/simibubi/create/content/equipment/goggles/GoggleConfigScreen.java similarity index 92% rename from src/main/java/com/simibubi/create/content/contraptions/goggles/GoggleConfigScreen.java rename to src/main/java/com/simibubi/create/content/equipment/goggles/GoggleConfigScreen.java index 24b6539c1..72060dc94 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/goggles/GoggleConfigScreen.java +++ b/src/main/java/com/simibubi/create/content/equipment/goggles/GoggleConfigScreen.java @@ -1,15 +1,15 @@ -package com.simibubi.create.content.contraptions.goggles; +package com.simibubi.create.content.equipment.goggles; import java.util.ArrayList; import java.util.List; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllItems; -import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.gui.AbstractSimiScreen; import com.simibubi.create.foundation.gui.element.GuiGameElement; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.ChatFormatting; import net.minecraft.network.chat.Component; @@ -57,14 +57,14 @@ public class GoggleConfigScreen extends AbstractSimiScreen { this.height = minecraft.getWindow() .getGuiScaledHeight(); - offsetX = AllConfigs.CLIENT.overlayOffsetX.get(); - offsetY = AllConfigs.CLIENT.overlayOffsetY.get(); + offsetX = AllConfigs.client().overlayOffsetX.get(); + offsetY = AllConfigs.client().overlayOffsetY.get(); } @Override public void removed() { - AllConfigs.CLIENT.overlayOffsetX.set(offsetX); - AllConfigs.CLIENT.overlayOffsetY.set(offsetY); + AllConfigs.client().overlayOffsetX.set(offsetX); + AllConfigs.client().overlayOffsetY.set(offsetY); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/goggles/GoggleOverlayRenderer.java b/src/main/java/com/simibubi/create/content/equipment/goggles/GoggleOverlayRenderer.java similarity index 81% rename from src/main/java/com/simibubi/create/content/contraptions/goggles/GoggleOverlayRenderer.java rename to src/main/java/com/simibubi/create/content/equipment/goggles/GoggleOverlayRenderer.java index 451a75532..da9504077 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/goggles/GoggleOverlayRenderer.java +++ b/src/main/java/com/simibubi/create/content/equipment/goggles/GoggleOverlayRenderer.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.goggles; +package com.simibubi.create.content.equipment.goggles; import java.util.ArrayList; import java.util.List; @@ -8,22 +8,22 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; import com.simibubi.create.CreateClient; -import com.simibubi.create.content.contraptions.components.structureMovement.IDisplayAssemblyExceptions; -import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.piston.PistonExtensionPoleBlock; -import com.simibubi.create.content.logistics.trains.entity.TrainRelocator; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.config.CClient; +import com.simibubi.create.content.contraptions.IDisplayAssemblyExceptions; +import com.simibubi.create.content.contraptions.piston.MechanicalPistonBlock; +import com.simibubi.create.content.contraptions.piston.PistonExtensionPoleBlock; +import com.simibubi.create.content.trains.entity.TrainRelocator; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBox; import com.simibubi.create.foundation.gui.RemovedGuiUtils; import com.simibubi.create.foundation.gui.Theme; import com.simibubi.create.foundation.gui.element.GuiGameElement; -import com.simibubi.create.foundation.tileEntity.behaviour.ValueBox; +import com.simibubi.create.foundation.outliner.Outline; +import com.simibubi.create.foundation.outliner.Outliner.OutlineEntry; import com.simibubi.create.foundation.utility.Color; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.outliner.Outline; -import com.simibubi.create.foundation.utility.outliner.Outliner.OutlineEntry; +import com.simibubi.create.infrastructure.config.AllConfigs; +import com.simibubi.create.infrastructure.config.CClient; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; @@ -34,6 +34,7 @@ import net.minecraft.network.chat.FormattedText; import net.minecraft.util.Mth; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.GameType; +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; @@ -74,16 +75,18 @@ public class GoggleOverlayRenderer { BlockHitResult result = (BlockHitResult) objectMouseOver; ClientLevel world = mc.level; BlockPos pos = result.getBlockPos(); - BlockEntity te = world.getBlockEntity(pos); int prevHoverTicks = hoverTicks; hoverTicks++; lastHovered = pos; + pos = proxiedOverlayPosition(world, pos); + + BlockEntity be = world.getBlockEntity(pos); boolean wearingGoggles = GogglesItem.isWearingGoggles(mc.player); - boolean hasGoggleInformation = te instanceof IHaveGoggleInformation; - boolean hasHoveringInformation = te instanceof IHaveHoveringInformation; + boolean hasGoggleInformation = be instanceof IHaveGoggleInformation; + boolean hasHoveringInformation = be instanceof IHaveHoveringInformation; boolean goggleAddedInformation = false; boolean hoverAddedInformation = false; @@ -91,22 +94,22 @@ public class GoggleOverlayRenderer { List tooltip = new ArrayList<>(); if (hasGoggleInformation && wearingGoggles) { - IHaveGoggleInformation gte = (IHaveGoggleInformation) te; + IHaveGoggleInformation gte = (IHaveGoggleInformation) be; goggleAddedInformation = gte.addToGoggleTooltip(tooltip, mc.player.isShiftKeyDown()); } if (hasHoveringInformation) { if (!tooltip.isEmpty()) tooltip.add(Components.immutableEmpty()); - IHaveHoveringInformation hte = (IHaveHoveringInformation) te; + IHaveHoveringInformation hte = (IHaveHoveringInformation) be; hoverAddedInformation = hte.addToTooltip(tooltip, mc.player.isShiftKeyDown()); if (goggleAddedInformation && !hoverAddedInformation) tooltip.remove(tooltip.size() - 1); } - if (te instanceof IDisplayAssemblyExceptions) { - boolean exceptionAdded = ((IDisplayAssemblyExceptions) te).addExceptionToTooltip(tooltip); + if (be instanceof IDisplayAssemblyExceptions) { + boolean exceptionAdded = ((IDisplayAssemblyExceptions) be).addExceptionToTooltip(tooltip); if (exceptionAdded) { hasHoveringInformation = true; hoverAddedInformation = true; @@ -171,7 +174,7 @@ public class GoggleOverlayRenderer { tooltipHeight += (tooltip.size() - 1) * 10; } - CClient cfg = AllConfigs.CLIENT; + CClient cfg = AllConfigs.client(); int posX = width / 2 + cfg.overlayOffsetX.get(); int posY = height / 2 + cfg.overlayOffsetY.get(); @@ -206,5 +209,12 @@ public class GoggleOverlayRenderer { .render(poseStack); poseStack.popPose(); } + + public static BlockPos proxiedOverlayPosition(Level level, BlockPos pos) { + BlockState targetedState = level.getBlockState(pos); + if (targetedState.getBlock() instanceof IProxyHoveringInformation proxy) + return proxy.getInformationSource(level, pos, targetedState); + return pos; + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/goggles/GogglesItem.java b/src/main/java/com/simibubi/create/content/equipment/goggles/GogglesItem.java similarity index 97% rename from src/main/java/com/simibubi/create/content/contraptions/goggles/GogglesItem.java rename to src/main/java/com/simibubi/create/content/equipment/goggles/GogglesItem.java index 19063c4d6..22d59c6bd 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/goggles/GogglesItem.java +++ b/src/main/java/com/simibubi/create/content/equipment/goggles/GogglesItem.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.goggles; +package com.simibubi.create.content.equipment.goggles; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/com/simibubi/create/content/contraptions/goggles/GogglesModel.java b/src/main/java/com/simibubi/create/content/equipment/goggles/GogglesModel.java similarity index 82% rename from src/main/java/com/simibubi/create/content/contraptions/goggles/GogglesModel.java rename to src/main/java/com/simibubi/create/content/equipment/goggles/GogglesModel.java index d683b65dd..0dec2de7b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/goggles/GogglesModel.java +++ b/src/main/java/com/simibubi/create/content/equipment/goggles/GogglesModel.java @@ -1,7 +1,7 @@ -package com.simibubi.create.content.contraptions.goggles; +package com.simibubi.create.content.equipment.goggles; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.AllPartialModels; import net.minecraft.client.renderer.block.model.ItemTransforms.TransformType; import net.minecraft.client.resources.model.BakedModel; @@ -16,7 +16,7 @@ public class GogglesModel extends BakedModelWrapper { @Override public BakedModel applyTransform(TransformType cameraTransformType, PoseStack mat, boolean leftHanded) { if (cameraTransformType == TransformType.HEAD) - return AllBlockPartials.GOGGLES.get() + return AllPartialModels.GOGGLES.get() .applyTransform(cameraTransformType, mat, leftHanded); return super.applyTransform(cameraTransformType, mat, leftHanded); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/goggles/IHaveGoggleInformation.java b/src/main/java/com/simibubi/create/content/equipment/goggles/IHaveGoggleInformation.java similarity index 91% rename from src/main/java/com/simibubi/create/content/contraptions/goggles/IHaveGoggleInformation.java rename to src/main/java/com/simibubi/create/content/equipment/goggles/IHaveGoggleInformation.java index 308db240c..97085d1ed 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/goggles/IHaveGoggleInformation.java +++ b/src/main/java/com/simibubi/create/content/equipment/goggles/IHaveGoggleInformation.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.goggles; +package com.simibubi.create.content.equipment.goggles; import java.util.List; import java.util.Optional; @@ -14,7 +14,7 @@ import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler; /* -* Implement this Interface in the TileEntity class that wants to add info to the screen +* Implement this Interface in the BlockEntity class that wants to add info to the screen * */ public interface IHaveGoggleInformation { @@ -30,7 +30,7 @@ public interface IHaveGoggleInformation { Component componentSpacing = Components.literal(spacing); /** - * this method will be called when looking at a TileEntity that implemented this + * this method will be called when looking at a BlockEntity that implemented this * interface * * @return {@code true} if the tooltip creation was successful and should be diff --git a/src/main/java/com/simibubi/create/content/equipment/goggles/IHaveHoveringInformation.java b/src/main/java/com/simibubi/create/content/equipment/goggles/IHaveHoveringInformation.java new file mode 100644 index 000000000..ea97e262a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/goggles/IHaveHoveringInformation.java @@ -0,0 +1,16 @@ +package com.simibubi.create.content.equipment.goggles; + +import java.util.List; + +import net.minecraft.network.chat.Component; + +/* +* Implement this Interface in the BlockEntity class that wants to add info to the screen +* */ +public interface IHaveHoveringInformation { + + default boolean addToTooltip(List tooltip, boolean isPlayerSneaking) { + return false; + } + +} diff --git a/src/main/java/com/simibubi/create/content/equipment/goggles/IProxyHoveringInformation.java b/src/main/java/com/simibubi/create/content/equipment/goggles/IProxyHoveringInformation.java new file mode 100644 index 000000000..dad2d3051 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/goggles/IProxyHoveringInformation.java @@ -0,0 +1,11 @@ +package com.simibubi.create.content.equipment.goggles; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; + +public interface IProxyHoveringInformation { + + public BlockPos getInformationSource(Level level, BlockPos pos, BlockState state); + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/weapons/BuiltinPotatoProjectileTypes.java b/src/main/java/com/simibubi/create/content/equipment/potatoCannon/BuiltinPotatoProjectileTypes.java similarity index 99% rename from src/main/java/com/simibubi/create/content/curiosities/weapons/BuiltinPotatoProjectileTypes.java rename to src/main/java/com/simibubi/create/content/equipment/potatoCannon/BuiltinPotatoProjectileTypes.java index fbe0f5396..4bebe12f3 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/weapons/BuiltinPotatoProjectileTypes.java +++ b/src/main/java/com/simibubi/create/content/equipment/potatoCannon/BuiltinPotatoProjectileTypes.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.weapons; +package com.simibubi.create.content.equipment.potatoCannon; import java.util.UUID; import java.util.function.BiPredicate; diff --git a/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonItem.java b/src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoCannonItem.java similarity index 94% rename from src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonItem.java rename to src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoCannonItem.java index 869ac9ab6..1e56bfae6 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonItem.java +++ b/src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoCannonItem.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.weapons; +package com.simibubi.create.content.equipment.potatoCannon; import java.util.List; import java.util.Optional; @@ -11,15 +11,15 @@ import com.simibubi.create.AllEnchantments; import com.simibubi.create.AllEntityTypes; import com.simibubi.create.Create; import com.simibubi.create.CreateClient; -import com.simibubi.create.content.curiosities.armor.BackTankUtil; -import com.simibubi.create.content.curiosities.zapper.ShootableGadgetItemMethods; -import com.simibubi.create.foundation.config.AllConfigs; +import com.simibubi.create.content.equipment.armor.BacktankUtil; +import com.simibubi.create.content.equipment.zapper.ShootableGadgetItemMethods; import com.simibubi.create.foundation.item.CustomArmPoseItem; import com.simibubi.create.foundation.item.render.SimpleCustomRenderer; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; @@ -86,21 +86,21 @@ public class PotatoCannonItem extends ProjectileWeaponItem implements CustomArmP @Override public boolean isBarVisible(ItemStack stack) { - return BackTankUtil.isBarVisible(stack, maxUses()); + return BacktankUtil.isBarVisible(stack, maxUses()); } @Override public int getBarWidth(ItemStack stack) { - return BackTankUtil.getBarWidth(stack, maxUses()); + return BacktankUtil.getBarWidth(stack, maxUses()); } @Override public int getBarColor(ItemStack stack) { - return BackTankUtil.getBarColor(stack, maxUses()); + return BacktankUtil.getBarColor(stack, maxUses()); } private int maxUses() { - return AllConfigs.SERVER.curiosities.maxPotatoCannonShots.get(); + return AllConfigs.server().equipment.maxPotatoCannonShots.get(); } public boolean isCannon(ItemStack stack) { @@ -168,7 +168,7 @@ public class PotatoCannonItem extends ProjectileWeaponItem implements CustomArmP player.getInventory().removeItem(itemStack); } - if (!BackTankUtil.canAbsorbDamage(player, maxUses())) + if (!BacktankUtil.canAbsorbDamage(player, maxUses())) stack.hurtAndBreak(1, player, p -> p.broadcastBreakEvent(hand)); Integer cooldown = diff --git a/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonItemRenderer.java b/src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoCannonItemRenderer.java similarity index 82% rename from src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonItemRenderer.java rename to src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoCannonItemRenderer.java index 242d920bd..184402aba 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoCannonItemRenderer.java +++ b/src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoCannonItemRenderer.java @@ -1,9 +1,12 @@ -package com.simibubi.create.content.curiosities.weapons; +package com.simibubi.create.content.equipment.potatoCannon; +import com.jozufozu.flywheel.core.PartialModel; import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Axis; +import com.simibubi.create.Create; import com.simibubi.create.CreateClient; +import com.simibubi.create.foundation.item.render.CustomRenderedItemModel; import com.simibubi.create.foundation.item.render.CustomRenderedItemModelRenderer; import com.simibubi.create.foundation.item.render.PartialItemModelRenderer; import com.simibubi.create.foundation.utility.AnimationTickHolder; @@ -14,15 +17,16 @@ import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.block.model.ItemTransforms.TransformType; import net.minecraft.client.renderer.entity.ItemRenderer; import net.minecraft.client.renderer.texture.OverlayTexture; -import net.minecraft.client.resources.model.BakedModel; import net.minecraft.util.Mth; import net.minecraft.world.entity.HumanoidArm; import net.minecraft.world.item.ItemStack; -public class PotatoCannonItemRenderer extends CustomRenderedItemModelRenderer { +public class PotatoCannonItemRenderer extends CustomRenderedItemModelRenderer { + + protected static final PartialModel COG = new PartialModel(Create.asResource("item/potato_cannon/cog")); @Override - protected void render(ItemStack stack, PotatoCannonModel model, PartialItemModelRenderer renderer, + protected void render(ItemStack stack, CustomRenderedItemModel model, PartialItemModelRenderer renderer, TransformType transformType, PoseStack ms, MultiBufferSource buffer, int light, int overlay) { ItemRenderer itemRenderer = Minecraft.getInstance() .getItemRenderer(); @@ -46,7 +50,7 @@ public class PotatoCannonItemRenderer extends CustomRenderedItemModelRenderer player), new SyncPacket()); + AllPackets.getChannel().send(PacketDistributor.PLAYER.with(() -> player), new SyncPacket()); } public static void syncToAll() { - AllPackets.channel.send(PacketDistributor.ALL.noArg(), new SyncPacket()); + AllPackets.getChannel().send(PacketDistributor.ALL.noArg(), new SyncPacket()); } public static class ReloadListener extends SimpleJsonResourceReloadListener { @@ -148,11 +148,11 @@ public class PotatoProjectileTypeManager { } @Override - public void handle(Supplier context) { - context.get().enqueueWork(() -> { + public boolean handle(Context context) { + context.enqueueWork(() -> { fromBuffer(buffer); }); - context.get().setPacketHandled(true); + return true; } } diff --git a/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoRecoveryEnchantment.java b/src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoRecoveryEnchantment.java similarity index 91% rename from src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoRecoveryEnchantment.java rename to src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoRecoveryEnchantment.java index 2f8a2f063..47e767fff 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/weapons/PotatoRecoveryEnchantment.java +++ b/src/main/java/com/simibubi/create/content/equipment/potatoCannon/PotatoRecoveryEnchantment.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.weapons; +package com.simibubi.create.content.equipment.potatoCannon; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.item.ItemStack; diff --git a/src/main/java/com/simibubi/create/content/curiosities/tools/SandPaperItem.java b/src/main/java/com/simibubi/create/content/equipment/sandPaper/SandPaperItem.java similarity index 99% rename from src/main/java/com/simibubi/create/content/curiosities/tools/SandPaperItem.java rename to src/main/java/com/simibubi/create/content/equipment/sandPaper/SandPaperItem.java index 3e007d31f..df54f3b29 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/tools/SandPaperItem.java +++ b/src/main/java/com/simibubi/create/content/equipment/sandPaper/SandPaperItem.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.tools; +package com.simibubi.create.content.equipment.sandPaper; import java.util.function.Consumer; diff --git a/src/main/java/com/simibubi/create/content/curiosities/tools/SandPaperItemRenderer.java b/src/main/java/com/simibubi/create/content/equipment/sandPaper/SandPaperItemRenderer.java similarity index 80% rename from src/main/java/com/simibubi/create/content/curiosities/tools/SandPaperItemRenderer.java rename to src/main/java/com/simibubi/create/content/equipment/sandPaper/SandPaperItemRenderer.java index 842826977..175992b8a 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/tools/SandPaperItemRenderer.java +++ b/src/main/java/com/simibubi/create/content/equipment/sandPaper/SandPaperItemRenderer.java @@ -1,10 +1,8 @@ -package com.simibubi.create.content.curiosities.tools; - -import org.joml.Vector3f; +package com.simibubi.create.content.equipment.sandPaper; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Axis; -import com.simibubi.create.foundation.item.render.CreateCustomRenderedItemModel; +import com.simibubi.create.foundation.item.render.CustomRenderedItemModel; import com.simibubi.create.foundation.item.render.CustomRenderedItemModelRenderer; import com.simibubi.create.foundation.item.render.PartialItemModelRenderer; import com.simibubi.create.foundation.utility.AnimationTickHolder; @@ -14,15 +12,14 @@ import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.block.model.ItemTransforms.TransformType; import net.minecraft.client.renderer.entity.ItemRenderer; -import net.minecraft.client.resources.model.BakedModel; import net.minecraft.nbt.CompoundTag; import net.minecraft.util.Mth; import net.minecraft.world.item.ItemStack; -public class SandPaperItemRenderer extends CustomRenderedItemModelRenderer { +public class SandPaperItemRenderer extends CustomRenderedItemModelRenderer { @Override - protected void render(ItemStack stack, SandPaperModel model, PartialItemModelRenderer renderer, + protected void render(ItemStack stack, CustomRenderedItemModel model, PartialItemModelRenderer renderer, TransformType transformType, PoseStack ms, MultiBufferSource buffer, int light, int overlay) { ItemRenderer itemRenderer = Minecraft.getInstance().getItemRenderer(); LocalPlayer player = Minecraft.getInstance().player; @@ -81,17 +78,4 @@ public class SandPaperItemRenderer extends CustomRenderedItemModelRenderer context) { - context.get().enqueueWork(() -> { - ServerPlayer player = context.get().getSender(); + public boolean handle(Context context) { + context.enqueueWork(() -> { + ServerPlayer player = context.getSender(); if (player == null) { return; } @@ -44,7 +42,7 @@ public class ConfigureSymmetryWandPacket extends SimplePacketBase { SymmetryWandItem.configureSettings(stack, mirror); } }); - context.get().setPacketHandled(true); + return true; } } diff --git a/src/main/java/com/simibubi/create/content/curiosities/symmetry/SymmetryEffectPacket.java b/src/main/java/com/simibubi/create/content/equipment/symmetryWand/SymmetryEffectPacket.java similarity index 83% rename from src/main/java/com/simibubi/create/content/curiosities/symmetry/SymmetryEffectPacket.java rename to src/main/java/com/simibubi/create/content/equipment/symmetryWand/SymmetryEffectPacket.java index 9ddd7f21c..c7572c4cb 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/symmetry/SymmetryEffectPacket.java +++ b/src/main/java/com/simibubi/create/content/equipment/symmetryWand/SymmetryEffectPacket.java @@ -1,8 +1,7 @@ -package com.simibubi.create.content.curiosities.symmetry; +package com.simibubi.create.content.equipment.symmetryWand; import java.util.ArrayList; import java.util.List; -import java.util.function.Supplier; import com.simibubi.create.foundation.networking.SimplePacketBase; @@ -43,14 +42,14 @@ public class SymmetryEffectPacket extends SimplePacketBase { } @Override - public void handle(Supplier ctx) { - ctx.get().enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { + public boolean handle(Context context) { + context.enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { if (Minecraft.getInstance().player.position().distanceTo(Vec3.atLowerCornerOf(mirror)) > 100) return; for (BlockPos to : positions) SymmetryHandler.drawEffect(mirror, to); })); - ctx.get().setPacketHandled(true); + return true; } } diff --git a/src/main/java/com/simibubi/create/content/curiosities/symmetry/SymmetryHandler.java b/src/main/java/com/simibubi/create/content/equipment/symmetryWand/SymmetryHandler.java similarity index 95% rename from src/main/java/com/simibubi/create/content/curiosities/symmetry/SymmetryHandler.java rename to src/main/java/com/simibubi/create/content/equipment/symmetryWand/SymmetryHandler.java index 7d274573b..a2e8c7e64 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/symmetry/SymmetryHandler.java +++ b/src/main/java/com/simibubi/create/content/equipment/symmetryWand/SymmetryHandler.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.symmetry; +package com.simibubi.create.content.equipment.symmetryWand; import java.util.Random; @@ -7,8 +7,8 @@ import org.joml.Vector3f; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import com.simibubi.create.AllItems; -import com.simibubi.create.content.curiosities.symmetry.mirror.EmptyMirror; -import com.simibubi.create.content.curiosities.symmetry.mirror.SymmetryMirror; +import com.simibubi.create.content.equipment.symmetryWand.mirror.EmptyMirror; +import com.simibubi.create.content.equipment.symmetryWand.mirror.SymmetryMirror; import com.simibubi.create.foundation.utility.AnimationTickHolder; import net.minecraft.client.Camera; @@ -113,8 +113,7 @@ public class SymmetryHandler { PoseStack ms = event.getPoseStack(); ms.pushPose(); - ms.translate(-view.x(), -view.y(), -view.z()); - ms.translate(pos.getX(), pos.getY(), pos.getZ()); + ms.translate(pos.getX() - view.x(), pos.getY() - view.y(), pos.getZ() - view.z()); ms.translate(0, yShift + .2f, 0); mirror.applyModelTransform(ms); BakedModel model = mirror.getModel() diff --git a/src/main/java/com/simibubi/create/content/curiosities/symmetry/SymmetryWandItem.java b/src/main/java/com/simibubi/create/content/equipment/symmetryWand/SymmetryWandItem.java similarity index 89% rename from src/main/java/com/simibubi/create/content/curiosities/symmetry/SymmetryWandItem.java rename to src/main/java/com/simibubi/create/content/equipment/symmetryWand/SymmetryWandItem.java index ad0a9904d..ac201192e 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/symmetry/SymmetryWandItem.java +++ b/src/main/java/com/simibubi/create/content/equipment/symmetryWand/SymmetryWandItem.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.symmetry; +package com.simibubi.create.content.equipment.symmetryWand; import java.util.ArrayList; import java.util.HashMap; @@ -9,18 +9,17 @@ import java.util.function.Consumer; import javax.annotation.Nonnull; import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerBlock; -import com.simibubi.create.content.curiosities.symmetry.client.SymmetryWandItemRenderer; -import com.simibubi.create.content.curiosities.symmetry.mirror.CrossPlaneMirror; -import com.simibubi.create.content.curiosities.symmetry.mirror.EmptyMirror; -import com.simibubi.create.content.curiosities.symmetry.mirror.PlaneMirror; -import com.simibubi.create.content.curiosities.symmetry.mirror.SymmetryMirror; -import com.simibubi.create.foundation.config.AllConfigs; +import com.simibubi.create.AllPackets; +import com.simibubi.create.content.contraptions.mounted.CartAssemblerBlock; +import com.simibubi.create.content.equipment.symmetryWand.mirror.CrossPlaneMirror; +import com.simibubi.create.content.equipment.symmetryWand.mirror.EmptyMirror; +import com.simibubi.create.content.equipment.symmetryWand.mirror.PlaneMirror; +import com.simibubi.create.content.equipment.symmetryWand.mirror.SymmetryMirror; import com.simibubi.create.foundation.gui.ScreenOpener; import com.simibubi.create.foundation.item.render.SimpleCustomRenderer; -import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.utility.BlockHelper; import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -204,7 +203,7 @@ public class SymmetryWandItem extends Item { .getCompound(SYMMETRY)); Vec3 mirrorPos = symmetry.getPosition(); - if (mirrorPos.distanceTo(Vec3.atLowerCornerOf(pos)) > AllConfigs.SERVER.curiosities.maxSymmetryWandRange.get()) + if (mirrorPos.distanceTo(Vec3.atLowerCornerOf(pos)) > AllConfigs.server().equipment.maxSymmetryWandRange.get()) return; if (!player.isCreative() && isHoldingBlock(player, block) && BlockHelper.findAndRemoveInInventory(block, player, 1) == 0) @@ -267,7 +266,7 @@ public class SymmetryWandItem extends Item { } } - AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY_AND_SELF.with(() -> player), + AllPackets.getChannel().send(PacketDistributor.TRACKING_ENTITY_AND_SELF.with(() -> player), new SymmetryEffectPacket(to, targets)); } @@ -292,7 +291,7 @@ public class SymmetryWandItem extends Item { .getCompound(SYMMETRY)); Vec3 mirrorPos = symmetry.getPosition(); - if (mirrorPos.distanceTo(Vec3.atLowerCornerOf(pos)) > AllConfigs.SERVER.curiosities.maxSymmetryWandRange.get()) + if (mirrorPos.distanceTo(Vec3.atLowerCornerOf(pos)) > AllConfigs.server().equipment.maxSymmetryWandRange.get()) return; symmetry.process(blockSet); @@ -319,13 +318,13 @@ public class SymmetryWandItem extends Item { .isEmpty()) player.getMainHandItem() .mineBlock(world, blockstate, position, player); - BlockEntity tileentity = blockstate.hasBlockEntity() ? world.getBlockEntity(position) : null; - Block.dropResources(blockstate, world, pos, tileentity, player, player.getMainHandItem()); // Add fortune, silk touch and other loot modifiers + BlockEntity blockEntity = blockstate.hasBlockEntity() ? world.getBlockEntity(position) : null; + Block.dropResources(blockstate, world, pos, blockEntity, player, player.getMainHandItem()); // Add fortune, silk touch and other loot modifiers } } } - AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY_AND_SELF.with(() -> player), + AllPackets.getChannel().send(PacketDistributor.TRACKING_ENTITY_AND_SELF.with(() -> player), new SymmetryEffectPacket(to, targets)); } diff --git a/src/main/java/com/simibubi/create/content/equipment/symmetryWand/SymmetryWandItemRenderer.java b/src/main/java/com/simibubi/create/content/equipment/symmetryWand/SymmetryWandItemRenderer.java new file mode 100644 index 000000000..af0d648d7 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/symmetryWand/SymmetryWandItemRenderer.java @@ -0,0 +1,43 @@ +package com.simibubi.create.content.equipment.symmetryWand; + +import com.jozufozu.flywheel.core.PartialModel; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Axis; +import com.simibubi.create.Create; +import com.simibubi.create.foundation.item.render.CustomRenderedItemModel; +import com.simibubi.create.foundation.item.render.CustomRenderedItemModelRenderer; +import com.simibubi.create.foundation.item.render.PartialItemModelRenderer; +import com.simibubi.create.foundation.utility.AnimationTickHolder; + +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.block.model.ItemTransforms; +import net.minecraft.util.Mth; +import net.minecraft.world.item.ItemStack; + +public class SymmetryWandItemRenderer extends CustomRenderedItemModelRenderer { + + protected static final PartialModel BITS = new PartialModel(Create.asResource("item/wand_of_symmetry/bits")); + protected static final PartialModel CORE = new PartialModel(Create.asResource("item/wand_of_symmetry/core")); + protected static final PartialModel CORE_GLOW = new PartialModel(Create.asResource("item/wand_of_symmetry/core_glow")); + + @Override + protected void render(ItemStack stack, CustomRenderedItemModel model, PartialItemModelRenderer renderer, ItemTransforms.TransformType transformType, + PoseStack ms, MultiBufferSource buffer, int light, int overlay) { + float worldTime = AnimationTickHolder.getRenderTime() / 20; + int maxLight = LightTexture.FULL_BRIGHT; + + renderer.render(model.getOriginalModel(), light); + renderer.renderSolidGlowing(CORE.get(), maxLight); + renderer.renderGlowing(CORE_GLOW.get(), maxLight); + + float floating = Mth.sin(worldTime) * .05f; + float angle = worldTime * -10 % 360; + + ms.translate(0, floating, 0); + ms.mulPose(Axis.YP.rotationDegrees(angle)); + + renderer.renderGlowing(BITS.get(), maxLight); + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/symmetry/SymmetryWandScreen.java b/src/main/java/com/simibubi/create/content/equipment/symmetryWand/SymmetryWandScreen.java similarity index 86% rename from src/main/java/com/simibubi/create/content/curiosities/symmetry/SymmetryWandScreen.java rename to src/main/java/com/simibubi/create/content/equipment/symmetryWand/SymmetryWandScreen.java index 01849ecd5..9e99f16e9 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/symmetry/SymmetryWandScreen.java +++ b/src/main/java/com/simibubi/create/content/equipment/symmetryWand/SymmetryWandScreen.java @@ -1,14 +1,15 @@ -package com.simibubi.create.content.curiosities.symmetry; +package com.simibubi.create.content.equipment.symmetryWand; import org.joml.Vector3f; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Axis; -import com.simibubi.create.content.curiosities.symmetry.mirror.CrossPlaneMirror; -import com.simibubi.create.content.curiosities.symmetry.mirror.EmptyMirror; -import com.simibubi.create.content.curiosities.symmetry.mirror.PlaneMirror; -import com.simibubi.create.content.curiosities.symmetry.mirror.SymmetryMirror; -import com.simibubi.create.content.curiosities.symmetry.mirror.TriplePlaneMirror; +import com.simibubi.create.AllPackets; +import com.simibubi.create.content.equipment.symmetryWand.mirror.CrossPlaneMirror; +import com.simibubi.create.content.equipment.symmetryWand.mirror.EmptyMirror; +import com.simibubi.create.content.equipment.symmetryWand.mirror.PlaneMirror; +import com.simibubi.create.content.equipment.symmetryWand.mirror.SymmetryMirror; +import com.simibubi.create.content.equipment.symmetryWand.mirror.TriplePlaneMirror; import com.simibubi.create.foundation.gui.AbstractSimiScreen; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; @@ -17,7 +18,6 @@ import com.simibubi.create.foundation.gui.widget.IconButton; import com.simibubi.create.foundation.gui.widget.Label; import com.simibubi.create.foundation.gui.widget.ScrollInput; import com.simibubi.create.foundation.gui.widget.SelectionScrollInput; -import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Lang; @@ -124,7 +124,7 @@ public class SymmetryWandScreen extends AbstractSimiScreen { int y = guiTop; background.render(ms, x, y, this); - font.draw(ms, wand.getHoverName(), x + 11, y + 4, 0x6B3802); + font.draw(ms, wand.getHoverName(), x + 11, y + 4, 0x592424); renderBlock(ms, x, y); GuiGameElement.of(wand) @@ -150,7 +150,7 @@ public class SymmetryWandScreen extends AbstractSimiScreen { @Override public void removed() { SymmetryWandItem.configureSettings(wand, currentElement); - AllPackets.channel.sendToServer(new ConfigureSymmetryWandPacket(hand, currentElement)); + AllPackets.getChannel().sendToServer(new ConfigureSymmetryWandPacket(hand, currentElement)); } } diff --git a/src/main/java/com/simibubi/create/content/curiosities/symmetry/mirror/CrossPlaneMirror.java b/src/main/java/com/simibubi/create/content/equipment/symmetryWand/mirror/CrossPlaneMirror.java similarity index 94% rename from src/main/java/com/simibubi/create/content/curiosities/symmetry/mirror/CrossPlaneMirror.java rename to src/main/java/com/simibubi/create/content/equipment/symmetryWand/mirror/CrossPlaneMirror.java index e1342bf4b..9a9172cca 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/symmetry/mirror/CrossPlaneMirror.java +++ b/src/main/java/com/simibubi/create/content/equipment/symmetryWand/mirror/CrossPlaneMirror.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.symmetry.mirror; +package com.simibubi.create.content.equipment.symmetryWand.mirror; import java.util.HashMap; import java.util.List; @@ -8,7 +8,7 @@ import com.google.common.collect.ImmutableList; import com.jozufozu.flywheel.core.PartialModel; import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.AllPartialModels; import com.simibubi.create.foundation.utility.Lang; import net.minecraft.core.BlockPos; @@ -91,7 +91,7 @@ public class CrossPlaneMirror extends SymmetryMirror { @Override @OnlyIn(Dist.CLIENT) public PartialModel getModel() { - return AllBlockPartials.SYMMETRY_CROSSPLANE; + return AllPartialModels.SYMMETRY_CROSSPLANE; } @Override diff --git a/src/main/java/com/simibubi/create/content/curiosities/symmetry/mirror/EmptyMirror.java b/src/main/java/com/simibubi/create/content/equipment/symmetryWand/mirror/EmptyMirror.java similarity index 95% rename from src/main/java/com/simibubi/create/content/curiosities/symmetry/mirror/EmptyMirror.java rename to src/main/java/com/simibubi/create/content/equipment/symmetryWand/mirror/EmptyMirror.java index 56103a1ee..cf30a04fd 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/symmetry/mirror/EmptyMirror.java +++ b/src/main/java/com/simibubi/create/content/equipment/symmetryWand/mirror/EmptyMirror.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.symmetry.mirror; +package com.simibubi.create.content.equipment.symmetryWand.mirror; import java.util.HashMap; import java.util.List; diff --git a/src/main/java/com/simibubi/create/content/curiosities/symmetry/mirror/PlaneMirror.java b/src/main/java/com/simibubi/create/content/equipment/symmetryWand/mirror/PlaneMirror.java similarity index 93% rename from src/main/java/com/simibubi/create/content/curiosities/symmetry/mirror/PlaneMirror.java rename to src/main/java/com/simibubi/create/content/equipment/symmetryWand/mirror/PlaneMirror.java index 06b6a0ceb..b68cda9e7 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/symmetry/mirror/PlaneMirror.java +++ b/src/main/java/com/simibubi/create/content/equipment/symmetryWand/mirror/PlaneMirror.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.symmetry.mirror; +package com.simibubi.create.content.equipment.symmetryWand.mirror; import java.util.HashMap; import java.util.List; @@ -8,7 +8,7 @@ import com.google.common.collect.ImmutableList; import com.jozufozu.flywheel.core.PartialModel; import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.AllPartialModels; import com.simibubi.create.foundation.utility.Lang; import net.minecraft.core.BlockPos; @@ -87,7 +87,7 @@ public class PlaneMirror extends SymmetryMirror { @Override @OnlyIn(Dist.CLIENT) public PartialModel getModel() { - return AllBlockPartials.SYMMETRY_PLANE; + return AllPartialModels.SYMMETRY_PLANE; } @Override diff --git a/src/main/java/com/simibubi/create/content/curiosities/symmetry/mirror/SymmetryMirror.java b/src/main/java/com/simibubi/create/content/equipment/symmetryWand/mirror/SymmetryMirror.java similarity index 98% rename from src/main/java/com/simibubi/create/content/curiosities/symmetry/mirror/SymmetryMirror.java rename to src/main/java/com/simibubi/create/content/equipment/symmetryWand/mirror/SymmetryMirror.java index 0ad3e979e..a61430c79 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/symmetry/mirror/SymmetryMirror.java +++ b/src/main/java/com/simibubi/create/content/equipment/symmetryWand/mirror/SymmetryMirror.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.symmetry.mirror; +package com.simibubi.create.content.equipment.symmetryWand.mirror; import java.util.HashMap; import java.util.List; diff --git a/src/main/java/com/simibubi/create/content/curiosities/symmetry/mirror/TriplePlaneMirror.java b/src/main/java/com/simibubi/create/content/equipment/symmetryWand/mirror/TriplePlaneMirror.java similarity index 91% rename from src/main/java/com/simibubi/create/content/curiosities/symmetry/mirror/TriplePlaneMirror.java rename to src/main/java/com/simibubi/create/content/equipment/symmetryWand/mirror/TriplePlaneMirror.java index a0d9a9a61..73ea306f4 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/symmetry/mirror/TriplePlaneMirror.java +++ b/src/main/java/com/simibubi/create/content/equipment/symmetryWand/mirror/TriplePlaneMirror.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.symmetry.mirror; +package com.simibubi.create.content.equipment.symmetryWand.mirror; import java.util.HashMap; import java.util.List; @@ -6,7 +6,7 @@ import java.util.Map; import com.google.common.collect.ImmutableList; import com.jozufozu.flywheel.core.PartialModel; -import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.AllPartialModels; import com.simibubi.create.foundation.utility.Lang; import net.minecraft.core.BlockPos; @@ -48,7 +48,7 @@ public class TriplePlaneMirror extends SymmetryMirror { @Override @OnlyIn(Dist.CLIENT) public PartialModel getModel() { - return AllBlockPartials.SYMMETRY_TRIPLEPLANE; + return AllPartialModels.SYMMETRY_TRIPLEPLANE; } @Override diff --git a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ItemReturnInvWrapper.java b/src/main/java/com/simibubi/create/content/equipment/toolbox/ItemReturnInvWrapper.java similarity index 90% rename from src/main/java/com/simibubi/create/content/curiosities/toolbox/ItemReturnInvWrapper.java rename to src/main/java/com/simibubi/create/content/equipment/toolbox/ItemReturnInvWrapper.java index 24346ff20..24bcc11fd 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ItemReturnInvWrapper.java +++ b/src/main/java/com/simibubi/create/content/equipment/toolbox/ItemReturnInvWrapper.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.toolbox; +package com.simibubi.create.content.equipment.toolbox; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.item.ItemStack; diff --git a/src/main/java/com/simibubi/create/content/curiosities/toolbox/RadialToolboxMenu.java b/src/main/java/com/simibubi/create/content/equipment/toolbox/RadialToolboxMenu.java similarity index 90% rename from src/main/java/com/simibubi/create/content/curiosities/toolbox/RadialToolboxMenu.java rename to src/main/java/com/simibubi/create/content/equipment/toolbox/RadialToolboxMenu.java index 0bf111bec..196145444 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/toolbox/RadialToolboxMenu.java +++ b/src/main/java/com/simibubi/create/content/equipment/toolbox/RadialToolboxMenu.java @@ -1,6 +1,6 @@ -package com.simibubi.create.content.curiosities.toolbox; +package com.simibubi.create.content.equipment.toolbox; -import static com.simibubi.create.content.curiosities.toolbox.ToolboxInventory.STACKS_PER_COMPARTMENT; +import static com.simibubi.create.content.equipment.toolbox.ToolboxInventory.STACKS_PER_COMPARTMENT; import java.util.List; @@ -13,11 +13,11 @@ import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllKeys; +import com.simibubi.create.AllPackets; import com.simibubi.create.foundation.gui.AbstractSimiScreen; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.gui.element.GuiGameElement; -import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.Lang; @@ -36,13 +36,13 @@ public class RadialToolboxMenu extends AbstractSimiScreen { private int hoveredSlot; private boolean scrollMode; private int scrollSlot = 0; - private List toolboxes; - private ToolboxTileEntity selectedBox; + private List toolboxes; + private ToolboxBlockEntity selectedBox; private static final int DEPOSIT = -7; private static final int UNEQUIP = -5; - public RadialToolboxMenu(List toolboxes, State state, @Nullable ToolboxTileEntity selectedBox) { + public RadialToolboxMenu(List toolboxes, State state, @Nullable ToolboxBlockEntity selectedBox) { this.toolboxes = toolboxes; this.state = state; hoveredSlot = -1; @@ -155,15 +155,15 @@ public class RadialToolboxMenu extends AbstractSimiScreen { if (slot < toolboxes.size()) { AllGuiTextures.TOOLBELT_SLOT.render(ms, 0, 0, this); - ToolboxTileEntity toolboxTileEntity = toolboxes.get(slot); - GuiGameElement.of(AllBlocks.TOOLBOXES.get(toolboxTileEntity.getColor()) + ToolboxBlockEntity toolboxBlockEntity = toolboxes.get(slot); + GuiGameElement.of(AllBlocks.TOOLBOXES.get(toolboxBlockEntity.getColor()) .asStack()) .at(3, 3) .render(ms); if (slot == (scrollMode ? scrollSlot : hoveredSlot)) { AllGuiTextures.TOOLBELT_SLOT_HIGHLIGHT.render(ms, -1, -1, this); - tip = toolboxTileEntity.getDisplayName(); + tip = toolboxBlockEntity.getDisplayName(); } } else AllGuiTextures.TOOLBELT_EMPTY_SLOT.render(ms, 0, 0, this); @@ -231,9 +231,9 @@ public class RadialToolboxMenu extends AbstractSimiScreen { if (state == State.DETACH) return; else if (state == State.SELECT_BOX) - toolboxes.forEach(te -> AllPackets.channel.sendToServer(new ToolboxDisposeAllPacket(te.getBlockPos()))); + toolboxes.forEach(be -> AllPackets.getChannel().sendToServer(new ToolboxDisposeAllPacket(be.getBlockPos()))); else - AllPackets.channel.sendToServer(new ToolboxDisposeAllPacket(selectedBox.getBlockPos())); + AllPackets.getChannel().sendToServer(new ToolboxDisposeAllPacket(selectedBox.getBlockPos())); return; } @@ -242,13 +242,13 @@ public class RadialToolboxMenu extends AbstractSimiScreen { if (state == State.DETACH) { if (selected == UNEQUIP) - AllPackets.channel.sendToServer( + AllPackets.getChannel().sendToServer( new ToolboxEquipPacket(null, selected, minecraft.player.getInventory().selected)); return; } if (selected == UNEQUIP) - AllPackets.channel.sendToServer(new ToolboxEquipPacket(selectedBox.getBlockPos(), selected, + AllPackets.getChannel().sendToServer(new ToolboxEquipPacket(selectedBox.getBlockPos(), selected, minecraft.player.getInventory().selected)); if (selected < 0) @@ -261,7 +261,7 @@ public class RadialToolboxMenu extends AbstractSimiScreen { .isEmpty()) return; - AllPackets.channel.sendToServer(new ToolboxEquipPacket(selectedBox.getBlockPos(), selected, + AllPackets.getChannel().sendToServer(new ToolboxEquipPacket(selectedBox.getBlockPos(), selected, minecraft.player.getInventory().selected)); } @@ -334,7 +334,7 @@ public class RadialToolboxMenu extends AbstractSimiScreen { if (state == State.SELECT_ITEM_UNEQUIP && selected == UNEQUIP) { if (toolboxes.size() > 1) { - AllPackets.channel.sendToServer(new ToolboxEquipPacket(selectedBox.getBlockPos(), selected, + AllPackets.getChannel().sendToServer(new ToolboxEquipPacket(selectedBox.getBlockPos(), selected, minecraft.player.getInventory().selected)); state = State.SELECT_BOX; return true; diff --git a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolBoxInstance.java b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolBoxInstance.java similarity index 86% rename from src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolBoxInstance.java rename to src/main/java/com/simibubi/create/content/equipment/toolbox/ToolBoxInstance.java index aac661c5e..375c63cf0 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolBoxInstance.java +++ b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolBoxInstance.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.toolbox; +package com.simibubi.create.content.equipment.toolbox; import com.jozufozu.flywheel.api.Instancer; import com.jozufozu.flywheel.api.MaterialManager; @@ -6,21 +6,21 @@ import com.jozufozu.flywheel.api.instance.DynamicInstance; import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance; import com.jozufozu.flywheel.core.Materials; import com.jozufozu.flywheel.core.materials.model.ModelData; -import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.AllPartialModels; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.Iterate; import net.minecraft.core.Direction; import net.minecraft.world.level.block.state.BlockState; -public class ToolBoxInstance extends BlockEntityInstance implements DynamicInstance { +public class ToolBoxInstance extends BlockEntityInstance implements DynamicInstance { private final Direction facing; private ModelData lid; private ModelData[] drawers; - public ToolBoxInstance(MaterialManager materialManager, ToolboxTileEntity tile) { - super(materialManager, tile); + public ToolBoxInstance(MaterialManager materialManager, ToolboxBlockEntity blockEntity) { + super(materialManager, blockEntity); facing = blockState.getValue(ToolboxBlock.FACING) .getOpposite(); @@ -32,12 +32,12 @@ public class ToolBoxInstance extends BlockEntityInstance impl Instancer drawerModel = materialManager.defaultSolid() .material(Materials.TRANSFORMED) - .getModel(AllBlockPartials.TOOLBOX_DRAWER, blockState); + .getModel(AllPartialModels.TOOLBOX_DRAWER, blockState); drawers = new ModelData[]{drawerModel.createInstance(), drawerModel.createInstance()}; lid = materialManager.defaultCutout() .material(Materials.TRANSFORMED) - .getModel(AllBlockPartials.TOOLBOX_LIDS.get(blockEntity.getColor()), blockState) + .getModel(AllPartialModels.TOOLBOX_LIDS.get(blockEntity.getColor()), blockState) .createInstance(); } diff --git a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxBlock.java b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxBlock.java similarity index 84% rename from src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxBlock.java rename to src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxBlock.java index aeedc3968..613ae9153 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxBlock.java +++ b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxBlock.java @@ -1,13 +1,13 @@ -package com.simibubi.create.content.curiosities.toolbox; +package com.simibubi.create.content.equipment.toolbox; import static net.minecraft.world.level.block.state.properties.BlockStateProperties.WATERLOGGED; import java.util.Optional; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.utility.BlockHelper; import net.minecraft.core.BlockPos; @@ -41,7 +41,7 @@ import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraftforge.common.util.FakePlayer; import net.minecraftforge.network.NetworkHooks; -public class ToolboxBlock extends HorizontalDirectionalBlock implements SimpleWaterloggedBlock, ITE { +public class ToolboxBlock extends HorizontalDirectionalBlock implements SimpleWaterloggedBlock, IBE { protected final DyeColor color; @@ -69,13 +69,13 @@ public class ToolboxBlock extends HorizontalDirectionalBlock implements SimpleWa return; if (stack == null) return; - withTileEntityDo(worldIn, pos, te -> { + withBlockEntityDo(worldIn, pos, be -> { CompoundTag orCreateTag = stack.getOrCreateTag(); - te.readInventory(orCreateTag.getCompound("Inventory")); + be.readInventory(orCreateTag.getCompound("Inventory")); if (orCreateTag.contains("UniqueId")) - te.setUniqueId(orCreateTag.getUUID("UniqueId")); + be.setUniqueId(orCreateTag.getUUID("UniqueId")); if (stack.hasCustomHoverName()) - te.setCustomName(stack.getHoverName()); + be.setCustomName(stack.getHoverName()); }); } @@ -91,7 +91,7 @@ public class ToolboxBlock extends HorizontalDirectionalBlock implements SimpleWa return; if (world.isClientSide) return; - withTileEntityDo(world, pos, ToolboxTileEntity::unequipTracked); + withBlockEntityDo(world, pos, ToolboxBlockEntity::unequipTracked); if (world instanceof ServerLevel) { ItemStack cloneItemStack = getCloneItemStack(world, pos, state); world.destroyBlock(pos, false); @@ -103,16 +103,16 @@ public class ToolboxBlock extends HorizontalDirectionalBlock implements SimpleWa @Override public ItemStack getCloneItemStack(BlockGetter world, BlockPos pos, BlockState state) { ItemStack item = new ItemStack(this); - Optional tileEntityOptional = getTileEntityOptional(world, pos); + Optional blockEntityOptional = getBlockEntityOptional(world, pos); CompoundTag tag = item.getOrCreateTag(); - CompoundTag inv = tileEntityOptional.map(tb -> tb.inventory.serializeNBT()) + CompoundTag inv = blockEntityOptional.map(tb -> tb.inventory.serializeNBT()) .orElse(new CompoundTag()); tag.put("Inventory", inv); - tileEntityOptional.map(tb -> tb.getUniqueId()) + blockEntityOptional.map(tb -> tb.getUniqueId()) .ifPresent(uid -> tag.putUUID("UniqueId", uid)); - tileEntityOptional.map(ToolboxTileEntity::getCustomName) + blockEntityOptional.map(ToolboxBlockEntity::getCustomName) .ifPresent(item::setHoverName); return item; } @@ -153,8 +153,8 @@ public class ToolboxBlock extends HorizontalDirectionalBlock implements SimpleWa if (world.isClientSide) return InteractionResult.SUCCESS; - withTileEntityDo(world, pos, - toolbox -> NetworkHooks.openScreen((ServerPlayer) player, toolbox, toolbox::sendToContainer)); + withBlockEntityDo(world, pos, + toolbox -> NetworkHooks.openScreen((ServerPlayer) player, toolbox, toolbox::sendToMenu)); return InteractionResult.SUCCESS; } @@ -168,13 +168,13 @@ public class ToolboxBlock extends HorizontalDirectionalBlock implements SimpleWa } @Override - public Class getTileEntityClass() { - return ToolboxTileEntity.class; + public Class getBlockEntityClass() { + return ToolboxBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.TOOLBOX.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.TOOLBOX.get(); } public DyeColor getColor() { diff --git a/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxBlockEntity.java b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxBlockEntity.java new file mode 100644 index 000000000..ee397eea1 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxBlockEntity.java @@ -0,0 +1,421 @@ +package com.simibubi.create.content.equipment.toolbox; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.UUID; +import java.util.WeakHashMap; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.ResetableLazy; +import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; + +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.ServerPlayer; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.MenuProvider; +import net.minecraft.world.Nameable; +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.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemHandlerHelper; + +public class ToolboxBlockEntity extends SmartBlockEntity implements MenuProvider, Nameable { + + public LerpedFloat lid = LerpedFloat.linear() + .startWithValue(0); + + public LerpedFloat drawers = LerpedFloat.linear() + .startWithValue(0); + + UUID uniqueId; + ToolboxInventory inventory; + LazyOptional inventoryProvider; + ResetableLazy colorProvider; + protected int openCount; + + Map> connectedPlayers; + + private Component customName; + + public ToolboxBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + connectedPlayers = new HashMap<>(); + inventory = new ToolboxInventory(this); + inventoryProvider = LazyOptional.of(() -> inventory); + colorProvider = ResetableLazy.of(() -> { + BlockState blockState = getBlockState(); + if (blockState != null && blockState.getBlock() instanceof ToolboxBlock) + return ((ToolboxBlock) blockState.getBlock()).getColor(); + return DyeColor.BROWN; + }); + setLazyTickRate(10); + } + + public DyeColor getColor() { + return colorProvider.get(); + } + + @Override + public void addBehaviours(List behaviours) {} + + @Override + public void initialize() { + super.initialize(); + ToolboxHandler.onLoad(this); + } + + @Override + public void invalidate() { + super.invalidate(); + ToolboxHandler.onUnload(this); + } + + @Override + public void tick() { + super.tick(); + + if (level.isClientSide) + tickAudio(); + if (!level.isClientSide) + tickPlayers(); + + lid.chase(openCount > 0 ? 1 : 0, 0.2f, Chaser.LINEAR); + drawers.chase(openCount > 0 ? 1 : 0, 0.2f, Chaser.EXP); + lid.tickChaser(); + drawers.tickChaser(); + } + + private void tickPlayers() { + boolean update = false; + + for (Iterator>> toolboxSlots = connectedPlayers.entrySet() + .iterator(); toolboxSlots.hasNext();) { + + Entry> toolboxSlotEntry = toolboxSlots.next(); + WeakHashMap set = toolboxSlotEntry.getValue(); + int slot = toolboxSlotEntry.getKey(); + + ItemStack referenceItem = inventory.filters.get(slot); + boolean clear = referenceItem.isEmpty(); + + for (Iterator> playerEntries = set.entrySet() + .iterator(); playerEntries.hasNext();) { + Entry playerEntry = playerEntries.next(); + + Player player = playerEntry.getKey(); + int hotbarSlot = playerEntry.getValue(); + + if (!clear && !ToolboxHandler.withinRange(player, this)) + continue; + + Inventory playerInv = player.getInventory(); + ItemStack playerStack = playerInv.getItem(hotbarSlot); + + if (clear || !playerStack.isEmpty() + && !ToolboxInventory.canItemsShareCompartment(playerStack, referenceItem)) { + player.getPersistentData() + .getCompound("CreateToolboxData") + .remove(String.valueOf(hotbarSlot)); + playerEntries.remove(); + if (player instanceof ServerPlayer) + ToolboxHandler.syncData(player); + continue; + } + + int count = playerStack.getCount(); + int targetAmount = (referenceItem.getMaxStackSize() + 1) / 2; + + if (count < targetAmount) { + int amountToReplenish = targetAmount - count; + + if (isOpenInContainer(player)) { + ItemStack extracted = inventory.takeFromCompartment(amountToReplenish, slot, true); + if (!extracted.isEmpty()) { + ToolboxHandler.unequip(player, hotbarSlot, false); + ToolboxHandler.syncData(player); + continue; + } + } + + ItemStack extracted = inventory.takeFromCompartment(amountToReplenish, slot, false); + if (!extracted.isEmpty()) { + update = true; + ItemStack template = playerStack.isEmpty() ? extracted : playerStack; + playerInv.setItem(hotbarSlot, + ItemHandlerHelper.copyStackWithSize(template, count + extracted.getCount())); + } + } + + if (count > targetAmount) { + int amountToDeposit = count - targetAmount; + ItemStack toDistribute = ItemHandlerHelper.copyStackWithSize(playerStack, amountToDeposit); + + if (isOpenInContainer(player)) { + int deposited = amountToDeposit - inventory.distributeToCompartment(toDistribute, slot, true) + .getCount(); + if (deposited > 0) { + ToolboxHandler.unequip(player, hotbarSlot, true); + ToolboxHandler.syncData(player); + continue; + } + } + + int deposited = amountToDeposit - inventory.distributeToCompartment(toDistribute, slot, false) + .getCount(); + if (deposited > 0) { + update = true; + playerInv.setItem(hotbarSlot, + ItemHandlerHelper.copyStackWithSize(playerStack, count - deposited)); + } + } + } + + if (clear) + toolboxSlots.remove(); + } + + if (update) + + sendData(); + + } + + private boolean isOpenInContainer(Player player) { + return player.containerMenu instanceof ToolboxMenu + && ((ToolboxMenu) player.containerMenu).contentHolder == this; + } + + public void unequipTracked() { + if (level.isClientSide) + return; + + Set affected = new HashSet<>(); + + for (Iterator>> toolboxSlots = connectedPlayers.entrySet() + .iterator(); toolboxSlots.hasNext();) { + + Entry> toolboxSlotEntry = toolboxSlots.next(); + WeakHashMap set = toolboxSlotEntry.getValue(); + + for (Iterator> playerEntries = set.entrySet() + .iterator(); playerEntries.hasNext();) { + Entry playerEntry = playerEntries.next(); + + Player player = playerEntry.getKey(); + int hotbarSlot = playerEntry.getValue(); + + ToolboxHandler.unequip(player, hotbarSlot, false); + if (player instanceof ServerPlayer) + affected.add((ServerPlayer) player); + } + } + + for (ServerPlayer player : affected) + ToolboxHandler.syncData(player); + connectedPlayers.clear(); + } + + public void unequip(int slot, Player player, int hotbarSlot, boolean keepItems) { + if (!connectedPlayers.containsKey(slot)) + return; + connectedPlayers.get(slot) + .remove(player); + if (keepItems) + return; + + Inventory playerInv = player.getInventory(); + ItemStack playerStack = playerInv.getItem(hotbarSlot); + ItemStack toInsert = ToolboxInventory.cleanItemNBT(playerStack.copy()); + ItemStack remainder = inventory.distributeToCompartment(toInsert, slot, false); + + if (remainder.getCount() != toInsert.getCount()) + playerInv.setItem(hotbarSlot, remainder); + } + + private void tickAudio() { + Vec3 vec = VecHelper.getCenterOf(worldPosition); + if (lid.settled()) { + if (openCount > 0 && lid.getChaseTarget() == 0) { + level.playLocalSound(vec.x, vec.y, vec.z, SoundEvents.IRON_DOOR_OPEN, SoundSource.BLOCKS, 0.25F, + level.random.nextFloat() * 0.1F + 1.2F, true); + level.playLocalSound(vec.x, vec.y, vec.z, SoundEvents.CHEST_OPEN, SoundSource.BLOCKS, 0.1F, + level.random.nextFloat() * 0.1F + 1.1F, true); + } + if (openCount == 0 && lid.getChaseTarget() == 1) + level.playLocalSound(vec.x, vec.y, vec.z, SoundEvents.CHEST_CLOSE, SoundSource.BLOCKS, 0.1F, + level.random.nextFloat() * 0.1F + 1.1F, true); + + } else if (openCount == 0 && lid.getChaseTarget() == 0 && lid.getValue(0) > 1 / 16f + && lid.getValue(1) < 1 / 16f) + level.playLocalSound(vec.x, vec.y, vec.z, SoundEvents.IRON_DOOR_CLOSE, SoundSource.BLOCKS, 0.25F, + level.random.nextFloat() * 0.1F + 1.2F, true); + } + + @Override + public LazyOptional getCapability(Capability cap, Direction side) { + if (isItemHandlerCap(cap)) + return inventoryProvider.cast(); + return super.getCapability(cap, side); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + inventory.deserializeNBT(compound.getCompound("Inventory")); + super.read(compound, clientPacket); + if (compound.contains("UniqueId", 11)) + this.uniqueId = compound.getUUID("UniqueId"); + if (compound.contains("CustomName", 8)) + this.customName = Component.Serializer.fromJson(compound.getString("CustomName")); + if (clientPacket) + openCount = compound.getInt("OpenCount"); + } + + @Override + protected void write(CompoundTag compound, boolean clientPacket) { + if (uniqueId == null) + uniqueId = UUID.randomUUID(); + + compound.put("Inventory", inventory.serializeNBT()); + compound.putUUID("UniqueId", uniqueId); + + if (customName != null) + compound.putString("CustomName", Component.Serializer.toJson(customName)); + super.write(compound, clientPacket); + if (clientPacket) + compound.putInt("OpenCount", openCount); + } + + @Override + public AbstractContainerMenu createMenu(int id, Inventory inv, Player player) { + return ToolboxMenu.create(id, inv, this); + } + + @Override + public void lazyTick() { + updateOpenCount(); + // keep re-advertising active TEs + ToolboxHandler.onLoad(this); + super.lazyTick(); + } + + void updateOpenCount() { + if (level.isClientSide) + return; + if (openCount == 0) + return; + + int prevOpenCount = openCount; + openCount = 0; + + for (Player playerentity : level.getEntitiesOfClass(Player.class, new AABB(worldPosition).inflate(8))) + if (playerentity.containerMenu instanceof ToolboxMenu + && ((ToolboxMenu) playerentity.containerMenu).contentHolder == this) + openCount++; + + if (prevOpenCount != openCount) + sendData(); + } + + public void startOpen(Player player) { + if (player.isSpectator()) + return; + if (openCount < 0) + openCount = 0; + openCount++; + sendData(); + } + + public void stopOpen(Player player) { + if (player.isSpectator()) + return; + openCount--; + sendData(); + } + + public void connectPlayer(int slot, Player player, int hotbarSlot) { + if (level.isClientSide) + return; + WeakHashMap map = connectedPlayers.computeIfAbsent(slot, WeakHashMap::new); + Integer previous = map.get(player); + if (previous != null) { + if (previous == hotbarSlot) + return; + ToolboxHandler.unequip(player, previous, false); + } + map.put(player, hotbarSlot); + } + + public void readInventory(CompoundTag compound) { + inventory.deserializeNBT(compound); + } + + public void setUniqueId(UUID uniqueId) { + this.uniqueId = uniqueId; + } + + public UUID getUniqueId() { + return uniqueId; + } + + public boolean isFullyInitialized() { + // returns true when uniqueId has been initialized + return uniqueId != null; + } + + public void setCustomName(Component customName) { + this.customName = customName; + } + + @Override + public Component getDisplayName() { + return customName != null ? customName + : AllBlocks.TOOLBOXES.get(getColor()) + .get() + .getName(); + } + + @Override + public Component getCustomName() { + return customName; + } + + @Override + public boolean hasCustomName() { + return customName != null; + } + + @Override + public Component getName() { + return customName; + } + + @SuppressWarnings("deprecation") + @Override + public void setBlockState(BlockState state) { + super.setBlockState(state); + colorProvider.reset(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxDisposeAllPacket.java b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxDisposeAllPacket.java similarity index 84% rename from src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxDisposeAllPacket.java rename to src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxDisposeAllPacket.java index 920ab41db..e9a6fb2ff 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxDisposeAllPacket.java +++ b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxDisposeAllPacket.java @@ -1,6 +1,4 @@ -package com.simibubi.create.content.curiosities.toolbox; - -import java.util.function.Supplier; +package com.simibubi.create.content.equipment.toolbox; import org.apache.commons.lang3.mutable.MutableBoolean; @@ -35,10 +33,9 @@ public class ToolboxDisposeAllPacket extends SimplePacketBase { } @Override - public void handle(Supplier context) { - Context ctx = context.get(); - ctx.enqueueWork(() -> { - ServerPlayer player = ctx.getSender(); + public boolean handle(Context context) { + context.enqueueWork(() -> { + ServerPlayer player = context.getSender(); Level world = player.level; BlockEntity blockEntity = world.getBlockEntity(toolboxPos); @@ -46,9 +43,9 @@ public class ToolboxDisposeAllPacket extends SimplePacketBase { if (player.distanceToSqr(toolboxPos.getX() + 0.5, toolboxPos.getY(), toolboxPos.getZ() + 0.5) > maxRange * maxRange) return; - if (!(blockEntity instanceof ToolboxTileEntity)) + if (!(blockEntity instanceof ToolboxBlockEntity)) return; - ToolboxTileEntity toolbox = (ToolboxTileEntity) blockEntity; + ToolboxBlockEntity toolbox = (ToolboxBlockEntity) blockEntity; CompoundTag compound = player.getPersistentData() .getCompound("CreateToolboxData"); @@ -73,9 +70,8 @@ public class ToolboxDisposeAllPacket extends SimplePacketBase { if (sendData.booleanValue()) ToolboxHandler.syncData(player); - }); - ctx.setPacketHandled(true); + return true; } } diff --git a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxDyeingRecipe.java b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxDyeingRecipe.java similarity index 97% rename from src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxDyeingRecipe.java rename to src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxDyeingRecipe.java index 1ac96c362..949a6f8bb 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxDyeingRecipe.java +++ b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxDyeingRecipe.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.toolbox; +package com.simibubi.create.content.equipment.toolbox; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllRecipeTypes; diff --git a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxEquipPacket.java b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxEquipPacket.java similarity index 82% rename from src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxEquipPacket.java rename to src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxEquipPacket.java index 55538921e..13c8c3284 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxEquipPacket.java +++ b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxEquipPacket.java @@ -1,6 +1,4 @@ -package com.simibubi.create.content.curiosities.toolbox; - -import java.util.function.Supplier; +package com.simibubi.create.content.equipment.toolbox; import com.simibubi.create.foundation.networking.SimplePacketBase; @@ -44,10 +42,9 @@ public class ToolboxEquipPacket extends SimplePacketBase { } @Override - public void handle(Supplier context) { - Context ctx = context.get(); - ctx.enqueueWork(() -> { - ServerPlayer player = ctx.getSender(); + public boolean handle(Context context) { + context.enqueueWork(() -> { + ServerPlayer player = context.getSender(); Level world = player.level; if (toolboxPos == null) { @@ -62,7 +59,7 @@ public class ToolboxEquipPacket extends SimplePacketBase { if (player.distanceToSqr(toolboxPos.getX() + 0.5, toolboxPos.getY(), toolboxPos.getZ() + 0.5) > maxRange * maxRange) return; - if (!(blockEntity instanceof ToolboxTileEntity)) + if (!(blockEntity instanceof ToolboxBlockEntity)) return; ToolboxHandler.unequip(player, hotbarSlot, false); @@ -72,12 +69,12 @@ public class ToolboxEquipPacket extends SimplePacketBase { return; } - ToolboxTileEntity toolboxTileEntity = (ToolboxTileEntity) blockEntity; + ToolboxBlockEntity toolboxBlockEntity = (ToolboxBlockEntity) blockEntity; ItemStack playerStack = player.getInventory().getItem(hotbarSlot); if (!playerStack.isEmpty() && !ToolboxInventory.canItemsShareCompartment(playerStack, - toolboxTileEntity.inventory.filters.get(slot))) { - toolboxTileEntity.inventory.inLimitedMode(inventory -> { + toolboxBlockEntity.inventory.filters.get(slot))) { + toolboxBlockEntity.inventory.inLimitedMode(inventory -> { ItemStack remainder = ItemHandlerHelper.insertItemStacked(inventory, playerStack, false); if (!remainder.isEmpty()) remainder = ItemHandlerHelper.insertItemStacked(new ItemReturnInvWrapper(player.getInventory()), @@ -99,10 +96,10 @@ public class ToolboxEquipPacket extends SimplePacketBase { player.getPersistentData() .put("CreateToolboxData", compound); - toolboxTileEntity.connectPlayer(slot, player, hotbarSlot); + toolboxBlockEntity.connectPlayer(slot, player, hotbarSlot); ToolboxHandler.syncData(player); }); - ctx.setPacketHandled(true); + return true; } } diff --git a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxHandler.java b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxHandler.java similarity index 78% rename from src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxHandler.java rename to src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxHandler.java index c7ec4aacc..8a799f183 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxHandler.java +++ b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxHandler.java @@ -1,13 +1,13 @@ -package com.simibubi.create.content.curiosities.toolbox; +package com.simibubi.create.content.equipment.toolbox; import java.util.List; import java.util.WeakHashMap; import java.util.stream.Collectors; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.AllPackets; import com.simibubi.create.foundation.networking.ISyncPersistentData.PersistentDataPacket; import com.simibubi.create.foundation.utility.WorldAttached; +import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; @@ -24,17 +24,17 @@ import net.minecraftforge.network.PacketDistributor; public class ToolboxHandler { - public static final WorldAttached> toolboxes = + public static final WorldAttached> toolboxes = new WorldAttached<>(w -> new WeakHashMap<>()); - public static void onLoad(ToolboxTileEntity te) { - toolboxes.get(te.getLevel()) - .put(te.getBlockPos(), te); + public static void onLoad(ToolboxBlockEntity be) { + toolboxes.get(be.getLevel()) + .put(be.getBlockPos(), be); } - public static void onUnload(ToolboxTileEntity te) { - toolboxes.get(te.getLevel()) - .remove(te.getBlockPos()); + public static void onUnload(ToolboxBlockEntity be) { + toolboxes.get(be.getLevel()) + .remove(be.getBlockPos()); } static int validationTimer = 20; @@ -76,8 +76,8 @@ public class ToolboxHandler { } BlockEntity prevBlockEntity = world.getBlockEntity(pos); - if (prevBlockEntity instanceof ToolboxTileEntity) - ((ToolboxTileEntity) prevBlockEntity).connectPlayer(slot, player, i); + if (prevBlockEntity instanceof ToolboxBlockEntity) + ((ToolboxBlockEntity) prevBlockEntity).connectPlayer(slot, player, i); } if (sendData) @@ -97,11 +97,11 @@ public class ToolboxHandler { } public static void syncData(Player player) { - AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), + AllPackets.getChannel().send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), new PersistentDataPacket(player)); } - public static List getNearest(LevelAccessor world, Player player, int maxAmount) { + public static List getNearest(LevelAccessor world, Player player, int maxAmount) { Vec3 location = player.position(); double maxRange = getMaxRange(player); return toolboxes.get(world) @@ -111,7 +111,7 @@ public class ToolboxHandler { .sorted((p1, p2) -> Double.compare(distance(location, p1), distance(location, p2))) .limit(maxAmount) .map(toolboxes.get(world)::get) - .filter(ToolboxTileEntity::isFullyInitialized) + .filter(ToolboxBlockEntity::isFullyInitialized) .collect(Collectors.toList()); } @@ -128,14 +128,14 @@ public class ToolboxHandler { int prevSlot = prevData.getInt("Slot"); BlockEntity prevBlockEntity = world.getBlockEntity(prevPos); - if (prevBlockEntity instanceof ToolboxTileEntity) { - ToolboxTileEntity toolbox = (ToolboxTileEntity) prevBlockEntity; + if (prevBlockEntity instanceof ToolboxBlockEntity) { + ToolboxBlockEntity toolbox = (ToolboxBlockEntity) prevBlockEntity; toolbox.unequip(prevSlot, player, hotbarSlot, keepItems || !ToolboxHandler.withinRange(player, toolbox)); } compound.remove(key); } - public static boolean withinRange(Player player, ToolboxTileEntity box) { + public static boolean withinRange(Player player, ToolboxBlockEntity box) { if (player.level != box.getLevel()) return false; double maxRange = getMaxRange(player); @@ -147,7 +147,7 @@ public class ToolboxHandler { } public static double getMaxRange(Player player) { - return AllConfigs.SERVER.curiosities.toolboxRange.get() + return AllConfigs.server().equipment.toolboxRange.get() .doubleValue(); } diff --git a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxHandlerClient.java b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxHandlerClient.java similarity index 88% rename from src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxHandlerClient.java rename to src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxHandlerClient.java index 41bae329d..21505db29 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxHandlerClient.java +++ b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxHandlerClient.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.toolbox; +package com.simibubi.create.content.equipment.toolbox; import static com.simibubi.create.foundation.gui.AllGuiTextures.TOOLBELT_HOTBAR_OFF; import static com.simibubi.create.foundation.gui.AllGuiTextures.TOOLBELT_HOTBAR_ON; @@ -12,9 +12,9 @@ import com.google.common.collect.ImmutableList; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllKeys; +import com.simibubi.create.AllPackets; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.ScreenOpener; -import com.simibubi.create.foundation.networking.AllPackets; import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; @@ -60,7 +60,7 @@ public class ToolboxHandlerClient { return false; ItemStack result = ItemStack.EMPTY; - List toolboxes = ToolboxHandler.getNearest(player.level, player, 8); + List toolboxes = ToolboxHandler.getNearest(player.level, player, 8); if (toolboxes.isEmpty()) return false; @@ -80,8 +80,8 @@ public class ToolboxHandlerClient { if (result.isEmpty()) return false; - for (ToolboxTileEntity toolboxTileEntity : toolboxes) { - ToolboxInventory inventory = toolboxTileEntity.inventory; + for (ToolboxBlockEntity toolboxBlockEntity : toolboxes) { + ToolboxInventory inventory = toolboxBlockEntity.inventory; for (int comp = 0; comp < 8; comp++) { ItemStack inSlot = inventory.takeFromCompartment(1, comp, true); if (inSlot.isEmpty()) @@ -91,8 +91,8 @@ public class ToolboxHandlerClient { if (!ItemStack.tagMatches(inSlot, result)) continue; - AllPackets.channel.sendToServer( - new ToolboxEquipPacket(toolboxTileEntity.getBlockPos(), comp, player.getInventory().selected)); + AllPackets.getChannel().sendToServer( + new ToolboxEquipPacket(toolboxBlockEntity.getBlockPos(), comp, player.getInventory().selected)); return true; } @@ -115,8 +115,8 @@ public class ToolboxHandlerClient { return; Level level = player.level; - List toolboxes = ToolboxHandler.getNearest(player.level, player, 8); - toolboxes.sort(Comparator.comparing(ToolboxTileEntity::getUniqueId)); + List toolboxes = ToolboxHandler.getNearest(player.level, player, 8); + toolboxes.sort(Comparator.comparing(ToolboxBlockEntity::getUniqueId)); CompoundTag compound = player.getPersistentData() .getCompound("CreateToolboxData"); @@ -132,9 +132,9 @@ public class ToolboxHandlerClient { if (canReachToolbox) { BlockEntity blockEntity = level.getBlockEntity(pos); - if (blockEntity instanceof ToolboxTileEntity) { + if (blockEntity instanceof ToolboxBlockEntity) { RadialToolboxMenu screen = new RadialToolboxMenu(toolboxes, - RadialToolboxMenu.State.SELECT_ITEM_UNEQUIP, (ToolboxTileEntity) blockEntity); + RadialToolboxMenu.State.SELECT_ITEM_UNEQUIP, (ToolboxBlockEntity) blockEntity); screen.prevSlot(compound.getCompound(slotKey) .getInt("Slot")); ScreenOpener.open(screen); diff --git a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxInventory.java b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxInventory.java similarity index 94% rename from src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxInventory.java rename to src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxInventory.java index 1d35771c3..a9d69e9ca 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxInventory.java +++ b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxInventory.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.toolbox; +package com.simibubi.create.content.equipment.toolbox; import java.util.ArrayList; import java.util.List; @@ -20,13 +20,13 @@ public class ToolboxInventory extends ItemStackHandler { public static final int STACKS_PER_COMPARTMENT = 4; List filters; boolean settling; - private ToolboxTileEntity te; + private ToolboxBlockEntity blockEntity; private boolean limitedMode; - public ToolboxInventory(ToolboxTileEntity te) { + public ToolboxInventory(ToolboxBlockEntity be) { super(8 * STACKS_PER_COMPARTMENT); - this.te = te; + this.blockEntity = be; limitedMode = false; filters = new ArrayList<>(); settling = false; @@ -83,7 +83,7 @@ public class ToolboxInventory extends ItemStackHandler { } } settling = false; - te.sendData(); + blockEntity.sendData(); } @Override @@ -109,7 +109,7 @@ public class ToolboxInventory extends ItemStackHandler { if (!stack.isEmpty() && filters.get(compartment) .isEmpty()) { filters.set(compartment, ItemHandlerHelper.copyStackWithSize(stack, 1)); - te.sendData(); + blockEntity.sendData(); } } @@ -121,7 +121,7 @@ public class ToolboxInventory extends ItemStackHandler { if (!stack.isEmpty() && filters.get(compartment) .isEmpty()) { filters.set(compartment, ItemHandlerHelper.copyStackWithSize(stack, 1)); - te.sendData(); + blockEntity.sendData(); } } return insertItem; @@ -136,10 +136,10 @@ public class ToolboxInventory extends ItemStackHandler { @Override protected void onContentsChanged(int slot) { - if (!settling && !te.getLevel().isClientSide) + if (!settling && !blockEntity.getLevel().isClientSide) settle(slot / STACKS_PER_COMPARTMENT); - te.sendData(); - te.setChanged(); + blockEntity.sendData(); + blockEntity.setChanged(); super.onContentsChanged(slot); } diff --git a/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxMenu.java b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxMenu.java new file mode 100644 index 000000000..8dacb716f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxMenu.java @@ -0,0 +1,159 @@ +package com.simibubi.create.content.equipment.toolbox; + +import static com.simibubi.create.content.equipment.toolbox.ToolboxInventory.STACKS_PER_COMPARTMENT; + +import com.simibubi.create.AllMenuTypes; +import com.simibubi.create.foundation.gui.menu.MenuBase; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +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.minecraft.world.level.block.entity.BlockEntity; +import net.minecraftforge.items.SlotItemHandler; + +public class ToolboxMenu extends MenuBase { + + public ToolboxMenu(MenuType type, int id, Inventory inv, FriendlyByteBuf extraData) { + super(type, id, inv, extraData); + } + + public ToolboxMenu(MenuType type, int id, Inventory inv, ToolboxBlockEntity be) { + super(type, id, inv, be); + be.startOpen(player); + } + + public static ToolboxMenu create(int id, Inventory inv, ToolboxBlockEntity be) { + return new ToolboxMenu(AllMenuTypes.TOOLBOX.get(), id, inv, be); + } + + @Override + protected ToolboxBlockEntity createOnClient(FriendlyByteBuf extraData) { + BlockPos readBlockPos = extraData.readBlockPos(); + CompoundTag readNbt = extraData.readNbt(); + + ClientLevel world = Minecraft.getInstance().level; + BlockEntity blockEntity = world.getBlockEntity(readBlockPos); + if (blockEntity instanceof ToolboxBlockEntity) { + ToolboxBlockEntity toolbox = (ToolboxBlockEntity) blockEntity; + toolbox.readClient(readNbt); + return toolbox; + } + + return null; + } + + @Override + public ItemStack quickMoveStack(Player player, int index) { + Slot clickedSlot = getSlot(index); + if (!clickedSlot.hasItem()) + return ItemStack.EMPTY; + + ItemStack stack = clickedSlot.getItem(); + int size = contentHolder.inventory.getSlots(); + boolean success = false; + if (index < size) { + success = !moveItemStackTo(stack, size, slots.size(), false); + contentHolder.inventory.onContentsChanged(index); + } else + success = !moveItemStackTo(stack, 0, size - 1, false); + + return success ? ItemStack.EMPTY : stack; + } + + @Override + protected void initAndReadInventory(ToolboxBlockEntity contentHolder) { + + } + + @Override + public void clicked(int index, int flags, ClickType type, Player player) { + int size = contentHolder.inventory.getSlots(); + + if (index >= 0 && index < size) { + ItemStack itemInClickedSlot = getSlot(index).getItem(); + ItemStack carried = getCarried(); + + if (type == ClickType.PICKUP && !carried.isEmpty() && !itemInClickedSlot.isEmpty() + && ToolboxInventory.canItemsShareCompartment(itemInClickedSlot, carried)) { + int subIndex = index % STACKS_PER_COMPARTMENT; + if (subIndex != STACKS_PER_COMPARTMENT - 1) { + clicked(index - subIndex + STACKS_PER_COMPARTMENT - 1, flags, type, player); + return; + } + } + + if (type == ClickType.PICKUP && carried.isEmpty() && itemInClickedSlot.isEmpty()) + if (!player.level.isClientSide) { + contentHolder.inventory.filters.set(index / STACKS_PER_COMPARTMENT, ItemStack.EMPTY); + contentHolder.sendData(); + } + + } + super.clicked(index, flags, type, player); + } + + @Override + public boolean canDragTo(Slot slot) { + return slot.index > contentHolder.inventory.getSlots() && super.canDragTo(slot); + } + + public ItemStack getFilter(int compartment) { + return contentHolder.inventory.filters.get(compartment); + } + + public int totalCountInCompartment(int compartment) { + int count = 0; + int baseSlot = compartment * STACKS_PER_COMPARTMENT; + for (int i = 0; i < STACKS_PER_COMPARTMENT; i++) + count += getSlot(baseSlot + i).getItem() + .getCount(); + return count; + } + + public boolean renderPass; + + @Override + protected void addSlots() { + ToolboxInventory inventory = contentHolder.inventory; + + int x = 79; + int y = 37; + + int[] xOffsets = { x, x + 33, x + 66, x + 66 + 6, x + 66, x + 33, x, x - 6 }; + int[] yOffsets = { y, y - 6, y, y + 33, y + 66, y + 66 + 6, y + 66, y + 33 }; + + for (int compartment = 0; compartment < 8; compartment++) { + int baseIndex = compartment * STACKS_PER_COMPARTMENT; + + // Representative Slots + addSlot(new ToolboxSlot(this, inventory, baseIndex, xOffsets[compartment], yOffsets[compartment])); + + // Hidden Slots + for (int i = 1; i < STACKS_PER_COMPARTMENT; i++) + addSlot(new SlotItemHandler(inventory, baseIndex + i, -10000, -10000)); + } + + addPlayerSlots(8, 165); + } + + @Override + protected void saveData(ToolboxBlockEntity contentHolder) { + + } + + @Override + public void removed(Player playerIn) { + super.removed(playerIn); + if (!playerIn.level.isClientSide) + contentHolder.stopOpen(playerIn); + } + +} diff --git a/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxRenderer.java b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxRenderer.java new file mode 100644 index 000000000..df2a4cf68 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxRenderer.java @@ -0,0 +1,58 @@ +package com.simibubi.create.content.equipment.toolbox; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.foundation.blockEntity.renderer.SmartBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.Iterate; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.state.BlockState; + +public class ToolboxRenderer extends SmartBlockEntityRenderer { + + public ToolboxRenderer(BlockEntityRendererProvider.Context context) { + super(context); + } + + @Override + protected void renderSafe(ToolboxBlockEntity blockEntity, float partialTicks, PoseStack ms, + MultiBufferSource buffer, int light, int overlay) { + + BlockState blockState = blockEntity.getBlockState(); + Direction facing = blockState.getValue(ToolboxBlock.FACING) + .getOpposite(); + SuperByteBuffer lid = + CachedBufferer.partial(AllPartialModels.TOOLBOX_LIDS.get(blockEntity.getColor()), blockState); + SuperByteBuffer drawer = CachedBufferer.partial(AllPartialModels.TOOLBOX_DRAWER, blockState); + + float lidAngle = blockEntity.lid.getValue(partialTicks); + float drawerOffset = blockEntity.drawers.getValue(partialTicks); + + VertexConsumer builder = buffer.getBuffer(RenderType.cutoutMipped()); + lid.centre() + .rotateY(-facing.toYRot()) + .unCentre() + .translate(0, 6 / 16f, 12 / 16f) + .rotateX(135 * lidAngle) + .translate(0, -6 / 16f, -12 / 16f) + .light(light) + .renderInto(ms, builder); + + for (int offset : Iterate.zeroAndOne) { + drawer.centre() + .rotateY(-facing.toYRot()) + .unCentre() + .translate(0, offset * 1 / 8f, -drawerOffset * .175f * (2 - offset)) + .light(light) + .renderInto(ms, builder); + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxScreen.java b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxScreen.java similarity index 88% rename from src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxScreen.java rename to src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxScreen.java index 13110e32b..71c7fe500 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/toolbox/ToolboxScreen.java +++ b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxScreen.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.toolbox; +package com.simibubi.create.content.equipment.toolbox; import java.util.Collections; import java.util.List; @@ -7,14 +7,14 @@ import com.google.common.collect.ImmutableList; import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPackets; +import com.simibubi.create.AllPartialModels; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.gui.container.AbstractSimiContainerScreen; import com.simibubi.create.foundation.gui.element.GuiGameElement; +import com.simibubi.create.foundation.gui.menu.AbstractSimiContainerScreen; import com.simibubi.create.foundation.gui.widget.IconButton; -import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Lang; @@ -25,7 +25,7 @@ import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.ItemStack; -public class ToolboxScreen extends AbstractSimiContainerScreen { +public class ToolboxScreen extends AbstractSimiContainerScreen { protected static final AllGuiTextures BG = AllGuiTextures.TOOLBOX; protected static final AllGuiTextures PLAYER = AllGuiTextures.PLAYER_INVENTORY; @@ -37,8 +37,8 @@ public class ToolboxScreen extends AbstractSimiContainerScreen private List extraAreas = Collections.emptyList(); - public ToolboxScreen(ToolboxContainer container, Inventory inv, Component title) { - super(container, inv, title); + public ToolboxScreen(ToolboxMenu menu, Inventory inv, Component title) { + super(menu, inv, title); init(); } @@ -58,7 +58,7 @@ public class ToolboxScreen extends AbstractSimiContainerScreen disposeButton = new IconButton(leftPos + 30 + 81, topPos + 69, AllIcons.I_TOOLBOX); disposeButton.withCallback(() -> { - AllPackets.channel.sendToServer(new ToolboxDisposeAllPacket(menu.contentHolder.getBlockPos())); + AllPackets.getChannel().sendToServer(new ToolboxDisposeAllPacket(menu.contentHolder.getBlockPos())); }); disposeButton.setToolTip(Lang.translateDirect("toolbox.depositBox")); addRenderableWidget(disposeButton); @@ -81,7 +81,7 @@ public class ToolboxScreen extends AbstractSimiContainerScreen int y = topPos; BG.render(ms, x, y, this); - font.draw(ms, title, x + 15, y + 4, 0x442000); + font.draw(ms, title, x + 15, y + 4, 0x592424); int invX = leftPos; int invY = topPos + imageHeight - PLAYER.height; @@ -141,7 +141,7 @@ public class ToolboxScreen extends AbstractSimiContainerScreen .translate(0, -6 / 16f, 12 / 16f) .rotateX(-105 * menu.contentHolder.lid.getValue(partialTicks)) .translate(0, 6 / 16f, -12 / 16f); - GuiGameElement.of(AllBlockPartials.TOOLBOX_LIDS.get(color)) + GuiGameElement.of(AllPartialModels.TOOLBOX_LIDS.get(color)) .render(ms); ms.popPose(); @@ -149,7 +149,7 @@ public class ToolboxScreen extends AbstractSimiContainerScreen ms.pushPose(); ms.translate(0, -offset * 1 / 8f, menu.contentHolder.drawers.getValue(partialTicks) * -.175f * (2 - offset)); - GuiGameElement.of(AllBlockPartials.TOOLBOX_DRAWER) + GuiGameElement.of(AllPartialModels.TOOLBOX_DRAWER) .render(ms); ms.popPose(); } diff --git a/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxSlot.java b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxSlot.java new file mode 100644 index 000000000..a87c21594 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxSlot.java @@ -0,0 +1,20 @@ +package com.simibubi.create.content.equipment.toolbox; + +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.SlotItemHandler; + +public class ToolboxSlot extends SlotItemHandler { + + private ToolboxMenu toolboxMenu; + + public ToolboxSlot(ToolboxMenu menu, IItemHandler itemHandler, int index, int xPosition, int yPosition) { + super(itemHandler, index, xPosition, yPosition); + this.toolboxMenu = menu; + } + + @Override + public boolean isActive() { + return !toolboxMenu.renderPass && super.isActive(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/wrench/IWrenchable.java b/src/main/java/com/simibubi/create/content/equipment/wrench/IWrenchable.java similarity index 84% rename from src/main/java/com/simibubi/create/content/contraptions/wrench/IWrenchable.java rename to src/main/java/com/simibubi/create/content/equipment/wrench/IWrenchable.java index 55a656e2c..c55d5059d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/wrench/IWrenchable.java +++ b/src/main/java/com/simibubi/create/content/equipment/wrench/IWrenchable.java @@ -1,14 +1,14 @@ -package com.simibubi.create.content.contraptions.wrench; +package com.simibubi.create.content.equipment.wrench; import com.simibubi.create.AllSoundEvents; import com.simibubi.create.Create; -import com.simibubi.create.content.contraptions.base.DirectionalAxisKineticBlock; -import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock; -import com.simibubi.create.content.contraptions.base.GeneratingKineticTileEntity; -import com.simibubi.create.content.contraptions.base.HorizontalAxisKineticBlock; -import com.simibubi.create.content.contraptions.base.HorizontalKineticBlock; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock; +import com.simibubi.create.content.kinetics.base.DirectionalAxisKineticBlock; +import com.simibubi.create.content.kinetics.base.DirectionalKineticBlock; +import com.simibubi.create.content.kinetics.base.GeneratingKineticBlockEntity; +import com.simibubi.create.content.kinetics.base.HorizontalAxisKineticBlock; +import com.simibubi.create.content.kinetics.base.HorizontalKineticBlock; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.base.RotatedPillarKineticBlock; import com.simibubi.create.foundation.utility.VoxelShaper; import net.minecraft.core.BlockPos; @@ -31,12 +31,12 @@ public interface IWrenchable { if (!rotated.canSurvive(world, context.getClickedPos())) return InteractionResult.PASS; - KineticTileEntity.switchToBlockState(world, context.getClickedPos(), updateAfterWrenched(rotated, context)); + KineticBlockEntity.switchToBlockState(world, context.getClickedPos(), updateAfterWrenched(rotated, context)); - BlockEntity te = context.getLevel() + BlockEntity be = context.getLevel() .getBlockEntity(context.getClickedPos()); - if (te instanceof GeneratingKineticTileEntity) { - ((GeneratingKineticTileEntity) te).reActivateSource = true; + if (be instanceof GeneratingKineticBlockEntity) { + ((GeneratingKineticBlockEntity) be).reActivateSource = true; } if (world.getBlockState(context.getClickedPos()) != state) diff --git a/src/main/java/com/simibubi/create/content/contraptions/wrench/IWrenchableWithBracket.java b/src/main/java/com/simibubi/create/content/equipment/wrench/IWrenchableWithBracket.java similarity index 93% rename from src/main/java/com/simibubi/create/content/contraptions/wrench/IWrenchableWithBracket.java rename to src/main/java/com/simibubi/create/content/equipment/wrench/IWrenchableWithBracket.java index 14bf177e1..dd7f115fd 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/wrench/IWrenchableWithBracket.java +++ b/src/main/java/com/simibubi/create/content/equipment/wrench/IWrenchableWithBracket.java @@ -1,9 +1,9 @@ -package com.simibubi.create.content.contraptions.wrench; +package com.simibubi.create.content.equipment.wrench; import java.util.Optional; import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.fluids.FluidPropagator; +import com.simibubi.create.content.fluids.FluidPropagator; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; diff --git a/src/main/java/com/simibubi/create/content/contraptions/wrench/WrenchEventHandler.java b/src/main/java/com/simibubi/create/content/equipment/wrench/WrenchEventHandler.java similarity index 96% rename from src/main/java/com/simibubi/create/content/contraptions/wrench/WrenchEventHandler.java rename to src/main/java/com/simibubi/create/content/equipment/wrench/WrenchEventHandler.java index ab4954df2..b9d6bb3bb 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/wrench/WrenchEventHandler.java +++ b/src/main/java/com/simibubi/create/content/equipment/wrench/WrenchEventHandler.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.wrench; +package com.simibubi.create.content.equipment.wrench; import com.simibubi.create.AllItems; import com.simibubi.create.AllTags.AllItemTags; diff --git a/src/main/java/com/simibubi/create/content/contraptions/wrench/WrenchItem.java b/src/main/java/com/simibubi/create/content/equipment/wrench/WrenchItem.java similarity index 98% rename from src/main/java/com/simibubi/create/content/contraptions/wrench/WrenchItem.java rename to src/main/java/com/simibubi/create/content/equipment/wrench/WrenchItem.java index 9b4f63d58..832c3c232 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/wrench/WrenchItem.java +++ b/src/main/java/com/simibubi/create/content/equipment/wrench/WrenchItem.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.wrench; +package com.simibubi.create.content.equipment.wrench; import java.util.function.Consumer; diff --git a/src/main/java/com/simibubi/create/content/equipment/wrench/WrenchItemRenderer.java b/src/main/java/com/simibubi/create/content/equipment/wrench/WrenchItemRenderer.java new file mode 100644 index 000000000..0086cf19b --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/wrench/WrenchItemRenderer.java @@ -0,0 +1,34 @@ +package com.simibubi.create.content.equipment.wrench; + +import com.jozufozu.flywheel.core.PartialModel; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Axis; +import com.simibubi.create.Create; +import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollValueHandler; +import com.simibubi.create.foundation.item.render.CustomRenderedItemModel; +import com.simibubi.create.foundation.item.render.CustomRenderedItemModelRenderer; +import com.simibubi.create.foundation.item.render.PartialItemModelRenderer; +import com.simibubi.create.foundation.utility.AnimationTickHolder; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.block.model.ItemTransforms; +import net.minecraft.world.item.ItemStack; + +public class WrenchItemRenderer extends CustomRenderedItemModelRenderer { + + protected static final PartialModel GEAR = new PartialModel(Create.asResource("item/wrench/gear")); + + @Override + protected void render(ItemStack stack, CustomRenderedItemModel model, PartialItemModelRenderer renderer, ItemTransforms.TransformType transformType, + PoseStack ms, MultiBufferSource buffer, int light, int overlay) { + renderer.render(model.getOriginalModel(), light); + + float xOffset = -1/16f; + ms.translate(-xOffset, 0, 0); + ms.mulPose(Axis.YP.rotationDegrees(ScrollValueHandler.getScroll(AnimationTickHolder.getPartialTicks()))); + ms.translate(xOffset, 0, 0); + + renderer.render(GEAR.get(), light); + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/ConfigureZapperPacket.java b/src/main/java/com/simibubi/create/content/equipment/zapper/ConfigureZapperPacket.java similarity index 80% rename from src/main/java/com/simibubi/create/content/curiosities/zapper/ConfigureZapperPacket.java rename to src/main/java/com/simibubi/create/content/equipment/zapper/ConfigureZapperPacket.java index 99c842730..6b90d8b2c 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/ConfigureZapperPacket.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/ConfigureZapperPacket.java @@ -1,6 +1,4 @@ -package com.simibubi.create.content.curiosities.zapper; - -import java.util.function.Supplier; +package com.simibubi.create.content.equipment.zapper; import com.simibubi.create.foundation.networking.SimplePacketBase; @@ -32,9 +30,9 @@ public abstract class ConfigureZapperPacket extends SimplePacketBase { } @Override - public void handle(Supplier context) { - context.get().enqueueWork(() -> { - ServerPlayer player = context.get().getSender(); + public boolean handle(Context context) { + context.enqueueWork(() -> { + ServerPlayer player = context.getSender(); if (player == null) { return; } @@ -43,7 +41,7 @@ public abstract class ConfigureZapperPacket extends SimplePacketBase { configureZapper(stack); } }); - context.get().setPacketHandled(true); + return true; } public abstract void configureZapper(ItemStack stack); diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/PlacementPatterns.java b/src/main/java/com/simibubi/create/content/equipment/zapper/PlacementPatterns.java similarity index 96% rename from src/main/java/com/simibubi/create/content/curiosities/zapper/PlacementPatterns.java rename to src/main/java/com/simibubi/create/content/equipment/zapper/PlacementPatterns.java index e50492867..4391b0769 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/PlacementPatterns.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/PlacementPatterns.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.zapper; +package com.simibubi.create.content.equipment.zapper; import java.util.List; import java.util.Random; diff --git a/src/main/java/com/simibubi/create/content/equipment/zapper/ShootGadgetPacket.java b/src/main/java/com/simibubi/create/content/equipment/zapper/ShootGadgetPacket.java new file mode 100644 index 000000000..8b624b98a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/ShootGadgetPacket.java @@ -0,0 +1,74 @@ +package com.simibubi.create.content.equipment.zapper; + +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.client.Minecraft; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.network.NetworkEvent.Context; + +public abstract class ShootGadgetPacket extends SimplePacketBase { + + public Vec3 location; + public InteractionHand hand; + public boolean self; + + public ShootGadgetPacket(Vec3 location, InteractionHand hand, boolean self) { + this.location = location; + this.hand = hand; + this.self = self; + } + + public ShootGadgetPacket(FriendlyByteBuf buffer) { + hand = buffer.readBoolean() ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND; + self = buffer.readBoolean(); + location = new Vec3(buffer.readDouble(), buffer.readDouble(), buffer.readDouble()); + readAdditional(buffer); + } + + public final void write(FriendlyByteBuf buffer) { + buffer.writeBoolean(hand == InteractionHand.MAIN_HAND); + buffer.writeBoolean(self); + buffer.writeDouble(location.x); + buffer.writeDouble(location.y); + buffer.writeDouble(location.z); + writeAdditional(buffer); + } + + protected abstract void readAdditional(FriendlyByteBuf buffer); + + protected abstract void writeAdditional(FriendlyByteBuf buffer); + + @OnlyIn(Dist.CLIENT) + protected abstract void handleAdditional(); + + @OnlyIn(Dist.CLIENT) + protected abstract ShootableGadgetRenderHandler getHandler(); + + @Override + @OnlyIn(Dist.CLIENT) + public boolean handle(Context context) { + context.enqueueWork(() -> { + Entity renderViewEntity = Minecraft.getInstance() + .getCameraEntity(); + if (renderViewEntity == null) + return; + if (renderViewEntity.position() + .distanceTo(location) > 100) + return; + + ShootableGadgetRenderHandler handler = getHandler(); + handleAdditional(); + if (self) + handler.shoot(hand, location); + else + handler.playSound(hand, location); + }); + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/ShootableGadgetItemMethods.java b/src/main/java/com/simibubi/create/content/equipment/zapper/ShootableGadgetItemMethods.java similarity index 87% rename from src/main/java/com/simibubi/create/content/curiosities/zapper/ShootableGadgetItemMethods.java rename to src/main/java/com/simibubi/create/content/equipment/zapper/ShootableGadgetItemMethods.java index 85cdf59d0..d03ff7a43 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/ShootableGadgetItemMethods.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/ShootableGadgetItemMethods.java @@ -1,9 +1,9 @@ -package com.simibubi.create.content.curiosities.zapper; +package com.simibubi.create.content.equipment.zapper; import java.util.function.Function; import java.util.function.Predicate; -import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.AllPackets; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; @@ -29,8 +29,8 @@ public class ShootableGadgetItemMethods { public static void sendPackets(Player player, Function factory) { if (!(player instanceof ServerPlayer)) return; - AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> player), factory.apply(false)); - AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), factory.apply(true)); + AllPackets.getChannel().send(PacketDistributor.TRACKING_ENTITY.with(() -> player), factory.apply(false)); + AllPackets.getChannel().send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), factory.apply(true)); } public static boolean shouldSwap(Player player, ItemStack item, InteractionHand hand, Predicate predicate) { diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/ShootableGadgetRenderHandler.java b/src/main/java/com/simibubi/create/content/equipment/zapper/ShootableGadgetRenderHandler.java similarity index 99% rename from src/main/java/com/simibubi/create/content/curiosities/zapper/ShootableGadgetRenderHandler.java rename to src/main/java/com/simibubi/create/content/equipment/zapper/ShootableGadgetRenderHandler.java index de77c23db..6fe2c13a4 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/ShootableGadgetRenderHandler.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/ShootableGadgetRenderHandler.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.zapper; +package com.simibubi.create.content.equipment.zapper; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperBeamPacket.java b/src/main/java/com/simibubi/create/content/equipment/zapper/ZapperBeamPacket.java similarity index 89% rename from src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperBeamPacket.java rename to src/main/java/com/simibubi/create/content/equipment/zapper/ZapperBeamPacket.java index 352728857..e4b79c0f0 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperBeamPacket.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/ZapperBeamPacket.java @@ -1,7 +1,7 @@ -package com.simibubi.create.content.curiosities.zapper; +package com.simibubi.create.content.equipment.zapper; import com.simibubi.create.CreateClient; -import com.simibubi.create.content.curiosities.zapper.ZapperRenderHandler.LaserBeam; +import com.simibubi.create.content.equipment.zapper.ZapperRenderHandler.LaserBeam; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.world.InteractionHand; diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperInteractionHandler.java b/src/main/java/com/simibubi/create/content/equipment/zapper/ZapperInteractionHandler.java similarity index 95% rename from src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperInteractionHandler.java rename to src/main/java/com/simibubi/create/content/equipment/zapper/ZapperInteractionHandler.java index b4be3cb80..cbccf8228 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperInteractionHandler.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/ZapperInteractionHandler.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.zapper; +package com.simibubi.create.content.equipment.zapper; import java.util.Objects; @@ -79,9 +79,9 @@ public class ZapperInteractionHandler { newState = newState.setValue(BlockStateProperties.WATERLOGGED, false); CompoundTag data = null; - BlockEntity tile = player.level.getBlockEntity(pos); - if (tile != null) { - data = tile.saveWithFullMetadata(); + BlockEntity blockEntity = player.level.getBlockEntity(pos); + if (blockEntity != null) { + data = blockEntity.saveWithFullMetadata(); data.remove("x"); data.remove("y"); data.remove("z"); diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperItem.java b/src/main/java/com/simibubi/create/content/equipment/zapper/ZapperItem.java similarity index 93% rename from src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperItem.java rename to src/main/java/com/simibubi/create/content/equipment/zapper/ZapperItem.java index 5f017ae9b..d8cf21448 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperItem.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/ZapperItem.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.zapper; +package com.simibubi.create.content.equipment.zapper; import java.util.List; @@ -10,7 +10,6 @@ import com.simibubi.create.AllSoundEvents; import com.simibubi.create.AllTags.AllBlockTags; import com.simibubi.create.CreateClient; import com.simibubi.create.foundation.item.CustomArmPoseItem; -import com.simibubi.create.foundation.item.ItemDescription; import com.simibubi.create.foundation.utility.BlockHelper; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.NBTHelper; @@ -65,10 +64,9 @@ public abstract class ZapperItem extends Item implements CustomArmPoseItem { .getCompound("BlockUsed")) .getBlock() .getName(); - ItemDescription.add(tooltip, - Lang.translateDirect("terrainzapper.usingBlock", - usedBlock.withStyle(ChatFormatting.GRAY)) - .withStyle(ChatFormatting.DARK_GRAY)); + tooltip.add(Lang.translateDirect("terrainzapper.usingBlock", + usedBlock.withStyle(ChatFormatting.GRAY)) + .withStyle(ChatFormatting.DARK_GRAY)); } } @@ -235,17 +233,17 @@ public abstract class ZapperItem extends Item implements CustomArmPoseItem { NBTHelper.writeEnum(nbt, "Pattern", pattern); } - public static void setTileData(Level world, BlockPos pos, BlockState state, CompoundTag data, Player player) { + public static void setBlockEntityData(Level world, BlockPos pos, BlockState state, CompoundTag data, Player player) { if (data != null && AllBlockTags.SAFE_NBT.matches(state)) { - BlockEntity tile = world.getBlockEntity(pos); - if (tile != null) { - data = NBTProcessors.process(tile, data, !player.isCreative()); + BlockEntity blockEntity = world.getBlockEntity(pos); + if (blockEntity != null) { + data = NBTProcessors.process(blockEntity, data, !player.isCreative()); if (data == null) return; data.putInt("x", pos.getX()); data.putInt("y", pos.getY()); data.putInt("z", pos.getZ()); - tile.load(data); + blockEntity.load(data); } } } diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperItemRenderer.java b/src/main/java/com/simibubi/create/content/equipment/zapper/ZapperItemRenderer.java similarity index 88% rename from src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperItemRenderer.java rename to src/main/java/com/simibubi/create/content/equipment/zapper/ZapperItemRenderer.java index 9f8a1f475..a77d87407 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperItemRenderer.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/ZapperItemRenderer.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.zapper; +package com.simibubi.create.content.equipment.zapper; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.CreateClient; @@ -17,10 +17,10 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.CrossCollisionBlock; import net.minecraft.world.level.block.state.BlockState; -public abstract class ZapperItemRenderer extends CustomRenderedItemModelRenderer { +public abstract class ZapperItemRenderer extends CustomRenderedItemModelRenderer { @Override - protected void render(ItemStack stack, M model, PartialItemModelRenderer renderer, TransformType transformType, + protected void render(ItemStack stack, CustomRenderedItemModel model, PartialItemModelRenderer renderer, TransformType transformType, PoseStack ms, MultiBufferSource buffer, int light, int overlay) { // Block indicator if (transformType == TransformType.GUI && stack.hasTag() && stack.getTag() diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperLog.java b/src/main/java/com/simibubi/create/content/equipment/zapper/ZapperLog.java similarity index 89% rename from src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperLog.java rename to src/main/java/com/simibubi/create/content/equipment/zapper/ZapperLog.java index ac17c5c19..d5d5fa88c 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperLog.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/ZapperLog.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.zapper; +package com.simibubi.create.content.equipment.zapper; import java.util.LinkedList; import java.util.List; @@ -35,8 +35,8 @@ public class ZapperLog { activeWorld = world; List blocks = positions.stream().map(pos -> { - BlockEntity tileEntity = world.getBlockEntity(pos); - return new StructureBlockInfo(pos, world.getBlockState(pos), tileEntity == null ? null : tileEntity.saveWithFullMetadata()); + BlockEntity blockEntity = world.getBlockEntity(pos); + return new StructureBlockInfo(pos, world.getBlockState(pos), blockEntity == null ? null : blockEntity.saveWithFullMetadata()); }).collect(Collectors.toList()); log.add(0, blocks); diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperRenderHandler.java b/src/main/java/com/simibubi/create/content/equipment/zapper/ZapperRenderHandler.java similarity index 97% rename from src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperRenderHandler.java rename to src/main/java/com/simibubi/create/content/equipment/zapper/ZapperRenderHandler.java index 9c3bb83ab..cd32e71c6 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperRenderHandler.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/ZapperRenderHandler.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.zapper; +package com.simibubi.create.content.equipment.zapper; import java.util.LinkedList; import java.util.List; @@ -39,7 +39,7 @@ public class ZapperRenderHandler extends ShootableGadgetRenderHandler { cachedBeams.forEach(beam -> { CreateClient.OUTLINER.endChasingLine(beam, beam.start, beam.end, 1 - beam.itensity, false) - .disableNormals() + .disableLineNormals() .colored(0xffffff) .lineWidth(beam.itensity * 1 / 8f); }); diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperScreen.java b/src/main/java/com/simibubi/create/content/equipment/zapper/ZapperScreen.java similarity index 96% rename from src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperScreen.java rename to src/main/java/com/simibubi/create/content/equipment/zapper/ZapperScreen.java index ff13166c9..ae5d03e9d 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperScreen.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/ZapperScreen.java @@ -1,15 +1,15 @@ -package com.simibubi.create.content.curiosities.zapper; +package com.simibubi.create.content.equipment.zapper; import java.util.Vector; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Axis; +import com.simibubi.create.AllPackets; import com.simibubi.create.foundation.gui.AbstractSimiScreen; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.gui.element.GuiGameElement; import com.simibubi.create.foundation.gui.widget.IconButton; -import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.NBTHelper; @@ -118,7 +118,7 @@ public abstract class ZapperScreen extends AbstractSimiScreen { public void removed() { ConfigureZapperPacket packet = getConfigurationPacket(); packet.configureZapper(zapper); - AllPackets.channel.sendToServer(packet); + AllPackets.getChannel().sendToServer(packet); } protected void renderZapper(PoseStack ms, int x, int y) { diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/Brush.java b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/Brush.java similarity index 95% rename from src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/Brush.java rename to src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/Brush.java index 4b1123d17..a015a02b5 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/Brush.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/Brush.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.zapper.terrainzapper; +package com.simibubi.create.content.equipment.zapper.terrainzapper; import java.util.Collection; diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/ConfigureWorldshaperPacket.java b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/ConfigureWorldshaperPacket.java similarity index 87% rename from src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/ConfigureWorldshaperPacket.java rename to src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/ConfigureWorldshaperPacket.java index 43931770d..4830a0ee5 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/ConfigureWorldshaperPacket.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/ConfigureWorldshaperPacket.java @@ -1,7 +1,7 @@ -package com.simibubi.create.content.curiosities.zapper.terrainzapper; +package com.simibubi.create.content.equipment.zapper.terrainzapper; -import com.simibubi.create.content.curiosities.zapper.ConfigureZapperPacket; -import com.simibubi.create.content.curiosities.zapper.PlacementPatterns; +import com.simibubi.create.content.equipment.zapper.ConfigureZapperPacket; +import com.simibubi.create.content.equipment.zapper.PlacementPatterns; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.world.InteractionHand; diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/CuboidBrush.java b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/CuboidBrush.java similarity index 96% rename from src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/CuboidBrush.java rename to src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/CuboidBrush.java index eb9b246bc..9374530cf 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/CuboidBrush.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/CuboidBrush.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.zapper.terrainzapper; +package com.simibubi.create.content.equipment.zapper.terrainzapper; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/CylinderBrush.java b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/CylinderBrush.java similarity index 97% rename from src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/CylinderBrush.java rename to src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/CylinderBrush.java index e468a11f5..8afb01d7a 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/CylinderBrush.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/CylinderBrush.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.zapper.terrainzapper; +package com.simibubi.create.content.equipment.zapper.terrainzapper; import java.util.ArrayList; import java.util.HashMap; diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/DynamicBrush.java b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/DynamicBrush.java similarity index 98% rename from src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/DynamicBrush.java rename to src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/DynamicBrush.java index 976376488..a2f81cab5 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/DynamicBrush.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/DynamicBrush.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.zapper.terrainzapper; +package com.simibubi.create.content.equipment.zapper.terrainzapper; import java.util.Collection; import java.util.HashSet; diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/FlattenTool.java b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/FlattenTool.java similarity index 98% rename from src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/FlattenTool.java rename to src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/FlattenTool.java index 1c16a03f9..fb2243f0a 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/FlattenTool.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/FlattenTool.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.zapper.terrainzapper; +package com.simibubi.create.content.equipment.zapper.terrainzapper; import java.util.ArrayList; import java.util.HashMap; diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/PlacementOptions.java b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/PlacementOptions.java similarity index 85% rename from src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/PlacementOptions.java rename to src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/PlacementOptions.java index 9861b2505..840327a95 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/PlacementOptions.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/PlacementOptions.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.zapper.terrainzapper; +package com.simibubi.create.content.equipment.zapper.terrainzapper; import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.utility.Lang; diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/ShapedBrush.java b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/ShapedBrush.java similarity index 91% rename from src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/ShapedBrush.java rename to src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/ShapedBrush.java index f26117ef7..4e6b074ac 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/ShapedBrush.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/ShapedBrush.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.zapper.terrainzapper; +package com.simibubi.create.content.equipment.zapper.terrainzapper; import java.util.Collection; import java.util.List; diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/SphereBrush.java b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/SphereBrush.java similarity index 95% rename from src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/SphereBrush.java rename to src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/SphereBrush.java index 4fcfa3b9e..91b859a16 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/SphereBrush.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/SphereBrush.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.zapper.terrainzapper; +package com.simibubi.create.content.equipment.zapper.terrainzapper; import java.util.HashMap; import java.util.List; diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/TerrainBrushes.java b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/TerrainBrushes.java similarity index 82% rename from src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/TerrainBrushes.java rename to src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/TerrainBrushes.java index fa11468b6..11b4a1719 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/TerrainBrushes.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/TerrainBrushes.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.zapper.terrainzapper; +package com.simibubi.create.content.equipment.zapper.terrainzapper; public enum TerrainBrushes { diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/TerrainTools.java b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/TerrainTools.java similarity index 84% rename from src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/TerrainTools.java rename to src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/TerrainTools.java index 79e6fe2be..b8014073d 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/TerrainTools.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/TerrainTools.java @@ -1,10 +1,10 @@ -package com.simibubi.create.content.curiosities.zapper.terrainzapper; +package com.simibubi.create.content.equipment.zapper.terrainzapper; import java.util.List; import javax.annotation.Nullable; -import com.simibubi.create.content.curiosities.zapper.ZapperItem; +import com.simibubi.create.content.equipment.zapper.ZapperItem; import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.utility.Lang; @@ -50,7 +50,7 @@ public enum TerrainTools { if (!isReplaceable(toReplace)) return; world.setBlockAndUpdate(p, paintedState); - ZapperItem.setTileData(world, p, paintedState, data, player); + ZapperItem.setBlockEntityData(world, p, paintedState, data, player); }); break; case Flatten: @@ -70,13 +70,13 @@ public enum TerrainTools { if (!isReplaceable(toReplace)) return; world.setBlockAndUpdate(p, paintedState); - ZapperItem.setTileData(world, p, paintedState, data, player); + ZapperItem.setBlockEntityData(world, p, paintedState, data, player); }); break; case Place: targetPositions.forEach(p -> { world.setBlockAndUpdate(p, paintedState); - ZapperItem.setTileData(world, p, paintedState, data, player); + ZapperItem.setBlockEntityData(world, p, paintedState, data, player); }); break; case Replace: @@ -85,7 +85,7 @@ public enum TerrainTools { if (isReplaceable(toReplace)) return; world.setBlockAndUpdate(p, paintedState); - ZapperItem.setTileData(world, p, paintedState, data, player); + ZapperItem.setBlockEntityData(world, p, paintedState, data, player); }); break; } diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperItem.java b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/WorldshaperItem.java similarity index 94% rename from src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperItem.java rename to src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/WorldshaperItem.java index 067839b23..57442b3fe 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperItem.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/WorldshaperItem.java @@ -1,11 +1,11 @@ -package com.simibubi.create.content.curiosities.zapper.terrainzapper; +package com.simibubi.create.content.equipment.zapper.terrainzapper; import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; -import com.simibubi.create.content.curiosities.zapper.PlacementPatterns; -import com.simibubi.create.content.curiosities.zapper.ZapperItem; +import com.simibubi.create.content.equipment.zapper.PlacementPatterns; +import com.simibubi.create.content.equipment.zapper.ZapperItem; import com.simibubi.create.foundation.gui.ScreenOpener; import com.simibubi.create.foundation.item.render.SimpleCustomRenderer; import com.simibubi.create.foundation.utility.Lang; diff --git a/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/WorldshaperItemRenderer.java b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/WorldshaperItemRenderer.java new file mode 100644 index 000000000..f68d51435 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/WorldshaperItemRenderer.java @@ -0,0 +1,70 @@ +package com.simibubi.create.content.equipment.zapper.terrainzapper; + +import static java.lang.Math.max; + +import com.jozufozu.flywheel.core.PartialModel; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Axis; +import com.simibubi.create.Create; +import com.simibubi.create.content.equipment.zapper.ZapperItemRenderer; +import com.simibubi.create.foundation.item.render.CustomRenderedItemModel; +import com.simibubi.create.foundation.item.render.PartialItemModelRenderer; +import com.simibubi.create.foundation.utility.AnimationTickHolder; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.block.model.ItemTransforms; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.HumanoidArm; +import net.minecraft.world.item.ItemStack; + +public class WorldshaperItemRenderer extends ZapperItemRenderer { + + protected static final PartialModel CORE = new PartialModel(Create.asResource("item/handheld_worldshaper/core")); + protected static final PartialModel CORE_GLOW = new PartialModel(Create.asResource("item/handheld_worldshaper/core_glow")); + protected static final PartialModel ACCELERATOR = new PartialModel(Create.asResource("item/handheld_worldshaper/accelerator")); + + @Override + protected void render(ItemStack stack, CustomRenderedItemModel model, PartialItemModelRenderer renderer, ItemTransforms.TransformType transformType, + PoseStack ms, MultiBufferSource buffer, int light, int overlay) { + super.render(stack, model, renderer, transformType, ms, buffer, light, overlay); + + float pt = AnimationTickHolder.getPartialTicks(); + float worldTime = AnimationTickHolder.getRenderTime() / 20; + + renderer.renderSolid(model.getOriginalModel(), light); + + LocalPlayer player = Minecraft.getInstance().player; + boolean leftHanded = player.getMainArm() == HumanoidArm.LEFT; + boolean mainHand = player.getMainHandItem() == stack; + boolean offHand = player.getOffhandItem() == stack; + float animation = getAnimationProgress(pt, leftHanded, mainHand); + + // Core glows + float multiplier; + if (mainHand || offHand) + multiplier = animation; + else + multiplier = Mth.sin(worldTime * 5); + + int lightItensity = (int) (15 * Mth.clamp(multiplier, 0, 1)); + int glowLight = LightTexture.pack(lightItensity, max(lightItensity, 4)); + renderer.renderSolidGlowing(CORE.get(), glowLight); + renderer.renderGlowing(CORE_GLOW.get(), glowLight); + + // Accelerator spins + float angle = worldTime * -25; + if (mainHand || offHand) + angle += 360 * animation; + + angle %= 360; + float offset = -.155f; + ms.translate(0, offset, 0); + ms.mulPose(Axis.ZP.rotationDegrees(angle)); + ms.translate(0, -offset, 0); + renderer.render(ACCELERATOR.get(), light); + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperRenderHandler.java b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/WorldshaperRenderHandler.java similarity index 97% rename from src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperRenderHandler.java rename to src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/WorldshaperRenderHandler.java index b5e8ed028..8d8ef054d 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperRenderHandler.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/WorldshaperRenderHandler.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities.zapper.terrainzapper; +package com.simibubi.create.content.equipment.zapper.terrainzapper; import java.util.ArrayList; import java.util.Collection; @@ -33,7 +33,7 @@ public class WorldshaperRenderHandler { CreateClient.OUTLINER.showCluster("terrainZapper", renderedPositions.get()) .colored(0xbfbfbf) - .disableNormals() + .disableLineNormals() .lineWidth(1 / 32f) .withFaceTexture(AllSpecialTextures.CHECKERED); } diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperScreen.java b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/WorldshaperScreen.java similarity index 97% rename from src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperScreen.java rename to src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/WorldshaperScreen.java index 68eb0275b..fcf18f93f 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperScreen.java +++ b/src/main/java/com/simibubi/create/content/equipment/zapper/terrainzapper/WorldshaperScreen.java @@ -1,11 +1,11 @@ -package com.simibubi.create.content.curiosities.zapper.terrainzapper; +package com.simibubi.create.content.equipment.zapper.terrainzapper; import java.util.List; import java.util.Vector; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.content.curiosities.zapper.ConfigureZapperPacket; -import com.simibubi.create.content.curiosities.zapper.ZapperScreen; +import com.simibubi.create.content.equipment.zapper.ConfigureZapperPacket; +import com.simibubi.create.content.equipment.zapper.ZapperScreen; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.gui.widget.IconButton; diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/FlowSource.java b/src/main/java/com/simibubi/create/content/fluids/FlowSource.java similarity index 86% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/FlowSource.java rename to src/main/java/com/simibubi/create/content/fluids/FlowSource.java index 8a2455275..5f3e94212 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/FlowSource.java +++ b/src/main/java/com/simibubi/create/content/fluids/FlowSource.java @@ -1,9 +1,9 @@ -package com.simibubi.create.content.contraptions.fluids; +package com.simibubi.create.content.fluids; import java.lang.ref.WeakReference; import java.util.function.Predicate; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.utility.BlockFace; import net.minecraft.world.level.Level; @@ -70,9 +70,9 @@ public abstract class FlowSource { public void manageSource(Level world) { if (fluidHandler.isPresent() && world.getGameTime() % 20 != 0) return; - BlockEntity tileEntity = world.getBlockEntity(location.getConnectedPos()); - if (tileEntity != null) - fluidHandler = tileEntity.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, + BlockEntity blockEntity = world.getBlockEntity(location.getConnectedPos()); + if (blockEntity != null) + fluidHandler = blockEntity.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, location.getOppositeFace()); } @@ -96,11 +96,11 @@ public abstract class FlowSource { @Override public void manageSource(Level world) { - if (cached != null && cached.get() != null && !cached.get().tileEntity.isRemoved()) + if (cached != null && cached.get() != null && !cached.get().blockEntity.isRemoved()) return; cached = null; FluidTransportBehaviour fluidTransportBehaviour = - TileEntityBehaviour.get(world, location.getConnectedPos(), FluidTransportBehaviour.TYPE); + BlockEntityBehaviour.get(world, location.getConnectedPos(), FluidTransportBehaviour.TYPE); if (fluidTransportBehaviour != null) cached = new WeakReference<>(fluidTransportBehaviour); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidBottleItemHook.java b/src/main/java/com/simibubi/create/content/fluids/FluidBottleItemHook.java similarity index 93% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/FluidBottleItemHook.java rename to src/main/java/com/simibubi/create/content/fluids/FluidBottleItemHook.java index 035b715bc..c6074eccd 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidBottleItemHook.java +++ b/src/main/java/com/simibubi/create/content/fluids/FluidBottleItemHook.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.fluids; +package com.simibubi.create.content.fluids; import com.simibubi.create.Create; import com.simibubi.create.foundation.utility.RegisteredObjects; @@ -22,8 +22,8 @@ import net.minecraftforge.fml.common.Mod.EventBusSubscriber; @EventBusSubscriber public class FluidBottleItemHook extends Item { - public FluidBottleItemHook(Properties p_i48487_1_) { - super(p_i48487_1_); + private FluidBottleItemHook(Properties p) { + super(p); } @SubscribeEvent diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidFX.java b/src/main/java/com/simibubi/create/content/fluids/FluidFX.java similarity index 96% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/FluidFX.java rename to src/main/java/com/simibubi/create/content/fluids/FluidFX.java index e58f0ad1a..f91f54b14 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidFX.java +++ b/src/main/java/com/simibubi/create/content/fluids/FluidFX.java @@ -1,7 +1,7 @@ -package com.simibubi.create.content.contraptions.fluids; +package com.simibubi.create.content.fluids; import com.simibubi.create.AllParticleTypes; -import com.simibubi.create.content.contraptions.fluids.particle.FluidParticleData; +import com.simibubi.create.content.fluids.particle.FluidParticleData; import com.simibubi.create.foundation.fluid.FluidHelper; import com.simibubi.create.foundation.utility.VecHelper; diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidNetwork.java b/src/main/java/com/simibubi/create/content/fluids/FluidNetwork.java similarity index 95% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/FluidNetwork.java rename to src/main/java/com/simibubi/create/content/fluids/FluidNetwork.java index eeaf6000d..e012b8119 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidNetwork.java +++ b/src/main/java/com/simibubi/create/content/fluids/FluidNetwork.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.fluids; +package com.simibubi.create.content.fluids; import java.lang.ref.WeakReference; import java.util.ArrayList; @@ -13,10 +13,10 @@ import java.util.function.Supplier; import javax.annotation.Nullable; -import com.simibubi.create.content.contraptions.components.actors.PortableFluidInterfaceTileEntity.InterfaceFluidHandler; -import com.simibubi.create.content.contraptions.fluids.PipeConnection.Flow; +import com.simibubi.create.content.contraptions.actors.psi.PortableFluidInterfaceBlockEntity.InterfaceFluidHandler; +import com.simibubi.create.content.fluids.PipeConnection.Flow; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.fluid.FluidHelper; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.utility.BlockFace; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Pair; @@ -314,10 +314,10 @@ public class FluidNetwork { private FluidTransportBehaviour getFluidTransfer(BlockPos pos) { WeakReference weakReference = cache.get(pos); FluidTransportBehaviour behaviour = weakReference != null ? weakReference.get() : null; - if (behaviour != null && behaviour.tileEntity.isRemoved()) + if (behaviour != null && behaviour.blockEntity.isRemoved()) behaviour = null; if (behaviour == null) { - behaviour = TileEntityBehaviour.get(world, pos, FluidTransportBehaviour.TYPE); + behaviour = BlockEntityBehaviour.get(world, pos, FluidTransportBehaviour.TYPE); if (behaviour != null) cache.put(pos, new WeakReference<>(behaviour)); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidPropagator.java b/src/main/java/com/simibubi/create/content/fluids/FluidPropagator.java similarity index 86% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/FluidPropagator.java rename to src/main/java/com/simibubi/create/content/fluids/FluidPropagator.java index 0ac0e4274..bad5e0007 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidPropagator.java +++ b/src/main/java/com/simibubi/create/content/fluids/FluidPropagator.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.fluids; +package com.simibubi.create.content.fluids; import java.util.ArrayList; import java.util.HashSet; @@ -9,17 +9,19 @@ import javax.annotation.Nullable; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllTags.AllBlockTags; -import com.simibubi.create.content.contraptions.fluids.PipeConnection.Flow; -import com.simibubi.create.content.contraptions.fluids.pipes.AxisPipeBlock; -import com.simibubi.create.content.contraptions.fluids.pipes.FluidPipeBlock; -import com.simibubi.create.content.contraptions.fluids.pipes.VanillaFluidTargets; +import com.simibubi.create.content.fluids.PipeConnection.Flow; +import com.simibubi.create.content.fluids.pipes.AxisPipeBlock; +import com.simibubi.create.content.fluids.pipes.FluidPipeBlock; +import com.simibubi.create.content.fluids.pipes.VanillaFluidTargets; +import com.simibubi.create.content.fluids.pump.PumpBlock; +import com.simibubi.create.content.fluids.pump.PumpBlockEntity; import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.advancement.CreateAdvancement; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.utility.BlockHelper; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Pair; +import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -47,7 +49,7 @@ public class FluidPropagator { public static void propagateChangedPipe(LevelAccessor world, BlockPos pipePos, BlockState pipeState) { List> frontier = new ArrayList<>(); Set visited = new HashSet<>(); - Set> discoveredPumps = new HashSet<>(); + Set> discoveredPumps = new HashSet<>(); frontier.add(Pair.of(0, pipePos)); @@ -69,13 +71,13 @@ public class FluidPropagator { if (world instanceof Level l && !l.isLoaded(target)) continue; - BlockEntity tileEntity = world.getBlockEntity(target); + BlockEntity blockEntity = world.getBlockEntity(target); BlockState targetState = world.getBlockState(target); - if (tileEntity instanceof PumpTileEntity) { + if (blockEntity instanceof PumpBlockEntity) { if (!AllBlocks.MECHANICAL_PUMP.has(targetState) || targetState.getValue(PumpBlock.FACING) .getAxis() != direction.getAxis()) continue; - discoveredPumps.add(Pair.of((PumpTileEntity) tileEntity, direction.getOpposite())); + discoveredPumps.add(Pair.of((PumpBlockEntity) blockEntity, direction.getOpposite())); continue; } if (visited.contains(target)) @@ -160,7 +162,7 @@ public class FluidPropagator { } public static FluidTransportBehaviour getPipe(BlockGetter reader, BlockPos pos) { - return TileEntityBehaviour.get(reader, pos, FluidTransportBehaviour.TYPE); + return BlockEntityBehaviour.get(reader, pos, FluidTransportBehaviour.TYPE); } public static boolean isOpenEnd(BlockGetter reader, BlockPos pos, Direction side) { @@ -195,15 +197,15 @@ public class FluidPropagator { } public static int getPumpRange() { - return AllConfigs.SERVER.fluids.mechanicalPumpRange.get(); + return AllConfigs.server().fluids.mechanicalPumpRange.get(); } public static boolean hasFluidCapability(BlockGetter world, BlockPos pos, Direction side) { - BlockEntity tileEntity = world.getBlockEntity(pos); - if (tileEntity == null) + BlockEntity blockEntity = world.getBlockEntity(pos); + if (blockEntity == null) return false; LazyOptional capability = - tileEntity.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, side); + blockEntity.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, side); return capability.isPresent(); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidReactions.java b/src/main/java/com/simibubi/create/content/fluids/FluidReactions.java similarity index 98% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/FluidReactions.java rename to src/main/java/com/simibubi/create/content/fluids/FluidReactions.java index 60f93a592..254e3476d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidReactions.java +++ b/src/main/java/com/simibubi/create/content/fluids/FluidReactions.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.fluids; +package com.simibubi.create.content.fluids; import com.simibubi.create.AllFluids; import com.simibubi.create.foundation.advancement.AdvancementBehaviour; diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidTransportBehaviour.java b/src/main/java/com/simibubi/create/content/fluids/FluidTransportBehaviour.java similarity index 86% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/FluidTransportBehaviour.java rename to src/main/java/com/simibubi/create/content/fluids/FluidTransportBehaviour.java index 87a6eef0f..bcd2f64df 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidTransportBehaviour.java +++ b/src/main/java/com/simibubi/create/content/fluids/FluidTransportBehaviour.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.fluids; +package com.simibubi.create.content.fluids; import java.util.Collection; import java.util.HashMap; @@ -9,10 +9,11 @@ import java.util.function.Predicate; import javax.annotation.Nullable; import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.fluids.pipes.EncasedPipeBlock; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType; +import com.simibubi.create.content.fluids.pipes.EncasedPipeBlock; +import com.simibubi.create.content.fluids.pump.PumpBlock; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.WorldAttached; @@ -25,7 +26,7 @@ import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.state.BlockState; import net.minecraftforge.fluids.FluidStack; -public abstract class FluidTransportBehaviour extends TileEntityBehaviour { +public abstract class FluidTransportBehaviour extends BlockEntityBehaviour { public static final BehaviourType TYPE = new BehaviourType<>(); @@ -38,8 +39,8 @@ public abstract class FluidTransportBehaviour extends TileEntityBehaviour { public Map interfaces; public UpdatePhase phase; - public FluidTransportBehaviour(SmartTileEntity te) { - super(te); + public FluidTransportBehaviour(SmartBlockEntity be) { + super(be); phase = UpdatePhase.WAIT_FOR_PUMPS; } @@ -60,7 +61,7 @@ public abstract class FluidTransportBehaviour extends TileEntityBehaviour { super.tick(); Level world = getWorld(); BlockPos pos = getPos(); - boolean onServer = !world.isClientSide || tileEntity.isVirtual(); + boolean onServer = !world.isClientSide || blockEntity.isVirtual(); if (interfaces == null) return; @@ -88,7 +89,7 @@ public abstract class FluidTransportBehaviour extends TileEntityBehaviour { connection.manageSource(world, pos); } if (sendUpdate) - tileEntity.notifyUpdate(); + blockEntity.notifyUpdate(); } if (phase == UpdatePhase.FLIP_FLOWS) { @@ -127,12 +128,12 @@ public abstract class FluidTransportBehaviour extends TileEntityBehaviour { for (PipeConnection connection : connections) { FluidStack internalFluid = singleSource != connection ? availableFlow : FluidStack.EMPTY; Predicate extractionPredicate = - extracted -> canPullFluidFrom(extracted, tileEntity.getBlockState(), connection.side); + extracted -> canPullFluidFrom(extracted, blockEntity.getBlockState(), connection.side); sendUpdate |= connection.manageFlows(world, pos, internalFluid, extractionPredicate); } if (sendUpdate) - tileEntity.notifyUpdate(); + blockEntity.notifyUpdate(); } for (PipeConnection connection : connections) @@ -155,7 +156,7 @@ public abstract class FluidTransportBehaviour extends TileEntityBehaviour { } interfaces.values() - .forEach(connection -> connection.deserializeNBT(nbt, tileEntity.getBlockPos(), clientPacket)); + .forEach(connection -> connection.deserializeNBT(nbt, blockEntity.getBlockPos(), clientPacket)); } @Override @@ -206,13 +207,13 @@ public abstract class FluidTransportBehaviour extends TileEntityBehaviour { return; interfaces.get(side) .addPressure(inbound, pressure); - tileEntity.sendData(); + blockEntity.sendData(); } public void wipePressure() { if (interfaces != null) for (Direction d : Iterate.directions) { - if (!canHaveFlowToward(tileEntity.getBlockState(), d)) + if (!canHaveFlowToward(blockEntity.getBlockState(), d)) interfaces.remove(d); else interfaces.computeIfAbsent(d, PipeConnection::new); @@ -221,7 +222,7 @@ public abstract class FluidTransportBehaviour extends TileEntityBehaviour { createConnectionData(); interfaces.values() .forEach(PipeConnection::wipePressure); - tileEntity.sendData(); + blockEntity.sendData(); } private void createConnectionData() { @@ -229,7 +230,7 @@ public abstract class FluidTransportBehaviour extends TileEntityBehaviour { return; interfaces = new IdentityHashMap<>(); for (Direction d : Iterate.directions) - if (canHaveFlowToward(tileEntity.getBlockState(), d)) + if (canHaveFlowToward(blockEntity.getBlockState(), d)) interfaces.put(d, new PipeConnection(d)); } @@ -294,14 +295,14 @@ public abstract class FluidTransportBehaviour extends TileEntityBehaviour { new WorldAttached<>($ -> new HashMap<>()); public static void cacheFlows(LevelAccessor world, BlockPos pos) { - FluidTransportBehaviour pipe = TileEntityBehaviour.get(world, pos, FluidTransportBehaviour.TYPE); + FluidTransportBehaviour pipe = BlockEntityBehaviour.get(world, pos, FluidTransportBehaviour.TYPE); if (pipe != null) interfaceTransfer.get(world) .put(pos, pipe.interfaces); } public static void loadFlows(LevelAccessor world, BlockPos pos) { - FluidTransportBehaviour newPipe = TileEntityBehaviour.get(world, pos, FluidTransportBehaviour.TYPE); + FluidTransportBehaviour newPipe = BlockEntityBehaviour.get(world, pos, FluidTransportBehaviour.TYPE); if (newPipe != null) newPipe.interfaces = interfaceTransfer.get(world) .remove(pos); diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/OpenEndedPipe.java b/src/main/java/com/simibubi/create/content/fluids/OpenEndedPipe.java similarity index 91% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/OpenEndedPipe.java rename to src/main/java/com/simibubi/create/content/fluids/OpenEndedPipe.java index bc4059b73..d2bea4eb2 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/OpenEndedPipe.java +++ b/src/main/java/com/simibubi/create/content/fluids/OpenEndedPipe.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.fluids; +package com.simibubi.create.content.fluids; import static net.minecraft.world.level.block.state.properties.BlockStateProperties.WATERLOGGED; @@ -8,13 +8,13 @@ import java.util.List; import javax.annotation.Nullable; import com.simibubi.create.AllFluids; -import com.simibubi.create.content.contraptions.fluids.pipes.VanillaFluidTargets; -import com.simibubi.create.content.contraptions.fluids.potion.PotionFluidHandler; +import com.simibubi.create.content.fluids.pipes.VanillaFluidTargets; +import com.simibubi.create.content.fluids.potion.PotionFluidHandler; import com.simibubi.create.foundation.advancement.AdvancementBehaviour; import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.fluid.FluidHelper; import com.simibubi.create.foundation.utility.BlockFace; +import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -25,6 +25,7 @@ import net.minecraft.tags.BlockTags; import net.minecraft.tags.FluidTags; import net.minecraft.world.effect.MobEffect; import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ItemStack; @@ -54,6 +55,7 @@ public class OpenEndedPipe extends FlowSource { registerEffectHandler(new MilkEffectHandler()); registerEffectHandler(new WaterEffectHandler()); registerEffectHandler(new LavaEffectHandler()); + registerEffectHandler(new TeaEffectHandler()); } private Level world; @@ -120,9 +122,9 @@ public class OpenEndedPipe extends FlowSource { return compound; } - public static OpenEndedPipe fromNBT(CompoundTag compound, BlockPos tilePos) { + public static OpenEndedPipe fromNBT(CompoundTag compound, BlockPos blockEntityPos) { BlockFace fromNBT = BlockFace.fromNBT(compound.getCompound("Location")); - OpenEndedPipe oep = new OpenEndedPipe(new BlockFace(tilePos, fromNBT.getFace())); + OpenEndedPipe oep = new OpenEndedPipe(new BlockFace(blockEntityPos, fromNBT.getFace())); oep.fluidHandler.readFromNBT(compound); oep.wasPulling = compound.getBoolean("Pulling"); return oep; @@ -217,7 +219,7 @@ public class OpenEndedPipe extends FlowSource { return true; } - if (!AllConfigs.SERVER.fluids.placeFluidSourceBlocks.get()) + if (!AllConfigs.server().fluids.placeFluidSourceBlocks.get()) return true; world.setBlock(outputPos, fluid.getFluid() @@ -443,4 +445,23 @@ public class OpenEndedPipe extends FlowSource { } } + public static class TeaEffectHandler implements IEffectHandler { + @Override + public boolean canApplyEffects(OpenEndedPipe pipe, FluidStack fluid) { + return fluid.getFluid().isSame(AllFluids.TEA.get()); + } + + @Override + public void applyEffects(OpenEndedPipe pipe, FluidStack fluid) { + Level world = pipe.getWorld(); + if (world.getGameTime() % 5 != 0) + return; + List entities = world + .getEntitiesOfClass(LivingEntity.class, pipe.getAOE(), LivingEntity::isAffectedByPotions); + for (LivingEntity entity : entities) { + entity.addEffect(new MobEffectInstance(MobEffects.DIG_SPEED, 21, 0, false, false, false)); + } + } + } + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/PipeAttachmentModel.java b/src/main/java/com/simibubi/create/content/fluids/PipeAttachmentModel.java similarity index 77% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/PipeAttachmentModel.java rename to src/main/java/com/simibubi/create/content/fluids/PipeAttachmentModel.java index 0d3cd94fb..b2da9549f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/PipeAttachmentModel.java +++ b/src/main/java/com/simibubi/create/content/fluids/PipeAttachmentModel.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.fluids; +package com.simibubi.create.content.fluids; import java.util.ArrayList; import java.util.Arrays; @@ -6,13 +6,13 @@ import java.util.List; import org.jetbrains.annotations.NotNull; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.fluids.FluidTransportBehaviour.AttachmentTypes; -import com.simibubi.create.content.contraptions.fluids.FluidTransportBehaviour.AttachmentTypes.ComponentPartials; -import com.simibubi.create.content.contraptions.fluids.pipes.FluidPipeBlock; -import com.simibubi.create.content.contraptions.relays.elementary.BracketedTileEntityBehaviour; -import com.simibubi.create.foundation.block.connected.BakedModelWrapperWithData; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.decoration.bracket.BracketedBlockEntityBehaviour; +import com.simibubi.create.content.fluids.FluidTransportBehaviour.AttachmentTypes; +import com.simibubi.create.content.fluids.FluidTransportBehaviour.AttachmentTypes.ComponentPartials; +import com.simibubi.create.content.fluids.pipes.FluidPipeBlock; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.model.BakedModelWrapperWithData; import com.simibubi.create.foundation.utility.Iterate; import net.minecraft.client.Minecraft; @@ -39,10 +39,11 @@ public class PipeAttachmentModel extends BakedModelWrapperWithData { } @Override - protected Builder gatherModelData(Builder builder, BlockAndTintGetter world, BlockPos pos, BlockState state) { + protected ModelData.Builder gatherModelData(Builder builder, BlockAndTintGetter world, BlockPos pos, BlockState state, + ModelData blockEntityData) { PipeModelData data = new PipeModelData(); - FluidTransportBehaviour transport = TileEntityBehaviour.get(world, pos, FluidTransportBehaviour.TYPE); - BracketedTileEntityBehaviour bracket = TileEntityBehaviour.get(world, pos, BracketedTileEntityBehaviour.TYPE); + FluidTransportBehaviour transport = BlockEntityBehaviour.get(world, pos, FluidTransportBehaviour.TYPE); + BracketedBlockEntityBehaviour bracket = BlockEntityBehaviour.get(world, pos, BracketedBlockEntityBehaviour.TYPE); if (transport != null) for (Direction d : Iterate.directions) @@ -84,14 +85,14 @@ public class PipeAttachmentModel extends BakedModelWrapperWithData { for (Direction d : Iterate.directions) { AttachmentTypes type = pipeData.getAttachment(d); for (ComponentPartials partial : type.partials) { - quads.addAll(AllBlockPartials.PIPE_ATTACHMENTS.get(partial) + quads.addAll(AllPartialModels.PIPE_ATTACHMENTS.get(partial) .get(d) .get() .getQuads(state, side, rand, data, renderType)); } } if (pipeData.isEncased()) - quads.addAll(AllBlockPartials.FLUID_PIPE_CASING.get() + quads.addAll(AllPartialModels.FLUID_PIPE_CASING.get() .getQuads(state, side, rand, data, renderType)); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/PipeConnection.java b/src/main/java/com/simibubi/create/content/fluids/PipeConnection.java similarity index 97% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/PipeConnection.java rename to src/main/java/com/simibubi/create/content/fluids/PipeConnection.java index b51f5b698..309547aa0 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/PipeConnection.java +++ b/src/main/java/com/simibubi/create/content/fluids/PipeConnection.java @@ -1,10 +1,10 @@ -package com.simibubi.create.content.contraptions.fluids; +package com.simibubi.create.content.fluids; import java.util.Optional; import java.util.Random; import java.util.function.Predicate; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.utility.BlockFace; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Iterate; @@ -179,7 +179,7 @@ public class PipeConnection { } FluidTransportBehaviour behaviour = - TileEntityBehaviour.get(world, relative, FluidTransportBehaviour.TYPE); + BlockEntityBehaviour.get(world, relative, FluidTransportBehaviour.TYPE); source = Optional.of(behaviour == null ? new FlowSource.Blocked(location) : new FlowSource.OtherPipe(location)); return true; } @@ -201,7 +201,7 @@ public class PipeConnection { particleSplashNextTick = false; } - float flowSpeed = 1 / 32f + Mth.clamp(pressure.get(flow.inbound) / 512f, 0, 1) * 31 / 32f; + float flowSpeed = 1 / 32f + Mth.clamp(pressure.get(flow.inbound) / 128f, 0, 1) * 31 / 32f; flow.progress.setValue(Math.min(flow.progress.getValue() + flowSpeed, 1)); if (flow.progress.getValue() >= 1) flow.complete = true; @@ -237,7 +237,7 @@ public class PipeConnection { return source.orElse(null) instanceof OpenEndedPipe; } - public void deserializeNBT(CompoundTag tag, BlockPos tilePos, boolean clientPacket) { + public void deserializeNBT(CompoundTag tag, BlockPos blockEntityPos, boolean clientPacket) { CompoundTag connectionData = tag.getCompound(side.getName()); if (connectionData.contains("Pressure")) { @@ -248,7 +248,7 @@ public class PipeConnection { source = Optional.empty(); if (connectionData.contains("OpenEnd")) - source = Optional.of(OpenEndedPipe.fromNBT(connectionData.getCompound("OpenEnd"), tilePos)); + source = Optional.of(OpenEndedPipe.fromNBT(connectionData.getCompound("OpenEnd"), blockEntityPos)); if (connectionData.contains("Flow")) { CompoundTag flowData = connectionData.getCompound("Flow"); @@ -308,6 +308,10 @@ public class PipeConnection { this.pressure = this.pressure.mapWithContext((f, in) -> in == inbound ? f + pressure : f); } + public Couple getPressure() { + return pressure; + } + public boolean hasPressure() { return getInboundPressure() != 0 || getOutwardPressure() != 0; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/VirtualFluid.java b/src/main/java/com/simibubi/create/content/fluids/VirtualFluid.java similarity index 94% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/VirtualFluid.java rename to src/main/java/com/simibubi/create/content/fluids/VirtualFluid.java index 890fd9071..d7c086f11 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/VirtualFluid.java +++ b/src/main/java/com/simibubi/create/content/fluids/VirtualFluid.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.fluids; +package com.simibubi.create.content.fluids; import net.minecraft.world.item.Item; import net.minecraft.world.item.Items; diff --git a/src/main/java/com/simibubi/create/content/fluids/drain/ItemDrainBlock.java b/src/main/java/com/simibubi/create/content/fluids/drain/ItemDrainBlock.java new file mode 100644 index 000000000..3ca89cfc2 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/fluids/drain/ItemDrainBlock.java @@ -0,0 +1,156 @@ +package com.simibubi.create.content.fluids.drain; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllShapes; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.content.fluids.transfer.GenericItemEmptying; +import com.simibubi.create.content.kinetics.belt.behaviour.DirectBeltInputBehaviour; +import com.simibubi.create.foundation.advancement.AdvancementBehaviour; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.blockEntity.ComparatorUtil; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.fluid.FluidHelper; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.Containers; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.BlockItem; +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.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.pathfinder.PathComputationType; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; + +public class ItemDrainBlock extends Block implements IWrenchable, IBE { + + public ItemDrainBlock(Properties p_i48440_1_) { + super(p_i48440_1_); + } + + @Override + public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, + BlockHitResult hit) { + ItemStack heldItem = player.getItemInHand(handIn); + + if (heldItem.getItem() instanceof BlockItem + && !heldItem.getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY) + .isPresent()) + return InteractionResult.PASS; + + return onBlockEntityUse(worldIn, pos, be -> { + if (!heldItem.isEmpty()) { + be.internalTank.allowInsertion(); + InteractionResult tryExchange = tryExchange(worldIn, player, handIn, heldItem, be); + be.internalTank.forbidInsertion(); + if (tryExchange.consumesAction()) + return tryExchange; + } + + ItemStack heldItemStack = be.getHeldItemStack(); + if (!worldIn.isClientSide && !heldItemStack.isEmpty()) { + player.getInventory() + .placeItemBackInInventory(heldItemStack); + be.heldItem = null; + be.notifyUpdate(); + } + return InteractionResult.SUCCESS; + }); + } + + @Override + public void updateEntityAfterFallOn(BlockGetter worldIn, Entity entityIn) { + super.updateEntityAfterFallOn(worldIn, entityIn); + if (!(entityIn instanceof ItemEntity)) + return; + if (!entityIn.isAlive()) + return; + if (entityIn.level.isClientSide) + return; + + ItemEntity itemEntity = (ItemEntity) entityIn; + DirectBeltInputBehaviour inputBehaviour = + BlockEntityBehaviour.get(worldIn, entityIn.blockPosition(), DirectBeltInputBehaviour.TYPE); + if (inputBehaviour == null) + return; + Vec3 deltaMovement = entityIn.getDeltaMovement() + .multiply(1, 0, 1) + .normalize(); + Direction nearest = Direction.getNearest(deltaMovement.x, deltaMovement.y, deltaMovement.z); + ItemStack remainder = inputBehaviour.handleInsertion(itemEntity.getItem(), nearest, false); + itemEntity.setItem(remainder); + if (remainder.isEmpty()) + itemEntity.discard(); + } + + protected InteractionResult tryExchange(Level worldIn, Player player, InteractionHand handIn, ItemStack heldItem, + ItemDrainBlockEntity be) { + if (FluidHelper.tryEmptyItemIntoBE(worldIn, player, handIn, heldItem, be)) + return InteractionResult.SUCCESS; + if (GenericItemEmptying.canItemBeEmptied(worldIn, heldItem)) + return InteractionResult.SUCCESS; + return InteractionResult.PASS; + } + + @Override + public VoxelShape getShape(BlockState p_220053_1_, BlockGetter p_220053_2_, BlockPos p_220053_3_, + CollisionContext p_220053_4_) { + return AllShapes.CASING_13PX.get(Direction.UP); + } + + @Override + public void onRemove(BlockState state, Level worldIn, BlockPos pos, BlockState newState, boolean isMoving) { + if (!state.hasBlockEntity() || state.getBlock() == newState.getBlock()) + return; + withBlockEntityDo(worldIn, pos, be -> { + ItemStack heldItemStack = be.getHeldItemStack(); + if (!heldItemStack.isEmpty()) + Containers.dropItemStack(worldIn, pos.getX(), pos.getY(), pos.getZ(), heldItemStack); + }); + worldIn.removeBlockEntity(pos); + } + + @Override + public Class getBlockEntityClass() { + return ItemDrainBlockEntity.class; + } + + @Override + public void setPlacedBy(Level pLevel, BlockPos pPos, BlockState pState, LivingEntity pPlacer, ItemStack pStack) { + super.setPlacedBy(pLevel, pPos, pState, pPlacer, pStack); + AdvancementBehaviour.setPlacedBy(pLevel, pPos, pPlacer); + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.ITEM_DRAIN.get(); + } + + @Override + public boolean hasAnalogOutputSignal(BlockState state) { + return true; + } + + @Override + public int getAnalogOutputSignal(BlockState blockState, Level worldIn, BlockPos pos) { + return ComparatorUtil.levelOfSmartFluidTank(worldIn, pos); + } + + @Override + public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) { + return false; + } + +} diff --git a/src/main/java/com/simibubi/create/content/fluids/drain/ItemDrainBlockEntity.java b/src/main/java/com/simibubi/create/content/fluids/drain/ItemDrainBlockEntity.java new file mode 100644 index 000000000..59fee211f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/fluids/drain/ItemDrainBlockEntity.java @@ -0,0 +1,302 @@ +package com.simibubi.create.content.fluids.drain; + +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; + +import com.simibubi.create.content.equipment.goggles.IHaveGoggleInformation; +import com.simibubi.create.content.fluids.transfer.GenericItemEmptying; +import com.simibubi.create.content.kinetics.belt.behaviour.DirectBeltInputBehaviour; +import com.simibubi.create.content.kinetics.belt.transport.TransportedItemStack; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.fluid.SmartFluidTankBehaviour; +import com.simibubi.create.foundation.utility.BlockHelper; +import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.Pair; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction; +import net.minecraftforge.items.ItemHandlerHelper; + +public class ItemDrainBlockEntity extends SmartBlockEntity implements IHaveGoggleInformation { + + public static final int FILLING_TIME = 20; + + SmartFluidTankBehaviour internalTank; + TransportedItemStack heldItem; + protected int processingTicks; + Map> itemHandlers; + + public ItemDrainBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + itemHandlers = new IdentityHashMap<>(); + for (Direction d : Iterate.horizontalDirections) { + ItemDrainItemHandler itemDrainItemHandler = new ItemDrainItemHandler(this, d); + itemHandlers.put(d, LazyOptional.of(() -> itemDrainItemHandler)); + } + } + + @Override + public void addBehaviours(List behaviours) { + behaviours.add(new DirectBeltInputBehaviour(this).allowingBeltFunnels() + .setInsertionHandler(this::tryInsertingFromSide)); + behaviours.add(internalTank = SmartFluidTankBehaviour.single(this, 1500) + .allowExtraction() + .forbidInsertion()); + registerAwardables(behaviours, AllAdvancements.DRAIN, AllAdvancements.CHAINED_DRAIN); + } + + private ItemStack tryInsertingFromSide(TransportedItemStack transportedStack, Direction side, boolean simulate) { + ItemStack inserted = transportedStack.stack; + ItemStack returned = ItemStack.EMPTY; + + if (!getHeldItemStack().isEmpty()) + return inserted; + + if (inserted.getCount() > 1 && GenericItemEmptying.canItemBeEmptied(level, inserted)) { + returned = ItemHandlerHelper.copyStackWithSize(inserted, inserted.getCount() - 1); + inserted = ItemHandlerHelper.copyStackWithSize(inserted, 1); + } + + if (simulate) + return returned; + + transportedStack = transportedStack.copy(); + transportedStack.stack = inserted.copy(); + transportedStack.beltPosition = side.getAxis() + .isVertical() ? .5f : 0; + transportedStack.prevSideOffset = transportedStack.sideOffset; + transportedStack.prevBeltPosition = transportedStack.beltPosition; + setHeldItem(transportedStack, side); + setChanged(); + sendData(); + + return returned; + } + + public ItemStack getHeldItemStack() { + return heldItem == null ? ItemStack.EMPTY : heldItem.stack; + } + + @Override + public void tick() { + super.tick(); + + if (heldItem == null) { + processingTicks = 0; + return; + } + + boolean onClient = level.isClientSide && !isVirtual(); + + if (processingTicks > 0) { + heldItem.prevBeltPosition = .5f; + boolean wasAtBeginning = processingTicks == FILLING_TIME; + if (!onClient || processingTicks < FILLING_TIME) + processingTicks--; + if (!continueProcessing()) { + processingTicks = 0; + notifyUpdate(); + return; + } + if (wasAtBeginning != (processingTicks == FILLING_TIME)) + sendData(); + return; + } + + heldItem.prevBeltPosition = heldItem.beltPosition; + heldItem.prevSideOffset = heldItem.sideOffset; + + heldItem.beltPosition += itemMovementPerTick(); + if (heldItem.beltPosition > 1) { + heldItem.beltPosition = 1; + + if (onClient) + return; + + Direction side = heldItem.insertedFrom; + + ItemStack tryExportingToBeltFunnel = getBehaviour(DirectBeltInputBehaviour.TYPE) + .tryExportingToBeltFunnel(heldItem.stack, side.getOpposite(), false); + if (tryExportingToBeltFunnel != null) { + if (tryExportingToBeltFunnel.getCount() != heldItem.stack.getCount()) { + if (tryExportingToBeltFunnel.isEmpty()) + heldItem = null; + else + heldItem.stack = tryExportingToBeltFunnel; + notifyUpdate(); + return; + } + if (!tryExportingToBeltFunnel.isEmpty()) + return; + } + + BlockPos nextPosition = worldPosition.relative(side); + DirectBeltInputBehaviour directBeltInputBehaviour = + BlockEntityBehaviour.get(level, nextPosition, DirectBeltInputBehaviour.TYPE); + if (directBeltInputBehaviour == null) { + if (!BlockHelper.hasBlockSolidSide(level.getBlockState(nextPosition), level, nextPosition, + side.getOpposite())) { + ItemStack ejected = heldItem.stack; + Vec3 outPos = VecHelper.getCenterOf(worldPosition) + .add(Vec3.atLowerCornerOf(side.getNormal()) + .scale(.75)); + float movementSpeed = itemMovementPerTick(); + Vec3 outMotion = Vec3.atLowerCornerOf(side.getNormal()) + .scale(movementSpeed) + .add(0, 1 / 8f, 0); + outPos.add(outMotion.normalize()); + ItemEntity entity = new ItemEntity(level, outPos.x, outPos.y + 6 / 16f, outPos.z, ejected); + entity.setDeltaMovement(outMotion); + entity.setDefaultPickUpDelay(); + entity.hurtMarked = true; + level.addFreshEntity(entity); + + heldItem = null; + notifyUpdate(); + } + return; + } + + if (!directBeltInputBehaviour.canInsertFromSide(side)) + return; + + ItemStack returned = directBeltInputBehaviour.handleInsertion(heldItem.copy(), side, false); + + if (returned.isEmpty()) { + if (level.getBlockEntity(nextPosition) instanceof ItemDrainBlockEntity) + award(AllAdvancements.CHAINED_DRAIN); + heldItem = null; + notifyUpdate(); + return; + } + + if (returned.getCount() != heldItem.stack.getCount()) { + heldItem.stack = returned; + notifyUpdate(); + return; + } + + return; + } + + if (heldItem.prevBeltPosition < .5f && heldItem.beltPosition >= .5f) { + if (!GenericItemEmptying.canItemBeEmptied(level, heldItem.stack)) + return; + heldItem.beltPosition = .5f; + if (onClient) + return; + processingTicks = FILLING_TIME; + sendData(); + } + + } + + protected boolean continueProcessing() { + if (level.isClientSide && !isVirtual()) + return true; + if (processingTicks < 5) + return true; + if (!GenericItemEmptying.canItemBeEmptied(level, heldItem.stack)) + return false; + + Pair emptyItem = GenericItemEmptying.emptyItem(level, heldItem.stack, true); + FluidStack fluidFromItem = emptyItem.getFirst(); + + if (processingTicks > 5) { + internalTank.allowInsertion(); + if (internalTank.getPrimaryHandler() + .fill(fluidFromItem, FluidAction.SIMULATE) != fluidFromItem.getAmount()) { + internalTank.forbidInsertion(); + processingTicks = FILLING_TIME; + return true; + } + internalTank.forbidInsertion(); + return true; + } + + emptyItem = GenericItemEmptying.emptyItem(level, heldItem.stack.copy(), false); + award(AllAdvancements.DRAIN); + + // Process finished + ItemStack out = emptyItem.getSecond(); + if (!out.isEmpty()) + heldItem.stack = out; + else + heldItem = null; + internalTank.allowInsertion(); + internalTank.getPrimaryHandler() + .fill(fluidFromItem, FluidAction.EXECUTE); + internalTank.forbidInsertion(); + notifyUpdate(); + return true; + } + + private float itemMovementPerTick() { + return 1 / 8f; + } + + @Override + public void invalidate() { + super.invalidate(); + for (LazyOptional lazyOptional : itemHandlers.values()) + lazyOptional.invalidate(); + } + + public void setHeldItem(TransportedItemStack heldItem, Direction insertedFrom) { + this.heldItem = heldItem; + this.heldItem.insertedFrom = insertedFrom; + } + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + compound.putInt("ProcessingTicks", processingTicks); + if (heldItem != null) + compound.put("HeldItem", heldItem.serializeNBT()); + super.write(compound, clientPacket); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + heldItem = null; + processingTicks = compound.getInt("ProcessingTicks"); + if (compound.contains("HeldItem")) + heldItem = TransportedItemStack.read(compound.getCompound("HeldItem")); + super.read(compound, clientPacket); + } + + @Override + public LazyOptional getCapability(Capability cap, Direction side) { + if (side != null && side.getAxis() + .isHorizontal() && isItemHandlerCap(cap)) + return itemHandlers.get(side) + .cast(); + + if (side != Direction.UP && isFluidHandlerCap(cap)) + return internalTank.getCapability() + .cast(); + + return super.getCapability(cap, side); + } + + @Override + public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { + return containedFluidTooltip(tooltip, isPlayerSneaking, getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY)); + } + +} diff --git a/src/main/java/com/simibubi/create/content/fluids/drain/ItemDrainItemHandler.java b/src/main/java/com/simibubi/create/content/fluids/drain/ItemDrainItemHandler.java new file mode 100644 index 000000000..d69e16c55 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/fluids/drain/ItemDrainItemHandler.java @@ -0,0 +1,80 @@ +package com.simibubi.create.content.fluids.drain; + +import com.simibubi.create.content.fluids.transfer.GenericItemEmptying; +import com.simibubi.create.content.kinetics.belt.transport.TransportedItemStack; + +import net.minecraft.core.Direction; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemHandlerHelper; + +public class ItemDrainItemHandler implements IItemHandler { + + private ItemDrainBlockEntity blockEntity; + private Direction side; + + public ItemDrainItemHandler(ItemDrainBlockEntity be, Direction side) { + this.blockEntity = be; + this.side = side; + } + + @Override + public int getSlots() { + return 1; + } + + @Override + public ItemStack getStackInSlot(int slot) { + return blockEntity.getHeldItemStack(); + } + + @Override + public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) { + if (!blockEntity.getHeldItemStack() + .isEmpty()) + return stack; + + ItemStack returned = ItemStack.EMPTY; + if (stack.getCount() > 1 && GenericItemEmptying.canItemBeEmptied(blockEntity.getLevel(), stack)) { + returned = ItemHandlerHelper.copyStackWithSize(stack, stack.getCount() - 1); + stack = ItemHandlerHelper.copyStackWithSize(stack, 1); + } + + if (!simulate) { + TransportedItemStack heldItem = new TransportedItemStack(stack); + heldItem.prevBeltPosition = 0; + blockEntity.setHeldItem(heldItem, side.getOpposite()); + blockEntity.notifyUpdate(); + } + + return returned; + } + + @Override + public ItemStack extractItem(int slot, int amount, boolean simulate) { + TransportedItemStack held = blockEntity.heldItem; + if (held == null) + return ItemStack.EMPTY; + + ItemStack stack = held.stack.copy(); + ItemStack extracted = stack.split(amount); + if (!simulate) { + blockEntity.heldItem.stack = stack; + if (stack.isEmpty()) + blockEntity.heldItem = null; + blockEntity.notifyUpdate(); + } + return extracted; + } + + @Override + public int getSlotLimit(int slot) { + return 64; + } + + @Override + public boolean isItemValid(int slot, ItemStack stack) { + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/ItemDrainRenderer.java b/src/main/java/com/simibubi/create/content/fluids/drain/ItemDrainRenderer.java similarity index 76% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/actors/ItemDrainRenderer.java rename to src/main/java/com/simibubi/create/content/fluids/drain/ItemDrainRenderer.java index 7ba591559..e0e27a18a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/ItemDrainRenderer.java +++ b/src/main/java/com/simibubi/create/content/fluids/drain/ItemDrainRenderer.java @@ -1,17 +1,17 @@ -package com.simibubi.create.content.contraptions.fluids.actors; +package com.simibubi.create.content.fluids.drain; import java.util.Random; import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Axis; -import com.simibubi.create.content.contraptions.processing.EmptyingByBasin; -import com.simibubi.create.content.contraptions.relays.belt.BeltHelper; -import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack; +import com.simibubi.create.content.fluids.transfer.GenericItemEmptying; +import com.simibubi.create.content.kinetics.belt.BeltHelper; +import com.simibubi.create.content.kinetics.belt.transport.TransportedItemStack; +import com.simibubi.create.foundation.blockEntity.behaviour.fluid.SmartFluidTankBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.fluid.SmartFluidTankBehaviour.TankSegment; +import com.simibubi.create.foundation.blockEntity.renderer.SmartBlockEntityRenderer; import com.simibubi.create.foundation.fluid.FluidRenderer; -import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour.TankSegment; -import com.simibubi.create.foundation.tileEntity.renderer.SmartTileEntityRenderer; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.client.Minecraft; @@ -27,28 +27,28 @@ import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import net.minecraftforge.fluids.FluidStack; -public class ItemDrainRenderer extends SmartTileEntityRenderer { +public class ItemDrainRenderer extends SmartBlockEntityRenderer { public ItemDrainRenderer(BlockEntityRendererProvider.Context context) { super(context); } @Override - protected void renderSafe(ItemDrainTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, + protected void renderSafe(ItemDrainBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light, int overlay) { - super.renderSafe(te, partialTicks, ms, buffer, light, overlay); - renderFluid(te, partialTicks, ms, buffer, light); - renderItem(te, partialTicks, ms, buffer, light, overlay); + super.renderSafe(be, partialTicks, ms, buffer, light, overlay); + renderFluid(be, partialTicks, ms, buffer, light); + renderItem(be, partialTicks, ms, buffer, light, overlay); } - protected void renderItem(ItemDrainTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, + protected void renderItem(ItemDrainBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light, int overlay) { - TransportedItemStack transported = te.heldItem; + TransportedItemStack transported = be.heldItem; if (transported == null) return; TransformStack msr = TransformStack.cast(ms); - Vec3 itemPosition = VecHelper.getCenterOf(te.getBlockPos()); + Vec3 itemPosition = VecHelper.getCenterOf(be.getBlockPos()); Direction insertedFrom = transported.insertedFrom; if (!insertedFrom.getAxis() @@ -130,9 +130,9 @@ public class ItemDrainRenderer extends SmartTileEntityRenderer { +public class HosePulleyBlock extends HorizontalKineticBlock implements IBE { public HosePulleyBlock(Properties properties) { super(properties); @@ -71,13 +71,13 @@ public class HosePulleyBlock extends HorizontalKineticBlock implements ITE getTileEntityClass() { - return HosePulleyTileEntity.class; + public Class getBlockEntityClass() { + return HosePulleyBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.HOSE_PULLEY.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.HOSE_PULLEY.get(); } } diff --git a/src/main/java/com/simibubi/create/content/fluids/hosePulley/HosePulleyBlockEntity.java b/src/main/java/com/simibubi/create/content/fluids/hosePulley/HosePulleyBlockEntity.java new file mode 100644 index 000000000..651c087e0 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/fluids/hosePulley/HosePulleyBlockEntity.java @@ -0,0 +1,194 @@ +package com.simibubi.create.content.fluids.hosePulley; + +import java.util.List; + +import com.simibubi.create.content.fluids.transfer.FluidDrainingBehaviour; +import com.simibubi.create.content.fluids.transfer.FluidFillingBehaviour; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.fluid.SmartFluidTank; +import com.simibubi.create.foundation.item.TooltipHelper; +import com.simibubi.create.foundation.utility.ServerSpeedProvider; +import com.simibubi.create.foundation.utility.animation.LerpedFloat; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.IFluidHandler; + +public class HosePulleyBlockEntity extends KineticBlockEntity { + + LerpedFloat offset; + boolean isMoving; + + private SmartFluidTank internalTank; + private LazyOptional capability; + private FluidDrainingBehaviour drainer; + private FluidFillingBehaviour filler; + private HosePulleyFluidHandler handler; + private boolean infinite; + + public HosePulleyBlockEntity(BlockEntityType typeIn, BlockPos pos, BlockState state) { + super(typeIn, pos, state); + offset = LerpedFloat.linear() + .startWithValue(0); + isMoving = true; + internalTank = new SmartFluidTank(1500, this::onTankContentsChanged); + handler = new HosePulleyFluidHandler(internalTank, filler, drainer, + () -> worldPosition.below((int) Math.ceil(offset.getValue())), () -> !this.isMoving); + capability = LazyOptional.of(() -> handler); + } + + @Override + public void sendData() { + infinite = filler.isInfinite() || drainer.isInfinite(); + super.sendData(); + } + + @Override + public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { + boolean addToGoggleTooltip = super.addToGoggleTooltip(tooltip, isPlayerSneaking); + if (infinite) + TooltipHelper.addHint(tooltip, "hint.hose_pulley"); + return addToGoggleTooltip; + } + + @Override + public void addBehaviours(List behaviours) { + drainer = new FluidDrainingBehaviour(this); + filler = new FluidFillingBehaviour(this); + behaviours.add(drainer); + behaviours.add(filler); + super.addBehaviours(behaviours); + registerAwardables(behaviours, AllAdvancements.HOSE_PULLEY, AllAdvancements.HOSE_PULLEY_LAVA); + } + + protected void onTankContentsChanged(FluidStack contents) {} + + @Override + public void onSpeedChanged(float previousSpeed) { + isMoving = true; + if (getSpeed() == 0) { + offset.forceNextSync(); + offset.setValue(Math.round(offset.getValue())); + isMoving = false; + } + + if (isMoving) { + float newOffset = offset.getValue() + getMovementSpeed(); + if (newOffset < 0) + isMoving = false; + if (!level.getBlockState(worldPosition.below((int) Math.ceil(newOffset))) + .getMaterial() + .isReplaceable()) { + isMoving = false; + } + if (isMoving) { + drainer.reset(); + filler.reset(); + } + } + + super.onSpeedChanged(previousSpeed); + } + + @Override + protected AABB createRenderBoundingBox() { + return super.createRenderBoundingBox().expandTowards(0, -offset.getValue(), 0); + } + + @Override + public void tick() { + super.tick(); + float newOffset = offset.getValue() + getMovementSpeed(); + if (newOffset < 0) { + newOffset = 0; + isMoving = false; + } + if (!level.getBlockState(worldPosition.below((int) Math.ceil(newOffset))) + .getMaterial() + .isReplaceable()) { + newOffset = (int) newOffset; + isMoving = false; + } + if (getSpeed() == 0) + isMoving = false; + + offset.setValue(newOffset); + invalidateRenderBoundingBox(); + } + + @Override + public void lazyTick() { + super.lazyTick(); + if (level.isClientSide) + return; + if (isMoving) + return; + + int ceil = (int) Math.ceil(offset.getValue() + getMovementSpeed()); + if (getMovementSpeed() > 0 && level.getBlockState(worldPosition.below(ceil)) + .getMaterial() + .isReplaceable()) { + isMoving = true; + drainer.reset(); + filler.reset(); + return; + } + + sendData(); + } + + @Override + protected void write(CompoundTag compound, boolean clientPacket) { + if (clientPacket) + offset.forceNextSync(); + compound.put("Offset", offset.writeNBT()); + compound.put("Tank", internalTank.writeToNBT(new CompoundTag())); + super.write(compound, clientPacket); + if (clientPacket) + compound.putBoolean("Infinite", infinite); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + offset.readNBT(compound.getCompound("Offset"), clientPacket); + internalTank.readFromNBT(compound.getCompound("Tank")); + super.read(compound, clientPacket); + if (clientPacket) + infinite = compound.getBoolean("Infinite"); + } + + @Override + public void invalidate() { + super.invalidate(); + capability.invalidate(); + } + + public float getMovementSpeed() { + float movementSpeed = convertToLinear(getSpeed()); + if (level.isClientSide) + movementSpeed *= ServerSpeedProvider.get(); + return movementSpeed; + } + + public float getInterpolatedOffset(float pt) { + return offset.getValue(pt); + } + + @Override + public LazyOptional getCapability(Capability cap, Direction side) { + if (isFluidHandlerCap(cap) + && (side == null || HosePulleyBlock.hasPipeTowards(level, worldPosition, getBlockState(), side))) + return this.capability.cast(); + return super.getCapability(cap, side); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/HosePulleyFluidHandler.java b/src/main/java/com/simibubi/create/content/fluids/hosePulley/HosePulleyFluidHandler.java similarity index 93% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/actors/HosePulleyFluidHandler.java rename to src/main/java/com/simibubi/create/content/fluids/hosePulley/HosePulleyFluidHandler.java index 063a52eae..5cb60d651 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/HosePulleyFluidHandler.java +++ b/src/main/java/com/simibubi/create/content/fluids/hosePulley/HosePulleyFluidHandler.java @@ -1,9 +1,11 @@ -package com.simibubi.create.content.contraptions.fluids.actors; +package com.simibubi.create.content.fluids.hosePulley; import java.util.function.Supplier; import javax.annotation.Nullable; +import com.simibubi.create.content.fluids.transfer.FluidDrainingBehaviour; +import com.simibubi.create.content.fluids.transfer.FluidFillingBehaviour; import com.simibubi.create.foundation.fluid.FluidHelper; import com.simibubi.create.foundation.fluid.SmartFluidTank; @@ -125,4 +127,8 @@ public class HosePulleyFluidHandler implements IFluidHandler { return internalTank.isFluidValid(tank, stack); } + public SmartFluidTank getInternalTank() { + return internalTank; + } + } diff --git a/src/main/java/com/simibubi/create/content/fluids/hosePulley/HosePulleyRenderer.java b/src/main/java/com/simibubi/create/content/fluids/hosePulley/HosePulleyRenderer.java new file mode 100644 index 000000000..77b623ecc --- /dev/null +++ b/src/main/java/com/simibubi/create/content/fluids/hosePulley/HosePulleyRenderer.java @@ -0,0 +1,51 @@ +package com.simibubi.create.content.fluids.hosePulley; + +import com.jozufozu.flywheel.core.PartialModel; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.contraptions.pulley.AbstractPulleyRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; + +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.core.Direction.Axis; + +public class HosePulleyRenderer extends AbstractPulleyRenderer { + + public HosePulleyRenderer(BlockEntityRendererProvider.Context context) { + super(context, AllPartialModels.HOSE_HALF, AllPartialModels.HOSE_HALF_MAGNET); + } + + @Override + protected Axis getShaftAxis(HosePulleyBlockEntity be) { + return be.getBlockState() + .getValue(HosePulleyBlock.HORIZONTAL_FACING) + .getClockWise() + .getAxis(); + } + + @Override + protected PartialModel getCoil() { + return AllPartialModels.HOSE_COIL; + } + + @Override + protected SuperByteBuffer renderRope(HosePulleyBlockEntity be) { + return CachedBufferer.partial(AllPartialModels.HOSE, be.getBlockState()); + } + + @Override + protected SuperByteBuffer renderMagnet(HosePulleyBlockEntity be) { + return CachedBufferer.partial(AllPartialModels.HOSE_MAGNET, be.getBlockState()); + } + + @Override + protected float getOffset(HosePulleyBlockEntity be, float partialTicks) { + return be.getInterpolatedOffset(partialTicks); + } + + @Override + protected boolean isRunning(HosePulleyBlockEntity be) { + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/particle/BasinFluidParticle.java b/src/main/java/com/simibubi/create/content/fluids/particle/BasinFluidParticle.java similarity index 88% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/particle/BasinFluidParticle.java rename to src/main/java/com/simibubi/create/content/fluids/particle/BasinFluidParticle.java index 1d391f343..7e0141c83 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/particle/BasinFluidParticle.java +++ b/src/main/java/com/simibubi/create/content/fluids/particle/BasinFluidParticle.java @@ -1,10 +1,10 @@ -package com.simibubi.create.content.contraptions.fluids.particle; +package com.simibubi.create.content.fluids.particle; import org.joml.Quaternionf; import com.mojang.blaze3d.vertex.VertexConsumer; import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.processing.BasinTileEntity; +import com.simibubi.create.content.processing.basin.BasinBlockEntity; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.client.Camera; @@ -62,9 +62,9 @@ public class BasinFluidParticle extends FluidStackParticle { return; } - BlockEntity tileEntity = level.getBlockEntity(basinPos); - if (tileEntity instanceof BasinTileEntity) { - float totalUnits = ((BasinTileEntity) tileEntity).getTotalFluidUnits(0); + BlockEntity blockEntity = level.getBlockEntity(basinPos); + if (blockEntity instanceof BasinBlockEntity) { + float totalUnits = ((BasinBlockEntity) blockEntity).getTotalFluidUnits(0); if (totalUnits < 1) totalUnits = 0; float fluidLevel = Mth.clamp(totalUnits / 2000, 0, 1); diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/particle/FluidParticleData.java b/src/main/java/com/simibubi/create/content/fluids/particle/FluidParticleData.java similarity index 95% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/particle/FluidParticleData.java rename to src/main/java/com/simibubi/create/content/fluids/particle/FluidParticleData.java index 1bd73686a..167458610 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/particle/FluidParticleData.java +++ b/src/main/java/com/simibubi/create/content/fluids/particle/FluidParticleData.java @@ -1,11 +1,11 @@ -package com.simibubi.create.content.contraptions.fluids.particle; +package com.simibubi.create.content.fluids.particle; import com.mojang.brigadier.StringReader; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; import com.simibubi.create.AllParticleTypes; -import com.simibubi.create.content.contraptions.particle.ICustomParticleData; +import com.simibubi.create.foundation.particle.ICustomParticleData; import com.simibubi.create.foundation.utility.RegisteredObjects; import net.minecraft.client.particle.ParticleProvider; diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/particle/FluidStackParticle.java b/src/main/java/com/simibubi/create/content/fluids/particle/FluidStackParticle.java similarity index 96% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/particle/FluidStackParticle.java rename to src/main/java/com/simibubi/create/content/fluids/particle/FluidStackParticle.java index b383b9405..cd9de2d49 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/particle/FluidStackParticle.java +++ b/src/main/java/com/simibubi/create/content/fluids/particle/FluidStackParticle.java @@ -1,7 +1,7 @@ -package com.simibubi.create.content.contraptions.fluids.particle; +package com.simibubi.create.content.fluids.particle; import com.simibubi.create.AllParticleTypes; -import com.simibubi.create.content.contraptions.fluids.potion.PotionFluid; +import com.simibubi.create.content.fluids.potion.PotionFluid; import com.simibubi.create.foundation.utility.Color; import net.minecraft.client.Minecraft; diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/AxisPipeBlock.java b/src/main/java/com/simibubi/create/content/fluids/pipes/AxisPipeBlock.java similarity index 90% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/AxisPipeBlock.java rename to src/main/java/com/simibubi/create/content/fluids/pipes/AxisPipeBlock.java index 685dc3ae4..c98ad13d0 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/AxisPipeBlock.java +++ b/src/main/java/com/simibubi/create/content/fluids/pipes/AxisPipeBlock.java @@ -1,16 +1,16 @@ -package com.simibubi.create.content.contraptions.fluids.pipes; +package com.simibubi.create.content.fluids.pipes; import java.util.Map; import java.util.Optional; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; -import com.simibubi.create.content.contraptions.fluids.FluidPropagator; -import com.simibubi.create.content.contraptions.fluids.FluidTransportBehaviour; -import com.simibubi.create.content.contraptions.relays.elementary.BracketedTileEntityBehaviour; -import com.simibubi.create.content.contraptions.wrench.IWrenchableWithBracket; +import com.simibubi.create.content.decoration.bracket.BracketedBlockEntityBehaviour; +import com.simibubi.create.content.equipment.wrench.IWrenchableWithBracket; +import com.simibubi.create.content.fluids.FluidPropagator; +import com.simibubi.create.content.fluids.FluidTransportBehaviour; import com.simibubi.create.foundation.advancement.AdvancementBehaviour; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.utility.Iterate; import net.minecraft.core.BlockPos; @@ -134,7 +134,7 @@ public class AxisPipeBlock extends RotatedPillarBlock implements IWrenchableWith @Override public Optional removeBracket(BlockGetter world, BlockPos pos, boolean inOnReplacedContext) { - BracketedTileEntityBehaviour behaviour = TileEntityBehaviour.get(world, pos, BracketedTileEntityBehaviour.TYPE); + BracketedBlockEntityBehaviour behaviour = BlockEntityBehaviour.get(world, pos, BracketedBlockEntityBehaviour.TYPE); if (behaviour == null) return Optional.empty(); BlockState bracket = behaviour.removeBracket(inOnReplacedContext); diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/EncasedPipeBlock.java b/src/main/java/com/simibubi/create/content/fluids/pipes/EncasedPipeBlock.java similarity index 78% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/EncasedPipeBlock.java rename to src/main/java/com/simibubi/create/content/fluids/pipes/EncasedPipeBlock.java index afe6ee197..acf2991bd 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/EncasedPipeBlock.java +++ b/src/main/java/com/simibubi/create/content/fluids/pipes/EncasedPipeBlock.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.fluids.pipes; +package com.simibubi.create.content.fluids.pipes; import static net.minecraft.world.level.block.state.properties.BlockStateProperties.DOWN; import static net.minecraft.world.level.block.state.properties.BlockStateProperties.EAST; @@ -10,16 +10,18 @@ import static net.minecraft.world.level.block.state.properties.BlockStatePropert import java.util.Map; import java.util.function.Supplier; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.fluids.FluidPropagator; -import com.simibubi.create.content.contraptions.fluids.FluidTransportBehaviour; -import com.simibubi.create.content.contraptions.relays.elementary.EncasedBlock; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; -import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement; -import com.simibubi.create.content.schematics.ItemRequirement; +import com.simibubi.create.content.contraptions.ITransformableBlock; +import com.simibubi.create.content.contraptions.StructureTransform; +import com.simibubi.create.content.decoration.encasing.EncasedBlock; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.content.fluids.FluidPropagator; +import com.simibubi.create.content.fluids.FluidTransportBehaviour; +import com.simibubi.create.content.schematics.requirement.ISpecialBlockItemRequirement; +import com.simibubi.create.content.schematics.requirement.ItemRequirement; import com.simibubi.create.foundation.advancement.AdvancementBehaviour; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.utility.Iterate; import net.minecraft.core.BlockPos; @@ -36,7 +38,9 @@ import net.minecraft.world.item.context.UseOnContext; 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.Mirror; import net.minecraft.world.level.block.PipeBlock; +import net.minecraft.world.level.block.Rotation; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; @@ -46,7 +50,8 @@ import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; import net.minecraft.world.ticks.TickPriority; -public class EncasedPipeBlock extends Block implements IWrenchable, ISpecialBlockItemRequirement, ITE, EncasedBlock { +public class EncasedPipeBlock extends Block + implements IWrenchable, ISpecialBlockItemRequirement, IBE, EncasedBlock, ITransformableBlock { public static final Map FACING_TO_PROPERTY_MAP = PipeBlock.PROPERTY_BY_DIRECTION; private final Supplier casing; @@ -146,18 +151,18 @@ public class EncasedPipeBlock extends Block implements IWrenchable, ISpecialBloc } @Override - public ItemRequirement getRequiredItems(BlockState state, BlockEntity te) { - return ItemRequirement.of(AllBlocks.FLUID_PIPE.getDefaultState(), te); + public ItemRequirement getRequiredItems(BlockState state, BlockEntity be) { + return ItemRequirement.of(AllBlocks.FLUID_PIPE.getDefaultState(), be); } @Override - public Class getTileEntityClass() { - return FluidPipeTileEntity.class; + public Class getBlockEntityClass() { + return FluidPipeBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.ENCASED_FLUID_PIPE.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.ENCASED_FLUID_PIPE.get(); } @Override @@ -173,4 +178,20 @@ public class EncasedPipeBlock extends Block implements IWrenchable, ISpecialBloc EncasedPipeBlock.transferSixWayProperties(state, defaultBlockState())); FluidTransportBehaviour.loadFlows(level, pos); } + + @Override + public BlockState rotate(BlockState pState, Rotation pRotation) { + return FluidPipeBlockRotation.rotate(pState, pRotation); + } + + @Override + public BlockState mirror(BlockState pState, Mirror pMirror) { + return FluidPipeBlockRotation.mirror(pState, pMirror); + } + + @Override + public BlockState transform(BlockState state, StructureTransform transform) { + return FluidPipeBlockRotation.transform(state, transform); + } + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidPipeBlock.java b/src/main/java/com/simibubi/create/content/fluids/pipes/FluidPipeBlock.java similarity index 83% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidPipeBlock.java rename to src/main/java/com/simibubi/create/content/fluids/pipes/FluidPipeBlock.java index d7998b973..a15074c6c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidPipeBlock.java +++ b/src/main/java/com/simibubi/create/content/fluids/pipes/FluidPipeBlock.java @@ -1,21 +1,23 @@ -package com.simibubi.create.content.contraptions.fluids.pipes; +package com.simibubi.create.content.fluids.pipes; import java.util.Arrays; import java.util.Optional; import javax.annotation.Nullable; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.fluids.FluidPropagator; -import com.simibubi.create.content.contraptions.fluids.FluidTransportBehaviour; -import com.simibubi.create.content.contraptions.relays.elementary.BracketedTileEntityBehaviour; -import com.simibubi.create.content.contraptions.relays.elementary.EncasableBlock; -import com.simibubi.create.content.contraptions.wrench.IWrenchableWithBracket; +import com.simibubi.create.content.contraptions.ITransformableBlock; +import com.simibubi.create.content.contraptions.StructureTransform; +import com.simibubi.create.content.decoration.bracket.BracketedBlockEntityBehaviour; +import com.simibubi.create.content.decoration.encasing.EncasableBlock; +import com.simibubi.create.content.equipment.wrench.IWrenchableWithBracket; +import com.simibubi.create.content.fluids.FluidPropagator; +import com.simibubi.create.content.fluids.FluidTransportBehaviour; import com.simibubi.create.foundation.advancement.AdvancementBehaviour; import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.block.ITE; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.utility.Iterate; import net.minecraft.core.BlockPos; @@ -36,7 +38,9 @@ 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.Mirror; import net.minecraft.world.level.block.PipeBlock; +import net.minecraft.world.level.block.Rotation; import net.minecraft.world.level.block.SimpleWaterloggedBlock; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; @@ -50,8 +54,8 @@ import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.ticks.TickPriority; -public class FluidPipeBlock extends PipeBlock - implements SimpleWaterloggedBlock, IWrenchableWithBracket, ITE, EncasableBlock { +public class FluidPipeBlock extends PipeBlock implements SimpleWaterloggedBlock, IWrenchableWithBracket, + IBE, EncasableBlock, ITransformableBlock { private static final VoxelShape OCCLUSION_BOX = Block.box(4, 4, 4, 12, 12, 12); @@ -91,7 +95,7 @@ public class FluidPipeBlock extends PipeBlock if (clickedFace.getAxis() == axis) return InteractionResult.PASS; if (!world.isClientSide) { - withTileEntityDo(world, pos, fpte -> fpte.getBehaviour(FluidTransportBehaviour.TYPE).interfaces.values() + withBlockEntityDo(world, pos, fpte -> fpte.getBehaviour(FluidTransportBehaviour.TYPE).interfaces.values() .stream() .filter(pc -> pc != null && pc.hasFlow()) .findAny() @@ -181,9 +185,9 @@ public class FluidPipeBlock extends PipeBlock return true; if (VanillaFluidTargets.shouldPipesConnectTo(neighbour)) return true; - FluidTransportBehaviour transport = TileEntityBehaviour.get(world, neighbourPos, FluidTransportBehaviour.TYPE); - BracketedTileEntityBehaviour bracket = - TileEntityBehaviour.get(world, neighbourPos, BracketedTileEntityBehaviour.TYPE); + FluidTransportBehaviour transport = BlockEntityBehaviour.get(world, neighbourPos, FluidTransportBehaviour.TYPE); + BracketedBlockEntityBehaviour bracket = + BlockEntityBehaviour.get(world, neighbourPos, BracketedBlockEntityBehaviour.TYPE); if (isPipe(neighbour)) return bracket == null || !bracket.isBracketPresent() || FluidPropagator.getStraightPipeAxis(neighbour) == direction.getAxis(); @@ -255,7 +259,7 @@ public class FluidPipeBlock extends PipeBlock public BlockState updateBlockState(BlockState state, Direction preferredDirection, @Nullable Direction ignore, BlockAndTintGetter world, BlockPos pos) { - BracketedTileEntityBehaviour bracket = TileEntityBehaviour.get(world, pos, BracketedTileEntityBehaviour.TYPE); + BracketedBlockEntityBehaviour bracket = BlockEntityBehaviour.get(world, pos, BracketedBlockEntityBehaviour.TYPE); if (bracket != null && bracket.isBracketPresent()) return state; @@ -303,8 +307,8 @@ public class FluidPipeBlock extends PipeBlock @Override public Optional removeBracket(BlockGetter world, BlockPos pos, boolean inOnReplacedContext) { - BracketedTileEntityBehaviour behaviour = - BracketedTileEntityBehaviour.get(world, pos, BracketedTileEntityBehaviour.TYPE); + BracketedBlockEntityBehaviour behaviour = + BracketedBlockEntityBehaviour.get(world, pos, BracketedBlockEntityBehaviour.TYPE); if (behaviour == null) return Optional.empty(); BlockState bracket = behaviour.removeBracket(inOnReplacedContext); @@ -319,13 +323,13 @@ public class FluidPipeBlock extends PipeBlock } @Override - public Class getTileEntityClass() { - return FluidPipeTileEntity.class; + public Class getBlockEntityClass() { + return FluidPipeBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.FLUID_PIPE.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.FLUID_PIPE.get(); } @Override @@ -337,4 +341,20 @@ public class FluidPipeBlock extends PipeBlock public VoxelShape getOcclusionShape(BlockState pState, BlockGetter pLevel, BlockPos pPos) { return OCCLUSION_BOX; } + + @Override + public BlockState rotate(BlockState pState, Rotation pRotation) { + return FluidPipeBlockRotation.rotate(pState, pRotation); + } + + @Override + public BlockState mirror(BlockState pState, Mirror pMirror) { + return FluidPipeBlockRotation.mirror(pState, pMirror); + } + + @Override + public BlockState transform(BlockState state, StructureTransform transform) { + return FluidPipeBlockRotation.transform(state, transform); + } + } diff --git a/src/main/java/com/simibubi/create/content/fluids/pipes/FluidPipeBlockEntity.java b/src/main/java/com/simibubi/create/content/fluids/pipes/FluidPipeBlockEntity.java new file mode 100644 index 000000000..a7021c604 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/fluids/pipes/FluidPipeBlockEntity.java @@ -0,0 +1,86 @@ +package com.simibubi.create.content.fluids.pipes; + +import java.util.List; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.contraptions.ITransformableBlockEntity; +import com.simibubi.create.content.contraptions.StructureTransform; +import com.simibubi.create.content.decoration.bracket.BracketedBlockEntityBehaviour; +import com.simibubi.create.content.fluids.FluidPropagator; +import com.simibubi.create.content.fluids.FluidTransportBehaviour; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; + +public class FluidPipeBlockEntity extends SmartBlockEntity implements ITransformableBlockEntity { + + public FluidPipeBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + public void addBehaviours(List behaviours) { + behaviours.add(new StandardPipeFluidTransportBehaviour(this)); + behaviours.add(new BracketedBlockEntityBehaviour(this, this::canHaveBracket)); + registerAwardables(behaviours, FluidPropagator.getSharedTriggers()); + } + + @Override + public void transform(StructureTransform transform) { + BracketedBlockEntityBehaviour bracketBehaviour = getBehaviour(BracketedBlockEntityBehaviour.TYPE); + if (bracketBehaviour != null) { + bracketBehaviour.transformBracket(transform); + } + } + + private boolean canHaveBracket(BlockState state) { + return !(state.getBlock() instanceof EncasedPipeBlock); + } + + class StandardPipeFluidTransportBehaviour extends FluidTransportBehaviour { + + public StandardPipeFluidTransportBehaviour(SmartBlockEntity be) { + super(be); + } + + @Override + public boolean canHaveFlowToward(BlockState state, Direction direction) { + return (FluidPipeBlock.isPipe(state) || state.getBlock() instanceof EncasedPipeBlock) + && state.getValue(FluidPipeBlock.PROPERTY_BY_DIRECTION.get(direction)); + } + + @Override + public AttachmentTypes getRenderedRimAttachment(BlockAndTintGetter world, BlockPos pos, BlockState state, + Direction direction) { + AttachmentTypes attachment = super.getRenderedRimAttachment(world, pos, state, direction); + + BlockPos offsetPos = pos.relative(direction); + BlockState otherState = world.getBlockState(offsetPos); + + if (state.getBlock() instanceof EncasedPipeBlock && attachment != AttachmentTypes.DRAIN) + return AttachmentTypes.NONE; + + if (attachment == AttachmentTypes.RIM && !FluidPipeBlock.isPipe(otherState) + && !AllBlocks.MECHANICAL_PUMP.has(otherState) && !AllBlocks.ENCASED_FLUID_PIPE.has(otherState)) { + FluidTransportBehaviour pipeBehaviour = + BlockEntityBehaviour.get(world, offsetPos, FluidTransportBehaviour.TYPE); + if (pipeBehaviour != null) + if (pipeBehaviour.canHaveFlowToward(otherState, direction.getOpposite())) + return AttachmentTypes.CONNECTION; + } + + if (attachment == AttachmentTypes.RIM && !FluidPipeBlock.shouldDrawRim(world, pos, state, direction)) + return AttachmentTypes.CONNECTION; + if (attachment == AttachmentTypes.NONE && state.getValue(FluidPipeBlock.PROPERTY_BY_DIRECTION.get(direction))) + return AttachmentTypes.CONNECTION; + return attachment; + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/fluids/pipes/FluidPipeBlockRotation.java b/src/main/java/com/simibubi/create/content/fluids/pipes/FluidPipeBlockRotation.java new file mode 100644 index 000000000..df559fbf2 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/fluids/pipes/FluidPipeBlockRotation.java @@ -0,0 +1,49 @@ +package com.simibubi.create.content.fluids.pipes; + +import java.util.Map; + +import com.simibubi.create.content.contraptions.StructureTransform; +import com.simibubi.create.foundation.utility.Iterate; + +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.Mirror; +import net.minecraft.world.level.block.PipeBlock; +import net.minecraft.world.level.block.Rotation; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BooleanProperty; + +public class FluidPipeBlockRotation { + + public static final Map FACING_TO_PROPERTY_MAP = PipeBlock.PROPERTY_BY_DIRECTION; + + public static BlockState rotate(BlockState state, Rotation rotation) { + BlockState rotated = state; + for (Direction direction : Iterate.horizontalDirections) + rotated = rotated.setValue(FACING_TO_PROPERTY_MAP.get(rotation.rotate(direction)), + state.getValue(FACING_TO_PROPERTY_MAP.get(direction))); + return rotated; + } + + public static BlockState mirror(BlockState state, Mirror mirror) { + BlockState mirrored = state; + for (Direction direction : Iterate.horizontalDirections) + mirrored = mirrored.setValue(FACING_TO_PROPERTY_MAP.get(mirror.mirror(direction)), + state.getValue(FACING_TO_PROPERTY_MAP.get(direction))); + return mirrored; + } + + public static BlockState transform(BlockState state, StructureTransform transform) { + if (transform.mirror != null) + state = mirror(state, transform.mirror); + + if (transform.rotationAxis == Direction.Axis.Y) + return rotate(state, transform.rotation); + + BlockState rotated = state; + for (Direction direction : Iterate.directions) + rotated = rotated.setValue(FACING_TO_PROPERTY_MAP.get(transform.rotateFacing(direction)), + state.getValue(FACING_TO_PROPERTY_MAP.get(direction))); + return rotated; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/GlassFluidPipeBlock.java b/src/main/java/com/simibubi/create/content/fluids/pipes/GlassFluidPipeBlock.java similarity index 81% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/GlassFluidPipeBlock.java rename to src/main/java/com/simibubi/create/content/fluids/pipes/GlassFluidPipeBlock.java index 8b697039a..4752f03ae 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/GlassFluidPipeBlock.java +++ b/src/main/java/com/simibubi/create/content/fluids/pipes/GlassFluidPipeBlock.java @@ -1,13 +1,13 @@ -package com.simibubi.create.content.contraptions.fluids.pipes; +package com.simibubi.create.content.fluids.pipes; import javax.annotation.ParametersAreNonnullByDefault; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.fluids.FluidTransportBehaviour; -import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement; -import com.simibubi.create.content.schematics.ItemRequirement; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.content.fluids.FluidTransportBehaviour; +import com.simibubi.create.content.schematics.requirement.ISpecialBlockItemRequirement; +import com.simibubi.create.content.schematics.requirement.ItemRequirement; +import com.simibubi.create.foundation.block.IBE; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; @@ -30,7 +30,7 @@ import net.minecraft.world.level.pathfinder.PathComputationType; @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault -public class GlassFluidPipeBlock extends AxisPipeBlock implements ITE, SimpleWaterloggedBlock, ISpecialBlockItemRequirement { +public class GlassFluidPipeBlock extends AxisPipeBlock implements IBE, SimpleWaterloggedBlock, ISpecialBlockItemRequirement { public static final BooleanProperty ALT = BooleanProperty.create("alt"); @@ -74,8 +74,8 @@ public class GlassFluidPipeBlock extends AxisPipeBlock implements ITE getTileEntityClass() { - return StraightPipeTileEntity.class; + public Class getBlockEntityClass() { + return StraightPipeBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.GLASS_FLUID_PIPE.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.GLASS_FLUID_PIPE.get(); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/IAxisPipe.java b/src/main/java/com/simibubi/create/content/fluids/pipes/IAxisPipe.java similarity index 86% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/IAxisPipe.java rename to src/main/java/com/simibubi/create/content/fluids/pipes/IAxisPipe.java index 8087248e5..f6e32dfc6 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/IAxisPipe.java +++ b/src/main/java/com/simibubi/create/content/fluids/pipes/IAxisPipe.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.fluids.pipes; +package com.simibubi.create.content.fluids.pipes; import javax.annotation.Nullable; diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/SmartFluidPipeBlock.java b/src/main/java/com/simibubi/create/content/fluids/pipes/SmartFluidPipeBlock.java similarity index 89% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/SmartFluidPipeBlock.java rename to src/main/java/com/simibubi/create/content/fluids/pipes/SmartFluidPipeBlock.java index f0389c430..5b2a17b61 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/SmartFluidPipeBlock.java +++ b/src/main/java/com/simibubi/create/content/fluids/pipes/SmartFluidPipeBlock.java @@ -1,11 +1,11 @@ -package com.simibubi.create.content.contraptions.fluids.pipes; +package com.simibubi.create.content.fluids.pipes; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.fluids.FluidPropagator; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.content.fluids.FluidPropagator; import com.simibubi.create.foundation.advancement.AdvancementBehaviour; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.block.ProperWaterloggedBlock; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.VoxelShaper; @@ -36,7 +36,7 @@ import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.ticks.TickPriority; public class SmartFluidPipeBlock extends FaceAttachedHorizontalDirectionalBlock - implements ITE, IAxisPipe, IWrenchable, ProperWaterloggedBlock { + implements IBE, IAxisPipe, IWrenchable, ProperWaterloggedBlock { public SmartFluidPipeBlock(Properties p_i48339_1_) { super(p_i48339_1_); @@ -92,8 +92,7 @@ public class SmartFluidPipeBlock extends FaceAttachedHorizontalDirectionalBlock boolean blockTypeChanged = state.getBlock() != newState.getBlock(); if (blockTypeChanged && !world.isClientSide) FluidPropagator.propagateChangedPipe(world, pos, state); - if (state.hasBlockEntity() && (blockTypeChanged || !newState.hasBlockEntity())) - world.removeBlockEntity(pos); + IBE.onRemove(state, world, pos, newState); } @Override @@ -174,13 +173,13 @@ public class SmartFluidPipeBlock extends FaceAttachedHorizontalDirectionalBlock } @Override - public Class getTileEntityClass() { - return SmartFluidPipeTileEntity.class; + public Class getBlockEntityClass() { + return SmartFluidPipeBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.SMART_FLUID_PIPE.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.SMART_FLUID_PIPE.get(); } } diff --git a/src/main/java/com/simibubi/create/content/fluids/pipes/SmartFluidPipeBlockEntity.java b/src/main/java/com/simibubi/create/content/fluids/pipes/SmartFluidPipeBlockEntity.java new file mode 100644 index 000000000..3d4aa3b96 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/fluids/pipes/SmartFluidPipeBlockEntity.java @@ -0,0 +1,101 @@ +package com.simibubi.create.content.fluids.pipes; + +import java.util.List; + +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.content.fluids.FluidPropagator; +import com.simibubi.create.content.fluids.pipes.StraightPipeBlockEntity.StraightPipeFluidTransportBehaviour; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.AttachFace; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.fluids.FluidStack; + +public class SmartFluidPipeBlockEntity extends SmartBlockEntity { + + private FilteringBehaviour filter; + + public SmartFluidPipeBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + public void addBehaviours(List behaviours) { + behaviours.add(new SmartPipeBehaviour(this)); + behaviours.add(filter = new FilteringBehaviour(this, new SmartPipeFilterSlot()).forFluids() + .withCallback(this::onFilterChanged)); + registerAwardables(behaviours, FluidPropagator.getSharedTriggers()); + } + + private void onFilterChanged(ItemStack newFilter) { + if (!level.isClientSide) + FluidPropagator.propagateChangedPipe(level, worldPosition, getBlockState()); + } + + class SmartPipeBehaviour extends StraightPipeFluidTransportBehaviour { + + public SmartPipeBehaviour(SmartBlockEntity be) { + super(be); + } + + @Override + public boolean canPullFluidFrom(FluidStack fluid, BlockState state, Direction direction) { + if (fluid.isEmpty() || filter != null && filter.test(fluid)) + return super.canPullFluidFrom(fluid, state, direction); + return false; + } + + @Override + public boolean canHaveFlowToward(BlockState state, Direction direction) { + return state.getBlock() instanceof SmartFluidPipeBlock + && SmartFluidPipeBlock.getPipeAxis(state) == direction.getAxis(); + } + + } + + class SmartPipeFilterSlot extends ValueBoxTransform { + + @Override + public Vec3 getLocalOffset(BlockState state) { + AttachFace face = state.getValue(SmartFluidPipeBlock.FACE); + float y = face == AttachFace.CEILING ? 0.55f : face == AttachFace.WALL ? 11.4f : 15.45f; + float z = face == AttachFace.CEILING ? 4.6f : face == AttachFace.WALL ? 0.55f : 4.625f; + return VecHelper.rotateCentered(VecHelper.voxelSpace(8, y, z), angleY(state), Axis.Y); + } + + @Override + public float getScale() { + return super.getScale() * 1.02f; + } + + @Override + public void rotate(BlockState state, PoseStack ms) { + AttachFace face = state.getValue(SmartFluidPipeBlock.FACE); + TransformStack.cast(ms) + .rotateY(angleY(state)) + .rotateX(face == AttachFace.CEILING ? -45 : 45); + } + + protected float angleY(BlockState state) { + AttachFace face = state.getValue(SmartFluidPipeBlock.FACE); + float horizontalAngle = AngleHelper.horizontalAngle(state.getValue(SmartFluidPipeBlock.FACING)); + if (face == AttachFace.WALL) + horizontalAngle += 180; + return horizontalAngle; + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/SmartFluidPipeGenerator.java b/src/main/java/com/simibubi/create/content/fluids/pipes/SmartFluidPipeGenerator.java similarity index 95% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/SmartFluidPipeGenerator.java rename to src/main/java/com/simibubi/create/content/fluids/pipes/SmartFluidPipeGenerator.java index 4e688c80a..30c39a1de 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/SmartFluidPipeGenerator.java +++ b/src/main/java/com/simibubi/create/content/fluids/pipes/SmartFluidPipeGenerator.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.fluids.pipes; +package com.simibubi.create.content.fluids.pipes; import com.simibubi.create.foundation.data.AssetLookup; import com.simibubi.create.foundation.data.SpecialBlockStateGen; diff --git a/src/main/java/com/simibubi/create/content/fluids/pipes/StraightPipeBlockEntity.java b/src/main/java/com/simibubi/create/content/fluids/pipes/StraightPipeBlockEntity.java new file mode 100644 index 000000000..de8a98ca8 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/fluids/pipes/StraightPipeBlockEntity.java @@ -0,0 +1,68 @@ +package com.simibubi.create.content.fluids.pipes; + +import java.util.List; + +import com.simibubi.create.content.decoration.bracket.BracketedBlockEntityBehaviour; +import com.simibubi.create.content.fluids.FluidPropagator; +import com.simibubi.create.content.fluids.FluidTransportBehaviour; +import com.simibubi.create.content.fluids.pipes.valve.FluidValveBlock; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; + +public class StraightPipeBlockEntity extends SmartBlockEntity { + + public StraightPipeBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + public void addBehaviours(List behaviours) { + behaviours.add(new StraightPipeFluidTransportBehaviour(this)); + behaviours.add(new BracketedBlockEntityBehaviour(this)); + registerAwardables(behaviours, FluidPropagator.getSharedTriggers()); + } + + public static class StraightPipeFluidTransportBehaviour extends FluidTransportBehaviour { + + public StraightPipeFluidTransportBehaviour(SmartBlockEntity be) { + super(be); + } + + @Override + public boolean canHaveFlowToward(BlockState state, Direction direction) { + return state.hasProperty(AxisPipeBlock.AXIS) && state.getValue(AxisPipeBlock.AXIS) == direction.getAxis(); + } + + @Override + public AttachmentTypes getRenderedRimAttachment(BlockAndTintGetter world, BlockPos pos, BlockState state, + Direction direction) { + AttachmentTypes attachment = super.getRenderedRimAttachment(world, pos, state, direction); + BlockState otherState = world.getBlockState(pos.relative(direction)); + + Axis axis = IAxisPipe.getAxisOf(state); + Axis otherAxis = IAxisPipe.getAxisOf(otherState); + + if (attachment == AttachmentTypes.RIM && state.getBlock() instanceof FluidValveBlock) + return AttachmentTypes.NONE; + if (attachment == AttachmentTypes.RIM && FluidPipeBlock.isPipe(otherState)) + return AttachmentTypes.PARTIAL_RIM; + if (axis == otherAxis && axis != null) + return AttachmentTypes.NONE; + + if (otherState.getBlock() instanceof FluidValveBlock + && FluidValveBlock.getPipeAxis(otherState) == direction.getAxis()) + return AttachmentTypes.NONE; + + return attachment.withoutConnector(); + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/fluids/pipes/TransparentStraightPipeRenderer.java b/src/main/java/com/simibubi/create/content/fluids/pipes/TransparentStraightPipeRenderer.java new file mode 100644 index 000000000..8659592cf --- /dev/null +++ b/src/main/java/com/simibubi/create/content/fluids/pipes/TransparentStraightPipeRenderer.java @@ -0,0 +1,66 @@ +package com.simibubi.create.content.fluids.pipes; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.content.fluids.FluidTransportBehaviour; +import com.simibubi.create.content.fluids.PipeConnection.Flow; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; +import com.simibubi.create.foundation.fluid.FluidRenderer; +import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.animation.LerpedFloat; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.core.Direction; +import net.minecraftforge.fluids.FluidStack; + +public class TransparentStraightPipeRenderer extends SafeBlockEntityRenderer { + + public TransparentStraightPipeRenderer(BlockEntityRendererProvider.Context context) { + } + + @Override + protected void renderSafe(StraightPipeBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + FluidTransportBehaviour pipe = be.getBehaviour(FluidTransportBehaviour.TYPE); + if (pipe == null) + return; + + for (Direction side : Iterate.directions) { + + Flow flow = pipe.getFlow(side); + if (flow == null) + continue; + FluidStack fluidStack = flow.fluid; + if (fluidStack.isEmpty()) + continue; + LerpedFloat progress = flow.progress; + if (progress == null) + continue; + + float value = progress.getValue(partialTicks); + boolean inbound = flow.inbound; + if (value == 1) { + if (inbound) { + Flow opposite = pipe.getFlow(side.getOpposite()); + if (opposite == null) + value -= 1e-6f; + } else { + FluidTransportBehaviour adjacent = BlockEntityBehaviour.get(be.getLevel(), be.getBlockPos() + .relative(side), FluidTransportBehaviour.TYPE); + if (adjacent == null) + value -= 1e-6f; + else { + Flow other = adjacent.getFlow(side.getOpposite()); + if (other == null || !other.inbound && !other.complete) + value -= 1e-6f; + } + } + } + + FluidRenderer.renderFluidStream(fluidStack, side, 3 / 16f, value, inbound, buffer, ms, light); + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/VanillaFluidTargets.java b/src/main/java/com/simibubi/create/content/fluids/pipes/VanillaFluidTargets.java similarity index 96% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/VanillaFluidTargets.java rename to src/main/java/com/simibubi/create/content/fluids/pipes/VanillaFluidTargets.java index 0b761d4e6..d971b9b66 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/VanillaFluidTargets.java +++ b/src/main/java/com/simibubi/create/content/fluids/pipes/VanillaFluidTargets.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.fluids.pipes; +package com.simibubi.create.content.fluids.pipes; import static net.minecraft.world.level.block.state.properties.BlockStateProperties.LEVEL_HONEY; diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveBlock.java b/src/main/java/com/simibubi/create/content/fluids/pipes/valve/FluidValveBlock.java similarity index 87% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveBlock.java rename to src/main/java/com/simibubi/create/content/fluids/pipes/valve/FluidValveBlock.java index afedc3684..1bd5f0538 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveBlock.java +++ b/src/main/java/com/simibubi/create/content/fluids/pipes/valve/FluidValveBlock.java @@ -1,12 +1,14 @@ -package com.simibubi.create.content.contraptions.fluids.pipes; +package com.simibubi.create.content.fluids.pipes.valve; import javax.annotation.Nonnull; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.DirectionalAxisKineticBlock; -import com.simibubi.create.content.contraptions.fluids.FluidPropagator; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.content.fluids.FluidPropagator; +import com.simibubi.create.content.fluids.pipes.FluidPipeBlock; +import com.simibubi.create.content.fluids.pipes.IAxisPipe; +import com.simibubi.create.content.kinetics.base.DirectionalAxisKineticBlock; +import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.block.ProperWaterloggedBlock; import com.simibubi.create.foundation.utility.Iterate; @@ -33,7 +35,7 @@ import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.ticks.TickPriority; public class FluidValveBlock extends DirectionalAxisKineticBlock - implements IAxisPipe, ITE, ProperWaterloggedBlock { + implements IAxisPipe, IBE, ProperWaterloggedBlock { public static final BooleanProperty ENABLED = BooleanProperty.create("enabled"); @@ -136,13 +138,13 @@ public class FluidValveBlock extends DirectionalAxisKineticBlock } @Override - public Class getTileEntityClass() { - return FluidValveTileEntity.class; + public Class getBlockEntityClass() { + return FluidValveBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.FLUID_VALVE.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.FLUID_VALVE.get(); } @Override diff --git a/src/main/java/com/simibubi/create/content/fluids/pipes/valve/FluidValveBlockEntity.java b/src/main/java/com/simibubi/create/content/fluids/pipes/valve/FluidValveBlockEntity.java new file mode 100644 index 000000000..33726a4dd --- /dev/null +++ b/src/main/java/com/simibubi/create/content/fluids/pipes/valve/FluidValveBlockEntity.java @@ -0,0 +1,105 @@ +package com.simibubi.create.content.fluids.pipes.valve; + +import java.util.List; + +import com.simibubi.create.content.fluids.FluidPropagator; +import com.simibubi.create.content.fluids.pipes.StraightPipeBlockEntity.StraightPipeFluidTransportBehaviour; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.Mth; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.fluids.FluidStack; + +public class FluidValveBlockEntity extends KineticBlockEntity { + + LerpedFloat pointer; + + public FluidValveBlockEntity(BlockEntityType typeIn, BlockPos pos, BlockState state) { + super(typeIn, pos, state); + pointer = LerpedFloat.linear() + .startWithValue(0) + .chase(0, 0, Chaser.LINEAR); + } + + @Override + public void onSpeedChanged(float previousSpeed) { + super.onSpeedChanged(previousSpeed); + float speed = getSpeed(); + pointer.chase(speed > 0 ? 1 : 0, getChaseSpeed(), Chaser.LINEAR); + sendData(); + } + + @Override + public void tick() { + super.tick(); + pointer.tickChaser(); + + if (level.isClientSide) + return; + + BlockState blockState = getBlockState(); + if (!(blockState.getBlock() instanceof FluidValveBlock)) + return; + boolean stateOpen = blockState.getValue(FluidValveBlock.ENABLED); + + if (stateOpen && pointer.getValue() == 0) { + switchToBlockState(level, worldPosition, blockState.setValue(FluidValveBlock.ENABLED, false)); + return; + } + if (!stateOpen && pointer.getValue() == 1) { + switchToBlockState(level, worldPosition, blockState.setValue(FluidValveBlock.ENABLED, true)); + return; + } + } + + private float getChaseSpeed() { + return Mth.clamp(Math.abs(getSpeed()) / 16 / 20, 0, 1); + } + + @Override + protected void write(CompoundTag compound, boolean clientPacket) { + super.write(compound, clientPacket); + compound.put("Pointer", pointer.writeNBT()); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + super.read(compound, clientPacket); + pointer.readNBT(compound.getCompound("Pointer"), clientPacket); + } + + @Override + public void addBehaviours(List behaviours) { + behaviours.add(new ValvePipeBehaviour(this)); + registerAwardables(behaviours, FluidPropagator.getSharedTriggers()); + } + + class ValvePipeBehaviour extends StraightPipeFluidTransportBehaviour { + + public ValvePipeBehaviour(SmartBlockEntity be) { + super(be); + } + + @Override + public boolean canHaveFlowToward(BlockState state, Direction direction) { + return FluidValveBlock.getPipeAxis(state) == direction.getAxis(); + } + + @Override + public boolean canPullFluidFrom(FluidStack fluid, BlockState state, Direction direction) { + if (state.hasProperty(FluidValveBlock.ENABLED) && state.getValue(FluidValveBlock.ENABLED)) + return super.canPullFluidFrom(fluid, state, direction); + return false; + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/fluids/pipes/valve/FluidValveInstance.java b/src/main/java/com/simibubi/create/content/fluids/pipes/valve/FluidValveInstance.java new file mode 100644 index 000000000..c99af77c3 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/fluids/pipes/valve/FluidValveInstance.java @@ -0,0 +1,80 @@ +package com.simibubi.create.content.fluids.pipes.valve; + +import com.jozufozu.flywheel.api.MaterialManager; +import com.jozufozu.flywheel.api.instance.DynamicInstance; +import com.jozufozu.flywheel.core.Materials; +import com.jozufozu.flywheel.core.materials.model.ModelData; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.content.kinetics.base.ShaftInstance; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.AnimationTickHolder; + +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; + +public class FluidValveInstance extends ShaftInstance implements DynamicInstance { + + protected ModelData pointer; + protected boolean settled; + + protected final double xRot; + protected final double yRot; + protected final int pointerRotationOffset; + + public FluidValveInstance(MaterialManager dispatcher, FluidValveBlockEntity blockEntity) { + super(dispatcher, blockEntity); + + Direction facing = blockState.getValue(FluidValveBlock.FACING); + + yRot = AngleHelper.horizontalAngle(facing); + xRot = facing == Direction.UP ? 0 : facing == Direction.DOWN ? 180 : 90; + + Direction.Axis pipeAxis = FluidValveBlock.getPipeAxis(blockState); + Direction.Axis shaftAxis = KineticBlockEntityRenderer.getRotationAxisOf(blockEntity); + + boolean twist = pipeAxis.isHorizontal() && shaftAxis == Direction.Axis.X || pipeAxis.isVertical(); + pointerRotationOffset = twist ? 90 : 0; + settled = false; + + pointer = materialManager.defaultSolid() + .material(Materials.TRANSFORMED) + .getModel(AllPartialModels.FLUID_VALVE_POINTER, blockState).createInstance(); + + transformPointer(); + } + + @Override + public void beginFrame() { + if (blockEntity.pointer.settled() && settled) + return; + + transformPointer(); + } + + private void transformPointer() { + float value = blockEntity.pointer.getValue(AnimationTickHolder.getPartialTicks()); + float pointerRotation = Mth.lerp(value, 0, -90); + settled = (value == 0 || value == 1) && blockEntity.pointer.settled(); + + pointer.loadIdentity() + .translate(getInstancePosition()) + .centre() + .rotateY(yRot) + .rotateX(xRot) + .rotateY(pointerRotationOffset + pointerRotation) + .unCentre(); + } + + @Override + public void updateLight() { + super.updateLight(); + relight(pos, pointer); + } + + @Override + public void remove() { + super.remove(); + pointer.delete(); + } +} diff --git a/src/main/java/com/simibubi/create/content/fluids/pipes/valve/FluidValveRenderer.java b/src/main/java/com/simibubi/create/content/fluids/pipes/valve/FluidValveRenderer.java new file mode 100644 index 000000000..70e073573 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/fluids/pipes/valve/FluidValveRenderer.java @@ -0,0 +1,58 @@ +package com.simibubi.create.content.fluids.pipes.valve; + +import com.jozufozu.flywheel.backend.Backend; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.AngleHelper; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.util.Mth; +import net.minecraft.world.level.block.state.BlockState; + +public class FluidValveRenderer extends KineticBlockEntityRenderer { + + public FluidValveRenderer(BlockEntityRendererProvider.Context context) { + super(context); + } + + @Override + protected void renderSafe(FluidValveBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + + if (Backend.canUseInstancing(be.getLevel())) return; + + super.renderSafe(be, partialTicks, ms, buffer, light, overlay); + BlockState blockState = be.getBlockState(); + SuperByteBuffer pointer = CachedBufferer.partial(AllPartialModels.FLUID_VALVE_POINTER, blockState); + Direction facing = blockState.getValue(FluidValveBlock.FACING); + + float pointerRotation = Mth.lerp(be.pointer.getValue(partialTicks), 0, -90); + Axis pipeAxis = FluidValveBlock.getPipeAxis(blockState); + Axis shaftAxis = getRotationAxisOf(be); + + int pointerRotationOffset = 0; + if (pipeAxis.isHorizontal() && shaftAxis == Axis.X || pipeAxis.isVertical()) + pointerRotationOffset = 90; + + pointer.centre() + .rotateY(AngleHelper.horizontalAngle(facing)) + .rotateX(facing == Direction.UP ? 0 : facing == Direction.DOWN ? 180 : 90) + .rotateY(pointerRotationOffset + pointerRotation) + .unCentre() + .light(light) + .renderInto(ms, buffer.getBuffer(RenderType.solid())); + } + + @Override + protected BlockState getRenderedBlockState(FluidValveBlockEntity be) { + return shaft(getRotationAxisOf(be)); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/potion/PotionFluid.java b/src/main/java/com/simibubi/create/content/fluids/potion/PotionFluid.java similarity index 95% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/potion/PotionFluid.java rename to src/main/java/com/simibubi/create/content/fluids/potion/PotionFluid.java index 8b08ba655..fda2b5ea3 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/potion/PotionFluid.java +++ b/src/main/java/com/simibubi/create/content/fluids/potion/PotionFluid.java @@ -1,11 +1,11 @@ -package com.simibubi.create.content.contraptions.fluids.potion; +package com.simibubi.create.content.fluids.potion; import java.util.Collection; import java.util.List; import com.simibubi.create.AllFluids; import com.simibubi.create.AllFluids.TintedFluidType; -import com.simibubi.create.content.contraptions.fluids.VirtualFluid; +import com.simibubi.create.content.fluids.VirtualFluid; import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.RegisteredObjects; diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/potion/PotionFluidHandler.java b/src/main/java/com/simibubi/create/content/fluids/potion/PotionFluidHandler.java similarity index 97% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/potion/PotionFluidHandler.java rename to src/main/java/com/simibubi/create/content/fluids/potion/PotionFluidHandler.java index db2552e56..ebe37f05c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/potion/PotionFluidHandler.java +++ b/src/main/java/com/simibubi/create/content/fluids/potion/PotionFluidHandler.java @@ -1,11 +1,11 @@ -package com.simibubi.create.content.contraptions.fluids.potion; +package com.simibubi.create.content.fluids.potion; import java.util.List; import java.util.Map; import java.util.Map.Entry; import com.google.common.collect.Lists; -import com.simibubi.create.content.contraptions.fluids.potion.PotionFluid.BottleType; +import com.simibubi.create.content.fluids.potion.PotionFluid.BottleType; import com.simibubi.create.foundation.fluid.FluidHelper; import com.simibubi.create.foundation.fluid.FluidIngredient; import com.simibubi.create.foundation.utility.Components; diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/recipe/PotionMixingRecipes.java b/src/main/java/com/simibubi/create/content/fluids/potion/PotionMixingRecipes.java similarity index 91% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/recipe/PotionMixingRecipes.java rename to src/main/java/com/simibubi/create/content/fluids/potion/PotionMixingRecipes.java index 4f91335b4..4d3230eba 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/recipe/PotionMixingRecipes.java +++ b/src/main/java/com/simibubi/create/content/fluids/potion/PotionMixingRecipes.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.fluids.recipe; +package com.simibubi.create.content.fluids.potion; import java.util.ArrayList; import java.util.HashMap; @@ -8,11 +8,10 @@ import java.util.Map; import java.util.Set; import com.simibubi.create.Create; -import com.simibubi.create.content.contraptions.components.mixer.MixingRecipe; -import com.simibubi.create.content.contraptions.fluids.potion.PotionFluid.BottleType; -import com.simibubi.create.content.contraptions.fluids.potion.PotionFluidHandler; -import com.simibubi.create.content.contraptions.processing.HeatCondition; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder; +import com.simibubi.create.content.fluids.potion.PotionFluid.BottleType; +import com.simibubi.create.content.kinetics.mixer.MixingRecipe; +import com.simibubi.create.content.processing.recipe.HeatCondition; +import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder; import com.simibubi.create.foundation.fluid.FluidIngredient; import net.minecraft.world.item.Item; diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpBlock.java b/src/main/java/com/simibubi/create/content/fluids/pump/PumpBlock.java similarity index 75% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/PumpBlock.java rename to src/main/java/com/simibubi/create/content/fluids/pump/PumpBlock.java index 6e14451c2..2cfee03aa 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpBlock.java +++ b/src/main/java/com/simibubi/create/content/fluids/pump/PumpBlock.java @@ -1,11 +1,12 @@ -package com.simibubi.create.content.contraptions.fluids; +package com.simibubi.create.content.fluids.pump; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock; -import com.simibubi.create.content.contraptions.fluids.pipes.FluidPipeBlock; -import com.simibubi.create.content.contraptions.relays.elementary.ICogWheel; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.content.fluids.FluidPropagator; +import com.simibubi.create.content.fluids.pipes.FluidPipeBlock; +import com.simibubi.create.content.kinetics.base.DirectionalKineticBlock; +import com.simibubi.create.content.kinetics.simpleRelays.ICogWheel; +import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.block.ProperWaterloggedBlock; import com.simibubi.create.foundation.utility.Iterate; @@ -31,12 +32,13 @@ import net.minecraft.world.level.block.state.properties.BlockStateProperties; 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.Vec3; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.ticks.TickPriority; public class PumpBlock extends DirectionalKineticBlock - implements SimpleWaterloggedBlock, ICogWheel, ITE { + implements SimpleWaterloggedBlock, ICogWheel, IBE { public PumpBlock(Properties p_i48415_1_) { super(p_i48415_1_); @@ -106,20 +108,33 @@ public class PumpBlock extends DirectionalKineticBlock Player player = context.getPlayer(); toPlace = ProperWaterloggedBlock.withWater(level, toPlace, pos); - if (player != null && player.isSteppingCarefully()) - return toPlace; + Direction nearestLookingDirection = context.getNearestLookingDirection(); + Direction targetDirection = context.getPlayer() != null && context.getPlayer() + .isShiftKeyDown() ? nearestLookingDirection : nearestLookingDirection.getOpposite(); + Direction bestConnectedDirection = null; + double bestDistance = Double.MAX_VALUE; for (Direction d : Iterate.directions) { BlockPos adjPos = pos.relative(d); BlockState adjState = level.getBlockState(adjPos); if (!FluidPipeBlock.canConnectTo(level, adjPos, adjState, d)) continue; - toPlace = toPlace.setValue(FACING, d); - if (context.getClickedFace() == d.getOpposite()) - break; + double distance = Vec3.atLowerCornerOf(d.getNormal()) + .distanceTo(Vec3.atLowerCornerOf(targetDirection.getNormal())); + if (distance > bestDistance) + continue; + bestDistance = distance; + bestConnectedDirection = d; } - return toPlace; + if (bestConnectedDirection == null) + return toPlace; + if (bestConnectedDirection.getAxis() == targetDirection.getAxis()) + return toPlace; + if (player.isSteppingCarefully() && bestConnectedDirection.getAxis() != targetDirection.getAxis()) + return toPlace; + + return toPlace.setValue(FACING, bestConnectedDirection); } public static boolean isPump(BlockState state) { @@ -136,10 +151,10 @@ public class PumpBlock extends DirectionalKineticBlock if (isPump(state) && isPump(oldState) && state.getValue(FACING) == oldState.getValue(FACING) .getOpposite()) { - BlockEntity tileEntity = world.getBlockEntity(pos); - if (!(tileEntity instanceof PumpTileEntity)) + BlockEntity blockEntity = world.getBlockEntity(pos); + if (!(blockEntity instanceof PumpBlockEntity)) return; - PumpTileEntity pump = (PumpTileEntity) tileEntity; + PumpBlockEntity pump = (PumpBlockEntity) blockEntity; pump.pressureUpdate = true; } } @@ -168,13 +183,13 @@ public class PumpBlock extends DirectionalKineticBlock } @Override - public Class getTileEntityClass() { - return PumpTileEntity.class; + public Class getBlockEntityClass() { + return PumpBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.MECHANICAL_PUMP.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.MECHANICAL_PUMP.get(); } } diff --git a/src/main/java/com/simibubi/create/content/fluids/pump/PumpBlockEntity.java b/src/main/java/com/simibubi/create/content/fluids/pump/PumpBlockEntity.java new file mode 100644 index 000000000..3d7aca5a9 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/fluids/pump/PumpBlockEntity.java @@ -0,0 +1,373 @@ +package com.simibubi.create.content.fluids.pump; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import javax.annotation.Nullable; + +import org.apache.commons.lang3.mutable.MutableBoolean; + +import com.simibubi.create.content.fluids.FluidPropagator; +import com.simibubi.create.content.fluids.FluidTransportBehaviour; +import com.simibubi.create.content.fluids.PipeConnection; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.BlockFace; +import com.simibubi.create.foundation.utility.Couple; +import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.Pair; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler; + +public class PumpBlockEntity extends KineticBlockEntity { + + Couple sidesToUpdate; + boolean pressureUpdate; + + // Backcompat- flips any pump blockstate that loads with reversed=true + boolean scheduleFlip; + + public PumpBlockEntity(BlockEntityType typeIn, BlockPos pos, BlockState state) { + super(typeIn, pos, state); + sidesToUpdate = Couple.create(MutableBoolean::new); + } + + @Override + public void addBehaviours(List behaviours) { + super.addBehaviours(behaviours); + behaviours.add(new PumpFluidTransferBehaviour(this)); + registerAwardables(behaviours, FluidPropagator.getSharedTriggers()); + registerAwardables(behaviours, AllAdvancements.PUMP); + } + + @Override + public void tick() { + super.tick(); + + if (level.isClientSide && !isVirtual()) + return; + + if (scheduleFlip) { + level.setBlockAndUpdate(worldPosition, + getBlockState().setValue(PumpBlock.FACING, getBlockState().getValue(PumpBlock.FACING) + .getOpposite())); + scheduleFlip = false; + } + + sidesToUpdate.forEachWithContext((update, isFront) -> { + if (update.isFalse()) + return; + update.setFalse(); + distributePressureTo(isFront ? getFront() : getFront().getOpposite()); + }); + } + + @Override + public void onSpeedChanged(float previousSpeed) { + super.onSpeedChanged(previousSpeed); + + if (Math.abs(previousSpeed) == Math.abs(getSpeed())) + return; + if (speed != 0) + award(AllAdvancements.PUMP); + if (level.isClientSide && !isVirtual()) + return; + + updatePressureChange(); + } + + public void updatePressureChange() { + pressureUpdate = false; + BlockPos frontPos = worldPosition.relative(getFront()); + BlockPos backPos = worldPosition.relative(getFront().getOpposite()); + FluidPropagator.propagateChangedPipe(level, frontPos, level.getBlockState(frontPos)); + FluidPropagator.propagateChangedPipe(level, backPos, level.getBlockState(backPos)); + + FluidTransportBehaviour behaviour = getBehaviour(FluidTransportBehaviour.TYPE); + if (behaviour != null) + behaviour.wipePressure(); + sidesToUpdate.forEach(MutableBoolean::setTrue); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + super.read(compound, clientPacket); + if (compound.getBoolean("Reversed")) + scheduleFlip = true; + } + + protected void distributePressureTo(Direction side) { + if (getSpeed() == 0) + return; + + BlockFace start = new BlockFace(worldPosition, side); + boolean pull = isPullingOnSide(isFront(side)); + Set targets = new HashSet<>(); + Map>> pipeGraph = new HashMap<>(); + + if (!pull) + FluidPropagator.resetAffectedFluidNetworks(level, worldPosition, side.getOpposite()); + + if (!hasReachedValidEndpoint(level, start, pull)) { + + pipeGraph.computeIfAbsent(worldPosition, $ -> Pair.of(0, new IdentityHashMap<>())) + .getSecond() + .put(side, pull); + pipeGraph.computeIfAbsent(start.getConnectedPos(), $ -> Pair.of(1, new IdentityHashMap<>())) + .getSecond() + .put(side.getOpposite(), !pull); + + List> frontier = new ArrayList<>(); + Set visited = new HashSet<>(); + int maxDistance = FluidPropagator.getPumpRange(); + frontier.add(Pair.of(1, start.getConnectedPos())); + + while (!frontier.isEmpty()) { + Pair entry = frontier.remove(0); + int distance = entry.getFirst(); + BlockPos currentPos = entry.getSecond(); + + if (!level.isLoaded(currentPos)) + continue; + if (visited.contains(currentPos)) + continue; + visited.add(currentPos); + BlockState currentState = level.getBlockState(currentPos); + FluidTransportBehaviour pipe = FluidPropagator.getPipe(level, currentPos); + if (pipe == null) + continue; + + for (Direction face : FluidPropagator.getPipeConnections(currentState, pipe)) { + BlockFace blockFace = new BlockFace(currentPos, face); + BlockPos connectedPos = blockFace.getConnectedPos(); + + if (!level.isLoaded(connectedPos)) + continue; + if (blockFace.isEquivalent(start)) + continue; + if (hasReachedValidEndpoint(level, blockFace, pull)) { + pipeGraph.computeIfAbsent(currentPos, $ -> Pair.of(distance, new IdentityHashMap<>())) + .getSecond() + .put(face, pull); + targets.add(blockFace); + continue; + } + + FluidTransportBehaviour pipeBehaviour = FluidPropagator.getPipe(level, connectedPos); + if (pipeBehaviour == null) + continue; + if (pipeBehaviour instanceof PumpFluidTransferBehaviour) + continue; + if (visited.contains(connectedPos)) + continue; + if (distance + 1 >= maxDistance) { + pipeGraph.computeIfAbsent(currentPos, $ -> Pair.of(distance, new IdentityHashMap<>())) + .getSecond() + .put(face, pull); + targets.add(blockFace); + continue; + } + + pipeGraph.computeIfAbsent(currentPos, $ -> Pair.of(distance, new IdentityHashMap<>())) + .getSecond() + .put(face, pull); + pipeGraph.computeIfAbsent(connectedPos, $ -> Pair.of(distance + 1, new IdentityHashMap<>())) + .getSecond() + .put(face.getOpposite(), !pull); + frontier.add(Pair.of(distance + 1, connectedPos)); + } + } + } + + // DFS + Map> validFaces = new HashMap<>(); + searchForEndpointRecursively(pipeGraph, targets, validFaces, + new BlockFace(start.getPos(), start.getOppositeFace()), pull); + + float pressure = Math.abs(getSpeed()); + for (Set set : validFaces.values()) { + int parallelBranches = Math.max(1, set.size() - 1); + for (BlockFace face : set) { + BlockPos pipePos = face.getPos(); + Direction pipeSide = face.getFace(); + + if (pipePos.equals(worldPosition)) + continue; + + boolean inbound = pipeGraph.get(pipePos) + .getSecond() + .get(pipeSide); + FluidTransportBehaviour pipeBehaviour = FluidPropagator.getPipe(level, pipePos); + if (pipeBehaviour == null) + continue; + + pipeBehaviour.addPressure(pipeSide, inbound, pressure / parallelBranches); + } + } + + } + + protected boolean searchForEndpointRecursively(Map>> pipeGraph, + Set targets, Map> validFaces, BlockFace currentFace, boolean pull) { + BlockPos currentPos = currentFace.getPos(); + if (!pipeGraph.containsKey(currentPos)) + return false; + Pair> pair = pipeGraph.get(currentPos); + int distance = pair.getFirst(); + + boolean atLeastOneBranchSuccessful = false; + for (Direction nextFacing : Iterate.directions) { + if (nextFacing == currentFace.getFace()) + continue; + Map map = pair.getSecond(); + if (!map.containsKey(nextFacing)) + continue; + + BlockFace localTarget = new BlockFace(currentPos, nextFacing); + if (targets.contains(localTarget)) { + validFaces.computeIfAbsent(distance, $ -> new HashSet<>()) + .add(localTarget); + atLeastOneBranchSuccessful = true; + continue; + } + + if (map.get(nextFacing) != pull) + continue; + if (!searchForEndpointRecursively(pipeGraph, targets, validFaces, + new BlockFace(currentPos.relative(nextFacing), nextFacing.getOpposite()), pull)) + continue; + + validFaces.computeIfAbsent(distance, $ -> new HashSet<>()) + .add(localTarget); + atLeastOneBranchSuccessful = true; + } + + if (atLeastOneBranchSuccessful) + validFaces.computeIfAbsent(distance, $ -> new HashSet<>()) + .add(currentFace); + + return atLeastOneBranchSuccessful; + } + + private boolean hasReachedValidEndpoint(LevelAccessor world, BlockFace blockFace, boolean pull) { + BlockPos connectedPos = blockFace.getConnectedPos(); + BlockState connectedState = world.getBlockState(connectedPos); + BlockEntity blockEntity = world.getBlockEntity(connectedPos); + Direction face = blockFace.getFace(); + + // facing a pump + if (PumpBlock.isPump(connectedState) && connectedState.getValue(PumpBlock.FACING) + .getAxis() == face.getAxis() && blockEntity instanceof PumpBlockEntity) { + PumpBlockEntity pumpBE = (PumpBlockEntity) blockEntity; + return pumpBE.isPullingOnSide(pumpBE.isFront(blockFace.getOppositeFace())) != pull; + } + + // other pipe, no endpoint + FluidTransportBehaviour pipe = FluidPropagator.getPipe(world, connectedPos); + if (pipe != null && pipe.canHaveFlowToward(connectedState, blockFace.getOppositeFace())) + return false; + + // fluid handler endpoint + if (blockEntity != null) { + LazyOptional capability = + blockEntity.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, face.getOpposite()); + if (capability.isPresent()) + return true; + } + + // open endpoint + return FluidPropagator.isOpenEnd(world, blockFace.getPos(), face); + } + + public void updatePipesOnSide(Direction side) { + if (!isSideAccessible(side)) + return; + updatePipeNetwork(isFront(side)); + getBehaviour(FluidTransportBehaviour.TYPE).wipePressure(); + } + + protected boolean isFront(Direction side) { + BlockState blockState = getBlockState(); + if (!(blockState.getBlock() instanceof PumpBlock)) + return false; + Direction front = blockState.getValue(PumpBlock.FACING); + boolean isFront = side == front; + return isFront; + } + + @Nullable + protected Direction getFront() { + BlockState blockState = getBlockState(); + if (!(blockState.getBlock() instanceof PumpBlock)) + return null; + return blockState.getValue(PumpBlock.FACING); + } + + protected void updatePipeNetwork(boolean front) { + sidesToUpdate.get(front) + .setTrue(); + } + + public boolean isSideAccessible(Direction side) { + BlockState blockState = getBlockState(); + if (!(blockState.getBlock() instanceof PumpBlock)) + return false; + return blockState.getValue(PumpBlock.FACING) + .getAxis() == side.getAxis(); + } + + public boolean isPullingOnSide(boolean front) { + return !front; + } + + class PumpFluidTransferBehaviour extends FluidTransportBehaviour { + + public PumpFluidTransferBehaviour(SmartBlockEntity be) { + super(be); + } + + @Override + public void tick() { + super.tick(); + for (Entry entry : interfaces.entrySet()) { + boolean pull = isPullingOnSide(isFront(entry.getKey())); + Couple pressure = entry.getValue().getPressure(); + pressure.set(pull, Math.abs(getSpeed())); + pressure.set(!pull, 0f); + } + } + + @Override + public boolean canHaveFlowToward(BlockState state, Direction direction) { + return isSideAccessible(direction); + } + + @Override + public AttachmentTypes getRenderedRimAttachment(BlockAndTintGetter world, BlockPos pos, BlockState state, + Direction direction) { + AttachmentTypes attachment = super.getRenderedRimAttachment(world, pos, state, direction); + if (attachment == AttachmentTypes.RIM) + return AttachmentTypes.NONE; + return attachment; + } + + } +} diff --git a/src/main/java/com/simibubi/create/content/fluids/pump/PumpCogInstance.java b/src/main/java/com/simibubi/create/content/fluids/pump/PumpCogInstance.java new file mode 100644 index 000000000..629ec754a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/fluids/pump/PumpCogInstance.java @@ -0,0 +1,30 @@ +package com.simibubi.create.content.fluids.pump; + +import com.jozufozu.flywheel.api.Instancer; +import com.jozufozu.flywheel.api.MaterialManager; +import com.jozufozu.flywheel.api.instance.DynamicInstance; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.SingleRotatingInstance; +import com.simibubi.create.content.kinetics.base.flwdata.RotatingData; + +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; + +public class PumpCogInstance extends SingleRotatingInstance implements DynamicInstance { + + public PumpCogInstance(MaterialManager materialManager, PumpBlockEntity blockEntity) { + super(materialManager, blockEntity); + } + + @Override + public void beginFrame() {} + + @Override + protected Instancer getModel() { + BlockState referenceState = blockEntity.getBlockState(); + Direction facing = referenceState.getValue(BlockStateProperties.FACING); + return getRotatingMaterial().getModel(AllPartialModels.MECHANICAL_PUMP_COG, referenceState, facing); + } + +} diff --git a/src/main/java/com/simibubi/create/content/fluids/pump/PumpRenderer.java b/src/main/java/com/simibubi/create/content/fluids/pump/PumpRenderer.java new file mode 100644 index 000000000..294e3c6e5 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/fluids/pump/PumpRenderer.java @@ -0,0 +1,22 @@ +package com.simibubi.create.content.fluids.pump; + +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; + +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.world.level.block.state.BlockState; + +public class PumpRenderer extends KineticBlockEntityRenderer { + + public PumpRenderer(BlockEntityRendererProvider.Context context) { + super(context); + } + + @Override + protected SuperByteBuffer getRotatedModel(PumpBlockEntity be, BlockState state) { + return CachedBufferer.partialFacing(AllPartialModels.MECHANICAL_PUMP_COG, state); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FillingBySpout.java b/src/main/java/com/simibubi/create/content/fluids/spout/FillingBySpout.java similarity index 75% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FillingBySpout.java rename to src/main/java/com/simibubi/create/content/fluids/spout/FillingBySpout.java index e49bea738..2a4652694 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FillingBySpout.java +++ b/src/main/java/com/simibubi/create/content/fluids/spout/FillingBySpout.java @@ -1,10 +1,12 @@ -package com.simibubi.create.content.contraptions.fluids.actors; +package com.simibubi.create.content.fluids.spout; import java.util.List; import java.util.Optional; import com.simibubi.create.AllRecipeTypes; -import com.simibubi.create.content.contraptions.itemAssembly.SequencedAssemblyRecipe; +import com.simibubi.create.content.fluids.transfer.FillingRecipe; +import com.simibubi.create.content.fluids.transfer.GenericItemFilling; +import com.simibubi.create.content.processing.sequenced.SequencedAssemblyRecipe; import com.simibubi.create.foundation.fluid.FluidIngredient; import net.minecraft.world.item.ItemStack; @@ -16,27 +18,27 @@ import net.minecraftforge.items.wrapper.RecipeWrapper; public class FillingBySpout { - static RecipeWrapper wrapper = new RecipeWrapper(new ItemStackHandler(1)); + private static final RecipeWrapper WRAPPER = new RecipeWrapper(new ItemStackHandler(1)); public static boolean canItemBeFilled(Level world, ItemStack stack) { - wrapper.setItem(0, stack); + WRAPPER.setItem(0, stack); Optional assemblyRecipe = - SequencedAssemblyRecipe.getRecipe(world, wrapper, AllRecipeTypes.FILLING.getType(), FillingRecipe.class); + SequencedAssemblyRecipe.getRecipe(world, WRAPPER, AllRecipeTypes.FILLING.getType(), FillingRecipe.class); if (assemblyRecipe.isPresent()) return true; - if (AllRecipeTypes.FILLING.find(wrapper, world) + if (AllRecipeTypes.FILLING.find(WRAPPER, world) .isPresent()) return true; return GenericItemFilling.canItemBeFilled(world, stack); } public static int getRequiredAmountForItem(Level world, ItemStack stack, FluidStack availableFluid) { - wrapper.setItem(0, stack); + WRAPPER.setItem(0, stack); Optional assemblyRecipe = - SequencedAssemblyRecipe.getRecipe(world, wrapper, AllRecipeTypes.FILLING.getType(), FillingRecipe.class); + SequencedAssemblyRecipe.getRecipe(world, WRAPPER, AllRecipeTypes.FILLING.getType(), FillingRecipe.class); if (assemblyRecipe.isPresent()) { FluidIngredient requiredFluid = assemblyRecipe.get() .getRequiredFluid(); @@ -45,7 +47,7 @@ public class FillingBySpout { } for (Recipe recipe : world.getRecipeManager() - .getRecipesFor(AllRecipeTypes.FILLING.getType(), wrapper, world)) { + .getRecipesFor(AllRecipeTypes.FILLING.getType(), WRAPPER, world)) { FillingRecipe fillingRecipe = (FillingRecipe) recipe; FluidIngredient requiredFluid = fillingRecipe.getRequiredFluid(); if (requiredFluid.test(availableFluid)) @@ -58,15 +60,15 @@ public class FillingBySpout { FluidStack toFill = availableFluid.copy(); toFill.setAmount(requiredAmount); - wrapper.setItem(0, stack); + WRAPPER.setItem(0, stack); FillingRecipe fillingRecipe = - SequencedAssemblyRecipe.getRecipe(world, wrapper, AllRecipeTypes.FILLING.getType(), FillingRecipe.class) + SequencedAssemblyRecipe.getRecipe(world, WRAPPER, AllRecipeTypes.FILLING.getType(), FillingRecipe.class) .filter(fr -> fr.getRequiredFluid() .test(toFill)) .orElseGet(() -> { for (Recipe recipe : world.getRecipeManager() - .getRecipesFor(AllRecipeTypes.FILLING.getType(), wrapper, world)) { + .getRecipesFor(AllRecipeTypes.FILLING.getType(), WRAPPER, world)) { FillingRecipe fr = (FillingRecipe) recipe; FluidIngredient requiredFluid = fr.getRequiredFluid(); if (requiredFluid.test(toFill)) diff --git a/src/main/java/com/simibubi/create/content/fluids/spout/SpoutBlock.java b/src/main/java/com/simibubi/create/content/fluids/spout/SpoutBlock.java new file mode 100644 index 000000000..b861fbdb1 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/fluids/spout/SpoutBlock.java @@ -0,0 +1,65 @@ +package com.simibubi.create.content.fluids.spout; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllShapes; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.foundation.advancement.AdvancementBehaviour; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.blockEntity.ComparatorUtil; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.LivingEntity; +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.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.pathfinder.PathComputationType; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +public class SpoutBlock extends Block implements IWrenchable, IBE { + + public SpoutBlock(Properties p_i48440_1_) { + super(p_i48440_1_); + } + + @Override + public VoxelShape getShape(BlockState p_220053_1_, BlockGetter p_220053_2_, BlockPos p_220053_3_, + CollisionContext p_220053_4_) { + return AllShapes.SPOUT; + } + + @Override + public void setPlacedBy(Level pLevel, BlockPos pPos, BlockState pState, LivingEntity pPlacer, ItemStack pStack) { + super.setPlacedBy(pLevel, pPos, pState, pPlacer, pStack); + AdvancementBehaviour.setPlacedBy(pLevel, pPos, pPlacer); + } + + @Override + public boolean hasAnalogOutputSignal(BlockState state) { + return true; + } + + @Override + public int getAnalogOutputSignal(BlockState blockState, Level worldIn, BlockPos pos) { + return ComparatorUtil.levelOfSmartFluidTank(worldIn, pos); + } + + @Override + public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) { + return false; + } + + @Override + public Class getBlockEntityClass() { + return SpoutBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.SPOUT.get(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/fluids/spout/SpoutBlockEntity.java b/src/main/java/com/simibubi/create/content/fluids/spout/SpoutBlockEntity.java new file mode 100644 index 000000000..56af6c4e8 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/fluids/spout/SpoutBlockEntity.java @@ -0,0 +1,258 @@ +package com.simibubi.create.content.fluids.spout; + +import static com.simibubi.create.content.kinetics.belt.behaviour.BeltProcessingBehaviour.ProcessingResult.HOLD; +import static com.simibubi.create.content.kinetics.belt.behaviour.BeltProcessingBehaviour.ProcessingResult.PASS; + +import java.util.ArrayList; +import java.util.List; + +import com.simibubi.create.AllItems; +import com.simibubi.create.api.behaviour.BlockSpoutingBehaviour; +import com.simibubi.create.content.equipment.goggles.IHaveGoggleInformation; +import com.simibubi.create.content.fluids.FluidFX; +import com.simibubi.create.content.kinetics.belt.behaviour.BeltProcessingBehaviour; +import com.simibubi.create.content.kinetics.belt.behaviour.BeltProcessingBehaviour.ProcessingResult; +import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour; +import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour.TransportedResult; +import com.simibubi.create.content.kinetics.belt.transport.TransportedItemStack; +import com.simibubi.create.foundation.advancement.AdvancementBehaviour; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.fluid.SmartFluidTankBehaviour; +import com.simibubi.create.foundation.fluid.FluidHelper; +import com.simibubi.create.foundation.utility.NBTHelper; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.particles.ParticleOptions; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; + +public class SpoutBlockEntity extends SmartBlockEntity implements IHaveGoggleInformation { + + public static final int FILLING_TIME = 20; + protected BeltProcessingBehaviour beltProcessing; + + public int processingTicks; + public boolean sendSplash; + public BlockSpoutingBehaviour customProcess; + + SmartFluidTankBehaviour tank; + + private boolean createdSweetRoll, createdHoneyApple, createdChocolateBerries; + + public SpoutBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + processingTicks = -1; + } + + @Override + protected AABB createRenderBoundingBox() { + return super.createRenderBoundingBox().expandTowards(0, -2, 0); + } + + @Override + public void addBehaviours(List behaviours) { + tank = SmartFluidTankBehaviour.single(this, 1000); + behaviours.add(tank); + + beltProcessing = new BeltProcessingBehaviour(this).whenItemEnters(this::onItemReceived) + .whileItemHeld(this::whenItemHeld); + behaviours.add(beltProcessing); + + registerAwardables(behaviours, AllAdvancements.SPOUT, AllAdvancements.FOODS); + } + + protected ProcessingResult onItemReceived(TransportedItemStack transported, + TransportedItemStackHandlerBehaviour handler) { + if (handler.blockEntity.isVirtual()) + return PASS; + if (!FillingBySpout.canItemBeFilled(level, transported.stack)) + return PASS; + if (tank.isEmpty()) + return HOLD; + if (FillingBySpout.getRequiredAmountForItem(level, transported.stack, getCurrentFluidInTank()) == -1) + return PASS; + return HOLD; + } + + protected ProcessingResult whenItemHeld(TransportedItemStack transported, + TransportedItemStackHandlerBehaviour handler) { + if (processingTicks != -1 && processingTicks != 5) + return HOLD; + if (!FillingBySpout.canItemBeFilled(level, transported.stack)) + return PASS; + if (tank.isEmpty()) + return HOLD; + FluidStack fluid = getCurrentFluidInTank(); + int requiredAmountForItem = FillingBySpout.getRequiredAmountForItem(level, transported.stack, fluid.copy()); + if (requiredAmountForItem == -1) + return PASS; + if (requiredAmountForItem > fluid.getAmount()) + return HOLD; + + if (processingTicks == -1) { + processingTicks = FILLING_TIME; + notifyUpdate(); + return HOLD; + } + + // Process finished + ItemStack out = FillingBySpout.fillItem(level, requiredAmountForItem, transported.stack, fluid); + if (!out.isEmpty()) { + List outList = new ArrayList<>(); + TransportedItemStack held = null; + TransportedItemStack result = transported.copy(); + result.stack = out; + if (!transported.stack.isEmpty()) + held = transported.copy(); + outList.add(result); + handler.handleProcessingOnItem(transported, TransportedResult.convertToAndLeaveHeld(outList, held)); + } + + award(AllAdvancements.SPOUT); + if (trackFoods()) { + createdChocolateBerries |= AllItems.CHOCOLATE_BERRIES.isIn(out); + createdHoneyApple |= AllItems.HONEYED_APPLE.isIn(out); + createdSweetRoll |= AllItems.SWEET_ROLL.isIn(out); + if (createdChocolateBerries && createdHoneyApple && createdSweetRoll) + award(AllAdvancements.FOODS); + } + + tank.getPrimaryHandler() + .setFluid(fluid); + sendSplash = true; + notifyUpdate(); + return HOLD; + } + + private FluidStack getCurrentFluidInTank() { + return tank.getPrimaryHandler() + .getFluid(); + } + + @Override + protected void write(CompoundTag compound, boolean clientPacket) { + super.write(compound, clientPacket); + + compound.putInt("ProcessingTicks", processingTicks); + if (sendSplash && clientPacket) { + compound.putBoolean("Splash", true); + sendSplash = false; + } + + if (!trackFoods()) + return; + if (createdChocolateBerries) + NBTHelper.putMarker(compound, "ChocolateBerries"); + if (createdHoneyApple) + NBTHelper.putMarker(compound, "HoneyApple"); + if (createdSweetRoll) + NBTHelper.putMarker(compound, "SweetRoll"); + } + + private boolean trackFoods() { + return getBehaviour(AdvancementBehaviour.TYPE).isOwnerPresent(); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + super.read(compound, clientPacket); + processingTicks = compound.getInt("ProcessingTicks"); + + createdChocolateBerries = compound.contains("ChocolateBerries"); + createdHoneyApple = compound.contains("HoneyApple"); + createdSweetRoll = compound.contains("SweetRoll"); + + if (!clientPacket) + return; + if (compound.contains("Splash")) + spawnSplash(tank.getPrimaryTank() + .getRenderedFluid()); + } + + @Override + public LazyOptional getCapability(Capability cap, Direction side) { + if (cap == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY && side != Direction.DOWN) + return tank.getCapability() + .cast(); + return super.getCapability(cap, side); + } + + public void tick() { + super.tick(); + + FluidStack currentFluidInTank = getCurrentFluidInTank(); + if (processingTicks == -1 && (isVirtual() || !level.isClientSide()) && !currentFluidInTank.isEmpty()) { + BlockSpoutingBehaviour.forEach(behaviour -> { + if (customProcess != null) + return; + if (behaviour.fillBlock(level, worldPosition.below(2), this, currentFluidInTank, true) > 0) { + processingTicks = FILLING_TIME; + customProcess = behaviour; + notifyUpdate(); + } + }); + } + + if (processingTicks >= 0) { + processingTicks--; + if (processingTicks == 5 && customProcess != null) { + int fillBlock = customProcess.fillBlock(level, worldPosition.below(2), this, currentFluidInTank, false); + customProcess = null; + if (fillBlock > 0) { + tank.getPrimaryHandler() + .setFluid(FluidHelper.copyStackWithAmount(currentFluidInTank, + currentFluidInTank.getAmount() - fillBlock)); + sendSplash = true; + notifyUpdate(); + } + } + } + + if (processingTicks >= 8 && level.isClientSide) + spawnProcessingParticles(tank.getPrimaryTank() + .getRenderedFluid()); + } + + protected void spawnProcessingParticles(FluidStack fluid) { + if (isVirtual()) + return; + Vec3 vec = VecHelper.getCenterOf(worldPosition); + vec = vec.subtract(0, 8 / 16f, 0); + ParticleOptions particle = FluidFX.getFluidParticle(fluid); + level.addAlwaysVisibleParticle(particle, vec.x, vec.y, vec.z, 0, -.1f, 0); + } + + protected static int SPLASH_PARTICLE_COUNT = 20; + + protected void spawnSplash(FluidStack fluid) { + if (isVirtual()) + return; + Vec3 vec = VecHelper.getCenterOf(worldPosition); + vec = vec.subtract(0, 2 - 5 / 16f, 0); + ParticleOptions particle = FluidFX.getFluidParticle(fluid); + for (int i = 0; i < SPLASH_PARTICLE_COUNT; i++) { + Vec3 m = VecHelper.offsetRandomly(Vec3.ZERO, level.random, 0.125f); + m = new Vec3(m.x, Math.abs(m.y), m.z); + level.addAlwaysVisibleParticle(particle, vec.x, vec.y, vec.z, m.x, m.y, m.z); + } + } + + @Override + public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { + return containedFluidTooltip(tooltip, isPlayerSneaking, + getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY)); + } +} diff --git a/src/main/java/com/simibubi/create/content/fluids/spout/SpoutRenderer.java b/src/main/java/com/simibubi/create/content/fluids/spout/SpoutRenderer.java new file mode 100644 index 000000000..9c103dd94 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/fluids/spout/SpoutRenderer.java @@ -0,0 +1,94 @@ +package com.simibubi.create.content.fluids.spout; + +import com.jozufozu.flywheel.core.PartialModel; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.foundation.blockEntity.behaviour.fluid.SmartFluidTankBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.fluid.SmartFluidTankBehaviour.TankSegment; +import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; +import com.simibubi.create.foundation.fluid.FluidRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.util.Mth; +import net.minecraft.world.phys.AABB; +import net.minecraftforge.fluids.FluidStack; + +public class SpoutRenderer extends SafeBlockEntityRenderer { + + public SpoutRenderer(BlockEntityRendererProvider.Context context) { + } + + static final PartialModel[] BITS = + { AllPartialModels.SPOUT_TOP, AllPartialModels.SPOUT_MIDDLE, AllPartialModels.SPOUT_BOTTOM }; + + @Override + protected void renderSafe(SpoutBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + + SmartFluidTankBehaviour tank = be.tank; + if (tank == null) + return; + + TankSegment primaryTank = tank.getPrimaryTank(); + FluidStack fluidStack = primaryTank.getRenderedFluid(); + float level = primaryTank.getFluidLevel() + .getValue(partialTicks); + + if (!fluidStack.isEmpty() && level != 0) { + boolean top = fluidStack.getFluid() + .getFluidType() + .isLighterThanAir(); + + level = Math.max(level, 0.175f); + float min = 2.5f / 16f; + float max = min + (11 / 16f); + float yOffset = (11 / 16f) * level; + + ms.pushPose(); + if (!top) ms.translate(0, yOffset, 0); + else ms.translate(0, max - min, 0); + + FluidRenderer.renderFluidBox(fluidStack, + min, min - yOffset, min, + max, min, max, + buffer, ms, light, false); + + ms.popPose(); + } + + int processingTicks = be.processingTicks; + float processingPT = processingTicks - partialTicks; + float processingProgress = 1 - (processingPT - 5) / 10; + processingProgress = Mth.clamp(processingProgress, 0, 1); + float radius = 0; + + if (processingTicks != -1) { + radius = (float) (Math.pow(((2 * processingProgress) - 1), 2) - 1); + AABB bb = new AABB(0.5, .5, 0.5, 0.5, -1.2, 0.5).inflate(radius / 32f); + FluidRenderer.renderFluidBox(fluidStack, (float) bb.minX, (float) bb.minY, (float) bb.minZ, + (float) bb.maxX, (float) bb.maxY, (float) bb.maxZ, buffer, ms, light, true); + } + + float squeeze = radius; + if (processingPT < 0) + squeeze = 0; + else if (processingPT < 2) + squeeze = Mth.lerp(processingPT / 2f, 0, -1); + else if (processingPT < 10) + squeeze = -1; + + ms.pushPose(); + for (PartialModel bit : BITS) { + CachedBufferer.partial(bit, be.getBlockState()) + .light(light) + .renderInto(ms, buffer.getBuffer(RenderType.solid())); + ms.translate(0, -3 * squeeze / 32f, 0); + } + ms.popPose(); + + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/BoilerData.java b/src/main/java/com/simibubi/create/content/fluids/tank/BoilerData.java similarity index 89% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/tank/BoilerData.java rename to src/main/java/com/simibubi/create/content/fluids/tank/BoilerData.java index 890810f6d..4b9be558f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/BoilerData.java +++ b/src/main/java/com/simibubi/create/content/fluids/tank/BoilerData.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.fluids.tank; +package com.simibubi.create.content.fluids.tank; import java.util.Arrays; import java.util.HashSet; @@ -9,13 +9,13 @@ import org.jetbrains.annotations.NotNull; import com.simibubi.create.AllBlocks; import com.simibubi.create.Create; -import com.simibubi.create.content.contraptions.components.steam.SteamEngineBlock; -import com.simibubi.create.content.contraptions.components.steam.whistle.WhistleBlock; -import com.simibubi.create.content.contraptions.components.steam.whistle.WhistleTileEntity; -import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation; +import com.simibubi.create.content.decoration.steamWhistle.WhistleBlock; +import com.simibubi.create.content.decoration.steamWhistle.WhistleBlockEntity; +import com.simibubi.create.content.equipment.goggles.IHaveGoggleInformation; +import com.simibubi.create.content.kinetics.BlockStressValues; +import com.simibubi.create.content.kinetics.steamEngine.SteamEngineBlock; import com.simibubi.create.foundation.advancement.AdvancementBehaviour; import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.block.BlockStressValues; import com.simibubi.create.foundation.fluid.FluidHelper; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Iterate; @@ -66,7 +66,7 @@ public class BoilerData { public LerpedFloat gauge = LerpedFloat.linear(); - public void tick(FluidTankTileEntity controller) { + public void tick(FluidTankBlockEntity controller) { if (!isActive()) return; if (controller.getLevel().isClientSide) { @@ -96,8 +96,8 @@ public class BoilerData { for (float i : supplyOverTime) waterSupply = Math.max(i, waterSupply); } - - if (controller instanceof CreativeFluidTankTileEntity) + + if (controller instanceof CreativeFluidTankBlockEntity) waterSupply = waterSupplyPerLevel * 20; if (getActualHeat(controller.getTotalTankSize()) == 18) @@ -171,6 +171,22 @@ public class BoilerData { tooltip.add(Components.immutableEmpty()); + if (attachedEngines > 0 && maxHeatForSize > 0 && maxHeatForWater == 0 && (passiveHeat ? 1 : activeHeat) > 0) { + Lang.translate("boiler.water_input_rate") + .style(ChatFormatting.GRAY) + .forGoggles(tooltip); + Lang.number(waterSupply) + .style(ChatFormatting.BLUE) + .add(Lang.translate("generic.unit.millibuckets")) + .add(Lang.text(" / ") + .style(ChatFormatting.GRAY)) + .add(Lang.translate("boiler.per_tick", Lang.number(waterSupplyPerLevel) + .add(Lang.translate("generic.unit.millibuckets"))) + .style(ChatFormatting.DARK_GRAY)) + .forGoggles(tooltip, 1); + return true; + } + Lang.translate("tooltip.capacityProvided") .style(ChatFormatting.GRAY) .forGoggles(tooltip); @@ -250,10 +266,11 @@ public class BoilerData { } private MutableComponent bars(int level, ChatFormatting format) { - return Components.literal(Strings.repeat('|', level)).withStyle(format); + return Components.literal(Strings.repeat('|', level)) + .withStyle(format); } - public boolean evaluate(FluidTankTileEntity controller) { + public boolean evaluate(FluidTankBlockEntity controller) { BlockPos controllerPos = controller.getBlockPos(); Level level = controller.getLevel(); int prevEngines = attachedEngines; @@ -287,7 +304,7 @@ public class BoilerData { return prevEngines != attachedEngines || prevWhistles != attachedWhistles; } - public void checkPipeOrganAdvancement(FluidTankTileEntity controller) { + public void checkPipeOrganAdvancement(FluidTankBlockEntity controller) { if (!controller.getBehaviour(AdvancementBehaviour.TYPE) .isOwnerPresent()) return; @@ -310,8 +327,8 @@ public class BoilerData { if (AllBlocks.STEAM_WHISTLE.has(attachedState) && WhistleBlock.getAttachedDirection(attachedState) .getOpposite() == d) { - if (level.getBlockEntity(attachedPos)instanceof WhistleTileEntity wte) - whistlePitches.add(wte.getPitchId()); + if (level.getBlockEntity(attachedPos) instanceof WhistleBlockEntity wbe) + whistlePitches.add(wbe.getPitchId()); } } } @@ -322,7 +339,7 @@ public class BoilerData { controller.award(AllAdvancements.PIPE_ORGAN); } - public boolean updateTemperature(FluidTankTileEntity controller) { + public boolean updateTemperature(FluidTankBlockEntity controller) { BlockPos controllerPos = controller.getBlockPos(); Level level = controller.getLevel(); needsHeatLevelUpdate = false; diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/BoilerHeaters.java b/src/main/java/com/simibubi/create/content/fluids/tank/BoilerHeaters.java similarity index 85% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/tank/BoilerHeaters.java rename to src/main/java/com/simibubi/create/content/fluids/tank/BoilerHeaters.java index 07776ca01..7e5458425 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/BoilerHeaters.java +++ b/src/main/java/com/simibubi/create/content/fluids/tank/BoilerHeaters.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.fluids.tank; +package com.simibubi.create.content.fluids.tank; import java.util.ArrayList; import java.util.List; @@ -7,9 +7,9 @@ import org.jetbrains.annotations.Nullable; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllTags.AllBlockTags; -import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock; -import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.HeatLevel; -import com.simibubi.create.foundation.utility.CreateRegistry; +import com.simibubi.create.content.processing.burner.BlazeBurnerBlock; +import com.simibubi.create.content.processing.burner.BlazeBurnerBlock.HeatLevel; +import com.simibubi.create.foundation.utility.AttachedRegistry; import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceLocation; @@ -19,7 +19,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraftforge.registries.ForgeRegistries; public class BoilerHeaters { - private static final CreateRegistry BLOCK_HEATERS = new CreateRegistry<>(ForgeRegistries.BLOCKS); + private static final AttachedRegistry BLOCK_HEATERS = new AttachedRegistry<>(ForgeRegistries.BLOCKS); private static final List GLOBAL_HEATERS = new ArrayList<>(); public static void registerHeater(ResourceLocation block, Heater heater) { diff --git a/src/main/java/com/simibubi/create/content/fluids/tank/CreativeFluidTankBlockEntity.java b/src/main/java/com/simibubi/create/content/fluids/tank/CreativeFluidTankBlockEntity.java new file mode 100644 index 000000000..e0c5a55dc --- /dev/null +++ b/src/main/java/com/simibubi/create/content/fluids/tank/CreativeFluidTankBlockEntity.java @@ -0,0 +1,65 @@ +package com.simibubi.create.content.fluids.tank; + +import java.util.List; +import java.util.function.Consumer; + +import com.simibubi.create.foundation.fluid.SmartFluidTank; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.fluids.FluidStack; + +public class CreativeFluidTankBlockEntity extends FluidTankBlockEntity { + + public CreativeFluidTankBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + protected SmartFluidTank createInventory() { + return new CreativeSmartFluidTank(getCapacityMultiplier(), this::onFluidStackChanged); + } + + @Override + public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { + return false; + } + + public static class CreativeSmartFluidTank extends SmartFluidTank { + + public CreativeSmartFluidTank(int capacity, Consumer updateCallback) { + super(capacity, updateCallback); + } + + @Override + public int getFluidAmount() { + return getFluid().isEmpty() ? 0 : getTankCapacity(0); + } + + public void setContainedFluid(FluidStack fluidStack) { + fluid = fluidStack.copy(); + if (!fluidStack.isEmpty()) + fluid.setAmount(getTankCapacity(0)); + onContentsChanged(); + } + + @Override + public int fill(FluidStack resource, FluidAction action) { + return resource.getAmount(); + } + + @Override + public FluidStack drain(FluidStack resource, FluidAction action) { + return super.drain(resource, FluidAction.SIMULATE); + } + + @Override + public FluidStack drain(int maxDrain, FluidAction action) { + return super.drain(maxDrain, FluidAction.SIMULATE); + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankBlock.java b/src/main/java/com/simibubi/create/content/fluids/tank/FluidTankBlock.java similarity index 79% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankBlock.java rename to src/main/java/com/simibubi/create/content/fluids/tank/FluidTankBlock.java index a050729ea..203f80496 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankBlock.java +++ b/src/main/java/com/simibubi/create/content/fluids/tank/FluidTankBlock.java @@ -1,16 +1,16 @@ -package com.simibubi.create.content.contraptions.fluids.tank; +package com.simibubi.create.content.fluids.tank; -import com.simibubi.create.AllTileEntities; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.api.connectivity.ConnectivityHandler; -import com.simibubi.create.content.contraptions.fluids.actors.GenericItemFilling; -import com.simibubi.create.content.contraptions.fluids.tank.CreativeFluidTankTileEntity.CreativeSmartFluidTank; -import com.simibubi.create.content.contraptions.processing.EmptyingByBasin; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.content.fluids.tank.CreativeFluidTankBlockEntity.CreativeSmartFluidTank; +import com.simibubi.create.content.fluids.transfer.GenericItemEmptying; +import com.simibubi.create.content.fluids.transfer.GenericItemFilling; import com.simibubi.create.foundation.advancement.AdvancementBehaviour; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.blockEntity.ComparatorUtil; import com.simibubi.create.foundation.fluid.FluidHelper; import com.simibubi.create.foundation.fluid.FluidHelper.FluidExchange; -import com.simibubi.create.foundation.tileEntity.ComparatorUtil; import com.simibubi.create.foundation.utility.Lang; import net.minecraft.core.BlockPos; @@ -55,7 +55,7 @@ import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler; -public class FluidTankBlock extends Block implements IWrenchable, ITE { +public class FluidTankBlock extends Block implements IWrenchable, IBE { public static final BooleanProperty TOP = BooleanProperty.create("top"); public static final BooleanProperty BOTTOM = BooleanProperty.create("bottom"); @@ -95,7 +95,7 @@ public class FluidTankBlock extends Block implements IWrenchable, ITE tankCapability = te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY); + LazyOptional tankCapability = be.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY); if (!tankCapability.isPresent()) return InteractionResult.PASS; IFluidHandler fluidTank = tankCapability.orElse(null); FluidStack prevFluidInTank = fluidTank.getFluidInTank(0) .copy(); - if (FluidHelper.tryEmptyItemIntoTE(world, player, hand, heldItem, te)) + if (FluidHelper.tryEmptyItemIntoBE(world, player, hand, heldItem, be)) exchange = FluidExchange.ITEM_TO_TANK; - else if (FluidHelper.tryFillItemFromTE(world, player, hand, heldItem, te)) + else if (FluidHelper.tryFillItemFromBE(world, player, hand, heldItem, be)) exchange = FluidExchange.TANK_TO_ITEM; if (exchange == null) { - if (EmptyingByBasin.canItemBeEmptied(world, heldItem) + if (GenericItemEmptying.canItemBeEmptied(world, heldItem) || GenericItemFilling.canItemBeFilled(world, heldItem)) return InteractionResult.SUCCESS; return InteractionResult.PASS; @@ -185,7 +185,7 @@ public class FluidTankBlock extends Block implements IWrenchable, ITE getTileEntityClass() { - return FluidTankTileEntity.class; + public Class getBlockEntityClass() { + return FluidTankBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return creative ? AllTileEntities.CREATIVE_FLUID_TANK.get() : AllTileEntities.FLUID_TANK.get(); + public BlockEntityType getBlockEntityType() { + return creative ? AllBlockEntityTypes.CREATIVE_FLUID_TANK.get() : AllBlockEntityTypes.FLUID_TANK.get(); } @Override @@ -345,8 +345,8 @@ public class FluidTankBlock extends Block implements IWrenchable, ITE ComparatorUtil.fractionToRedstoneLevel(te.getFillState())) + return getBlockEntityOptional(worldIn, pos).map(FluidTankBlockEntity::getControllerBE) + .map(be -> ComparatorUtil.fractionToRedstoneLevel(be.getFillState())) .orElse(0); } @@ -354,13 +354,13 @@ public class FluidTankBlock extends Block implements IWrenchable, ITE fluidCapability; + protected boolean forceFluidLevelUpdate; + protected FluidTank tankInventory; + protected BlockPos controller; + protected BlockPos lastKnownPos; + protected boolean updateConnectivity; + protected boolean window; + protected int luminosity; + protected int width; + protected int height; + + public BoilerData boiler; + + private static final int SYNC_RATE = 8; + protected int syncCooldown; + protected boolean queuedSync; + + // For rendering purposes only + private LerpedFloat fluidLevel; + + public FluidTankBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + tankInventory = createInventory(); + fluidCapability = LazyOptional.of(() -> tankInventory); + forceFluidLevelUpdate = true; + updateConnectivity = false; + window = true; + height = 1; + width = 1; + boiler = new BoilerData(); + refreshCapability(); + } + + protected SmartFluidTank createInventory() { + return new SmartFluidTank(getCapacityMultiplier(), this::onFluidStackChanged); + } + + protected void updateConnectivity() { + updateConnectivity = false; + if (level.isClientSide) + return; + if (!isController()) + return; + ConnectivityHandler.formMulti(this); + } + + @Override + public void tick() { + super.tick(); + if (syncCooldown > 0) { + syncCooldown--; + if (syncCooldown == 0 && queuedSync) + sendData(); + } + + if (lastKnownPos == null) + lastKnownPos = getBlockPos(); + else if (!lastKnownPos.equals(worldPosition) && worldPosition != null) { + onPositionChanged(); + return; + } + + if (updateConnectivity) + updateConnectivity(); + if (fluidLevel != null) + fluidLevel.tickChaser(); + if (isController()) + boiler.tick(this); + } + + @Override + public BlockPos getLastKnownPos() { + return lastKnownPos; + } + + @Override + public boolean isController() { + return controller == null || worldPosition.getX() == controller.getX() + && worldPosition.getY() == controller.getY() && worldPosition.getZ() == controller.getZ(); + } + + @Override + public void initialize() { + super.initialize(); + sendData(); + if (level.isClientSide) + invalidateRenderBoundingBox(); + } + + private void onPositionChanged() { + removeController(true); + lastKnownPos = worldPosition; + } + + protected void onFluidStackChanged(FluidStack newFluidStack) { + if (!hasLevel()) + return; + + FluidType attributes = newFluidStack.getFluid() + .getFluidType(); + int luminosity = (int) (attributes.getLightLevel(newFluidStack) / 1.2f); + boolean reversed = attributes.isLighterThanAir(); + int maxY = (int) ((getFillState() * height) + 1); + + for (int yOffset = 0; yOffset < height; yOffset++) { + boolean isBright = reversed ? (height - yOffset <= maxY) : (yOffset < maxY); + int actualLuminosity = isBright ? luminosity : luminosity > 0 ? 1 : 0; + + for (int xOffset = 0; xOffset < width; xOffset++) { + for (int zOffset = 0; zOffset < width; zOffset++) { + BlockPos pos = this.worldPosition.offset(xOffset, yOffset, zOffset); + FluidTankBlockEntity tankAt = ConnectivityHandler.partAt(getType(), level, pos); + if (tankAt == null) + continue; + level.updateNeighbourForOutputSignal(pos, tankAt.getBlockState() + .getBlock()); + if (tankAt.luminosity == actualLuminosity) + continue; + tankAt.setLuminosity(actualLuminosity); + } + } + } + + if (!level.isClientSide) { + setChanged(); + sendData(); + } + + if (isVirtual()) { + if (fluidLevel == null) + fluidLevel = LerpedFloat.linear() + .startWithValue(getFillState()); + fluidLevel.chase(getFillState(), .5f, Chaser.EXP); + } + } + + protected void setLuminosity(int luminosity) { + if (level.isClientSide) + return; + if (this.luminosity == luminosity) + return; + this.luminosity = luminosity; + sendData(); + } + + @SuppressWarnings("unchecked") + @Override + public FluidTankBlockEntity getControllerBE() { + if (isController()) + return this; + BlockEntity blockEntity = level.getBlockEntity(controller); + if (blockEntity instanceof FluidTankBlockEntity) + return (FluidTankBlockEntity) blockEntity; + return null; + } + + public void applyFluidTankSize(int blocks) { + tankInventory.setCapacity(blocks * getCapacityMultiplier()); + int overflow = tankInventory.getFluidAmount() - tankInventory.getCapacity(); + if (overflow > 0) + tankInventory.drain(overflow, FluidAction.EXECUTE); + forceFluidLevelUpdate = true; + } + + public void removeController(boolean keepFluids) { + if (level.isClientSide) + return; + updateConnectivity = true; + if (!keepFluids) + applyFluidTankSize(1); + controller = null; + width = 1; + height = 1; + boiler.clear(); + onFluidStackChanged(tankInventory.getFluid()); + + BlockState state = getBlockState(); + if (FluidTankBlock.isTank(state)) { + state = state.setValue(FluidTankBlock.BOTTOM, true); + state = state.setValue(FluidTankBlock.TOP, true); + state = state.setValue(FluidTankBlock.SHAPE, window ? Shape.WINDOW : Shape.PLAIN); + getLevel().setBlock(worldPosition, state, 22); + } + + refreshCapability(); + setChanged(); + sendData(); + } + + public void toggleWindows() { + FluidTankBlockEntity be = getControllerBE(); + if (be == null) + return; + if (be.boiler.isActive()) + return; + be.setWindows(!be.window); + } + + public void updateBoilerTemperature() { + FluidTankBlockEntity be = getControllerBE(); + if (be == null) + return; + if (!be.boiler.isActive()) + return; + be.boiler.needsHeatLevelUpdate = true; + } + + public void sendDataImmediately() { + syncCooldown = 0; + queuedSync = false; + sendData(); + } + + @Override + public void sendData() { + if (syncCooldown > 0) { + queuedSync = true; + return; + } + super.sendData(); + queuedSync = false; + syncCooldown = SYNC_RATE; + } + + public void setWindows(boolean window) { + this.window = window; + for (int yOffset = 0; yOffset < height; yOffset++) { + for (int xOffset = 0; xOffset < width; xOffset++) { + for (int zOffset = 0; zOffset < width; zOffset++) { + + BlockPos pos = this.worldPosition.offset(xOffset, yOffset, zOffset); + BlockState blockState = level.getBlockState(pos); + if (!FluidTankBlock.isTank(blockState)) + continue; + + Shape shape = Shape.PLAIN; + if (window) { + // SIZE 1: Every tank has a window + if (width == 1) + shape = Shape.WINDOW; + // SIZE 2: Every tank has a corner window + if (width == 2) + shape = xOffset == 0 ? zOffset == 0 ? Shape.WINDOW_NW : Shape.WINDOW_SW + : zOffset == 0 ? Shape.WINDOW_NE : Shape.WINDOW_SE; + // SIZE 3: Tanks in the center have a window + if (width == 3 && abs(abs(xOffset) - abs(zOffset)) == 1) + shape = Shape.WINDOW; + } + + level.setBlock(pos, blockState.setValue(FluidTankBlock.SHAPE, shape), 22); + level.getChunkSource() + .getLightEngine() + .checkBlock(pos); + } + } + } + } + + public void updateBoilerState() { + if (!isController()) + return; + + boolean wasBoiler = boiler.isActive(); + boolean changed = boiler.evaluate(this); + + if (wasBoiler != boiler.isActive()) { + if (boiler.isActive()) + setWindows(false); + + for (int yOffset = 0; yOffset < height; yOffset++) + for (int xOffset = 0; xOffset < width; xOffset++) + for (int zOffset = 0; zOffset < width; zOffset++) + if (level.getBlockEntity( + worldPosition.offset(xOffset, yOffset, zOffset)) instanceof FluidTankBlockEntity fbe) + fbe.refreshCapability(); + } + + if (changed) { + notifyUpdate(); + boiler.checkPipeOrganAdvancement(this); + } + } + + @Override + public void setController(BlockPos controller) { + if (level.isClientSide && !isVirtual()) + return; + if (controller.equals(this.controller)) + return; + this.controller = controller; + refreshCapability(); + setChanged(); + sendData(); + } + + private void refreshCapability() { + LazyOptional oldCap = fluidCapability; + fluidCapability = LazyOptional.of(() -> handlerForCapability()); + oldCap.invalidate(); + } + + private IFluidHandler handlerForCapability() { + return isController() ? boiler.isActive() ? boiler.createHandler() : tankInventory + : getControllerBE() != null ? getControllerBE().handlerForCapability() : new FluidTank(0); + } + + @Override + public BlockPos getController() { + return isController() ? worldPosition : controller; + } + + @Override + protected AABB createRenderBoundingBox() { + if (isController()) + return super.createRenderBoundingBox().expandTowards(width - 1, height - 1, width - 1); + else + return super.createRenderBoundingBox(); + } + + @Nullable + public FluidTankBlockEntity getOtherFluidTankBlockEntity(Direction direction) { + BlockEntity otherBE = level.getBlockEntity(worldPosition.relative(direction)); + if (otherBE instanceof FluidTankBlockEntity) + return (FluidTankBlockEntity) otherBE; + return null; + } + + @Override + public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { + FluidTankBlockEntity controllerBE = getControllerBE(); + if (controllerBE == null) + return false; + if (controllerBE.boiler.addToGoggleTooltip(tooltip, isPlayerSneaking, controllerBE.getTotalTankSize())) + return true; + return containedFluidTooltip(tooltip, isPlayerSneaking, + controllerBE.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY)); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + super.read(compound, clientPacket); + + BlockPos controllerBefore = controller; + int prevSize = width; + int prevHeight = height; + int prevLum = luminosity; + + updateConnectivity = compound.contains("Uninitialized"); + luminosity = compound.getInt("Luminosity"); + controller = null; + lastKnownPos = null; + + if (compound.contains("LastKnownPos")) + lastKnownPos = NbtUtils.readBlockPos(compound.getCompound("LastKnownPos")); + if (compound.contains("Controller")) + controller = NbtUtils.readBlockPos(compound.getCompound("Controller")); + + if (isController()) { + window = compound.getBoolean("Window"); + width = compound.getInt("Size"); + height = compound.getInt("Height"); + tankInventory.setCapacity(getTotalTankSize() * getCapacityMultiplier()); + tankInventory.readFromNBT(compound.getCompound("TankContent")); + if (tankInventory.getSpace() < 0) + tankInventory.drain(-tankInventory.getSpace(), FluidAction.EXECUTE); + } + + boiler.read(compound.getCompound("Boiler"), width * width * height); + + if (compound.contains("ForceFluidLevel") || fluidLevel == null) + fluidLevel = LerpedFloat.linear() + .startWithValue(getFillState()); + + if (!clientPacket) + return; + + boolean changeOfController = + controllerBefore == null ? controller != null : !controllerBefore.equals(controller); + if (changeOfController || prevSize != width || prevHeight != height) { + if (hasLevel()) + level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 16); + if (isController()) + tankInventory.setCapacity(getCapacityMultiplier() * getTotalTankSize()); + invalidateRenderBoundingBox(); + } + if (isController()) { + float fillState = getFillState(); + if (compound.contains("ForceFluidLevel") || fluidLevel == null) + fluidLevel = LerpedFloat.linear() + .startWithValue(fillState); + fluidLevel.chase(fillState, 0.5f, Chaser.EXP); + } + if (luminosity != prevLum && hasLevel()) + level.getChunkSource() + .getLightEngine() + .checkBlock(worldPosition); + + if (compound.contains("LazySync")) + fluidLevel.chase(fluidLevel.getChaseTarget(), 0.125f, Chaser.EXP); + } + + public float getFillState() { + return (float) tankInventory.getFluidAmount() / tankInventory.getCapacity(); + } + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + if (updateConnectivity) + compound.putBoolean("Uninitialized", true); + compound.put("Boiler", boiler.write()); + if (lastKnownPos != null) + compound.put("LastKnownPos", NbtUtils.writeBlockPos(lastKnownPos)); + if (!isController()) + compound.put("Controller", NbtUtils.writeBlockPos(controller)); + if (isController()) { + compound.putBoolean("Window", window); + compound.put("TankContent", tankInventory.writeToNBT(new CompoundTag())); + compound.putInt("Size", width); + compound.putInt("Height", height); + } + compound.putInt("Luminosity", luminosity); + super.write(compound, clientPacket); + + if (!clientPacket) + return; + if (forceFluidLevelUpdate) + compound.putBoolean("ForceFluidLevel", true); + if (queuedSync) + compound.putBoolean("LazySync", true); + forceFluidLevelUpdate = false; + } + + @Nonnull + @Override + public LazyOptional getCapability(@Nonnull Capability cap, @Nullable Direction side) { + if (!fluidCapability.isPresent()) + refreshCapability(); + if (cap == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) + return fluidCapability.cast(); + return super.getCapability(cap, side); + } + + @Override + public void invalidate() { + super.invalidate(); + } + + @Override + public void addBehaviours(List behaviours) { + registerAwardables(behaviours, AllAdvancements.STEAM_ENGINE_MAXED, AllAdvancements.PIPE_ORGAN); + } + + public IFluidTank getTankInventory() { + return tankInventory; + } + + public int getTotalTankSize() { + return width * width * height; + } + + public static int getMaxSize() { + return MAX_SIZE; + } + + public static int getCapacityMultiplier() { + return AllConfigs.server().fluids.fluidTankCapacity.get() * 1000; + } + + public static int getMaxHeight() { + return AllConfigs.server().fluids.fluidTankMaxHeight.get(); + } + + public LerpedFloat getFluidLevel() { + return fluidLevel; + } + + public void setFluidLevel(LerpedFloat fluidLevel) { + this.fluidLevel = fluidLevel; + } + + @Override + public void preventConnectivityUpdate() { + updateConnectivity = false; + } + + @Override + public void notifyMultiUpdated() { + BlockState state = this.getBlockState(); + if (FluidTankBlock.isTank(state)) { // safety + state = state.setValue(FluidTankBlock.BOTTOM, getController().getY() == getBlockPos().getY()); + state = state.setValue(FluidTankBlock.TOP, getController().getY() + height - 1 == getBlockPos().getY()); + level.setBlock(getBlockPos(), state, 6); + } + if (isController()) + setWindows(window); + onFluidStackChanged(tankInventory.getFluid()); + updateBoilerState(); + setChanged(); + } + + @Override + public void setExtraData(@Nullable Object data) { + if (data instanceof Boolean) + window = (boolean) data; + } + + @Override + @Nullable + public Object getExtraData() { + return window; + } + + @Override + public Object modifyExtraData(Object data) { + if (data instanceof Boolean windows) { + windows |= window; + return windows; + } + return data; + } + + @Override + public Direction.Axis getMainConnectionAxis() { + return Direction.Axis.Y; + } + + @Override + public int getMaxLength(Direction.Axis longAxis, int width) { + if (longAxis == Direction.Axis.Y) + return getMaxHeight(); + return getMaxWidth(); + } + + @Override + public int getMaxWidth() { + return MAX_SIZE; + } + + @Override + public int getHeight() { + return height; + } + + @Override + public void setHeight(int height) { + this.height = height; + } + + @Override + public int getWidth() { + return width; + } + + @Override + public void setWidth(int width) { + this.width = width; + } + + @Override + public boolean hasTank() { + return true; + } + + @Override + public int getTankSize(int tank) { + return getCapacityMultiplier(); + } + + @Override + public void setTankSize(int tank, int blocks) { + applyFluidTankSize(blocks); + } + + @Override + public IFluidTank getTank(int tank) { + return tankInventory; + } + + @Override + public FluidStack getFluid(int tank) { + return tankInventory.getFluid() + .copy(); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankCTBehaviour.java b/src/main/java/com/simibubi/create/content/fluids/tank/FluidTankCTBehaviour.java similarity index 95% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankCTBehaviour.java rename to src/main/java/com/simibubi/create/content/fluids/tank/FluidTankCTBehaviour.java index 845fecb94..d197b6c97 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankCTBehaviour.java +++ b/src/main/java/com/simibubi/create/content/fluids/tank/FluidTankCTBehaviour.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.fluids.tank; +package com.simibubi.create.content.fluids.tank; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankGenerator.java b/src/main/java/com/simibubi/create/content/fluids/tank/FluidTankGenerator.java similarity index 93% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankGenerator.java rename to src/main/java/com/simibubi/create/content/fluids/tank/FluidTankGenerator.java index fb366a8e9..183dff0de 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankGenerator.java +++ b/src/main/java/com/simibubi/create/content/fluids/tank/FluidTankGenerator.java @@ -1,6 +1,6 @@ -package com.simibubi.create.content.contraptions.fluids.tank; +package com.simibubi.create.content.fluids.tank; -import com.simibubi.create.content.contraptions.fluids.tank.FluidTankBlock.Shape; +import com.simibubi.create.content.fluids.tank.FluidTankBlock.Shape; import com.simibubi.create.foundation.data.AssetLookup; import com.simibubi.create.foundation.data.SpecialBlockStateGen; import com.tterrag.registrate.providers.DataGenContext; diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankItem.java b/src/main/java/com/simibubi/create/content/fluids/tank/FluidTankItem.java similarity index 85% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankItem.java rename to src/main/java/com/simibubi/create/content/fluids/tank/FluidTankItem.java index 22fb7387e..b5df74db5 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankItem.java +++ b/src/main/java/com/simibubi/create/content/fluids/tank/FluidTankItem.java @@ -1,7 +1,7 @@ -package com.simibubi.create.content.contraptions.fluids.tank; +package com.simibubi.create.content.fluids.tank; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllTileEntities; import com.simibubi.create.api.connectivity.ConnectivityHandler; import net.minecraft.core.BlockPos; @@ -49,7 +49,7 @@ public class FluidTankItem extends BlockItem { if (nbt.contains("TankContent")) { FluidStack fluid = FluidStack.loadFluidStackFromNBT(nbt.getCompound("TankContent")); if (!fluid.isEmpty()) { - fluid.setAmount(Math.min(FluidTankTileEntity.getCapacityMultiplier(), fluid.getAmount())); + fluid.setAmount(Math.min(FluidTankBlockEntity.getCapacityMultiplier(), fluid.getAmount())); nbt.put("TankContent", fluid.writeToNBT(new CompoundTag())); } } @@ -76,24 +76,24 @@ public class FluidTankItem extends BlockItem { if (!FluidTankBlock.isTank(placedOnState)) return; boolean creative = getBlock().equals(AllBlocks.CREATIVE_FLUID_TANK.get()); - FluidTankTileEntity tankAt = ConnectivityHandler.partAt( - creative ? AllTileEntities.CREATIVE_FLUID_TANK.get() : AllTileEntities.FLUID_TANK.get(), world, placedOnPos + FluidTankBlockEntity tankAt = ConnectivityHandler.partAt( + creative ? AllBlockEntityTypes.CREATIVE_FLUID_TANK.get() : AllBlockEntityTypes.FLUID_TANK.get(), world, placedOnPos ); if (tankAt == null) return; - FluidTankTileEntity controllerTE = tankAt.getControllerTE(); - if (controllerTE == null) + FluidTankBlockEntity controllerBE = tankAt.getControllerBE(); + if (controllerBE == null) return; - int width = controllerTE.width; + int width = controllerBE.width; if (width == 1) return; int tanksToPlace = 0; - BlockPos startPos = face == Direction.DOWN ? controllerTE.getBlockPos() + BlockPos startPos = face == Direction.DOWN ? controllerBE.getBlockPos() .below() - : controllerTE.getBlockPos() - .above(controllerTE.height); + : controllerBE.getBlockPos() + .above(controllerBE.height); if (startPos.getY() != pos.getY()) return; diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankModel.java b/src/main/java/com/simibubi/create/content/fluids/tank/FluidTankModel.java similarity index 89% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankModel.java rename to src/main/java/com/simibubi/create/content/fluids/tank/FluidTankModel.java index 8fad341a4..475263e3d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankModel.java +++ b/src/main/java/com/simibubi/create/content/fluids/tank/FluidTankModel.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.fluids.tank; +package com.simibubi.create.content.fluids.tank; import java.util.ArrayList; import java.util.Arrays; @@ -43,11 +43,13 @@ public class FluidTankModel extends CTModel { } @Override - protected Builder gatherModelData(Builder builder, BlockAndTintGetter world, BlockPos pos, BlockState state) { + protected ModelData.Builder gatherModelData(Builder builder, BlockAndTintGetter world, BlockPos pos, BlockState state, + ModelData blockEntityData) { + super.gatherModelData(builder, world, pos, state, blockEntityData); CullData cullData = new CullData(); for (Direction d : Iterate.horizontalDirections) cullData.setCulled(d, ConnectivityHandler.isConnected(world, pos, pos.relative(d))); - return super.gatherModelData(builder, world, pos, state).with(CULL_PROPERTY, cullData); + return builder.with(CULL_PROPERTY, cullData); } @Override @@ -66,7 +68,7 @@ public class FluidTankModel extends CTModel { return quads; } - private class CullData { + private static class CullData { boolean[] culledFaces; public CullData() { diff --git a/src/main/java/com/simibubi/create/content/fluids/tank/FluidTankRenderer.java b/src/main/java/com/simibubi/create/content/fluids/tank/FluidTankRenderer.java new file mode 100644 index 000000000..e1acc93ad --- /dev/null +++ b/src/main/java/com/simibubi/create/content/fluids/tank/FluidTankRenderer.java @@ -0,0 +1,119 @@ +package com.simibubi.create.content.fluids.tank; + +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; +import com.simibubi.create.foundation.fluid.FluidRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.animation.LerpedFloat; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.templates.FluidTank; + +public class FluidTankRenderer extends SafeBlockEntityRenderer { + + public FluidTankRenderer(BlockEntityRendererProvider.Context context) {} + + @Override + protected void renderSafe(FluidTankBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + if (!be.isController()) + return; + if (!be.window) { + if (be.boiler.isActive()) + renderAsBoiler(be, partialTicks, ms, buffer, light, overlay); + return; + } + + LerpedFloat fluidLevel = be.getFluidLevel(); + if (fluidLevel == null) + return; + + float capHeight = 1 / 4f; + float tankHullWidth = 1 / 16f + 1 / 128f; + float minPuddleHeight = 1 / 16f; + float totalHeight = be.height - 2 * capHeight - minPuddleHeight; + + float level = fluidLevel.getValue(partialTicks); + if (level < 1 / (512f * totalHeight)) + return; + float clampedLevel = Mth.clamp(level * totalHeight, 0, totalHeight); + + FluidTank tank = be.tankInventory; + FluidStack fluidStack = tank.getFluid(); + + if (fluidStack.isEmpty()) + return; + + boolean top = fluidStack.getFluid() + .getFluidType() + .isLighterThanAir(); + + float xMin = tankHullWidth; + float xMax = xMin + be.width - 2 * tankHullWidth; + float yMin = totalHeight + capHeight + minPuddleHeight - clampedLevel; + float yMax = yMin + clampedLevel; + + if (top) { + yMin += totalHeight - clampedLevel; + yMax += totalHeight - clampedLevel; + } + + float zMin = tankHullWidth; + float zMax = zMin + be.width - 2 * tankHullWidth; + + ms.pushPose(); + ms.translate(0, clampedLevel - totalHeight, 0); + FluidRenderer.renderFluidBox(fluidStack, xMin, yMin, zMin, xMax, yMax, zMax, buffer, ms, light, false); + ms.popPose(); + } + + protected void renderAsBoiler(FluidTankBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + BlockState blockState = be.getBlockState(); + VertexConsumer vb = buffer.getBuffer(RenderType.solid()); + ms.pushPose(); + TransformStack msr = TransformStack.cast(ms); + msr.translate(be.width / 2f, 0.5, be.width / 2f); + + float dialPivot = 5.75f / 16; + float progress = be.boiler.gauge.getValue(partialTicks); + + for (Direction d : Iterate.horizontalDirections) { + ms.pushPose(); + CachedBufferer.partial(AllPartialModels.BOILER_GAUGE, blockState) + .rotateY(d.toYRot()) + .unCentre() + .translate(be.width / 2f - 6 / 16f, 0, 0) + .light(light) + .renderInto(ms, vb); + CachedBufferer.partial(AllPartialModels.BOILER_GAUGE_DIAL, blockState) + .rotateY(d.toYRot()) + .unCentre() + .translate(be.width / 2f - 6 / 16f, 0, 0) + .translate(0, dialPivot, dialPivot) + .rotateX(-90 * progress) + .translate(0, -dialPivot, -dialPivot) + .light(light) + .renderInto(ms, vb); + ms.popPose(); + } + + ms.popPose(); + } + + @Override + public boolean shouldRenderOffScreen(FluidTankBlockEntity be) { + return be.isController(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/EmptyingRecipe.java b/src/main/java/com/simibubi/create/content/fluids/transfer/EmptyingRecipe.java similarity index 79% rename from src/main/java/com/simibubi/create/content/contraptions/processing/EmptyingRecipe.java rename to src/main/java/com/simibubi/create/content/fluids/transfer/EmptyingRecipe.java index 848d75fde..dbd492fd5 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/EmptyingRecipe.java +++ b/src/main/java/com/simibubi/create/content/fluids/transfer/EmptyingRecipe.java @@ -1,7 +1,8 @@ -package com.simibubi.create.content.contraptions.processing; +package com.simibubi.create.content.fluids.transfer; import com.simibubi.create.AllRecipeTypes; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder.ProcessingRecipeParams; +import com.simibubi.create.content.processing.recipe.ProcessingRecipe; +import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder.ProcessingRecipeParams; import net.minecraft.world.level.Level; import net.minecraftforge.fluids.FluidStack; diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FillingRecipe.java b/src/main/java/com/simibubi/create/content/fluids/transfer/FillingRecipe.java similarity index 88% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FillingRecipe.java rename to src/main/java/com/simibubi/create/content/fluids/transfer/FillingRecipe.java index 4b1c31c78..54d8b3695 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FillingRecipe.java +++ b/src/main/java/com/simibubi/create/content/fluids/transfer/FillingRecipe.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.fluids.actors; +package com.simibubi.create.content.fluids.transfer; import java.util.List; import java.util.Set; @@ -7,9 +7,9 @@ import java.util.function.Supplier; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllRecipeTypes; import com.simibubi.create.compat.jei.category.sequencedAssembly.SequencedAssemblySubCategory; -import com.simibubi.create.content.contraptions.itemAssembly.IAssemblyRecipe; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipe; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder.ProcessingRecipeParams; +import com.simibubi.create.content.processing.recipe.ProcessingRecipe; +import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder.ProcessingRecipeParams; +import com.simibubi.create.content.processing.sequenced.IAssemblyRecipe; import com.simibubi.create.foundation.fluid.FluidIngredient; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Lang; diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidDrainingBehaviour.java b/src/main/java/com/simibubi/create/content/fluids/transfer/FluidDrainingBehaviour.java similarity index 88% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidDrainingBehaviour.java rename to src/main/java/com/simibubi/create/content/fluids/transfer/FluidDrainingBehaviour.java index 25d568bf1..6354642fa 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidDrainingBehaviour.java +++ b/src/main/java/com/simibubi/create/content/fluids/transfer/FluidDrainingBehaviour.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.fluids.actors; +package com.simibubi.create.content.fluids.transfer; import java.util.ArrayList; import java.util.HashSet; @@ -9,9 +9,9 @@ import java.util.Set; import javax.annotation.Nullable; import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; import com.simibubi.create.foundation.fluid.FluidHelper; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType; import com.simibubi.create.foundation.utility.BBHelper; import com.simibubi.create.foundation.utility.Iterate; @@ -47,8 +47,8 @@ public class FluidDrainingBehaviour extends FluidManipulationBehaviour { Set validationVisited; Set newValidationSet; - public FluidDrainingBehaviour(SmartTileEntity te) { - super(te); + public FluidDrainingBehaviour(SmartBlockEntity be) { + super(be); validationVisited = new HashSet<>(); validationFrontier = new ArrayList<>(); validationSet = new HashSet<>(); @@ -83,10 +83,21 @@ public class FluidDrainingBehaviour extends FluidManipulationBehaviour { if (validationFrontier.isEmpty() && !queue.isEmpty() && !simulate && revalidateIn == 0) revalidate(root); + if (infinite) { + blockEntity.award(AllAdvancements.HOSE_PULLEY); + if (FluidHelper.isLava(fluid)) + blockEntity.award(AllAdvancements.HOSE_PULLEY_LAVA); + + playEffect(world, root, fluid, true); + return true; + } + while (!queue.isEmpty()) { // Dont dequeue here, so we can decide not to dequeue a valid entry when // simulating - BlockPos currentPos = queue.first().pos(); + BlockPos currentPos = queue.first() + .pos(); + BlockState blockState = world.getBlockState(currentPos); BlockState emptied = blockState; Fluid fluid = Fluids.EMPTY; @@ -102,7 +113,7 @@ public class FluidDrainingBehaviour extends FluidManipulationBehaviour { fluid = flowingFluid.getFluid(); else { affectedArea = BBHelper.encapsulate(affectedArea, BoundingBox.fromCorners(currentPos, currentPos)); - if (!tileEntity.isVirtual()) + if (!blockEntity.isVirtual()) world.setBlock(currentPos, emptied, 2 | 16); queue.dequeue(); if (queue.isEmpty()) { @@ -135,15 +146,9 @@ public class FluidDrainingBehaviour extends FluidManipulationBehaviour { return true; playEffect(world, currentPos, fluid, true); - tileEntity.award(AllAdvancements.HOSE_PULLEY); + blockEntity.award(AllAdvancements.HOSE_PULLEY); - if (infinite) { - if (FluidHelper.isLava(fluid)) - tileEntity.award(AllAdvancements.HOSE_PULLEY_LAVA); - return true; - } - - if (!tileEntity.isVirtual()) + if (!blockEntity.isVirtual()) world.setBlock(currentPos, emptied, 2 | 16); affectedArea = BBHelper.encapsulate(affectedArea, currentPos); @@ -176,12 +181,12 @@ public class FluidDrainingBehaviour extends FluidManipulationBehaviour { infinite = false; setValidationTimer(); frontier.add(new BlockPosEntry(root, 0)); - tileEntity.sendData(); + blockEntity.sendData(); } protected boolean checkValid(Level world, BlockPos root) { BlockPos currentPos = root; - for (int timeout = 1000; timeout > 0 && !root.equals(tileEntity.getBlockPos()); timeout--) { + for (int timeout = 1000; timeout > 0 && !root.equals(blockEntity.getBlockPos()); timeout--) { FluidBlockType canPullFluidsFrom = canPullFluidsFrom(world.getBlockState(currentPos), currentPos); if (canPullFluidsFrom == FluidBlockType.FLOWING) { for (Direction d : Iterate.directions) { @@ -268,37 +273,28 @@ public class FluidDrainingBehaviour extends FluidManipulationBehaviour { validationSet.add(e); }, false); } catch (ChunkNotLoadedException e) { - tileEntity.sendData(); + blockEntity.sendData(); frontier.clear(); visited.clear(); } - Level world = getWorld(); int maxBlocks = maxBlocks(); if (visited.size() > maxBlocks && canDrainInfinitely(fluid) && !queue.isEmpty()) { infinite = true; - // Find first block with valid fluid - while (true) { - BlockPos first = queue.first().pos(); - if (canPullFluidsFrom(world.getBlockState(first), first) != FluidBlockType.SOURCE) { - queue.dequeue(); - continue; - } - break; - } - BlockPos firstValid = queue.first().pos(); + BlockPos firstValid = queue.first() + .pos(); frontier.clear(); visited.clear(); queue.clear(); queue.enqueue(new BlockPosEntry(firstValid, 0)); - tileEntity.sendData(); + blockEntity.sendData(); return; } if (!frontier.isEmpty()) return; - tileEntity.sendData(); + blockEntity.sendData(); visited.clear(); } @@ -344,7 +340,7 @@ public class FluidDrainingBehaviour extends FluidManipulationBehaviour { newValidationSet.clear(); validationFrontier.clear(); validationVisited.clear(); - tileEntity.sendData(); + blockEntity.sendData(); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidFillingBehaviour.java b/src/main/java/com/simibubi/create/content/fluids/transfer/FluidFillingBehaviour.java similarity index 92% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidFillingBehaviour.java rename to src/main/java/com/simibubi/create/content/fluids/transfer/FluidFillingBehaviour.java index 3bb5fb369..398619387 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidFillingBehaviour.java +++ b/src/main/java/com/simibubi/create/content/fluids/transfer/FluidFillingBehaviour.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.fluids.actors; +package com.simibubi.create.content.fluids.transfer; import java.util.ArrayList; import java.util.HashSet; @@ -7,12 +7,12 @@ import java.util.Objects; import java.util.Set; import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.config.AllConfigs; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; import com.simibubi.create.foundation.fluid.FluidHelper; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType; import com.simibubi.create.foundation.utility.BBHelper; import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.infrastructure.config.AllConfigs; import it.unimi.dsi.fastutil.PriorityQueue; import it.unimi.dsi.fastutil.objects.ObjectHeapPriorityQueue; @@ -49,8 +49,8 @@ public class FluidFillingBehaviour extends FluidManipulationBehaviour { List infinityCheckFrontier; Set infinityCheckVisited; - public FluidFillingBehaviour(SmartTileEntity te) { - super(te); + public FluidFillingBehaviour(SmartBlockEntity be) { + super(be); queue = new ObjectHeapPriorityQueue<>((p, p2) -> -comparePositions(p, p2)); revalidateIn = 1; infinityCheckFrontier = new ArrayList<>(); @@ -87,7 +87,7 @@ public class FluidFillingBehaviour extends FluidManipulationBehaviour { if (!infinite) { reset(); infinite = true; - tileEntity.sendData(); + blockEntity.sendData(); } infinityCheckFrontier.clear(); setLongValidationTimer(); @@ -137,7 +137,7 @@ public class FluidFillingBehaviour extends FluidManipulationBehaviour { int maxBlocks = maxBlocks(); boolean evaporate = world.dimensionType() .ultraWarm() && FluidHelper.isTag(fluid, FluidTags.WATER); - boolean canPlaceSources = AllConfigs.SERVER.fluids.placeFluidSourceBlocks.get(); + boolean canPlaceSources = AllConfigs.server().fluids.placeFluidSourceBlocks.get(); if ((!fillInfinite() && infinite) || evaporate || !canPlaceSources) { FluidState fluidState = world.getFluidState(rootPos); @@ -155,7 +155,7 @@ public class FluidFillingBehaviour extends FluidManipulationBehaviour { world.playSound(null, i, j, k, SoundEvents.FIRE_EXTINGUISH, SoundSource.BLOCKS, 0.5F, 2.6F + (world.random.nextFloat() - world.random.nextFloat()) * 0.8F); } else if (!canPlaceSources) - tileEntity.award(AllAdvancements.HOSE_PULLEY); + blockEntity.award(AllAdvancements.HOSE_PULLEY); return true; } @@ -191,13 +191,13 @@ public class FluidFillingBehaviour extends FluidManipulationBehaviour { BlockState blockState = world.getBlockState(currentPos); if (blockState.hasProperty(BlockStateProperties.WATERLOGGED) && fluid.isSame(Fluids.WATER)) { - if (!tileEntity.isVirtual()) + if (!blockEntity.isVirtual()) world.setBlock(currentPos, updatePostWaterlogging(blockState.setValue(BlockStateProperties.WATERLOGGED, true)), 2 | 16); } else { replaceBlock(world, currentPos, blockState); - if (!tileEntity.isVirtual()) + if (!blockEntity.isVirtual()) world.setBlock(currentPos, FluidHelper.convertToStill(fluid) .defaultFluidState() .createLegacyBlock(), 2 | 16); @@ -236,7 +236,7 @@ public class FluidFillingBehaviour extends FluidManipulationBehaviour { } if (!simulate && success) - tileEntity.award(AllAdvancements.HOSE_PULLEY); + blockEntity.award(AllAdvancements.HOSE_PULLEY); return success; } @@ -246,7 +246,7 @@ public class FluidFillingBehaviour extends FluidManipulationBehaviour { queue.enqueue(new BlockPosEntry(root, 0)); infinite = false; setValidationTimer(); - tileEntity.sendData(); + blockEntity.sendData(); } enum SpaceType { @@ -276,8 +276,8 @@ public class FluidFillingBehaviour extends FluidManipulationBehaviour { } protected void replaceBlock(Level world, BlockPos pos, BlockState state) { - BlockEntity tileentity = state.hasBlockEntity() ? world.getBlockEntity(pos) : null; - Block.dropResources(state, world, pos, tileentity); + BlockEntity blockEntity = state.hasBlockEntity() ? world.getBlockEntity(pos) : null; + Block.dropResources(state, world, pos, blockEntity); } // From FlowingFluidBlock#isBlocked diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidManipulationBehaviour.java b/src/main/java/com/simibubi/create/content/fluids/transfer/FluidManipulationBehaviour.java similarity index 89% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidManipulationBehaviour.java rename to src/main/java/com/simibubi/create/content/fluids/transfer/FluidManipulationBehaviour.java index 66b9821f0..b245a6530 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidManipulationBehaviour.java +++ b/src/main/java/com/simibubi/create/content/fluids/transfer/FluidManipulationBehaviour.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.fluids.actors; +package com.simibubi.create.content.fluids.transfer; import java.util.ArrayList; import java.util.HashSet; @@ -7,15 +7,15 @@ import java.util.Set; import java.util.function.BiConsumer; import java.util.function.Predicate; +import com.simibubi.create.AllPackets; import com.simibubi.create.AllTags.AllFluidTags; -import com.simibubi.create.foundation.config.AllConfigs; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.fluid.FluidHelper; -import com.simibubi.create.foundation.networking.AllPackets; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -32,7 +32,7 @@ import net.minecraft.world.level.material.FluidState; import net.minecraft.world.phys.Vec3; import net.minecraftforge.fluids.FluidStack; -public abstract class FluidManipulationBehaviour extends TileEntityBehaviour { +public abstract class FluidManipulationBehaviour extends BlockEntityBehaviour { public static record BlockPosEntry(BlockPos pos, int distance) { }; @@ -54,14 +54,18 @@ public abstract class FluidManipulationBehaviour extends TileEntityBehaviour { int revalidateIn; - public FluidManipulationBehaviour(SmartTileEntity te) { - super(te); + public FluidManipulationBehaviour(SmartBlockEntity be) { + super(be); setValidationTimer(); infinite = false; visited = new HashSet<>(); frontier = new ArrayList<>(); } + public boolean isInfinite() { + return infinite; + } + public void counterpartActed() { counterpartActed = true; } @@ -81,15 +85,15 @@ public abstract class FluidManipulationBehaviour extends TileEntityBehaviour { } protected int maxRange() { - return AllConfigs.SERVER.fluids.hosePulleyRange.get(); + return AllConfigs.server().fluids.hosePulleyRange.get(); } protected int maxBlocks() { - return AllConfigs.SERVER.fluids.hosePulleyBlockThreshold.get(); + return AllConfigs.server().fluids.hosePulleyBlockThreshold.get(); } protected boolean fillInfinite() { - return AllConfigs.SERVER.fluids.fillInfinite.get(); + return AllConfigs.server().fluids.fillInfinite.get(); } public void reset() { @@ -197,7 +201,7 @@ public abstract class FluidManipulationBehaviour extends TileEntityBehaviour { } protected void playEffect(Level world, BlockPos pos, Fluid fluid, boolean fillSound) { - BlockPos splooshPos = pos == null ? tileEntity.getBlockPos() : pos; + BlockPos splooshPos = pos == null ? blockEntity.getBlockPos() : pos; FluidStack stack = new FluidStack(fluid, 1); SoundEvent soundevent = fillSound ? FluidHelper.getFillSound(stack) : FluidHelper.getEmptySound(stack); @@ -209,7 +213,7 @@ public abstract class FluidManipulationBehaviour extends TileEntityBehaviour { protected boolean canDrainInfinitely(Fluid fluid) { if (fluid == null) return false; - return maxBlocks() != -1 && AllConfigs.SERVER.fluids.bottomlessFluidMode.get() + return maxBlocks() != -1 && AllConfigs.server().fluids.bottomlessFluidMode.get() .test(fluid); } diff --git a/src/main/java/com/simibubi/create/content/fluids/transfer/FluidSplashPacket.java b/src/main/java/com/simibubi/create/content/fluids/transfer/FluidSplashPacket.java new file mode 100644 index 000000000..d4cd72945 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/fluids/transfer/FluidSplashPacket.java @@ -0,0 +1,47 @@ +package com.simibubi.create.content.fluids.transfer; + +import com.simibubi.create.content.fluids.FluidFX; +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.network.NetworkEvent.Context; + +public class FluidSplashPacket extends SimplePacketBase { + + private BlockPos pos; + private FluidStack fluid; + + public FluidSplashPacket(BlockPos pos, FluidStack fluid) { + this.pos = pos; + this.fluid = fluid; + } + + public FluidSplashPacket(FriendlyByteBuf buffer) { + pos = buffer.readBlockPos(); + fluid = buffer.readFluidStack(); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeBlockPos(pos); + buffer.writeFluidStack(fluid); + } + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { + if (Minecraft.getInstance().player.position() + .distanceTo(new Vec3(pos.getX(), pos.getY(), pos.getZ())) > 100) + return; + FluidFX.splash(pos, fluid); + })); + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/fluids/transfer/GenericItemEmptying.java b/src/main/java/com/simibubi/create/content/fluids/transfer/GenericItemEmptying.java new file mode 100644 index 000000000..d9e3d9aa4 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/fluids/transfer/GenericItemEmptying.java @@ -0,0 +1,83 @@ +package com.simibubi.create.content.fluids.transfer; + +import java.util.List; +import java.util.Optional; + +import com.simibubi.create.AllRecipeTypes; +import com.simibubi.create.content.fluids.potion.PotionFluidHandler; +import com.simibubi.create.foundation.utility.Pair; + +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.PotionItem; +import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.level.Level; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction; +import net.minecraftforge.fluids.capability.IFluidHandlerItem; +import net.minecraftforge.items.ItemStackHandler; +import net.minecraftforge.items.wrapper.RecipeWrapper; + +public class GenericItemEmptying { + + private static final RecipeWrapper WRAPPER = new RecipeWrapper(new ItemStackHandler(1)); + + public static boolean canItemBeEmptied(Level world, ItemStack stack) { + if (stack.getItem() instanceof PotionItem) + return true; + + WRAPPER.setItem(0, stack); + if (AllRecipeTypes.EMPTYING.find(WRAPPER, world) + .isPresent()) + return true; + + LazyOptional capability = + stack.getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY); + IFluidHandlerItem tank = capability.orElse(null); + if (tank == null) + return false; + for (int i = 0; i < tank.getTanks(); i++) { + if (tank.getFluidInTank(i) + .getAmount() > 0) + return true; + } + return false; + } + + public static Pair emptyItem(Level world, ItemStack stack, boolean simulate) { + FluidStack resultingFluid = FluidStack.EMPTY; + ItemStack resultingItem = ItemStack.EMPTY; + + if (stack.getItem() instanceof PotionItem) + return PotionFluidHandler.emptyPotion(stack, simulate); + + WRAPPER.setItem(0, stack); + Optional> recipe = AllRecipeTypes.EMPTYING.find(WRAPPER, world); + if (recipe.isPresent()) { + EmptyingRecipe emptyingRecipe = (EmptyingRecipe) recipe.get(); + List results = emptyingRecipe.rollResults(); + if (!simulate) + stack.shrink(1); + resultingItem = results.isEmpty() ? ItemStack.EMPTY : results.get(0); + resultingFluid = emptyingRecipe.getResultingFluid(); + return Pair.of(resultingFluid, resultingItem); + } + + ItemStack split = stack.copy(); + split.setCount(1); + LazyOptional capability = + split.getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY); + IFluidHandlerItem tank = capability.orElse(null); + if (tank == null) + return Pair.of(resultingFluid, resultingItem); + resultingFluid = tank.drain(1000, simulate ? FluidAction.SIMULATE : FluidAction.EXECUTE); + resultingItem = tank.getContainer() + .copy(); + if (!simulate) + stack.shrink(1); + + return Pair.of(resultingFluid, resultingItem); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/GenericItemFilling.java b/src/main/java/com/simibubi/create/content/fluids/transfer/GenericItemFilling.java similarity index 97% rename from src/main/java/com/simibubi/create/content/contraptions/fluids/actors/GenericItemFilling.java rename to src/main/java/com/simibubi/create/content/fluids/transfer/GenericItemFilling.java index e6ce73c75..4a7ad0580 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/GenericItemFilling.java +++ b/src/main/java/com/simibubi/create/content/fluids/transfer/GenericItemFilling.java @@ -1,8 +1,8 @@ -package com.simibubi.create.content.contraptions.fluids.actors; +package com.simibubi.create.content.fluids.transfer; import com.simibubi.create.AllFluids; import com.simibubi.create.AllItems; -import com.simibubi.create.content.contraptions.fluids.potion.PotionFluidHandler; +import com.simibubi.create.content.fluids.potion.PotionFluidHandler; import com.simibubi.create.foundation.fluid.FluidHelper; import net.minecraft.world.item.BucketItem; diff --git a/src/main/java/com/simibubi/create/foundation/block/BlockStressDefaults.java b/src/main/java/com/simibubi/create/content/kinetics/BlockStressDefaults.java similarity index 97% rename from src/main/java/com/simibubi/create/foundation/block/BlockStressDefaults.java rename to src/main/java/com/simibubi/create/content/kinetics/BlockStressDefaults.java index 1ea374b1b..16fb0cd2e 100644 --- a/src/main/java/com/simibubi/create/foundation/block/BlockStressDefaults.java +++ b/src/main/java/com/simibubi/create/content/kinetics/BlockStressDefaults.java @@ -1,4 +1,4 @@ -package com.simibubi.create.foundation.block; +package com.simibubi.create.content.kinetics; import java.util.HashMap; import java.util.Map; diff --git a/src/main/java/com/simibubi/create/foundation/block/BlockStressValues.java b/src/main/java/com/simibubi/create/content/kinetics/BlockStressValues.java similarity index 89% rename from src/main/java/com/simibubi/create/foundation/block/BlockStressValues.java rename to src/main/java/com/simibubi/create/content/kinetics/BlockStressValues.java index b1592abd6..7225fbfa6 100644 --- a/src/main/java/com/simibubi/create/foundation/block/BlockStressValues.java +++ b/src/main/java/com/simibubi/create/content/kinetics/BlockStressValues.java @@ -1,4 +1,4 @@ -package com.simibubi.create.foundation.block; +package com.simibubi.create.content.kinetics; import java.util.HashMap; import java.util.Map; @@ -74,6 +74,16 @@ public class BlockStressValues { return BlockStressDefaults.DEFAULT_CAPACITIES.containsKey(blockId); } + @Nullable + public static Couple getGeneratedRPM(Block block) { + ResourceLocation blockId = RegisteredObjects.getKeyOrThrow(block); + IStressValueProvider provider = getProvider(blockId.getNamespace()); + if (provider != null) { + return provider.getGeneratedRPM(block); + } + return null; + } + public interface IStressValueProvider { /** * Gets the stress impact of a block. diff --git a/src/main/java/com/simibubi/create/content/kinetics/KineticDebugger.java b/src/main/java/com/simibubi/create/content/kinetics/KineticDebugger.java new file mode 100644 index 000000000..90c5a4ee5 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/KineticDebugger.java @@ -0,0 +1,89 @@ +package com.simibubi.create.content.kinetics; + +import com.simibubi.create.CreateClient; +import com.simibubi.create.content.kinetics.base.IRotate; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.foundation.utility.Color; +import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.Direction.AxisDirection; +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; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.phys.shapes.VoxelShape; + +public class KineticDebugger { + + public static void tick() { + if (!isActive()) { + if (KineticBlockEntityRenderer.rainbowMode) { + KineticBlockEntityRenderer.rainbowMode = false; + CreateClient.BUFFER_CACHE.invalidate(); + } + return; + } + + KineticBlockEntity be = getSelectedBE(); + if (be == null) + return; + + Level world = Minecraft.getInstance().level; + BlockPos toOutline = be.hasSource() ? be.source : be.getBlockPos(); + BlockState state = be.getBlockState(); + VoxelShape shape = world.getBlockState(toOutline) + .getBlockSupportShape(world, toOutline); + + if (be.getTheoreticalSpeed() != 0 && !shape.isEmpty()) + CreateClient.OUTLINER.chaseAABB("kineticSource", shape.bounds() + .move(toOutline)) + .lineWidth(1 / 16f) + .colored(be.hasSource() ? Color.generateFromLong(be.network).getRGB() : 0xffcc00); + + if (state.getBlock() instanceof IRotate) { + Axis axis = ((IRotate) state.getBlock()).getRotationAxis(state); + Vec3 vec = Vec3.atLowerCornerOf(Direction.get(AxisDirection.POSITIVE, axis) + .getNormal()); + Vec3 center = VecHelper.getCenterOf(be.getBlockPos()); + CreateClient.OUTLINER.showLine("rotationAxis", center.add(vec), center.subtract(vec)) + .lineWidth(1 / 16f); + } + + } + + public static boolean isActive() { + return isF3DebugModeActive() && AllConfigs.client().rainbowDebug.get(); + } + + public static boolean isF3DebugModeActive() { + return Minecraft.getInstance().options.renderDebug; + } + + public static KineticBlockEntity getSelectedBE() { + HitResult obj = Minecraft.getInstance().hitResult; + ClientLevel world = Minecraft.getInstance().level; + if (obj == null) + return null; + if (world == null) + return null; + if (!(obj instanceof BlockHitResult)) + return null; + + BlockHitResult ray = (BlockHitResult) obj; + BlockEntity be = world.getBlockEntity(ray.getBlockPos()); + if (!(be instanceof KineticBlockEntity)) + return null; + + return (KineticBlockEntity) be; + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/KineticNetwork.java b/src/main/java/com/simibubi/create/content/kinetics/KineticNetwork.java new file mode 100644 index 000000000..b1d154607 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/KineticNetwork.java @@ -0,0 +1,181 @@ +package com.simibubi.create.content.kinetics; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; + +public class KineticNetwork { + + public Long id; + public boolean initialized; + public Map sources; + public Map members; + + private float currentCapacity; + private float currentStress; + private float unloadedCapacity; + private float unloadedStress; + private int unloadedMembers; + + public KineticNetwork() { + sources = new HashMap<>(); + members = new HashMap<>(); + } + + public void initFromTE(float maxStress, float currentStress, int members) { + unloadedCapacity = maxStress; + unloadedStress = currentStress; + unloadedMembers = members; + initialized = true; + updateStress(); + updateCapacity(); + } + + public void addSilently(KineticBlockEntity be, float lastCapacity, float lastStress) { + if (members.containsKey(be)) + return; + if (be.isSource()) { + unloadedCapacity -= lastCapacity * getStressMultiplierForSpeed(be.getGeneratedSpeed()); + float addedStressCapacity = be.calculateAddedStressCapacity(); + sources.put(be, addedStressCapacity); + } + + unloadedStress -= lastStress * getStressMultiplierForSpeed(be.getTheoreticalSpeed()); + float stressApplied = be.calculateStressApplied(); + members.put(be, stressApplied); + + unloadedMembers--; + if (unloadedMembers < 0) + unloadedMembers = 0; + if (unloadedCapacity < 0) + unloadedCapacity = 0; + if (unloadedStress < 0) + unloadedStress = 0; + } + + public void add(KineticBlockEntity be) { + if (members.containsKey(be)) + return; + if (be.isSource()) + sources.put(be, be.calculateAddedStressCapacity()); + members.put(be, be.calculateStressApplied()); + updateFromNetwork(be); + be.networkDirty = true; + } + + public void updateCapacityFor(KineticBlockEntity be, float capacity) { + sources.put(be, capacity); + updateCapacity(); + } + + public void updateStressFor(KineticBlockEntity be, float stress) { + members.put(be, stress); + updateStress(); + } + + public void remove(KineticBlockEntity be) { + if (!members.containsKey(be)) + return; + if (be.isSource()) + sources.remove(be); + members.remove(be); + be.updateFromNetwork(0, 0, 0); + + if (members.isEmpty()) { + TorquePropagator.networks.get(be.getLevel()) + .remove(this.id); + return; + } + + members.keySet() + .stream() + .findFirst() + .map(member -> member.networkDirty = true); + } + + public void sync() { + for (KineticBlockEntity be : members.keySet()) + updateFromNetwork(be); + } + + private void updateFromNetwork(KineticBlockEntity be) { + be.updateFromNetwork(currentCapacity, currentStress, getSize()); + } + + public void updateCapacity() { + float newMaxStress = calculateCapacity(); + if (currentCapacity != newMaxStress) { + currentCapacity = newMaxStress; + sync(); + } + } + + public void updateStress() { + float newStress = calculateStress(); + if (currentStress != newStress) { + currentStress = newStress; + sync(); + } + } + + public void updateNetwork() { + float newStress = calculateStress(); + float newMaxStress = calculateCapacity(); + if (currentStress != newStress || currentCapacity != newMaxStress) { + currentStress = newStress; + currentCapacity = newMaxStress; + sync(); + } + } + + public float calculateCapacity() { + float presentCapacity = 0; + for (Iterator iterator = sources.keySet() + .iterator(); iterator.hasNext();) { + KineticBlockEntity be = iterator.next(); + if (be.getLevel() + .getBlockEntity(be.getBlockPos()) != be) { + iterator.remove(); + continue; + } + presentCapacity += getActualCapacityOf(be); + } + float newMaxStress = presentCapacity + unloadedCapacity; + return newMaxStress; + } + + public float calculateStress() { + float presentStress = 0; + for (Iterator iterator = members.keySet() + .iterator(); iterator.hasNext();) { + KineticBlockEntity be = iterator.next(); + if (be.getLevel() + .getBlockEntity(be.getBlockPos()) != be) { + iterator.remove(); + continue; + } + presentStress += getActualStressOf(be); + } + float newStress = presentStress + unloadedStress; + return newStress; + } + + public float getActualCapacityOf(KineticBlockEntity be) { + return sources.get(be) * getStressMultiplierForSpeed(be.getGeneratedSpeed()); + } + + public float getActualStressOf(KineticBlockEntity be) { + return members.get(be) * getStressMultiplierForSpeed(be.getTheoreticalSpeed()); + } + + private static float getStressMultiplierForSpeed(float speed) { + return Math.abs(speed); + } + + public int getSize() { + return unloadedMembers + members.size(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/RotationPropagator.java b/src/main/java/com/simibubi/create/content/kinetics/RotationPropagator.java new file mode 100644 index 000000000..0399ba808 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/RotationPropagator.java @@ -0,0 +1,448 @@ +package com.simibubi.create.content.kinetics; + +import static net.minecraft.world.level.block.state.properties.BlockStateProperties.AXIS; + +import java.util.LinkedList; +import java.util.List; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.kinetics.base.DirectionalShaftHalvesBlockEntity; +import com.simibubi.create.content.kinetics.base.IRotate; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.chainDrive.ChainDriveBlock; +import com.simibubi.create.content.kinetics.gearbox.GearboxBlockEntity; +import com.simibubi.create.content.kinetics.simpleRelays.CogWheelBlock; +import com.simibubi.create.content.kinetics.simpleRelays.ICogWheel; +import com.simibubi.create.content.kinetics.speedController.SpeedControllerBlock; +import com.simibubi.create.content.kinetics.speedController.SpeedControllerBlockEntity; +import com.simibubi.create.content.kinetics.transmission.SplitShaftBlockEntity; +import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +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; + + +public class RotationPropagator { + + private static final int MAX_FLICKER_SCORE = 128; + + /** + * Determines the change in rotation between two attached kinetic entities. For + * instance, an axis connection returns 1 while a 1-to-1 gear connection + * reverses the rotation and therefore returns -1. + * + * @param from + * @param to + * @return + */ + private static float getRotationSpeedModifier(KineticBlockEntity from, KineticBlockEntity to) { + final BlockState stateFrom = from.getBlockState(); + final BlockState stateTo = to.getBlockState(); + + Block fromBlock = stateFrom.getBlock(); + Block toBlock = stateTo.getBlock(); + if (!(fromBlock instanceof IRotate && toBlock instanceof IRotate)) + return 0; + + final IRotate definitionFrom = (IRotate) fromBlock; + final IRotate definitionTo = (IRotate) toBlock; + final BlockPos diff = to.getBlockPos() + .subtract(from.getBlockPos()); + final Direction direction = Direction.getNearest(diff.getX(), diff.getY(), diff.getZ()); + final Level world = from.getLevel(); + + boolean alignedAxes = true; + for (Axis axis : Axis.values()) + if (axis != direction.getAxis()) + if (axis.choose(diff.getX(), diff.getY(), diff.getZ()) != 0) + alignedAxes = false; + + boolean connectedByAxis = + alignedAxes && definitionFrom.hasShaftTowards(world, from.getBlockPos(), stateFrom, direction) + && definitionTo.hasShaftTowards(world, to.getBlockPos(), stateTo, direction.getOpposite()); + + boolean connectedByGears = ICogWheel.isSmallCog(stateFrom) + && ICogWheel.isSmallCog(stateTo); + + float custom = from.propagateRotationTo(to, stateFrom, stateTo, diff, connectedByAxis, connectedByGears); + if (custom != 0) + return custom; + + // Axis <-> Axis + if (connectedByAxis) { + float axisModifier = getAxisModifier(to, direction.getOpposite()); + if (axisModifier != 0) + axisModifier = 1 / axisModifier; + return getAxisModifier(from, direction) * axisModifier; + } + + // Attached Encased Belts + if (fromBlock instanceof ChainDriveBlock && toBlock instanceof ChainDriveBlock) { + boolean connected = ChainDriveBlock.areBlocksConnected(stateFrom, stateTo, direction); + return connected ? ChainDriveBlock.getRotationSpeedModifier(from, to) : 0; + } + + // Large Gear <-> Large Gear + if (isLargeToLargeGear(stateFrom, stateTo, diff)) { + Axis sourceAxis = stateFrom.getValue(AXIS); + Axis targetAxis = stateTo.getValue(AXIS); + int sourceAxisDiff = sourceAxis.choose(diff.getX(), diff.getY(), diff.getZ()); + int targetAxisDiff = targetAxis.choose(diff.getX(), diff.getY(), diff.getZ()); + + return sourceAxisDiff > 0 ^ targetAxisDiff > 0 ? -1 : 1; + } + + // Gear <-> Large Gear + if (ICogWheel.isLargeCog(stateFrom) && ICogWheel.isSmallCog(stateTo)) + if (isLargeToSmallCog(stateFrom, stateTo, definitionTo, diff)) + return -2f; + if (ICogWheel.isLargeCog(stateTo) && ICogWheel.isSmallCog(stateFrom)) + if (isLargeToSmallCog(stateTo, stateFrom, definitionFrom, diff)) + return -.5f; + + // Gear <-> Gear + if (connectedByGears) { + if (diff.distManhattan(BlockPos.ZERO) != 1) + return 0; + if (ICogWheel.isLargeCog(stateTo)) + return 0; + if (direction.getAxis() == definitionFrom.getRotationAxis(stateFrom)) + return 0; + if (definitionFrom.getRotationAxis(stateFrom) == definitionTo.getRotationAxis(stateTo)) + return -1; + } + + return 0; + } + + private static float getConveyedSpeed(KineticBlockEntity from, KineticBlockEntity to) { + final BlockState stateFrom = from.getBlockState(); + final BlockState stateTo = to.getBlockState(); + + // Rotation Speed Controller <-> Large Gear + if (isLargeCogToSpeedController(stateFrom, stateTo, to.getBlockPos() + .subtract(from.getBlockPos()))) + return SpeedControllerBlockEntity.getConveyedSpeed(from, to, true); + if (isLargeCogToSpeedController(stateTo, stateFrom, from.getBlockPos() + .subtract(to.getBlockPos()))) + return SpeedControllerBlockEntity.getConveyedSpeed(to, from, false); + + float rotationSpeedModifier = getRotationSpeedModifier(from, to); + return from.getTheoreticalSpeed() * rotationSpeedModifier; + } + + private static boolean isLargeToLargeGear(BlockState from, BlockState to, BlockPos diff) { + if (!ICogWheel.isLargeCog(from) || !ICogWheel.isLargeCog(to)) + return false; + Axis fromAxis = from.getValue(AXIS); + Axis toAxis = to.getValue(AXIS); + if (fromAxis == toAxis) + return false; + for (Axis axis : Axis.values()) { + int axisDiff = axis.choose(diff.getX(), diff.getY(), diff.getZ()); + if (axis == fromAxis || axis == toAxis) { + if (axisDiff == 0) + return false; + + } else if (axisDiff != 0) + return false; + } + return true; + } + + private static float getAxisModifier(KineticBlockEntity be, Direction direction) { + if (!(be.hasSource()||be.isSource()) || !(be instanceof DirectionalShaftHalvesBlockEntity)) + return 1; + Direction source = ((DirectionalShaftHalvesBlockEntity) be).getSourceFacing(); + + if (be instanceof GearboxBlockEntity) + return direction.getAxis() == source.getAxis() ? direction == source ? 1 : -1 + : direction.getAxisDirection() == source.getAxisDirection() ? -1 : 1; + + if (be instanceof SplitShaftBlockEntity) + return ((SplitShaftBlockEntity) be).getRotationSpeedModifier(direction); + + return 1; + } + + private static boolean isLargeToSmallCog(BlockState from, BlockState to, IRotate defTo, BlockPos diff) { + Axis axisFrom = from.getValue(AXIS); + if (axisFrom != defTo.getRotationAxis(to)) + return false; + if (axisFrom.choose(diff.getX(), diff.getY(), diff.getZ()) != 0) + return false; + for (Axis axis : Axis.values()) { + if (axis == axisFrom) + continue; + if (Math.abs(axis.choose(diff.getX(), diff.getY(), diff.getZ())) != 1) + return false; + } + return true; + } + + private static boolean isLargeCogToSpeedController(BlockState from, BlockState to, BlockPos diff) { + if (!ICogWheel.isLargeCog(from) || !AllBlocks.ROTATION_SPEED_CONTROLLER.has(to)) + return false; + if (!diff.equals(BlockPos.ZERO.below())) + return false; + Axis axis = from.getValue(CogWheelBlock.AXIS); + if (axis.isVertical()) + return false; + if (to.getValue(SpeedControllerBlock.HORIZONTAL_AXIS) == axis) + return false; + return true; + } + + /** + * Insert the added position to the kinetic network. + * + * @param worldIn + * @param pos + */ + public static void handleAdded(Level worldIn, BlockPos pos, KineticBlockEntity addedTE) { + if (worldIn.isClientSide) + return; + if (!worldIn.isLoaded(pos)) + return; + propagateNewSource(addedTE); + } + + /** + * Search for sourceless networks attached to the given entity and update them. + * + * @param currentTE + */ + private static void propagateNewSource(KineticBlockEntity currentTE) { + BlockPos pos = currentTE.getBlockPos(); + Level world = currentTE.getLevel(); + + for (KineticBlockEntity neighbourTE : getConnectedNeighbours(currentTE)) { + float speedOfCurrent = currentTE.getTheoreticalSpeed(); + float speedOfNeighbour = neighbourTE.getTheoreticalSpeed(); + float newSpeed = getConveyedSpeed(currentTE, neighbourTE); + float oppositeSpeed = getConveyedSpeed(neighbourTE, currentTE); + + if (newSpeed == 0 && oppositeSpeed == 0) + continue; + + boolean incompatible = + Math.signum(newSpeed) != Math.signum(speedOfNeighbour) && (newSpeed != 0 && speedOfNeighbour != 0); + + boolean tooFast = Math.abs(newSpeed) > AllConfigs.server().kinetics.maxRotationSpeed.get() + || Math.abs(oppositeSpeed) > AllConfigs.server().kinetics.maxRotationSpeed.get(); + // Check for both the new speed and the opposite speed, just in case + + boolean speedChangedTooOften = currentTE.getFlickerScore() > MAX_FLICKER_SCORE; + if (tooFast || speedChangedTooOften) { + world.destroyBlock(pos, true); + return; + } + + // Opposite directions + if (incompatible) { + world.destroyBlock(pos, true); + return; + + // Same direction: overpower the slower speed + } else { + + // Neighbour faster, overpower the incoming tree + if (Math.abs(oppositeSpeed) > Math.abs(speedOfCurrent)) { + float prevSpeed = currentTE.getSpeed(); + currentTE.setSource(neighbourTE.getBlockPos()); + currentTE.setSpeed(getConveyedSpeed(neighbourTE, currentTE)); + currentTE.onSpeedChanged(prevSpeed); + currentTE.sendData(); + + propagateNewSource(currentTE); + return; + } + + // Current faster, overpower the neighbours' tree + if (Math.abs(newSpeed) >= Math.abs(speedOfNeighbour)) { + + // Do not overpower you own network -> cycle + if (!currentTE.hasNetwork() || currentTE.network.equals(neighbourTE.network)) { + float epsilon = Math.abs(speedOfNeighbour) / 256f / 256f; + if (Math.abs(newSpeed) > Math.abs(speedOfNeighbour) + epsilon) + world.destroyBlock(pos, true); + continue; + } + + if (currentTE.hasSource() && currentTE.source.equals(neighbourTE.getBlockPos())) + currentTE.removeSource(); + + float prevSpeed = neighbourTE.getSpeed(); + neighbourTE.setSource(currentTE.getBlockPos()); + neighbourTE.setSpeed(getConveyedSpeed(currentTE, neighbourTE)); + neighbourTE.onSpeedChanged(prevSpeed); + neighbourTE.sendData(); + propagateNewSource(neighbourTE); + continue; + } + } + + if (neighbourTE.getTheoreticalSpeed() == newSpeed) + continue; + + float prevSpeed = neighbourTE.getSpeed(); + neighbourTE.setSpeed(newSpeed); + neighbourTE.setSource(currentTE.getBlockPos()); + neighbourTE.onSpeedChanged(prevSpeed); + neighbourTE.sendData(); + propagateNewSource(neighbourTE); + + } + } + + /** + * Remove the given entity from the network. + * + * @param worldIn + * @param pos + * @param removedBE + */ + public static void handleRemoved(Level worldIn, BlockPos pos, KineticBlockEntity removedBE) { + if (worldIn.isClientSide) + return; + if (removedBE == null) + return; + if (removedBE.getTheoreticalSpeed() == 0) + return; + + for (BlockPos neighbourPos : getPotentialNeighbourLocations(removedBE)) { + BlockState neighbourState = worldIn.getBlockState(neighbourPos); + if (!(neighbourState.getBlock() instanceof IRotate)) + continue; + BlockEntity blockEntity = worldIn.getBlockEntity(neighbourPos); + if (!(blockEntity instanceof KineticBlockEntity)) + continue; + + final KineticBlockEntity neighbourBE = (KineticBlockEntity) blockEntity; + if (!neighbourBE.hasSource() || !neighbourBE.source.equals(pos)) + continue; + + propagateMissingSource(neighbourBE); + } + + } + + /** + * Clear the entire subnetwork depending on the given entity and find a new + * source + * + * @param updateTE + */ + private static void propagateMissingSource(KineticBlockEntity updateTE) { + final Level world = updateTE.getLevel(); + + List potentialNewSources = new LinkedList<>(); + List frontier = new LinkedList<>(); + frontier.add(updateTE.getBlockPos()); + BlockPos missingSource = updateTE.hasSource() ? updateTE.source : null; + + while (!frontier.isEmpty()) { + final BlockPos pos = frontier.remove(0); + BlockEntity blockEntity = world.getBlockEntity(pos); + if (!(blockEntity instanceof KineticBlockEntity)) + continue; + final KineticBlockEntity currentBE = (KineticBlockEntity) blockEntity; + + currentBE.removeSource(); + currentBE.sendData(); + + for (KineticBlockEntity neighbourBE : getConnectedNeighbours(currentBE)) { + if (neighbourBE.getBlockPos() + .equals(missingSource)) + continue; + if (!neighbourBE.hasSource()) + continue; + + if (!neighbourBE.source.equals(pos)) { + potentialNewSources.add(neighbourBE); + continue; + } + + if (neighbourBE.isSource()) + potentialNewSources.add(neighbourBE); + + frontier.add(neighbourBE.getBlockPos()); + } + } + + for (KineticBlockEntity newSource : potentialNewSources) { + if (newSource.hasSource() || newSource.isSource()) { + propagateNewSource(newSource); + return; + } + } + } + + private static KineticBlockEntity findConnectedNeighbour(KineticBlockEntity currentTE, BlockPos neighbourPos) { + BlockState neighbourState = currentTE.getLevel() + .getBlockState(neighbourPos); + if (!(neighbourState.getBlock() instanceof IRotate)) + return null; + if (!neighbourState.hasBlockEntity()) + return null; + BlockEntity neighbourBE = currentTE.getLevel() + .getBlockEntity(neighbourPos); + if (!(neighbourBE instanceof KineticBlockEntity)) + return null; + KineticBlockEntity neighbourKBE = (KineticBlockEntity) neighbourBE; + if (!(neighbourKBE.getBlockState() + .getBlock() instanceof IRotate)) + return null; + if (!isConnected(currentTE, neighbourKBE) && !isConnected(neighbourKBE, currentTE)) + return null; + return neighbourKBE; + } + + public static boolean isConnected(KineticBlockEntity from, KineticBlockEntity to) { + final BlockState stateFrom = from.getBlockState(); + final BlockState stateTo = to.getBlockState(); + return isLargeCogToSpeedController(stateFrom, stateTo, to.getBlockPos() + .subtract(from.getBlockPos())) || getRotationSpeedModifier(from, to) != 0 + || from.isCustomConnection(to, stateFrom, stateTo); + } + + private static List getConnectedNeighbours(KineticBlockEntity be) { + List neighbours = new LinkedList<>(); + for (BlockPos neighbourPos : getPotentialNeighbourLocations(be)) { + final KineticBlockEntity neighbourBE = findConnectedNeighbour(be, neighbourPos); + if (neighbourBE == null) + continue; + + neighbours.add(neighbourBE); + } + return neighbours; + } + + private static List getPotentialNeighbourLocations(KineticBlockEntity be) { + List neighbours = new LinkedList<>(); + BlockPos blockPos = be.getBlockPos(); + Level level = be.getLevel(); + + if (!level.isLoaded(blockPos)) + return neighbours; + + for (Direction facing : Iterate.directions) { + BlockPos relative = blockPos.relative(facing); + if (level.isLoaded(relative)) + neighbours.add(relative); + } + + BlockState blockState = be.getBlockState(); + if (!(blockState.getBlock() instanceof IRotate)) + return neighbours; + IRotate block = (IRotate) blockState.getBlock(); + return be.addPropagationLocations(block, blockState, neighbours); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/TorquePropagator.java b/src/main/java/com/simibubi/create/content/kinetics/TorquePropagator.java new file mode 100644 index 000000000..5f6c64f51 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/TorquePropagator.java @@ -0,0 +1,42 @@ +package com.simibubi.create.content.kinetics; + +import java.util.HashMap; +import java.util.Map; + +import com.simibubi.create.Create; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.foundation.utility.WorldHelper; + +import net.minecraft.world.level.LevelAccessor; + +public class TorquePropagator { + + static Map> networks = new HashMap<>(); + + public void onLoadWorld(LevelAccessor world) { + networks.put(world, new HashMap<>()); + Create.LOGGER.debug("Prepared Kinetic Network Space for " + WorldHelper.getDimensionID(world)); + } + + public void onUnloadWorld(LevelAccessor world) { + networks.remove(world); + Create.LOGGER.debug("Removed Kinetic Network Space for " + WorldHelper.getDimensionID(world)); + } + + public KineticNetwork getOrCreateNetworkFor(KineticBlockEntity be) { + Long id = be.network; + KineticNetwork network; + Map map = networks.computeIfAbsent(be.getLevel(), $ -> new HashMap<>()); + if (id == null) + return null; + + if (!map.containsKey(id)) { + network = new KineticNetwork(); + network.id = be.network; + map.put(id, network); + } + network = map.get(id); + return network; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/AbstractEncasedShaftBlock.java b/src/main/java/com/simibubi/create/content/kinetics/base/AbstractEncasedShaftBlock.java similarity index 93% rename from src/main/java/com/simibubi/create/content/contraptions/relays/encased/AbstractEncasedShaftBlock.java rename to src/main/java/com/simibubi/create/content/kinetics/base/AbstractEncasedShaftBlock.java index 229d20097..362cdbbb2 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/AbstractEncasedShaftBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/AbstractEncasedShaftBlock.java @@ -1,9 +1,7 @@ -package com.simibubi.create.content.contraptions.relays.encased; +package com.simibubi.create.content.kinetics.base; import javax.annotation.Nullable; -import com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock; - import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/BackHalfShaftInstance.java b/src/main/java/com/simibubi/create/content/kinetics/base/BackHalfShaftInstance.java new file mode 100644 index 000000000..c530c8c86 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/base/BackHalfShaftInstance.java @@ -0,0 +1,17 @@ +package com.simibubi.create.content.kinetics.base; + +import com.jozufozu.flywheel.api.MaterialManager; + +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; + +public class BackHalfShaftInstance extends HalfShaftInstance { + public BackHalfShaftInstance(MaterialManager materialManager, T blockEntity) { + super(materialManager, blockEntity); + } + + @Override + protected Direction getShaftDirection() { + return blockState.getValue(BlockStateProperties.FACING).getOpposite(); + } +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/BlockBreakingKineticBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/base/BlockBreakingKineticBlockEntity.java new file mode 100644 index 000000000..b2159fd7b --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/base/BlockBreakingKineticBlockEntity.java @@ -0,0 +1,158 @@ +package com.simibubi.create.content.kinetics.base; + +import java.util.concurrent.atomic.AtomicInteger; + +import com.simibubi.create.foundation.utility.BlockHelper; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.sounds.SoundSource; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.level.GameRules; +import net.minecraft.world.level.block.AirBlock; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public abstract class BlockBreakingKineticBlockEntity extends KineticBlockEntity { + + public static final AtomicInteger NEXT_BREAKER_ID = new AtomicInteger(); + protected int ticksUntilNextProgress; + protected int destroyProgress; + protected int breakerId = -NEXT_BREAKER_ID.incrementAndGet(); + protected BlockPos breakingPos; + + public BlockBreakingKineticBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + public void onSpeedChanged(float prevSpeed) { + super.onSpeedChanged(prevSpeed); + if (destroyProgress == -1) + destroyNextTick(); + } + + @Override + public void lazyTick() { + super.lazyTick(); + if (ticksUntilNextProgress == -1) + destroyNextTick(); + } + + public void destroyNextTick() { + ticksUntilNextProgress = 1; + } + + protected abstract BlockPos getBreakingPos(); + + protected boolean shouldRun() { + return true; + } + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + compound.putInt("Progress", destroyProgress); + compound.putInt("NextTick", ticksUntilNextProgress); + if (breakingPos != null) + compound.put("Breaking", NbtUtils.writeBlockPos(breakingPos)); + super.write(compound, clientPacket); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + destroyProgress = compound.getInt("Progress"); + ticksUntilNextProgress = compound.getInt("NextTick"); + if (compound.contains("Breaking")) + breakingPos = NbtUtils.readBlockPos(compound.getCompound("Breaking")); + super.read(compound, clientPacket); + } + + @Override + public void invalidate() { + super.invalidate(); + if (!level.isClientSide && destroyProgress != 0) + level.destroyBlockProgress(breakerId, breakingPos, -1); + } + + @Override + public void tick() { + super.tick(); + + if (level.isClientSide) + return; + if (!shouldRun()) + return; + if (getSpeed() == 0) + return; + + breakingPos = getBreakingPos(); + + if (ticksUntilNextProgress < 0) + return; + if (ticksUntilNextProgress-- > 0) + return; + + BlockState stateToBreak = level.getBlockState(breakingPos); + float blockHardness = stateToBreak.getDestroySpeed(level, breakingPos); + + if (!canBreak(stateToBreak, blockHardness)) { + if (destroyProgress != 0) { + destroyProgress = 0; + level.destroyBlockProgress(breakerId, breakingPos, -1); + } + return; + } + + float breakSpeed = getBreakSpeed(); + destroyProgress += Mth.clamp((int) (breakSpeed / blockHardness), 1, 10 - destroyProgress); + level.playSound(null, worldPosition, stateToBreak.getSoundType() + .getHitSound(), SoundSource.NEUTRAL, .25f, 1); + + if (destroyProgress >= 10) { + onBlockBroken(stateToBreak); + destroyProgress = 0; + ticksUntilNextProgress = -1; + level.destroyBlockProgress(breakerId, breakingPos, -1); + return; + } + + ticksUntilNextProgress = (int) (blockHardness / breakSpeed); + level.destroyBlockProgress(breakerId, breakingPos, (int) destroyProgress); + } + + public boolean canBreak(BlockState stateToBreak, float blockHardness) { + return isBreakable(stateToBreak, blockHardness); + } + + public static boolean isBreakable(BlockState stateToBreak, float blockHardness) { + return !(stateToBreak.getMaterial() + .isLiquid() || stateToBreak.getBlock() instanceof AirBlock || blockHardness == -1); + } + + public void onBlockBroken(BlockState stateToBreak) { + Vec3 vec = VecHelper.offsetRandomly(VecHelper.getCenterOf(breakingPos), level.random, .125f); + BlockHelper.destroyBlock(level, breakingPos, 1f, (stack) -> { + if (stack.isEmpty()) + return; + if (!level.getGameRules() + .getBoolean(GameRules.RULE_DOBLOCKDROPS)) + return; + if (level.restoringBlockSnapshots) + return; + + ItemEntity itementity = new ItemEntity(level, vec.x, vec.y, vec.z, stack); + itementity.setDefaultPickUpDelay(); + itementity.setDeltaMovement(Vec3.ZERO); + level.addFreshEntity(itementity); + }); + } + + protected float getBreakSpeed() { + return Math.abs(getSpeed() / 100f); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/BlockBreakingMovementBehaviour.java b/src/main/java/com/simibubi/create/content/kinetics/base/BlockBreakingMovementBehaviour.java similarity index 84% rename from src/main/java/com/simibubi/create/content/contraptions/components/actors/BlockBreakingMovementBehaviour.java rename to src/main/java/com/simibubi/create/content/kinetics/base/BlockBreakingMovementBehaviour.java index 70771c429..72b6bd20c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/BlockBreakingMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/BlockBreakingMovementBehaviour.java @@ -1,9 +1,11 @@ -package com.simibubi.create.content.contraptions.components.actors; +package com.simibubi.create.content.kinetics.base; -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; -import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.OrientedContraptionEntity; +import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.contraptions.mounted.MountedContraption; +import com.simibubi.create.content.trains.entity.CarriageContraption; import com.simibubi.create.foundation.utility.BlockHelper; import net.minecraft.core.BlockPos; @@ -28,7 +30,7 @@ public class BlockBreakingMovementBehaviour implements MovementBehaviour { public void startMoving(MovementContext context) { if (context.world.isClientSide) return; - context.data.putInt("BreakerId", -BlockBreakingKineticTileEntity.NEXT_BREAKER_ID.incrementAndGet()); + context.data.putInt("BreakerId", -BlockBreakingKineticBlockEntity.NEXT_BREAKER_ID.incrementAndGet()); } @Override @@ -40,9 +42,9 @@ public class BlockBreakingMovementBehaviour implements MovementBehaviour { damageEntities(context, pos, world); if (world.isClientSide) return; + if (!canBreak(world, pos, stateVisited)) return; - context.data.put("BreakingPos", NbtUtils.writeBlockPos(pos)); context.stall = true; } @@ -180,7 +182,7 @@ public class BlockBreakingMovementBehaviour implements MovementBehaviour { return; } - float breakSpeed = Mth.clamp(Math.abs(context.getAnimationSpeed()) / 500f, 1 / 128f, 16f); + float breakSpeed = getBlockBreakingSpeed(context); destroyProgress += Mth.clamp((int) (breakSpeed / blockHardness), 1, 10 - destroyProgress); world.playSound(null, breakingPos, stateToBreak.getSoundType() .getHitSound(), SoundSource.NEUTRAL, .25f, 1); @@ -199,7 +201,7 @@ public class BlockBreakingMovementBehaviour implements MovementBehaviour { context.stall = false; if (shouldDestroyStartBlock(stateToBreak)) - BlockHelper.destroyBlock(context.world, breakingPos, 1f, stack -> this.dropItem(context, stack)); + destroyBlock(context, breakingPos); onBlockBroken(context, ogPos, stateToBreak); ticksUntilNextProgress = -1; data.remove("Progress"); @@ -214,13 +216,26 @@ public class BlockBreakingMovementBehaviour implements MovementBehaviour { data.putInt("Progress", destroyProgress); } + protected void destroyBlock(MovementContext context, BlockPos breakingPos) { + BlockHelper.destroyBlock(context.world, breakingPos, 1f, stack -> this.dropItem(context, stack)); + } + + protected float getBlockBreakingSpeed(MovementContext context) { + float lowerLimit = 1 / 128f; + if (context.contraption instanceof MountedContraption) + lowerLimit = 1f; + if (context.contraption instanceof CarriageContraption) + lowerLimit = 2f; + return Mth.clamp(Math.abs(context.getAnimationSpeed()) / 500f, lowerLimit, 16f); + } + protected boolean shouldDestroyStartBlock(BlockState stateToBreak) { return true; } public boolean canBreak(Level world, BlockPos breakingPos, BlockState state) { float blockHardness = state.getDestroySpeed(world, breakingPos); - return BlockBreakingKineticTileEntity.isBreakable(state, blockHardness); + return BlockBreakingKineticBlockEntity.isBreakable(state, blockHardness); } protected void onBlockBroken(MovementContext context, BlockPos pos, BlockState brokenState) { diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/CutoutRotatingInstance.java b/src/main/java/com/simibubi/create/content/kinetics/base/CutoutRotatingInstance.java new file mode 100644 index 000000000..72b3767be --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/base/CutoutRotatingInstance.java @@ -0,0 +1,18 @@ +package com.simibubi.create.content.kinetics.base; + +import com.jozufozu.flywheel.api.Material; +import com.jozufozu.flywheel.api.MaterialManager; +import com.simibubi.create.content.kinetics.base.flwdata.RotatingData; +import com.simibubi.create.foundation.render.AllMaterialSpecs; + +public class CutoutRotatingInstance extends SingleRotatingInstance { + public CutoutRotatingInstance(MaterialManager materialManager, T blockEntity) { + super(materialManager, blockEntity); + } + + @Override + protected Material getRotatingMaterial() { + return materialManager.defaultCutout() + .material(AllMaterialSpecs.ROTATING); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/DirectionalAxisKineticBlock.java b/src/main/java/com/simibubi/create/content/kinetics/base/DirectionalAxisKineticBlock.java similarity index 95% rename from src/main/java/com/simibubi/create/content/contraptions/base/DirectionalAxisKineticBlock.java rename to src/main/java/com/simibubi/create/content/kinetics/base/DirectionalAxisKineticBlock.java index de3f0345d..f94b67d2b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/DirectionalAxisKineticBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/DirectionalAxisKineticBlock.java @@ -1,7 +1,7 @@ -package com.simibubi.create.content.contraptions.base; +package com.simibubi.create.content.kinetics.base; -import com.simibubi.create.content.contraptions.components.structureMovement.ITransformableBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform; +import com.simibubi.create.content.contraptions.ITransformableBlock; +import com.simibubi.create.content.contraptions.StructureTransform; import com.simibubi.create.foundation.utility.Iterate; import net.minecraft.core.BlockPos; diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/DirectionalKineticBlock.java b/src/main/java/com/simibubi/create/content/kinetics/base/DirectionalKineticBlock.java similarity index 97% rename from src/main/java/com/simibubi/create/content/contraptions/base/DirectionalKineticBlock.java rename to src/main/java/com/simibubi/create/content/kinetics/base/DirectionalKineticBlock.java index 219643025..9e9669755 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/DirectionalKineticBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/DirectionalKineticBlock.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.base; +package com.simibubi.create.content.kinetics.base; import com.simibubi.create.foundation.utility.Iterate; diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/DirectionalShaftHalvesBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/base/DirectionalShaftHalvesBlockEntity.java new file mode 100644 index 000000000..aa6735987 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/base/DirectionalShaftHalvesBlockEntity.java @@ -0,0 +1,19 @@ +package com.simibubi.create.content.kinetics.base; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; + +public class DirectionalShaftHalvesBlockEntity extends KineticBlockEntity { + + public DirectionalShaftHalvesBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + public Direction getSourceFacing() { + BlockPos localSource = source.subtract(getBlockPos()); + return Direction.getNearest(localSource.getX(), localSource.getY(), localSource.getZ()); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/GeneratingKineticBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/base/GeneratingKineticBlockEntity.java new file mode 100644 index 000000000..b11625687 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/base/GeneratingKineticBlockEntity.java @@ -0,0 +1,171 @@ +package com.simibubi.create.content.kinetics.base; + +import java.util.List; + +import com.simibubi.create.content.kinetics.KineticNetwork; +import com.simibubi.create.content.kinetics.base.IRotate.SpeedLevel; +import com.simibubi.create.content.kinetics.base.IRotate.StressImpact; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.ChatFormatting; +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; +import net.minecraft.util.Mth; +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 GeneratingKineticBlockEntity extends KineticBlockEntity { + + public boolean reActivateSource; + + public GeneratingKineticBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + protected void notifyStressCapacityChange(float capacity) { + getOrCreateNetwork().updateCapacityFor(this, capacity); + } + + @Override + public void removeSource() { + if (hasSource() && isSource()) + reActivateSource = true; + super.removeSource(); + } + + @Override + public void setSource(BlockPos source) { + super.setSource(source); + BlockEntity blockEntity = level.getBlockEntity(source); + if (!(blockEntity instanceof KineticBlockEntity)) + return; + KineticBlockEntity sourceBE = (KineticBlockEntity) blockEntity; + if (reActivateSource && Math.abs(sourceBE.getSpeed()) >= Math.abs(getGeneratedSpeed())) + reActivateSource = false; + } + + @Override + public void tick() { + super.tick(); + if (reActivateSource) { + updateGeneratedRotation(); + reActivateSource = false; + } + } + + @Override + public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { + boolean added = super.addToGoggleTooltip(tooltip, isPlayerSneaking); + if (!StressImpact.isEnabled()) + return added; + + float stressBase = calculateAddedStressCapacity(); + if (Mth.equal(stressBase, 0)) + return added; + + Lang.translate("gui.goggles.generator_stats") + .forGoggles(tooltip); + Lang.translate("tooltip.capacityProvided") + .style(ChatFormatting.GRAY) + .forGoggles(tooltip); + + float speed = getTheoreticalSpeed(); + if (speed != getGeneratedSpeed() && speed != 0) + stressBase *= getGeneratedSpeed() / speed; + speed = Math.abs(speed); + + float stressTotal = stressBase * speed; + + Lang.number(stressTotal) + .translate("generic.unit.stress") + .style(ChatFormatting.AQUA) + .space() + .add(Lang.translate("gui.goggles.at_current_speed") + .style(ChatFormatting.DARK_GRAY)) + .forGoggles(tooltip, 1); + + return true; + } + + public void updateGeneratedRotation() { + float speed = getGeneratedSpeed(); + float prevSpeed = this.speed; + + if (level == null || level.isClientSide) + return; + + if (prevSpeed != speed) { + if (!hasSource()) { + SpeedLevel levelBefore = SpeedLevel.of(this.speed); + SpeedLevel levelafter = SpeedLevel.of(speed); + if (levelBefore != levelafter) + effects.queueRotationIndicators(); + } + + applyNewSpeed(prevSpeed, speed); + } + + if (hasNetwork() && speed != 0) { + KineticNetwork network = getOrCreateNetwork(); + notifyStressCapacityChange(calculateAddedStressCapacity()); + getOrCreateNetwork().updateStressFor(this, calculateStressApplied()); + network.updateStress(); + } + + onSpeedChanged(prevSpeed); + sendData(); + } + + public void applyNewSpeed(float prevSpeed, float speed) { + + // Speed changed to 0 + if (speed == 0) { + if (hasSource()) { + notifyStressCapacityChange(0); + getOrCreateNetwork().updateStressFor(this, calculateStressApplied()); + return; + } + detachKinetics(); + setSpeed(0); + setNetwork(null); + return; + } + + // Now turning - create a new Network + if (prevSpeed == 0) { + setSpeed(speed); + setNetwork(createNetworkId()); + attachKinetics(); + return; + } + + // Change speed when overpowered by other generator + if (hasSource()) { + + // Staying below Overpowered speed + if (Math.abs(prevSpeed) >= Math.abs(speed)) { + if (Math.signum(prevSpeed) != Math.signum(speed)) + level.destroyBlock(worldPosition, true); + return; + } + + // Faster than attached network -> become the new source + detachKinetics(); + setSpeed(speed); + source = null; + setNetwork(createNetworkId()); + attachKinetics(); + return; + } + + // Reapply source + detachKinetics(); + setSpeed(speed); + attachKinetics(); + } + + public Long createNetworkId() { + return worldPosition.asLong(); + } +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/HalfShaftInstance.java b/src/main/java/com/simibubi/create/content/kinetics/base/HalfShaftInstance.java new file mode 100644 index 000000000..ce0b1f33d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/base/HalfShaftInstance.java @@ -0,0 +1,25 @@ +package com.simibubi.create.content.kinetics.base; + +import com.jozufozu.flywheel.api.Instancer; +import com.jozufozu.flywheel.api.MaterialManager; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.flwdata.RotatingData; + +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; + +public class HalfShaftInstance extends SingleRotatingInstance { + public HalfShaftInstance(MaterialManager materialManager, T blockEntity) { + super(materialManager, blockEntity); + } + + @Override + protected Instancer getModel() { + Direction dir = getShaftDirection(); + return getRotatingMaterial().getModel(AllPartialModels.SHAFT_HALF, blockState, dir); + } + + protected Direction getShaftDirection() { + return blockState.getValue(BlockStateProperties.FACING); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/HorizontalAxisKineticBlock.java b/src/main/java/com/simibubi/create/content/kinetics/base/HorizontalAxisKineticBlock.java similarity index 98% rename from src/main/java/com/simibubi/create/content/contraptions/base/HorizontalAxisKineticBlock.java rename to src/main/java/com/simibubi/create/content/kinetics/base/HorizontalAxisKineticBlock.java index a9c674ac9..5b12fc4bd 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/HorizontalAxisKineticBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/HorizontalAxisKineticBlock.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.base; +package com.simibubi.create.content.kinetics.base; import com.simibubi.create.foundation.utility.Iterate; diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/HorizontalHalfShaftInstance.java b/src/main/java/com/simibubi/create/content/kinetics/base/HorizontalHalfShaftInstance.java new file mode 100644 index 000000000..297807d33 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/base/HorizontalHalfShaftInstance.java @@ -0,0 +1,18 @@ +package com.simibubi.create.content.kinetics.base; + +import com.jozufozu.flywheel.api.MaterialManager; + +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; + +public class HorizontalHalfShaftInstance extends HalfShaftInstance { + + public HorizontalHalfShaftInstance(MaterialManager materialManager, T blockEntity) { + super(materialManager, blockEntity); + } + + @Override + protected Direction getShaftDirection() { + return blockState.getValue(BlockStateProperties.HORIZONTAL_FACING).getOpposite(); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/HorizontalKineticBlock.java b/src/main/java/com/simibubi/create/content/kinetics/base/HorizontalKineticBlock.java similarity index 97% rename from src/main/java/com/simibubi/create/content/contraptions/base/HorizontalKineticBlock.java rename to src/main/java/com/simibubi/create/content/kinetics/base/HorizontalKineticBlock.java index 85cfc7e95..027ba89eb 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/HorizontalKineticBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/HorizontalKineticBlock.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.base; +package com.simibubi.create.content.kinetics.base; import com.simibubi.create.foundation.utility.Iterate; diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/IRotate.java b/src/main/java/com/simibubi/create/content/kinetics/base/IRotate.java similarity index 83% rename from src/main/java/com/simibubi/create/content/contraptions/base/IRotate.java rename to src/main/java/com/simibubi/create/content/kinetics/base/IRotate.java index 089d86101..73afc24b9 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/IRotate.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/IRotate.java @@ -1,10 +1,10 @@ -package com.simibubi.create.content.contraptions.base; +package com.simibubi.create.content.kinetics.base; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.item.ItemDescription; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.foundation.item.TooltipHelper; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.LangBuilder; +import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; @@ -46,10 +46,10 @@ public interface IRotate extends IWrenchable { public float getSpeedValue() { switch (this) { case FAST: - return AllConfigs.SERVER.kinetics.fastSpeed.get() + return AllConfigs.server().kinetics.fastSpeed.get() .floatValue(); case MEDIUM: - return AllConfigs.SERVER.kinetics.mediumSpeed.get() + return AllConfigs.server().kinetics.mediumSpeed.get() .floatValue(); case SLOW: return 1; @@ -62,9 +62,9 @@ public interface IRotate extends IWrenchable { public static SpeedLevel of(float speed) { speed = Math.abs(speed); - if (speed >= AllConfigs.SERVER.kinetics.fastSpeed.get()) + if (speed >= AllConfigs.server().kinetics.fastSpeed.get()) return FAST; - if (speed >= AllConfigs.SERVER.kinetics.mediumSpeed.get()) + if (speed >= AllConfigs.server().kinetics.mediumSpeed.get()) return MEDIUM; if (speed >= 1) return SLOW; @@ -73,7 +73,7 @@ public interface IRotate extends IWrenchable { public static LangBuilder getFormattedSpeedText(float speed, boolean overstressed) { SpeedLevel speedLevel = of(speed); - LangBuilder builder = Lang.text(ItemDescription.makeProgressBar(3, speedLevel.ordinal())); + LangBuilder builder = Lang.text(TooltipHelper.makeProgressBar(3, speedLevel.ordinal())); builder.translate("tooltip.speedRequirement." + Lang.asId(speedLevel.name())) .space() @@ -128,12 +128,12 @@ public interface IRotate extends IWrenchable { } public static boolean isEnabled() { - return !AllConfigs.SERVER.kinetics.disableStress.get(); + return !AllConfigs.server().kinetics.disableStress.get(); } public static LangBuilder getFormattedStressText(double stressPercent) { StressImpact stressLevel = of(stressPercent); - return Lang.text(ItemDescription.makeProgressBar(3, Math.min(stressLevel.ordinal() + 1, 3))) + return Lang.text(TooltipHelper.makeProgressBar(3, Math.min(stressLevel.ordinal() + 1, 3))) .translate("tooltip.stressImpact." + Lang.asId(stressLevel.name())) .text(String.format(" (%s%%) ", (int) (stressPercent * 100))) .style(stressLevel.getRelativeColor()); diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/KineticBlock.java b/src/main/java/com/simibubi/create/content/kinetics/base/KineticBlock.java new file mode 100644 index 000000000..40882f34f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/base/KineticBlock.java @@ -0,0 +1,104 @@ +package com.simibubi.create.content.kinetics.base; + +import com.simibubi.create.foundation.advancement.AdvancementBehaviour; +import com.simibubi.create.foundation.block.IBE; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; + +public abstract class KineticBlock extends Block implements IRotate { + + public KineticBlock(Properties properties) { + super(properties); + } + + @Override + public void onPlace(BlockState state, Level worldIn, BlockPos pos, BlockState oldState, boolean isMoving) { + // onBlockAdded is useless for init, as sometimes the BE gets re-instantiated + + // however, if a block change occurs that does not change kinetic connections, + // we can prevent a major re-propagation here + + BlockEntity blockEntity = worldIn.getBlockEntity(pos); + if (blockEntity instanceof KineticBlockEntity) { + KineticBlockEntity kineticBlockEntity = (KineticBlockEntity) blockEntity; + kineticBlockEntity.preventSpeedUpdate = 0; + + if (oldState.getBlock() != state.getBlock()) + return; + if (state.hasBlockEntity() != oldState.hasBlockEntity()) + return; + if (!areStatesKineticallyEquivalent(oldState, state)) + return; + + kineticBlockEntity.preventSpeedUpdate = 2; + } + } + + @Override + public void onRemove(BlockState pState, Level pLevel, BlockPos pPos, BlockState pNewState, boolean pIsMoving) { + IBE.onRemove(pState, pLevel, pPos, pNewState); + } + + @Override + public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) { + return false; + } + + protected boolean areStatesKineticallyEquivalent(BlockState oldState, BlockState newState) { + if (oldState.getBlock() != newState.getBlock()) + return false; + return getRotationAxis(newState) == getRotationAxis(oldState); + } + + @Override + public void updateIndirectNeighbourShapes(BlockState stateIn, LevelAccessor worldIn, BlockPos pos, int flags, + int count) { + if (worldIn.isClientSide()) + return; + + BlockEntity blockEntity = worldIn.getBlockEntity(pos); + if (!(blockEntity instanceof KineticBlockEntity)) + return; + KineticBlockEntity kbe = (KineticBlockEntity) blockEntity; + + if (kbe.preventSpeedUpdate > 0) + return; + + // Remove previous information when block is added + kbe.warnOfMovement(); + kbe.clearKineticInformation(); + kbe.updateSpeed = true; + } + + @Override + public void setPlacedBy(Level worldIn, BlockPos pos, BlockState state, LivingEntity placer, ItemStack stack) { + AdvancementBehaviour.setPlacedBy(worldIn, pos, placer); + if (worldIn.isClientSide) + return; + + BlockEntity blockEntity = worldIn.getBlockEntity(pos); + if (!(blockEntity instanceof KineticBlockEntity)) + return; + + KineticBlockEntity kbe = (KineticBlockEntity) blockEntity; + kbe.effects.queueRotationIndicators(); + } + + public float getParticleTargetRadius() { + return .65f; + } + + public float getParticleInitialRadius() { + return .75f; + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/KineticBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/base/KineticBlockEntity.java new file mode 100644 index 000000000..09fe0c834 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/base/KineticBlockEntity.java @@ -0,0 +1,611 @@ +package com.simibubi.create.content.kinetics.base; + +import static net.minecraft.ChatFormatting.GOLD; +import static net.minecraft.ChatFormatting.GRAY; + +import java.util.List; + +import javax.annotation.Nullable; + +import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; +import com.simibubi.create.Create; +import com.simibubi.create.content.equipment.goggles.IHaveGoggleInformation; +import com.simibubi.create.content.equipment.goggles.IHaveHoveringInformation; +import com.simibubi.create.content.kinetics.BlockStressValues; +import com.simibubi.create.content.kinetics.KineticNetwork; +import com.simibubi.create.content.kinetics.RotationPropagator; +import com.simibubi.create.content.kinetics.base.IRotate.SpeedLevel; +import com.simibubi.create.content.kinetics.base.IRotate.StressImpact; +import com.simibubi.create.content.kinetics.gearbox.GearboxBlock; +import com.simibubi.create.content.kinetics.simpleRelays.ICogWheel; +import com.simibubi.create.content.kinetics.transmission.sequencer.SequencedGearshiftBlockEntity.SequenceContext; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.item.TooltipHelper; +import com.simibubi.create.foundation.item.TooltipHelper.Palette; +import com.simibubi.create.foundation.sound.SoundScapes; +import com.simibubi.create.foundation.sound.SoundScapes.AmbienceGroup; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.minecraft.ChatFormatting; +import net.minecraft.client.resources.language.I18n; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.util.Mth; +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.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.fml.DistExecutor; + +public class KineticBlockEntity extends SmartBlockEntity implements IHaveGoggleInformation, IHaveHoveringInformation { + + public @Nullable Long network; + public @Nullable BlockPos source; + public boolean networkDirty; + public boolean updateSpeed; + public int preventSpeedUpdate; + + protected KineticEffectHandler effects; + protected float speed; + protected float capacity; + protected float stress; + protected boolean overStressed; + protected boolean wasMoved; + + private int flickerTally; + private int networkSize; + private int validationCountdown; + protected float lastStressApplied; + protected float lastCapacityProvided; + + public SequenceContext sequenceContext; + + public KineticBlockEntity(BlockEntityType typeIn, BlockPos pos, BlockState state) { + super(typeIn, pos, state); + effects = new KineticEffectHandler(this); + updateSpeed = true; + } + + @Override + public void initialize() { + if (hasNetwork() && !level.isClientSide) { + KineticNetwork network = getOrCreateNetwork(); + if (!network.initialized) + network.initFromTE(capacity, stress, networkSize); + network.addSilently(this, lastCapacityProvided, lastStressApplied); + } + + super.initialize(); + } + + @Override + public void tick() { + if (!level.isClientSide && needsSpeedUpdate()) + attachKinetics(); + + super.tick(); + effects.tick(); + + preventSpeedUpdate = 0; + + if (level.isClientSide) { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> this.tickAudio()); + return; + } + + if (validationCountdown-- <= 0) { + validationCountdown = AllConfigs.server().kinetics.kineticValidationFrequency.get(); + validateKinetics(); + } + + if (getFlickerScore() > 0) + flickerTally = getFlickerScore() - 1; + + if (networkDirty) { + if (hasNetwork()) + getOrCreateNetwork().updateNetwork(); + networkDirty = false; + } + } + + private void validateKinetics() { + if (hasSource()) { + if (!hasNetwork()) { + removeSource(); + return; + } + + if (!level.isLoaded(source)) + return; + + BlockEntity blockEntity = level.getBlockEntity(source); + KineticBlockEntity sourceBE = + blockEntity instanceof KineticBlockEntity ? (KineticBlockEntity) blockEntity : null; + if (sourceBE == null || sourceBE.speed == 0) { + removeSource(); + detachKinetics(); + return; + } + + return; + } + + if (speed != 0) { + if (getGeneratedSpeed() == 0) + speed = 0; + } + } + + public void updateFromNetwork(float maxStress, float currentStress, int networkSize) { + networkDirty = false; + this.capacity = maxStress; + this.stress = currentStress; + this.networkSize = networkSize; + boolean overStressed = maxStress < currentStress && StressImpact.isEnabled(); + setChanged(); + + if (overStressed != this.overStressed) { + float prevSpeed = getSpeed(); + this.overStressed = overStressed; + onSpeedChanged(prevSpeed); + sendData(); + } + } + + protected Block getStressConfigKey() { + return getBlockState().getBlock(); + } + + public float calculateStressApplied() { + float impact = (float) BlockStressValues.getImpact(getStressConfigKey()); + this.lastStressApplied = impact; + return impact; + } + + public float calculateAddedStressCapacity() { + float capacity = (float) BlockStressValues.getCapacity(getStressConfigKey()); + this.lastCapacityProvided = capacity; + return capacity; + } + + public void onSpeedChanged(float previousSpeed) { + boolean fromOrToZero = (previousSpeed == 0) != (getSpeed() == 0); + boolean directionSwap = !fromOrToZero && Math.signum(previousSpeed) != Math.signum(getSpeed()); + if (fromOrToZero || directionSwap) + flickerTally = getFlickerScore() + 5; + setChanged(); + } + + @Override + public void remove() { + if (!level.isClientSide) { + if (hasNetwork()) + getOrCreateNetwork().remove(this); + detachKinetics(); + } + super.remove(); + } + + @Override + protected void write(CompoundTag compound, boolean clientPacket) { + compound.putFloat("Speed", speed); + if (sequenceContext != null && (!clientPacket || syncSequenceContext())) + compound.put("Sequence", sequenceContext.serializeNBT()); + + if (needsSpeedUpdate()) + compound.putBoolean("NeedsSpeedUpdate", true); + + if (hasSource()) + compound.put("Source", NbtUtils.writeBlockPos(source)); + + if (hasNetwork()) { + CompoundTag networkTag = new CompoundTag(); + networkTag.putLong("Id", this.network); + networkTag.putFloat("Stress", stress); + networkTag.putFloat("Capacity", capacity); + networkTag.putInt("Size", networkSize); + + if (lastStressApplied != 0) + networkTag.putFloat("AddedStress", lastStressApplied); + if (lastCapacityProvided != 0) + networkTag.putFloat("AddedCapacity", lastCapacityProvided); + + compound.put("Network", networkTag); + } + + super.write(compound, clientPacket); + } + + public boolean needsSpeedUpdate() { + return updateSpeed; + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + boolean overStressedBefore = overStressed; + clearKineticInformation(); + + // DO NOT READ kinetic information when placed after movement + if (wasMoved) { + super.read(compound, clientPacket); + return; + } + + speed = compound.getFloat("Speed"); + sequenceContext = SequenceContext.fromNBT(compound.getCompound("Sequence")); + + if (compound.contains("Source")) + source = NbtUtils.readBlockPos(compound.getCompound("Source")); + + if (compound.contains("Network")) { + CompoundTag networkTag = compound.getCompound("Network"); + network = networkTag.getLong("Id"); + stress = networkTag.getFloat("Stress"); + capacity = networkTag.getFloat("Capacity"); + networkSize = networkTag.getInt("Size"); + lastStressApplied = networkTag.getFloat("AddedStress"); + lastCapacityProvided = networkTag.getFloat("AddedCapacity"); + overStressed = capacity < stress && StressImpact.isEnabled(); + } + + super.read(compound, clientPacket); + + if (clientPacket && overStressedBefore != overStressed && speed != 0) + effects.triggerOverStressedEffect(); + + if (clientPacket) + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(this)); + } + + public float getGeneratedSpeed() { + return 0; + } + + public boolean isSource() { + return getGeneratedSpeed() != 0; + } + + public float getSpeed() { + if (overStressed) + return 0; + return getTheoreticalSpeed(); + } + + public float getTheoreticalSpeed() { + return speed; + } + + public void setSpeed(float speed) { + this.speed = speed; + } + + public boolean hasSource() { + return source != null; + } + + public void setSource(BlockPos source) { + this.source = source; + if (level == null || level.isClientSide) + return; + + BlockEntity blockEntity = level.getBlockEntity(source); + if (!(blockEntity instanceof KineticBlockEntity sourceBE)) { + removeSource(); + return; + } + + setNetwork(sourceBE.network); + copySequenceContextFrom(sourceBE); + } + + protected void copySequenceContextFrom(KineticBlockEntity sourceBE) { + sequenceContext = sourceBE.sequenceContext; + } + + public void removeSource() { + float prevSpeed = getSpeed(); + + speed = 0; + source = null; + setNetwork(null); + sequenceContext = null; + + onSpeedChanged(prevSpeed); + } + + public void setNetwork(@Nullable Long networkIn) { + if (network == networkIn) + return; + if (network != null) + getOrCreateNetwork().remove(this); + + network = networkIn; + setChanged(); + + if (networkIn == null) + return; + + network = networkIn; + KineticNetwork network = getOrCreateNetwork(); + network.initialized = true; + network.add(this); + } + + public KineticNetwork getOrCreateNetwork() { + return Create.TORQUE_PROPAGATOR.getOrCreateNetworkFor(this); + } + + public boolean hasNetwork() { + return network != null; + } + + public void attachKinetics() { + updateSpeed = false; + RotationPropagator.handleAdded(level, worldPosition, this); + } + + public void detachKinetics() { + RotationPropagator.handleRemoved(level, worldPosition, this); + } + + public boolean isSpeedRequirementFulfilled() { + BlockState state = getBlockState(); + if (!(getBlockState().getBlock() instanceof IRotate)) + return true; + IRotate def = (IRotate) state.getBlock(); + SpeedLevel minimumRequiredSpeedLevel = def.getMinimumRequiredSpeedLevel(); + return Math.abs(getSpeed()) >= minimumRequiredSpeedLevel.getSpeedValue(); + } + + public static void switchToBlockState(Level world, BlockPos pos, BlockState state) { + if (world.isClientSide) + return; + + BlockEntity blockEntity = world.getBlockEntity(pos); + BlockState currentState = world.getBlockState(pos); + boolean isKinetic = blockEntity instanceof KineticBlockEntity; + + if (currentState == state) + return; + if (blockEntity == null || !isKinetic) { + world.setBlock(pos, state, 3); + return; + } + + KineticBlockEntity kineticBlockEntity = (KineticBlockEntity) blockEntity; + if (state.getBlock() instanceof KineticBlock + && !((KineticBlock) state.getBlock()).areStatesKineticallyEquivalent(currentState, state)) { + if (kineticBlockEntity.hasNetwork()) + kineticBlockEntity.getOrCreateNetwork() + .remove(kineticBlockEntity); + kineticBlockEntity.detachKinetics(); + kineticBlockEntity.removeSource(); + } + + world.setBlock(pos, state, 3); + } + + @Override + public void addBehaviours(List behaviours) {} + + @Override + public boolean addToTooltip(List tooltip, boolean isPlayerSneaking) { + boolean notFastEnough = !isSpeedRequirementFulfilled() && getSpeed() != 0; + + if (overStressed && AllConfigs.client().enableOverstressedTooltip.get()) { + Lang.translate("gui.stressometer.overstressed") + .style(GOLD) + .forGoggles(tooltip); + Component hint = Lang.translateDirect("gui.contraptions.network_overstressed"); + List cutString = TooltipHelper.cutTextComponent(hint, Palette.GRAY_AND_WHITE); + for (int i = 0; i < cutString.size(); i++) + Lang.builder() + .add(cutString.get(i) + .copy()) + .forGoggles(tooltip); + return true; + } + + if (notFastEnough) { + Lang.translate("tooltip.speedRequirement") + .style(GOLD) + .forGoggles(tooltip); + MutableComponent hint = + Lang.translateDirect("gui.contraptions.not_fast_enough", I18n.get(getBlockState().getBlock() + .getDescriptionId())); + List cutString = TooltipHelper.cutTextComponent(hint, Palette.GRAY_AND_WHITE); + for (int i = 0; i < cutString.size(); i++) + Lang.builder() + .add(cutString.get(i) + .copy()) + .forGoggles(tooltip); + return true; + } + + return false; + } + + @Override + public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { + boolean added = false; + + if (!StressImpact.isEnabled()) + return added; + float stressAtBase = calculateStressApplied(); + if (Mth.equal(stressAtBase, 0)) + return added; + + Lang.translate("gui.goggles.kinetic_stats") + .forGoggles(tooltip); + + addStressImpactStats(tooltip, stressAtBase); + + return true; + + } + + protected void addStressImpactStats(List tooltip, float stressAtBase) { + Lang.translate("tooltip.stressImpact") + .style(GRAY) + .forGoggles(tooltip); + + float stressTotal = stressAtBase * Math.abs(getTheoreticalSpeed()); + + Lang.number(stressTotal) + .translate("generic.unit.stress") + .style(ChatFormatting.AQUA) + .space() + .add(Lang.translate("gui.goggles.at_current_speed") + .style(ChatFormatting.DARK_GRAY)) + .forGoggles(tooltip, 1); + } + + public void clearKineticInformation() { + speed = 0; + source = null; + network = null; + overStressed = false; + stress = 0; + capacity = 0; + lastStressApplied = 0; + lastCapacityProvided = 0; + } + + public void warnOfMovement() { + wasMoved = true; + } + + public int getFlickerScore() { + return flickerTally; + } + + public static float convertToDirection(float axisSpeed, Direction d) { + return d.getAxisDirection() == AxisDirection.POSITIVE ? axisSpeed : -axisSpeed; + } + + public static float convertToLinear(float speed) { + return speed / 512f; + } + + public static float convertToAngular(float speed) { + return speed * 3 / 10f; + } + + public boolean isOverStressed() { + return overStressed; + } + + // Custom Propagation + + /** + * Specify ratio of transferred rotation from this kinetic component to a + * specific other. + * + * @param target other Kinetic BE to transfer to + * @param stateFrom this BE's blockstate + * @param stateTo other BE's blockstate + * @param diff difference in position (to.pos - from.pos) + * @param connectedViaAxes whether these kinetic blocks are connected via mutual + * IRotate.hasShaftTowards() + * @param connectedViaCogs whether these kinetic blocks are connected via mutual + * IRotate.hasIntegratedCogwheel() + * @return factor of rotation speed from this BE to other. 0 if no rotation is + * transferred, or the standard rules apply (integrated shafts/cogs) + */ + public float propagateRotationTo(KineticBlockEntity target, BlockState stateFrom, BlockState stateTo, BlockPos diff, + boolean connectedViaAxes, boolean connectedViaCogs) { + return 0; + } + + /** + * Specify additional locations the rotation propagator should look for + * potentially connected components. Neighbour list contains offset positions in + * all 6 directions by default. + * + * @param block + * @param state + * @param neighbours + * @return + */ + public List addPropagationLocations(IRotate block, BlockState state, List neighbours) { + if (!canPropagateDiagonally(block, state)) + return neighbours; + + Axis axis = block.getRotationAxis(state); + BlockPos.betweenClosedStream(new BlockPos(-1, -1, -1), new BlockPos(1, 1, 1)) + .forEach(offset -> { + if (axis.choose(offset.getX(), offset.getY(), offset.getZ()) != 0) + return; + if (offset.distSqr(BlockPos.ZERO) != 2) + return; + neighbours.add(worldPosition.offset(offset)); + }); + return neighbours; + } + + /** + * Specify whether this component can propagate speed to the other in any + * circumstance. Shaft and cogwheel connections are already handled by internal + * logic. Does not have to be specified on both ends, it is assumed that this + * relation is symmetrical. + * + * @param other + * @param state + * @param otherState + * @return true if this and the other component should check their propagation + * factor and are not already connected via integrated cogs or shafts + */ + public boolean isCustomConnection(KineticBlockEntity other, BlockState state, BlockState otherState) { + return false; + } + + protected boolean canPropagateDiagonally(IRotate block, BlockState state) { + return ICogWheel.isSmallCog(state); + } + + @Override + public void requestModelDataUpdate() { + super.requestModelDataUpdate(); + if (!this.remove) + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(this)); + } + + @OnlyIn(Dist.CLIENT) + public void tickAudio() { + float componentSpeed = Math.abs(getSpeed()); + if (componentSpeed == 0) + return; + float pitch = Mth.clamp((componentSpeed / 256f) + .45f, .85f, 1f); + + if (isNoisy()) + SoundScapes.play(AmbienceGroup.KINETIC, worldPosition, pitch); + + Block block = getBlockState().getBlock(); + if (ICogWheel.isSmallCog(block) || ICogWheel.isLargeCog(block) || block instanceof GearboxBlock) + SoundScapes.play(AmbienceGroup.COG, worldPosition, pitch); + } + + protected boolean isNoisy() { + return true; + } + + public int getRotationAngleOffset(Axis axis) { + return 0; + } + + protected boolean syncSequenceContext() { + return false; + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/KineticBlockEntityInstance.java b/src/main/java/com/simibubi/create/content/kinetics/base/KineticBlockEntityInstance.java new file mode 100644 index 000000000..0cec4b1ec --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/base/KineticBlockEntityInstance.java @@ -0,0 +1,97 @@ +package com.simibubi.create.content.kinetics.base; + +import com.jozufozu.flywheel.api.Material; +import com.jozufozu.flywheel.api.MaterialManager; +import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.kinetics.base.flwdata.RotatingData; +import com.simibubi.create.content.kinetics.simpleRelays.ICogWheel; +import com.simibubi.create.content.kinetics.simpleRelays.ShaftBlock; +import com.simibubi.create.foundation.render.AllMaterialSpecs; + +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.world.level.block.state.BlockState; + +public abstract class KineticBlockEntityInstance extends BlockEntityInstance { + + protected final Direction.Axis axis; + + public KineticBlockEntityInstance(MaterialManager materialManager, T blockEntity) { + super(materialManager, blockEntity); + axis = (blockState.getBlock() instanceof IRotate irotate) ? irotate.getRotationAxis(blockState) : Axis.Y; + } + + protected final void updateRotation(RotatingData instance) { + updateRotation(instance, getRotationAxis(), getBlockEntitySpeed()); + } + + protected final void updateRotation(RotatingData instance, Direction.Axis axis) { + updateRotation(instance, axis, getBlockEntitySpeed()); + } + + protected final void updateRotation(RotatingData instance, float speed) { + updateRotation(instance, getRotationAxis(), speed); + } + + protected final void updateRotation(RotatingData instance, Direction.Axis axis, float speed) { + instance.setRotationAxis(axis) + .setRotationOffset(getRotationOffset(axis)) + .setRotationalSpeed(speed) + .setColor(blockEntity); + } + + protected final RotatingData setup(RotatingData key) { + return setup(key, getRotationAxis(), getBlockEntitySpeed()); + } + + protected final RotatingData setup(RotatingData key, Direction.Axis axis) { + return setup(key, axis, getBlockEntitySpeed()); + } + + protected final RotatingData setup(RotatingData key, float speed) { + return setup(key, getRotationAxis(), speed); + } + + protected final RotatingData setup(RotatingData key, Direction.Axis axis, float speed) { + key.setRotationAxis(axis) + .setRotationalSpeed(speed) + .setRotationOffset(getRotationOffset(axis)) + .setColor(blockEntity) + .setPosition(getInstancePosition()); + + return key; + } + + protected float getRotationOffset(final Direction.Axis axis) { + float offset = ICogWheel.isLargeCog(blockState) ? 11.25f : 0; + double d = (((axis == Direction.Axis.X) ? 0 : pos.getX()) + ((axis == Direction.Axis.Y) ? 0 : pos.getY()) + + ((axis == Direction.Axis.Z) ? 0 : pos.getZ())) % 2; + if (d == 0) { + offset = 22.5f; + } + return offset; + } + + protected Direction.Axis getRotationAxis() { + return axis; + } + + protected float getBlockEntitySpeed() { + return blockEntity.getSpeed(); + } + + protected BlockState shaft() { + return shaft(getRotationAxis()); + } + + protected Material getRotatingMaterial() { + return materialManager.defaultSolid() + .material(AllMaterialSpecs.ROTATING); + } + + public static BlockState shaft(Direction.Axis axis) { + return AllBlocks.SHAFT.getDefaultState() + .setValue(ShaftBlock.AXIS, axis); + } +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/KineticBlockEntityRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/base/KineticBlockEntityRenderer.java new file mode 100644 index 000000000..b5d8b9196 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/base/KineticBlockEntityRenderer.java @@ -0,0 +1,143 @@ +package com.simibubi.create.content.kinetics.base; + +import org.apache.commons.lang3.ArrayUtils; + +import com.jozufozu.flywheel.backend.Backend; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.kinetics.KineticDebugger; +import com.simibubi.create.content.kinetics.simpleRelays.ICogWheel; +import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.render.SuperByteBufferCache; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.Color; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraftforge.client.ChunkRenderTypeSet; +import net.minecraftforge.client.model.data.ModelData; + +public class KineticBlockEntityRenderer extends SafeBlockEntityRenderer { + + public static final SuperByteBufferCache.Compartment KINETIC_BLOCK = new SuperByteBufferCache.Compartment<>(); + public static boolean rainbowMode = false; + + protected static final RenderType[] REVERSED_CHUNK_BUFFER_LAYERS = RenderType.chunkBufferLayers().toArray(RenderType[]::new); + static { + ArrayUtils.reverse(REVERSED_CHUNK_BUFFER_LAYERS); + } + + public KineticBlockEntityRenderer(BlockEntityRendererProvider.Context context) { + } + + @Override + protected void renderSafe(T be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + if (Backend.canUseInstancing(be.getLevel())) return; + + BlockState state = getRenderedBlockState(be); + RenderType type = getRenderType(be, state); + if (type != null) + renderRotatingBuffer(be, getRotatedModel(be, state), ms, buffer.getBuffer(type), light); + } + + protected BlockState getRenderedBlockState(T be) { + return be.getBlockState(); + } + + protected RenderType getRenderType(T be, BlockState state) { + // TODO: this is not very clean + BakedModel model = Minecraft.getInstance() + .getBlockRenderer().getBlockModel(state); + ChunkRenderTypeSet typeSet = model.getRenderTypes(state, RandomSource.create(42L), ModelData.EMPTY); + for (RenderType type : REVERSED_CHUNK_BUFFER_LAYERS) + if (typeSet.contains(type)) + return type; + return null; + } + + protected SuperByteBuffer getRotatedModel(T be, BlockState state) { + return CachedBufferer.block(KINETIC_BLOCK, state); + } + + public static void renderRotatingKineticBlock(KineticBlockEntity be, BlockState renderedState, PoseStack ms, + VertexConsumer buffer, int light) { + SuperByteBuffer superByteBuffer = CachedBufferer.block(KINETIC_BLOCK, renderedState); + renderRotatingBuffer(be, superByteBuffer, ms, buffer, light); + } + + public static void renderRotatingBuffer(KineticBlockEntity be, SuperByteBuffer superBuffer, PoseStack ms, + VertexConsumer buffer, int light) { + standardKineticRotationTransform(superBuffer, be, light).renderInto(ms, buffer); + } + + public static float getAngleForTe(KineticBlockEntity be, final BlockPos pos, Axis axis) { + float time = AnimationTickHolder.getRenderTime(be.getLevel()); + float offset = getRotationOffsetForPosition(be, pos, axis); + float angle = ((time * be.getSpeed() * 3f / 10 + offset) % 360) / 180 * (float) Math.PI; + return angle; + } + + public static SuperByteBuffer standardKineticRotationTransform(SuperByteBuffer buffer, KineticBlockEntity be, + int light) { + final BlockPos pos = be.getBlockPos(); + Axis axis = ((IRotate) be.getBlockState() + .getBlock()).getRotationAxis(be.getBlockState()); + return kineticRotationTransform(buffer, be, axis, getAngleForTe(be, pos, axis), light); + } + + public static SuperByteBuffer kineticRotationTransform(SuperByteBuffer buffer, KineticBlockEntity be, Axis axis, + float angle, int light) { + buffer.light(light); + buffer.rotateCentered(Direction.get(AxisDirection.POSITIVE, axis), angle); + + if (KineticDebugger.isActive()) { + rainbowMode = true; + buffer.color(be.hasNetwork() ? Color.generateFromLong(be.network) : Color.WHITE); + } else { + float overStressedEffect = be.effects.overStressedEffect; + if (overStressedEffect != 0) + if (overStressedEffect > 0) + buffer.color(Color.WHITE.mixWith(Color.RED, overStressedEffect)); + else + buffer.color(Color.WHITE.mixWith(Color.SPRING_GREEN, -overStressedEffect)); + else + buffer.color(Color.WHITE); + } + + return buffer; + } + + public static float getRotationOffsetForPosition(KineticBlockEntity be, final BlockPos pos, final Axis axis) { + float offset = ICogWheel.isLargeCog(be.getBlockState()) ? 11.25f : 0; + double d = (((axis == Axis.X) ? 0 : pos.getX()) + ((axis == Axis.Y) ? 0 : pos.getY()) + + ((axis == Axis.Z) ? 0 : pos.getZ())) % 2; + if (d == 0) + offset = 22.5f; + return offset + be.getRotationAngleOffset(axis); + } + + public static BlockState shaft(Axis axis) { + return AllBlocks.SHAFT.getDefaultState() + .setValue(BlockStateProperties.AXIS, axis); + } + + public static Axis getRotationAxisOf(KineticBlockEntity be) { + return ((IRotate) be.getBlockState() + .getBlock()).getRotationAxis(be.getBlockState()); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/KineticEffectHandler.java b/src/main/java/com/simibubi/create/content/kinetics/base/KineticEffectHandler.java similarity index 91% rename from src/main/java/com/simibubi/create/content/contraptions/base/KineticEffectHandler.java rename to src/main/java/com/simibubi/create/content/kinetics/base/KineticEffectHandler.java index 6e9c35bac..b80763459 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/KineticEffectHandler.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/KineticEffectHandler.java @@ -1,7 +1,6 @@ -package com.simibubi.create.content.contraptions.base; +package com.simibubi.create.content.kinetics.base; -import com.simibubi.create.content.contraptions.base.IRotate.SpeedLevel; -import com.simibubi.create.content.contraptions.particle.RotationIndicatorParticleData; +import com.simibubi.create.content.kinetics.base.IRotate.SpeedLevel; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.core.BlockPos; @@ -20,9 +19,9 @@ public class KineticEffectHandler { int overStressedTime; float overStressedEffect; int particleSpawnCountdown; - KineticTileEntity kte; + KineticBlockEntity kte; - public KineticEffectHandler(KineticTileEntity kte) { + public KineticEffectHandler(KineticBlockEntity kte) { this.kte = kte; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/RotatedPillarKineticBlock.java b/src/main/java/com/simibubi/create/content/kinetics/base/RotatedPillarKineticBlock.java similarity index 97% rename from src/main/java/com/simibubi/create/content/contraptions/base/RotatedPillarKineticBlock.java rename to src/main/java/com/simibubi/create/content/kinetics/base/RotatedPillarKineticBlock.java index 2b199c07a..9c97e6b34 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/RotatedPillarKineticBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/RotatedPillarKineticBlock.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.base; +package com.simibubi.create.content.kinetics.base; import com.simibubi.create.foundation.utility.Iterate; diff --git a/src/main/java/com/simibubi/create/content/contraptions/particle/RotationIndicatorParticle.java b/src/main/java/com/simibubi/create/content/kinetics/base/RotationIndicatorParticle.java similarity index 96% rename from src/main/java/com/simibubi/create/content/contraptions/particle/RotationIndicatorParticle.java rename to src/main/java/com/simibubi/create/content/kinetics/base/RotationIndicatorParticle.java index 593940293..70aa4b028 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/particle/RotationIndicatorParticle.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/RotationIndicatorParticle.java @@ -1,7 +1,7 @@ -package com.simibubi.create.content.contraptions.particle; +package com.simibubi.create.content.kinetics.base; import com.mojang.blaze3d.vertex.VertexConsumer; -import com.simibubi.create.content.contraptions.goggles.GogglesItem; +import com.simibubi.create.content.equipment.goggles.GogglesItem; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.Color; import com.simibubi.create.foundation.utility.VecHelper; diff --git a/src/main/java/com/simibubi/create/content/contraptions/particle/RotationIndicatorParticleData.java b/src/main/java/com/simibubi/create/content/kinetics/base/RotationIndicatorParticleData.java similarity index 97% rename from src/main/java/com/simibubi/create/content/contraptions/particle/RotationIndicatorParticleData.java rename to src/main/java/com/simibubi/create/content/kinetics/base/RotationIndicatorParticleData.java index 02502d5cd..7a249f698 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/particle/RotationIndicatorParticleData.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/RotationIndicatorParticleData.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.particle; +package com.simibubi.create.content.kinetics.base; import java.util.Locale; @@ -10,6 +10,7 @@ import com.mojang.serialization.DynamicOps; import com.mojang.serialization.codecs.PrimitiveCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; import com.simibubi.create.AllParticleTypes; +import com.simibubi.create.foundation.particle.ICustomParticleDataWithSprite; import net.minecraft.client.particle.ParticleEngine.SpriteParticleRegistration; import net.minecraft.core.Direction.Axis; diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/ShaftInstance.java b/src/main/java/com/simibubi/create/content/kinetics/base/ShaftInstance.java new file mode 100644 index 000000000..6649249bb --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/base/ShaftInstance.java @@ -0,0 +1,18 @@ +package com.simibubi.create.content.kinetics.base; + +import com.jozufozu.flywheel.api.MaterialManager; + +import net.minecraft.world.level.block.state.BlockState; + +public class ShaftInstance extends SingleRotatingInstance { + + public ShaftInstance(MaterialManager materialManager, T blockEntity) { + super(materialManager, blockEntity); + } + + @Override + protected BlockState getRenderedBlockState() { + return shaft(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/ShaftRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/base/ShaftRenderer.java new file mode 100644 index 000000000..a0c722edf --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/base/ShaftRenderer.java @@ -0,0 +1,17 @@ +package com.simibubi.create.content.kinetics.base; + +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.world.level.block.state.BlockState; + +public class ShaftRenderer extends KineticBlockEntityRenderer { + + public ShaftRenderer(BlockEntityRendererProvider.Context context) { + super(context); + } + + @Override + protected BlockState getRenderedBlockState(KineticBlockEntity be) { + return shaft(getRotationAxisOf(be)); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/SingleRotatingInstance.java b/src/main/java/com/simibubi/create/content/kinetics/base/SingleRotatingInstance.java new file mode 100644 index 000000000..1a38e762a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/base/SingleRotatingInstance.java @@ -0,0 +1,44 @@ +package com.simibubi.create.content.kinetics.base; + +import com.jozufozu.flywheel.api.Instancer; +import com.jozufozu.flywheel.api.MaterialManager; +import com.simibubi.create.content.kinetics.base.flwdata.RotatingData; + +import net.minecraft.world.level.block.state.BlockState; + +public class SingleRotatingInstance extends KineticBlockEntityInstance { + + protected RotatingData rotatingModel; + + public SingleRotatingInstance(MaterialManager materialManager, T blockEntity) { + super(materialManager, blockEntity); + } + + @Override + public void init() { + rotatingModel = setup(getModel().createInstance()); + } + + @Override + public void update() { + updateRotation(rotatingModel); + } + + @Override + public void updateLight() { + relight(pos, rotatingModel); + } + + @Override + public void remove() { + rotatingModel.delete(); + } + + protected BlockState getRenderedBlockState() { + return blockState; + } + + protected Instancer getModel() { + return getRotatingMaterial().getModel(getRenderedBlockState()); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/flwdata/BeltData.java b/src/main/java/com/simibubi/create/content/kinetics/base/flwdata/BeltData.java similarity index 94% rename from src/main/java/com/simibubi/create/content/contraptions/base/flwdata/BeltData.java rename to src/main/java/com/simibubi/create/content/kinetics/base/flwdata/BeltData.java index 935bc68b9..e00e96fe7 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/flwdata/BeltData.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/flwdata/BeltData.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.base.flwdata; +package com.simibubi.create.content.kinetics.base.flwdata; import org.joml.Quaternionf; diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/flwdata/BeltType.java b/src/main/java/com/simibubi/create/content/kinetics/base/flwdata/BeltType.java similarity index 93% rename from src/main/java/com/simibubi/create/content/contraptions/base/flwdata/BeltType.java rename to src/main/java/com/simibubi/create/content/kinetics/base/flwdata/BeltType.java index d881d28ee..6be331b8c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/flwdata/BeltType.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/flwdata/BeltType.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.base.flwdata; +package com.simibubi.create.content.kinetics.base.flwdata; import org.joml.Quaternionf; @@ -9,7 +9,7 @@ import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; import com.jozufozu.flywheel.core.layout.BufferLayout; import com.jozufozu.flywheel.core.model.ModelTransformer; import com.jozufozu.flywheel.util.RenderMath; -import com.simibubi.create.content.contraptions.KineticDebugger; +import com.simibubi.create.content.kinetics.KineticDebugger; import com.simibubi.create.foundation.render.AllInstanceFormats; import com.simibubi.create.foundation.render.AllProgramSpecs; import com.simibubi.create.foundation.utility.AnimationTickHolder; diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/flwdata/BeltWriterUnsafe.java b/src/main/java/com/simibubi/create/content/kinetics/base/flwdata/BeltWriterUnsafe.java similarity index 93% rename from src/main/java/com/simibubi/create/content/contraptions/base/flwdata/BeltWriterUnsafe.java rename to src/main/java/com/simibubi/create/content/kinetics/base/flwdata/BeltWriterUnsafe.java index 1cf570be5..002e25e3a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/flwdata/BeltWriterUnsafe.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/flwdata/BeltWriterUnsafe.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.base.flwdata; +package com.simibubi.create.content.kinetics.base.flwdata; import org.lwjgl.system.MemoryUtil; diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/flwdata/KineticData.java b/src/main/java/com/simibubi/create/content/kinetics/base/flwdata/KineticData.java similarity index 81% rename from src/main/java/com/simibubi/create/content/contraptions/base/flwdata/KineticData.java rename to src/main/java/com/simibubi/create/content/kinetics/base/flwdata/KineticData.java index 85c016538..d305fffd6 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/flwdata/KineticData.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/flwdata/KineticData.java @@ -1,9 +1,9 @@ -package com.simibubi.create.content.contraptions.base.flwdata; +package com.simibubi.create.content.kinetics.base.flwdata; import org.joml.Vector3f; import com.jozufozu.flywheel.core.materials.BasicData; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; import com.simibubi.create.foundation.utility.Color; import net.minecraft.core.BlockPos; @@ -39,9 +39,9 @@ public class KineticData extends BasicData { return this; } - public KineticData setColor(KineticTileEntity te) { - if (te.hasNetwork()) { - setColor(Color.generateFromLong(te.network)); + public KineticData setColor(KineticBlockEntity blockEntity) { + if (blockEntity.hasNetwork()) { + setColor(Color.generateFromLong(blockEntity.network)); }else { setColor(0xFF, 0xFF, 0xFF); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/flwdata/KineticWriterUnsafe.java b/src/main/java/com/simibubi/create/content/kinetics/base/flwdata/KineticWriterUnsafe.java similarity index 92% rename from src/main/java/com/simibubi/create/content/contraptions/base/flwdata/KineticWriterUnsafe.java rename to src/main/java/com/simibubi/create/content/kinetics/base/flwdata/KineticWriterUnsafe.java index d450b1d6a..3787e73d7 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/flwdata/KineticWriterUnsafe.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/flwdata/KineticWriterUnsafe.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.base.flwdata; +package com.simibubi.create.content.kinetics.base.flwdata; import org.lwjgl.system.MemoryUtil; diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/flwdata/RotatingData.java b/src/main/java/com/simibubi/create/content/kinetics/base/flwdata/RotatingData.java similarity index 92% rename from src/main/java/com/simibubi/create/content/contraptions/base/flwdata/RotatingData.java rename to src/main/java/com/simibubi/create/content/kinetics/base/flwdata/RotatingData.java index 99820725a..5d1db8070 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/flwdata/RotatingData.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/flwdata/RotatingData.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.base.flwdata; +package com.simibubi.create.content.kinetics.base.flwdata; import org.joml.Vector3f; diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/flwdata/RotatingType.java b/src/main/java/com/simibubi/create/content/kinetics/base/flwdata/RotatingType.java similarity index 92% rename from src/main/java/com/simibubi/create/content/contraptions/base/flwdata/RotatingType.java rename to src/main/java/com/simibubi/create/content/kinetics/base/flwdata/RotatingType.java index 43b71c8db..c0d444c2e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/flwdata/RotatingType.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/flwdata/RotatingType.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.base.flwdata; +package com.simibubi.create.content.kinetics.base.flwdata; import org.joml.Vector3f; @@ -10,7 +10,7 @@ import com.jozufozu.flywheel.core.layout.BufferLayout; import com.jozufozu.flywheel.core.model.ModelTransformer; import com.jozufozu.flywheel.util.RenderMath; import com.mojang.math.Axis; -import com.simibubi.create.content.contraptions.KineticDebugger; +import com.simibubi.create.content.kinetics.KineticDebugger; import com.simibubi.create.foundation.render.AllInstanceFormats; import com.simibubi.create.foundation.render.AllProgramSpecs; import com.simibubi.create.foundation.utility.AnimationTickHolder; diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/flwdata/RotatingWriterUnsafe.java b/src/main/java/com/simibubi/create/content/kinetics/base/flwdata/RotatingWriterUnsafe.java similarity index 91% rename from src/main/java/com/simibubi/create/content/contraptions/base/flwdata/RotatingWriterUnsafe.java rename to src/main/java/com/simibubi/create/content/kinetics/base/flwdata/RotatingWriterUnsafe.java index b57e21d2a..8b043be7a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/flwdata/RotatingWriterUnsafe.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/flwdata/RotatingWriterUnsafe.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.base.flwdata; +package com.simibubi.create.content.kinetics.base.flwdata; import org.lwjgl.system.MemoryUtil; diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/flwdata/package-info.java b/src/main/java/com/simibubi/create/content/kinetics/base/flwdata/package-info.java new file mode 100644 index 000000000..9e9a5554f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/base/flwdata/package-info.java @@ -0,0 +1,6 @@ +@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault +package com.simibubi.create.content.kinetics.base.flwdata; + +import javax.annotation.ParametersAreNonnullByDefault; + +import net.minecraft.MethodsReturnNonnullByDefault; diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltBlock.java b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltBlock.java similarity index 77% rename from src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltBlock.java rename to src/main/java/com/simibubi/create/content/kinetics/belt/BeltBlock.java index 19302dc73..92656133a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltBlock.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.relays.belt; +package com.simibubi.create.content.kinetics.belt; import java.util.ArrayList; import java.util.HashSet; @@ -9,27 +9,30 @@ import java.util.function.Consumer; import org.apache.commons.lang3.mutable.MutableBoolean; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; -import com.simibubi.create.AllTileEntities; import com.simibubi.create.Create; -import com.simibubi.create.content.contraptions.base.HorizontalKineticBlock; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.ITransformableBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform; -import com.simibubi.create.content.contraptions.processing.EmptyingByBasin; -import com.simibubi.create.content.contraptions.relays.belt.BeltSlicer.Feedback; -import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity.CasingType; -import com.simibubi.create.content.contraptions.relays.belt.transport.BeltMovementHandler.TransportedEntityInfo; -import com.simibubi.create.content.contraptions.relays.belt.transport.BeltTunnelInteractionHandler; -import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelBlock; -import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement; -import com.simibubi.create.content.schematics.ItemRequirement; -import com.simibubi.create.content.schematics.ItemRequirement.ItemUseType; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.content.contraptions.ITransformableBlock; +import com.simibubi.create.content.contraptions.StructureTransform; +import com.simibubi.create.content.equipment.armor.DivingBootsItem; +import com.simibubi.create.content.fluids.transfer.GenericItemEmptying; +import com.simibubi.create.content.kinetics.base.HorizontalKineticBlock; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.belt.BeltBlockEntity.CasingType; +import com.simibubi.create.content.kinetics.belt.BeltSlicer.Feedback; +import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour.TransportedResult; +import com.simibubi.create.content.kinetics.belt.transport.BeltMovementHandler.TransportedEntityInfo; +import com.simibubi.create.content.kinetics.belt.transport.BeltTunnelInteractionHandler; +import com.simibubi.create.content.logistics.funnel.FunnelBlock; +import com.simibubi.create.content.logistics.tunnel.BeltTunnelBlock; +import com.simibubi.create.content.schematics.requirement.ISpecialBlockItemRequirement; +import com.simibubi.create.content.schematics.requirement.ItemRequirement; +import com.simibubi.create.content.schematics.requirement.ItemRequirement.ItemUseType; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.block.ProperWaterloggedBlock; import com.simibubi.create.foundation.block.render.MultiPosDestructionHandler; import com.simibubi.create.foundation.block.render.ReducedDestroyEffects; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour.TransportedResult; import com.simibubi.create.foundation.utility.Iterate; import net.minecraft.client.multiplayer.ClientLevel; @@ -66,10 +69,12 @@ import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraft.world.level.block.state.properties.EnumProperty; import net.minecraft.world.level.block.state.properties.Property; import net.minecraft.world.level.levelgen.DebugLevelSource; +import net.minecraft.world.level.material.FluidState; import net.minecraft.world.level.material.Fluids; import net.minecraft.world.level.pathfinder.BlockPathTypes; import net.minecraft.world.level.pathfinder.PathComputationType; import net.minecraft.world.level.storage.loot.parameters.LootContextParams; +import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.shapes.CollisionContext; @@ -83,7 +88,8 @@ import net.minecraftforge.common.Tags; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; -public class BeltBlock extends HorizontalKineticBlock implements ITE, ISpecialBlockItemRequirement, ITransformableBlock { +public class BeltBlock extends HorizontalKineticBlock + implements IBE, ISpecialBlockItemRequirement, ITransformableBlock, ProperWaterloggedBlock { public static final Property SLOPE = EnumProperty.create("slope", BeltSlope.class); public static final Property PART = EnumProperty.create("part", BeltPart.class); @@ -93,7 +99,8 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE getDrops(BlockState state, net.minecraft.world.level.storage.loot.LootContext.Builder builder) { List drops = super.getDrops(state, builder); - BlockEntity tileEntity = builder.getOptionalParameter(LootContextParams.BLOCK_ENTITY); - if (tileEntity instanceof BeltTileEntity && ((BeltTileEntity) tileEntity).hasPulley()) + BlockEntity blockEntity = builder.getOptionalParameter(LootContextParams.BLOCK_ENTITY); + if (blockEntity instanceof BeltBlockEntity && ((BeltBlockEntity) blockEntity).hasPulley()) drops.addAll(AllBlocks.SHAFT.getDefaultState() .getDrops(builder)); return drops; @@ -144,9 +151,9 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE { + withBlockEntityDo(worldIn, pos, be -> { ItemEntity itemEntity = (ItemEntity) entityIn; - IItemHandler handler = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) + IItemHandler handler = be.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) .orElse(null); if (handler == null) return; @@ -215,7 +221,7 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE te.applyColor(DyeColor.getColor(heldItem))); - return InteractionResult.SUCCESS; - } + if (isDye || hasWater) + return onBlockEntityUse(world, pos, + be -> be.applyColor(DyeColor.getColor(heldItem)) ? InteractionResult.SUCCESS : InteractionResult.PASS); if (isConnector) return BeltSlicer.useConnector(state, world, pos, player, handIn, hit, new Feedback()); if (isWrench) return BeltSlicer.useWrench(state, world, pos, player, handIn, hit, new Feedback()); - BeltTileEntity belt = BeltHelper.getSegmentTE(world, pos); + BeltBlockEntity belt = BeltHelper.getSegmentBE(world, pos); if (belt == null) return InteractionResult.PASS; if (isHand) { - BeltTileEntity controllerBelt = belt.getControllerTE(); + BeltBlockEntity controllerBelt = belt.getControllerBE(); if (controllerBelt == null) return InteractionResult.PASS; if (world.isClientSide) @@ -293,21 +297,19 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE te.setCasingType(CasingType.BRASS)); + withBlockEntityDo(world, pos, be -> be.setCasingType(CasingType.BRASS)); + updateCoverProperty(world, pos, world.getBlockState(pos)); return InteractionResult.SUCCESS; } if (AllBlocks.ANDESITE_CASING.isIn(heldItem)) { - if (world.isClientSide) - return InteractionResult.SUCCESS; - withTileEntityDo(world, pos, te -> te.setCasingType(CasingType.ANDESITE)); + withBlockEntityDo(world, pos, be -> be.setCasingType(CasingType.ANDESITE)); + updateCoverProperty(world, pos, world.getBlockState(pos)); return InteractionResult.SUCCESS; } @@ -323,14 +325,14 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE te.setCasingType(CasingType.NONE)); + withBlockEntityDo(world, pos, be -> be.setCasingType(CasingType.NONE)); return InteractionResult.SUCCESS; } if (state.getValue(PART) == BeltPart.PULLEY) { if (world.isClientSide) return InteractionResult.SUCCESS; - KineticTileEntity.switchToBlockState(world, pos, state.setValue(PART, BeltPart.MIDDLE)); + KineticBlockEntity.switchToBlockState(world, pos, state.setValue(PART, BeltPart.MIDDLE)); if (player != null && !player.isCreative()) player.getInventory() .placeItemBackInInventory(AllBlocks.SHAFT.asStack()); @@ -342,7 +344,7 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE builder) { - builder.add(SLOPE, PART, CASING); + builder.add(SLOPE, PART, CASING, WATERLOGGED); super.createBlockStateDefinition(builder); } @@ -365,12 +367,12 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE { + return getBlockEntityOptional(worldIn, pos).map(be -> { Entity entity = ((EntityCollisionContext) context).getEntity(); if (entity == null) return shape; - BeltTileEntity controller = te.getControllerTE(); + BeltBlockEntity controller = be.getControllerBE(); if (controller == null) return shape; if (controller.passengers == null || !controller.passengers.containsKey(entity)) @@ -422,20 +424,20 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE bbe.setCovered(isBlockCoveringBelt(world, pos.above()))); + } + + public static boolean isBlockCoveringBelt(LevelAccessor world, BlockPos pos) { + BlockState blockState = world.getBlockState(pos); + VoxelShape collisionShape = blockState.getCollisionShape(world, pos); + if (collisionShape.isEmpty()) + return false; + AABB bounds = collisionShape.bounds(); + if (bounds.getXsize() < .5f || bounds.getZsize() < .5f) + return false; + if (bounds.minY > 0) + return false; + if (AllBlocks.CRUSHING_WHEEL_CONTROLLER.has(blockState)) + return false; + if (FunnelBlock.isFunnel(blockState) && FunnelBlock.getFunnelFacing(blockState) != Direction.UP) + return false; + if (blockState.getBlock() instanceof BeltTunnelBlock) + return false; + return true; + } + private void updateTunnelConnections(LevelAccessor world, BlockPos pos) { Block tunnelBlock = world.getBlockState(pos) .getBlock(); @@ -543,17 +575,17 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE getTileEntityClass() { - return BeltTileEntity.class; + public Class getBlockEntityClass() { + return BeltBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.BELT.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.BELT.get(); } @Override - public ItemRequirement getRequiredItems(BlockState state, BlockEntity te) { + public ItemRequirement getRequiredItems(BlockState state, BlockEntity be) { List required = new ArrayList<>(); if (state.getValue(PART) != BeltPart.MIDDLE) required.add(AllBlocks.SHAFT.asStack()); @@ -680,12 +712,17 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE getExtraPositions(ClientLevel level, BlockPos pos, BlockState blockState, int progress) { BlockEntity blockEntity = level.getBlockEntity(pos); - if (blockEntity instanceof BeltTileEntity belt) { + if (blockEntity instanceof BeltBlockEntity belt) { return new HashSet<>(BeltBlock.getBeltChain(level, belt.getController())); } return null; diff --git a/src/main/java/com/simibubi/create/content/kinetics/belt/BeltBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltBlockEntity.java new file mode 100644 index 000000000..5cea7e684 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltBlockEntity.java @@ -0,0 +1,678 @@ +package com.simibubi.create.content.kinetics.belt; + +import static com.simibubi.create.content.kinetics.belt.BeltPart.MIDDLE; +import static com.simibubi.create.content.kinetics.belt.BeltSlope.HORIZONTAL; +import static net.minecraft.core.Direction.AxisDirection.NEGATIVE; +import static net.minecraft.core.Direction.AxisDirection.POSITIVE; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; + +import com.jozufozu.flywheel.light.LightListener; +import com.jozufozu.flywheel.light.LightUpdater; +import com.jozufozu.flywheel.util.box.GridAlignedBB; +import com.jozufozu.flywheel.util.box.ImmutableBox; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.kinetics.base.IRotate; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.belt.behaviour.DirectBeltInputBehaviour; +import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour; +import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour.TransportedResult; +import com.simibubi.create.content.kinetics.belt.transport.BeltInventory; +import com.simibubi.create.content.kinetics.belt.transport.BeltMovementHandler; +import com.simibubi.create.content.kinetics.belt.transport.BeltMovementHandler.TransportedEntityInfo; +import com.simibubi.create.content.kinetics.belt.transport.BeltTunnelInteractionHandler; +import com.simibubi.create.content.kinetics.belt.transport.ItemHandlerBeltSegment; +import com.simibubi.create.content.kinetics.belt.transport.TransportedItemStack; +import com.simibubi.create.content.logistics.tunnel.BrassTunnelBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.NBTHelper; + +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.Vec3i; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.item.DyeColor; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.LightLayer; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.client.model.data.ModelData; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; + +public class BeltBlockEntity extends KineticBlockEntity { + + public Map passengers; + public Optional color; + public int beltLength; + public int index; + public Direction lastInsert; + public CasingType casing; + public boolean covered; + + protected BlockPos controller; + protected BeltInventory inventory; + protected LazyOptional itemHandler; + + public CompoundTag trackerUpdateTag; + + @OnlyIn(Dist.CLIENT) + public BeltLighter lighter; + + public static enum CasingType { + NONE, ANDESITE, BRASS; + } + + public BeltBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + controller = BlockPos.ZERO; + itemHandler = LazyOptional.empty(); + casing = CasingType.NONE; + color = Optional.empty(); + } + + @Override + public void addBehaviours(List behaviours) { + super.addBehaviours(behaviours); + behaviours.add(new DirectBeltInputBehaviour(this).onlyInsertWhen(this::canInsertFrom) + .setInsertionHandler(this::tryInsertingFromSide)); + behaviours.add(new TransportedItemStackHandlerBehaviour(this, this::applyToAllItems) + .withStackPlacement(this::getWorldPositionOf)); + } + + @Override + public void tick() { + // Init belt + if (beltLength == 0) + BeltBlock.initBelt(level, worldPosition); + + super.tick(); + + if (!AllBlocks.BELT.has(level.getBlockState(worldPosition))) + return; + + initializeItemHandler(); + + // Move Items + if (!isController()) + return; + + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { + if (beltLength > 0 && lighter == null) { + lighter = new BeltLighter(); + } + }); + invalidateRenderBoundingBox(); + + getInventory().tick(); + + if (getSpeed() == 0) + return; + + // Move Entities + if (passengers == null) + passengers = new HashMap<>(); + + List toRemove = new ArrayList<>(); + passengers.forEach((entity, info) -> { + boolean canBeTransported = BeltMovementHandler.canBeTransported(entity); + boolean leftTheBelt = + info.getTicksSinceLastCollision() > ((getBlockState().getValue(BeltBlock.SLOPE) != HORIZONTAL) ? 3 : 1); + if (!canBeTransported || leftTheBelt) { + toRemove.add(entity); + return; + } + + info.tick(); + BeltMovementHandler.transportEntity(this, entity, info); + }); + toRemove.forEach(passengers::remove); + } + + @Override + public float calculateStressApplied() { + if (!isController()) + return 0; + return super.calculateStressApplied(); + } + + @Override + public AABB createRenderBoundingBox() { + if (!isController()) + return super.createRenderBoundingBox(); + else + return super.createRenderBoundingBox().inflate(beltLength + 1); + } + + protected void initializeItemHandler() { + if (level.isClientSide || itemHandler.isPresent()) + return; + if (beltLength == 0 || controller == null) + return; + if (!level.isLoaded(controller)) + return; + BlockEntity be = level.getBlockEntity(controller); + if (be == null || !(be instanceof BeltBlockEntity)) + return; + BeltInventory inventory = ((BeltBlockEntity) be).getInventory(); + if (inventory == null) + return; + IItemHandler handler = new ItemHandlerBeltSegment(inventory, index); + itemHandler = LazyOptional.of(() -> handler); + } + + @Override + public LazyOptional getCapability(Capability cap, Direction side) { + if (!isRemoved() && !itemHandler.isPresent()) + initializeItemHandler(); + if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) { + if (side == Direction.UP || BeltBlock.canAccessFromSide(side, getBlockState())) { + return itemHandler.cast(); + } + } + return super.getCapability(cap, side); + } + + @Override + public void destroy() { + super.destroy(); + if (isController()) + getInventory().ejectAll(); + } + + @Override + public void invalidate() { + super.invalidate(); + itemHandler.invalidate(); + } + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + if (controller != null) + compound.put("Controller", NbtUtils.writeBlockPos(controller)); + compound.putBoolean("IsController", isController()); + compound.putInt("Length", beltLength); + compound.putInt("Index", index); + NBTHelper.writeEnum(compound, "Casing", casing); + compound.putBoolean("Covered", covered); + + if (color.isPresent()) + NBTHelper.writeEnum(compound, "Dye", color.get()); + + if (isController()) + compound.put("Inventory", getInventory().write()); + super.write(compound, clientPacket); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + int prevBeltLength = beltLength; + super.read(compound, clientPacket); + + if (compound.getBoolean("IsController")) + controller = worldPosition; + + color = compound.contains("Dye") ? Optional.of(NBTHelper.readEnum(compound, "Dye", DyeColor.class)) + : Optional.empty(); + + if (!wasMoved) { + if (!isController()) + controller = NbtUtils.readBlockPos(compound.getCompound("Controller")); + trackerUpdateTag = compound; + index = compound.getInt("Index"); + beltLength = compound.getInt("Length"); + if (prevBeltLength != beltLength) { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { + if (lighter != null) { + lighter.initializeLight(); + } + }); + } + } + + if (isController()) + getInventory().read(compound.getCompound("Inventory")); + + CasingType casingBefore = casing; + boolean coverBefore = covered; + casing = NBTHelper.readEnum(compound, "Casing", CasingType.class); + covered = compound.getBoolean("Covered"); + + if (!clientPacket) + return; + + if (casingBefore == casing && coverBefore == covered) + return; + if (!isVirtual()) + requestModelDataUpdate(); + if (hasLevel()) + level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 16); + } + + @Override + public void clearKineticInformation() { + super.clearKineticInformation(); + beltLength = 0; + index = 0; + controller = null; + trackerUpdateTag = new CompoundTag(); + } + + public boolean applyColor(DyeColor colorIn) { + if (colorIn == null) { + if (!color.isPresent()) + return false; + } else if (color.isPresent() && color.get() == colorIn) + return false; + if (level.isClientSide()) + return true; + + for (BlockPos blockPos : BeltBlock.getBeltChain(level, getController())) { + BeltBlockEntity belt = BeltHelper.getSegmentBE(level, blockPos); + if (belt == null) + continue; + belt.color = Optional.ofNullable(colorIn); + belt.setChanged(); + belt.sendData(); + } + + return true; + } + + public BeltBlockEntity getControllerBE() { + if (controller == null) + return null; + if (!level.isLoaded(controller)) + return null; + BlockEntity be = level.getBlockEntity(controller); + if (be == null || !(be instanceof BeltBlockEntity)) + return null; + return (BeltBlockEntity) be; + } + + public void setController(BlockPos controller) { + this.controller = controller; + } + + public BlockPos getController() { + return controller == null ? worldPosition : controller; + } + + public boolean isController() { + return controller != null && worldPosition.getX() == controller.getX() + && worldPosition.getY() == controller.getY() && worldPosition.getZ() == controller.getZ(); + } + + public float getBeltMovementSpeed() { + return getSpeed() / 480f; + } + + public float getDirectionAwareBeltMovementSpeed() { + int offset = getBeltFacing().getAxisDirection() + .getStep(); + if (getBeltFacing().getAxis() == Axis.X) + offset *= -1; + return getBeltMovementSpeed() * offset; + } + + public boolean hasPulley() { + if (!AllBlocks.BELT.has(getBlockState())) + return false; + return getBlockState().getValue(BeltBlock.PART) != MIDDLE; + } + + protected boolean isLastBelt() { + if (getSpeed() == 0) + return false; + + Direction direction = getBeltFacing(); + if (getBlockState().getValue(BeltBlock.SLOPE) == BeltSlope.VERTICAL) + return false; + + BeltPart part = getBlockState().getValue(BeltBlock.PART); + if (part == MIDDLE) + return false; + + boolean movingPositively = (getSpeed() > 0 == (direction.getAxisDirection() + .getStep() == 1)) ^ direction.getAxis() == Axis.X; + return part == BeltPart.START ^ movingPositively; + } + + public Vec3i getMovementDirection(boolean firstHalf) { + return this.getMovementDirection(firstHalf, false); + } + + public Vec3i getBeltChainDirection() { + return this.getMovementDirection(true, true); + } + + protected Vec3i getMovementDirection(boolean firstHalf, boolean ignoreHalves) { + if (getSpeed() == 0) + return BlockPos.ZERO; + + final BlockState blockState = getBlockState(); + final Direction beltFacing = blockState.getValue(BlockStateProperties.HORIZONTAL_FACING); + final BeltSlope slope = blockState.getValue(BeltBlock.SLOPE); + final BeltPart part = blockState.getValue(BeltBlock.PART); + final Axis axis = beltFacing.getAxis(); + + Direction movementFacing = Direction.get(axis == Axis.X ? NEGATIVE : POSITIVE, axis); + boolean notHorizontal = blockState.getValue(BeltBlock.SLOPE) != HORIZONTAL; + if (getSpeed() < 0) + movementFacing = movementFacing.getOpposite(); + Vec3i movement = movementFacing.getNormal(); + + boolean slopeBeforeHalf = (part == BeltPart.END) == (beltFacing.getAxisDirection() == POSITIVE); + boolean onSlope = notHorizontal && (part == MIDDLE || slopeBeforeHalf == firstHalf || ignoreHalves); + boolean movingUp = onSlope && slope == (movementFacing == beltFacing ? BeltSlope.UPWARD : BeltSlope.DOWNWARD); + + if (!onSlope) + return movement; + + return new Vec3i(movement.getX(), movingUp ? 1 : -1, movement.getZ()); + } + + public Direction getMovementFacing() { + Axis axis = getBeltFacing().getAxis(); + return Direction.fromAxisAndDirection(axis, getBeltMovementSpeed() < 0 ^ axis == Axis.X ? NEGATIVE : POSITIVE); + } + + protected Direction getBeltFacing() { + return getBlockState().getValue(BlockStateProperties.HORIZONTAL_FACING); + } + + public BeltInventory getInventory() { + if (!isController()) { + BeltBlockEntity controllerBE = getControllerBE(); + if (controllerBE != null) + return controllerBE.getInventory(); + return null; + } + if (inventory == null) { + inventory = new BeltInventory(this); + } + return inventory; + } + + private void applyToAllItems(float maxDistanceFromCenter, + Function processFunction) { + BeltBlockEntity controller = getControllerBE(); + if (controller == null) + return; + BeltInventory inventory = controller.getInventory(); + if (inventory != null) + inventory.applyToEachWithin(index + .5f, maxDistanceFromCenter, processFunction); + } + + private Vec3 getWorldPositionOf(TransportedItemStack transported) { + BeltBlockEntity controllerBE = getControllerBE(); + if (controllerBE == null) + return Vec3.ZERO; + return BeltHelper.getVectorForOffset(controllerBE, transported.beltPosition); + } + + public void setCasingType(CasingType type) { + if (casing == type) + return; + + BlockState blockState = getBlockState(); + boolean shouldBlockHaveCasing = type != CasingType.NONE; + + if (level.isClientSide) { + casing = type; + level.setBlock(worldPosition, blockState.setValue(BeltBlock.CASING, shouldBlockHaveCasing), 0); + requestModelDataUpdate(); + level.sendBlockUpdated(worldPosition, getBlockState(), getBlockState(), 16); + return; + } + + if (casing != CasingType.NONE) + level.levelEvent(2001, worldPosition, + Block.getId(casing == CasingType.ANDESITE ? AllBlocks.ANDESITE_CASING.getDefaultState() + : AllBlocks.BRASS_CASING.getDefaultState())); + if (blockState.getValue(BeltBlock.CASING) != shouldBlockHaveCasing) + KineticBlockEntity.switchToBlockState(level, worldPosition, + blockState.setValue(BeltBlock.CASING, shouldBlockHaveCasing)); + casing = type; + setChanged(); + sendData(); + } + + private boolean canInsertFrom(Direction side) { + if (getSpeed() == 0) + return false; + BlockState state = getBlockState(); + if (state.hasProperty(BeltBlock.SLOPE) && (state.getValue(BeltBlock.SLOPE) == BeltSlope.SIDEWAYS + || state.getValue(BeltBlock.SLOPE) == BeltSlope.VERTICAL)) + return false; + return getMovementFacing() != side.getOpposite(); + } + + private ItemStack tryInsertingFromSide(TransportedItemStack transportedStack, Direction side, boolean simulate) { + BeltBlockEntity nextBeltController = getControllerBE(); + ItemStack inserted = transportedStack.stack; + ItemStack empty = ItemStack.EMPTY; + + if (nextBeltController == null) + return inserted; + BeltInventory nextInventory = nextBeltController.getInventory(); + if (nextInventory == null) + return inserted; + + BlockEntity teAbove = level.getBlockEntity(worldPosition.above()); + if (teAbove instanceof BrassTunnelBlockEntity) { + BrassTunnelBlockEntity tunnelBE = (BrassTunnelBlockEntity) teAbove; + if (tunnelBE.hasDistributionBehaviour()) { + if (!tunnelBE.getStackToDistribute() + .isEmpty()) + return inserted; + if (!tunnelBE.testFlapFilter(side.getOpposite(), inserted)) + return inserted; + if (!simulate) { + BeltTunnelInteractionHandler.flapTunnel(nextInventory, index, side.getOpposite(), true); + tunnelBE.setStackToDistribute(inserted, side.getOpposite()); + } + return empty; + } + } + + if (getSpeed() == 0) + return inserted; + if (getMovementFacing() == side.getOpposite()) + return inserted; + if (!nextInventory.canInsertAtFromSide(index, side)) + return inserted; + if (simulate) + return empty; + + transportedStack = transportedStack.copy(); + transportedStack.beltPosition = index + .5f - Math.signum(getDirectionAwareBeltMovementSpeed()) / 16f; + + Direction movementFacing = getMovementFacing(); + if (!side.getAxis() + .isVertical()) { + if (movementFacing != side) { + transportedStack.sideOffset = side.getAxisDirection() + .getStep() * .35f; + if (side.getAxis() == Axis.X) + transportedStack.sideOffset *= -1; + } else + transportedStack.beltPosition = getDirectionAwareBeltMovementSpeed() > 0 ? index : index + 1; + } + + transportedStack.prevSideOffset = transportedStack.sideOffset; + transportedStack.insertedAt = index; + transportedStack.insertedFrom = side; + transportedStack.prevBeltPosition = transportedStack.beltPosition; + + BeltTunnelInteractionHandler.flapTunnel(nextInventory, index, side.getOpposite(), true); + + nextInventory.addItem(transportedStack); + nextBeltController.setChanged(); + nextBeltController.sendData(); + return empty; + } + + @Override + public ModelData getModelData() { + return ModelData.builder() + .with(BeltModel.CASING_PROPERTY, casing) + .with(BeltModel.COVER_PROPERTY, covered) + .build(); + } + + @Override + protected boolean canPropagateDiagonally(IRotate block, BlockState state) { + return state.hasProperty(BeltBlock.SLOPE) && (state.getValue(BeltBlock.SLOPE) == BeltSlope.UPWARD + || state.getValue(BeltBlock.SLOPE) == BeltSlope.DOWNWARD); + } + + @Override + public float propagateRotationTo(KineticBlockEntity target, BlockState stateFrom, BlockState stateTo, BlockPos diff, + boolean connectedViaAxes, boolean connectedViaCogs) { + if (target instanceof BeltBlockEntity && !connectedViaAxes) + return getController().equals(((BeltBlockEntity) target).getController()) ? 1 : 0; + return 0; + } + + public void invalidateItemHandler() { + itemHandler.invalidate(); + } + + public boolean shouldRenderNormally() { + if (level == null) + return isController(); + BlockState state = getBlockState(); + return state != null && state.hasProperty(BeltBlock.PART) && state.getValue(BeltBlock.PART) == BeltPart.START; + } + + /** + * Hide this behavior in an inner class to avoid loading LightListener on servers. + */ + @OnlyIn(Dist.CLIENT) + class BeltLighter implements LightListener { + private byte[] light; + + public BeltLighter() { + initializeLight(); + LightUpdater.get(level) + .addListener(this); + } + + /** + * Get the number of belt segments represented by the lighter. + * @return The number of segments. + */ + public int lightSegments() { + return light == null ? 0 : light.length / 2; + } + + /** + * Get the light value for a given segment. + * @param segment The segment to get the light value for. + * @return The light value. + */ + public int getPackedLight(int segment) { + return light == null ? 0 : LightTexture.pack(light[segment * 2], light[segment * 2 + 1]); + } + + @Override + public GridAlignedBB getVolume() { + BlockPos endPos = BeltHelper.getPositionForOffset(BeltBlockEntity.this, beltLength - 1); + GridAlignedBB bb = GridAlignedBB.from(worldPosition, endPos); + bb.fixMinMax(); + return bb; + } + + @Override + public boolean isListenerInvalid() { + return remove; + } + + @Override + public void onLightUpdate(LightLayer type, ImmutableBox changed) { + if (remove) + return; + if (level == null) + return; + + GridAlignedBB beltVolume = getVolume(); + + if (beltVolume.intersects(changed)) { + if (type == LightLayer.BLOCK) + updateBlockLight(); + + if (type == LightLayer.SKY) + updateSkyLight(); + } + } + + private void initializeLight() { + light = new byte[beltLength * 2]; + + Vec3i vec = getBeltFacing().getNormal(); + BeltSlope slope = getBlockState().getValue(BeltBlock.SLOPE); + int verticality = slope == BeltSlope.DOWNWARD ? -1 : slope == BeltSlope.UPWARD ? 1 : 0; + + MutableBlockPos pos = new MutableBlockPos(controller.getX(), controller.getY(), controller.getZ()); + for (int i = 0; i < beltLength * 2; i += 2) { + light[i] = (byte) level.getBrightness(LightLayer.BLOCK, pos); + light[i + 1] = (byte) level.getBrightness(LightLayer.SKY, pos); + pos.move(vec.getX(), verticality, vec.getZ()); + } + } + + private void updateBlockLight() { + Vec3i vec = getBeltFacing().getNormal(); + BeltSlope slope = getBlockState().getValue(BeltBlock.SLOPE); + int verticality = slope == BeltSlope.DOWNWARD ? -1 : slope == BeltSlope.UPWARD ? 1 : 0; + + MutableBlockPos pos = new MutableBlockPos(controller.getX(), controller.getY(), controller.getZ()); + for (int i = 0; i < beltLength * 2; i += 2) { + light[i] = (byte) level.getBrightness(LightLayer.BLOCK, pos); + + pos.move(vec.getX(), verticality, vec.getZ()); + } + } + + private void updateSkyLight() { + Vec3i vec = getBeltFacing().getNormal(); + BeltSlope slope = getBlockState().getValue(BeltBlock.SLOPE); + int verticality = slope == BeltSlope.DOWNWARD ? -1 : slope == BeltSlope.UPWARD ? 1 : 0; + + MutableBlockPos pos = new MutableBlockPos(controller.getX(), controller.getY(), controller.getZ()); + for (int i = 1; i < beltLength * 2; i += 2) { + light[i] = (byte) level.getBrightness(LightLayer.SKY, pos); + + pos.move(vec.getX(), verticality, vec.getZ()); + } + } + } + + public void setCovered(boolean blockCoveringBelt) { + if (blockCoveringBelt == covered) + return; + covered = blockCoveringBelt; + notifyUpdate(); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltGenerator.java b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltGenerator.java similarity index 97% rename from src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltGenerator.java rename to src/main/java/com/simibubi/create/content/kinetics/belt/BeltGenerator.java index d190e6e30..633c59bc4 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltGenerator.java +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltGenerator.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.relays.belt; +package com.simibubi.create.content.kinetics.belt; import com.simibubi.create.foundation.data.SpecialBlockStateGen; import com.tterrag.registrate.providers.DataGenContext; diff --git a/src/main/java/com/simibubi/create/content/kinetics/belt/BeltHelper.java b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltHelper.java new file mode 100644 index 000000000..07430e5e7 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltHelper.java @@ -0,0 +1,101 @@ +package com.simibubi.create.content.kinetics.belt; + +import com.simibubi.create.AllTags.AllItemTags; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Vec3i; +import net.minecraft.util.Mth; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; + +public class BeltHelper { + + public static boolean isItemUpright(ItemStack stack) { + return stack.getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY) + .isPresent() || AllItemTags.UPRIGHT_ON_BELT.matches(stack); + } + + public static BeltBlockEntity getSegmentBE(LevelAccessor world, BlockPos pos) { + if (world instanceof Level l && !l.isLoaded(pos)) + return null; + BlockEntity blockEntity = world.getBlockEntity(pos); + if (!(blockEntity instanceof BeltBlockEntity)) + return null; + return (BeltBlockEntity) blockEntity; + } + + public static BeltBlockEntity getControllerBE(LevelAccessor world, BlockPos pos) { + BeltBlockEntity segment = getSegmentBE(world, pos); + if (segment == null) + return null; + BlockPos controllerPos = segment.controller; + if (controllerPos == null) + return null; + return getSegmentBE(world, controllerPos); + } + + public static BeltBlockEntity getBeltForOffset(BeltBlockEntity controller, float offset) { + return getBeltAtSegment(controller, (int) Math.floor(offset)); + } + + public static BeltBlockEntity getBeltAtSegment(BeltBlockEntity controller, int segment) { + BlockPos pos = getPositionForOffset(controller, segment); + BlockEntity be = controller.getLevel() + .getBlockEntity(pos); + if (be == null || !(be instanceof BeltBlockEntity)) + return null; + return (BeltBlockEntity) be; + } + + public static BlockPos getPositionForOffset(BeltBlockEntity controller, int offset) { + BlockPos pos = controller.getBlockPos(); + Vec3i vec = controller.getBeltFacing() + .getNormal(); + BeltSlope slope = controller.getBlockState() + .getValue(BeltBlock.SLOPE); + int verticality = slope == BeltSlope.DOWNWARD ? -1 : slope == BeltSlope.UPWARD ? 1 : 0; + + return pos.offset(offset * vec.getX(), Mth.clamp(offset, 0, controller.beltLength - 1) * verticality, + offset * vec.getZ()); + } + + public static Vec3 getVectorForOffset(BeltBlockEntity controller, float offset) { + BeltSlope slope = controller.getBlockState() + .getValue(BeltBlock.SLOPE); + int verticality = slope == BeltSlope.DOWNWARD ? -1 : slope == BeltSlope.UPWARD ? 1 : 0; + float verticalMovement = verticality; + if (offset < .5) + verticalMovement = 0; + verticalMovement = verticalMovement * (Math.min(offset, controller.beltLength - .5f) - .5f); + Vec3 vec = VecHelper.getCenterOf(controller.getBlockPos()); + Vec3 horizontalMovement = Vec3.atLowerCornerOf(controller.getBeltFacing() + .getNormal()) + .scale(offset - .5f); + + if (slope == BeltSlope.VERTICAL) + horizontalMovement = Vec3.ZERO; + + vec = vec.add(horizontalMovement) + .add(0, verticalMovement, 0); + return vec; + } + + public static Vec3 getBeltVector(BlockState state) { + BeltSlope slope = state.getValue(BeltBlock.SLOPE); + int verticality = slope == BeltSlope.DOWNWARD ? -1 : slope == BeltSlope.UPWARD ? 1 : 0; + Vec3 horizontalMovement = Vec3.atLowerCornerOf(state.getValue(BeltBlock.HORIZONTAL_FACING) + .getNormal()); + if (slope == BeltSlope.VERTICAL) + return new Vec3(0, state.getValue(BeltBlock.HORIZONTAL_FACING) + .getAxisDirection() + .getStep(), 0); + return new Vec3(0, verticality, 0).add(horizontalMovement); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltInstance.java b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltInstance.java similarity index 89% rename from src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltInstance.java rename to src/main/java/com/simibubi/create/content/kinetics/belt/BeltInstance.java index a1be69da0..f241e25ba 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltInstance.java +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltInstance.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.relays.belt; +package com.simibubi.create.content.kinetics.belt; import java.util.ArrayList; import java.util.function.Supplier; @@ -11,11 +11,11 @@ import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.core.PartialModel; import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.base.KineticTileInstance; -import com.simibubi.create.content.contraptions.base.flwdata.BeltData; -import com.simibubi.create.content.contraptions.base.flwdata.RotatingData; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityInstance; +import com.simibubi.create.content.kinetics.base.flwdata.BeltData; +import com.simibubi.create.content.kinetics.base.flwdata.RotatingData; import com.simibubi.create.foundation.block.render.SpriteShiftEntry; import com.simibubi.create.foundation.render.AllMaterialSpecs; import com.simibubi.create.foundation.utility.Iterate; @@ -25,7 +25,7 @@ import net.minecraft.util.Mth; import net.minecraft.world.item.DyeColor; import net.minecraft.world.level.LightLayer; -public class BeltInstance extends KineticTileInstance { +public class BeltInstance extends KineticBlockEntityInstance { boolean upward; boolean diagonal; @@ -38,8 +38,8 @@ public class BeltInstance extends KineticTileInstance { protected ArrayList keys; protected RotatingData pulleyKey; - public BeltInstance(MaterialManager materialManager, BeltTileEntity tile) { - super(materialManager, tile); + public BeltInstance(MaterialManager materialManager, BeltBlockEntity blockEntity) { + super(materialManager, blockEntity); if (!AllBlocks.BELT.has(blockState)) return; @@ -58,7 +58,7 @@ public class BeltInstance extends KineticTileInstance { BeltPart part = blockState.getValue(BeltBlock.PART); boolean start = part == BeltPart.START; boolean end = part == BeltPart.END; - DyeColor color = tile.color.orElse(null); + DyeColor color = blockEntity.color.orElse(null); for (boolean bottom : Iterate.trueAndFalse) { PartialModel beltPartial = BeltRenderer.getBeltPartial(diagonal, start, end, bottom); @@ -73,7 +73,7 @@ public class BeltInstance extends KineticTileInstance { if (diagonal) break; } - if (tile.hasPulley()) { + if (blockEntity.hasPulley()) { Instancer pulleyModel = getPulleyModel(); pulleyKey = setup(pulleyModel.createInstance()); @@ -145,7 +145,7 @@ public class BeltInstance extends KineticTileInstance { return modelTransform; }; - return getRotatingMaterial().getModel(AllBlockPartials.BELT_PULLEY, blockState, dir, ms); + return getRotatingMaterial().getModel(AllPartialModels.BELT_PULLEY, blockState, dir, ms); } private Direction getOrientation() { diff --git a/src/main/java/com/simibubi/create/content/kinetics/belt/BeltModel.java b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltModel.java new file mode 100644 index 000000000..e80256677 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltModel.java @@ -0,0 +1,94 @@ +package com.simibubi.create.content.kinetics.belt; + +import java.util.ArrayList; +import java.util.List; + +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.AllSpriteShifts; +import com.simibubi.create.content.kinetics.belt.BeltBlockEntity.CasingType; +import com.simibubi.create.foundation.block.render.SpriteShiftEntry; +import com.simibubi.create.foundation.model.BakedQuadHelper; + +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.client.model.BakedModelWrapper; +import net.minecraftforge.client.model.data.ModelData; +import net.minecraftforge.client.model.data.ModelProperty; + +public class BeltModel extends BakedModelWrapper { + + public static final ModelProperty CASING_PROPERTY = new ModelProperty<>(); + public static final ModelProperty COVER_PROPERTY = new ModelProperty<>(); + + private static final SpriteShiftEntry SPRITE_SHIFT = AllSpriteShifts.ANDESIDE_BELT_CASING; + + public BeltModel(BakedModel template) { + super(template); + } + + @Override + public TextureAtlasSprite getParticleIcon(ModelData data) { + if (!data.has(CASING_PROPERTY)) + return super.getParticleIcon(data); + CasingType type = data.get(CASING_PROPERTY); + if (type == CasingType.NONE || type == CasingType.BRASS) + return super.getParticleIcon(data); + return AllSpriteShifts.ANDESITE_CASING.getOriginal(); + } + + @Override + public List getQuads(BlockState state, Direction side, RandomSource rand, ModelData extraData, RenderType renderType) { + List quads = super.getQuads(state, side, rand, extraData, renderType); + if (!extraData.has(CASING_PROPERTY)) + return quads; + + boolean cover = extraData.get(COVER_PROPERTY); + CasingType type = extraData.get(CASING_PROPERTY); + boolean brassCasing = type == CasingType.BRASS; + + if (type == CasingType.NONE || brassCasing && !cover) + return quads; + + quads = new ArrayList<>(quads); + + if (cover) { + boolean alongX = state.getValue(BeltBlock.HORIZONTAL_FACING) + .getAxis() == Axis.X; + BakedModel coverModel = + (brassCasing ? alongX ? AllPartialModels.BRASS_BELT_COVER_X : AllPartialModels.BRASS_BELT_COVER_Z + : alongX ? AllPartialModels.ANDESITE_BELT_COVER_X : AllPartialModels.ANDESITE_BELT_COVER_Z).get(); + quads.addAll(coverModel.getQuads(state, side, rand, extraData, renderType)); + } + + if (brassCasing) + return quads; + + for (int i = 0; i < quads.size(); i++) { + BakedQuad quad = quads.get(i); + TextureAtlasSprite original = quad.getSprite(); + if (original != SPRITE_SHIFT.getOriginal()) + continue; + + BakedQuad newQuad = BakedQuadHelper.clone(quad); + int[] vertexData = newQuad.getVertices(); + + for (int vertex = 0; vertex < 4; vertex++) { + float u = BakedQuadHelper.getU(vertexData, vertex); + float v = BakedQuadHelper.getV(vertexData, vertex); + BakedQuadHelper.setU(vertexData, vertex, SPRITE_SHIFT.getTargetU(u)); + BakedQuadHelper.setV(vertexData, vertex, SPRITE_SHIFT.getTargetV(v)); + } + + quads.set(i, newQuad); + } + + return quads; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltPart.java b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltPart.java similarity index 81% rename from src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltPart.java rename to src/main/java/com/simibubi/create/content/kinetics/belt/BeltPart.java index 852c07c97..537e4e2cd 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltPart.java +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltPart.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.relays.belt; +package com.simibubi.create.content.kinetics.belt; import com.simibubi.create.foundation.utility.Lang; diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltRenderer.java similarity index 79% rename from src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltRenderer.java rename to src/main/java/com/simibubi/create/content/kinetics/belt/BeltRenderer.java index 7dcec6495..baeb34e6d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltRenderer.java +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltRenderer.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.relays.belt; +package com.simibubi.create.content.kinetics.belt; import java.util.Random; import java.util.function.Supplier; @@ -9,16 +9,16 @@ import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import com.mojang.math.Axis; -import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPartialModels; import com.simibubi.create.AllSpriteShifts; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.content.kinetics.belt.transport.TransportedItemStack; import com.simibubi.create.foundation.block.render.SpriteShiftEntry; +import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; import com.simibubi.create.foundation.render.CachedBufferer; import com.simibubi.create.foundation.render.ShadowRenderHelper; import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.Iterate; @@ -39,23 +39,23 @@ import net.minecraft.world.item.DyeColor; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; -public class BeltRenderer extends SafeTileEntityRenderer { +public class BeltRenderer extends SafeBlockEntityRenderer { public BeltRenderer(BlockEntityRendererProvider.Context context) { } @Override - public boolean shouldRenderOffScreen(BeltTileEntity te) { - return te.isController(); + public boolean shouldRenderOffScreen(BeltBlockEntity be) { + return be.isController(); } @Override - protected void renderSafe(BeltTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, + protected void renderSafe(BeltBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light, int overlay) { - if (!Backend.canUseInstancing(te.getLevel())) { + if (!Backend.canUseInstancing(be.getLevel())) { - BlockState blockState = te.getBlockState(); + BlockState blockState = be.getBlockState(); if (!AllBlocks.BELT.has(blockState)) return; BeltSlope beltSlope = blockState.getValue(BeltBlock.SLOPE); @@ -74,7 +74,7 @@ public class BeltRenderer extends SafeTileEntityRenderer { PoseStack localTransforms = new PoseStack(); TransformStack msr = TransformStack.cast(localTransforms); VertexConsumer vb = buffer.getBuffer(RenderType.solid()); - float renderTick = AnimationTickHolder.getRenderTime(te.getLevel()); + float renderTick = AnimationTickHolder.getRenderTime(be.getLevel()); msr.centre() .rotateY(AngleHelper.horizontalAngle(facing) + (upward ? 180 : 0) + (sideways ? 270 : 0)) @@ -88,7 +88,7 @@ public class BeltRenderer extends SafeTileEntityRenderer { end = b; } - DyeColor color = te.color.orElse(null); + DyeColor color = be.color.orElse(null); for (boolean bottom : Iterate.trueAndFalse) { @@ -100,8 +100,8 @@ public class BeltRenderer extends SafeTileEntityRenderer { SpriteShiftEntry spriteShift = getSpriteShiftEntry(color, diagonal, bottom); // UV shift - float speed = te.getSpeed(); - if (speed != 0 || te.color.isPresent()) { + float speed = be.getSpeed(); + if (speed != 0 || be.color.isPresent()) { float time = renderTick * axisDirection.getStep(); if (diagonal && (downward ^ alongX) || !sideways && !diagonal && alongX || sideways && axisDirection == AxisDirection.NEGATIVE) speed = -speed; @@ -125,7 +125,7 @@ public class BeltRenderer extends SafeTileEntityRenderer { if (diagonal) break; } - if (te.hasPulley()) { + if (be.hasPulley()) { Direction dir = sideways ? Direction.UP : blockState.getValue(BeltBlock.HORIZONTAL_FACING).getClockWise(); Supplier matrixStackSupplier = () -> { @@ -139,12 +139,12 @@ public class BeltRenderer extends SafeTileEntityRenderer { return stack; }; - SuperByteBuffer superBuffer = CachedBufferer.partialDirectional(AllBlockPartials.BELT_PULLEY, blockState, dir, matrixStackSupplier); - KineticTileEntityRenderer.standardKineticRotationTransform(superBuffer, te, light).renderInto(ms, vb); + SuperByteBuffer superBuffer = CachedBufferer.partialDirectional(AllPartialModels.BELT_PULLEY, blockState, dir, matrixStackSupplier); + KineticBlockEntityRenderer.standardKineticRotationTransform(superBuffer, be, light).renderInto(ms, vb); } } - renderItems(te, partialTicks, ms, buffer, light, overlay); + renderItems(be, partialTicks, ms, buffer, light, overlay); } public static SpriteShiftEntry getSpriteShiftEntry(DyeColor color, boolean diagonal, boolean bottom) { @@ -158,44 +158,44 @@ public class BeltRenderer extends SafeTileEntityRenderer { public static PartialModel getBeltPartial(boolean diagonal, boolean start, boolean end, boolean bottom) { if (diagonal) { - if (start) return AllBlockPartials.BELT_DIAGONAL_START; - if (end) return AllBlockPartials.BELT_DIAGONAL_END; - return AllBlockPartials.BELT_DIAGONAL_MIDDLE; + if (start) return AllPartialModels.BELT_DIAGONAL_START; + if (end) return AllPartialModels.BELT_DIAGONAL_END; + return AllPartialModels.BELT_DIAGONAL_MIDDLE; } else if (bottom) { - if (start) return AllBlockPartials.BELT_START_BOTTOM; - if (end) return AllBlockPartials.BELT_END_BOTTOM; - return AllBlockPartials.BELT_MIDDLE_BOTTOM; + if (start) return AllPartialModels.BELT_START_BOTTOM; + if (end) return AllPartialModels.BELT_END_BOTTOM; + return AllPartialModels.BELT_MIDDLE_BOTTOM; } else { - if (start) return AllBlockPartials.BELT_START; - if (end) return AllBlockPartials.BELT_END; - return AllBlockPartials.BELT_MIDDLE; + if (start) return AllPartialModels.BELT_START; + if (end) return AllPartialModels.BELT_END; + return AllPartialModels.BELT_MIDDLE; } } - protected void renderItems(BeltTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, + protected void renderItems(BeltBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light, int overlay) { - if (!te.isController()) + if (!be.isController()) return; - if (te.beltLength == 0) + if (be.beltLength == 0) return; ms.pushPose(); - Direction beltFacing = te.getBeltFacing(); + Direction beltFacing = be.getBeltFacing(); Vec3i directionVec = beltFacing .getNormal(); Vec3 beltStartOffset = Vec3.atLowerCornerOf(directionVec).scale(-.5) .add(.5, 15 / 16f, .5); ms.translate(beltStartOffset.x, beltStartOffset.y, beltStartOffset.z); - BeltSlope slope = te.getBlockState() + BeltSlope slope = be.getBlockState() .getValue(BeltBlock.SLOPE); int verticality = slope == BeltSlope.DOWNWARD ? -1 : slope == BeltSlope.UPWARD ? 1 : 0; boolean slopeAlongX = beltFacing .getAxis() == Direction.Axis.X; - boolean onContraption = te.getLevel() instanceof WrappedWorld; + boolean onContraption = be.getLevel() instanceof WrappedWorld; - for (TransportedItemStack transported : te.getInventory() + for (TransportedItemStack transported : be.getInventory() .getTransportedItems()) { ms.pushPose(); TransformStack.cast(ms) @@ -205,7 +205,7 @@ public class BeltRenderer extends SafeTileEntityRenderer { float sideOffset; float verticalMovement; - if (te.getSpeed() == 0) { + if (be.getSpeed() == 0) { offset = transported.beltPosition; sideOffset = transported.sideOffset; } else { @@ -216,12 +216,12 @@ public class BeltRenderer extends SafeTileEntityRenderer { if (offset < .5) verticalMovement = 0; else - verticalMovement = verticality * (Math.min(offset, te.beltLength - .5f) - .5f); + verticalMovement = verticality * (Math.min(offset, be.beltLength - .5f) - .5f); Vec3 offsetVec = Vec3.atLowerCornerOf(directionVec).scale(offset); if (verticalMovement != 0) offsetVec = offsetVec.add(0, verticalMovement, 0); boolean onSlope = - slope != BeltSlope.HORIZONTAL && Mth.clamp(offset, .5f, te.beltLength - .5f) == offset; + slope != BeltSlope.HORIZONTAL && Mth.clamp(offset, .5f, be.beltLength - .5f) == offset; boolean tiltForward = (slope == BeltSlope.DOWNWARD ^ beltFacing .getAxisDirection() == AxisDirection.POSITIVE) == (beltFacing .getAxis() == Direction.Axis.Z); @@ -236,11 +236,11 @@ public class BeltRenderer extends SafeTileEntityRenderer { sideOffset *= -1; ms.translate(alongX ? sideOffset : 0, 0, alongX ? 0 : sideOffset); - int stackLight = onContraption ? light : getPackedLight(te, offset); + int stackLight = onContraption ? light : getPackedLight(be, offset); ItemRenderer itemRenderer = Minecraft.getInstance() .getItemRenderer(); boolean renderUpright = BeltHelper.isItemUpright(transported.stack); - boolean blockItem = itemRenderer.getModel(transported.stack, te.getLevel(), null, 0) + boolean blockItem = itemRenderer.getModel(transported.stack, be.getLevel(), null, 0) .isGui3d(); int count = (int) (Mth.log2((int) (transported.stack.getCount()))) / 2; Random r = new Random(transported.angle); @@ -266,7 +266,7 @@ public class BeltRenderer extends SafeTileEntityRenderer { Entity renderViewEntity = Minecraft.getInstance().cameraEntity; if (renderViewEntity != null) { Vec3 positionVec = renderViewEntity.position(); - Vec3 vectorForOffset = BeltHelper.getVectorForOffset(te, offset); + Vec3 vectorForOffset = BeltHelper.getVectorForOffset(be, offset); Vec3 diff = vectorForOffset.subtract(positionVec); float yRot = (float) (Mth.atan2(diff.x, diff.z) + Math.PI); ms.mulPose(Axis.YP.rotation(yRot)); @@ -288,7 +288,7 @@ public class BeltRenderer extends SafeTileEntityRenderer { } ms.scale(.5f, .5f, .5f); - itemRenderer.renderStatic(null, transported.stack, TransformType.FIXED, false, ms, buffer, te.getLevel(), stackLight, overlay, 0); + itemRenderer.renderStatic(null, transported.stack, TransformType.FIXED, false, ms, buffer, be.getLevel(), stackLight, overlay, 0); ms.popPose(); if (!renderUpright) { @@ -305,7 +305,7 @@ public class BeltRenderer extends SafeTileEntityRenderer { ms.popPose(); } - protected int getPackedLight(BeltTileEntity controller, float beltPos) { + protected int getPackedLight(BeltBlockEntity controller, float beltPos) { int segment = (int) Math.floor(beltPos); if (controller.lighter == null || segment >= controller.lighter.lightSegments() || segment < 0) return 0; diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltShapes.java b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltShapes.java similarity index 99% rename from src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltShapes.java rename to src/main/java/com/simibubi/create/content/kinetics/belt/BeltShapes.java index 2cd553b0d..c3129ee19 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltShapes.java +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltShapes.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.relays.belt; +package com.simibubi.create.content.kinetics.belt; import static net.minecraft.world.level.block.Block.box; diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltSlicer.java b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltSlicer.java similarity index 80% rename from src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltSlicer.java rename to src/main/java/com/simibubi/create/content/kinetics/belt/BeltSlicer.java index 443cacf40..f2f59e6a7 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltSlicer.java +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltSlicer.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.relays.belt; +package com.simibubi.create.content.kinetics.belt; import java.util.ArrayList; import java.util.Iterator; @@ -8,11 +8,12 @@ import java.util.Optional; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; import com.simibubi.create.CreateClient; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity.CasingType; -import com.simibubi.create.content.contraptions.relays.belt.item.BeltConnectorItem; -import com.simibubi.create.content.contraptions.relays.belt.transport.BeltInventory; -import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.belt.BeltBlockEntity.CasingType; +import com.simibubi.create.content.kinetics.belt.item.BeltConnectorItem; +import com.simibubi.create.content.kinetics.belt.transport.BeltInventory; +import com.simibubi.create.content.kinetics.belt.transport.TransportedItemStack; +import com.simibubi.create.foundation.block.ProperWaterloggedBlock; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.VecHelper; @@ -53,8 +54,8 @@ public class BeltSlicer { public static InteractionResult useWrench(BlockState state, Level world, BlockPos pos, Player player, InteractionHand handIn, BlockHitResult hit, Feedback feedBack) { - BeltTileEntity controllerTE = BeltHelper.getControllerTE(world, pos); - if (controllerTE == null) + BeltBlockEntity controllerBE = BeltHelper.getControllerBE(world, pos); + if (controllerBE == null) return InteractionResult.PASS; if (state.getValue(BeltBlock.CASING) && hit.getDirection() != Direction.UP) return InteractionResult.PASS; @@ -62,13 +63,13 @@ public class BeltSlicer { .getAxis() != Axis.Y) return InteractionResult.PASS; - int beltLength = controllerTE.beltLength; + int beltLength = controllerBE.beltLength; if (beltLength == 2) return InteractionResult.FAIL; BlockPos beltVector = new BlockPos(BeltHelper.getBeltVector(state)); BeltPart part = state.getValue(BeltBlock.PART); - List beltChain = BeltBlock.getBeltChain(world, controllerTE.getBlockPos()); + List beltChain = BeltBlock.getBeltChain(world, controllerBE.getBlockPos()); boolean creative = player.isCreative(); // Shorten from End @@ -77,7 +78,7 @@ public class BeltSlicer { return InteractionResult.SUCCESS; for (BlockPos blockPos : beltChain) { - BeltTileEntity belt = BeltHelper.getSegmentTE(world, blockPos); + BeltBlockEntity belt = BeltHelper.getSegmentBE(world, blockPos); if (belt == null) continue; belt.detachKinetics(); @@ -85,13 +86,14 @@ public class BeltSlicer { belt.beltLength = 0; } - BeltInventory inventory = controllerTE.inventory; + BeltInventory inventory = controllerBE.inventory; BlockPos next = part == BeltPart.END ? pos.subtract(beltVector) : pos.offset(beltVector); BlockState replacedState = world.getBlockState(next); - BeltTileEntity segmentTE = BeltHelper.getSegmentTE(world, next); - KineticTileEntity.switchToBlockState(world, next, - state.setValue(BeltBlock.CASING, segmentTE != null && segmentTE.casing != CasingType.NONE)); - world.setBlock(pos, Blocks.AIR.defaultBlockState(), Block.UPDATE_ALL | Block.UPDATE_MOVE_BY_PISTON); + BeltBlockEntity segmentBE = BeltHelper.getSegmentBE(world, next); + KineticBlockEntity.switchToBlockState(world, next, ProperWaterloggedBlock.withWater(world, + state.setValue(BeltBlock.CASING, segmentBE != null && segmentBE.casing != CasingType.NONE), next)); + world.setBlock(pos, ProperWaterloggedBlock.withWater(world, Blocks.AIR.defaultBlockState(), pos), + Block.UPDATE_ALL | Block.UPDATE_MOVE_BY_PISTON); world.removeBlockEntity(pos); world.levelEvent(2001, pos, Block.getId(state)); @@ -110,10 +112,10 @@ public class BeltSlicer { } // Transfer items to new controller - if (part == BeltPart.START && segmentTE != null && inventory != null) { - controllerTE.inventory = null; - segmentTE.inventory = null; - segmentTE.setController(next); + if (part == BeltPart.START && segmentBE != null && inventory != null) { + controllerBE.inventory = null; + segmentBE.inventory = null; + segmentBE.setController(next); for (TransportedItemStack transportedItemStack : inventory.getTransportedItems()) { transportedItemStack.beltPosition -= 1; if (transportedItemStack.beltPosition <= 0) { @@ -124,7 +126,7 @@ public class BeltSlicer { entity.hurtMarked = true; world.addFreshEntity(entity); } else - segmentTE.getInventory() + segmentBE.getInventory() .addItem(transportedItemStack); } } @@ -132,12 +134,12 @@ public class BeltSlicer { return InteractionResult.SUCCESS; } - BeltTileEntity segmentTE = BeltHelper.getSegmentTE(world, pos); - if (segmentTE == null) + BeltBlockEntity segmentBE = BeltHelper.getSegmentBE(world, pos); + if (segmentBE == null) return InteractionResult.PASS; // Split in half - int hitSegment = segmentTE.index; + int hitSegment = segmentBE.index; Vec3 centerOf = VecHelper.getCenterOf(hit.getBlockPos()); Vec3 subtract = hit.getLocation() .subtract(centerOf); @@ -146,13 +148,13 @@ public class BeltSlicer { if (hitSegment == 0 || hitSegment == 1 && !towardPositive) return InteractionResult.FAIL; - if (hitSegment == controllerTE.beltLength - 1 || hitSegment == controllerTE.beltLength - 2 && towardPositive) + if (hitSegment == controllerBE.beltLength - 1 || hitSegment == controllerBE.beltLength - 2 && towardPositive) return InteractionResult.FAIL; // Look for shafts if (!creative) { int requiredShafts = 0; - if (!segmentTE.hasPulley()) + if (!segmentBE.hasPulley()) requiredShafts++; BlockState other = world.getBlockState(next); if (AllBlocks.BELT.has(other) && other.getValue(BeltBlock.PART) == BeltPart.MIDDLE) @@ -196,7 +198,7 @@ public class BeltSlicer { if (!world.isClientSide) { for (BlockPos blockPos : beltChain) { - BeltTileEntity belt = BeltHelper.getSegmentTE(world, blockPos); + BeltBlockEntity belt = BeltHelper.getSegmentBE(world, blockPos); if (belt == null) continue; belt.detachKinetics(); @@ -204,16 +206,16 @@ public class BeltSlicer { belt.beltLength = 0; } - BeltInventory inventory = controllerTE.inventory; - KineticTileEntity.switchToBlockState(world, pos, + BeltInventory inventory = controllerBE.inventory; + KineticBlockEntity.switchToBlockState(world, pos, state.setValue(BeltBlock.PART, towardPositive ? BeltPart.END : BeltPart.START)); - KineticTileEntity.switchToBlockState(world, next, world.getBlockState(next) + KineticBlockEntity.switchToBlockState(world, next, world.getBlockState(next) .setValue(BeltBlock.PART, towardPositive ? BeltPart.START : BeltPart.END)); world.playSound(null, pos, SoundEvents.WOOL_HIT, player == null ? SoundSource.BLOCKS : SoundSource.PLAYERS, 0.5F, 2.3F); // Transfer items to new controller - BeltTileEntity newController = towardPositive ? BeltHelper.getSegmentTE(world, next) : segmentTE; + BeltBlockEntity newController = towardPositive ? BeltHelper.getSegmentBE(world, next) : segmentBE; if (newController != null && inventory != null) { newController.inventory = null; newController.setController(newController.getBlockPos()); @@ -236,25 +238,25 @@ public class BeltSlicer { public static InteractionResult useConnector(BlockState state, Level world, BlockPos pos, Player player, InteractionHand handIn, BlockHitResult hit, Feedback feedBack) { - BeltTileEntity controllerTE = BeltHelper.getControllerTE(world, pos); - if (controllerTE == null) + BeltBlockEntity controllerBE = BeltHelper.getControllerBE(world, pos); + if (controllerBE == null) return InteractionResult.PASS; - int beltLength = controllerTE.beltLength; + int beltLength = controllerBE.beltLength; if (beltLength == BeltConnectorItem.maxLength()) return InteractionResult.FAIL; BlockPos beltVector = new BlockPos(BeltHelper.getBeltVector(state)); BeltPart part = state.getValue(BeltBlock.PART); Direction facing = state.getValue(BeltBlock.HORIZONTAL_FACING); - List beltChain = BeltBlock.getBeltChain(world, controllerTE.getBlockPos()); + List beltChain = BeltBlock.getBeltChain(world, controllerBE.getBlockPos()); boolean creative = player.isCreative(); if (!hoveringEnd(state, hit)) return InteractionResult.PASS; BlockPos next = part == BeltPart.START ? pos.subtract(beltVector) : pos.offset(beltVector); - BeltTileEntity mergedController = null; + BeltBlockEntity mergedController = null; int mergedBeltLength = 0; // Merge Belts / Extend at End @@ -266,7 +268,7 @@ public class BeltSlicer { if (!beltStatesCompatible(state, nextState)) return InteractionResult.FAIL; - mergedController = BeltHelper.getControllerTE(world, next); + mergedController = BeltHelper.getControllerBE(world, next); if (mergedController == null) return InteractionResult.FAIL; if (mergedController.beltLength + beltLength > BeltConnectorItem.maxLength()) @@ -276,9 +278,9 @@ public class BeltSlicer { if (!world.isClientSide) { boolean flipBelt = facing != nextState.getValue(BeltBlock.HORIZONTAL_FACING); - Optional color = controllerTE.color; + Optional color = controllerBE.color; for (BlockPos blockPos : BeltBlock.getBeltChain(world, mergedController.getBlockPos())) { - BeltTileEntity belt = BeltHelper.getSegmentTE(world, blockPos); + BeltBlockEntity belt = BeltHelper.getSegmentBE(world, blockPos); if (belt == null) continue; belt.detachKinetics(); @@ -303,7 +305,7 @@ public class BeltSlicer { if (!world.isClientSide) { for (BlockPos blockPos : beltChain) { - BeltTileEntity belt = BeltHelper.getSegmentTE(world, blockPos); + BeltBlockEntity belt = BeltHelper.getSegmentBE(world, blockPos); if (belt == null) continue; belt.detachKinetics(); @@ -311,24 +313,26 @@ public class BeltSlicer { belt.beltLength = 0; } - BeltInventory inventory = controllerTE.inventory; - KineticTileEntity.switchToBlockState(world, pos, state.setValue(BeltBlock.PART, BeltPart.MIDDLE)); + BeltInventory inventory = controllerBE.inventory; + KineticBlockEntity.switchToBlockState(world, pos, state.setValue(BeltBlock.PART, BeltPart.MIDDLE)); if (mergedController == null) { // Attach at end - world.setBlock(next, state.setValue(BeltBlock.CASING, false), Block.UPDATE_ALL | Block.UPDATE_MOVE_BY_PISTON); - BeltTileEntity segmentTE = BeltHelper.getSegmentTE(world, next); - if (segmentTE != null) - segmentTE.color = controllerTE.color; + world.setBlock(next, + ProperWaterloggedBlock.withWater(world, state.setValue(BeltBlock.CASING, false), next), + Block.UPDATE_ALL | Block.UPDATE_MOVE_BY_PISTON); + BeltBlockEntity segmentBE = BeltHelper.getSegmentBE(world, next); + if (segmentBE != null) + segmentBE.color = controllerBE.color; world.playSound(null, pos, SoundEvents.WOOL_PLACE, player == null ? SoundSource.BLOCKS : SoundSource.PLAYERS, 0.5F, 1F); // Transfer items to new controller - if (part == BeltPart.START && segmentTE != null && inventory != null) { - segmentTE.setController(next); + if (part == BeltPart.START && segmentBE != null && inventory != null) { + segmentBE.setController(next); for (TransportedItemStack transportedItemStack : inventory.getTransportedItems()) { transportedItemStack.beltPosition += 1; - segmentTE.getInventory() + segmentBE.getInventory() .addItem(transportedItemStack); } } @@ -338,9 +342,9 @@ public class BeltSlicer { BeltInventory mergedInventory = mergedController.inventory; world.playSound(null, pos, SoundEvents.WOOL_HIT, player == null ? SoundSource.BLOCKS : SoundSource.PLAYERS, 0.5F, 1.3F); - BeltTileEntity segmentTE = BeltHelper.getSegmentTE(world, next); - KineticTileEntity.switchToBlockState(world, next, - state.setValue(BeltBlock.CASING, segmentTE != null && segmentTE.casing != CasingType.NONE) + BeltBlockEntity segmentBE = BeltHelper.getSegmentBE(world, next); + KineticBlockEntity.switchToBlockState(world, next, + state.setValue(BeltBlock.CASING, segmentBE != null && segmentBE.casing != CasingType.NONE) .setValue(BeltBlock.PART, BeltPart.MIDDLE)); if (!creative) { @@ -349,7 +353,7 @@ public class BeltSlicer { } // Transfer items to other controller - BlockPos search = controllerTE.getBlockPos(); + BlockPos search = controllerBE.getBlockPos(); for (int i = 0; i < 10000; i++) { BlockState blockState = world.getBlockState(search); if (!AllBlocks.BELT.has(blockState)) @@ -359,11 +363,11 @@ public class BeltSlicer { continue; } - BeltTileEntity newController = BeltHelper.getSegmentTE(world, search); + BeltBlockEntity newController = BeltHelper.getSegmentBE(world, search); - if (newController != controllerTE && inventory != null) { + if (newController != controllerBE && inventory != null) { newController.setController(search); - controllerTE.inventory = null; + controllerBE.inventory = null; for (TransportedItemStack transportedItemStack : inventory.getTransportedItems()) { transportedItemStack.beltPosition += mergedBeltLength; newController.getInventory() @@ -375,7 +379,7 @@ public class BeltSlicer { newController.setController(search); mergedController.inventory = null; for (TransportedItemStack transportedItemStack : mergedInventory.getTransportedItems()) { - if (newController == controllerTE) + if (newController == controllerBE) transportedItemStack.beltPosition += beltLength; newController.getInventory() .addItem(transportedItemStack); diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltSlope.java b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltSlope.java similarity index 85% rename from src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltSlope.java rename to src/main/java/com/simibubi/create/content/kinetics/belt/BeltSlope.java index 0001fb187..5e1f38908 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltSlope.java +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/BeltSlope.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.relays.belt; +package com.simibubi.create.content.kinetics.belt; import com.simibubi.create.foundation.utility.Lang; diff --git a/src/main/java/com/simibubi/create/content/kinetics/belt/behaviour/BeltProcessingBehaviour.java b/src/main/java/com/simibubi/create/content/kinetics/belt/behaviour/BeltProcessingBehaviour.java new file mode 100644 index 000000000..adfb35e39 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/behaviour/BeltProcessingBehaviour.java @@ -0,0 +1,72 @@ +package com.simibubi.create.content.kinetics.belt.behaviour; + +import com.simibubi.create.content.kinetics.belt.transport.TransportedItemStack; +import com.simibubi.create.content.logistics.funnel.AbstractFunnelBlock; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.block.state.BlockState; + +/** + * Behaviour for BlockEntities which can process items on belts or depots beneath + * them. Currently only supports placement location 2 spaces above the belt + * block. Example use: Mechanical Press + */ +public class BeltProcessingBehaviour extends BlockEntityBehaviour { + + public static final BehaviourType TYPE = new BehaviourType<>(); + + public static enum ProcessingResult { + PASS, HOLD, REMOVE; + } + + private ProcessingCallback onItemEnter; + private ProcessingCallback continueProcessing; + + public BeltProcessingBehaviour(SmartBlockEntity be) { + super(be); + onItemEnter = (s, i) -> ProcessingResult.PASS; + continueProcessing = (s, i) -> ProcessingResult.PASS; + } + + public BeltProcessingBehaviour whenItemEnters(ProcessingCallback callback) { + onItemEnter = callback; + return this; + } + + public BeltProcessingBehaviour whileItemHeld(ProcessingCallback callback) { + continueProcessing = callback; + return this; + } + + public static boolean isBlocked(BlockGetter world, BlockPos processingSpace) { + BlockState blockState = world.getBlockState(processingSpace.above()); + if (AbstractFunnelBlock.isFunnel(blockState)) + return false; + return !blockState.getCollisionShape(world, processingSpace.above()) + .isEmpty(); + } + + @Override + public BehaviourType getType() { + return TYPE; + } + + public ProcessingResult handleReceivedItem(TransportedItemStack stack, + TransportedItemStackHandlerBehaviour inventory) { + return onItemEnter.apply(stack, inventory); + } + + public ProcessingResult handleHeldItem(TransportedItemStack stack, TransportedItemStackHandlerBehaviour inventory) { + return continueProcessing.apply(stack, inventory); + } + + @FunctionalInterface + public interface ProcessingCallback { + public ProcessingResult apply(TransportedItemStack stack, TransportedItemStackHandlerBehaviour inventory); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/belt/behaviour/DirectBeltInputBehaviour.java b/src/main/java/com/simibubi/create/content/kinetics/belt/behaviour/DirectBeltInputBehaviour.java new file mode 100644 index 000000000..f48f69cf0 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/behaviour/DirectBeltInputBehaviour.java @@ -0,0 +1,128 @@ +package com.simibubi.create.content.kinetics.belt.behaviour; + +import java.util.function.Supplier; + +import javax.annotation.Nullable; + +import com.simibubi.create.content.kinetics.belt.transport.TransportedItemStack; +import com.simibubi.create.content.logistics.funnel.BeltFunnelBlock; +import com.simibubi.create.content.logistics.funnel.BeltFunnelBlock.Shape; +import com.simibubi.create.content.logistics.funnel.FunnelBlock; +import com.simibubi.create.content.logistics.funnel.FunnelBlockEntity; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; + +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 net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemHandlerHelper; + +/** + * Behaviour for BlockEntities to which belts can transfer items directly in a + * backup-friendly manner. Example uses: Basin, Saw, Depot + */ +public class DirectBeltInputBehaviour extends BlockEntityBehaviour { + + public static final BehaviourType TYPE = new BehaviourType<>(); + + private InsertionCallback tryInsert; + private AvailabilityPredicate canInsert; + private Supplier supportsBeltFunnels; + + public DirectBeltInputBehaviour(SmartBlockEntity be) { + super(be); + tryInsert = this::defaultInsertionCallback; + canInsert = d -> true; + supportsBeltFunnels = () -> false; + } + + public DirectBeltInputBehaviour allowingBeltFunnelsWhen(Supplier pred) { + supportsBeltFunnels = pred; + return this; + } + + public DirectBeltInputBehaviour allowingBeltFunnels() { + supportsBeltFunnels = () -> true; + return this; + } + + public DirectBeltInputBehaviour onlyInsertWhen(AvailabilityPredicate pred) { + canInsert = pred; + return this; + } + + public DirectBeltInputBehaviour setInsertionHandler(InsertionCallback callback) { + tryInsert = callback; + return this; + } + + private ItemStack defaultInsertionCallback(TransportedItemStack inserted, Direction side, boolean simulate) { + LazyOptional lazy = blockEntity.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side); + if (!lazy.isPresent()) + return inserted.stack; + return ItemHandlerHelper.insertItemStacked(lazy.orElse(null), inserted.stack.copy(), simulate); + } + + // TODO: verify that this side is consistent across all calls + public boolean canInsertFromSide(Direction side) { + return canInsert.test(side); + } + + public ItemStack handleInsertion(ItemStack stack, Direction side, boolean simulate) { + return handleInsertion(new TransportedItemStack(stack), side, simulate); + } + + public ItemStack handleInsertion(TransportedItemStack stack, Direction side, boolean simulate) { + return tryInsert.apply(stack, side, simulate); + } + + @Override + public BehaviourType getType() { + return TYPE; + } + + @FunctionalInterface + public interface InsertionCallback { + public ItemStack apply(TransportedItemStack stack, Direction side, boolean simulate); + } + + @FunctionalInterface + public interface AvailabilityPredicate { + public boolean test(Direction side); + } + + @Nullable + public ItemStack tryExportingToBeltFunnel(ItemStack stack, @Nullable Direction side, boolean simulate) { + BlockPos funnelPos = blockEntity.getBlockPos() + .above(); + Level world = getWorld(); + BlockState funnelState = world.getBlockState(funnelPos); + if (!(funnelState.getBlock() instanceof BeltFunnelBlock)) + return null; + if (funnelState.getValue(BeltFunnelBlock.SHAPE) != Shape.PULLING) + return null; + if (side != null && FunnelBlock.getFunnelFacing(funnelState) != side) + return null; + BlockEntity be = world.getBlockEntity(funnelPos); + if (!(be instanceof FunnelBlockEntity)) + return null; + if (funnelState.getValue(BeltFunnelBlock.POWERED)) + return stack; + ItemStack insert = FunnelBlock.tryInsert(world, funnelPos, stack, simulate); + if (insert.getCount() != stack.getCount() && !simulate) + ((FunnelBlockEntity) be).flap(true); + return insert; + } + + public boolean canSupportBeltFunnels() { + return supportsBeltFunnels.get(); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/belt/TransportedItemStackHandlerBehaviour.java b/src/main/java/com/simibubi/create/content/kinetics/belt/behaviour/TransportedItemStackHandlerBehaviour.java similarity index 85% rename from src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/belt/TransportedItemStackHandlerBehaviour.java rename to src/main/java/com/simibubi/create/content/kinetics/belt/behaviour/TransportedItemStackHandlerBehaviour.java index 869e52ad0..a492180a9 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/belt/TransportedItemStackHandlerBehaviour.java +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/behaviour/TransportedItemStackHandlerBehaviour.java @@ -1,4 +1,4 @@ -package com.simibubi.create.foundation.tileEntity.behaviour.belt; +package com.simibubi.create.content.kinetics.belt.behaviour; import java.util.List; import java.util.function.Function; @@ -6,16 +6,16 @@ import java.util.function.Function; import javax.annotation.Nullable; import com.google.common.collect.ImmutableList; -import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType; +import com.simibubi.create.content.kinetics.belt.transport.TransportedItemStack; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.world.item.ItemStack; import net.minecraft.world.phys.Vec3; -public class TransportedItemStackHandlerBehaviour extends TileEntityBehaviour { +public class TransportedItemStackHandlerBehaviour extends BlockEntityBehaviour { public static final BehaviourType TYPE = new BehaviourType<>(); @@ -84,10 +84,10 @@ public class TransportedItemStackHandlerBehaviour extends TileEntityBehaviour { } - public TransportedItemStackHandlerBehaviour(SmartTileEntity te, ProcessingCallback processingCallback) { - super(te); + public TransportedItemStackHandlerBehaviour(SmartBlockEntity be, ProcessingCallback processingCallback) { + super(be); this.processingCallback = processingCallback; - positionGetter = t -> VecHelper.getCenterOf(te.getBlockPos()); + positionGetter = t -> VecHelper.getCenterOf(be.getBlockPos()); } public TransportedItemStackHandlerBehaviour withStackPlacement(PositionGetter function) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/item/BeltConnectorHandler.java b/src/main/java/com/simibubi/create/content/kinetics/belt/item/BeltConnectorHandler.java similarity index 93% rename from src/main/java/com/simibubi/create/content/contraptions/relays/belt/item/BeltConnectorHandler.java rename to src/main/java/com/simibubi/create/content/kinetics/belt/item/BeltConnectorHandler.java index 55f58f677..29e88f305 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/item/BeltConnectorHandler.java +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/item/BeltConnectorHandler.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.relays.belt.item; +package com.simibubi.create.content.kinetics.belt.item; import java.util.LinkedList; import java.util.List; @@ -7,8 +7,8 @@ import java.util.Random; import org.joml.Vector3f; import com.simibubi.create.AllItems; -import com.simibubi.create.content.contraptions.relays.elementary.ShaftBlock; -import com.simibubi.create.foundation.config.AllConfigs; +import com.simibubi.create.content.kinetics.simpleRelays.ShaftBlock; +import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.client.Minecraft; import net.minecraft.core.BlockPos; @@ -76,7 +76,7 @@ public class BeltConnectorHandler { return; if (!ShaftBlock.isShaft(world.getBlockState(selected))) selected = selected.relative(((BlockHitResult) rayTrace).getDirection()); - if (!selected.closerThan(first, AllConfigs.SERVER.kinetics.maxBeltLength.get())) + if (!selected.closerThan(first, AllConfigs.server().kinetics.maxBeltLength.get())) return; boolean canConnect = diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/item/BeltConnectorItem.java b/src/main/java/com/simibubi/create/content/kinetics/belt/item/BeltConnectorItem.java similarity index 86% rename from src/main/java/com/simibubi/create/content/contraptions/relays/belt/item/BeltConnectorItem.java rename to src/main/java/com/simibubi/create/content/kinetics/belt/item/BeltConnectorItem.java index 8043bdf8b..a2b78fcf4 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/item/BeltConnectorItem.java +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/item/BeltConnectorItem.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.relays.belt.item; +package com.simibubi.create.content.kinetics.belt.item; import java.util.LinkedList; import java.util.List; @@ -6,15 +6,16 @@ import java.util.List; import javax.annotation.Nonnull; import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.relays.belt.BeltBlock; -import com.simibubi.create.content.contraptions.relays.belt.BeltPart; -import com.simibubi.create.content.contraptions.relays.belt.BeltSlope; -import com.simibubi.create.content.contraptions.relays.elementary.AbstractSimpleShaftBlock; -import com.simibubi.create.content.contraptions.relays.elementary.ShaftBlock; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.belt.BeltBlock; +import com.simibubi.create.content.kinetics.belt.BeltPart; +import com.simibubi.create.content.kinetics.belt.BeltSlope; +import com.simibubi.create.content.kinetics.simpleRelays.AbstractSimpleShaftBlock; +import com.simibubi.create.content.kinetics.simpleRelays.ShaftBlock; import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.config.AllConfigs; +import com.simibubi.create.foundation.block.ProperWaterloggedBlock; import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -43,7 +44,7 @@ public class BeltConnectorItem extends BlockItem { public String getDescriptionId() { return getOrCreateDescriptionId(); } - + @Nonnull @Override public InteractionResult useOn(UseOnContext context) { @@ -144,9 +145,10 @@ public class BeltConnectorItem extends BlockItem { .isReplaceable()) world.destroyBlock(pos, false); - KineticTileEntity.switchToBlockState(world, pos, beltBlock.setValue(BeltBlock.SLOPE, slope) - .setValue(BeltBlock.PART, part) - .setValue(BeltBlock.HORIZONTAL_FACING, facing)); + KineticBlockEntity.switchToBlockState(world, pos, + ProperWaterloggedBlock.withWater(world, beltBlock.setValue(BeltBlock.SLOPE, slope) + .setValue(BeltBlock.PART, part) + .setValue(BeltBlock.HORIZONTAL_FACING, facing), pos)); } if (!failed) @@ -232,16 +234,16 @@ public class BeltConnectorItem extends BlockItem { if (shaftAxis == Axis.Y && x != 0 && z != 0) return false; - BlockEntity tileEntity = world.getBlockEntity(first); - BlockEntity tileEntity2 = world.getBlockEntity(second); + BlockEntity blockEntity = world.getBlockEntity(first); + BlockEntity blockEntity2 = world.getBlockEntity(second); - if (!(tileEntity instanceof KineticTileEntity)) + if (!(blockEntity instanceof KineticBlockEntity)) return false; - if (!(tileEntity2 instanceof KineticTileEntity)) + if (!(blockEntity2 instanceof KineticBlockEntity)) return false; - float speed1 = ((KineticTileEntity) tileEntity).getTheoreticalSpeed(); - float speed2 = ((KineticTileEntity) tileEntity2).getTheoreticalSpeed(); + float speed1 = ((KineticBlockEntity) blockEntity).getTheoreticalSpeed(); + float speed2 = ((KineticBlockEntity) blockEntity2).getTheoreticalSpeed(); if (Math.signum(speed1) != Math.signum(speed2) && speed1 != 0 && speed2 != 0) return false; @@ -262,7 +264,7 @@ public class BeltConnectorItem extends BlockItem { } public static Integer maxLength() { - return AllConfigs.SERVER.kinetics.maxBeltLength.get(); + return AllConfigs.server().kinetics.maxBeltLength.get(); } public static boolean validateAxis(Level world, BlockPos pos) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltCrusherInteractionHandler.java b/src/main/java/com/simibubi/create/content/kinetics/belt/transport/BeltCrusherInteractionHandler.java similarity index 82% rename from src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltCrusherInteractionHandler.java rename to src/main/java/com/simibubi/create/content/kinetics/belt/transport/BeltCrusherInteractionHandler.java index ea8f9e8d6..a710973de 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltCrusherInteractionHandler.java +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/transport/BeltCrusherInteractionHandler.java @@ -1,8 +1,8 @@ -package com.simibubi.create.content.contraptions.relays.belt.transport; +package com.simibubi.create.content.kinetics.belt.transport; -import com.simibubi.create.content.contraptions.components.crusher.CrushingWheelControllerBlock; -import com.simibubi.create.content.contraptions.components.crusher.CrushingWheelControllerTileEntity; -import com.simibubi.create.content.contraptions.relays.belt.BeltHelper; +import com.simibubi.create.content.kinetics.belt.BeltHelper; +import com.simibubi.create.content.kinetics.crusher.CrushingWheelControllerBlock; +import com.simibubi.create.content.kinetics.crusher.CrushingWheelControllerBlockEntity; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -46,15 +46,15 @@ public class BeltCrusherInteractionHandler { return false; currentItem.beltPosition = crusherEntry; - BlockEntity te = world.getBlockEntity(crusherPos); - if (!(te instanceof CrushingWheelControllerTileEntity)) + BlockEntity be = world.getBlockEntity(crusherPos); + if (!(be instanceof CrushingWheelControllerBlockEntity)) return true; - CrushingWheelControllerTileEntity crusherTE = (CrushingWheelControllerTileEntity) te; + CrushingWheelControllerBlockEntity crusherBE = (CrushingWheelControllerBlockEntity) be; ItemStack toInsert = currentItem.stack.copy(); - ItemStack remainder = ItemHandlerHelper.insertItemStacked(crusherTE.inventory, toInsert, false); + ItemStack remainder = ItemHandlerHelper.insertItemStacked(crusherBE.inventory, toInsert, false); if (toInsert.equals(remainder, false)) return true; diff --git a/src/main/java/com/simibubi/create/content/kinetics/belt/transport/BeltFunnelInteractionHandler.java b/src/main/java/com/simibubi/create/content/kinetics/belt/transport/BeltFunnelInteractionHandler.java new file mode 100644 index 000000000..db37e8afb --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/transport/BeltFunnelInteractionHandler.java @@ -0,0 +1,121 @@ +package com.simibubi.create.content.kinetics.belt.transport; + +import com.simibubi.create.content.kinetics.belt.BeltHelper; +import com.simibubi.create.content.logistics.funnel.BeltFunnelBlock; +import com.simibubi.create.content.logistics.funnel.BeltFunnelBlock.Shape; +import com.simibubi.create.content.logistics.funnel.FunnelBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.inventory.InvManipulationBehaviour; +import com.simibubi.create.foundation.item.ItemHelper.ExtractionCountMode; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; +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.minecraftforge.items.ItemHandlerHelper; + +public class BeltFunnelInteractionHandler { + + public static boolean checkForFunnels(BeltInventory beltInventory, TransportedItemStack currentItem, + float nextOffset) { + boolean beltMovementPositive = beltInventory.beltMovementPositive; + int firstUpcomingSegment = (int) Math.floor(currentItem.beltPosition); + int step = beltMovementPositive ? 1 : -1; + firstUpcomingSegment = Mth.clamp(firstUpcomingSegment, 0, beltInventory.belt.beltLength - 1); + + for (int segment = firstUpcomingSegment; beltMovementPositive ? segment <= nextOffset + : segment + 1 >= nextOffset; segment += step) { + BlockPos funnelPos = BeltHelper.getPositionForOffset(beltInventory.belt, segment) + .above(); + Level world = beltInventory.belt.getLevel(); + BlockState funnelState = world.getBlockState(funnelPos); + if (!(funnelState.getBlock() instanceof BeltFunnelBlock)) + continue; + Direction funnelFacing = funnelState.getValue(BeltFunnelBlock.HORIZONTAL_FACING); + Direction movementFacing = beltInventory.belt.getMovementFacing(); + boolean blocking = funnelFacing == movementFacing.getOpposite(); + if (funnelFacing == movementFacing) + continue; + if (funnelState.getValue(BeltFunnelBlock.SHAPE) == Shape.PUSHING) + continue; + + float funnelEntry = segment + .5f; + if (funnelState.getValue(BeltFunnelBlock.SHAPE) == Shape.EXTENDED) + funnelEntry += .499f * (beltMovementPositive ? -1 : 1); + + boolean hasCrossed = nextOffset > funnelEntry && beltMovementPositive + || nextOffset < funnelEntry && !beltMovementPositive; + if (!hasCrossed) + return false; + if (blocking) + currentItem.beltPosition = funnelEntry; + + if (world.isClientSide || funnelState.getOptionalValue(BeltFunnelBlock.POWERED).orElse(false)) + if (blocking) + return true; + else + continue; + + BlockEntity be = world.getBlockEntity(funnelPos); + if (!(be instanceof FunnelBlockEntity)) + return true; + + FunnelBlockEntity funnelBE = (FunnelBlockEntity) be; + InvManipulationBehaviour inserting = funnelBE.getBehaviour(InvManipulationBehaviour.TYPE); + FilteringBehaviour filtering = funnelBE.getBehaviour(FilteringBehaviour.TYPE); + + if (inserting == null || filtering != null && !filtering.test(currentItem.stack)) + if (blocking) + return true; + else + continue; + + int amountToExtract = funnelBE.getAmountToExtract(); + ExtractionCountMode modeToExtract = funnelBE.getModeToExtract(); + + ItemStack toInsert = currentItem.stack.copy(); + if (amountToExtract > toInsert.getCount() && modeToExtract != ExtractionCountMode.UPTO) + if (blocking) + return true; + else + continue; + + if (amountToExtract != -1 && modeToExtract != ExtractionCountMode.UPTO) { + toInsert.setCount(Math.min(amountToExtract, toInsert.getCount())); + ItemStack remainder = inserting.simulate() + .insert(toInsert); + if (!remainder.isEmpty()) + if (blocking) + return true; + else + continue; + } + + ItemStack remainder = inserting.insert(toInsert); + if (toInsert.equals(remainder, false)) + if (blocking) + return true; + else + continue; + + int notFilled = currentItem.stack.getCount() - toInsert.getCount(); + if (!remainder.isEmpty()) { + remainder.grow(notFilled); + } else if (notFilled > 0) + remainder = ItemHandlerHelper.copyStackWithSize(currentItem.stack, notFilled); + + funnelBE.flap(true); + funnelBE.onTransfer(toInsert); + currentItem.stack = remainder; + beltInventory.belt.sendData(); + if (blocking) + return true; + } + + return false; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltInventory.java b/src/main/java/com/simibubi/create/content/kinetics/belt/transport/BeltInventory.java similarity index 89% rename from src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltInventory.java rename to src/main/java/com/simibubi/create/content/kinetics/belt/transport/BeltInventory.java index dbfecf2e0..42b0939f6 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltInventory.java +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/transport/BeltInventory.java @@ -1,6 +1,6 @@ -package com.simibubi.create.content.contraptions.relays.belt.transport; +package com.simibubi.create.content.kinetics.belt.transport; -import static com.simibubi.create.content.contraptions.relays.belt.transport.BeltTunnelInteractionHandler.flapTunnel; +import static com.simibubi.create.content.kinetics.belt.transport.BeltTunnelInteractionHandler.flapTunnel; import java.util.Collections; import java.util.Iterator; @@ -8,16 +8,16 @@ import java.util.LinkedList; import java.util.List; import java.util.function.Function; -import com.simibubi.create.content.contraptions.relays.belt.BeltBlock; -import com.simibubi.create.content.contraptions.relays.belt.BeltHelper; -import com.simibubi.create.content.contraptions.relays.belt.BeltSlope; -import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProcessingBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProcessingBehaviour.ProcessingResult; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour.TransportedResult; +import com.simibubi.create.content.kinetics.belt.BeltBlock; +import com.simibubi.create.content.kinetics.belt.BeltBlockEntity; +import com.simibubi.create.content.kinetics.belt.BeltHelper; +import com.simibubi.create.content.kinetics.belt.BeltSlope; +import com.simibubi.create.content.kinetics.belt.behaviour.BeltProcessingBehaviour; +import com.simibubi.create.content.kinetics.belt.behaviour.BeltProcessingBehaviour.ProcessingResult; +import com.simibubi.create.content.kinetics.belt.behaviour.DirectBeltInputBehaviour; +import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour; +import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour.TransportedResult; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.utility.BlockHelper; import com.simibubi.create.foundation.utility.ServerSpeedProvider; @@ -33,15 +33,15 @@ import net.minecraft.world.phys.Vec3; public class BeltInventory { - final BeltTileEntity belt; + final BeltBlockEntity belt; private final List items; final List toInsert; final List toRemove; boolean beltMovementPositive; final float SEGMENT_WINDOW = .75f; - public BeltInventory(BeltTileEntity te) { - this.belt = te; + public BeltInventory(BeltBlockEntity be) { + this.belt = be; items = new LinkedList<>(); toInsert = new LinkedList<>(); toRemove = new LinkedList<>(); @@ -184,7 +184,7 @@ public class BeltInventory { if (ending == Ending.INSERT) { DirectBeltInputBehaviour inputBehaviour = - TileEntityBehaviour.get(world, nextPosition, DirectBeltInputBehaviour.TYPE); + BlockEntityBehaviour.get(world, nextPosition, DirectBeltInputBehaviour.TYPE); if (inputBehaviour == null) continue; if (!inputBehaviour.canInsertFromSide(movementFacing)) @@ -284,12 +284,12 @@ public class BeltInventory { } protected BeltProcessingBehaviour getBeltProcessingAtSegment(int segment) { - return TileEntityBehaviour.get(belt.getLevel(), BeltHelper.getPositionForOffset(belt, segment) + return BlockEntityBehaviour.get(belt.getLevel(), BeltHelper.getPositionForOffset(belt, segment) .above(2), BeltProcessingBehaviour.TYPE); } protected TransportedItemStackHandlerBehaviour getTransportedItemStackHandlerAtSegment(int segment) { - return TileEntityBehaviour.get(belt.getLevel(), BeltHelper.getPositionForOffset(belt, segment), + return BlockEntityBehaviour.get(belt.getLevel(), BeltHelper.getPositionForOffset(belt, segment), TransportedItemStackHandlerBehaviour.TYPE); } @@ -311,7 +311,7 @@ public class BeltInventory { // return Ending.FUNNEL; DirectBeltInputBehaviour inputBehaviour = - TileEntityBehaviour.get(world, nextPosition, DirectBeltInputBehaviour.TYPE); + BlockEntityBehaviour.get(world, nextPosition, DirectBeltInputBehaviour.TYPE); if (inputBehaviour != null) return Ending.INSERT; diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltMovementHandler.java b/src/main/java/com/simibubi/create/content/kinetics/belt/transport/BeltMovementHandler.java similarity index 86% rename from src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltMovementHandler.java rename to src/main/java/com/simibubi/create/content/kinetics/belt/transport/BeltMovementHandler.java index 2b2777af1..059975478 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltMovementHandler.java +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/transport/BeltMovementHandler.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.relays.belt.transport; +package com.simibubi.create.content.kinetics.belt.transport; import static net.minecraft.core.Direction.AxisDirection.NEGATIVE; import static net.minecraft.core.Direction.AxisDirection.POSITIVE; @@ -7,10 +7,10 @@ import static net.minecraft.world.entity.MoverType.SELF; import java.util.List; import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.relays.belt.BeltBlock; -import com.simibubi.create.content.contraptions.relays.belt.BeltPart; -import com.simibubi.create.content.contraptions.relays.belt.BeltSlope; -import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity; +import com.simibubi.create.content.kinetics.belt.BeltBlock; +import com.simibubi.create.content.kinetics.belt.BeltBlockEntity; +import com.simibubi.create.content.kinetics.belt.BeltPart; +import com.simibubi.create.content.kinetics.belt.BeltSlope; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -65,18 +65,18 @@ public class BeltMovementHandler { return true; } - public static void transportEntity(BeltTileEntity beltTe, Entity entityIn, TransportedEntityInfo info) { + public static void transportEntity(BeltBlockEntity beltBE, Entity entityIn, TransportedEntityInfo info) { BlockPos pos = info.lastCollidedPos; - Level world = beltTe.getLevel(); - BlockEntity te = world.getBlockEntity(pos); - BlockEntity tileEntityBelowPassenger = world.getBlockEntity(entityIn.blockPosition()); + Level world = beltBE.getLevel(); + BlockEntity be = world.getBlockEntity(pos); + BlockEntity blockEntityBelowPassenger = world.getBlockEntity(entityIn.blockPosition()); BlockState blockState = info.lastCollidedState; Direction movementFacing = Direction.fromAxisAndDirection(blockState.getValue(BlockStateProperties.HORIZONTAL_FACING) - .getAxis(), beltTe.getSpeed() < 0 ? POSITIVE : NEGATIVE); + .getAxis(), beltBE.getSpeed() < 0 ? POSITIVE : NEGATIVE); - boolean collidedWithBelt = te instanceof BeltTileEntity; - boolean betweenBelts = tileEntityBelowPassenger instanceof BeltTileEntity && tileEntityBelowPassenger != te; + boolean collidedWithBelt = be instanceof BeltBlockEntity; + boolean betweenBelts = blockEntityBelowPassenger instanceof BeltBlockEntity && blockEntityBelowPassenger != be; // Don't fight other Belts if (!collidedWithBelt || betweenBelts) { @@ -84,9 +84,9 @@ public class BeltMovementHandler { } // Too slow - boolean notHorizontal = beltTe.getBlockState() + boolean notHorizontal = beltBE.getBlockState() .getValue(BeltBlock.SLOPE) != BeltSlope.HORIZONTAL; - if (Math.abs(beltTe.getSpeed()) < 1) + if (Math.abs(beltBE.getSpeed()) < 1) return; // Not on top @@ -101,7 +101,7 @@ public class BeltMovementHandler { final Direction beltFacing = blockState.getValue(BlockStateProperties.HORIZONTAL_FACING); final BeltSlope slope = blockState.getValue(BeltBlock.SLOPE); final Axis axis = beltFacing.getAxis(); - float movementSpeed = beltTe.getBeltMovementSpeed(); + float movementSpeed = beltBE.getBeltMovementSpeed(); final Direction movementDirection = Direction.get(axis == Axis.X ? NEGATIVE : POSITIVE, axis); Vec3i centeringDirection = Direction.get(POSITIVE, beltFacing.getClockWise() diff --git a/src/main/java/com/simibubi/create/content/kinetics/belt/transport/BeltTunnelInteractionHandler.java b/src/main/java/com/simibubi/create/content/kinetics/belt/transport/BeltTunnelInteractionHandler.java new file mode 100644 index 000000000..2c96df858 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/transport/BeltTunnelInteractionHandler.java @@ -0,0 +1,160 @@ +package com.simibubi.create.content.kinetics.belt.transport; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.kinetics.belt.BeltBlock; +import com.simibubi.create.content.kinetics.belt.BeltBlockEntity; +import com.simibubi.create.content.kinetics.belt.BeltHelper; +import com.simibubi.create.content.kinetics.belt.BeltSlope; +import com.simibubi.create.content.kinetics.belt.behaviour.DirectBeltInputBehaviour; +import com.simibubi.create.content.logistics.tunnel.BeltTunnelBlock; +import com.simibubi.create.content.logistics.tunnel.BeltTunnelBlockEntity; +import com.simibubi.create.content.logistics.tunnel.BrassTunnelBlock; +import com.simibubi.create.content.logistics.tunnel.BrassTunnelBlockEntity; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkBlock; +import com.simibubi.create.content.redstone.displayLink.source.AccumulatedItemCountDisplaySource; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.Iterate; + +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 net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.items.ItemHandlerHelper; + +public class BeltTunnelInteractionHandler { + + public static boolean flapTunnelsAndCheckIfStuck(BeltInventory beltInventory, TransportedItemStack current, + float nextOffset) { + + int currentSegment = (int) current.beltPosition; + int upcomingSegment = (int) nextOffset; + + Direction movementFacing = beltInventory.belt.getMovementFacing(); + if (!beltInventory.beltMovementPositive && nextOffset == 0) + upcomingSegment = -1; + if (currentSegment == upcomingSegment) + return false; + + if (stuckAtTunnel(beltInventory, upcomingSegment, current.stack, movementFacing)) { + current.beltPosition = currentSegment + (beltInventory.beltMovementPositive ? .99f : .01f); + return true; + } + + Level world = beltInventory.belt.getLevel(); + boolean onServer = !world.isClientSide || beltInventory.belt.isVirtual(); + boolean removed = false; + BeltTunnelBlockEntity nextTunnel = getTunnelOnSegment(beltInventory, upcomingSegment); + int transferred = current.stack.getCount(); + + if (nextTunnel instanceof BrassTunnelBlockEntity) { + BrassTunnelBlockEntity brassTunnel = (BrassTunnelBlockEntity) nextTunnel; + if (brassTunnel.hasDistributionBehaviour()) { + if (!brassTunnel.canTakeItems()) + return true; + if (onServer) { + brassTunnel.setStackToDistribute(current.stack, movementFacing.getOpposite()); + current.stack = ItemStack.EMPTY; + beltInventory.belt.sendData(); + beltInventory.belt.setChanged(); + } + removed = true; + } + } else if (nextTunnel != null) { + BlockState blockState = nextTunnel.getBlockState(); + if (current.stack.getCount() > 1 && AllBlocks.ANDESITE_TUNNEL.has(blockState) + && BeltTunnelBlock.isJunction(blockState) + && movementFacing.getAxis() == blockState.getValue(BeltTunnelBlock.HORIZONTAL_AXIS)) { + + for (Direction d : Iterate.horizontalDirections) { + if (d.getAxis() == blockState.getValue(BeltTunnelBlock.HORIZONTAL_AXIS)) + continue; + if (!nextTunnel.flaps.containsKey(d)) + continue; + BlockPos outpos = nextTunnel.getBlockPos() + .below() + .relative(d); + if (!world.isLoaded(outpos)) + return true; + DirectBeltInputBehaviour behaviour = + BlockEntityBehaviour.get(world, outpos, DirectBeltInputBehaviour.TYPE); + if (behaviour == null) + continue; + if (!behaviour.canInsertFromSide(d)) + continue; + + ItemStack toinsert = ItemHandlerHelper.copyStackWithSize(current.stack, 1); + if (!behaviour.handleInsertion(toinsert, d, false) + .isEmpty()) + return true; + if (onServer) + flapTunnel(beltInventory, upcomingSegment, d, false); + + current.stack.shrink(1); + beltInventory.belt.sendData(); + if (current.stack.getCount() <= 1) + break; + } + } + } + + if (onServer) { + flapTunnel(beltInventory, currentSegment, movementFacing, false); + flapTunnel(beltInventory, upcomingSegment, movementFacing.getOpposite(), true); + + if (nextTunnel != null) + DisplayLinkBlock.sendToGatherers(world, nextTunnel.getBlockPos(), + (dgte, b) -> b.itemReceived(dgte, transferred), AccumulatedItemCountDisplaySource.class); + } + + if (removed) + return true; + + return false; + } + + public static boolean stuckAtTunnel(BeltInventory beltInventory, int offset, ItemStack stack, + Direction movementDirection) { + BeltBlockEntity belt = beltInventory.belt; + BlockPos pos = BeltHelper.getPositionForOffset(belt, offset) + .above(); + if (!(belt.getLevel() + .getBlockState(pos) + .getBlock() instanceof BrassTunnelBlock)) + return false; + BlockEntity be = belt.getLevel() + .getBlockEntity(pos); + if (be == null || !(be instanceof BrassTunnelBlockEntity)) + return false; + BrassTunnelBlockEntity tunnel = (BrassTunnelBlockEntity) be; + return !tunnel.canInsert(movementDirection.getOpposite(), stack); + } + + public static void flapTunnel(BeltInventory beltInventory, int offset, Direction side, boolean inward) { + BeltTunnelBlockEntity be = getTunnelOnSegment(beltInventory, offset); + if (be == null) + return; + be.flap(side, inward); + } + + protected static BeltTunnelBlockEntity getTunnelOnSegment(BeltInventory beltInventory, int offset) { + BeltBlockEntity belt = beltInventory.belt; + if (belt.getBlockState() + .getValue(BeltBlock.SLOPE) != BeltSlope.HORIZONTAL) + return null; + return getTunnelOnPosition(belt.getLevel(), BeltHelper.getPositionForOffset(belt, offset)); + } + + public static BeltTunnelBlockEntity getTunnelOnPosition(Level world, BlockPos pos) { + pos = pos.above(); + if (!(world.getBlockState(pos) + .getBlock() instanceof BeltTunnelBlock)) + return null; + BlockEntity be = world.getBlockEntity(pos); + if (be == null || !(be instanceof BeltTunnelBlockEntity)) + return null; + return ((BeltTunnelBlockEntity) be); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/ItemHandlerBeltSegment.java b/src/main/java/com/simibubi/create/content/kinetics/belt/transport/ItemHandlerBeltSegment.java similarity index 96% rename from src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/ItemHandlerBeltSegment.java rename to src/main/java/com/simibubi/create/content/kinetics/belt/transport/ItemHandlerBeltSegment.java index 5cd73adb7..3395f9393 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/ItemHandlerBeltSegment.java +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/transport/ItemHandlerBeltSegment.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.relays.belt.transport; +package com.simibubi.create.content.kinetics.belt.transport; import net.minecraft.world.item.ItemStack; import net.minecraftforge.items.IItemHandler; diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/TransportedItemStack.java b/src/main/java/com/simibubi/create/content/kinetics/belt/transport/TransportedItemStack.java similarity index 91% rename from src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/TransportedItemStack.java rename to src/main/java/com/simibubi/create/content/kinetics/belt/transport/TransportedItemStack.java index becba0f91..aec7c61f8 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/TransportedItemStack.java +++ b/src/main/java/com/simibubi/create/content/kinetics/belt/transport/TransportedItemStack.java @@ -1,9 +1,9 @@ -package com.simibubi.create.content.contraptions.relays.belt.transport; +package com.simibubi.create.content.kinetics.belt.transport; import java.util.Random; -import com.simibubi.create.content.contraptions.processing.InWorldProcessing; -import com.simibubi.create.content.contraptions.relays.belt.BeltHelper; +import com.simibubi.create.content.kinetics.belt.BeltHelper; +import com.simibubi.create.content.kinetics.fan.FanProcessing; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -25,7 +25,7 @@ public class TransportedItemStack implements Comparable { public float prevBeltPosition; public float prevSideOffset; - public InWorldProcessing.Type processedBy; + public FanProcessing.Type processedBy; public int processingTime; public TransportedItemStack(ItemStack stack) { diff --git a/src/main/java/com/simibubi/create/content/kinetics/chainDrive/ChainDriveBlock.java b/src/main/java/com/simibubi/create/content/kinetics/chainDrive/ChainDriveBlock.java new file mode 100644 index 000000000..bf92d0a4c --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/chainDrive/ChainDriveBlock.java @@ -0,0 +1,275 @@ +package com.simibubi.create.content.kinetics.chainDrive; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.content.contraptions.ITransformableBlock; +import com.simibubi.create.content.contraptions.StructureTransform; +import com.simibubi.create.content.kinetics.base.DirectionalAxisKineticBlock; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.base.RotatedPillarKineticBlock; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.util.StringRepresentable; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.item.context.UseOnContext; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Mirror; +import net.minecraft.world.level.block.Rotation; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition.Builder; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.level.block.state.properties.EnumProperty; +import net.minecraft.world.level.block.state.properties.Property; +import net.minecraft.world.level.material.PushReaction; + +public class ChainDriveBlock extends RotatedPillarKineticBlock + implements IBE, ITransformableBlock { + + public static final Property PART = EnumProperty.create("part", Part.class); + public static final BooleanProperty CONNECTED_ALONG_FIRST_COORDINATE = + DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE; + + public ChainDriveBlock(Properties properties) { + super(properties); + registerDefaultState(defaultBlockState().setValue(PART, Part.NONE)); + } + + @Override + public boolean shouldCheckWeakPower(BlockState state, LevelReader world, BlockPos pos, Direction side) { + return false; + } + + @Override + public PushReaction getPistonPushReaction(BlockState state) { + return PushReaction.NORMAL; + } + + @Override + protected void createBlockStateDefinition(Builder builder) { + super.createBlockStateDefinition(builder.add(PART, CONNECTED_ALONG_FIRST_COORDINATE)); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext context) { + Axis placedAxis = context.getNearestLookingDirection() + .getAxis(); + Axis axis = context.getPlayer() != null && context.getPlayer() + .isShiftKeyDown() ? placedAxis : getPreferredAxis(context); + if (axis == null) + axis = placedAxis; + + BlockState state = defaultBlockState().setValue(AXIS, axis); + for (Direction facing : Iterate.directions) { + if (facing.getAxis() == axis) + continue; + BlockPos pos = context.getClickedPos(); + BlockPos offset = pos.relative(facing); + state = updateShape(state, facing, context.getLevel() + .getBlockState(offset), context.getLevel(), pos, offset); + } + return state; + } + + @Override + public BlockState updateShape(BlockState stateIn, Direction face, BlockState neighbour, LevelAccessor worldIn, + BlockPos currentPos, BlockPos facingPos) { + Part part = stateIn.getValue(PART); + Axis axis = stateIn.getValue(AXIS); + boolean connectionAlongFirst = stateIn.getValue(CONNECTED_ALONG_FIRST_COORDINATE); + Axis connectionAxis = + connectionAlongFirst ? (axis == Axis.X ? Axis.Y : Axis.X) : (axis == Axis.Z ? Axis.Y : Axis.Z); + + Axis faceAxis = face.getAxis(); + boolean facingAlongFirst = axis == Axis.X ? faceAxis.isVertical() : faceAxis == Axis.X; + boolean positive = face.getAxisDirection() == AxisDirection.POSITIVE; + + if (axis == faceAxis) + return stateIn; + + if (!(neighbour.getBlock() instanceof ChainDriveBlock)) { + if (facingAlongFirst != connectionAlongFirst || part == Part.NONE) + return stateIn; + if (part == Part.MIDDLE) + return stateIn.setValue(PART, positive ? Part.END : Part.START); + if ((part == Part.START) == positive) + return stateIn.setValue(PART, Part.NONE); + return stateIn; + } + + Part otherPart = neighbour.getValue(PART); + Axis otherAxis = neighbour.getValue(AXIS); + boolean otherConnection = neighbour.getValue(CONNECTED_ALONG_FIRST_COORDINATE); + Axis otherConnectionAxis = + otherConnection ? (otherAxis == Axis.X ? Axis.Y : Axis.X) : (otherAxis == Axis.Z ? Axis.Y : Axis.Z); + + if (neighbour.getValue(AXIS) == faceAxis) + return stateIn; + if (otherPart != Part.NONE && otherConnectionAxis != faceAxis) + return stateIn; + + if (part == Part.NONE) { + part = positive ? Part.START : Part.END; + connectionAlongFirst = axis == Axis.X ? faceAxis.isVertical() : faceAxis == Axis.X; + } else if (connectionAxis != faceAxis) { + return stateIn; + } + + if ((part == Part.START) != positive) + part = Part.MIDDLE; + + return stateIn.setValue(PART, part) + .setValue(CONNECTED_ALONG_FIRST_COORDINATE, connectionAlongFirst); + } + + @Override + public BlockState getRotatedBlockState(BlockState originalState, Direction targetedFace) { + if (originalState.getValue(PART) == Part.NONE) + return super.getRotatedBlockState(originalState, targetedFace); + return super.getRotatedBlockState(originalState, + Direction.get(AxisDirection.POSITIVE, getConnectionAxis(originalState))); + } + + @Override + public BlockState updateAfterWrenched(BlockState newState, UseOnContext context) { +// Blocks.AIR.getDefaultState() +// .updateNeighbors(context.getWorld(), context.getPos(), 1); + Axis axis = newState.getValue(AXIS); + newState = defaultBlockState().setValue(AXIS, axis); + if (newState.hasProperty(BlockStateProperties.POWERED)) + newState = newState.setValue(BlockStateProperties.POWERED, context.getLevel() + .hasNeighborSignal(context.getClickedPos())); + for (Direction facing : Iterate.directions) { + if (facing.getAxis() == axis) + continue; + BlockPos pos = context.getClickedPos(); + BlockPos offset = pos.relative(facing); + newState = updateShape(newState, facing, context.getLevel() + .getBlockState(offset), context.getLevel(), pos, offset); + } +// newState.updateNeighbors(context.getWorld(), context.getPos(), 1 | 2); + return newState; + } + + @Override + public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) { + return face.getAxis() == state.getValue(AXIS); + } + + @Override + public Axis getRotationAxis(BlockState state) { + return state.getValue(AXIS); + } + + public static boolean areBlocksConnected(BlockState state, BlockState other, Direction facing) { + Part part = state.getValue(PART); + Axis connectionAxis = getConnectionAxis(state); + Axis otherConnectionAxis = getConnectionAxis(other); + + if (otherConnectionAxis != connectionAxis) + return false; + if (facing.getAxis() != connectionAxis) + return false; + if (facing.getAxisDirection() == AxisDirection.POSITIVE && (part == Part.MIDDLE || part == Part.START)) + return true; + if (facing.getAxisDirection() == AxisDirection.NEGATIVE && (part == Part.MIDDLE || part == Part.END)) + return true; + + return false; + } + + protected static Axis getConnectionAxis(BlockState state) { + Axis axis = state.getValue(AXIS); + boolean connectionAlongFirst = state.getValue(CONNECTED_ALONG_FIRST_COORDINATE); + Axis connectionAxis = + connectionAlongFirst ? (axis == Axis.X ? Axis.Y : Axis.X) : (axis == Axis.Z ? Axis.Y : Axis.Z); + return connectionAxis; + } + + public static float getRotationSpeedModifier(KineticBlockEntity from, KineticBlockEntity to) { + float fromMod = 1; + float toMod = 1; + if (from instanceof ChainGearshiftBlockEntity) + fromMod = ((ChainGearshiftBlockEntity) from).getModifier(); + if (to instanceof ChainGearshiftBlockEntity) + toMod = ((ChainGearshiftBlockEntity) to).getModifier(); + return fromMod / toMod; + } + + public enum Part implements StringRepresentable { + START, MIDDLE, END, NONE; + + @Override + public String getSerializedName() { + return Lang.asId(name()); + } + } + + @Override + public Class getBlockEntityClass() { + return KineticBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.ENCASED_SHAFT.get(); + } + + @Override + public BlockState rotate(BlockState state, Rotation rot) { + return rotate(state, rot, Axis.Y); + } + + protected BlockState rotate(BlockState pState, Rotation rot, Axis rotAxis) { + Axis connectionAxis = getConnectionAxis(pState); + Direction direction = Direction.fromAxisAndDirection(connectionAxis, AxisDirection.POSITIVE); + Direction normal = Direction.fromAxisAndDirection(pState.getValue(AXIS), AxisDirection.POSITIVE); + for (int i = 0; i < rot.ordinal(); i++) { + direction = direction.getClockWise(rotAxis); + normal = normal.getClockWise(rotAxis); + } + + if (direction.getAxisDirection() == AxisDirection.NEGATIVE) + pState = reversePart(pState); + + Axis newAxis = normal.getAxis(); + Axis newConnectingDirection = direction.getAxis(); + boolean alongFirst = newAxis == Axis.X && newConnectingDirection == Axis.Y + || newAxis != Axis.X && newConnectingDirection == Axis.X; + + return pState.setValue(AXIS, newAxis) + .setValue(CONNECTED_ALONG_FIRST_COORDINATE, alongFirst); + } + + @Override + public BlockState mirror(BlockState pState, Mirror pMirror) { + Axis connectionAxis = getConnectionAxis(pState); + if (pMirror.mirror(Direction.fromAxisAndDirection(connectionAxis, AxisDirection.POSITIVE)) + .getAxisDirection() == AxisDirection.POSITIVE) + return pState; + return reversePart(pState); + } + + protected BlockState reversePart(BlockState pState) { + Part part = pState.getValue(PART); + if (part == Part.START) + return pState.setValue(PART, Part.END); + if (part == Part.END) + return pState.setValue(PART, Part.START); + return pState; + } + + @Override + public BlockState transform(BlockState state, StructureTransform transform) { + return rotate(mirror(state, transform.mirror), transform.rotation, transform.rotationAxis); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/chainDrive/ChainDriveGenerator.java b/src/main/java/com/simibubi/create/content/kinetics/chainDrive/ChainDriveGenerator.java new file mode 100644 index 000000000..8518ef0cc --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/chainDrive/ChainDriveGenerator.java @@ -0,0 +1,72 @@ +package com.simibubi.create.content.kinetics.chainDrive; + +import java.util.function.BiFunction; + +import com.simibubi.create.content.kinetics.chainDrive.ChainDriveBlock.Part; +import com.simibubi.create.foundation.data.SpecialBlockStateGen; +import com.tterrag.registrate.providers.DataGenContext; +import com.tterrag.registrate.providers.RegistrateBlockstateProvider; + +import net.minecraft.core.Direction.Axis; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.client.model.generators.ModelFile; + +public class ChainDriveGenerator extends SpecialBlockStateGen { + + private BiFunction modelFunc; + + public ChainDriveGenerator(BiFunction modelFunc) { + this.modelFunc = modelFunc; + } + + @Override + protected int getXRotation(BlockState state) { + ChainDriveBlock.Part part = state.getValue(ChainDriveBlock.PART); + boolean connectedAlongFirst = state.getValue(ChainDriveBlock.CONNECTED_ALONG_FIRST_COORDINATE); + Axis axis = state.getValue(ChainDriveBlock.AXIS); + + if (part == Part.NONE) + return axis == Axis.Y ? 90 : 0; + if (axis == Axis.X) + return (connectedAlongFirst ? 90 : 0) + (part == Part.START ? 180 : 0); + if (axis == Axis.Z) + return (connectedAlongFirst ? 0 : (part == Part.START ? 270 : 90)); + return 0; + } + + @Override + protected int getYRotation(BlockState state) { + ChainDriveBlock.Part part = state.getValue(ChainDriveBlock.PART); + boolean connectedAlongFirst = state.getValue(ChainDriveBlock.CONNECTED_ALONG_FIRST_COORDINATE); + Axis axis = state.getValue(ChainDriveBlock.AXIS); + + if (part == Part.NONE) + return axis == Axis.X ? 90 : 0; + if (axis == Axis.Z) + return (connectedAlongFirst && part == Part.END ? 270 : 90); + boolean flip = part == Part.END && !connectedAlongFirst || part == Part.START && connectedAlongFirst; + if (axis == Axis.Y) + return (connectedAlongFirst ? 90 : 0) + (flip ? 180 : 0); + return 0; + } + + @Override + public ModelFile getModel(DataGenContext ctx, RegistrateBlockstateProvider prov, + BlockState state) { + return modelFunc.apply(state, getModelSuffix(state)); + } + + protected String getModelSuffix(BlockState state) { + ChainDriveBlock.Part part = state.getValue(ChainDriveBlock.PART); + Axis axis = state.getValue(ChainDriveBlock.AXIS); + + if (part == Part.NONE) + return "single"; + + String orientation = axis == Axis.Y ? "vertical" : "horizontal"; + String section = part == Part.MIDDLE ? "middle" : "end"; + return section + "_" + orientation; + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/chainDrive/ChainGearshiftBlock.java b/src/main/java/com/simibubi/create/content/kinetics/chainDrive/ChainGearshiftBlock.java new file mode 100644 index 000000000..ea6550ab8 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/chainDrive/ChainGearshiftBlock.java @@ -0,0 +1,68 @@ +package com.simibubi.create.content.kinetics.chainDrive; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition.Builder; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.BooleanProperty; + +public class ChainGearshiftBlock extends ChainDriveBlock { + + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; + + public ChainGearshiftBlock(Properties properties) { + super(properties); + registerDefaultState(defaultBlockState().setValue(POWERED, false)); + } + + @Override + protected void createBlockStateDefinition(Builder builder) { + super.createBlockStateDefinition(builder.add(POWERED)); + } + + @Override + public void onPlace(BlockState state, Level worldIn, BlockPos pos, BlockState oldState, boolean isMoving) { + super.onPlace(state, worldIn, pos, oldState, isMoving); + if (oldState.getBlock() == state.getBlock()) + return; + withBlockEntityDo(worldIn, pos, kbe -> ((ChainGearshiftBlockEntity) kbe).neighbourChanged()); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext context) { + return super.getStateForPlacement(context).setValue(POWERED, context.getLevel() + .hasNeighborSignal(context.getClickedPos())); + } + + @Override + protected boolean areStatesKineticallyEquivalent(BlockState oldState, BlockState newState) { + return super.areStatesKineticallyEquivalent(oldState, newState) + && oldState.getValue(POWERED) == newState.getValue(POWERED); + } + + @Override + public void neighborChanged(BlockState state, Level worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, + boolean isMoving) { + if (worldIn.isClientSide) + return; + + withBlockEntityDo(worldIn, pos, kbe -> ((ChainGearshiftBlockEntity) kbe).neighbourChanged()); + + boolean previouslyPowered = state.getValue(POWERED); + if (previouslyPowered != worldIn.hasNeighborSignal(pos)) + worldIn.setBlock(pos, state.cycle(POWERED), 18); + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.ADJUSTABLE_CHAIN_GEARSHIFT.get(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/chainDrive/ChainGearshiftBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/chainDrive/ChainGearshiftBlockEntity.java new file mode 100644 index 000000000..8470887da --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/chainDrive/ChainGearshiftBlockEntity.java @@ -0,0 +1,75 @@ +package com.simibubi.create.content.kinetics.chainDrive; + +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; + +public class ChainGearshiftBlockEntity extends KineticBlockEntity { + + int signal; + boolean signalChanged; + + public ChainGearshiftBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + signal = 0; + setLazyTickRate(40); + } + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + compound.putInt("Signal", signal); + super.write(compound, clientPacket); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + signal = compound.getInt("Signal"); + super.read(compound, clientPacket); + } + + public float getModifier() { + return getModifierForSignal(signal); + } + + public void neighbourChanged() { + if (!hasLevel()) + return; + int power = level.getBestNeighborSignal(worldPosition); + if (power != signal) + signalChanged = true; + } + + @Override + public void lazyTick() { + super.lazyTick(); + neighbourChanged(); + } + + @Override + public void tick() { + super.tick(); + if (level.isClientSide) + return; + if (signalChanged) { + signalChanged = false; + analogSignalChanged(level.getBestNeighborSignal(worldPosition)); + } + } + + protected void analogSignalChanged(int newSignal) { + detachKinetics(); + removeSource(); + signal = newSignal; + attachKinetics(); + } + + protected float getModifierForSignal(int newPower) { + if (newPower == 0) + return 1; + return 1 + ((newPower + 1) / 16f); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/clock/CuckooClockBlock.java b/src/main/java/com/simibubi/create/content/kinetics/clock/CuckooClockBlock.java similarity index 82% rename from src/main/java/com/simibubi/create/content/contraptions/components/clock/CuckooClockBlock.java rename to src/main/java/com/simibubi/create/content/kinetics/clock/CuckooClockBlock.java index 98ae27fbc..5e1afd539 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/clock/CuckooClockBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/clock/CuckooClockBlock.java @@ -1,9 +1,9 @@ -package com.simibubi.create.content.contraptions.components.clock; +package com.simibubi.create.content.kinetics.clock; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.HorizontalKineticBlock; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.content.kinetics.base.HorizontalKineticBlock; +import com.simibubi.create.foundation.block.IBE; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -18,7 +18,7 @@ import net.minecraft.world.level.pathfinder.PathComputationType; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; -public class CuckooClockBlock extends HorizontalKineticBlock implements ITE { +public class CuckooClockBlock extends HorizontalKineticBlock implements IBE { private boolean mysterious; @@ -70,13 +70,13 @@ public class CuckooClockBlock extends HorizontalKineticBlock implements ITE getTileEntityClass() { - return CuckooClockTileEntity.class; + public Class getBlockEntityClass() { + return CuckooClockBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.CUCKOO_CLOCK.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.CUCKOO_CLOCK.get(); } } diff --git a/src/main/java/com/simibubi/create/content/kinetics/clock/CuckooClockBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/clock/CuckooClockBlockEntity.java new file mode 100644 index 000000000..dbffe299a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/clock/CuckooClockBlockEntity.java @@ -0,0 +1,194 @@ +package com.simibubi.create.content.kinetics.clock; + +import java.util.List; + +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.NBTHelper; +import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.util.Mth; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.level.Level.ExplosionInteraction; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class CuckooClockBlockEntity extends KineticBlockEntity { + + public static DamageSource CUCKOO_SURPRISE = new DamageSource("create.cuckoo_clock_explosion").setExplosion(); + + public LerpedFloat hourHand = LerpedFloat.angular(); + public LerpedFloat minuteHand = LerpedFloat.angular(); + public LerpedFloat animationProgress = LerpedFloat.linear(); + public Animation animationType; + private boolean sendAnimationUpdate; + + enum Animation { + PIG, CREEPER, SURPRISE, NONE; + } + + public CuckooClockBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + animationType = Animation.NONE; + } + + @Override + public void addBehaviours(List behaviours) { + super.addBehaviours(behaviours); + registerAwardables(behaviours, AllAdvancements.CUCKOO_CLOCK); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + super.read(compound, clientPacket); + if (clientPacket && compound.contains("Animation")) { + animationType = NBTHelper.readEnum(compound, "Animation", Animation.class); + animationProgress.startWithValue(0); + } + } + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + if (clientPacket && sendAnimationUpdate) + NBTHelper.writeEnum(compound, "Animation", animationType); + sendAnimationUpdate = false; + super.write(compound, clientPacket); + } + + @Override + public void tick() { + super.tick(); + if (getSpeed() == 0) + return; + + + boolean isNatural = level.dimensionType().natural(); + int dayTime = (int) ((level.getDayTime() * (isNatural ? 1 : 24)) % 24000); + int hours = (dayTime / 1000 + 6) % 24; + int minutes = (dayTime % 1000) * 60 / 1000; + + if (!isNatural) { + if (level.isClientSide) { + moveHands(hours, minutes); + + if (AnimationTickHolder.getTicks() % 6 == 0) + playSound(SoundEvents.NOTE_BLOCK_HAT.get(), 1 / 16f, 2f); + else if (AnimationTickHolder.getTicks() % 3 == 0) + playSound(SoundEvents.NOTE_BLOCK_HAT.get(), 1 / 16f, 1.5f); + } + return; + } + + if (!level.isClientSide) { + if (animationType == Animation.NONE) { + if (hours == 12 && minutes < 5) + startAnimation(Animation.PIG); + if (hours == 18 && minutes < 36 && minutes > 31) + startAnimation(Animation.CREEPER); + } else { + float value = animationProgress.getValue(); + animationProgress.setValue(value + 1); + if (value > 100) + animationType = Animation.NONE; + + if (animationType == Animation.SURPRISE && Mth.equal(animationProgress.getValue(), 50)) { + Vec3 center = VecHelper.getCenterOf(worldPosition); + level.destroyBlock(worldPosition, false); + level.explode(null, CUCKOO_SURPRISE, null, center.x, center.y, center.z, 3, false, + ExplosionInteraction.BLOCK); + } + + } + } + + if (level.isClientSide) { + moveHands(hours, minutes); + + if (animationType == Animation.NONE) { + if (AnimationTickHolder.getTicks() % 32 == 0) + playSound(SoundEvents.NOTE_BLOCK_HAT.get(), 1 / 16f, 2f); + else if (AnimationTickHolder.getTicks() % 16 == 0) + playSound(SoundEvents.NOTE_BLOCK_HAT.get(), 1 / 16f, 1.5f); + } else { + + boolean isSurprise = animationType == Animation.SURPRISE; + float value = animationProgress.getValue(); + animationProgress.setValue(value + 1); + if (value > 100) + animationType = null; + + // sounds + + if (value == 1) + playSound(SoundEvents.NOTE_BLOCK_CHIME.get(), 2, .5f); + if (value == 21) + playSound(SoundEvents.NOTE_BLOCK_CHIME.get(), 2, 0.793701f); + + if (value > 30 && isSurprise) { + Vec3 pos = VecHelper.offsetRandomly(VecHelper.getCenterOf(this.worldPosition), level.random, .5f); + level.addParticle(ParticleTypes.LARGE_SMOKE, pos.x, pos.y, pos.z, 0, 0, 0); + } + if (value == 40 && isSurprise) + playSound(SoundEvents.TNT_PRIMED, 1f, 1f); + + int step = isSurprise ? 3 : 15; + for (int phase = 30; phase <= 60; phase += step) { + if (value == phase - step / 3) + playSound(SoundEvents.CHEST_OPEN, 1 / 16f, 2f); + if (value == phase) { + if (animationType == Animation.PIG) + playSound(SoundEvents.PIG_AMBIENT, 1 / 4f, 1f); + else + playSound(SoundEvents.CREEPER_HURT, 1 / 4f, 3f); + } + if (value == phase + step / 3) + playSound(SoundEvents.CHEST_CLOSE, 1 / 16f, 2f); + + } + + } + + return; + } + } + + public void startAnimation(Animation animation) { + animationType = animation; + if (animation != null && CuckooClockBlock.containsSurprise(getBlockState())) + animationType = Animation.SURPRISE; + animationProgress.startWithValue(0); + sendAnimationUpdate = true; + + if (animation == Animation.CREEPER) + awardIfNear(AllAdvancements.CUCKOO_CLOCK, 32); + + sendData(); + } + + public void moveHands(int hours, int minutes) { + float hourTarget = (float) (360 / 12 * (hours % 12)); + float minuteTarget = (float) (360 / 60 * minutes); + + hourHand.chase(hourTarget, .2f, Chaser.EXP); + minuteHand.chase(minuteTarget, .2f, Chaser.EXP); + + hourHand.tickChaser(); + minuteHand.tickChaser(); + } + + private void playSound(SoundEvent sound, float volume, float pitch) { + Vec3 vec = VecHelper.getCenterOf(worldPosition); + level.playLocalSound(vec.x, vec.y, vec.z, sound, SoundSource.BLOCKS, volume, pitch, false); + } +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/clock/CuckooClockRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/clock/CuckooClockRenderer.java new file mode 100644 index 000000000..65dbffb31 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/clock/CuckooClockRenderer.java @@ -0,0 +1,119 @@ +package com.simibubi.create.content.kinetics.clock; + +import com.jozufozu.flywheel.core.PartialModel; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.content.kinetics.clock.CuckooClockBlockEntity.Animation; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.AngleHelper; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; +import net.minecraft.world.level.block.state.BlockState; + +public class CuckooClockRenderer extends KineticBlockEntityRenderer { + + public CuckooClockRenderer(BlockEntityRendererProvider.Context context) { + super(context); + } + + @Override + protected void renderSafe(CuckooClockBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + super.renderSafe(be, partialTicks, ms, buffer, light, overlay); + if (!(be instanceof CuckooClockBlockEntity)) + return; + + BlockState blockState = be.getBlockState(); + Direction direction = blockState.getValue(CuckooClockBlock.HORIZONTAL_FACING); + + VertexConsumer vb = buffer.getBuffer(RenderType.solid()); + + // Render Hands + SuperByteBuffer hourHand = CachedBufferer.partial(AllPartialModels.CUCKOO_HOUR_HAND, blockState); + SuperByteBuffer minuteHand = CachedBufferer.partial(AllPartialModels.CUCKOO_MINUTE_HAND, blockState); + float hourAngle = be.hourHand.getValue(partialTicks); + float minuteAngle = be.minuteHand.getValue(partialTicks); + rotateHand(hourHand, hourAngle, direction).light(light) + .renderInto(ms, vb); + rotateHand(minuteHand, minuteAngle, direction).light(light) + .renderInto(ms, vb); + + // Doors + SuperByteBuffer leftDoor = CachedBufferer.partial(AllPartialModels.CUCKOO_LEFT_DOOR, blockState); + SuperByteBuffer rightDoor = CachedBufferer.partial(AllPartialModels.CUCKOO_RIGHT_DOOR, blockState); + float angle = 0; + float offset = 0; + + if (be.animationType != null) { + float value = be.animationProgress.getValue(partialTicks); + int step = be.animationType == Animation.SURPRISE ? 3 : 15; + for (int phase = 30; phase <= 60; phase += step) { + float local = value - phase; + if (local < -step / 3) + continue; + else if (local < 0) + angle = Mth.lerp(((value - (phase - 5)) / 5), 0, 135); + else if (local < step / 3) + angle = 135; + else if (local < 2 * step / 3) + angle = Mth.lerp(((value - (phase + 5)) / 5), 135, 0); + + } + } + + rotateDoor(leftDoor, angle, true, direction).light(light) + .renderInto(ms, vb); + rotateDoor(rightDoor, angle, false, direction).light(light) + .renderInto(ms, vb); + + // Figure + if (be.animationType != Animation.NONE) { + offset = -(angle / 135) * 1 / 2f + 10 / 16f; + PartialModel partialModel = (be.animationType == Animation.PIG ? AllPartialModels.CUCKOO_PIG : AllPartialModels.CUCKOO_CREEPER); + SuperByteBuffer figure = + CachedBufferer.partial(partialModel, blockState); + figure.rotateCentered(Direction.UP, AngleHelper.rad(AngleHelper.horizontalAngle(direction.getCounterClockWise()))); + figure.translate(offset, 0, 0); + figure.light(light) + .renderInto(ms, vb); + } + + } + + @Override + protected SuperByteBuffer getRotatedModel(CuckooClockBlockEntity be, BlockState state) { + return CachedBufferer.partialFacing(AllPartialModels.SHAFT_HALF, state, state + .getValue(CuckooClockBlock.HORIZONTAL_FACING) + .getOpposite()); + } + + private SuperByteBuffer rotateHand(SuperByteBuffer buffer, float angle, Direction facing) { + float pivotX = 2 / 16f; + float pivotY = 6 / 16f; + float pivotZ = 8 / 16f; + buffer.rotateCentered(Direction.UP, AngleHelper.rad(AngleHelper.horizontalAngle(facing.getCounterClockWise()))); + buffer.translate(pivotX, pivotY, pivotZ); + buffer.rotate(Direction.EAST, AngleHelper.rad(angle)); + buffer.translate(-pivotX, -pivotY, -pivotZ); + return buffer; + } + + private SuperByteBuffer rotateDoor(SuperByteBuffer buffer, float angle, boolean left, Direction facing) { + float pivotX = 2 / 16f; + float pivotY = 0; + float pivotZ = (left ? 6 : 10) / 16f; + buffer.rotateCentered(Direction.UP, AngleHelper.rad(AngleHelper.horizontalAngle(facing.getCounterClockWise()))); + buffer.translate(pivotX, pivotY, pivotZ); + buffer.rotate(Direction.UP, AngleHelper.rad(angle) * (left ? -1 : 1)); + buffer.translate(-pivotX, -pivotY, -pivotZ); + return buffer; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/ConnectedInputHandler.java b/src/main/java/com/simibubi/create/content/kinetics/crafter/ConnectedInputHandler.java similarity index 90% rename from src/main/java/com/simibubi/create/content/contraptions/components/crafter/ConnectedInputHandler.java rename to src/main/java/com/simibubi/create/content/kinetics/crafter/ConnectedInputHandler.java index 36a6c2d7c..9f21379fb 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/ConnectedInputHandler.java +++ b/src/main/java/com/simibubi/create/content/kinetics/crafter/ConnectedInputHandler.java @@ -1,6 +1,6 @@ -package com.simibubi.create.content.contraptions.components.crafter; +package com.simibubi.create.content.kinetics.crafter; -import static com.simibubi.create.content.contraptions.base.HorizontalKineticBlock.HORIZONTAL_FACING; +import static com.simibubi.create.content.kinetics.base.HorizontalKineticBlock.HORIZONTAL_FACING; import java.util.ArrayList; import java.util.Arrays; @@ -53,8 +53,8 @@ public class ConnectedInputHandler { } public static void toggleConnection(Level world, BlockPos pos, BlockPos pos2) { - MechanicalCrafterTileEntity crafter1 = CrafterHelper.getCrafter(world, pos); - MechanicalCrafterTileEntity crafter2 = CrafterHelper.getCrafter(world, pos2); + MechanicalCrafterBlockEntity crafter1 = CrafterHelper.getCrafter(world, pos); + MechanicalCrafterBlockEntity crafter2 = CrafterHelper.getCrafter(world, pos2); if (crafter1 == null || crafter2 == null) return; @@ -65,7 +65,7 @@ public class ConnectedInputHandler { .offset(crafter2.input.data.get(0)); if (controllerPos1.equals(controllerPos2)) { - MechanicalCrafterTileEntity controller = CrafterHelper.getCrafter(world, controllerPos1); + MechanicalCrafterBlockEntity controller = CrafterHelper.getCrafter(world, controllerPos1); Set positions = controller.input.data.stream() .map(controllerPos1::offset) @@ -114,7 +114,7 @@ public class ConnectedInputHandler { crafter2.connectivityChanged(); } - public static void initAndAddAll(Level world, MechanicalCrafterTileEntity crafter, Collection positions) { + public static void initAndAddAll(Level world, MechanicalCrafterBlockEntity crafter, Collection positions) { crafter.input = new ConnectedInput(); positions.forEach(splitPos -> { modifyAndUpdate(world, splitPos, input -> { @@ -124,8 +124,8 @@ public class ConnectedInputHandler { }); } - public static void connectControllers(Level world, MechanicalCrafterTileEntity crafter1, - MechanicalCrafterTileEntity crafter2) { + public static void connectControllers(Level world, MechanicalCrafterBlockEntity crafter1, + MechanicalCrafterBlockEntity crafter2) { crafter1.input.data.forEach(offset -> { BlockPos connectedPos = crafter1.getBlockPos() @@ -150,11 +150,11 @@ public class ConnectedInputHandler { } private static void modifyAndUpdate(Level world, BlockPos pos, Consumer callback) { - BlockEntity te = world.getBlockEntity(pos); - if (!(te instanceof MechanicalCrafterTileEntity)) + BlockEntity blockEntity = world.getBlockEntity(pos); + if (!(blockEntity instanceof MechanicalCrafterBlockEntity)) return; - MechanicalCrafterTileEntity crafter = (MechanicalCrafterTileEntity) te; + MechanicalCrafterBlockEntity crafter = (MechanicalCrafterBlockEntity) blockEntity; callback.accept(crafter.input); crafter.setChanged(); crafter.connectivityChanged(); diff --git a/src/main/java/com/simibubi/create/content/kinetics/crafter/CrafterCTBehaviour.java b/src/main/java/com/simibubi/create/content/kinetics/crafter/CrafterCTBehaviour.java new file mode 100644 index 000000000..b6a7758ca --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/crafter/CrafterCTBehaviour.java @@ -0,0 +1,57 @@ +package com.simibubi.create.content.kinetics.crafter; + +import static com.simibubi.create.content.kinetics.base.HorizontalKineticBlock.HORIZONTAL_FACING; + +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.AllSpriteShifts; +import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry; +import com.simibubi.create.foundation.block.connected.ConnectedTextureBehaviour; + +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.state.BlockState; + +public class CrafterCTBehaviour extends ConnectedTextureBehaviour.Base { + + @Override + public boolean connectsTo(BlockState state, BlockState other, BlockAndTintGetter reader, BlockPos pos, BlockPos otherPos, + Direction face) { + if (state.getBlock() != other.getBlock()) + return false; + if (state.getValue(HORIZONTAL_FACING) != other.getValue(HORIZONTAL_FACING)) + return false; + return CrafterHelper.areCraftersConnected(reader, pos, otherPos); + } + + @Override + protected boolean reverseUVs(BlockState state, Direction direction) { + if (!direction.getAxis() + .isVertical()) + return false; + Direction facing = state.getValue(HORIZONTAL_FACING); + if (facing.getAxis() == direction.getAxis()) + return false; + + boolean isNegative = facing.getAxisDirection() == AxisDirection.NEGATIVE; + if (direction == Direction.DOWN && facing.getAxis() == Axis.Z) + return !isNegative; + return isNegative; + } + + @Override + public CTSpriteShiftEntry getShift(BlockState state, Direction direction, @Nullable TextureAtlasSprite sprite) { + Direction facing = state.getValue(HORIZONTAL_FACING); + boolean isFront = facing.getAxis() == direction.getAxis(); + boolean isVertical = direction.getAxis() + .isVertical(); + boolean facingX = facing.getAxis() == Axis.X; + return isFront ? AllSpriteShifts.BRASS_CASING + : isVertical && !facingX ? AllSpriteShifts.CRAFTER_OTHERSIDE : AllSpriteShifts.CRAFTER_SIDE; + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/crafter/CrafterHelper.java b/src/main/java/com/simibubi/create/content/kinetics/crafter/CrafterHelper.java new file mode 100644 index 000000000..54c417661 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/crafter/CrafterHelper.java @@ -0,0 +1,42 @@ +package com.simibubi.create.content.kinetics.crafter; + +import com.simibubi.create.content.kinetics.crafter.ConnectedInputHandler.ConnectedInput; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.entity.BlockEntity; + +public class CrafterHelper { + + public static MechanicalCrafterBlockEntity getCrafter(BlockAndTintGetter reader, BlockPos pos) { + BlockEntity blockEntity = reader.getBlockEntity(pos); + if (!(blockEntity instanceof MechanicalCrafterBlockEntity)) + return null; + return (MechanicalCrafterBlockEntity) blockEntity; + } + + public static ConnectedInputHandler.ConnectedInput getInput(BlockAndTintGetter reader, BlockPos pos) { + MechanicalCrafterBlockEntity crafter = getCrafter(reader, pos); + return crafter == null ? null : crafter.input; + } + + public static boolean areCraftersConnected(BlockAndTintGetter reader, BlockPos pos, BlockPos otherPos) { + ConnectedInput input1 = getInput(reader, pos); + ConnectedInput input2 = getInput(reader, otherPos); + + if (input1 == null || input2 == null) + return false; + if (input1.data.isEmpty() || input2.data.isEmpty()) + return false; + try { + if (pos.offset(input1.data.get(0)) + .equals(otherPos.offset(input2.data.get(0)))) + return true; + } catch (IndexOutOfBoundsException e) { + // race condition. data somehow becomes empty between the last 2 if statements + } + + return false; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterBlock.java b/src/main/java/com/simibubi/create/content/kinetics/crafter/MechanicalCrafterBlock.java similarity index 85% rename from src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterBlock.java rename to src/main/java/com/simibubi/create/content/kinetics/crafter/MechanicalCrafterBlock.java index 65c3c894d..34e6f4814 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/crafter/MechanicalCrafterBlock.java @@ -1,16 +1,16 @@ -package com.simibubi.create.content.contraptions.components.crafter; +package com.simibubi.create.content.kinetics.crafter; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.HorizontalKineticBlock; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.components.crafter.ConnectedInputHandler.ConnectedInput; -import com.simibubi.create.content.contraptions.components.crafter.MechanicalCrafterTileEntity.Phase; -import com.simibubi.create.content.contraptions.relays.elementary.ICogWheel; -import com.simibubi.create.foundation.block.ITE; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.inventory.InvManipulationBehaviour; +import com.simibubi.create.content.kinetics.base.HorizontalKineticBlock; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.crafter.ConnectedInputHandler.ConnectedInput; +import com.simibubi.create.content.kinetics.crafter.MechanicalCrafterBlockEntity.Phase; +import com.simibubi.create.content.kinetics.simpleRelays.ICogWheel; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.inventory.InvManipulationBehaviour; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Pointing; @@ -42,7 +42,7 @@ import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.items.ItemStackHandler; public class MechanicalCrafterBlock extends HorizontalKineticBlock - implements ITE, ICogWheel { + implements IBE, ICogWheel { public static final EnumProperty POINTING = EnumProperty.create("pointing", Pointing.class); @@ -89,14 +89,14 @@ public class MechanicalCrafterBlock extends HorizontalKineticBlock public void onRemove(BlockState state, Level worldIn, BlockPos pos, BlockState newState, boolean isMoving) { if (state.getBlock() == newState.getBlock()) { if (getTargetDirection(state) != getTargetDirection(newState)) { - MechanicalCrafterTileEntity crafter = CrafterHelper.getCrafter(worldIn, pos); + MechanicalCrafterBlockEntity crafter = CrafterHelper.getCrafter(worldIn, pos); if (crafter != null) crafter.blockChanged(); } } if (state.hasBlockEntity() && !state.is(newState.getBlock())) { - MechanicalCrafterTileEntity crafter = CrafterHelper.getCrafter(worldIn, pos); + MechanicalCrafterBlockEntity crafter = CrafterHelper.getCrafter(worldIn, pos); if (crafter != null) { if (crafter.covered) Block.popResource(worldIn, pos, AllItems.CRAFTER_SLOT_COVER.asStack()); @@ -145,7 +145,7 @@ public class MechanicalCrafterBlock extends HorizontalKineticBlock public InteractionResult onWrenched(BlockState state, UseOnContext context) { if (context.getClickedFace() == state.getValue(HORIZONTAL_FACING)) { if (!context.getLevel().isClientSide) - KineticTileEntity.switchToBlockState(context.getLevel(), context.getClickedPos(), + KineticBlockEntity.switchToBlockState(context.getLevel(), context.getClickedPos(), state.cycle(POINTING)); return InteractionResult.SUCCESS; } @@ -156,8 +156,8 @@ public class MechanicalCrafterBlock extends HorizontalKineticBlock @Override public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, BlockHitResult hit) { - BlockEntity te = worldIn.getBlockEntity(pos); - if (!(te instanceof MechanicalCrafterTileEntity crafter)) + BlockEntity blockEntity = worldIn.getBlockEntity(pos); + if (!(blockEntity instanceof MechanicalCrafterBlockEntity crafter)) return InteractionResult.PASS; ItemStack heldItem = player.getItemInHand(handIn); @@ -236,7 +236,7 @@ public class MechanicalCrafterBlock extends HorizontalKineticBlock @Override public void neighborChanged(BlockState state, Level worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, boolean isMoving) { - InvManipulationBehaviour behaviour = TileEntityBehaviour.get(worldIn, pos, InvManipulationBehaviour.TYPE); + InvManipulationBehaviour behaviour = BlockEntityBehaviour.get(worldIn, pos, InvManipulationBehaviour.TYPE); if (behaviour != null) behaviour.onNeighborChanged(fromPos); } @@ -279,13 +279,13 @@ public class MechanicalCrafterBlock extends HorizontalKineticBlock } @Override - public Class getTileEntityClass() { - return MechanicalCrafterTileEntity.class; + public Class getBlockEntityClass() { + return MechanicalCrafterBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.MECHANICAL_CRAFTER.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.MECHANICAL_CRAFTER.get(); } } diff --git a/src/main/java/com/simibubi/create/content/kinetics/crafter/MechanicalCrafterBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/crafter/MechanicalCrafterBlockEntity.java new file mode 100644 index 000000000..4dc940a64 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/crafter/MechanicalCrafterBlockEntity.java @@ -0,0 +1,542 @@ +package com.simibubi.create.content.kinetics.crafter; + +import static com.simibubi.create.content.kinetics.base.HorizontalKineticBlock.HORIZONTAL_FACING; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Map.Entry; + +import org.apache.commons.lang3.tuple.Pair; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllItems; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.belt.behaviour.DirectBeltInputBehaviour; +import com.simibubi.create.content.kinetics.crafter.ConnectedInputHandler.ConnectedInput; +import com.simibubi.create.content.kinetics.crafter.RecipeGridHandler.GroupedItems; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.edgeInteraction.EdgeInteractionBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.inventory.InvManipulationBehaviour; +import com.simibubi.create.foundation.item.SmartInventory; +import com.simibubi.create.foundation.utility.BlockFace; +import com.simibubi.create.foundation.utility.Pointing; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.particles.ItemParticleOption; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.items.IItemHandler; + +public class MechanicalCrafterBlockEntity extends KineticBlockEntity { + + enum Phase { + IDLE, ACCEPTING, ASSEMBLING, EXPORTING, WAITING, CRAFTING, INSERTING; + } + + public static class Inventory extends SmartInventory { + + private MechanicalCrafterBlockEntity blockEntity; + + public Inventory(MechanicalCrafterBlockEntity blockEntity) { + super(1, blockEntity, 1, false); + this.blockEntity = blockEntity; + forbidExtraction(); + whenContentsChanged(slot -> { + if (getItem(slot).isEmpty()) + return; + if (blockEntity.phase == Phase.IDLE) + blockEntity.checkCompletedRecipe(false); + }); + } + + @Override + public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) { + if (blockEntity.phase != Phase.IDLE) + return stack; + if (blockEntity.covered) + return stack; + ItemStack insertItem = super.insertItem(slot, stack, simulate); + if (insertItem.getCount() != stack.getCount() && !simulate) + blockEntity.getLevel() + .playSound(null, blockEntity.getBlockPos(), SoundEvents.ITEM_FRAME_ADD_ITEM, SoundSource.BLOCKS, .25f, .5f); + return insertItem; + } + + } + + protected Inventory inventory; + protected GroupedItems groupedItems = new GroupedItems(); + protected ConnectedInput input = new ConnectedInput(); + protected LazyOptional invSupplier = + LazyOptional.of(() -> input.getItemHandler(level, worldPosition)); + protected boolean reRender; + protected Phase phase; + protected int countDown; + protected boolean covered; + protected boolean wasPoweredBefore; + + protected GroupedItems groupedItemsBeforeCraft; // for rendering on client + private InvManipulationBehaviour inserting; + private EdgeInteractionBehaviour connectivity; + + private ItemStack scriptedResult = ItemStack.EMPTY; + + public MechanicalCrafterBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + setLazyTickRate(20); + phase = Phase.IDLE; + groupedItemsBeforeCraft = new GroupedItems(); + inventory = new Inventory(this); + + // Does not get serialized due to active checking in tick + wasPoweredBefore = true; + } + + @Override + public void addBehaviours(List behaviours) { + super.addBehaviours(behaviours); + inserting = new InvManipulationBehaviour(this, this::getTargetFace); + connectivity = new EdgeInteractionBehaviour(this, ConnectedInputHandler::toggleConnection) + .connectivity(ConnectedInputHandler::shouldConnect) + .require(AllItems.WRENCH.get()); + behaviours.add(inserting); + behaviours.add(connectivity); + registerAwardables(behaviours, AllAdvancements.CRAFTER, AllAdvancements.CRAFTER_LAZY); + } + + @Override + public void onSpeedChanged(float previousSpeed) { + super.onSpeedChanged(previousSpeed); + if (!Mth.equal(getSpeed(), 0)) { + award(AllAdvancements.CRAFTER); + if (Math.abs(getSpeed()) < 5) + award(AllAdvancements.CRAFTER_LAZY); + } + } + + public void blockChanged() { + removeBehaviour(InvManipulationBehaviour.TYPE); + inserting = new InvManipulationBehaviour(this, this::getTargetFace); + attachBehaviourLate(inserting); + } + + public BlockFace getTargetFace(Level world, BlockPos pos, BlockState state) { + return new BlockFace(pos, MechanicalCrafterBlock.getTargetDirection(state)); + } + + public Direction getTargetDirection() { + return MechanicalCrafterBlock.getTargetDirection(getBlockState()); + } + + @Override + public void writeSafe(CompoundTag compound) { + super.writeSafe(compound); + if (input == null) + return; + + CompoundTag inputNBT = new CompoundTag(); + input.write(inputNBT); + compound.put("ConnectedInput", inputNBT); + } + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + compound.put("Inventory", inventory.serializeNBT()); + + CompoundTag inputNBT = new CompoundTag(); + input.write(inputNBT); + compound.put("ConnectedInput", inputNBT); + + CompoundTag groupedItemsNBT = new CompoundTag(); + groupedItems.write(groupedItemsNBT); + compound.put("GroupedItems", groupedItemsNBT); + + compound.putString("Phase", phase.name()); + compound.putInt("CountDown", countDown); + compound.putBoolean("Cover", covered); + + super.write(compound, clientPacket); + + if (clientPacket && reRender) { + compound.putBoolean("Redraw", true); + reRender = false; + } + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + Phase phaseBefore = phase; + GroupedItems before = this.groupedItems; + + inventory.deserializeNBT(compound.getCompound("Inventory")); + input.read(compound.getCompound("ConnectedInput")); + groupedItems = GroupedItems.read(compound.getCompound("GroupedItems")); + phase = Phase.IDLE; + String name = compound.getString("Phase"); + for (Phase phase : Phase.values()) + if (phase.name() + .equals(name)) + this.phase = phase; + countDown = compound.getInt("CountDown"); + covered = compound.getBoolean("Cover"); + super.read(compound, clientPacket); + if (!clientPacket) + return; + if (compound.contains("Redraw")) + level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 16); + if (phaseBefore != phase && phase == Phase.CRAFTING) + groupedItemsBeforeCraft = before; + if (phaseBefore == Phase.EXPORTING && phase == Phase.WAITING) { + Direction facing = getBlockState().getValue(MechanicalCrafterBlock.HORIZONTAL_FACING); + Vec3 vec = Vec3.atLowerCornerOf(facing.getNormal()) + .scale(.75) + .add(VecHelper.getCenterOf(worldPosition)); + Direction targetDirection = MechanicalCrafterBlock.getTargetDirection(getBlockState()); + vec = vec.add(Vec3.atLowerCornerOf(targetDirection.getNormal()) + .scale(1)); + level.addParticle(ParticleTypes.CRIT, vec.x, vec.y, vec.z, 0, 0, 0); + } + } + + @Override + public void invalidate() { + super.invalidate(); + invSupplier.invalidate(); + } + + public int getCountDownSpeed() { + if (getSpeed() == 0) + return 0; + return Mth.clamp((int) Math.abs(getSpeed()), 4, 250); + } + + @Override + public void tick() { + super.tick(); + + if (phase == Phase.ACCEPTING) + return; + + boolean onClient = level.isClientSide; + boolean runLogic = !onClient || isVirtual(); + + if (wasPoweredBefore != level.hasNeighborSignal(worldPosition)) { + wasPoweredBefore = level.hasNeighborSignal(worldPosition); + if (wasPoweredBefore) { + if (!runLogic) + return; + checkCompletedRecipe(true); + } + } + + if (phase == Phase.ASSEMBLING) { + countDown -= getCountDownSpeed(); + if (countDown < 0) { + countDown = 0; + if (!runLogic) + return; + if (RecipeGridHandler.getTargetingCrafter(this) != null) { + phase = Phase.EXPORTING; + countDown = 1000; + sendData(); + return; + } + + ItemStack result = + isVirtual() ? scriptedResult : RecipeGridHandler.tryToApplyRecipe(level, groupedItems); + + if (result != null) { + List containers = new ArrayList<>(); + groupedItems.grid.values() + .forEach(stack -> { + if (stack.hasCraftingRemainingItem()) + containers.add(stack.getCraftingRemainingItem() + .copy()); + }); + + if (isVirtual()) + groupedItemsBeforeCraft = groupedItems; + + groupedItems = new GroupedItems(result); + for (int i = 0; i < containers.size(); i++) { + ItemStack stack = containers.get(i); + GroupedItems container = new GroupedItems(); + container.grid.put(Pair.of(i, 0), stack); + container.mergeOnto(groupedItems, Pointing.LEFT); + } + + phase = Phase.CRAFTING; + countDown = 2000; + sendData(); + return; + } + ejectWholeGrid(); + return; + } + } + + if (phase == Phase.EXPORTING) { + countDown -= getCountDownSpeed(); + + if (countDown < 0) { + countDown = 0; + if (!runLogic) + return; + + MechanicalCrafterBlockEntity targetingCrafter = RecipeGridHandler.getTargetingCrafter(this); + if (targetingCrafter == null) { + ejectWholeGrid(); + return; + } + + Pointing pointing = getBlockState().getValue(MechanicalCrafterBlock.POINTING); + groupedItems.mergeOnto(targetingCrafter.groupedItems, pointing); + groupedItems = new GroupedItems(); + + float pitch = targetingCrafter.groupedItems.grid.size() * 1 / 16f + .5f; + AllSoundEvents.CRAFTER_CLICK.playOnServer(level, worldPosition, 1, pitch); + + phase = Phase.WAITING; + countDown = 0; + sendData(); + targetingCrafter.continueIfAllPrecedingFinished(); + targetingCrafter.sendData(); + return; + } + } + + if (phase == Phase.CRAFTING) { + + if (onClient) { + Direction facing = getBlockState().getValue(MechanicalCrafterBlock.HORIZONTAL_FACING); + float progress = countDown / 2000f; + Vec3 facingVec = Vec3.atLowerCornerOf(facing.getNormal()); + Vec3 vec = facingVec.scale(.65) + .add(VecHelper.getCenterOf(worldPosition)); + Vec3 offset = VecHelper.offsetRandomly(Vec3.ZERO, level.random, .125f) + .multiply(VecHelper.axisAlingedPlaneOf(facingVec)) + .normalize() + .scale(progress * .5f) + .add(vec); + if (progress > .5f) + level.addParticle(ParticleTypes.CRIT, offset.x, offset.y, offset.z, 0, 0, 0); + + if (!groupedItemsBeforeCraft.grid.isEmpty() && progress < .5f) { + if (groupedItems.grid.containsKey(Pair.of(0, 0))) { + ItemStack stack = groupedItems.grid.get(Pair.of(0, 0)); + groupedItemsBeforeCraft = new GroupedItems(); + + for (int i = 0; i < 10; i++) { + Vec3 randVec = VecHelper.offsetRandomly(Vec3.ZERO, level.random, .125f) + .multiply(VecHelper.axisAlingedPlaneOf(facingVec)) + .normalize() + .scale(.25f); + Vec3 offset2 = randVec.add(vec); + randVec = randVec.scale(.35f); + level.addParticle(new ItemParticleOption(ParticleTypes.ITEM, stack), offset2.x, offset2.y, + offset2.z, randVec.x, randVec.y, randVec.z); + } + } + } + } + + int prev = countDown; + countDown -= getCountDownSpeed(); + + if (countDown < 1000 && prev >= 1000) { + AllSoundEvents.CRAFTER_CLICK.playOnServer(level, worldPosition, 1, 2); + AllSoundEvents.CRAFTER_CRAFT.playOnServer(level, worldPosition); + } + + if (countDown < 0) { + countDown = 0; + if (!runLogic) + return; + tryInsert(); + return; + } + } + + if (phase == Phase.INSERTING) { + if (runLogic && isTargetingBelt()) + tryInsert(); + return; + } + } + + protected boolean isTargetingBelt() { + DirectBeltInputBehaviour behaviour = getTargetingBelt(); + return behaviour != null && behaviour.canInsertFromSide(getTargetDirection()); + } + + protected DirectBeltInputBehaviour getTargetingBelt() { + BlockPos targetPos = worldPosition.relative(getTargetDirection()); + return BlockEntityBehaviour.get(level, targetPos, DirectBeltInputBehaviour.TYPE); + } + + public void tryInsert() { + if (!inserting.hasInventory() && !isTargetingBelt()) { + ejectWholeGrid(); + return; + } + + boolean chagedPhase = phase != Phase.INSERTING; + final List> inserted = new LinkedList<>(); + + DirectBeltInputBehaviour behaviour = getTargetingBelt(); + for (Entry, ItemStack> entry : groupedItems.grid.entrySet()) { + Pair pair = entry.getKey(); + ItemStack stack = entry.getValue(); + BlockFace face = getTargetFace(level, worldPosition, getBlockState()); + + ItemStack remainder = behaviour == null ? inserting.insert(stack.copy()) + : behaviour.handleInsertion(stack, face.getFace(), false); + if (!remainder.isEmpty()) { + stack.setCount(remainder.getCount()); + continue; + } + + inserted.add(pair); + } + + inserted.forEach(groupedItems.grid::remove); + if (groupedItems.grid.isEmpty()) + ejectWholeGrid(); + else + phase = Phase.INSERTING; + if (!inserted.isEmpty() || chagedPhase) + sendData(); + } + + public void ejectWholeGrid() { + List chain = RecipeGridHandler.getAllCraftersOfChain(this); + if (chain == null) + return; + chain.forEach(MechanicalCrafterBlockEntity::eject); + } + + public void eject() { + BlockState blockState = getBlockState(); + boolean present = AllBlocks.MECHANICAL_CRAFTER.has(blockState); + Vec3 vec = present ? Vec3.atLowerCornerOf(blockState.getValue(HORIZONTAL_FACING) + .getNormal()) + .scale(.75f) : Vec3.ZERO; + Vec3 ejectPos = VecHelper.getCenterOf(worldPosition) + .add(vec); + groupedItems.grid.forEach((pair, stack) -> dropItem(ejectPos, stack)); + if (!inventory.getItem(0) + .isEmpty()) + dropItem(ejectPos, inventory.getItem(0)); + phase = Phase.IDLE; + groupedItems = new GroupedItems(); + inventory.setStackInSlot(0, ItemStack.EMPTY); + sendData(); + } + + public void dropItem(Vec3 ejectPos, ItemStack stack) { + ItemEntity itemEntity = new ItemEntity(level, ejectPos.x, ejectPos.y, ejectPos.z, stack); + itemEntity.setDefaultPickUpDelay(); + level.addFreshEntity(itemEntity); + } + + @Override + public void lazyTick() { + super.lazyTick(); + if (level.isClientSide && !isVirtual()) + return; + if (phase == Phase.IDLE && craftingItemPresent()) + checkCompletedRecipe(false); + if (phase == Phase.INSERTING) + tryInsert(); + } + + public boolean craftingItemPresent() { + return !inventory.getItem(0) + .isEmpty(); + } + + public boolean craftingItemOrCoverPresent() { + return !inventory.getItem(0) + .isEmpty() || covered; + } + + protected void checkCompletedRecipe(boolean poweredStart) { + if (getSpeed() == 0) + return; + if (level.isClientSide && !isVirtual()) + return; + List chain = RecipeGridHandler.getAllCraftersOfChainIf(this, + poweredStart ? MechanicalCrafterBlockEntity::craftingItemPresent + : MechanicalCrafterBlockEntity::craftingItemOrCoverPresent, + poweredStart); + if (chain == null) + return; + chain.forEach(MechanicalCrafterBlockEntity::begin); + } + + protected void begin() { + phase = Phase.ACCEPTING; + groupedItems = new GroupedItems(inventory.getItem(0)); + inventory.setStackInSlot(0, ItemStack.EMPTY); + if (RecipeGridHandler.getPrecedingCrafters(this) + .isEmpty()) { + phase = Phase.ASSEMBLING; + countDown = 500; + } + sendData(); + } + + protected void continueIfAllPrecedingFinished() { + List preceding = RecipeGridHandler.getPrecedingCrafters(this); + if (preceding == null) { + ejectWholeGrid(); + return; + } + + for (MechanicalCrafterBlockEntity blockEntity : preceding) + if (blockEntity.phase != Phase.WAITING) + return; + + phase = Phase.ASSEMBLING; + countDown = Math.max(100, getCountDownSpeed() + 1); + } + + @Override + public LazyOptional getCapability(Capability cap, Direction side) { + if (isItemHandlerCap(cap)) + return invSupplier.cast(); + return super.getCapability(cap, side); + } + + public void connectivityChanged() { + reRender = true; + sendData(); + invSupplier.invalidate(); + invSupplier = LazyOptional.of(() -> input.getItemHandler(level, worldPosition)); + } + + public Inventory getInventory() { + return inventory; + } + + public void setScriptedResult(ItemStack scriptedResult) { + this.scriptedResult = scriptedResult; + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/crafter/MechanicalCrafterRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/crafter/MechanicalCrafterRenderer.java new file mode 100644 index 000000000..fd0577c14 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/crafter/MechanicalCrafterRenderer.java @@ -0,0 +1,223 @@ +package com.simibubi.create.content.kinetics.crafter; + +import static com.simibubi.create.content.kinetics.base.HorizontalKineticBlock.HORIZONTAL_FACING; +import static com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer.standardKineticRotationTransform; + +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.core.PartialModel; +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.math.Axis; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.AllSpriteShifts; +import com.simibubi.create.content.kinetics.crafter.MechanicalCrafterBlockEntity.Phase; +import com.simibubi.create.content.kinetics.crafter.RecipeGridHandler.GroupedItems; +import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.Pointing; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.block.model.ItemTransforms.TransformType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class MechanicalCrafterRenderer extends SafeBlockEntityRenderer { + + public MechanicalCrafterRenderer(BlockEntityRendererProvider.Context context) { + } + + @Override + protected void renderSafe(MechanicalCrafterBlockEntity be, float partialTicks, PoseStack ms, + MultiBufferSource buffer, int light, int overlay) { + ms.pushPose(); + Direction facing = be.getBlockState() + .getValue(HORIZONTAL_FACING); + Vec3 vec = Vec3.atLowerCornerOf(facing.getNormal()) + .scale(.58) + .add(.5, .5, .5); + + if (be.phase == Phase.EXPORTING) { + Direction targetDirection = MechanicalCrafterBlock.getTargetDirection(be.getBlockState()); + float progress = + Mth.clamp((1000 - be.countDown + be.getCountDownSpeed() * partialTicks) / 1000f, 0, 1); + vec = vec.add(Vec3.atLowerCornerOf(targetDirection.getNormal()) + .scale(progress * .75f)); + } + + ms.translate(vec.x, vec.y, vec.z); + ms.scale(1 / 2f, 1 / 2f, 1 / 2f); + float yRot = AngleHelper.horizontalAngle(facing); + ms.mulPose(Axis.YP.rotationDegrees(yRot)); + renderItems(be, partialTicks, ms, buffer, light, overlay); + ms.popPose(); + + renderFast(be, partialTicks, ms, buffer, light); + } + + public void renderItems(MechanicalCrafterBlockEntity be, float partialTicks, PoseStack ms, + MultiBufferSource buffer, int light, int overlay) { + if (be.phase == Phase.IDLE) { + ItemStack stack = be.getInventory() + .getItem(0); + if (!stack.isEmpty()) { + ms.pushPose(); + ms.translate(0, 0, -1 / 256f); + ms.mulPose(Axis.YP.rotationDegrees(180)); + Minecraft.getInstance() + .getItemRenderer() + .renderStatic(stack, TransformType.FIXED, light, overlay, ms, buffer, 0); + ms.popPose(); + } + } else { + // render grouped items + GroupedItems items = be.groupedItems; + float distance = .5f; + + ms.pushPose(); + + if (be.phase == Phase.CRAFTING) { + items = be.groupedItemsBeforeCraft; + items.calcStats(); + float progress = + Mth.clamp((2000 - be.countDown + be.getCountDownSpeed() * partialTicks) / 1000f, 0, 1); + float earlyProgress = Mth.clamp(progress * 2, 0, 1); + float lateProgress = Mth.clamp(progress * 2 - 1, 0, 1); + + ms.scale(1 - lateProgress, 1 - lateProgress, 1 - lateProgress); + Vec3 centering = + new Vec3(-items.minX + (-items.width + 1) / 2f, -items.minY + (-items.height + 1) / 2f, 0) + .scale(earlyProgress); + ms.translate(centering.x * .5f, centering.y * .5f, 0); + distance += (-4 * (progress - .5f) * (progress - .5f) + 1) * .25f; + } + + boolean onlyRenderFirst = be.phase == Phase.INSERTING || be.phase == Phase.CRAFTING && be.countDown < 1000; + final float spacing = distance; + items.grid.forEach((pair, stack) -> { + if (onlyRenderFirst && (pair.getLeft() + .intValue() != 0 + || pair.getRight() + .intValue() != 0)) + return; + + ms.pushPose(); + Integer x = pair.getKey(); + Integer y = pair.getValue(); + ms.translate(x * spacing, y * spacing, 0); + + int offset = 0; + if (be.phase == Phase.EXPORTING && be.getBlockState().hasProperty(MechanicalCrafterBlock.POINTING)) { + Pointing value = be.getBlockState().getValue(MechanicalCrafterBlock.POINTING); + offset = value == Pointing.UP ? -1 : value == Pointing.LEFT ? 2 : value == Pointing.RIGHT ? -2 : 1; + } + + TransformStack.cast(ms) + .rotateY(180) + .translate(0, 0, (x + y * 3 + offset * 9) / 1024f ); + Minecraft.getInstance() + .getItemRenderer() + .renderStatic(stack, TransformType.FIXED, light, overlay, ms, buffer, 0); + ms.popPose(); + }); + + ms.popPose(); + + if (be.phase == Phase.CRAFTING) { + items = be.groupedItems; + float progress = + Mth.clamp((1000 - be.countDown + be.getCountDownSpeed() * partialTicks) / 1000f, 0, 1); + float earlyProgress = Mth.clamp(progress * 2, 0, 1); + float lateProgress = Mth.clamp(progress * 2 - 1, 0, 1); + + ms.mulPose(Axis.ZP.rotationDegrees(earlyProgress * 2 * 360)); + float upScaling = earlyProgress * 1.125f; + float downScaling = 1 + (1 - lateProgress) * .125f; + ms.scale(upScaling, upScaling, upScaling); + ms.scale(downScaling, downScaling, downScaling); + + items.grid.forEach((pair, stack) -> { + if (pair.getLeft() + .intValue() != 0 + || pair.getRight() + .intValue() != 0) + return; + ms.pushPose(); + ms.mulPose(Axis.YP.rotationDegrees(180)); + Minecraft.getInstance() + .getItemRenderer() + .renderStatic(stack, TransformType.FIXED, light, overlay, ms, buffer, 0); + ms.popPose(); + }); + } + + } + } + + public void renderFast(MechanicalCrafterBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light) { + BlockState blockState = be.getBlockState(); + VertexConsumer vb = buffer.getBuffer(RenderType.solid()); + + if (!Backend.canUseInstancing(be.getLevel())) { + SuperByteBuffer superBuffer = CachedBufferer.partial(AllPartialModels.SHAFTLESS_COGWHEEL, blockState); + standardKineticRotationTransform(superBuffer, be, light); + superBuffer.rotateCentered(Direction.UP, (float) (blockState.getValue(HORIZONTAL_FACING) + .getAxis() != Direction.Axis.X ? 0 : Math.PI / 2)); + superBuffer.rotateCentered(Direction.EAST, (float) (Math.PI / 2)); + superBuffer.renderInto(ms, vb); + } + + Direction targetDirection = MechanicalCrafterBlock.getTargetDirection(blockState); + BlockPos pos = be.getBlockPos(); + + if ((be.covered || be.phase != Phase.IDLE) && be.phase != Phase.CRAFTING && be.phase != Phase.INSERTING) { + SuperByteBuffer lidBuffer = renderAndTransform(AllPartialModels.MECHANICAL_CRAFTER_LID, blockState); + lidBuffer.light(light) + .renderInto(ms, vb); + } + + if (MechanicalCrafterBlock.isValidTarget(be.getLevel(), pos.relative(targetDirection), blockState)) { + SuperByteBuffer beltBuffer = renderAndTransform(AllPartialModels.MECHANICAL_CRAFTER_BELT, blockState); + SuperByteBuffer beltFrameBuffer = + renderAndTransform(AllPartialModels.MECHANICAL_CRAFTER_BELT_FRAME, blockState); + + if (be.phase == Phase.EXPORTING) { + int textureIndex = (int) ((be.getCountDownSpeed() / 128f * AnimationTickHolder.getTicks())); + beltBuffer.shiftUVtoSheet(AllSpriteShifts.CRAFTER_THINGIES, (textureIndex % 4) / 4f, 0, 1); + } + + beltBuffer.light(light) + .renderInto(ms, vb); + beltFrameBuffer.light(light) + .renderInto(ms, vb); + + } else { + SuperByteBuffer arrowBuffer = renderAndTransform(AllPartialModels.MECHANICAL_CRAFTER_ARROW, blockState); + arrowBuffer.light(light) + .renderInto(ms, vb); + } + + } + + private SuperByteBuffer renderAndTransform(PartialModel renderBlock, BlockState crafterState) { + SuperByteBuffer buffer = CachedBufferer.partial(renderBlock, crafterState); + float xRot = crafterState.getValue(MechanicalCrafterBlock.POINTING) + .getXRotation(); + float yRot = AngleHelper.horizontalAngle(crafterState.getValue(HORIZONTAL_FACING)); + buffer.rotateCentered(Direction.UP, (float) ((yRot + 90) / 180 * Math.PI)); + buffer.rotateCentered(Direction.EAST, (float) ((xRot) / 180 * Math.PI)); + return buffer; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCraftingInventory.java b/src/main/java/com/simibubi/create/content/kinetics/crafter/MechanicalCraftingInventory.java similarity index 85% rename from src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCraftingInventory.java rename to src/main/java/com/simibubi/create/content/kinetics/crafter/MechanicalCraftingInventory.java index 7e228de1e..bb9808fce 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCraftingInventory.java +++ b/src/main/java/com/simibubi/create/content/kinetics/crafter/MechanicalCraftingInventory.java @@ -1,8 +1,8 @@ -package com.simibubi.create.content.contraptions.components.crafter; +package com.simibubi.create.content.kinetics.crafter; import org.apache.commons.lang3.tuple.Pair; -import com.simibubi.create.content.contraptions.components.crafter.RecipeGridHandler.GroupedItems; +import com.simibubi.create.content.kinetics.crafter.RecipeGridHandler.GroupedItems; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCraftingRecipe.java b/src/main/java/com/simibubi/create/content/kinetics/crafter/MechanicalCraftingRecipe.java similarity index 98% rename from src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCraftingRecipe.java rename to src/main/java/com/simibubi/create/content/kinetics/crafter/MechanicalCraftingRecipe.java index 81b38f84f..815cefd99 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCraftingRecipe.java +++ b/src/main/java/com/simibubi/create/content/kinetics/crafter/MechanicalCraftingRecipe.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.crafter; +package com.simibubi.create.content.kinetics.crafter; import com.google.gson.JsonObject; import com.simibubi.create.AllRecipeTypes; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/RecipeGridHandler.java b/src/main/java/com/simibubi/create/content/kinetics/crafter/RecipeGridHandler.java similarity index 75% rename from src/main/java/com/simibubi/create/content/contraptions/components/crafter/RecipeGridHandler.java rename to src/main/java/com/simibubi/create/content/kinetics/crafter/RecipeGridHandler.java index 8f6d69715..45c387b5a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/RecipeGridHandler.java +++ b/src/main/java/com/simibubi/create/content/kinetics/crafter/RecipeGridHandler.java @@ -1,6 +1,6 @@ -package com.simibubi.create.content.contraptions.components.crafter; +package com.simibubi.create.content.kinetics.crafter; -import static com.simibubi.create.content.contraptions.base.HorizontalKineticBlock.HORIZONTAL_FACING; +import static com.simibubi.create.content.kinetics.base.HorizontalKineticBlock.HORIZONTAL_FACING; import java.util.ArrayList; import java.util.HashMap; @@ -15,9 +15,9 @@ import org.apache.commons.lang3.tuple.Pair; import com.google.common.base.Predicates; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllRecipeTypes; -import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Pointing; +import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -34,20 +34,20 @@ import net.minecraft.world.level.block.state.BlockState; public class RecipeGridHandler { - public static List getAllCraftersOfChain(MechanicalCrafterTileEntity root) { + public static List getAllCraftersOfChain(MechanicalCrafterBlockEntity root) { return getAllCraftersOfChainIf(root, Predicates.alwaysTrue()); } - public static List getAllCraftersOfChainIf(MechanicalCrafterTileEntity root, - Predicate test) { + public static List getAllCraftersOfChainIf(MechanicalCrafterBlockEntity root, + Predicate test) { return getAllCraftersOfChainIf(root, test, false); } - public static List getAllCraftersOfChainIf(MechanicalCrafterTileEntity root, - Predicate test, boolean poweredStart) { - List crafters = new ArrayList<>(); - List> frontier = new ArrayList<>(); - Set visited = new HashSet<>(); + public static List getAllCraftersOfChainIf(MechanicalCrafterBlockEntity root, + Predicate test, boolean poweredStart) { + List crafters = new ArrayList<>(); + List> frontier = new ArrayList<>(); + Set visited = new HashSet<>(); frontier.add(Pair.of(root, null)); boolean powered = false; @@ -55,9 +55,9 @@ public class RecipeGridHandler { boolean allEmpty = true; while (!frontier.isEmpty()) { - Pair pair = frontier.remove(0); - MechanicalCrafterTileEntity current = pair.getKey(); - MechanicalCrafterTileEntity last = pair.getValue(); + Pair pair = frontier.remove(0); + MechanicalCrafterBlockEntity current = pair.getKey(); + MechanicalCrafterBlockEntity last = pair.getValue(); if (visited.contains(current)) return null; @@ -72,10 +72,10 @@ public class RecipeGridHandler { crafters.add(current); visited.add(current); - MechanicalCrafterTileEntity target = getTargetingCrafter(current); + MechanicalCrafterBlockEntity target = getTargetingCrafter(current); if (target != last && target != null) frontier.add(Pair.of(target, current)); - for (MechanicalCrafterTileEntity preceding : getPrecedingCrafters(current)) + for (MechanicalCrafterBlockEntity preceding : getPrecedingCrafters(current)) if (preceding != last) frontier.add(Pair.of(preceding, current)); } @@ -83,29 +83,29 @@ public class RecipeGridHandler { return empty && !powered || allEmpty ? null : crafters; } - public static MechanicalCrafterTileEntity getTargetingCrafter(MechanicalCrafterTileEntity crafter) { + public static MechanicalCrafterBlockEntity getTargetingCrafter(MechanicalCrafterBlockEntity crafter) { BlockState state = crafter.getBlockState(); if (!isCrafter(state)) return null; BlockPos targetPos = crafter.getBlockPos() .relative(MechanicalCrafterBlock.getTargetDirection(state)); - MechanicalCrafterTileEntity targetTE = CrafterHelper.getCrafter(crafter.getLevel(), targetPos); - if (targetTE == null) + MechanicalCrafterBlockEntity targetBE = CrafterHelper.getCrafter(crafter.getLevel(), targetPos); + if (targetBE == null) return null; - BlockState targetState = targetTE.getBlockState(); + BlockState targetState = targetBE.getBlockState(); if (!isCrafter(targetState)) return null; if (state.getValue(HORIZONTAL_FACING) != targetState.getValue(HORIZONTAL_FACING)) return null; - return targetTE; + return targetBE; } - public static List getPrecedingCrafters(MechanicalCrafterTileEntity crafter) { + public static List getPrecedingCrafters(MechanicalCrafterBlockEntity crafter) { BlockPos pos = crafter.getBlockPos(); Level world = crafter.getLevel(); - List crafters = new ArrayList<>(); + List crafters = new ArrayList<>(); BlockState blockState = crafter.getBlockState(); if (!isCrafter(blockState)) return crafters; @@ -126,11 +126,11 @@ public class RecipeGridHandler { continue; if (blockFacing != neighbourState.getValue(HORIZONTAL_FACING)) continue; - MechanicalCrafterTileEntity te = CrafterHelper.getCrafter(world, neighbourPos); - if (te == null) + MechanicalCrafterBlockEntity be = CrafterHelper.getCrafter(world, neighbourPos); + if (be == null) continue; - crafters.add(te); + crafters.add(be); } return crafters; @@ -144,7 +144,7 @@ public class RecipeGridHandler { items.calcStats(); CraftingContainer craftinginventory = new MechanicalCraftingInventory(items); ItemStack result = null; - if (AllConfigs.SERVER.recipes.allowRegularCraftingInCrafter.get()) + if (AllConfigs.server().recipes.allowRegularCraftingInCrafter.get()) result = world.getRecipeManager() .getRecipeFor(RecipeType.CRAFTING, craftinginventory, world) .filter(r -> isRecipeAllowed(r, craftinginventory)) @@ -165,7 +165,7 @@ public class RecipeGridHandler { numItems++; } } - if (numItems > AllConfigs.SERVER.recipes.maxFireworkIngredientsInCrafter.get()) { + if (numItems > AllConfigs.server().recipes.maxFireworkIngredientsInCrafter.get()) { return false; } } diff --git a/src/main/java/com/simibubi/create/content/kinetics/crafter/ShaftlessCogwheelInstance.java b/src/main/java/com/simibubi/create/content/kinetics/crafter/ShaftlessCogwheelInstance.java new file mode 100644 index 000000000..4b7e70c45 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/crafter/ShaftlessCogwheelInstance.java @@ -0,0 +1,42 @@ +package com.simibubi.create.content.kinetics.crafter; + +import java.util.function.Supplier; + +import com.jozufozu.flywheel.api.Instancer; +import com.jozufozu.flywheel.api.MaterialManager; +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.base.SingleRotatingInstance; +import com.simibubi.create.content.kinetics.base.flwdata.RotatingData; + +import net.minecraft.core.Direction; + +public class ShaftlessCogwheelInstance extends SingleRotatingInstance { + + public ShaftlessCogwheelInstance(MaterialManager materialManager, KineticBlockEntity blockEntity) { + super(materialManager, blockEntity); + } + + @Override + protected Instancer getModel() { + Direction facing = blockState.getValue(MechanicalCrafterBlock.HORIZONTAL_FACING); + + return getRotatingMaterial().getModel(AllPartialModels.SHAFTLESS_COGWHEEL, blockState, facing, rotateToFace(facing)); + } + + private Supplier rotateToFace(Direction facing) { + return () -> { + PoseStack stack = new PoseStack(); + TransformStack stacker = TransformStack.cast(stack) + .centre(); + + if (facing.getAxis() == Direction.Axis.X) stacker.rotateZ(90); + else if (facing.getAxis() == Direction.Axis.Z) stacker.rotateX(90); + + stacker.unCentre(); + return stack; + }; + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankBlock.java b/src/main/java/com/simibubi/create/content/kinetics/crank/HandCrankBlock.java similarity index 80% rename from src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankBlock.java rename to src/main/java/com/simibubi/create/content/kinetics/crank/HandCrankBlock.java index 96cb2a8ba..ab8dd5da4 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/crank/HandCrankBlock.java @@ -1,15 +1,14 @@ -package com.simibubi.create.content.contraptions.components.crank; +package com.simibubi.create.content.kinetics.crank; -import com.jozufozu.flywheel.core.PartialModel; -import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllItems; import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock; +import com.simibubi.create.content.kinetics.base.DirectionalKineticBlock; import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.block.ProperWaterloggedBlock; -import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.utility.Couple; +import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -32,11 +31,9 @@ import net.minecraft.world.level.pathfinder.PathComputationType; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; public class HandCrankBlock extends DirectionalKineticBlock - implements ITE, ProperWaterloggedBlock { + implements IBE, ProperWaterloggedBlock { public HandCrankBlock(Properties properties) { super(properties); @@ -53,11 +50,6 @@ public class HandCrankBlock extends DirectionalKineticBlock super.createBlockStateDefinition(builder.add(WATERLOGGED)); } - @OnlyIn(Dist.CLIENT) - public PartialModel getRenderedHandle() { - return AllBlockPartials.HAND_CRANK_HANDLE; - } - public int getRotationSpeed() { return 32; } @@ -73,8 +65,10 @@ public class HandCrankBlock extends DirectionalKineticBlock if (player.isSpectator()) return InteractionResult.PASS; - withTileEntityDo(worldIn, pos, te -> te.turn(player.isShiftKeyDown())); - player.causeFoodExhaustion(getRotationSpeed() * AllConfigs.SERVER.kinetics.crankHungerMultiplier.getF()); + withBlockEntityDo(worldIn, pos, be -> be.turn(player.isShiftKeyDown())); + if (!player.getItemInHand(handIn) + .is(AllItems.EXTENDO_GRIP.get())) + player.causeFoodExhaustion(getRotationSpeed() * AllConfigs.server().kinetics.crankHungerMultiplier.getF()); if (player.getFoodData() .getFoodLevel() == 0) @@ -117,14 +111,14 @@ public class HandCrankBlock extends DirectionalKineticBlock } } } - + @Override public BlockState updateShape(BlockState pState, Direction pDirection, BlockState pNeighborState, LevelAccessor pLevel, BlockPos pCurrentPos, BlockPos pNeighborPos) { updateWater(pLevel, pState, pCurrentPos); return pState; } - + @Override public FluidState getFluidState(BlockState pState) { return fluidState(pState); @@ -143,13 +137,13 @@ public class HandCrankBlock extends DirectionalKineticBlock } @Override - public Class getTileEntityClass() { - return HandCrankTileEntity.class; + public Class getBlockEntityClass() { + return HandCrankBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.HAND_CRANK.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.HAND_CRANK.get(); } @Override diff --git a/src/main/java/com/simibubi/create/content/kinetics/crank/HandCrankBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/crank/HandCrankBlockEntity.java new file mode 100644 index 000000000..e4c3f902a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/crank/HandCrankBlockEntity.java @@ -0,0 +1,134 @@ +package com.simibubi.create.content.kinetics.crank; + +import com.jozufozu.flywheel.api.Instancer; +import com.jozufozu.flywheel.api.Material; +import com.jozufozu.flywheel.core.materials.model.ModelData; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.content.kinetics.base.GeneratingKineticBlockEntity; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.AnimationTickHolder; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public class HandCrankBlockEntity extends GeneratingKineticBlockEntity { + + public int inUse; + public boolean backwards; + public float independentAngle; + public float chasingVelocity; + + public HandCrankBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + public void turn(boolean back) { + boolean update = false; + + if (getGeneratedSpeed() == 0 || back != backwards) + update = true; + + inUse = 10; + this.backwards = back; + if (update && !level.isClientSide) + updateGeneratedRotation(); + } + + public float getIndependentAngle(float partialTicks) { + return (independentAngle + partialTicks * chasingVelocity) / 360; + } + + @Override + public float getGeneratedSpeed() { + Block block = getBlockState().getBlock(); + if (!(block instanceof HandCrankBlock)) + return 0; + HandCrankBlock crank = (HandCrankBlock) block; + int speed = (inUse == 0 ? 0 : clockwise() ? -1 : 1) * crank.getRotationSpeed(); + return convertToDirection(speed, getBlockState().getValue(HandCrankBlock.FACING)); + } + + protected boolean clockwise() { + return backwards; + } + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + compound.putInt("InUse", inUse); + compound.putBoolean("Backwards", backwards); + super.write(compound, clientPacket); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + inUse = compound.getInt("InUse"); + backwards = compound.getBoolean("Backwards"); + super.read(compound, clientPacket); + } + + @Override + public void tick() { + super.tick(); + + float actualSpeed = getSpeed(); + chasingVelocity += ((actualSpeed * 10 / 3f) - chasingVelocity) * .25f; + independentAngle += chasingVelocity; + + if (inUse > 0) { + inUse--; + + if (inUse == 0 && !level.isClientSide) { + sequenceContext = null; + updateGeneratedRotation(); + } + } + } + + @OnlyIn(Dist.CLIENT) + public SuperByteBuffer getRenderedHandle() { + BlockState blockState = getBlockState(); + Direction facing = blockState.getOptionalValue(HandCrankBlock.FACING) + .orElse(Direction.UP); + return CachedBufferer.partialFacing(AllPartialModels.HAND_CRANK_HANDLE, blockState, facing.getOpposite()); + } + + @OnlyIn(Dist.CLIENT) + public Instancer getRenderedHandleInstance(Material material) { + BlockState blockState = getBlockState(); + Direction facing = blockState.getOptionalValue(HandCrankBlock.FACING) + .orElse(Direction.UP); + return material.getModel(AllPartialModels.HAND_CRANK_HANDLE, blockState, facing.getOpposite()); + } + + @OnlyIn(Dist.CLIENT) + public boolean shouldRenderShaft() { + return true; + } + + @Override + protected Block getStressConfigKey() { + return AllBlocks.HAND_CRANK.has(getBlockState()) ? AllBlocks.HAND_CRANK.get() + : AllBlocks.COPPER_VALVE_HANDLE.get(); + } + + @Override + @OnlyIn(Dist.CLIENT) + public void tickAudio() { + super.tickAudio(); + if (inUse > 0 && AnimationTickHolder.getTicks() % 10 == 0) { + if (!AllBlocks.HAND_CRANK.has(getBlockState())) + return; + AllSoundEvents.CRANKING.playAt(level, worldPosition, (inUse) / 2.5f, .65f + (10 - inUse) / 10f, true); + } + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/crank/HandCrankInstance.java b/src/main/java/com/simibubi/create/content/kinetics/crank/HandCrankInstance.java new file mode 100644 index 000000000..93b9c83ae --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/crank/HandCrankInstance.java @@ -0,0 +1,72 @@ +package com.simibubi.create.content.kinetics.crank; + +import com.jozufozu.flywheel.api.Instancer; +import com.jozufozu.flywheel.api.MaterialManager; +import com.jozufozu.flywheel.api.instance.DynamicInstance; +import com.jozufozu.flywheel.core.materials.model.ModelData; +import com.simibubi.create.content.kinetics.base.SingleRotatingInstance; +import com.simibubi.create.foundation.utility.AnimationTickHolder; + +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; + +public class HandCrankInstance extends SingleRotatingInstance implements DynamicInstance { + + private ModelData crank; + private Direction facing; + + public HandCrankInstance(MaterialManager modelManager, HandCrankBlockEntity blockEntity) { + super(modelManager, blockEntity); + facing = blockState.getValue(BlockStateProperties.FACING); + Instancer model = blockEntity.getRenderedHandleInstance(getTransformMaterial()); + crank = model.createInstance(); + rotateCrank(); + } + + @Override + public void beginFrame() { + if (crank == null) + return; + + rotateCrank(); + } + + private void rotateCrank() { + Direction.Axis axis = facing.getAxis(); + float angle = blockEntity.getIndependentAngle(AnimationTickHolder.getPartialTicks()); + + crank.loadIdentity() + .translate(getInstancePosition()) + .centre() + .rotate(Direction.get(Direction.AxisDirection.POSITIVE, axis), angle) + .unCentre(); + } + + @Override + public void init() { + if (blockEntity.shouldRenderShaft()) + super.init(); + } + + @Override + public void remove() { + if (blockEntity.shouldRenderShaft()) + super.remove(); + if (crank != null) + crank.delete(); + } + + @Override + public void update() { + if (blockEntity.shouldRenderShaft()) + super.update(); + } + + @Override + public void updateLight() { + if (blockEntity.shouldRenderShaft()) + super.updateLight(); + if (crank != null) + relight(pos, crank); + } +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/crank/HandCrankRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/crank/HandCrankRenderer.java new file mode 100644 index 000000000..bfea5c3c2 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/crank/HandCrankRenderer.java @@ -0,0 +1,35 @@ +package com.simibubi.create.content.kinetics.crank; + +import static net.minecraft.world.level.block.state.properties.BlockStateProperties.FACING; + +import com.jozufozu.flywheel.backend.Backend; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.core.Direction; + +public class HandCrankRenderer extends KineticBlockEntityRenderer { + + public HandCrankRenderer(BlockEntityRendererProvider.Context context) { + super(context); + } + + @Override + protected void renderSafe(HandCrankBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + if (be.shouldRenderShaft()) + super.renderSafe(be, partialTicks, ms, buffer, light, overlay); + + if (Backend.canUseInstancing(be.getLevel())) + return; + + Direction facing = be.getBlockState() + .getValue(FACING); + kineticRotationTransform(be.getRenderedHandle(), be, facing.getAxis(), be.getIndependentAngle(partialTicks), + light).renderInto(ms, buffer.getBuffer(RenderType.solid())); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/crank/ValveHandleBlock.java b/src/main/java/com/simibubi/create/content/kinetics/crank/ValveHandleBlock.java new file mode 100644 index 000000000..b8eead0be --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/crank/ValveHandleBlock.java @@ -0,0 +1,119 @@ +package com.simibubi.create.content.kinetics.crank; + +import javax.annotation.ParametersAreNonnullByDefault; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllItems; +import com.simibubi.create.AllShapes; +import com.simibubi.create.foundation.utility.BlockHelper; +import com.simibubi.create.foundation.utility.Couple; + +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.item.DyeColor; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntityType; +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.VoxelShape; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import net.minecraftforge.eventbus.api.EventPriority; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; + +@ParametersAreNonnullByDefault +@EventBusSubscriber +public class ValveHandleBlock extends HandCrankBlock { + + private final DyeColor color; + private final boolean inCreativeTab; + + public static ValveHandleBlock copper(Properties properties) { + return new ValveHandleBlock(properties, null, true); + } + + public static ValveHandleBlock dyed(Properties properties, DyeColor color) { + return new ValveHandleBlock(properties, color, false); + } + + private ValveHandleBlock(Properties properties, DyeColor color, boolean inCreativeTab) { + super(properties); + this.color = color; + this.inCreativeTab = inCreativeTab; + } + + @Override + public VoxelShape getShape(BlockState pState, BlockGetter worldIn, BlockPos pos, CollisionContext context) { + return AllShapes.VALVE_HANDLE.get(pState.getValue(FACING)); + } + + @SubscribeEvent(priority = EventPriority.LOW) + public static void onBlockActivated(PlayerInteractEvent.RightClickBlock event) { + BlockPos pos = event.getPos(); + Level level = event.getLevel(); + Player player = event.getEntity(); + BlockState blockState = level.getBlockState(pos); + + if (!(blockState.getBlock() instanceof ValveHandleBlock vhb)) + return; + if (AllItems.WRENCH.isIn(player.getItemInHand(event.getHand())) && player.isSteppingCarefully()) + return; + + if (vhb.clicked(level, pos, blockState, player, event.getHand())) { + event.setCanceled(true); + event.setCancellationResult(InteractionResult.SUCCESS); + } + } + + @Override + public void onRemove(BlockState pState, Level pLevel, BlockPos pPos, BlockState pNewState, boolean pIsMoving) { + if (!(pNewState.getBlock() instanceof ValveHandleBlock)) + super.onRemove(pState, pLevel, pPos, pNewState, pIsMoving); + } + + public boolean clicked(Level level, BlockPos pos, BlockState blockState, Player player, InteractionHand hand) { + ItemStack heldItem = player.getItemInHand(hand); + DyeColor color = DyeColor.getColor(heldItem); + + if (color != null && color != this.color) { + if (!level.isClientSide) + level.setBlockAndUpdate(pos, + BlockHelper.copyProperties(blockState, AllBlocks.DYED_VALVE_HANDLES.get(color) + .getDefaultState())); + return true; + } + + onBlockEntityUse(level, pos, + hcbe -> (hcbe instanceof ValveHandleBlockEntity vhbe) && vhbe.activate(player.isSteppingCarefully()) + ? InteractionResult.SUCCESS + : InteractionResult.PASS); + return true; + } + + @Override + public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, + BlockHitResult hit) { + return InteractionResult.PASS; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.VALVE_HANDLE.get(); + } + + @Override + public int getRotationSpeed() { + return 32; + } + + public static Couple getSpeedRange() { + return Couple.create(32, 32); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/crank/ValveHandleBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/crank/ValveHandleBlockEntity.java new file mode 100644 index 000000000..f504471a0 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/crank/ValveHandleBlockEntity.java @@ -0,0 +1,229 @@ +package com.simibubi.create.content.kinetics.crank; + +import java.util.List; + +import com.google.common.collect.ImmutableList; +import com.jozufozu.flywheel.api.Instancer; +import com.jozufozu.flywheel.api.Material; +import com.jozufozu.flywheel.core.materials.model.ModelData; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.content.kinetics.transmission.sequencer.SequencedGearshiftBlockEntity.SequenceContext; +import com.simibubi.create.content.kinetics.transmission.sequencer.SequencerInstructions; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsBoard; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsFormatter; +import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollValueBehaviour; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.VecHelper; + +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.network.chat.MutableComponent; +import net.minecraft.util.Mth; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public class ValveHandleBlockEntity extends HandCrankBlockEntity { + + public ScrollValueBehaviour angleInput; + public int cooldown; + + protected int startAngle; + protected int targetAngle; + protected int totalUseTicks; + + public ValveHandleBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + public void addBehaviours(List behaviours) { + super.addBehaviours(behaviours); + behaviours.add(angleInput = new ValveHandleScrollValueBehaviour(this).between(-180, 180)); + angleInput.onlyActiveWhen(this::showValue); + angleInput.setValue(45); + } + + @Override + protected boolean clockwise() { + return angleInput.getValue() < 0 ^ backwards; + } + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + super.write(compound, clientPacket); + compound.putInt("TotalUseTicks", totalUseTicks); + compound.putInt("StartAngle", startAngle); + compound.putInt("TargetAngle", targetAngle); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + super.read(compound, clientPacket); + totalUseTicks = compound.getInt("TotalUseTicks"); + startAngle = compound.getInt("StartAngle"); + targetAngle = compound.getInt("TargetAngle"); + } + + @Override + public void tick() { + super.tick(); + if (inUse == 0 && cooldown > 0) + cooldown--; + independentAngle = level.isClientSide() ? getIndependentAngle(0) : 0; + } + + @Override + public float getIndependentAngle(float partialTicks) { + if (inUse == 0 && source != null && getSpeed() != 0) + return KineticBlockEntityRenderer.getAngleForTe(this, worldPosition, + KineticBlockEntityRenderer.getRotationAxisOf(this)); + + int step = getBlockState().getOptionalValue(ValveHandleBlock.FACING) + .orElse(Direction.SOUTH) + .getAxisDirection() + .getStep(); + + return (inUse > 0 && totalUseTicks > 0 + ? Mth.lerp(Math.min(totalUseTicks, totalUseTicks - inUse + partialTicks) / (float) totalUseTicks, + startAngle, targetAngle) + : targetAngle) * Mth.DEG_TO_RAD * (backwards ? -1 : 1) * step; + } + + public boolean showValue() { + return inUse == 0; + } + + public boolean activate(boolean sneak) { + if (getTheoreticalSpeed() != 0) + return false; + if (inUse > 0 || cooldown > 0) + return false; + if (level.isClientSide) + return true; + + // Always overshoot, target will stop early + int value = angleInput.getValue(); + int target = Math.abs(value); + int rotationSpeed = AllBlocks.COPPER_VALVE_HANDLE.get() + .getRotationSpeed(); + double degreesPerTick = KineticBlockEntity.convertToAngular(rotationSpeed); + inUse = (int) Math.ceil(target / degreesPerTick) + 2; + + startAngle = (int) ((independentAngle) % 90 + 360) % 90; + targetAngle = Math.round((startAngle + (target > 135 ? 180 : 90) * Mth.sign(value)) / 90f) * 90; + totalUseTicks = inUse; + backwards = sneak; + + sequenceContext = SequenceContext.fromGearshift(SequencerInstructions.TURN_ANGLE, rotationSpeed, target); + updateGeneratedRotation(); + cooldown = 4; + + return true; + } + + @Override + protected void copySequenceContextFrom(KineticBlockEntity sourceBE) {} + + @Override + @OnlyIn(Dist.CLIENT) + public SuperByteBuffer getRenderedHandle() { + return CachedBufferer.block(getBlockState()); + } + + @Override + @OnlyIn(Dist.CLIENT) + public Instancer getRenderedHandleInstance(Material material) { + return material.getModel(getBlockState()); + } + + @Override + @OnlyIn(Dist.CLIENT) + public boolean shouldRenderShaft() { + return false; + } + + public static class ValveHandleScrollValueBehaviour extends ScrollValueBehaviour { + + public ValveHandleScrollValueBehaviour(SmartBlockEntity be) { + super(Lang.translateDirect("kinetics.valve_handle.rotated_angle"), be, new ValveHandleValueBox()); + withFormatter(v -> String.valueOf(Math.abs(v)) + Lang.translateDirect("generic.unit.degrees") + .getString()); + } + + @Override + public ValueSettingsBoard createBoard(Player player, BlockHitResult hitResult) { + ImmutableList rows = ImmutableList.of(Components.literal("\u27f3") + .withStyle(ChatFormatting.BOLD), + Components.literal("\u27f2") + .withStyle(ChatFormatting.BOLD)); + return new ValueSettingsBoard(label, 180, 45, rows, new ValueSettingsFormatter(this::formatValue)); + } + + @Override + public void setValueSettings(Player player, ValueSettings valueSetting, boolean ctrlHeld) { + int value = Math.max(1, valueSetting.value()); + if (!valueSetting.equals(getValueSettings())) + playFeedbackSound(this); + setValue(valueSetting.row() == 0 ? -value : value); + } + + @Override + public ValueSettings getValueSettings() { + return new ValueSettings(value < 0 ? 0 : 1, Math.abs(value)); + } + + public MutableComponent formatValue(ValueSettings settings) { + return Lang.number(Math.max(1, Math.abs(settings.value()))) + .add(Lang.translateDirect("generic.unit.degrees")) + .component(); + } + + @Override + public void onShortInteract(Player player, InteractionHand hand, Direction side) { + BlockState blockState = blockEntity.getBlockState(); + if (blockState.getBlock() instanceof ValveHandleBlock vhb) + vhb.clicked(getWorld(), getPos(), blockState, player, hand); + } + + } + + public static class ValveHandleValueBox extends ValueBoxTransform.Sided { + + @Override + protected boolean isSideActive(BlockState state, Direction direction) { + return direction == state.getValue(ValveHandleBlock.FACING); + } + + @Override + protected Vec3 getSouthLocation() { + return VecHelper.voxelSpace(8, 8, 4.5); + } + + @Override + public boolean testHit(BlockState state, Vec3 localHit) { + Vec3 offset = getLocalOffset(state); + if (offset == null) + return false; + return localHit.distanceTo(offset) < scale / 1.5f; + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/crusher/AbstractCrushingRecipe.java b/src/main/java/com/simibubi/create/content/kinetics/crusher/AbstractCrushingRecipe.java new file mode 100644 index 000000000..effcf39bc --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/crusher/AbstractCrushingRecipe.java @@ -0,0 +1,19 @@ +package com.simibubi.create.content.kinetics.crusher; + +import com.simibubi.create.content.processing.recipe.ProcessingRecipe; +import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder.ProcessingRecipeParams; +import com.simibubi.create.foundation.recipe.IRecipeTypeInfo; + +import net.minecraftforge.items.wrapper.RecipeWrapper; + +public abstract class AbstractCrushingRecipe extends ProcessingRecipe { + + public AbstractCrushingRecipe(IRecipeTypeInfo recipeType, ProcessingRecipeParams params) { + super(recipeType, params); + } + + @Override + protected int getMaxInputCount() { + return 1; + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingRecipe.java b/src/main/java/com/simibubi/create/content/kinetics/crusher/CrushingRecipe.java similarity index 78% rename from src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingRecipe.java rename to src/main/java/com/simibubi/create/content/kinetics/crusher/CrushingRecipe.java index 5833d160b..73a6c2b22 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingRecipe.java +++ b/src/main/java/com/simibubi/create/content/kinetics/crusher/CrushingRecipe.java @@ -1,9 +1,9 @@ -package com.simibubi.create.content.contraptions.components.crusher; +package com.simibubi.create.content.kinetics.crusher; import javax.annotation.ParametersAreNonnullByDefault; import com.simibubi.create.AllRecipeTypes; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder.ProcessingRecipeParams; +import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder.ProcessingRecipeParams; import net.minecraft.world.level.Level; import net.minecraftforge.items.wrapper.RecipeWrapper; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelBlock.java b/src/main/java/com/simibubi/create/content/kinetics/crusher/CrushingWheelBlock.java similarity index 84% rename from src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelBlock.java rename to src/main/java/com/simibubi/create/content/kinetics/crusher/CrushingWheelBlock.java index fdcef77ef..2fae8c212 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/crusher/CrushingWheelBlock.java @@ -1,12 +1,12 @@ -package com.simibubi.create.content.contraptions.components.crusher; +package com.simibubi.create.content.kinetics.crusher; -import static com.simibubi.create.content.contraptions.components.crusher.CrushingWheelControllerBlock.VALID; +import static com.simibubi.create.content.kinetics.crusher.CrushingWheelControllerBlock.VALID; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.content.kinetics.base.RotatedPillarKineticBlock; +import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.utility.Iterate; import net.minecraft.core.BlockPos; @@ -24,7 +24,7 @@ import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; -public class CrushingWheelBlock extends RotatedPillarKineticBlock implements ITE { +public class CrushingWheelBlock extends RotatedPillarKineticBlock implements IBE { public CrushingWheelBlock(Properties properties) { super(properties); @@ -80,14 +80,14 @@ public class CrushingWheelBlock extends RotatedPillarKineticBlock implements ITE if (AllBlocks.CRUSHING_WHEEL.has(otherState)) { controllerShouldExist = true; - CrushingWheelTileEntity te = getTileEntity(world, pos); - CrushingWheelTileEntity otherTe = getTileEntity(world, otherWheelPos); + CrushingWheelBlockEntity be = getBlockEntity(world, pos); + CrushingWheelBlockEntity otherBE = getBlockEntity(world, otherWheelPos); - if (te != null && otherTe != null && (te.getSpeed() > 0) != (otherTe.getSpeed() > 0) - && te.getSpeed() != 0) { + if (be != null && otherBE != null && (be.getSpeed() > 0) != (otherBE.getSpeed() > 0) + && be.getSpeed() != 0) { Axis wheelAxis = state.getValue(AXIS); Axis sideAxis = side.getAxis(); - int controllerADO = Math.round(Math.signum(te.getSpeed())) * side.getAxisDirection() + int controllerADO = Math.round(Math.signum(be.getSpeed())) * side.getAxisDirection() .getStep(); Vec3 controllerDirVec = new Vec3(wheelAxis == Axis.X ? 1 : 0, wheelAxis == Axis.Y ? 1 : 0, wheelAxis == Axis.Z ? 1 : 0).cross( @@ -132,7 +132,7 @@ public class CrushingWheelBlock extends RotatedPillarKineticBlock implements ITE if (entityIn.getY() < pos.getY() + 1.25f || !entityIn.isOnGround()) return; - float speed = getTileEntityOptional(worldIn, pos).map(CrushingWheelTileEntity::getSpeed) + float speed = getBlockEntityOptional(worldIn, pos).map(CrushingWheelBlockEntity::getSpeed) .orElse(0f); double x = 0; @@ -183,13 +183,13 @@ public class CrushingWheelBlock extends RotatedPillarKineticBlock implements ITE } @Override - public Class getTileEntityClass() { - return CrushingWheelTileEntity.class; + public Class getBlockEntityClass() { + return CrushingWheelBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.CRUSHING_WHEEL.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.CRUSHING_WHEEL.get(); } } diff --git a/src/main/java/com/simibubi/create/content/kinetics/crusher/CrushingWheelBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/crusher/CrushingWheelBlockEntity.java new file mode 100644 index 000000000..01f17e2ce --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/crusher/CrushingWheelBlockEntity.java @@ -0,0 +1,80 @@ +package com.simibubi.create.content.kinetics.crusher; + +import java.util.List; + +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.Iterate; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.event.entity.living.LivingDropsEvent; +import net.minecraftforge.event.entity.living.LootingLevelEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; + +@EventBusSubscriber +public class CrushingWheelBlockEntity extends KineticBlockEntity { + + public static final DamageSource DAMAGE_SOURCE = new DamageSource("create.crush").bypassArmor() + .setScalesWithDifficulty(); + + public CrushingWheelBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + setLazyTickRate(20); + } + + @Override + public void addBehaviours(List behaviours) { + super.addBehaviours(behaviours); + registerAwardables(behaviours, AllAdvancements.CRUSHING_WHEEL, AllAdvancements.CRUSHER_MAXED); + } + + @Override + public void onSpeedChanged(float prevSpeed) { + super.onSpeedChanged(prevSpeed); + fixControllers(); + } + + public void fixControllers() { + for (Direction d : Iterate.directions) + ((CrushingWheelBlock) getBlockState().getBlock()).updateControllers(getBlockState(), getLevel(), getBlockPos(), + d); + } + + @Override + protected AABB createRenderBoundingBox() { + return new AABB(worldPosition).inflate(1); + } + + @Override + public void lazyTick() { + super.lazyTick(); + fixControllers(); + } + + @SubscribeEvent + public static void crushingIsFortunate(LootingLevelEvent event) { + if (event.getDamageSource() != DAMAGE_SOURCE) + return; + event.setLootingLevel(2); //This does not currently increase mob drops. It seems like this only works for damage done by an entity. + } + + @SubscribeEvent + public static void handleCrushedMobDrops(LivingDropsEvent event) { + if (event.getSource() != CrushingWheelBlockEntity.DAMAGE_SOURCE) + return; + Vec3 outSpeed = Vec3.ZERO; + for (ItemEntity outputItem : event.getDrops()) { + outputItem.setDeltaMovement(outSpeed); + } + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelControllerBlock.java b/src/main/java/com/simibubi/create/content/kinetics/crusher/CrushingWheelControllerBlock.java similarity index 81% rename from src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelControllerBlock.java rename to src/main/java/com/simibubi/create/content/kinetics/crusher/CrushingWheelControllerBlock.java index f9d944d82..61171c248 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelControllerBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/crusher/CrushingWheelControllerBlock.java @@ -1,10 +1,10 @@ -package com.simibubi.create.content.contraptions.components.crusher; +package com.simibubi.create.content.kinetics.crusher; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.item.ItemHelper; import com.simibubi.create.foundation.utility.Iterate; @@ -37,7 +37,7 @@ import net.minecraft.world.phys.shapes.EntityCollisionContext; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; -public class CrushingWheelControllerBlock extends DirectionalBlock implements ITE { +public class CrushingWheelControllerBlock extends DirectionalBlock implements IBE { public CrushingWheelControllerBlock(Properties p_i48440_1_) { super(p_i48440_1_); @@ -71,8 +71,8 @@ public class CrushingWheelControllerBlock extends DirectionalBlock implements IT checkEntityForProcessing(worldIn, pos, entityIn); - withTileEntityDo(worldIn, pos, te -> { - if (te.processingEntity == entityIn) + withBlockEntityDo(worldIn, pos, be -> { + if (be.processingEntity == entityIn) entityIn.makeStuckInBlock(state, new Vec3(axis == Axis.X ? (double) 0.05F : 0.25D, axis == Axis.Y ? (double) 0.05F : 0.25D, axis == Axis.Z ? (double) 0.05F : 0.25D)); @@ -80,10 +80,10 @@ public class CrushingWheelControllerBlock extends DirectionalBlock implements IT } public void checkEntityForProcessing(Level worldIn, BlockPos pos, Entity entityIn) { - CrushingWheelControllerTileEntity te = getTileEntity(worldIn, pos); - if (te == null) + CrushingWheelControllerBlockEntity be = getBlockEntity(worldIn, pos); + if (be == null) return; - if (te.crushingspeed == 0) + if (be.crushingspeed == 0) return; // if (entityIn instanceof ItemEntity) // ((ItemEntity) entityIn).setPickUpDelay(10); @@ -92,7 +92,7 @@ public class CrushingWheelControllerBlock extends DirectionalBlock implements IT if (pos.equals(NbtUtils.readBlockPos(data.getCompound("BypassCrushingWheel")))) return; } - if (te.isOccupied()) + if (be.isOccupied()) return; boolean isPlayer = entityIn instanceof Player; if (isPlayer && ((Player) entityIn).isCreative()) @@ -100,7 +100,7 @@ public class CrushingWheelControllerBlock extends DirectionalBlock implements IT if (isPlayer && entityIn.level.getDifficulty() == Difficulty.PEACEFUL) return; - te.startCrushing(entityIn); + be.startCrushing(entityIn); } @Override @@ -129,11 +129,11 @@ public class CrushingWheelControllerBlock extends DirectionalBlock implements IT } public void updateSpeed(BlockState state, LevelAccessor world, BlockPos pos) { - withTileEntityDo(world, pos, te -> { + withBlockEntityDo(world, pos, be -> { if (!state.getValue(VALID)) { - if (te.crushingspeed != 0) { - te.crushingspeed = 0; - te.sendData(); + if (be.crushingspeed != 0) { + be.crushingspeed = 0; + be.sendData(); } return; } @@ -144,16 +144,16 @@ public class CrushingWheelControllerBlock extends DirectionalBlock implements IT continue; if (neighbour.getValue(BlockStateProperties.AXIS) == d.getAxis()) continue; - BlockEntity adjTe = world.getBlockEntity(pos.relative(d)); - if (!(adjTe instanceof CrushingWheelTileEntity cwte)) + BlockEntity adjBE = world.getBlockEntity(pos.relative(d)); + if (!(adjBE instanceof CrushingWheelBlockEntity cwbe)) continue; - te.crushingspeed = Math.abs(cwte.getSpeed() / 50f); - te.sendData(); - - cwte.award(AllAdvancements.CRUSHING_WHEEL); - if (cwte.getSpeed() > 255) - cwte.award(AllAdvancements.CRUSHER_MAXED); - + be.crushingspeed = Math.abs(cwbe.getSpeed() / 50f); + be.sendData(); + + cwbe.award(AllAdvancements.CRUSHING_WHEEL); + if (cwbe.getSpeed() > 255) + cwbe.award(AllAdvancements.CRUSHER_MAXED); + break; } }); @@ -178,8 +178,8 @@ public class CrushingWheelControllerBlock extends DirectionalBlock implements IT // than falling back through. return Shapes.empty(); - CrushingWheelControllerTileEntity te = getTileEntity(worldIn, pos); - if (te != null && te.processingEntity == entity) + CrushingWheelControllerBlockEntity be = getBlockEntity(worldIn, pos); + if (be != null && be.processingEntity == entity) return Shapes.empty(); return standardShape; @@ -190,18 +190,18 @@ public class CrushingWheelControllerBlock extends DirectionalBlock implements IT if (!state.hasBlockEntity() || state.getBlock() == newState.getBlock()) return; - withTileEntityDo(worldIn, pos, te -> ItemHelper.dropContents(worldIn, pos, te.inventory)); + withBlockEntityDo(worldIn, pos, be -> ItemHelper.dropContents(worldIn, pos, be.inventory)); worldIn.removeBlockEntity(pos); } @Override - public Class getTileEntityClass() { - return CrushingWheelControllerTileEntity.class; + public Class getBlockEntityClass() { + return CrushingWheelControllerBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.CRUSHING_WHEEL_CONTROLLER.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.CRUSHING_WHEEL_CONTROLLER.get(); } @Override diff --git a/src/main/java/com/simibubi/create/content/kinetics/crusher/CrushingWheelControllerBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/crusher/CrushingWheelControllerBlockEntity.java new file mode 100644 index 000000000..a7d15a1e1 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/crusher/CrushingWheelControllerBlockEntity.java @@ -0,0 +1,375 @@ +package com.simibubi.create.content.kinetics.crusher; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import com.simibubi.create.AllRecipeTypes; +import com.simibubi.create.content.kinetics.belt.behaviour.DirectBeltInputBehaviour; +import com.simibubi.create.content.processing.recipe.ProcessingInventory; +import com.simibubi.create.content.processing.recipe.ProcessingRecipe; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.item.ItemHelper; +import com.simibubi.create.foundation.sound.SoundScapes; +import com.simibubi.create.foundation.sound.SoundScapes.AmbienceGroup; +import com.simibubi.create.foundation.utility.NBTHelper; +import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.particles.BlockParticleOption; +import net.minecraft.core.particles.ItemParticleOption; +import net.minecraft.core.particles.ParticleOptions; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.wrapper.RecipeWrapper; + +public class CrushingWheelControllerBlockEntity extends SmartBlockEntity { + + public Entity processingEntity; + private UUID entityUUID; + protected boolean searchForEntity; + + public ProcessingInventory inventory; + protected LazyOptional handler = LazyOptional.of(() -> inventory); + private RecipeWrapper wrapper; + public float crushingspeed; + + public CrushingWheelControllerBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + inventory = new ProcessingInventory(this::itemInserted) { + + @Override + public boolean isItemValid(int slot, ItemStack stack) { + return super.isItemValid(slot, stack) && processingEntity == null; + } + + }; + wrapper = new RecipeWrapper(inventory); + } + + @Override + public void addBehaviours(List behaviours) { + behaviours.add(new DirectBeltInputBehaviour(this).onlyInsertWhen(this::supportsDirectBeltInput)); + } + + private boolean supportsDirectBeltInput(Direction side) { + BlockState blockState = getBlockState(); + if (blockState == null) + return false; + Direction direction = blockState.getValue(CrushingWheelControllerBlock.FACING); + return direction == Direction.DOWN || direction == side; + } + + @Override + public void tick() { + super.tick(); + if (searchForEntity) { + searchForEntity = false; + List search = level.getEntities((Entity) null, new AABB(getBlockPos()), + e -> entityUUID.equals(e.getUUID())); + if (search.isEmpty()) + clear(); + else + processingEntity = search.get(0); + } + + if (!isOccupied()) + return; + if (crushingspeed == 0) + return; + + if (level.isClientSide) + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> this.tickAudio()); + + float speed = crushingspeed * 4; + + Vec3 centerPos = VecHelper.getCenterOf(worldPosition); + Direction facing = getBlockState().getValue(CrushingWheelControllerBlock.FACING); + int offset = facing.getAxisDirection() + .getStep(); + Vec3 outSpeed = new Vec3((facing.getAxis() == Axis.X ? 0.25D : 0.0D) * offset, + offset == 1 ? (facing.getAxis() == Axis.Y ? 0.5D : 0.0D) : 0.0D // Increased upwards speed so upwards + // crushing wheels shoot out the item + // properly. + , (facing.getAxis() == Axis.Z ? 0.25D : 0.0D) * offset); // No downwards speed, so downwards crushing wheels + // drop the items as before. + Vec3 outPos = centerPos.add((facing.getAxis() == Axis.X ? .55f * offset : 0f), + (facing.getAxis() == Axis.Y ? .55f * offset : 0f), (facing.getAxis() == Axis.Z ? .55f * offset : 0f)); + + if (!hasEntity()) { + + float processingSpeed = + Mth.clamp((speed) / (!inventory.appliedRecipe ? Mth.log2(inventory.getStackInSlot(0) + .getCount()) : 1), .25f, 20); + inventory.remainingTime -= processingSpeed; + spawnParticles(inventory.getStackInSlot(0)); + + if (level.isClientSide) + return; + + if (inventory.remainingTime < 20 && !inventory.appliedRecipe) { + applyRecipe(); + inventory.appliedRecipe = true; + level.sendBlockUpdated(worldPosition, getBlockState(), getBlockState(), 2 | 16); + return; + } + + if (inventory.remainingTime > 0) { + return; + } + inventory.remainingTime = 0; + + // Output Items + if (facing != Direction.UP) { + BlockPos nextPos = worldPosition.offset(facing.getAxis() == Axis.X ? 1f * offset : 0f, (-1f), + facing.getAxis() == Axis.Z ? 1f * offset : 0f); + DirectBeltInputBehaviour behaviour = + BlockEntityBehaviour.get(level, nextPos, DirectBeltInputBehaviour.TYPE); + if (behaviour != null) { + boolean changed = false; + if (!behaviour.canInsertFromSide(facing)) + return; + for (int slot = 0; slot < inventory.getSlots(); slot++) { + ItemStack stack = inventory.getStackInSlot(slot); + if (stack.isEmpty()) + continue; + ItemStack remainder = behaviour.handleInsertion(stack, facing, false); + if (remainder.equals(stack, false)) + continue; + inventory.setStackInSlot(slot, remainder); + changed = true; + } + if (changed) { + setChanged(); + sendData(); + } + return; + } + } + + // Eject Items + for (int slot = 0; slot < inventory.getSlots(); slot++) { + ItemStack stack = inventory.getStackInSlot(slot); + if (stack.isEmpty()) + continue; + ItemEntity entityIn = new ItemEntity(level, outPos.x, outPos.y, outPos.z, stack); + entityIn.setDeltaMovement(outSpeed); + entityIn.getPersistentData() + .put("BypassCrushingWheel", NbtUtils.writeBlockPos(worldPosition)); + level.addFreshEntity(entityIn); + } + inventory.clear(); + level.sendBlockUpdated(worldPosition, getBlockState(), getBlockState(), 2 | 16); + + return; + } + + if (!processingEntity.isAlive() || !processingEntity.getBoundingBox() + .intersects(new AABB(worldPosition).inflate(.5f))) { + clear(); + return; + } + + double xMotion = ((worldPosition.getX() + .5f) - processingEntity.getX()) / 2f; + double zMotion = ((worldPosition.getZ() + .5f) - processingEntity.getZ()) / 2f; + if (processingEntity.isShiftKeyDown()) + xMotion = zMotion = 0; + double movement = Math.max(-speed / 4f, -.5f) * -offset; + processingEntity.setDeltaMovement( + new Vec3(facing.getAxis() == Axis.X ? movement : xMotion, facing.getAxis() == Axis.Y ? movement : 0f // Do + // not + // move + // entities + // upwards + // or + // downwards + // for + // horizontal + // crushers, + , facing.getAxis() == Axis.Z ? movement : zMotion)); // Or they'll only get their feet crushed. + + if (level.isClientSide) + return; + + if (!(processingEntity instanceof ItemEntity)) { + Vec3 entityOutPos = outPos.add(facing.getAxis() == Axis.X ? .5f * offset : 0f, + facing.getAxis() == Axis.Y ? .5f * offset : 0f, facing.getAxis() == Axis.Z ? .5f * offset : 0f); + int crusherDamage = AllConfigs.server().kinetics.crushingDamage.get(); + + if (processingEntity instanceof LivingEntity) { + if ((((LivingEntity) processingEntity).getHealth() - crusherDamage <= 0) // Takes LivingEntity instances + // as exception, so it can + // move them before it would + // kill them. + && (((LivingEntity) processingEntity).hurtTime <= 0)) { // This way it can actually output the items + // to the right spot. + processingEntity.setPos(entityOutPos.x, entityOutPos.y, entityOutPos.z); + } + } + processingEntity.hurt(CrushingWheelBlockEntity.DAMAGE_SOURCE, crusherDamage); + if (!processingEntity.isAlive()) { + processingEntity.setPos(entityOutPos.x, entityOutPos.y, entityOutPos.z); + } + return; + } + + ItemEntity itemEntity = (ItemEntity) processingEntity; + itemEntity.setPickUpDelay(20); + if (facing.getAxis() == Axis.Y) { + if (processingEntity.getY() * -offset < (centerPos.y - .25f) * -offset) { + intakeItem(itemEntity); + } + } else if (facing.getAxis() == Axis.Z) { + if (processingEntity.getZ() * -offset < (centerPos.z - .25f) * -offset) { + intakeItem(itemEntity); + } + } else { + if (processingEntity.getX() * -offset < (centerPos.x - .25f) * -offset) { + intakeItem(itemEntity); + } + } + } + + @OnlyIn(Dist.CLIENT) + public void tickAudio() { + float pitch = Mth.clamp((crushingspeed / 256f) + .45f, .85f, 1f); + if (entityUUID == null && inventory.getStackInSlot(0) + .isEmpty()) + return; + SoundScapes.play(AmbienceGroup.CRUSHING, worldPosition, pitch); + } + + private void intakeItem(ItemEntity itemEntity) { + inventory.clear(); + inventory.setStackInSlot(0, itemEntity.getItem() + .copy()); + itemInserted(inventory.getStackInSlot(0)); + itemEntity.discard(); + level.sendBlockUpdated(worldPosition, getBlockState(), getBlockState(), 2 | 16); + } + + protected void spawnParticles(ItemStack stack) { + if (stack == null || stack.isEmpty()) + return; + + ParticleOptions particleData = null; + if (stack.getItem() instanceof BlockItem) + particleData = new BlockParticleOption(ParticleTypes.BLOCK, ((BlockItem) stack.getItem()).getBlock() + .defaultBlockState()); + else + particleData = new ItemParticleOption(ParticleTypes.ITEM, stack); + + RandomSource r = level.random; + for (int i = 0; i < 4; i++) + level.addParticle(particleData, worldPosition.getX() + r.nextFloat(), worldPosition.getY() + r.nextFloat(), + worldPosition.getZ() + r.nextFloat(), 0, 0, 0); + } + + private void applyRecipe() { + Optional> recipe = findRecipe(); + + List list = new ArrayList<>(); + if (recipe.isPresent()) { + int rolls = inventory.getStackInSlot(0) + .getCount(); + inventory.clear(); + for (int roll = 0; roll < rolls; roll++) { + List rolledResults = recipe.get() + .rollResults(); + for (int i = 0; i < rolledResults.size(); i++) { + ItemStack stack = rolledResults.get(i); + ItemHelper.addToList(stack, list); + } + } + for (int slot = 0; slot < list.size() && slot + 1 < inventory.getSlots(); slot++) + inventory.setStackInSlot(slot + 1, list.get(slot)); + } else { + inventory.clear(); + } + + } + + public Optional> findRecipe() { + Optional> crushingRecipe = AllRecipeTypes.CRUSHING.find(wrapper, level); + if (!crushingRecipe.isPresent()) + crushingRecipe = AllRecipeTypes.MILLING.find(wrapper, level); + return crushingRecipe; + } + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + if (hasEntity()) + compound.put("Entity", NbtUtils.createUUID(entityUUID)); + compound.put("Inventory", inventory.serializeNBT()); + compound.putFloat("Speed", crushingspeed); + super.write(compound, clientPacket); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + super.read(compound, clientPacket); + if (compound.contains("Entity") && !isOccupied()) { + entityUUID = NbtUtils.loadUUID(NBTHelper.getINBT(compound, "Entity")); + this.searchForEntity = true; + } + crushingspeed = compound.getFloat("Speed"); + inventory.deserializeNBT(compound.getCompound("Inventory")); + } + + public void startCrushing(Entity entity) { + processingEntity = entity; + entityUUID = entity.getUUID(); + } + + private void itemInserted(ItemStack stack) { + Optional> recipe = findRecipe(); + inventory.remainingTime = recipe.isPresent() ? recipe.get() + .getProcessingDuration() : 100; + inventory.appliedRecipe = false; + } + + @Override + public LazyOptional getCapability(Capability cap, Direction side) { + if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) + return handler.cast(); + return super.getCapability(cap, side); + } + + public void clear() { + processingEntity = null; + entityUUID = null; + } + + public boolean isOccupied() { + return hasEntity() || !inventory.isEmpty(); + } + + public boolean hasEntity() { + return processingEntity != null; + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/deployer/BeltDeployerCallbacks.java b/src/main/java/com/simibubi/create/content/kinetics/deployer/BeltDeployerCallbacks.java new file mode 100644 index 000000000..d86d05294 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/deployer/BeltDeployerCallbacks.java @@ -0,0 +1,175 @@ +package com.simibubi.create.content.kinetics.deployer; + +import static com.simibubi.create.content.kinetics.base.DirectionalKineticBlock.FACING; + +import java.util.List; +import java.util.stream.Collectors; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.Create; +import com.simibubi.create.content.equipment.sandPaper.SandPaperPolishingRecipe; +import com.simibubi.create.content.kinetics.belt.BeltHelper; +import com.simibubi.create.content.kinetics.belt.behaviour.BeltProcessingBehaviour.ProcessingResult; +import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour; +import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour.TransportedResult; +import com.simibubi.create.content.kinetics.belt.transport.TransportedItemStack; +import com.simibubi.create.content.kinetics.deployer.DeployerBlockEntity.Mode; +import com.simibubi.create.content.kinetics.deployer.DeployerBlockEntity.State; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.advancement.CreateAdvancement; +import com.simibubi.create.foundation.recipe.RecipeApplier; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.items.ItemHandlerHelper; + +public class BeltDeployerCallbacks { + + public static ProcessingResult onItemReceived(TransportedItemStack s, TransportedItemStackHandlerBehaviour i, + DeployerBlockEntity blockEntity) { + + if (blockEntity.getSpeed() == 0) + return ProcessingResult.PASS; + if (blockEntity.mode == Mode.PUNCH) + return ProcessingResult.PASS; + BlockState blockState = blockEntity.getBlockState(); + if (!blockState.hasProperty(FACING) || blockState.getValue(FACING) != Direction.DOWN) + return ProcessingResult.PASS; + if (blockEntity.state != State.WAITING) + return ProcessingResult.HOLD; + if (blockEntity.redstoneLocked) + return ProcessingResult.PASS; + + DeployerFakePlayer player = blockEntity.getPlayer(); + ItemStack held = player == null ? ItemStack.EMPTY : player.getMainHandItem(); + + if (held.isEmpty()) + return ProcessingResult.HOLD; + if (blockEntity.getRecipe(s.stack) == null) + return ProcessingResult.PASS; + + blockEntity.start(); + return ProcessingResult.HOLD; + } + + public static ProcessingResult whenItemHeld(TransportedItemStack s, TransportedItemStackHandlerBehaviour i, + DeployerBlockEntity blockEntity) { + + if (blockEntity.getSpeed() == 0) + return ProcessingResult.PASS; + BlockState blockState = blockEntity.getBlockState(); + if (!blockState.hasProperty(FACING) || blockState.getValue(FACING) != Direction.DOWN) + return ProcessingResult.PASS; + + DeployerFakePlayer player = blockEntity.getPlayer(); + ItemStack held = player == null ? ItemStack.EMPTY : player.getMainHandItem(); + if (held.isEmpty()) + return ProcessingResult.HOLD; + + Recipe recipe = blockEntity.getRecipe(s.stack); + if (recipe == null) + return ProcessingResult.PASS; + + if (blockEntity.state == State.RETRACTING && blockEntity.timer == 1000) { + activate(s, i, blockEntity, recipe); + return ProcessingResult.HOLD; + } + + if (blockEntity.state == State.WAITING) { + if (blockEntity.redstoneLocked) + return ProcessingResult.PASS; + blockEntity.start(); + } + + return ProcessingResult.HOLD; + } + + public static void activate(TransportedItemStack transported, TransportedItemStackHandlerBehaviour handler, + DeployerBlockEntity blockEntity, Recipe recipe) { + + List collect = + RecipeApplier.applyRecipeOn(ItemHandlerHelper.copyStackWithSize(transported.stack, 1), recipe) + .stream() + .map(stack -> { + TransportedItemStack copy = transported.copy(); + boolean centered = BeltHelper.isItemUpright(stack); + copy.stack = stack; + copy.locked = true; + copy.angle = centered ? 180 : Create.RANDOM.nextInt(360); + return copy; + }) + .map(t -> { + t.locked = false; + return t; + }) + .collect(Collectors.toList()); + + blockEntity.award(AllAdvancements.DEPLOYER); + + TransportedItemStack left = transported.copy(); + blockEntity.player.spawnedItemEffects = transported.stack.copy(); + left.stack.shrink(1); + ItemStack resultItem = null; + + if (collect.isEmpty()) { + resultItem = left.stack.copy(); + handler.handleProcessingOnItem(transported, TransportedResult.convertTo(left)); + } else { + resultItem = collect.get(0).stack.copy(); + handler.handleProcessingOnItem(transported, TransportedResult.convertToAndLeaveHeld(collect, left)); + } + + ItemStack heldItem = blockEntity.player.getMainHandItem(); + boolean unbreakable = heldItem.hasTag() && heldItem.getTag() + .getBoolean("Unbreakable"); + boolean keepHeld = + recipe instanceof ItemApplicationRecipe && ((ItemApplicationRecipe) recipe).shouldKeepHeldItem(); + + if (!unbreakable && !keepHeld) { + if (heldItem.isDamageableItem()) + heldItem.hurtAndBreak(1, blockEntity.player, + s -> s.broadcastBreakEvent(InteractionHand.MAIN_HAND)); + else + heldItem.shrink(1); + } + + if (resultItem != null && !resultItem.isEmpty()) + awardAdvancements(blockEntity, resultItem); + + BlockPos pos = blockEntity.getBlockPos(); + Level world = blockEntity.getLevel(); + if (heldItem.isEmpty()) + world.playSound(null, pos, SoundEvents.ITEM_BREAK, SoundSource.BLOCKS, .25f, 1); + world.playSound(null, pos, SoundEvents.ITEM_PICKUP, SoundSource.BLOCKS, .25f, .75f); + if (recipe instanceof SandPaperPolishingRecipe) + AllSoundEvents.SANDING_SHORT.playOnServer(world, pos, .35f, 1f); + + blockEntity.sendData(); + } + + private static void awardAdvancements(DeployerBlockEntity blockEntity, ItemStack created) { + CreateAdvancement advancement = null; + + if (AllBlocks.ANDESITE_CASING.isIn(created)) + advancement = AllAdvancements.ANDESITE_CASING; + else if (AllBlocks.BRASS_CASING.isIn(created)) + advancement = AllAdvancements.BRASS_CASING; + else if (AllBlocks.COPPER_CASING.isIn(created)) + advancement = AllAdvancements.COPPER_CASING; + else if (AllBlocks.RAILWAY_CASING.isIn(created)) + advancement = AllAdvancements.TRAIN_CASING; + else + return; + + blockEntity.award(advancement); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerActorInstance.java b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerActorInstance.java similarity index 79% rename from src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerActorInstance.java rename to src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerActorInstance.java index 7477c48d1..7ec5e1a2b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerActorInstance.java +++ b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerActorInstance.java @@ -1,7 +1,7 @@ -package com.simibubi.create.content.contraptions.components.deployer; +package com.simibubi.create.content.kinetics.deployer; -import static com.simibubi.create.content.contraptions.base.DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE; -import static com.simibubi.create.content.contraptions.base.DirectionalKineticBlock.FACING; +import static com.simibubi.create.content.kinetics.base.DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE; +import static com.simibubi.create.content.kinetics.base.DirectionalKineticBlock.FACING; import com.jozufozu.flywheel.api.Material; import com.jozufozu.flywheel.api.MaterialManager; @@ -11,12 +11,12 @@ import com.jozufozu.flywheel.core.materials.model.ModelData; import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.IRotate; -import com.simibubi.create.content.contraptions.base.KineticTileInstance; -import com.simibubi.create.content.contraptions.base.flwdata.RotatingData; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.contraptions.render.ActorInstance; +import com.simibubi.create.content.kinetics.base.IRotate; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityInstance; +import com.simibubi.create.content.kinetics.base.flwdata.RotatingData; import com.simibubi.create.foundation.render.AllMaterialSpecs; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AnimationTickHolder; @@ -50,7 +50,7 @@ public class DeployerActorInstance extends ActorInstance { .material(Materials.TRANSFORMED); BlockState state = context.state; - DeployerTileEntity.Mode mode = NBTHelper.readEnum(context.tileData, "Mode", DeployerTileEntity.Mode.class); + DeployerBlockEntity.Mode mode = NBTHelper.readEnum(context.blockEntityData, "Mode", DeployerBlockEntity.Mode.class); PartialModel handPose = DeployerRenderer.getHandPose(mode); stationaryTimer = context.data.contains("StationaryTimer"); @@ -61,13 +61,13 @@ public class DeployerActorInstance extends ActorInstance { xRot = facing == Direction.UP ? 270 : facing == Direction.DOWN ? 90 : 0; zRot = rotatePole ? 90 : 0; - pole = mat.getModel(AllBlockPartials.DEPLOYER_POLE, state).createInstance(); + pole = mat.getModel(AllPartialModels.DEPLOYER_POLE, state).createInstance(); hand = mat.getModel(handPose, state).createInstance(); Direction.Axis axis = ((IRotate) state.getBlock()).getRotationAxis(state); shaft = materialManager.defaultSolid() .material(AllMaterialSpecs.ROTATING) - .getModel(KineticTileInstance.shaft(axis)) + .getModel(KineticBlockEntityInstance.shaft(axis)) .createInstance(); int blockLight = localBlockLight(); @@ -83,7 +83,9 @@ public class DeployerActorInstance extends ActorInstance { @Override public void beginFrame() { double factor; - if (context.contraption.stalled || context.position == null || context.data.contains("StationaryTimer")) { + if (context.disabled) { + factor = 0; + } else if (context.contraption.stalled || context.position == null || context.data.contains("StationaryTimer")) { factor = Mth.sin(AnimationTickHolder.getRenderTime() * .5f) * .25f + .25f; } else { Vec3 center = VecHelper.getCenterOf(new BlockPos(context.position)); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerApplicationRecipe.java b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerApplicationRecipe.java similarity index 84% rename from src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerApplicationRecipe.java rename to src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerApplicationRecipe.java index 66fba5e27..7aa694345 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerApplicationRecipe.java +++ b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerApplicationRecipe.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.deployer; +package com.simibubi.create.content.kinetics.deployer; import java.util.List; import java.util.Set; @@ -8,10 +8,9 @@ import com.simibubi.create.AllBlocks; import com.simibubi.create.AllRecipeTypes; import com.simibubi.create.AllTags.AllItemTags; import com.simibubi.create.compat.jei.category.sequencedAssembly.SequencedAssemblySubCategory; -import com.simibubi.create.content.contraptions.itemAssembly.IAssemblyRecipe; -import com.simibubi.create.content.contraptions.processing.ItemApplicationRecipe; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder.ProcessingRecipeParams; +import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder; +import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder.ProcessingRecipeParams; +import com.simibubi.create.content.processing.sequenced.IAssemblyRecipe; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Lang; diff --git a/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerBlock.java b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerBlock.java new file mode 100644 index 000000000..3b0195743 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerBlock.java @@ -0,0 +1,209 @@ +package com.simibubi.create.content.kinetics.deployer; + +import java.util.List; +import java.util.function.Predicate; + +import javax.annotation.ParametersAreNonnullByDefault; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllItems; +import com.simibubi.create.AllShapes; +import com.simibubi.create.content.kinetics.base.DirectionalAxisKineticBlock; +import com.simibubi.create.content.processing.AssemblyOperatorUseContext; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.placement.IPlacementHelper; +import com.simibubi.create.foundation.placement.PlacementHelpers; +import com.simibubi.create.foundation.placement.PlacementOffset; + +import net.minecraft.MethodsReturnNonnullByDefault; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +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.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.item.context.UseOnContext; +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.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.PushReaction; +import net.minecraft.world.level.pathfinder.PathComputationType; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +public class DeployerBlock extends DirectionalAxisKineticBlock implements IBE { + + private static final int placementHelperId = PlacementHelpers.register(new PlacementHelper()); + + public DeployerBlock(Properties properties) { + super(properties); + } + + @Override + public PushReaction getPistonPushReaction(BlockState state) { + return PushReaction.NORMAL; + } + + @Override + public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) { + return AllShapes.DEPLOYER_INTERACTION.get(state.getValue(FACING)); + } + + @Override + public VoxelShape getCollisionShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) { + return AllShapes.CASING_12PX.get(state.getValue(FACING)); + } + + @Override + public InteractionResult onWrenched(BlockState state, UseOnContext context) { + Vec3 normal = Vec3.atLowerCornerOf(state.getValue(FACING) + .getNormal()); + Vec3 location = context.getClickLocation() + .subtract(Vec3.atCenterOf(context.getClickedPos()) + .subtract(normal.scale(.5))) + .multiply(normal); + if (location.length() > .75f) { + if (!context.getLevel().isClientSide) + withBlockEntityDo(context.getLevel(), context.getClickedPos(), DeployerBlockEntity::changeMode); + return InteractionResult.SUCCESS; + } + return super.onWrenched(state, context); + } + + @Override + public void setPlacedBy(Level worldIn, BlockPos pos, BlockState state, LivingEntity placer, ItemStack stack) { + super.setPlacedBy(worldIn, pos, state, placer, stack); + if (placer instanceof ServerPlayer) + withBlockEntityDo(worldIn, pos, dbe -> dbe.owner = placer.getUUID()); + } + + @Override + public void onRemove(BlockState state, Level worldIn, BlockPos pos, BlockState newState, boolean isMoving) { + if (!isMoving && !state.is(newState.getBlock())) + withBlockEntityDo(worldIn, pos, DeployerBlockEntity::discardPlayer); + super.onRemove(state, worldIn, pos, newState, isMoving); + } + + @Override + public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, + BlockHitResult hit) { + ItemStack heldByPlayer = player.getItemInHand(handIn) + .copy(); + + IPlacementHelper placementHelper = PlacementHelpers.get(placementHelperId); + if (!player.isShiftKeyDown() && player.mayBuild()) { + if (placementHelper.matchesItem(heldByPlayer) && placementHelper.getOffset(player, worldIn, state, pos, hit) + .placeInWorld(worldIn, (BlockItem) heldByPlayer.getItem(), player, handIn, hit) + .consumesAction()) + return InteractionResult.SUCCESS; + } + + if (AllItems.WRENCH.isIn(heldByPlayer)) + return InteractionResult.PASS; + + Vec3 normal = Vec3.atLowerCornerOf(state.getValue(FACING) + .getNormal()); + Vec3 location = hit.getLocation() + .subtract(Vec3.atCenterOf(pos) + .subtract(normal.scale(.5))) + .multiply(normal); + if (location.length() < .75f) + return InteractionResult.PASS; + if (worldIn.isClientSide) + return InteractionResult.SUCCESS; + + withBlockEntityDo(worldIn, pos, be -> { + ItemStack heldByDeployer = be.player.getMainHandItem() + .copy(); + if (heldByDeployer.isEmpty() && heldByPlayer.isEmpty()) + return; + + player.setItemInHand(handIn, heldByDeployer); + be.player.setItemInHand(InteractionHand.MAIN_HAND, heldByPlayer); + be.sendData(); + }); + + return InteractionResult.SUCCESS; + } + + @Override + public Class getBlockEntityClass() { + return DeployerBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.DEPLOYER.get(); + } + + @Override + public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean isMoving) { + super.onPlace(state, world, pos, oldState, isMoving); + withBlockEntityDo(world, pos, DeployerBlockEntity::redstoneUpdate); + } + + @Override + public void neighborChanged(BlockState state, Level world, BlockPos pos, Block p_220069_4_, BlockPos p_220069_5_, + boolean p_220069_6_) { + withBlockEntityDo(world, pos, DeployerBlockEntity::redstoneUpdate); + } + + @Override + public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) { + return false; + } + + @Override + protected Direction getFacingForPlacement(BlockPlaceContext context) { + if (context instanceof AssemblyOperatorUseContext) + return Direction.DOWN; + else + return super.getFacingForPlacement(context); + } + + @MethodsReturnNonnullByDefault + private static class PlacementHelper implements IPlacementHelper { + + @Override + public Predicate getItemPredicate() { + return AllBlocks.DEPLOYER::isIn; + } + + @Override + public Predicate getStatePredicate() { + return AllBlocks.DEPLOYER::has; + } + + @Override + public PlacementOffset getOffset(Player player, Level world, BlockState state, BlockPos pos, + BlockHitResult ray) { + List directions = IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getLocation(), + state.getValue(FACING) + .getAxis(), + dir -> world.getBlockState(pos.relative(dir)) + .getMaterial() + .isReplaceable()); + + if (directions.isEmpty()) + return PlacementOffset.fail(); + else { + return PlacementOffset.success(pos.relative(directions.get(0)), + s -> s.setValue(FACING, state.getValue(FACING)) + .setValue(AXIS_ALONG_FIRST_COORDINATE, state.getValue(AXIS_ALONG_FIRST_COORDINATE))); + } + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerBlockEntity.java new file mode 100644 index 000000000..26363adb3 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerBlockEntity.java @@ -0,0 +1,571 @@ +package com.simibubi.create.content.kinetics.deployer; + +import static com.simibubi.create.content.kinetics.base.DirectionalKineticBlock.FACING; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + +import javax.annotation.Nullable; + +import com.jozufozu.flywheel.core.PartialModel; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.AllRecipeTypes; +import com.simibubi.create.content.equipment.sandPaper.SandPaperItem; +import com.simibubi.create.content.equipment.sandPaper.SandPaperPolishingRecipe.SandPaperInv; +import com.simibubi.create.content.kinetics.base.IRotate.StressImpact; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.belt.behaviour.BeltProcessingBehaviour; +import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour; +import com.simibubi.create.content.processing.sequenced.SequencedAssemblyRecipe; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.item.TooltipHelper; +import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.NBTHelper; +import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.animation.LerpedFloat; + +import net.minecraft.ChatFormatting; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.util.Mth; +import net.minecraft.world.Container; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.level.ClipContext; +import net.minecraft.world.level.ClipContext.Block; +import net.minecraft.world.level.ClipContext.Fluid; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.ItemStackHandler; +import net.minecraftforge.items.wrapper.RecipeWrapper; + +public class DeployerBlockEntity extends KineticBlockEntity { + + protected State state; + protected Mode mode; + protected ItemStack heldItem = ItemStack.EMPTY; + protected DeployerFakePlayer player; + protected int timer; + protected float reach; + protected boolean fistBump = false; + protected List overflowItems = new ArrayList<>(); + protected FilteringBehaviour filtering; + protected boolean redstoneLocked; + protected UUID owner; + private LazyOptional invHandler; + private ListTag deferredInventoryList; + + private LerpedFloat animatedOffset; + + public BeltProcessingBehaviour processingBehaviour; + + enum State { + WAITING, EXPANDING, RETRACTING, DUMPING; + } + + enum Mode { + PUNCH, USE + } + + public DeployerBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + this.state = State.WAITING; + mode = Mode.USE; + heldItem = ItemStack.EMPTY; + redstoneLocked = false; + animatedOffset = LerpedFloat.linear() + .startWithValue(0); + } + + @Override + public void addBehaviours(List behaviours) { + super.addBehaviours(behaviours); + filtering = new FilteringBehaviour(this, new DeployerFilterSlot()); + behaviours.add(filtering); + processingBehaviour = + new BeltProcessingBehaviour(this).whenItemEnters((s, i) -> BeltDeployerCallbacks.onItemReceived(s, i, this)) + .whileItemHeld((s, i) -> BeltDeployerCallbacks.whenItemHeld(s, i, this)); + behaviours.add(processingBehaviour); + + registerAwardables(behaviours, AllAdvancements.TRAIN_CASING, AllAdvancements.ANDESITE_CASING, + AllAdvancements.BRASS_CASING, AllAdvancements.COPPER_CASING, AllAdvancements.FIST_BUMP, + AllAdvancements.DEPLOYER, AllAdvancements.SELF_DEPLOYING); + } + + @Override + public void initialize() { + super.initialize(); + initHandler(); + } + + private void initHandler() { + if (invHandler != null) + return; + if (level instanceof ServerLevel sLevel) { + player = new DeployerFakePlayer(sLevel, owner); + if (deferredInventoryList != null) { + player.getInventory() + .load(deferredInventoryList); + deferredInventoryList = null; + heldItem = player.getMainHandItem(); + sendData(); + } + Vec3 initialPos = VecHelper.getCenterOf(worldPosition.relative(getBlockState().getValue(FACING))); + player.setPos(initialPos.x, initialPos.y, initialPos.z); + } + invHandler = LazyOptional.of(this::createHandler); + } + + protected void onExtract(ItemStack stack) { + player.setItemInHand(InteractionHand.MAIN_HAND, stack.copy()); + sendData(); + setChanged(); + } + + protected int getTimerSpeed() { + return (int) (getSpeed() == 0 ? 0 : Mth.clamp(Math.abs(getSpeed() * 2), 8, 512)); + } + + @Override + public void tick() { + super.tick(); + + if (getSpeed() == 0) + return; + if (!level.isClientSide && player != null && player.blockBreakingProgress != null) { + if (level.isEmptyBlock(player.blockBreakingProgress.getKey())) { + level.destroyBlockProgress(player.getId(), player.blockBreakingProgress.getKey(), -1); + player.blockBreakingProgress = null; + } + } + if (timer > 0) { + timer -= getTimerSpeed(); + return; + } + if (level.isClientSide) + return; + + ItemStack stack = player.getMainHandItem(); + if (state == State.WAITING) { + if (!overflowItems.isEmpty()) { + timer = getTimerSpeed() * 10; + return; + } + + boolean changed = false; + Inventory inventory = player.getInventory(); + for (int i = 0; i < inventory.getContainerSize(); i++) { + if (overflowItems.size() > 10) + break; + ItemStack item = inventory.getItem(i); + if (item.isEmpty()) + continue; + if (item != stack || !filtering.test(item)) { + overflowItems.add(item); + inventory.setItem(i, ItemStack.EMPTY); + changed = true; + } + } + + if (changed) { + sendData(); + timer = getTimerSpeed() * 10; + return; + } + + Direction facing = getBlockState().getValue(FACING); + if (mode == Mode.USE + && !DeployerHandler.shouldActivate(stack, level, worldPosition.relative(facing, 2), facing)) { + timer = getTimerSpeed() * 10; + return; + } + + // Check for advancement conditions + if (mode == Mode.PUNCH && !fistBump && startFistBump(facing)) + return; + if (redstoneLocked) + return; + + start(); + return; + } + + if (state == State.EXPANDING) { + if (fistBump) + triggerFistBump(); + activate(); + + state = State.RETRACTING; + timer = 1000; + sendData(); + return; + } + + if (state == State.RETRACTING) { + state = State.WAITING; + timer = 500; + sendData(); + return; + } + + } + + protected void start() { + state = State.EXPANDING; + Vec3 movementVector = getMovementVector(); + Vec3 rayOrigin = VecHelper.getCenterOf(worldPosition) + .add(movementVector.scale(3 / 2f)); + Vec3 rayTarget = VecHelper.getCenterOf(worldPosition) + .add(movementVector.scale(5 / 2f)); + ClipContext rayTraceContext = new ClipContext(rayOrigin, rayTarget, Block.OUTLINE, Fluid.NONE, player); + BlockHitResult result = level.clip(rayTraceContext); + reach = (float) (.5f + Math.min(result.getLocation() + .subtract(rayOrigin) + .length(), .75f)); + timer = 1000; + sendData(); + } + + public boolean startFistBump(Direction facing) { + int i = 0; + DeployerBlockEntity partner = null; + + for (i = 2; i < 5; i++) { + BlockPos otherDeployer = worldPosition.relative(facing, i); + if (!level.isLoaded(otherDeployer)) + return false; + BlockEntity other = level.getBlockEntity(otherDeployer); + if (other instanceof DeployerBlockEntity dpe) { + partner = dpe; + break; + } + } + + if (partner == null) + return false; + + if (level.getBlockState(partner.getBlockPos()) + .getValue(FACING) + .getOpposite() != facing || partner.mode != Mode.PUNCH) + return false; + if (partner.getSpeed() == 0) + return false; + + for (DeployerBlockEntity be : Arrays.asList(this, partner)) { + be.fistBump = true; + be.reach = ((i - 2)) * .5f; + be.timer = 1000; + be.state = State.EXPANDING; + be.sendData(); + } + + return true; + } + + public void triggerFistBump() { + int i = 0; + DeployerBlockEntity deployerBlockEntity = null; + for (i = 2; i < 5; i++) { + BlockPos pos = worldPosition.relative(getBlockState().getValue(FACING), i); + if (!level.isLoaded(pos)) + return; + if (level.getBlockEntity(pos) instanceof DeployerBlockEntity dpe) { + deployerBlockEntity = dpe; + break; + } + } + + if (deployerBlockEntity == null) + return; + if (!deployerBlockEntity.fistBump || deployerBlockEntity.state != State.EXPANDING) + return; + if (deployerBlockEntity.timer > 0) + return; + + fistBump = false; + deployerBlockEntity.fistBump = false; + deployerBlockEntity.state = State.RETRACTING; + deployerBlockEntity.timer = 1000; + deployerBlockEntity.sendData(); + award(AllAdvancements.FIST_BUMP); + + BlockPos soundLocation = new BlockPos(Vec3.atCenterOf(worldPosition) + .add(Vec3.atCenterOf(deployerBlockEntity.getBlockPos())) + .scale(.5f)); + level.playSound(null, soundLocation, SoundEvents.PLAYER_ATTACK_NODAMAGE, SoundSource.BLOCKS, .75f, .75f); + } + + protected void activate() { + Vec3 movementVector = getMovementVector(); + Direction direction = getBlockState().getValue(FACING); + Vec3 center = VecHelper.getCenterOf(worldPosition); + BlockPos clickedPos = worldPosition.relative(direction, 2); + player.setXRot(direction == Direction.UP ? -90 : direction == Direction.DOWN ? 90 : 0); + player.setYRot(direction.toYRot()); + + if (direction == Direction.DOWN + && BlockEntityBehaviour.get(level, clickedPos, TransportedItemStackHandlerBehaviour.TYPE) != null) + return; // Belt processing handled in BeltDeployerCallbacks + + DeployerHandler.activate(player, center, clickedPos, movementVector, mode); + award(AllAdvancements.DEPLOYER); + + if (player != null) + heldItem = player.getMainHandItem(); + } + + protected Vec3 getMovementVector() { + if (!AllBlocks.DEPLOYER.has(getBlockState())) + return Vec3.ZERO; + return Vec3.atLowerCornerOf(getBlockState().getValue(FACING) + .getNormal()); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + state = NBTHelper.readEnum(compound, "State", State.class); + mode = NBTHelper.readEnum(compound, "Mode", Mode.class); + timer = compound.getInt("Timer"); + redstoneLocked = compound.getBoolean("Powered"); + if (compound.contains("Owner")) + owner = compound.getUUID("Owner"); + + deferredInventoryList = compound.getList("Inventory", Tag.TAG_COMPOUND); + overflowItems = NBTHelper.readItemList(compound.getList("Overflow", Tag.TAG_COMPOUND)); + if (compound.contains("HeldItem")) + heldItem = ItemStack.of(compound.getCompound("HeldItem")); + super.read(compound, clientPacket); + + if (!clientPacket) + return; + fistBump = compound.getBoolean("Fistbump"); + reach = compound.getFloat("Reach"); + if (compound.contains("Particle")) { + ItemStack particleStack = ItemStack.of(compound.getCompound("Particle")); + SandPaperItem.spawnParticles(VecHelper.getCenterOf(worldPosition) + .add(getMovementVector().scale(reach + 1)), particleStack, this.level); + } + } + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + NBTHelper.writeEnum(compound, "Mode", mode); + NBTHelper.writeEnum(compound, "State", state); + compound.putInt("Timer", timer); + compound.putBoolean("Powered", redstoneLocked); + if (owner != null) + compound.putUUID("Owner", owner); + + if (player != null) { + ListTag invNBT = new ListTag(); + player.getInventory() + .save(invNBT); + compound.put("Inventory", invNBT); + compound.put("HeldItem", player.getMainHandItem() + .serializeNBT()); + compound.put("Overflow", NBTHelper.writeItemList(overflowItems)); + } else if (deferredInventoryList != null) { + compound.put("Inventory", deferredInventoryList); + } + + super.write(compound, clientPacket); + + if (!clientPacket) + return; + compound.putBoolean("Fistbump", fistBump); + compound.putFloat("Reach", reach); + if (player == null) + return; + compound.put("HeldItem", player.getMainHandItem() + .serializeNBT()); + if (player.spawnedItemEffects != null) { + compound.put("Particle", player.spawnedItemEffects.serializeNBT()); + player.spawnedItemEffects = null; + } + } + + @Override + public void writeSafe(CompoundTag tag) { + NBTHelper.writeEnum(tag, "Mode", mode); + super.writeSafe(tag); + } + + private IItemHandlerModifiable createHandler() { + return new DeployerItemHandler(this); + } + + public void redstoneUpdate() { + if (level.isClientSide) + return; + boolean blockPowered = level.hasNeighborSignal(worldPosition); + if (blockPowered == redstoneLocked) + return; + redstoneLocked = blockPowered; + sendData(); + } + + @OnlyIn(Dist.CLIENT) + public PartialModel getHandPose() { + return mode == Mode.PUNCH ? AllPartialModels.DEPLOYER_HAND_PUNCHING + : heldItem.isEmpty() ? AllPartialModels.DEPLOYER_HAND_POINTING : AllPartialModels.DEPLOYER_HAND_HOLDING; + } + + @Override + protected AABB createRenderBoundingBox() { + return super.createRenderBoundingBox().inflate(3); + } + + public void discardPlayer() { + if (player == null) + return; + player.getInventory() + .dropAll(); + overflowItems.forEach(itemstack -> player.drop(itemstack, true, false)); + player.discard(); + player = null; + } + + @Override + public void invalidate() { + super.invalidate(); + if (invHandler != null) + invHandler.invalidate(); + } + + public void changeMode() { + mode = mode == Mode.PUNCH ? Mode.USE : Mode.PUNCH; + setChanged(); + sendData(); + } + + @Override + public LazyOptional getCapability(Capability cap, Direction side) { + if (isItemHandlerCap(cap)) { + if (invHandler == null) + initHandler(); + return invHandler.cast(); + } + return super.getCapability(cap, side); + } + + @Override + public boolean addToTooltip(List tooltip, boolean isPlayerSneaking) { + if (super.addToTooltip(tooltip, isPlayerSneaking)) + return true; + if (getSpeed() == 0) + return false; + if (overflowItems.isEmpty()) + return false; + TooltipHelper.addHint(tooltip, "hint.full_deployer"); + return true; + } + + @Override + public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { + Lang.translate("tooltip.deployer.header") + .forGoggles(tooltip); + + Lang.translate("tooltip.deployer." + (mode == Mode.USE ? "using" : "punching")) + .style(ChatFormatting.YELLOW) + .forGoggles(tooltip); + + if (!heldItem.isEmpty()) + Lang.translate("tooltip.deployer.contains", Components.translatable(heldItem.getDescriptionId()) + .getString(), heldItem.getCount()) + .style(ChatFormatting.GREEN) + .forGoggles(tooltip); + + float stressAtBase = calculateStressApplied(); + if (StressImpact.isEnabled() && !Mth.equal(stressAtBase, 0)) { + tooltip.add(Components.immutableEmpty()); + addStressImpactStats(tooltip, stressAtBase); + } + + return true; + } + + @OnlyIn(Dist.CLIENT) + public float getHandOffset(float partialTicks) { + if (isVirtual()) + return animatedOffset.getValue(partialTicks); + + float progress = 0; + int timerSpeed = getTimerSpeed(); + PartialModel handPose = getHandPose(); + + if (state == State.EXPANDING) { + progress = 1 - (timer - partialTicks * timerSpeed) / 1000f; + if (fistBump) + progress *= progress; + } + if (state == State.RETRACTING) + progress = (timer - partialTicks * timerSpeed) / 1000f; + float handLength = handPose == AllPartialModels.DEPLOYER_HAND_POINTING ? 0 + : handPose == AllPartialModels.DEPLOYER_HAND_HOLDING ? 4 / 16f : 3 / 16f; + float distance = Math.min(Mth.clamp(progress, 0, 1) * (reach + handLength), 21 / 16f); + + return distance; + } + + public void setAnimatedOffset(float offset) { + animatedOffset.setValue(offset); + } + + RecipeWrapper recipeInv = new RecipeWrapper(new ItemStackHandler(2)); + SandPaperInv sandpaperInv = new SandPaperInv(ItemStack.EMPTY); + + @Nullable + public Recipe getRecipe(ItemStack stack) { + if (player == null || level == null) + return null; + + ItemStack heldItemMainhand = player.getMainHandItem(); + if (heldItemMainhand.getItem() instanceof SandPaperItem) { + sandpaperInv.setItem(0, stack); + return AllRecipeTypes.SANDPAPER_POLISHING.find(sandpaperInv, level) + .orElse(null); + } + + recipeInv.setItem(0, stack); + recipeInv.setItem(1, heldItemMainhand); + + DeployerRecipeSearchEvent event = new DeployerRecipeSearchEvent(this, recipeInv); + + event.addRecipe(() -> SequencedAssemblyRecipe.getRecipe(level, event.getInventory(), + AllRecipeTypes.DEPLOYING.getType(), DeployerApplicationRecipe.class), 100); + event.addRecipe(() -> AllRecipeTypes.DEPLOYING.find(event.getInventory(), level), 50); + event.addRecipe(() -> AllRecipeTypes.ITEM_APPLICATION.find(event.getInventory(), level), 50); + + MinecraftForge.EVENT_BUS.post(event); + return event.getRecipe(); + } + + public DeployerFakePlayer getPlayer() { + return player; + } +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerFakePlayer.java b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerFakePlayer.java new file mode 100644 index 000000000..a1242ce8b --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerFakePlayer.java @@ -0,0 +1,235 @@ +package com.simibubi.create.content.kinetics.deployer; + +import java.util.Objects; +import java.util.OptionalInt; +import java.util.UUID; + +import javax.annotation.Nullable; + +import org.apache.commons.lang3.tuple.Pair; + +import com.mojang.authlib.GameProfile; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.infrastructure.config.AllConfigs; +import com.simibubi.create.infrastructure.config.CKinetics; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.Connection; +import net.minecraft.network.PacketSendListener; +import net.minecraft.network.chat.Component; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.PacketFlow; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.network.ServerGamePacketListenerImpl; +import net.minecraft.world.MenuProvider; +import net.minecraft.world.damagesource.EntityDamageSource; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.Pose; +import net.minecraft.world.entity.monster.Creeper; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.common.UsernameCache; +import net.minecraftforge.common.util.FakePlayer; +import net.minecraftforge.event.entity.EntityEvent; +import net.minecraftforge.event.entity.living.LivingDropsEvent; +import net.minecraftforge.event.entity.living.LivingExperienceDropEvent; +import net.minecraftforge.event.entity.living.LivingSetAttackTargetEvent; +import net.minecraftforge.eventbus.api.EventPriority; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; + +@EventBusSubscriber +public class DeployerFakePlayer extends FakePlayer { + + private static final Connection NETWORK_MANAGER = new Connection(PacketFlow.CLIENTBOUND); + public static final UUID fallbackID = UUID.fromString("9e2faded-cafe-4ec2-c314-dad129ae971d"); + Pair blockBreakingProgress; + ItemStack spawnedItemEffects; + public boolean placedTracks; + public boolean onMinecartContraption; + private UUID owner; + + public DeployerFakePlayer(ServerLevel world, @Nullable UUID owner) { + super(world, new DeployerGameProfile(fallbackID, "Deployer", owner)); + connection = new FakePlayNetHandler(world.getServer(), this); + this.owner = owner; + } + + @Override + public OptionalInt openMenu(MenuProvider menuProvider) { + return OptionalInt.empty(); + } + + @Override + public Component getDisplayName() { + return Lang.translateDirect("block.deployer.damage_source_name"); + } + + @Override + @OnlyIn(Dist.CLIENT) + public float getEyeHeight(Pose poseIn) { + return 0; + } + + @Override + public Vec3 position() { + return new Vec3(getX(), getY(), getZ()); + } + + @Override + public float getCurrentItemAttackStrengthDelay() { + return 1 / 64f; + } + + @Override + public boolean canEat(boolean ignoreHunger) { + return false; + } + + @Override + public ItemStack eat(Level world, ItemStack stack) { + stack.shrink(1); + return stack; + } + + @Override + public boolean canBeAffected(MobEffectInstance pEffectInstance) { + return false; + } + + @Override + public UUID getUUID() { + return owner == null ? super.getUUID() : owner; + } + + @SubscribeEvent + public static void deployerHasEyesOnHisFeet(EntityEvent.Size event) { + if (event.getEntity() instanceof DeployerFakePlayer) + event.setNewEyeHeight(0); + } + + @SubscribeEvent(priority = EventPriority.LOWEST) + public static void deployerCollectsDropsFromKilledEntities(LivingDropsEvent event) { + if (!(event.getSource() instanceof EntityDamageSource)) + return; + EntityDamageSource source = (EntityDamageSource) event.getSource(); + Entity trueSource = source.getEntity(); + if (trueSource != null && trueSource instanceof DeployerFakePlayer) { + DeployerFakePlayer fakePlayer = (DeployerFakePlayer) trueSource; + event.getDrops() + .forEach(stack -> fakePlayer.getInventory() + .placeItemBackInInventory(stack.getItem())); + event.setCanceled(true); + } + } + + @Override + protected boolean doesEmitEquipEvent(EquipmentSlot p_217035_) { + return false; + } + + @Override + protected void playEquipSound(ItemStack p_217042_) {} + + @Override + public void remove(RemovalReason p_150097_) { + if (blockBreakingProgress != null && !level.isClientSide) + level.destroyBlockProgress(getId(), blockBreakingProgress.getKey(), -1); + super.remove(p_150097_); + } + + @SubscribeEvent + public static void deployerKillsDoNotSpawnXP(LivingExperienceDropEvent event) { + if (event.getAttackingPlayer() instanceof DeployerFakePlayer) + event.setCanceled(true); + } + + @SubscribeEvent + public static void entitiesDontRetaliate(LivingSetAttackTargetEvent event) { + if (!(event.getTarget() instanceof DeployerFakePlayer)) + return; + LivingEntity entityLiving = event.getEntity(); + if (!(entityLiving instanceof Mob)) + return; + Mob mob = (Mob) entityLiving; + + CKinetics.DeployerAggroSetting setting = AllConfigs.server().kinetics.ignoreDeployerAttacks.get(); + + switch (setting) { + case ALL: + mob.setTarget(null); + break; + case CREEPERS: + if (mob instanceof Creeper) + mob.setTarget(null); + break; + case NONE: + default: + } + } + + // Credit to Mekanism for this approach. Helps fake players get past claims and + // protection by other mods + private static class DeployerGameProfile extends GameProfile { + + private UUID owner; + + public DeployerGameProfile(UUID id, String name, UUID owner) { + super(id, name); + this.owner = owner; + } + + @Override + public UUID getId() { + return owner == null ? super.getId() : owner; + } + + @Override + public String getName() { + if (owner == null) + return super.getName(); + String lastKnownUsername = UsernameCache.getLastKnownUsername(owner); + return lastKnownUsername == null ? super.getName() : lastKnownUsername; + } + + @Override + public boolean equals(final Object o) { + if (this == o) + return true; + if (!(o instanceof GameProfile otherProfile)) + return false; + return Objects.equals(getId(), otherProfile.getId()) && Objects.equals(getName(), otherProfile.getName()); + } + + @Override + public int hashCode() { + UUID id = getId(); + String name = getName(); + int result = id == null ? 0 : id.hashCode(); + result = 31 * result + (name == null ? 0 : name.hashCode()); + return result; + } + } + + private static class FakePlayNetHandler extends ServerGamePacketListenerImpl { + public FakePlayNetHandler(MinecraftServer server, ServerPlayer playerIn) { + super(server, NETWORK_MANAGER, playerIn); + } + + @Override + public void send(Packet packetIn) {} + + @Override + public void send(Packet p_243227_, @Nullable PacketSendListener p_243273_) {} + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerFilterSlot.java b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerFilterSlot.java new file mode 100644 index 000000000..758d14d8a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerFilterSlot.java @@ -0,0 +1,59 @@ +package com.simibubi.create.content.kinetics.deployer; + +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class DeployerFilterSlot extends ValueBoxTransform.Sided { + + @Override + public Vec3 getLocalOffset(BlockState state) { + Direction facing = state.getValue(DeployerBlock.FACING); + Vec3 vec = VecHelper.voxelSpace(8f, 8f, 15.5f); + + vec = VecHelper.rotateCentered(vec, AngleHelper.horizontalAngle(getSide()), Axis.Y); + vec = VecHelper.rotateCentered(vec, AngleHelper.verticalAngle(getSide()), Axis.X); + vec = vec.subtract(Vec3.atLowerCornerOf(facing.getNormal()) + .scale(2 / 16f)); + + return vec; + } + + @Override + protected boolean isSideActive(BlockState state, Direction direction) { + Direction facing = state.getValue(DeployerBlock.FACING); + if (direction.getAxis() == facing.getAxis()) + return false; + if (((DeployerBlock) state.getBlock()).getRotationAxis(state) == direction.getAxis()) + return false; + return true; + } + + @Override + public void rotate(BlockState state, PoseStack ms) { + Direction facing = getSide(); + float xRot = facing == Direction.UP ? 90 : facing == Direction.DOWN ? 270 : 0; + float yRot = AngleHelper.horizontalAngle(facing) + 180; + + if (facing.getAxis() == Axis.Y) + TransformStack.cast(ms) + .rotateY(180 + AngleHelper.horizontalAngle(state.getValue(DeployerBlock.FACING))); + + TransformStack.cast(ms) + .rotateY(yRot) + .rotateX(xRot); + } + + @Override + protected Vec3 getSouthLocation() { + return Vec3.ZERO; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerHandler.java b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerHandler.java similarity index 94% rename from src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerHandler.java rename to src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerHandler.java index 29db146bd..c6f8a6d8d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerHandler.java +++ b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerHandler.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.deployer; +package com.simibubi.create.content.kinetics.deployer; import static net.minecraftforge.eventbus.api.Event.Result.DEFAULT; import static net.minecraftforge.eventbus.api.Event.Result.DENY; @@ -14,13 +14,13 @@ import org.apache.commons.lang3.tuple.Pair; import com.google.common.collect.Multimap; import com.simibubi.create.AllSoundEvents; import com.simibubi.create.AllTags.AllItemTags; -import com.simibubi.create.content.contraptions.components.deployer.DeployerTileEntity.Mode; -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerBlockItem; -import com.simibubi.create.content.curiosities.tools.SandPaperItem; -import com.simibubi.create.content.logistics.trains.ITrackBlock; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.mounted.CartAssemblerBlockItem; +import com.simibubi.create.content.equipment.sandPaper.SandPaperItem; +import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour; +import com.simibubi.create.content.kinetics.deployer.DeployerBlockEntity.Mode; +import com.simibubi.create.content.trains.track.ITrackBlock; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.utility.BlockHelper; import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld; @@ -121,7 +121,7 @@ public class DeployerHandler { } if (!held.isEmpty() && facing == Direction.DOWN - && TileEntityBehaviour.get(world, targetPos, TransportedItemStackHandlerBehaviour.TYPE) != null) + && BlockEntityBehaviour.get(world, targetPos, TransportedItemStackHandlerBehaviour.TYPE) != null) return false; return true; @@ -364,7 +364,7 @@ public class DeployerHandler { if (net.minecraftforge.common.ForgeHooks.onBlockBreakEvent(world, gameType, player, pos) == -1) return false; - BlockEntity tileentity = world.getBlockEntity(pos); + BlockEntity blockEntity = world.getBlockEntity(pos); if (player.getMainHandItem() .onBlockStartBreak(pos, player)) return false; @@ -398,7 +398,7 @@ public class DeployerHandler { if (!canHarvest) return true; - Block.getDrops(blockstate, world, pos, tileentity, player, prevHeldItem) + Block.getDrops(blockstate, world, pos, blockEntity, player, prevHeldItem) .forEach(item -> player.getInventory().placeItemBackInInventory(item)); blockstate.spawnAfterBreak(world, pos, prevHeldItem, true); return true; diff --git a/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerInstance.java b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerInstance.java new file mode 100644 index 000000000..99cd1728e --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerInstance.java @@ -0,0 +1,134 @@ +package com.simibubi.create.content.kinetics.deployer; + +import static com.simibubi.create.content.kinetics.base.DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE; +import static com.simibubi.create.content.kinetics.base.DirectionalKineticBlock.FACING; + +import org.joml.Quaternionf; + +import com.jozufozu.flywheel.api.MaterialManager; +import com.jozufozu.flywheel.api.instance.DynamicInstance; +import com.jozufozu.flywheel.api.instance.TickableInstance; +import com.jozufozu.flywheel.core.PartialModel; +import com.jozufozu.flywheel.core.materials.oriented.OrientedData; +import com.mojang.math.Axis; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.ShaftInstance; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.AnimationTickHolder; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Vec3i; +import net.minecraft.util.Mth; + +public class DeployerInstance extends ShaftInstance implements DynamicInstance, TickableInstance { + + final Direction facing; + final float yRot; + final float xRot; + final float zRot; + + protected final OrientedData pole; + + protected OrientedData hand; + + PartialModel currentHand; + float progress; + + public DeployerInstance(MaterialManager materialManager, DeployerBlockEntity blockEntity) { + super(materialManager, blockEntity); + + facing = blockState.getValue(FACING); + + boolean rotatePole = blockState.getValue(AXIS_ALONG_FIRST_COORDINATE) ^ facing.getAxis() == Direction.Axis.Z; + + yRot = AngleHelper.horizontalAngle(facing); + xRot = facing == Direction.UP ? 270 : facing == Direction.DOWN ? 90 : 0; + zRot = rotatePole ? 90 : 0; + + pole = getOrientedMaterial().getModel(AllPartialModels.DEPLOYER_POLE, blockState).createInstance(); + + currentHand = this.blockEntity.getHandPose(); + + hand = getOrientedMaterial().getModel(currentHand, blockState).createInstance(); + + progress = getProgress(AnimationTickHolder.getPartialTicks()); + updateRotation(pole, hand, yRot, xRot, zRot); + updatePosition(); + } + + @Override + public void tick() { + PartialModel handPose = blockEntity.getHandPose(); + + if (currentHand != handPose) { + currentHand = handPose; + getOrientedMaterial().getModel(currentHand, blockState) + .stealInstance(hand); + } + } + + @Override + public void beginFrame() { + + float newProgress = getProgress(AnimationTickHolder.getPartialTicks()); + + if (Mth.equal(newProgress, progress)) return; + + progress = newProgress; + + updatePosition(); + } + + @Override + public void updateLight() { + super.updateLight(); + relight(pos, hand, pole); + } + + @Override + public void remove() { + super.remove(); + hand.delete(); + pole.delete(); + } + + private float getProgress(float partialTicks) { + if (blockEntity.state == DeployerBlockEntity.State.EXPANDING) { + float f = 1 - (blockEntity.timer - partialTicks * blockEntity.getTimerSpeed()) / 1000f; + if (blockEntity.fistBump) + f *= f; + return f; + } + if (blockEntity.state == DeployerBlockEntity.State.RETRACTING) + return (blockEntity.timer - partialTicks * blockEntity.getTimerSpeed()) / 1000f; + return 0; + } + + private void updatePosition() { + float handLength = currentHand == AllPartialModels.DEPLOYER_HAND_POINTING ? 0 + : currentHand == AllPartialModels.DEPLOYER_HAND_HOLDING ? 4 / 16f : 3 / 16f; + float distance = Math.min(Mth.clamp(progress, 0, 1) * (blockEntity.reach + handLength), 21 / 16f); + Vec3i facingVec = facing.getNormal(); + BlockPos blockPos = getInstancePosition(); + + float x = blockPos.getX() + ((float) facingVec.getX()) * distance; + float y = blockPos.getY() + ((float) facingVec.getY()) * distance; + float z = blockPos.getZ() + ((float) facingVec.getZ()) * distance; + + pole.setPosition(x, y, z); + hand.setPosition(x, y, z); + } + + static void updateRotation(OrientedData pole, OrientedData hand, float yRot, float xRot, float zRot) { + + Quaternionf q = Axis.YP.rotationDegrees(yRot); + q.mul(Axis.XP.rotationDegrees(xRot)); + + hand.setRotation(q); + + q.mul(Axis.ZP.rotationDegrees(zRot)); + + pole.setRotation(q); + } +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerItemHandler.java b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerItemHandler.java new file mode 100644 index 000000000..ecabcf2ed --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerItemHandler.java @@ -0,0 +1,131 @@ +package com.simibubi.create.content.kinetics.deployer; + +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; + +import net.minecraft.world.InteractionHand; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.ItemHandlerHelper; + +public class DeployerItemHandler implements IItemHandlerModifiable { + + private DeployerBlockEntity be; + private DeployerFakePlayer player; + + public DeployerItemHandler(DeployerBlockEntity be) { + this.be = be; + this.player = be.player; + } + + @Override + public int getSlots() { + return 1 + be.overflowItems.size(); + } + + @Override + public ItemStack getStackInSlot(int slot) { + return slot >= be.overflowItems.size() ? getHeld() : be.overflowItems.get(slot); + } + + public ItemStack getHeld() { + if (player == null) + return ItemStack.EMPTY; + return player.getMainHandItem(); + } + + public void set(ItemStack stack) { + if (player == null) + return; + if (be.getLevel().isClientSide) + return; + player.setItemInHand(InteractionHand.MAIN_HAND, stack); + be.setChanged(); + be.sendData(); + } + + @Override + public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) { + if (slot < be.overflowItems.size()) + return stack; + if (!isItemValid(slot, stack)) + return stack; + + ItemStack held = getHeld(); + if (held.isEmpty()) { + if (!simulate) + set(stack); + return ItemStack.EMPTY; + } + + if (!ItemHandlerHelper.canItemStacksStack(held, stack)) + return stack; + + int space = held.getMaxStackSize() - held.getCount(); + ItemStack remainder = stack.copy(); + ItemStack split = remainder.split(space); + + if (space == 0) + return stack; + if (!simulate) { + held = held.copy(); + held.setCount(held.getCount() + split.getCount()); + set(held); + } + + return remainder; + } + + @Override + public ItemStack extractItem(int slot, int amount, boolean simulate) { + if (amount == 0) + return ItemStack.EMPTY; + + if (slot < be.overflowItems.size()) { + ItemStack itemStack = be.overflowItems.get(slot); + int toExtract = Math.min(amount, itemStack.getCount()); + ItemStack extracted = simulate ? itemStack.copy() : itemStack.split(toExtract); + extracted.setCount(toExtract); + if (!simulate && itemStack.isEmpty()) + be.overflowItems.remove(slot); + if (!simulate && !extracted.isEmpty()) + be.setChanged(); + return extracted; + } + + ItemStack held = getHeld(); + if (amount == 0 || held.isEmpty()) + return ItemStack.EMPTY; + if (!be.filtering.getFilter() + .isEmpty() && be.filtering.test(held)) + return ItemStack.EMPTY; + if (simulate) + return held.copy() + .split(amount); + + ItemStack toReturn = held.split(amount); + be.setChanged(); + be.sendData(); + return toReturn; + } + + @Override + public int getSlotLimit(int slot) { + return Math.min(getStackInSlot(slot).getMaxStackSize(), 64); + } + + @Override + public boolean isItemValid(int slot, ItemStack stack) { + FilteringBehaviour filteringBehaviour = be.getBehaviour(FilteringBehaviour.TYPE); + return filteringBehaviour == null || filteringBehaviour.test(stack); + } + + @Override + public void setStackInSlot(int slot, ItemStack stack) { + if (slot < be.overflowItems.size()) { + be.overflowItems.set(slot, stack); + return; + } + set(stack); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerMovementBehaviour.java b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerMovementBehaviour.java similarity index 79% rename from src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerMovementBehaviour.java rename to src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerMovementBehaviour.java index e64bfce04..305dbde12 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerMovementBehaviour.java @@ -1,7 +1,8 @@ -package com.simibubi.create.content.contraptions.components.deployer; +package com.simibubi.create.content.kinetics.deployer; import java.util.Arrays; import java.util.List; +import java.util.UUID; import javax.annotation.Nullable; @@ -11,28 +12,26 @@ import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; -import com.simibubi.create.AllTags.AllBlockTags; -import com.simibubi.create.content.contraptions.components.deployer.DeployerTileEntity.Mode; -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; -import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.mounted.MountedContraption; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; -import com.simibubi.create.content.logistics.item.filter.FilterItem; -import com.simibubi.create.content.logistics.trains.entity.CarriageContraption; -import com.simibubi.create.content.logistics.trains.entity.CarriageContraptionEntity; -import com.simibubi.create.content.schematics.ItemRequirement; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.OrientedContraptionEntity; +import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.contraptions.mounted.MountedContraption; +import com.simibubi.create.content.contraptions.render.ActorInstance; +import com.simibubi.create.content.contraptions.render.ContraptionMatrices; +import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher; +import com.simibubi.create.content.kinetics.deployer.DeployerBlockEntity.Mode; +import com.simibubi.create.content.logistics.filter.FilterItem; +import com.simibubi.create.content.schematics.SchematicInstances; import com.simibubi.create.content.schematics.SchematicWorld; -import com.simibubi.create.content.schematics.filtering.SchematicInstances; +import com.simibubi.create.content.schematics.requirement.ItemRequirement; +import com.simibubi.create.content.trains.entity.CarriageContraption; +import com.simibubi.create.content.trains.entity.CarriageContraptionEntity; import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.item.ItemHelper; import com.simibubi.create.foundation.item.ItemHelper.ExtractionCountMode; import com.simibubi.create.foundation.utility.BlockHelper; import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.NBTProcessors; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.client.renderer.MultiBufferSource; @@ -47,7 +46,6 @@ import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.player.Inventory; 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.Vec3; import net.minecraftforge.common.util.BlockSnapshot; @@ -108,8 +106,8 @@ public class DeployerMovementBehaviour implements MovementBehaviour { DeployerHandler.activate(player, vec, pos, facingVec, mode); if ((context.contraption instanceof MountedContraption || context.contraption instanceof CarriageContraption) - && player.placedTracks && context.tileData != null && context.tileData.contains("Owner")) - AllAdvancements.SELF_DEPLOYING.awardTo(world.getPlayerByUUID(context.tileData.getUUID("Owner"))); + && player.placedTracks && context.blockEntityData != null && context.blockEntityData.contains("Owner")) + AllAdvancements.SELF_DEPLOYING.awardTo(world.getPlayerByUUID(context.blockEntityData.getUUID("Owner"))); } protected void activateAsSchematicPrinter(MovementContext context, BlockPos pos, DeployerFakePlayer player, @@ -141,28 +139,20 @@ public class DeployerMovementBehaviour implements MovementBehaviour { ItemStack contextStack = requiredItems.isEmpty() ? ItemStack.EMPTY : requiredItems.get(0).stack; if (!context.contraption.hasUniversalCreativeCrate) { - IItemHandler iItemHandler = context.contraption.getSharedInventory(); + IItemHandler itemHandler = context.contraption.getSharedInventory(); for (ItemRequirement.StackRequirement required : requiredItems) { ItemStack stack= ItemHelper - .extract(iItemHandler, required::matches, ExtractionCountMode.EXACTLY, + .extract(itemHandler, required::matches, ExtractionCountMode.EXACTLY, required.stack.getCount(), true); if (stack.isEmpty()) return; } for (ItemRequirement.StackRequirement required : requiredItems) - contextStack = ItemHelper.extract(iItemHandler, required::matches, + contextStack = ItemHelper.extract(itemHandler, required::matches, ExtractionCountMode.EXACTLY, required.stack.getCount(), false); } - CompoundTag data = null; - if (AllBlockTags.SAFE_NBT.matches(blockState)) { - BlockEntity tile = schematicWorld.getBlockEntity(pos); - if (tile != null) { - data = tile.saveWithFullMetadata(); - data = NBTProcessors.process(tile, data, true); - } - } - + CompoundTag data = BlockHelper.prepareBlockEntityData(blockState, schematicWorld.getBlockEntity(pos)); BlockSnapshot blocksnapshot = BlockSnapshot.create(world.dimension(), world, pos); BlockHelper.placeSchematicBlock(world, blockState, pos, contextStack, data); if (ForgeEventFactory.onBlockPlace(player, blocksnapshot, Direction.UP)) @@ -221,7 +211,7 @@ public class DeployerMovementBehaviour implements MovementBehaviour { return; cancelStall(context); - context.tileData.put("Inventory", player.getInventory() + context.blockEntityData.put("Inventory", player.getInventory() .save(new ListTag())); player.discard(); } @@ -274,25 +264,26 @@ public class DeployerMovementBehaviour implements MovementBehaviour { private DeployerFakePlayer getPlayer(MovementContext context) { if (!(context.temporaryData instanceof DeployerFakePlayer) && context.world instanceof ServerLevel) { - DeployerFakePlayer deployerFakePlayer = new DeployerFakePlayer((ServerLevel) context.world); + UUID owner = context.blockEntityData.contains("Owner") ? context.blockEntityData.getUUID("Owner") : null; + DeployerFakePlayer deployerFakePlayer = new DeployerFakePlayer((ServerLevel) context.world, owner); deployerFakePlayer.onMinecartContraption = context.contraption instanceof MountedContraption; deployerFakePlayer.getInventory() - .load(context.tileData.getList("Inventory", Tag.TAG_COMPOUND)); + .load(context.blockEntityData.getList("Inventory", Tag.TAG_COMPOUND)); if (context.data.contains("HeldItem")) deployerFakePlayer.setItemInHand(InteractionHand.MAIN_HAND, ItemStack.of(context.data.getCompound("HeldItem"))); - context.tileData.remove("Inventory"); + context.blockEntityData.remove("Inventory"); context.temporaryData = deployerFakePlayer; } return (DeployerFakePlayer) context.temporaryData; } private ItemStack getFilter(MovementContext context) { - return ItemStack.of(context.tileData.getCompound("Filter")); + return ItemStack.of(context.blockEntityData.getCompound("Filter")); } private Mode getMode(MovementContext context) { - return NBTHelper.readEnum(context.tileData, "Mode", Mode.class); + return NBTHelper.readEnum(context.blockEntityData, "Mode", Mode.class); } @Override diff --git a/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerMovingInteraction.java b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerMovingInteraction.java new file mode 100644 index 000000000..1c07c4972 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerMovingInteraction.java @@ -0,0 +1,69 @@ +package com.simibubi.create.content.kinetics.deployer; + +import java.util.UUID; + +import org.apache.commons.lang3.tuple.MutablePair; + +import com.simibubi.create.AllItems; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.contraptions.behaviour.MovingInteractionBehaviour; +import com.simibubi.create.content.contraptions.mounted.MountedContraption; +import com.simibubi.create.foundation.utility.NBTHelper; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.Tag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; + +public class DeployerMovingInteraction extends MovingInteractionBehaviour { + + @Override + public boolean handlePlayerInteraction(Player player, InteractionHand activeHand, BlockPos localPos, + AbstractContraptionEntity contraptionEntity) { + MutablePair actor = contraptionEntity.getContraption() + .getActorAt(localPos); + if (actor == null || actor.right == null) + return false; + + MovementContext ctx = actor.right; + ItemStack heldStack = player.getItemInHand(activeHand); + if (heldStack.getItem() + .equals(AllItems.WRENCH.get())) { + DeployerBlockEntity.Mode mode = NBTHelper.readEnum(ctx.blockEntityData, "Mode", DeployerBlockEntity.Mode.class); + NBTHelper.writeEnum(ctx.blockEntityData, "Mode", + mode == DeployerBlockEntity.Mode.PUNCH ? DeployerBlockEntity.Mode.USE : DeployerBlockEntity.Mode.PUNCH); + + } else { + if (ctx.world.isClientSide) + return true; // we'll try again on the server side + DeployerFakePlayer fake = null; + + if (!(ctx.temporaryData instanceof DeployerFakePlayer) && ctx.world instanceof ServerLevel) { + UUID owner = ctx.blockEntityData.contains("Owner") ? ctx.blockEntityData.getUUID("Owner") : null; + DeployerFakePlayer deployerFakePlayer = new DeployerFakePlayer((ServerLevel) ctx.world, owner); + deployerFakePlayer.onMinecartContraption = ctx.contraption instanceof MountedContraption; + deployerFakePlayer.getInventory() + .load(ctx.blockEntityData.getList("Inventory", Tag.TAG_COMPOUND)); + ctx.temporaryData = fake = deployerFakePlayer; + ctx.blockEntityData.remove("Inventory"); + } else + fake = (DeployerFakePlayer) ctx.temporaryData; + + if (fake == null) + return false; + + ItemStack deployerItem = fake.getMainHandItem(); + player.setItemInHand(activeHand, deployerItem.copy()); + fake.setItemInHand(InteractionHand.MAIN_HAND, heldStack.copy()); + ctx.blockEntityData.put("HeldItem", heldStack.serializeNBT()); + ctx.data.put("HeldItem", heldStack.serializeNBT()); + } +// if (index >= 0) +// setContraptionActorData(contraptionEntity, index, info, ctx); + return true; + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerRecipeSearchEvent.java b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerRecipeSearchEvent.java similarity index 79% rename from src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerRecipeSearchEvent.java rename to src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerRecipeSearchEvent.java index e1c6db1fa..42f1dfd47 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerRecipeSearchEvent.java +++ b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerRecipeSearchEvent.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.deployer; +package com.simibubi.create.content.kinetics.deployer; import java.util.Optional; import java.util.function.Supplier; @@ -11,14 +11,14 @@ import net.minecraftforge.eventbus.api.Event; import net.minecraftforge.items.wrapper.RecipeWrapper; public class DeployerRecipeSearchEvent extends Event { - private final DeployerTileEntity tileEntity; + private final DeployerBlockEntity blockEntity; private final RecipeWrapper inventory; @Nullable Recipe recipe = null; private int maxPriority = 0; - public DeployerRecipeSearchEvent(DeployerTileEntity tileEntity, RecipeWrapper inventory) { - this.tileEntity = tileEntity; + public DeployerRecipeSearchEvent(DeployerBlockEntity blockEntity, RecipeWrapper inventory) { + this.blockEntity = blockEntity; this.inventory = inventory; } @@ -27,8 +27,8 @@ public class DeployerRecipeSearchEvent extends Event { return true; } - public DeployerTileEntity getTileEntity() { - return tileEntity; + public DeployerBlockEntity getBlockEntity() { + return blockEntity; } public RecipeWrapper getInventory() { diff --git a/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerRenderer.java new file mode 100644 index 000000000..b89fe89ac --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerRenderer.java @@ -0,0 +1,230 @@ +package com.simibubi.create.content.kinetics.deployer; + +import static com.simibubi.create.content.kinetics.base.DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE; +import static com.simibubi.create.content.kinetics.base.DirectionalKineticBlock.FACING; + +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.core.PartialModel; +import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.math.Axis; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.contraptions.render.ContraptionMatrices; +import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher; +import com.simibubi.create.content.kinetics.base.IRotate; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.content.kinetics.deployer.DeployerBlockEntity.Mode; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringRenderer; +import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.NBTHelper; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.block.model.ItemTransforms.TransformType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.client.renderer.entity.ItemRenderer; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.util.Mth; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class DeployerRenderer extends SafeBlockEntityRenderer { + + public DeployerRenderer(BlockEntityRendererProvider.Context context) { + } + + @Override + protected void renderSafe(DeployerBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + renderItem(be, partialTicks, ms, buffer, light, overlay); + FilteringRenderer.renderOnBlockEntity(be, partialTicks, ms, buffer, light, overlay); + + if (Backend.canUseInstancing(be.getLevel())) return; + + renderComponents(be, partialTicks, ms, buffer, light, overlay); + } + + protected void renderItem(DeployerBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + + if (be.heldItem.isEmpty()) return; + + BlockState deployerState = be.getBlockState(); + Vec3 offset = getHandOffset(be, partialTicks, deployerState).add(VecHelper.getCenterOf(BlockPos.ZERO)); + ms.pushPose(); + ms.translate(offset.x, offset.y, offset.z); + + Direction facing = deployerState.getValue(FACING); + boolean punching = be.mode == Mode.PUNCH; + + float yRot = AngleHelper.horizontalAngle(facing) + 180; + float xRot = facing == Direction.UP ? 90 : facing == Direction.DOWN ? 270 : 0; + boolean displayMode = facing == Direction.UP && be.getSpeed() == 0 && !punching; + + ms.mulPose(Axis.YP.rotationDegrees(yRot)); + if (!displayMode) { + ms.mulPose(Axis.XP.rotationDegrees(xRot)); + ms.translate(0, 0, -11 / 16f); + } + + if (punching) + ms.translate(0, 1 / 8f, -1 / 16f); + + ItemRenderer itemRenderer = Minecraft.getInstance() + .getItemRenderer(); + + TransformType transform = TransformType.NONE; + boolean isBlockItem = (be.heldItem.getItem() instanceof BlockItem) + && itemRenderer.getModel(be.heldItem, be.getLevel(), null, 0) + .isGui3d(); + + if (displayMode) { + float scale = isBlockItem ? 1.25f : 1; + ms.translate(0, isBlockItem ? 9 / 16f : 11 / 16f, 0); + ms.scale(scale, scale, scale); + transform = TransformType.GROUND; + ms.mulPose(Axis.YP.rotationDegrees(AnimationTickHolder.getRenderTime(be.getLevel()))); + + } else { + float scale = punching ? .75f : isBlockItem ? .75f - 1 / 64f : .5f; + ms.scale(scale, scale, scale); + transform = punching ? TransformType.THIRD_PERSON_RIGHT_HAND : TransformType.FIXED; + } + + itemRenderer.renderStatic(be.heldItem, transform, light, overlay, ms, buffer, 0); + ms.popPose(); + } + + protected void renderComponents(DeployerBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + VertexConsumer vb = buffer.getBuffer(RenderType.solid()); + if (!Backend.canUseInstancing(be.getLevel())) { + KineticBlockEntityRenderer.renderRotatingKineticBlock(be, getRenderedBlockState(be), ms, vb, light); + } + + BlockState blockState = be.getBlockState(); + Vec3 offset = getHandOffset(be, partialTicks, blockState); + + SuperByteBuffer pole = CachedBufferer.partial(AllPartialModels.DEPLOYER_POLE, blockState); + SuperByteBuffer hand = CachedBufferer.partial(be.getHandPose(), blockState); + + transform(pole.translate(offset.x, offset.y, offset.z), blockState, true) + .light(light) + .renderInto(ms, vb); + transform(hand.translate(offset.x, offset.y, offset.z), blockState, false) + .light(light) + .renderInto(ms, vb); + } + + protected Vec3 getHandOffset(DeployerBlockEntity be, float partialTicks, BlockState blockState) { + float distance = be.getHandOffset(partialTicks); + return Vec3.atLowerCornerOf(blockState.getValue(FACING).getNormal()).scale(distance); + } + + protected BlockState getRenderedBlockState(KineticBlockEntity be) { + return KineticBlockEntityRenderer.shaft(KineticBlockEntityRenderer.getRotationAxisOf(be)); + } + + private static SuperByteBuffer transform(SuperByteBuffer buffer, BlockState deployerState, boolean axisDirectionMatters) { + Direction facing = deployerState.getValue(FACING); + + float yRot = AngleHelper.horizontalAngle(facing); + float xRot = facing == Direction.UP ? 270 : facing == Direction.DOWN ? 90 : 0; + float zRot = + axisDirectionMatters && (deployerState.getValue(AXIS_ALONG_FIRST_COORDINATE) ^ facing.getAxis() == Direction.Axis.Z) ? 90 + : 0; + + buffer.rotateCentered(Direction.UP, (float) ((yRot) / 180 * Math.PI)); + buffer.rotateCentered(Direction.EAST, (float) ((xRot) / 180 * Math.PI)); + buffer.rotateCentered(Direction.SOUTH, (float) ((zRot) / 180 * Math.PI)); + return buffer; + } + + public static void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld, + ContraptionMatrices matrices, MultiBufferSource buffer) { + VertexConsumer builder = buffer.getBuffer(RenderType.solid()); + BlockState blockState = context.state; + Mode mode = NBTHelper.readEnum(context.blockEntityData, "Mode", Mode.class); + PartialModel handPose = getHandPose(mode); + + float speed = (float) context.getAnimationSpeed(); + if (context.contraption.stalled) + speed = 0; + + SuperByteBuffer shaft = CachedBufferer.block(AllBlocks.SHAFT.getDefaultState()); + SuperByteBuffer pole = CachedBufferer.partial(AllPartialModels.DEPLOYER_POLE, blockState); + SuperByteBuffer hand = CachedBufferer.partial(handPose, blockState); + + double factor; + if (context.contraption.stalled || context.position == null || context.data.contains("StationaryTimer")) { + factor = Mth.sin(AnimationTickHolder.getRenderTime() * .5f) * .25f + .25f; + } else { + Vec3 center = VecHelper.getCenterOf(new BlockPos(context.position)); + double distance = context.position.distanceTo(center); + double nextDistance = context.position.add(context.motion) + .distanceTo(center); + factor = .5f - Mth.clamp(Mth.lerp(AnimationTickHolder.getPartialTicks(), distance, nextDistance), 0, 1); + } + + Vec3 offset = Vec3.atLowerCornerOf(blockState.getValue(FACING) + .getNormal()).scale(factor); + + PoseStack m = matrices.getModel(); + m.pushPose(); + + m.pushPose(); + Direction.Axis axis = Direction.Axis.Y; + if (context.state.getBlock() instanceof IRotate) { + IRotate def = (IRotate) context.state.getBlock(); + axis = def.getRotationAxis(context.state); + } + + float time = AnimationTickHolder.getRenderTime(context.world) / 20; + float angle = (time * speed) % 360; + + TransformStack.cast(m) + .centre() + .rotateY(axis == Direction.Axis.Z ? 90 : 0) + .rotateZ(axis.isHorizontal() ? 90 : 0) + .unCentre(); + shaft.transform(m); + shaft.rotateCentered(Direction.get(AxisDirection.POSITIVE, Direction.Axis.Y), angle); + m.popPose(); + + if (!context.disabled) + m.translate(offset.x, offset.y, offset.z); + pole.transform(m); + hand.transform(m); + + transform(pole, blockState, true); + transform(hand, blockState, false); + + shaft.light(matrices.getWorld(), ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) + .renderInto(matrices.getViewProjection(), builder); + pole.light(matrices.getWorld(), ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) + .renderInto(matrices.getViewProjection(), builder); + hand.light(matrices.getWorld(), ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) + .renderInto(matrices.getViewProjection(), builder); + + m.popPose(); + } + + static PartialModel getHandPose(DeployerBlockEntity.Mode mode) { + return mode == DeployerBlockEntity.Mode.PUNCH ? AllPartialModels.DEPLOYER_HAND_PUNCHING : AllPartialModels.DEPLOYER_HAND_POINTING; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/ItemApplicationRecipe.java b/src/main/java/com/simibubi/create/content/kinetics/deployer/ItemApplicationRecipe.java similarity index 89% rename from src/main/java/com/simibubi/create/content/contraptions/processing/ItemApplicationRecipe.java rename to src/main/java/com/simibubi/create/content/kinetics/deployer/ItemApplicationRecipe.java index caee145e4..a57cb1374 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/ItemApplicationRecipe.java +++ b/src/main/java/com/simibubi/create/content/kinetics/deployer/ItemApplicationRecipe.java @@ -1,8 +1,9 @@ -package com.simibubi.create.content.contraptions.processing; +package com.simibubi.create.content.kinetics.deployer; import com.google.gson.JsonObject; import com.simibubi.create.AllRecipeTypes; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder.ProcessingRecipeParams; +import com.simibubi.create.content.processing.recipe.ProcessingRecipe; +import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder.ProcessingRecipeParams; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.util.GsonHelper; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/ManualApplicationRecipe.java b/src/main/java/com/simibubi/create/content/kinetics/deployer/ManualApplicationRecipe.java similarity index 92% rename from src/main/java/com/simibubi/create/content/contraptions/components/deployer/ManualApplicationRecipe.java rename to src/main/java/com/simibubi/create/content/kinetics/deployer/ManualApplicationRecipe.java index d8f6dfd2a..b95ea094e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/ManualApplicationRecipe.java +++ b/src/main/java/com/simibubi/create/content/kinetics/deployer/ManualApplicationRecipe.java @@ -1,14 +1,13 @@ -package com.simibubi.create.content.contraptions.components.deployer; +package com.simibubi.create.content.kinetics.deployer; import java.util.List; import java.util.Optional; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllRecipeTypes; -import com.simibubi.create.content.contraptions.processing.ItemApplicationRecipe; -import com.simibubi.create.content.contraptions.processing.ProcessingOutput; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder.ProcessingRecipeParams; +import com.simibubi.create.content.processing.recipe.ProcessingOutput; +import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder; +import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder.ProcessingRecipeParams; import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.advancement.CreateAdvancement; import com.simibubi.create.foundation.utility.BlockHelper; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillActorInstance.java b/src/main/java/com/simibubi/create/content/kinetics/drill/DrillActorInstance.java similarity index 81% rename from src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillActorInstance.java rename to src/main/java/com/simibubi/create/content/kinetics/drill/DrillActorInstance.java index 6d04ed77e..1f22043b1 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillActorInstance.java +++ b/src/main/java/com/simibubi/create/content/kinetics/drill/DrillActorInstance.java @@ -1,14 +1,14 @@ -package com.simibubi.create.content.contraptions.components.actors; +package com.simibubi.create.content.kinetics.drill; import org.joml.Quaternionf; import com.jozufozu.flywheel.api.Material; import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.components.actors.flwdata.ActorData; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.contraptions.actors.flwdata.ActorData; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.contraptions.render.ActorInstance; import com.simibubi.create.foundation.render.AllMaterialSpecs; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.VecHelper; @@ -41,7 +41,7 @@ public class DrillActorInstance extends ActorInstance { else eulerY = facing.toYRot() + ((axis == Direction.Axis.X) ? 180 : 0); - drillHead = material.getModel(AllBlockPartials.DRILL_HEAD, state).createInstance(); + drillHead = material.getModel(AllPartialModels.DRILL_HEAD, state).createInstance(); drillHead.setPosition(context.localPos) .setBlockLight(localBlockLight()) diff --git a/src/main/java/com/simibubi/create/content/kinetics/drill/DrillBlock.java b/src/main/java/com/simibubi/create/content/kinetics/drill/DrillBlock.java new file mode 100644 index 000000000..16b3c97f8 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/drill/DrillBlock.java @@ -0,0 +1,201 @@ +package com.simibubi.create.content.kinetics.drill; + +import java.util.List; +import java.util.function.Predicate; + +import javax.annotation.ParametersAreNonnullByDefault; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllShapes; +import com.simibubi.create.content.kinetics.base.DirectionalKineticBlock; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.placement.IPlacementHelper; +import com.simibubi.create.foundation.placement.PlacementHelpers; +import com.simibubi.create.foundation.placement.PlacementOffset; + +import net.minecraft.MethodsReturnNonnullByDefault; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.util.Mth; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +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.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.SimpleWaterloggedBlock; +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.BlockStateProperties; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.level.material.Fluids; +import net.minecraft.world.level.material.PushReaction; +import net.minecraft.world.level.pathfinder.PathComputationType; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +public class DrillBlock extends DirectionalKineticBlock implements IBE, SimpleWaterloggedBlock { + public static DamageSource damageSourceDrill = new DamageSource("create.mechanical_drill").bypassArmor(); + + private static final int placementHelperId = PlacementHelpers.register(new PlacementHelper()); + + public DrillBlock(Properties properties) { + super(properties); + registerDefaultState(super.defaultBlockState().setValue(BlockStateProperties.WATERLOGGED, false)); + } + + @Override + public void entityInside(BlockState state, Level worldIn, BlockPos pos, Entity entityIn) { + if (entityIn instanceof ItemEntity) + return; + if (!new AABB(pos).deflate(.1f) + .intersects(entityIn.getBoundingBox())) + return; + withBlockEntityDo(worldIn, pos, be -> { + if (be.getSpeed() == 0) + return; + entityIn.hurt(damageSourceDrill, (float) getDamage(be.getSpeed())); + }); + } + + @Override + public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) { + return AllShapes.CASING_12PX.get(state.getValue(FACING)); + } + + @Override + public void neighborChanged(BlockState state, Level worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, + boolean isMoving) { + withBlockEntityDo(worldIn, pos, DrillBlockEntity::destroyNextTick); + } + + @Override + public Axis getRotationAxis(BlockState state) { + return state.getValue(FACING) + .getAxis(); + } + + @Override + public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) { + return face == state.getValue(FACING) + .getOpposite(); + } + + @Override + public PushReaction getPistonPushReaction(BlockState state) { + return PushReaction.NORMAL; + } + + @Override + public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) { + return false; + } + + @Override + public FluidState getFluidState(BlockState state) { + return state.getValue(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getSource(false) : Fluids.EMPTY.defaultFluidState(); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder builder) { + builder.add(BlockStateProperties.WATERLOGGED); + super.createBlockStateDefinition(builder); + } + + @Override + public BlockState updateShape(BlockState state, Direction direction, BlockState neighbourState, + LevelAccessor world, BlockPos pos, BlockPos neighbourPos) { + if (state.getValue(BlockStateProperties.WATERLOGGED)) + world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world)); + return state; + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext context) { + FluidState FluidState = context.getLevel().getFluidState(context.getClickedPos()); + return super.getStateForPlacement(context).setValue(BlockStateProperties.WATERLOGGED, Boolean.valueOf(FluidState.getType() == Fluids.WATER)); + } + + public static double getDamage(float speed) { + float speedAbs = Math.abs(speed); + double sub1 = Math.min(speedAbs / 16, 2); + double sub2 = Math.min(speedAbs / 32, 4); + double sub3 = Math.min(speedAbs / 64, 4); + return Mth.clamp(sub1 + sub2 + sub3, 1, 10); + } + + @Override + public Class getBlockEntityClass() { + return DrillBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.DRILL.get(); + } + + @Override + public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, + BlockHitResult ray) { + ItemStack heldItem = player.getItemInHand(hand); + + IPlacementHelper placementHelper = PlacementHelpers.get(placementHelperId); + if (!player.isShiftKeyDown() && player.mayBuild()) { + if (placementHelper.matchesItem(heldItem)) { + placementHelper.getOffset(player, world, state, pos, ray) + .placeInWorld(world, (BlockItem) heldItem.getItem(), player, hand, ray); + return InteractionResult.SUCCESS; + } + } + + return InteractionResult.PASS; + } + + @MethodsReturnNonnullByDefault + private static class PlacementHelper implements IPlacementHelper { + + @Override + public Predicate getItemPredicate() { + return AllBlocks.MECHANICAL_DRILL::isIn; + } + + @Override + public Predicate getStatePredicate() { + return AllBlocks.MECHANICAL_DRILL::has; + } + + @Override + public PlacementOffset getOffset(Player player, Level world, BlockState state, BlockPos pos, + BlockHitResult ray) { + List directions = IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getLocation(), + state.getValue(FACING) + .getAxis(), + dir -> world.getBlockState(pos.relative(dir)) + .getMaterial() + .isReplaceable()); + + if (directions.isEmpty()) + return PlacementOffset.fail(); + else { + return PlacementOffset.success(pos.relative(directions.get(0)), + s -> s.setValue(FACING, state.getValue(FACING))); + } + } + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/drill/DrillBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/drill/DrillBlockEntity.java new file mode 100644 index 000000000..e8b3ffb5f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/drill/DrillBlockEntity.java @@ -0,0 +1,20 @@ +package com.simibubi.create.content.kinetics.drill; + +import com.simibubi.create.content.kinetics.base.BlockBreakingKineticBlockEntity; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; + +public class DrillBlockEntity extends BlockBreakingKineticBlockEntity { + + public DrillBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + protected BlockPos getBreakingPos() { + return getBlockPos().relative(getBlockState().getValue(DrillBlock.FACING)); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/drill/DrillInstance.java b/src/main/java/com/simibubi/create/content/kinetics/drill/DrillInstance.java new file mode 100644 index 000000000..8112622bf --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/drill/DrillInstance.java @@ -0,0 +1,25 @@ +package com.simibubi.create.content.kinetics.drill; + +import com.jozufozu.flywheel.api.Instancer; +import com.jozufozu.flywheel.api.MaterialManager; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.SingleRotatingInstance; +import com.simibubi.create.content.kinetics.base.flwdata.RotatingData; + +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; + +public class DrillInstance extends SingleRotatingInstance { + + public DrillInstance(MaterialManager materialManager, DrillBlockEntity blockEntity) { + super(materialManager, blockEntity); + } + + @Override + protected Instancer getModel() { + BlockState referenceState = blockEntity.getBlockState(); + Direction facing = referenceState.getValue(BlockStateProperties.FACING); + return getRotatingMaterial().getModel(AllPartialModels.DRILL_HEAD, referenceState, facing); + } +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/drill/DrillMovementBehaviour.java b/src/main/java/com/simibubi/create/content/kinetics/drill/DrillMovementBehaviour.java new file mode 100644 index 000000000..4962c7b1f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/drill/DrillMovementBehaviour.java @@ -0,0 +1,69 @@ +package com.simibubi.create.content.kinetics.drill; + +import javax.annotation.Nullable; + +import com.jozufozu.flywheel.api.MaterialManager; +import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; +import com.simibubi.create.AllTags; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.contraptions.render.ActorInstance; +import com.simibubi.create.content.contraptions.render.ContraptionMatrices; +import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher; +import com.simibubi.create.content.kinetics.base.BlockBreakingMovementBehaviour; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.core.BlockPos; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public class DrillMovementBehaviour extends BlockBreakingMovementBehaviour { + + @Override + public boolean isActive(MovementContext context) { + return super.isActive(context) + && !VecHelper.isVecPointingTowards(context.relativeMotion, context.state.getValue(DrillBlock.FACING) + .getOpposite()); + } + + @Override + public Vec3 getActiveAreaOffset(MovementContext context) { + return Vec3.atLowerCornerOf(context.state.getValue(DrillBlock.FACING) + .getNormal()).scale(.65f); + } + + @Override + @OnlyIn(value = Dist.CLIENT) + public void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld, + ContraptionMatrices matrices, MultiBufferSource buffer) { + if (!ContraptionRenderDispatcher.canInstance()) + DrillRenderer.renderInContraption(context, renderWorld, matrices, buffer); + } + + @Override + public boolean hasSpecialInstancedRendering() { + return true; + } + + @Nullable + @Override + public ActorInstance createInstance(MaterialManager materialManager, VirtualRenderWorld simulationWorld, MovementContext context) { + return new DrillActorInstance(materialManager, simulationWorld, context); + } + + @Override + protected DamageSource getDamageSource() { + return DrillBlock.damageSourceDrill; + } + + @Override + public boolean canBreak(Level world, BlockPos breakingPos, BlockState state) { + return super.canBreak(world, breakingPos, state) && !state.getCollisionShape(world, breakingPos) + .isEmpty() && !AllTags.AllBlockTags.TRACKS.matches(state); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/drill/DrillRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/drill/DrillRenderer.java new file mode 100644 index 000000000..d3efdbe6e --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/drill/DrillRenderer.java @@ -0,0 +1,56 @@ +package com.simibubi.create.content.kinetics.drill; + +import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.contraptions.render.ContraptionMatrices; +import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.state.BlockState; + +public class DrillRenderer extends KineticBlockEntityRenderer { + + public DrillRenderer(BlockEntityRendererProvider.Context context) { + super(context); + } + + @Override + protected SuperByteBuffer getRotatedModel(DrillBlockEntity be, BlockState state) { + return CachedBufferer.partialFacing(AllPartialModels.DRILL_HEAD, state); + } + + public static void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld, + ContraptionMatrices matrices, MultiBufferSource buffer) { + BlockState state = context.state; + SuperByteBuffer superBuffer = CachedBufferer.partial(AllPartialModels.DRILL_HEAD, state); + Direction facing = state.getValue(DrillBlock.FACING); + + float speed = (float) (context.contraption.stalled + || !VecHelper.isVecPointingTowards(context.relativeMotion, facing + .getOpposite()) ? context.getAnimationSpeed() : 0); + float time = AnimationTickHolder.getRenderTime() / 20; + float angle = (float) (((time * speed) % 360)); + + superBuffer + .transform(matrices.getModel()) + .centre() + .rotateY(AngleHelper.horizontalAngle(facing)) + .rotateX(AngleHelper.verticalAngle(facing)) + .rotateZ(angle) + .unCentre() + .light(matrices.getWorld(), + ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) + .renderInto(matrices.getViewProjection(), buffer.getBuffer(RenderType.solid())); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/fan/AirCurrent.java b/src/main/java/com/simibubi/create/content/kinetics/fan/AirCurrent.java similarity index 85% rename from src/main/java/com/simibubi/create/content/contraptions/components/fan/AirCurrent.java rename to src/main/java/com/simibubi/create/content/kinetics/fan/AirCurrent.java index 7a68fc804..672945f07 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/fan/AirCurrent.java +++ b/src/main/java/com/simibubi/create/content/kinetics/fan/AirCurrent.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.fan; +package com.simibubi.create.content.kinetics.fan; import java.util.ArrayList; import java.util.Iterator; @@ -7,16 +7,15 @@ import java.util.List; import org.apache.commons.lang3.tuple.Pair; import com.simibubi.create.AllTags; -import com.simibubi.create.content.contraptions.particle.AirFlowParticleData; -import com.simibubi.create.content.contraptions.processing.InWorldProcessing; -import com.simibubi.create.content.contraptions.processing.InWorldProcessing.Type; +import com.simibubi.create.content.decoration.copycat.CopycatBlock; +import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour; +import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour.TransportedResult; +import com.simibubi.create.content.kinetics.fan.FanProcessing.Type; import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour.TransportedResult; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.client.Minecraft; import net.minecraft.core.BlockPos; @@ -30,6 +29,7 @@ import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Fluids; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; @@ -49,7 +49,7 @@ public class AirCurrent { public boolean pushing; public float maxDistance; - protected List> affectedItemHandlers = + protected List> affectedItemHandlers = new ArrayList<>(); protected List caughtEntities = new ArrayList<>(); @@ -69,7 +69,7 @@ public class AirCurrent { Vec3 pos = VecHelper.getCenterOf(source.getAirCurrentPos()) .add(Vec3.atLowerCornerOf(facing.getNormal()) .scale(offset)); - if (world.random.nextFloat() < AllConfigs.CLIENT.fanParticleDensity.get()) + if (world.random.nextFloat() < AllConfigs.client().fanParticleDensity.get()) world.addParticle(new AirFlowParticleData(source.getAirCurrentPos()), pos.x, pos.y, pos.z, 0, 0, 0); } @@ -110,7 +110,7 @@ public class AirCurrent { ((ServerPlayer) entity).connection.aboveGroundTickCount = 0; entityDistance -= .5f; - InWorldProcessing.Type processingType = getSegmentAt((float) entityDistance); + FanProcessing.Type processingType = getSegmentAt((float) entityDistance); if (processingType == null || processingType == Type.NONE) continue; @@ -120,9 +120,9 @@ public class AirCurrent { processingType.spawnParticlesForProcessing(world, entity.position()); continue; } - if (InWorldProcessing.canProcess(itemEntity, processingType)) - if (InWorldProcessing.applyProcessing(itemEntity, processingType) - && source instanceof EncasedFanTileEntity fan) + if (FanProcessing.canProcess(itemEntity, processingType)) + if (FanProcessing.applyProcessing(itemEntity, processingType) + && source instanceof EncasedFanBlockEntity fan) fan.award(AllAdvancements.FAN_PROCESSING); continue; } @@ -155,7 +155,7 @@ public class AirCurrent { AirCurrentSegment currentSegment = new AirCurrentSegment(); segments.clear(); currentSegment.startOffset = 0; - InWorldProcessing.Type type = Type.NONE; + FanProcessing.Type type = Type.NONE; int limit = (int) (maxDistance + .5f); int searchStart = pushing ? 0 : limit; @@ -164,7 +164,7 @@ public class AirCurrent { for (int i = searchStart; i * searchStep <= searchEnd * searchStep; i += searchStep) { BlockPos currentPos = start.relative(direction, i); - InWorldProcessing.Type newType = InWorldProcessing.Type.byBlock(world, currentPos); + FanProcessing.Type newType = FanProcessing.Type.byBlock(world, currentPos); if (newType != Type.NONE) type = newType; if (currentSegment.type != type || currentSegment.startOffset == 0) { @@ -214,7 +214,8 @@ public class AirCurrent { if (!world.isLoaded(currentPos)) break; BlockState state = world.getBlockState(currentPos); - if (shouldAlwaysPass(state)) + BlockState copycatState = CopycatBlock.getMaterial(world, currentPos); + if (shouldAlwaysPass(copycatState.isAir() ? state : copycatState)) continue; VoxelShape voxelshape = state.getCollisionShape(world, currentPos, CollisionContext.empty()); if (voxelshape.isEmpty()) @@ -265,9 +266,13 @@ public class AirCurrent { BlockPos pos = start.relative(direction, i) .below(offset); TransportedItemStackHandlerBehaviour behaviour = - TileEntityBehaviour.get(world, pos, TransportedItemStackHandlerBehaviour.TYPE); + BlockEntityBehaviour.get(world, pos, TransportedItemStackHandlerBehaviour.TYPE); + FanProcessing.Type typeAtHandler = type; + if (world.getFluidState(pos) + .is(Fluids.WATER)) + typeAtHandler = Type.SPLASHING; if (behaviour != null) - affectedItemHandlers.add(Pair.of(behaviour, type)); + affectedItemHandlers.add(Pair.of(behaviour, typeAtHandler)); if (direction.getAxis() .isVertical()) break; @@ -279,7 +284,7 @@ public class AirCurrent { for (Pair pair : affectedItemHandlers) { TransportedItemStackHandlerBehaviour handler = pair.getKey(); Level world = handler.getWorld(); - InWorldProcessing.Type processingType = pair.getRight(); + FanProcessing.Type processingType = pair.getRight(); handler.handleProcessingOnAllItems((transported) -> { if (world.isClientSide) { @@ -287,8 +292,8 @@ public class AirCurrent { processingType.spawnParticlesForProcessing(world, handler.getWorldPositionOf(transported)); return TransportedResult.doNothing(); } - TransportedResult applyProcessing = InWorldProcessing.applyProcessing(transported, world, processingType); - if (!applyProcessing.doesNothing() && source instanceof EncasedFanTileEntity fan) + TransportedResult applyProcessing = FanProcessing.applyProcessing(transported, world, processingType); + if (!applyProcessing.doesNothing() && source instanceof EncasedFanBlockEntity fan) fan.award(AllAdvancements.FAN_PROCESSING); return applyProcessing; }); @@ -299,7 +304,7 @@ public class AirCurrent { return AllTags.AllBlockTags.FAN_TRANSPARENT.matches(state); } - public InWorldProcessing.Type getSegmentAt(float offset) { + public FanProcessing.Type getSegmentAt(float offset) { for (AirCurrentSegment airCurrentSegment : segments) { if (offset > airCurrentSegment.endOffset && pushing) continue; @@ -307,11 +312,11 @@ public class AirCurrent { continue; return airCurrentSegment.type; } - return InWorldProcessing.Type.NONE; + return FanProcessing.Type.NONE; } public static class AirCurrentSegment { - InWorldProcessing.Type type; + FanProcessing.Type type; int startOffset; int endOffset; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/fan/AirCurrentSound.java b/src/main/java/com/simibubi/create/content/kinetics/fan/AirCurrentSound.java similarity index 93% rename from src/main/java/com/simibubi/create/content/contraptions/components/fan/AirCurrentSound.java rename to src/main/java/com/simibubi/create/content/kinetics/fan/AirCurrentSound.java index dd74b1244..872780063 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/fan/AirCurrentSound.java +++ b/src/main/java/com/simibubi/create/content/kinetics/fan/AirCurrentSound.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.fan; +package com.simibubi.create.content.kinetics.fan; import net.minecraft.client.resources.sounds.AbstractTickableSoundInstance; import net.minecraft.client.resources.sounds.SoundInstance; diff --git a/src/main/java/com/simibubi/create/content/contraptions/particle/AirFlowParticle.java b/src/main/java/com/simibubi/create/content/kinetics/fan/AirFlowParticle.java similarity index 88% rename from src/main/java/com/simibubi/create/content/contraptions/particle/AirFlowParticle.java rename to src/main/java/com/simibubi/create/content/kinetics/fan/AirFlowParticle.java index f89c61d65..5ea39e902 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/particle/AirFlowParticle.java +++ b/src/main/java/com/simibubi/create/content/kinetics/fan/AirFlowParticle.java @@ -1,9 +1,7 @@ -package com.simibubi.create.content.contraptions.particle; +package com.simibubi.create.content.kinetics.fan; import javax.annotation.Nonnull; -import com.simibubi.create.content.contraptions.components.fan.IAirCurrentSource; -import com.simibubi.create.content.contraptions.processing.InWorldProcessing; import com.simibubi.create.foundation.utility.Color; import com.simibubi.create.foundation.utility.VecHelper; @@ -98,9 +96,9 @@ public class AirFlowParticle extends SimpleAnimatedParticle { public void morphType(double distance) { if (source.getAirCurrent() == null) return; - InWorldProcessing.Type type = source.getAirCurrent().getSegmentAt((float) distance); + FanProcessing.Type type = source.getAirCurrent().getSegmentAt((float) distance); - if (type == InWorldProcessing.Type.SPLASHING) { + if (type == FanProcessing.Type.SPLASHING) { setColor(Color.mixColors(0x4499FF, 0x2277FF, level.random.nextFloat())); setAlpha(1f); selectSprite(level.random.nextInt(3)); @@ -112,7 +110,7 @@ public class AirFlowParticle extends SimpleAnimatedParticle { zd * .125f); } - if (type == InWorldProcessing.Type.SMOKING) { + if (type == FanProcessing.Type.SMOKING) { setColor(Color.mixColors(0x0, 0x555555, level.random.nextFloat())); setAlpha(1f); selectSprite(level.random.nextInt(3)); @@ -124,7 +122,7 @@ public class AirFlowParticle extends SimpleAnimatedParticle { zd * .125f); } - if (type == InWorldProcessing.Type.HAUNTING) { + if (type == FanProcessing.Type.HAUNTING) { setColor(Color.mixColors(0x0, 0x126568, level.random.nextFloat())); setAlpha(1f); selectSprite(level.random.nextInt(3)); @@ -136,7 +134,7 @@ public class AirFlowParticle extends SimpleAnimatedParticle { zd * .125f); } - if (type == InWorldProcessing.Type.BLASTING) { + if (type == FanProcessing.Type.BLASTING) { setColor(Color.mixColors(0xFF4400, 0xFF8855, level.random.nextFloat())); setAlpha(.5f); selectSprite(level.random.nextInt(3)); @@ -177,10 +175,10 @@ public class AirFlowParticle extends SimpleAnimatedParticle { public Particle createParticle(AirFlowParticleData data, ClientLevel worldIn, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed) { - BlockEntity te = worldIn.getBlockEntity(new BlockPos(data.posX, data.posY, data.posZ)); - if (!(te instanceof IAirCurrentSource)) - te = null; - return new AirFlowParticle(worldIn, (IAirCurrentSource) te, x, y, z, this.spriteSet); + BlockEntity be = worldIn.getBlockEntity(new BlockPos(data.posX, data.posY, data.posZ)); + if (!(be instanceof IAirCurrentSource)) + be = null; + return new AirFlowParticle(worldIn, (IAirCurrentSource) be, x, y, z, this.spriteSet); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/particle/AirFlowParticleData.java b/src/main/java/com/simibubi/create/content/kinetics/fan/AirFlowParticleData.java similarity index 95% rename from src/main/java/com/simibubi/create/content/contraptions/particle/AirFlowParticleData.java rename to src/main/java/com/simibubi/create/content/kinetics/fan/AirFlowParticleData.java index fa0954bee..9655950b9 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/particle/AirFlowParticleData.java +++ b/src/main/java/com/simibubi/create/content/kinetics/fan/AirFlowParticleData.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.particle; +package com.simibubi.create.content.kinetics.fan; import java.util.Locale; @@ -7,6 +7,7 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; import com.simibubi.create.AllParticleTypes; +import com.simibubi.create.foundation.particle.ICustomParticleDataWithSprite; import net.minecraft.client.particle.ParticleEngine.SpriteParticleRegistration; import net.minecraft.core.Vec3i; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanBlock.java b/src/main/java/com/simibubi/create/content/kinetics/fan/EncasedFanBlock.java similarity index 79% rename from src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanBlock.java rename to src/main/java/com/simibubi/create/content/kinetics/fan/EncasedFanBlock.java index 445be9ef4..1f670a1e0 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/fan/EncasedFanBlock.java @@ -1,9 +1,9 @@ -package com.simibubi.create.content.contraptions.components.fan; +package com.simibubi.create.content.kinetics.fan; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock; -import com.simibubi.create.content.logistics.block.chute.AbstractChuteBlock; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.content.kinetics.base.DirectionalKineticBlock; +import com.simibubi.create.content.logistics.chute.AbstractChuteBlock; +import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld; import net.minecraft.core.BlockPos; @@ -18,7 +18,7 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; -public class EncasedFanBlock extends DirectionalKineticBlock implements ITE { +public class EncasedFanBlock extends DirectionalKineticBlock implements IBE { public EncasedFanBlock(Properties properties) { super(properties); @@ -65,11 +65,11 @@ public class EncasedFanBlock extends DirectionalKineticBlock implements ITE getTileEntityClass() { - return EncasedFanTileEntity.class; + public Class getBlockEntityClass() { + return EncasedFanBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.ENCASED_FAN.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.ENCASED_FAN.get(); } } diff --git a/src/main/java/com/simibubi/create/content/kinetics/fan/EncasedFanBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/fan/EncasedFanBlockEntity.java new file mode 100644 index 000000000..836b14a15 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/fan/EncasedFanBlockEntity.java @@ -0,0 +1,154 @@ +package com.simibubi.create.content.kinetics.fan; + +import java.util.List; + +import javax.annotation.Nullable; + +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.logistics.chute.ChuteBlockEntity; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.minecraft.MethodsReturnNonnullByDefault; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; + +@MethodsReturnNonnullByDefault +public class EncasedFanBlockEntity extends KineticBlockEntity implements IAirCurrentSource { + + public AirCurrent airCurrent; + protected int airCurrentUpdateCooldown; + protected int entitySearchCooldown; + protected boolean updateAirFlow; + + public EncasedFanBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + airCurrent = new AirCurrent(this); + updateAirFlow = true; + } + + @Override + public void addBehaviours(List behaviours) { + super.addBehaviours(behaviours); + registerAwardables(behaviours, AllAdvancements.ENCASED_FAN, AllAdvancements.FAN_PROCESSING); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + super.read(compound, clientPacket); + if (clientPacket) + airCurrent.rebuild(); + } + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + super.write(compound, clientPacket); + } + + @Override + public AirCurrent getAirCurrent() { + return airCurrent; + } + + @Nullable + @Override + public Level getAirCurrentWorld() { + return level; + } + + @Override + public BlockPos getAirCurrentPos() { + return worldPosition; + } + + @Override + public Direction getAirflowOriginSide() { + return this.getBlockState() + .getValue(EncasedFanBlock.FACING); + } + + @Override + public Direction getAirFlowDirection() { + float speed = getSpeed(); + if (speed == 0) + return null; + Direction facing = getBlockState().getValue(BlockStateProperties.FACING); + speed = convertToDirection(speed, facing); + return speed > 0 ? facing : facing.getOpposite(); + } + + @Override + public void remove() { + super.remove(); + updateChute(); + } + + @Override + public boolean isSourceRemoved() { + return remove; + } + + @Override + public void onSpeedChanged(float prevSpeed) { + super.onSpeedChanged(prevSpeed); + updateAirFlow = true; + updateChute(); + } + + public void updateChute() { + Direction direction = getBlockState().getValue(EncasedFanBlock.FACING); + if (!direction.getAxis() + .isVertical()) + return; + BlockEntity poweredChute = level.getBlockEntity(worldPosition.relative(direction)); + if (!(poweredChute instanceof ChuteBlockEntity)) + return; + ChuteBlockEntity chuteBE = (ChuteBlockEntity) poweredChute; + if (direction == Direction.DOWN) + chuteBE.updatePull(); + else + chuteBE.updatePush(1); + } + + public void blockInFrontChanged() { + updateAirFlow = true; + } + + @Override + public void tick() { + super.tick(); + + boolean server = !level.isClientSide || isVirtual(); + + if (server && airCurrentUpdateCooldown-- <= 0) { + airCurrentUpdateCooldown = AllConfigs.server().kinetics.fanBlockCheckRate.get(); + updateAirFlow = true; + } + + if (updateAirFlow) { + updateAirFlow = false; + airCurrent.rebuild(); + if (airCurrent.maxDistance > 0) + award(AllAdvancements.ENCASED_FAN); + sendData(); + } + + if (getSpeed() == 0) + return; + + if (entitySearchCooldown-- <= 0) { + entitySearchCooldown = 5; + airCurrent.findEntities(); + } + + airCurrent.tick(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/fan/EncasedFanRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/fan/EncasedFanRenderer.java new file mode 100644 index 000000000..ca0c31d99 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/fan/EncasedFanRenderer.java @@ -0,0 +1,57 @@ +package com.simibubi.create.content.kinetics.fan; + +import static net.minecraft.world.level.block.state.properties.BlockStateProperties.FACING; + +import com.jozufozu.flywheel.backend.Backend; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.AnimationTickHolder; + +import net.minecraft.client.renderer.LevelRenderer; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; + +public class EncasedFanRenderer extends KineticBlockEntityRenderer { + + public EncasedFanRenderer(BlockEntityRendererProvider.Context context) { + super(context); + } + + @Override + protected void renderSafe(EncasedFanBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + if (Backend.canUseInstancing(be.getLevel())) return; + + Direction direction = be.getBlockState() + .getValue(FACING); + VertexConsumer vb = buffer.getBuffer(RenderType.cutoutMipped()); + + int lightBehind = LevelRenderer.getLightColor(be.getLevel(), be.getBlockPos().relative(direction.getOpposite())); + int lightInFront = LevelRenderer.getLightColor(be.getLevel(), be.getBlockPos().relative(direction)); + + SuperByteBuffer shaftHalf = + CachedBufferer.partialFacing(AllPartialModels.SHAFT_HALF, be.getBlockState(), direction.getOpposite()); + SuperByteBuffer fanInner = + CachedBufferer.partialFacing(AllPartialModels.ENCASED_FAN_INNER, be.getBlockState(), direction.getOpposite()); + + float time = AnimationTickHolder.getRenderTime(be.getLevel()); + float speed = be.getSpeed() * 5; + if (speed > 0) + speed = Mth.clamp(speed, 80, 64 * 20); + if (speed < 0) + speed = Mth.clamp(speed, -64 * 20, -80); + float angle = (time * speed * 3 / 10f) % 360; + angle = angle / 180f * (float) Math.PI; + + standardKineticRotationTransform(shaftHalf, be, lightBehind).renderInto(ms, vb); + kineticRotationTransform(fanInner, be, direction.getAxis(), angle, lightInFront).renderInto(ms, vb); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/fan/FanInstance.java b/src/main/java/com/simibubi/create/content/kinetics/fan/FanInstance.java new file mode 100644 index 000000000..d509f08b3 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/fan/FanInstance.java @@ -0,0 +1,67 @@ +package com.simibubi.create.content.kinetics.fan; + +import static net.minecraft.world.level.block.state.properties.BlockStateProperties.FACING; + +import com.jozufozu.flywheel.api.MaterialManager; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityInstance; +import com.simibubi.create.content.kinetics.base.flwdata.RotatingData; +import com.simibubi.create.foundation.render.AllMaterialSpecs; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; + +public class FanInstance extends KineticBlockEntityInstance { + + protected final RotatingData shaft; + protected final RotatingData fan; + final Direction direction; + private final Direction opposite; + + public FanInstance(MaterialManager materialManager, EncasedFanBlockEntity blockEntity) { + super(materialManager, blockEntity); + + direction = blockState.getValue(FACING); + + opposite = direction.getOpposite(); + shaft = getRotatingMaterial().getModel(AllPartialModels.SHAFT_HALF, blockState, opposite).createInstance(); + fan = materialManager.defaultCutout() + .material(AllMaterialSpecs.ROTATING) + .getModel(AllPartialModels.ENCASED_FAN_INNER, blockState, opposite) + .createInstance(); + + setup(shaft); + setup(fan, getFanSpeed()); + } + + private float getFanSpeed() { + float speed = blockEntity.getSpeed() * 5; + if (speed > 0) + speed = Mth.clamp(speed, 80, 64 * 20); + if (speed < 0) + speed = Mth.clamp(speed, -64 * 20, -80); + return speed; + } + + @Override + public void update() { + updateRotation(shaft); + updateRotation(fan, getFanSpeed()); + } + + @Override + public void updateLight() { + BlockPos behind = pos.relative(opposite); + relight(behind, shaft); + + BlockPos inFront = pos.relative(direction); + relight(inFront, fan); + } + + @Override + public void remove() { + shaft.delete(); + fan.delete(); + } +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/fan/FanProcessing.java b/src/main/java/com/simibubi/create/content/kinetics/fan/FanProcessing.java new file mode 100644 index 000000000..e460cd473 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/fan/FanProcessing.java @@ -0,0 +1,453 @@ +package com.simibubi.create.content.kinetics.fan; + +import static com.simibubi.create.content.processing.burner.BlazeBurnerBlock.getHeatLevelOf; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import org.joml.Vector3f; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllRecipeTypes; +import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour.TransportedResult; +import com.simibubi.create.content.kinetics.belt.transport.TransportedItemStack; +import com.simibubi.create.content.processing.burner.BlazeBurnerBlock; +import com.simibubi.create.content.processing.burner.LitBlazeBurnerBlock; +import com.simibubi.create.foundation.recipe.RecipeApplier; +import com.simibubi.create.foundation.utility.Color; +import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.particles.DustParticleOptions; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.tags.BlockTags; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.animal.horse.Horse; +import net.minecraft.world.entity.animal.horse.SkeletonHorse; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.monster.EnderMan; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.AbstractCookingRecipe; +import net.minecraft.world.item.crafting.BlastingRecipe; +import net.minecraft.world.item.crafting.RecipeType; +import net.minecraft.world.item.crafting.SmeltingRecipe; +import net.minecraft.world.item.crafting.SmokingRecipe; +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.Blocks; +import net.minecraft.world.level.block.CampfireBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.level.material.Fluids; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.items.ItemStackHandler; +import net.minecraftforge.items.wrapper.RecipeWrapper; + +public class FanProcessing { + + private static final DamageSource FIRE_DAMAGE_SOURCE = new DamageSource("create.fan_fire").setScalesWithDifficulty() + .setIsFire(); + private static final DamageSource LAVA_DAMAGE_SOURCE = new DamageSource("create.fan_lava").setScalesWithDifficulty() + .setIsFire(); + + private static final RecipeWrapper RECIPE_WRAPPER = new RecipeWrapper(new ItemStackHandler(1)); + private static final SplashingWrapper SPLASHING_WRAPPER = new SplashingWrapper(); + private static final HauntingWrapper HAUNTING_WRAPPER = new HauntingWrapper(); + + public static boolean canProcess(ItemEntity entity, Type type) { + if (entity.getPersistentData() + .contains("CreateData")) { + CompoundTag compound = entity.getPersistentData() + .getCompound("CreateData"); + if (compound.contains("Processing")) { + CompoundTag processing = compound.getCompound("Processing"); + + if (Type.valueOf(processing.getString("Type")) != type) + return type.canProcess(entity.getItem(), entity.level); + else if (processing.getInt("Time") >= 0) + return true; + else if (processing.getInt("Time") == -1) + return false; + } + } + return type.canProcess(entity.getItem(), entity.level); + } + + public static boolean isWashable(ItemStack stack, Level world) { + SPLASHING_WRAPPER.setItem(0, stack); + Optional recipe = AllRecipeTypes.SPLASHING.find(SPLASHING_WRAPPER, world); + return recipe.isPresent(); + } + + public static boolean isHauntable(ItemStack stack, Level world) { + HAUNTING_WRAPPER.setItem(0, stack); + Optional recipe = AllRecipeTypes.HAUNTING.find(HAUNTING_WRAPPER, world); + return recipe.isPresent(); + } + + public static boolean applyProcessing(ItemEntity entity, Type type) { + if (decrementProcessingTime(entity, type) != 0) + return false; + List stacks = process(entity.getItem(), type, entity.level); + if (stacks == null) + return false; + if (stacks.isEmpty()) { + entity.discard(); + return false; + } + entity.setItem(stacks.remove(0)); + for (ItemStack additional : stacks) { + ItemEntity entityIn = new ItemEntity(entity.level, entity.getX(), entity.getY(), entity.getZ(), additional); + entityIn.setDeltaMovement(entity.getDeltaMovement()); + entity.level.addFreshEntity(entityIn); + } + return true; + } + + public static TransportedResult applyProcessing(TransportedItemStack transported, Level world, Type type) { + TransportedResult ignore = TransportedResult.doNothing(); + if (transported.processedBy != type) { + transported.processedBy = type; + int timeModifierForStackSize = ((transported.stack.getCount() - 1) / 16) + 1; + int processingTime = + (int) (AllConfigs.server().kinetics.fanProcessingTime.get() * timeModifierForStackSize) + 1; + transported.processingTime = processingTime; + if (!type.canProcess(transported.stack, world)) + transported.processingTime = -1; + return ignore; + } + if (transported.processingTime == -1) + return ignore; + if (transported.processingTime-- > 0) + return ignore; + + List stacks = process(transported.stack, type, world); + if (stacks == null) + return ignore; + + List transportedStacks = new ArrayList<>(); + for (ItemStack additional : stacks) { + TransportedItemStack newTransported = transported.getSimilar(); + newTransported.stack = additional.copy(); + transportedStacks.add(newTransported); + } + return TransportedResult.convertTo(transportedStacks); + } + + private static List process(ItemStack stack, Type type, Level world) { + if (type == Type.SPLASHING) { + SPLASHING_WRAPPER.setItem(0, stack); + Optional recipe = AllRecipeTypes.SPLASHING.find(SPLASHING_WRAPPER, world); + if (recipe.isPresent()) + return RecipeApplier.applyRecipeOn(stack, recipe.get()); + return null; + } + if (type == Type.HAUNTING) { + HAUNTING_WRAPPER.setItem(0, stack); + Optional recipe = AllRecipeTypes.HAUNTING.find(HAUNTING_WRAPPER, world); + if (recipe.isPresent()) + return RecipeApplier.applyRecipeOn(stack, recipe.get()); + return null; + } + + RECIPE_WRAPPER.setItem(0, stack); + Optional smokingRecipe = world.getRecipeManager() + .getRecipeFor(RecipeType.SMOKING, RECIPE_WRAPPER, world); + + if (type == Type.BLASTING) { + RECIPE_WRAPPER.setItem(0, stack); + Optional smeltingRecipe = world.getRecipeManager() + .getRecipeFor(RecipeType.SMELTING, RECIPE_WRAPPER, world); + if (!smeltingRecipe.isPresent()) { + RECIPE_WRAPPER.setItem(0, stack); + smeltingRecipe = world.getRecipeManager() + .getRecipeFor(RecipeType.BLASTING, RECIPE_WRAPPER, world); + } + + if (smeltingRecipe.isPresent()) { + if (!smokingRecipe.isPresent() || !ItemStack.isSame(smokingRecipe.get() + .getResultItem(), + smeltingRecipe.get() + .getResultItem())) { + return RecipeApplier.applyRecipeOn(stack, smeltingRecipe.get()); + } + } + + return Collections.emptyList(); + } + + if (type == Type.SMOKING && smokingRecipe.isPresent()) + return RecipeApplier.applyRecipeOn(stack, smokingRecipe.get()); + + return null; + } + + private static int decrementProcessingTime(ItemEntity entity, Type type) { + CompoundTag nbt = entity.getPersistentData(); + + if (!nbt.contains("CreateData")) + nbt.put("CreateData", new CompoundTag()); + CompoundTag createData = nbt.getCompound("CreateData"); + + if (!createData.contains("Processing")) + createData.put("Processing", new CompoundTag()); + CompoundTag processing = createData.getCompound("Processing"); + + if (!processing.contains("Type") || Type.valueOf(processing.getString("Type")) != type) { + processing.putString("Type", type.name()); + int timeModifierForStackSize = ((entity.getItem() + .getCount() - 1) / 16) + 1; + int processingTime = + (int) (AllConfigs.server().kinetics.fanProcessingTime.get() * timeModifierForStackSize) + 1; + processing.putInt("Time", processingTime); + } + + int value = processing.getInt("Time") - 1; + processing.putInt("Time", value); + return value; + } + + public enum Type { + SPLASHING { + @Override + public void spawnParticlesForProcessing(Level level, Vec3 pos) { + if (level.random.nextInt(8) != 0) + return; + Vector3f color = new Color(0x0055FF).asVectorF(); + level.addParticle(new DustParticleOptions(color, 1), pos.x + (level.random.nextFloat() - .5f) * .5f, + pos.y + .5f, pos.z + (level.random.nextFloat() - .5f) * .5f, 0, 1 / 8f, 0); + level.addParticle(ParticleTypes.SPIT, pos.x + (level.random.nextFloat() - .5f) * .5f, pos.y + .5f, + pos.z + (level.random.nextFloat() - .5f) * .5f, 0, 1 / 8f, 0); + } + + @Override + public void affectEntity(Entity entity, Level level) { + if (level.isClientSide) + return; + + if (entity instanceof EnderMan || entity.getType() == EntityType.SNOW_GOLEM + || entity.getType() == EntityType.BLAZE) { + entity.hurt(DamageSource.DROWN, 2); + } + if (entity.isOnFire()) { + entity.clearFire(); + level.playSound(null, entity.blockPosition(), SoundEvents.GENERIC_EXTINGUISH_FIRE, + SoundSource.NEUTRAL, 0.7F, 1.6F + (level.random.nextFloat() - level.random.nextFloat()) * 0.4F); + } + } + + @Override + public boolean canProcess(ItemStack stack, Level level) { + return isWashable(stack, level); + } + }, + SMOKING { + @Override + public void spawnParticlesForProcessing(Level level, Vec3 pos) { + if (level.random.nextInt(8) != 0) + return; + level.addParticle(ParticleTypes.POOF, pos.x, pos.y + .25f, pos.z, 0, 1 / 16f, 0); + } + + @Override + public void affectEntity(Entity entity, Level level) { + if (level.isClientSide) + return; + + if (!entity.fireImmune()) { + entity.setSecondsOnFire(2); + entity.hurt(FIRE_DAMAGE_SOURCE, 2); + } + } + + @Override + public boolean canProcess(ItemStack stack, Level level) { + RECIPE_WRAPPER.setItem(0, stack); + Optional recipe = level.getRecipeManager() + .getRecipeFor(RecipeType.SMOKING, RECIPE_WRAPPER, level); + return recipe.isPresent(); + } + }, + HAUNTING { + @Override + public void spawnParticlesForProcessing(Level level, Vec3 pos) { + if (level.random.nextInt(8) != 0) + return; + pos = pos.add(VecHelper.offsetRandomly(Vec3.ZERO, level.random, 1) + .multiply(1, 0.05f, 1) + .normalize() + .scale(0.15f)); + level.addParticle(ParticleTypes.SOUL_FIRE_FLAME, pos.x, pos.y + .45f, pos.z, 0, 0, 0); + if (level.random.nextInt(2) == 0) + level.addParticle(ParticleTypes.SMOKE, pos.x, pos.y + .25f, pos.z, 0, 0, 0); + } + + @Override + public void affectEntity(Entity entity, Level level) { + if (level.isClientSide) { + if (entity instanceof Horse) { + Vec3 p = entity.getPosition(0); + Vec3 v = p.add(0, 0.5f, 0) + .add(VecHelper.offsetRandomly(Vec3.ZERO, level.random, 1) + .multiply(1, 0.2f, 1) + .normalize() + .scale(1f)); + level.addParticle(ParticleTypes.SOUL_FIRE_FLAME, v.x, v.y, v.z, 0, 0.1f, 0); + if (level.random.nextInt(3) == 0) + level.addParticle(ParticleTypes.LARGE_SMOKE, p.x, p.y + .5f, p.z, + (level.random.nextFloat() - .5f) * .5f, 0.1f, (level.random.nextFloat() - .5f) * .5f); + } + return; + } + + if (entity instanceof LivingEntity livingEntity) { + livingEntity.addEffect(new MobEffectInstance(MobEffects.BLINDNESS, 30, 0, false, false)); + livingEntity.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, 20, 1, false, false)); + } + if (entity instanceof Horse horse) { + int progress = horse.getPersistentData() + .getInt("CreateHaunting"); + if (progress < 100) { + if (progress % 10 == 0) { + level.playSound(null, entity.blockPosition(), SoundEvents.SOUL_ESCAPE, SoundSource.NEUTRAL, + 1f, 1.5f * progress / 100f); + } + horse.getPersistentData() + .putInt("CreateHaunting", progress + 1); + return; + } + + level.playSound(null, entity.blockPosition(), SoundEvents.GENERIC_EXTINGUISH_FIRE, + SoundSource.NEUTRAL, 1.25f, 0.65f); + + SkeletonHorse skeletonHorse = EntityType.SKELETON_HORSE.create(level); + CompoundTag serializeNBT = horse.saveWithoutId(new CompoundTag()); + serializeNBT.remove("UUID"); + if (!horse.getArmor() + .isEmpty()) + horse.spawnAtLocation(horse.getArmor()); + + skeletonHorse.deserializeNBT(serializeNBT); + skeletonHorse.setPos(horse.getPosition(0)); + level.addFreshEntity(skeletonHorse); + horse.discard(); + } + } + + @Override + public boolean canProcess(ItemStack stack, Level level) { + return isHauntable(stack, level); + } + }, + BLASTING { + @Override + public void spawnParticlesForProcessing(Level level, Vec3 pos) { + if (level.random.nextInt(8) != 0) + return; + level.addParticle(ParticleTypes.LARGE_SMOKE, pos.x, pos.y + .25f, pos.z, 0, 1 / 16f, 0); + } + + @Override + public void affectEntity(Entity entity, Level level) { + if (level.isClientSide) + return; + + if (!entity.fireImmune()) { + entity.setSecondsOnFire(10); + entity.hurt(LAVA_DAMAGE_SOURCE, 4); + } + } + + @Override + public boolean canProcess(ItemStack stack, Level level) { + RECIPE_WRAPPER.setItem(0, stack); + Optional smeltingRecipe = level.getRecipeManager() + .getRecipeFor(RecipeType.SMELTING, RECIPE_WRAPPER, level); + + if (smeltingRecipe.isPresent()) + return true; + + RECIPE_WRAPPER.setItem(0, stack); + Optional blastingRecipe = level.getRecipeManager() + .getRecipeFor(RecipeType.BLASTING, RECIPE_WRAPPER, level); + + if (blastingRecipe.isPresent()) + return true; + + return !stack.getItem() + .isFireResistant(); + } + }, + NONE { + @Override + public void spawnParticlesForProcessing(Level level, Vec3 pos) {} + + @Override + public void affectEntity(Entity entity, Level level) {} + + @Override + public boolean canProcess(ItemStack stack, Level level) { + return false; + } + }; + + public abstract boolean canProcess(ItemStack stack, Level level); + + public abstract void spawnParticlesForProcessing(Level level, Vec3 pos); + + public abstract void affectEntity(Entity entity, Level level); + + public static Type byBlock(BlockGetter reader, BlockPos pos) { + FluidState fluidState = reader.getFluidState(pos); + if (fluidState.getType() == Fluids.WATER || fluidState.getType() == Fluids.FLOWING_WATER) + return Type.SPLASHING; + BlockState blockState = reader.getBlockState(pos); + Block block = blockState.getBlock(); + if (block == Blocks.SOUL_FIRE + || block == Blocks.SOUL_CAMPFIRE && blockState.getOptionalValue(CampfireBlock.LIT) + .orElse(false) + || AllBlocks.LIT_BLAZE_BURNER.has(blockState) + && blockState.getOptionalValue(LitBlazeBurnerBlock.FLAME_TYPE) + .map(flame -> flame == LitBlazeBurnerBlock.FlameType.SOUL) + .orElse(false)) + return Type.HAUNTING; + if (block == Blocks.FIRE + || blockState.is(BlockTags.CAMPFIRES) && blockState.getOptionalValue(CampfireBlock.LIT) + .orElse(false) + || AllBlocks.LIT_BLAZE_BURNER.has(blockState) + && blockState.getOptionalValue(LitBlazeBurnerBlock.FLAME_TYPE) + .map(flame -> flame == LitBlazeBurnerBlock.FlameType.REGULAR) + .orElse(false) + || getHeatLevelOf(blockState) == BlazeBurnerBlock.HeatLevel.SMOULDERING) + return Type.SMOKING; + if (block == Blocks.LAVA || getHeatLevelOf(blockState).isAtLeast(BlazeBurnerBlock.HeatLevel.FADING)) + return Type.BLASTING; + return Type.NONE; + } + } + + public static class SplashingWrapper extends RecipeWrapper { + public SplashingWrapper() { + super(new ItemStackHandler(1)); + } + } + + public static class HauntingWrapper extends RecipeWrapper { + public HauntingWrapper() { + super(new ItemStackHandler(1)); + } + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/fan/HauntingRecipe.java b/src/main/java/com/simibubi/create/content/kinetics/fan/HauntingRecipe.java new file mode 100644 index 000000000..43dbc81d0 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/fan/HauntingRecipe.java @@ -0,0 +1,36 @@ +package com.simibubi.create.content.kinetics.fan; + +import javax.annotation.ParametersAreNonnullByDefault; + +import com.simibubi.create.AllRecipeTypes; +import com.simibubi.create.content.processing.recipe.ProcessingRecipe; +import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder.ProcessingRecipeParams; + +import net.minecraft.world.level.Level; + +@ParametersAreNonnullByDefault +public class HauntingRecipe extends ProcessingRecipe { + + public HauntingRecipe(ProcessingRecipeParams params) { + super(AllRecipeTypes.HAUNTING, params); + } + + @Override + public boolean matches(FanProcessing.HauntingWrapper inv, Level worldIn) { + if (inv.isEmpty()) + return false; + return ingredients.get(0) + .test(inv.getItem(0)); + } + + @Override + protected int getMaxInputCount() { + return 1; + } + + @Override + protected int getMaxOutputCount() { + return 12; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/fan/IAirCurrentSource.java b/src/main/java/com/simibubi/create/content/kinetics/fan/IAirCurrentSource.java similarity index 80% rename from src/main/java/com/simibubi/create/content/contraptions/components/fan/IAirCurrentSource.java rename to src/main/java/com/simibubi/create/content/kinetics/fan/IAirCurrentSource.java index 2db3fb22d..0f232411b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/fan/IAirCurrentSource.java +++ b/src/main/java/com/simibubi/create/content/kinetics/fan/IAirCurrentSource.java @@ -1,9 +1,9 @@ -package com.simibubi.create.content.contraptions.components.fan; +package com.simibubi.create.content.kinetics.fan; import javax.annotation.Nullable; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.config.CKinetics; +import com.simibubi.create.infrastructure.config.AllConfigs; +import com.simibubi.create.infrastructure.config.CKinetics; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; @@ -30,7 +30,7 @@ public interface IAirCurrentSource { default float getMaxDistance() { float speed = Math.abs(this.getSpeed()); - CKinetics config = AllConfigs.SERVER.kinetics; + CKinetics config = AllConfigs.server().kinetics; float distanceFactor = Math.min(speed / config.fanRotationArgmax.get(), 1); float pushDistance = Mth.lerp(distanceFactor, 3, config.fanPushDistance.get()); float pullDistance = Mth.lerp(distanceFactor, 3f, config.fanPullDistance.get()); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/fan/NozzleBlock.java b/src/main/java/com/simibubi/create/content/kinetics/fan/NozzleBlock.java similarity index 80% rename from src/main/java/com/simibubi/create/content/contraptions/components/fan/NozzleBlock.java rename to src/main/java/com/simibubi/create/content/kinetics/fan/NozzleBlock.java index f5aae9ac1..d64f14dd8 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/fan/NozzleBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/fan/NozzleBlock.java @@ -1,10 +1,10 @@ -package com.simibubi.create.content.contraptions.components.fan; +package com.simibubi.create.content.kinetics.fan; import javax.annotation.ParametersAreNonnullByDefault; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.block.WrenchableDirectionalBlock; import net.minecraft.MethodsReturnNonnullByDefault; @@ -26,7 +26,7 @@ import net.minecraft.world.phys.shapes.VoxelShape; @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault -public class NozzleBlock extends WrenchableDirectionalBlock implements ITE { +public class NozzleBlock extends WrenchableDirectionalBlock implements IBE { public NozzleBlock(Properties p_i48415_1_) { super(p_i48415_1_); @@ -63,9 +63,9 @@ public class NozzleBlock extends WrenchableDirectionalBlock implements ITE getTileEntityClass() { - return NozzleTileEntity.class; + public Class getBlockEntityClass() { + return NozzleBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.NOZZLE.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.NOZZLE.get(); } } diff --git a/src/main/java/com/simibubi/create/content/kinetics/fan/NozzleBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/fan/NozzleBlockEntity.java new file mode 100644 index 000000000..3bc5f1d58 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/fan/NozzleBlockEntity.java @@ -0,0 +1,191 @@ +package com.simibubi.create.content.kinetics.fan; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.ClipContext; +import net.minecraft.world.level.ClipContext.Block; +import net.minecraft.world.level.ClipContext.Fluid; +import net.minecraft.world.level.Level.ExplosionInteraction; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; + +public class NozzleBlockEntity extends SmartBlockEntity { + + private List pushingEntities = new ArrayList<>(); + private float range; + private boolean pushing; + private BlockPos fanPos; + + public NozzleBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + setLazyTickRate(5); + } + + @Override + public void addBehaviours(List behaviours) {} + + @Override + protected void write(CompoundTag compound, boolean clientPacket) { + super.write(compound, clientPacket); + if (!clientPacket) + return; + compound.putFloat("Range", range); + compound.putBoolean("Pushing", pushing); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + super.read(compound, clientPacket); + if (!clientPacket) + return; + range = compound.getFloat("Range"); + pushing = compound.getBoolean("Pushing"); + } + + @Override + public void initialize() { + fanPos = worldPosition.relative(getBlockState().getValue(NozzleBlock.FACING) + .getOpposite()); + super.initialize(); + } + + @Override + public void tick() { + super.tick(); + + float range = calcRange(); + if (this.range != range) + setRange(range); + + Vec3 center = VecHelper.getCenterOf(worldPosition); + if (level.isClientSide && range != 0) { + if (level.random.nextInt( + Mth.clamp((AllConfigs.server().kinetics.fanPushDistance.get() - (int) range), 1, 10)) == 0) { + Vec3 start = VecHelper.offsetRandomly(center, level.random, pushing ? 1 : range / 2); + Vec3 motion = center.subtract(start) + .normalize() + .scale(Mth.clamp(range * (pushing ? .025f : 1f), 0, .5f) * (pushing ? -1 : 1)); + level.addParticle(ParticleTypes.POOF, start.x, start.y, start.z, motion.x, motion.y, motion.z); + } + } + + for (Iterator iterator = pushingEntities.iterator(); iterator.hasNext();) { + Entity entity = iterator.next(); + Vec3 diff = entity.position() + .subtract(center); + + if (!(entity instanceof Player) && level.isClientSide) + continue; + + double distance = diff.length(); + if (distance > range || entity.isShiftKeyDown() || AirCurrent.isPlayerCreativeFlying(entity)) { + iterator.remove(); + continue; + } + + if (!pushing && distance < 1.5f) + continue; + + float factor = (entity instanceof ItemEntity) ? 1 / 128f : 1 / 32f; + Vec3 pushVec = diff.normalize() + .scale((range - distance) * (pushing ? 1 : -1)); + entity.setDeltaMovement(entity.getDeltaMovement() + .add(pushVec.scale(factor))); + entity.fallDistance = 0; + entity.hurtMarked = true; + } + + } + + public void setRange(float range) { + this.range = range; + if (range == 0) + pushingEntities.clear(); + sendData(); + } + + private float calcRange() { + BlockEntity be = level.getBlockEntity(fanPos); + if (!(be instanceof IAirCurrentSource)) + return 0; + + IAirCurrentSource source = (IAirCurrentSource) be; + if (source.getAirCurrent() == null) + return 0; + if (source.getSpeed() == 0) + return 0; + pushing = source.getAirFlowDirection() == source.getAirflowOriginSide(); + return source.getMaxDistance(); + } + + @Override + public void lazyTick() { + super.lazyTick(); + + if (range == 0) + return; + + Vec3 center = VecHelper.getCenterOf(worldPosition); + AABB bb = new AABB(center, center).inflate(range / 2f); + + for (Entity entity : level.getEntitiesOfClass(Entity.class, bb)) { + Vec3 diff = entity.position() + .subtract(center); + + double distance = diff.length(); + if (distance > range || entity.isShiftKeyDown() || AirCurrent.isPlayerCreativeFlying(entity)) + continue; + + boolean canSee = canSee(entity); + if (!canSee) { + pushingEntities.remove(entity); + continue; + } + + if (!pushingEntities.contains(entity)) + pushingEntities.add(entity); + } + + for (Iterator iterator = pushingEntities.iterator(); iterator.hasNext();) { + Entity entity = iterator.next(); + if (entity.isAlive()) + continue; + iterator.remove(); + } + + if (!pushing && pushingEntities.size() > 256 && !level.isClientSide) { + level.explode(null, center.x, center.y, center.z, 2, ExplosionInteraction.NONE); + for (Iterator iterator = pushingEntities.iterator(); iterator.hasNext();) { + Entity entity = iterator.next(); + entity.discard(); + iterator.remove(); + } + } + + } + + private boolean canSee(Entity entity) { + ClipContext context = new ClipContext(entity.position(), VecHelper.getCenterOf(worldPosition), + Block.COLLIDER, Fluid.NONE, entity); + return worldPosition.equals(level.clip(context) + .getBlockPos()); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/fan/SplashingRecipe.java b/src/main/java/com/simibubi/create/content/kinetics/fan/SplashingRecipe.java new file mode 100644 index 000000000..b8734ae53 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/fan/SplashingRecipe.java @@ -0,0 +1,37 @@ +package com.simibubi.create.content.kinetics.fan; + +import javax.annotation.ParametersAreNonnullByDefault; + +import com.simibubi.create.AllRecipeTypes; +import com.simibubi.create.content.kinetics.fan.FanProcessing.SplashingWrapper; +import com.simibubi.create.content.processing.recipe.ProcessingRecipe; +import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder.ProcessingRecipeParams; + +import net.minecraft.world.level.Level; + +@ParametersAreNonnullByDefault +public class SplashingRecipe extends ProcessingRecipe { + + public SplashingRecipe(ProcessingRecipeParams params) { + super(AllRecipeTypes.SPLASHING, params); + } + + @Override + public boolean matches(SplashingWrapper inv, Level worldIn) { + if (inv.isEmpty()) + return false; + return ingredients.get(0) + .test(inv.getItem(0)); + } + + @Override + protected int getMaxInputCount() { + return 1; + } + + @Override + protected int getMaxOutputCount() { + return 12; + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/flywheel/FlywheelBlock.java b/src/main/java/com/simibubi/create/content/kinetics/flywheel/FlywheelBlock.java new file mode 100644 index 000000000..6cff991ce --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/flywheel/FlywheelBlock.java @@ -0,0 +1,65 @@ +package com.simibubi.create.content.kinetics.flywheel; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllShapes; +import com.simibubi.create.content.kinetics.base.RotatedPillarKineticBlock; +import com.simibubi.create.foundation.block.IBE; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.RenderShape; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +public class FlywheelBlock extends RotatedPillarKineticBlock implements IBE { + + public FlywheelBlock(Properties properties) { + super(properties); + } + + @Override + public Class getBlockEntityClass() { + return FlywheelBlockEntity.class; + } + + @Override + public VoxelShape getShape(BlockState pState, BlockGetter pLevel, BlockPos pPos, CollisionContext pContext) { + return AllShapes.LARGE_GEAR.get(pState.getValue(AXIS)); + } + + @Override + public RenderShape getRenderShape(BlockState pState) { + return RenderShape.ENTITYBLOCK_ANIMATED; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.FLYWHEEL.get(); + } + + @Override + public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) { + return face.getAxis() == getRotationAxis(state); + } + + @Override + public Axis getRotationAxis(BlockState state) { + return state.getValue(AXIS); + } + + @Override + public float getParticleTargetRadius() { + return 2f; + } + + @Override + public float getParticleInitialRadius() { + return 1.75f; + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/flywheel/FlywheelBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/flywheel/FlywheelBlockEntity.java new file mode 100644 index 000000000..63afa38e6 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/flywheel/FlywheelBlockEntity.java @@ -0,0 +1,52 @@ +package com.simibubi.create.content.kinetics.flywheel; + +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; + +public class FlywheelBlockEntity extends KineticBlockEntity { + + LerpedFloat visualSpeed = LerpedFloat.linear(); + float angle; + + public FlywheelBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + protected AABB createRenderBoundingBox() { + return super.createRenderBoundingBox().inflate(2); + } + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + super.write(compound, clientPacket); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + super.read(compound, clientPacket); + if (clientPacket) + visualSpeed.chase(getGeneratedSpeed(), 1 / 64f, Chaser.EXP); + } + + @Override + public void tick() { + super.tick(); + + if (!level.isClientSide) + return; + + float targetSpeed = getSpeed(); + visualSpeed.updateChaseTarget(targetSpeed); + visualSpeed.tickChaser(); + angle += visualSpeed.getValue() * 3 / 10f; + angle %= 360; + } +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/flywheel/FlywheelInstance.java b/src/main/java/com/simibubi/create/content/kinetics/flywheel/FlywheelInstance.java new file mode 100644 index 000000000..4f97923d9 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/flywheel/FlywheelInstance.java @@ -0,0 +1,76 @@ +package com.simibubi.create.content.kinetics.flywheel; + +import com.jozufozu.flywheel.api.MaterialManager; +import com.jozufozu.flywheel.api.instance.DynamicInstance; +import com.jozufozu.flywheel.core.materials.model.ModelData; +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityInstance; +import com.simibubi.create.content.kinetics.base.flwdata.RotatingData; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.AnimationTickHolder; + +import net.minecraft.core.Direction; + +public class FlywheelInstance extends KineticBlockEntityInstance implements DynamicInstance { + + protected final RotatingData shaft; + protected final ModelData wheel; + protected float lastAngle = Float.NaN; + + public FlywheelInstance(MaterialManager materialManager, FlywheelBlockEntity blockEntity) { + super(materialManager, blockEntity); + + shaft = setup(getRotatingMaterial().getModel(shaft()) + .createInstance()); + wheel = getTransformMaterial().getModel(blockState) + .createInstance(); + + animate(blockEntity.angle); + } + + @Override + public void beginFrame() { + + float partialTicks = AnimationTickHolder.getPartialTicks(); + + float speed = blockEntity.visualSpeed.getValue(partialTicks) * 3 / 10f; + float angle = blockEntity.angle + speed * partialTicks; + + if (Math.abs(angle - lastAngle) < 0.001) + return; + + animate(angle); + + lastAngle = angle; + } + + private void animate(float angle) { + PoseStack ms = new PoseStack(); + TransformStack msr = TransformStack.cast(ms); + + msr.translate(getInstancePosition()); + msr.centre() + .rotate(Direction.get(Direction.AxisDirection.POSITIVE, axis), AngleHelper.rad(angle)) + .unCentre(); + + wheel.setTransform(ms); + } + + @Override + public void update() { + updateRotation(shaft); + } + + @Override + public void updateLight() { + relight(pos, shaft, wheel); + } + + @Override + public void remove() { + shaft.delete(); + wheel.delete(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/flywheel/FlywheelRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/flywheel/FlywheelRenderer.java new file mode 100644 index 000000000..f563916f3 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/flywheel/FlywheelRenderer.java @@ -0,0 +1,51 @@ +package com.simibubi.create.content.kinetics.flywheel; + +import com.jozufozu.flywheel.backend.Backend; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.AngleHelper; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.world.level.block.state.BlockState; + +public class FlywheelRenderer extends KineticBlockEntityRenderer { + + public FlywheelRenderer(BlockEntityRendererProvider.Context context) { + super(context); + } + + @Override + protected void renderSafe(FlywheelBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + super.renderSafe(be, partialTicks, ms, buffer, light, overlay); + + if (Backend.canUseInstancing(be.getLevel())) + return; + + BlockState blockState = be.getBlockState(); + + float speed = be.visualSpeed.getValue(partialTicks) * 3 / 10f; + float angle = be.angle + speed * partialTicks; + + VertexConsumer vb = buffer.getBuffer(RenderType.solid()); + renderFlywheel(be, ms, light, blockState, angle, vb); + } + + private void renderFlywheel(FlywheelBlockEntity be, PoseStack ms, int light, BlockState blockState, float angle, + VertexConsumer vb) { + SuperByteBuffer wheel = CachedBufferer.block(blockState); + kineticRotationTransform(wheel, be, getRotationAxisOf(be), AngleHelper.rad(angle), light); + wheel.renderInto(ms, vb); + } + + @Override + protected BlockState getRenderedBlockState(FlywheelBlockEntity be) { + return shaft(getRotationAxisOf(be)); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/GantryShaftBlock.java b/src/main/java/com/simibubi/create/content/kinetics/gantry/GantryShaftBlock.java similarity index 89% rename from src/main/java/com/simibubi/create/content/contraptions/relays/advanced/GantryShaftBlock.java rename to src/main/java/com/simibubi/create/content/kinetics/gantry/GantryShaftBlock.java index c4160824a..5f894b2c4 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/GantryShaftBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/gantry/GantryShaftBlock.java @@ -1,21 +1,21 @@ -package com.simibubi.create.content.contraptions.relays.advanced; +package com.simibubi.create.content.kinetics.gantry; import java.util.ArrayList; import java.util.List; import java.util.function.Predicate; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.content.kinetics.base.DirectionalKineticBlock; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.placement.IPlacementHelper; +import com.simibubi.create.foundation.placement.PlacementHelpers; +import com.simibubi.create.foundation.placement.PlacementOffset; +import com.simibubi.create.foundation.placement.PoleHelper; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.placement.IPlacementHelper; -import com.simibubi.create.foundation.utility.placement.PlacementHelpers; -import com.simibubi.create.foundation.utility.placement.PlacementOffset; -import com.simibubi.create.foundation.utility.placement.util.PoleHelper; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -47,7 +47,7 @@ import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; -public class GantryShaftBlock extends DirectionalKineticBlock implements ITE { +public class GantryShaftBlock extends DirectionalKineticBlock implements IBE { public static final Property PART = EnumProperty.create("part", Part.class); public static final BooleanProperty POWERED = BlockStateProperties.POWERED; @@ -180,9 +180,9 @@ public class GantryShaftBlock extends DirectionalKineticBlock implements ITE getTileEntityClass() { - return GantryShaftTileEntity.class; + public Class getBlockEntityClass() { + return GantryShaftBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.GANTRY_SHAFT.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.GANTRY_SHAFT.get(); } } diff --git a/src/main/java/com/simibubi/create/content/kinetics/gantry/GantryShaftBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/gantry/GantryShaftBlockEntity.java new file mode 100644 index 000000000..14c20af4a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/gantry/GantryShaftBlockEntity.java @@ -0,0 +1,115 @@ +package com.simibubi.create.content.kinetics.gantry; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.contraptions.gantry.GantryCarriageBlock; +import com.simibubi.create.content.contraptions.gantry.GantryCarriageBlockEntity; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.foundation.utility.Iterate; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; +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 class GantryShaftBlockEntity extends KineticBlockEntity { + + public GantryShaftBlockEntity(BlockEntityType typeIn, BlockPos pos, BlockState state) { + super(typeIn, pos, state); + } + + @Override + protected boolean syncSequenceContext() { + return true; + } + + public void checkAttachedCarriageBlocks() { + if (!canAssembleOn()) + return; + for (Direction d : Iterate.directions) { + if (d.getAxis() == getBlockState().getValue(GantryShaftBlock.FACING) + .getAxis()) + continue; + BlockPos offset = worldPosition.relative(d); + BlockState pinionState = level.getBlockState(offset); + if (!AllBlocks.GANTRY_CARRIAGE.has(pinionState)) + continue; + if (pinionState.getValue(GantryCarriageBlock.FACING) != d) + continue; + BlockEntity blockEntity = level.getBlockEntity(offset); + if (blockEntity instanceof GantryCarriageBlockEntity) + ((GantryCarriageBlockEntity) blockEntity).queueAssembly(); + } + } + + @Override + public void onSpeedChanged(float previousSpeed) { + super.onSpeedChanged(previousSpeed); + checkAttachedCarriageBlocks(); + } + + @Override + public float propagateRotationTo(KineticBlockEntity target, BlockState stateFrom, BlockState stateTo, BlockPos diff, + boolean connectedViaAxes, boolean connectedViaCogs) { + float defaultModifier = + super.propagateRotationTo(target, stateFrom, stateTo, diff, connectedViaAxes, connectedViaCogs); + + if (connectedViaAxes) + return defaultModifier; + if (!stateFrom.getValue(GantryShaftBlock.POWERED)) + return defaultModifier; + if (!AllBlocks.GANTRY_CARRIAGE.has(stateTo)) + return defaultModifier; + + Direction direction = Direction.getNearest(diff.getX(), diff.getY(), diff.getZ()); + if (stateTo.getValue(GantryCarriageBlock.FACING) != direction) + return defaultModifier; + return GantryCarriageBlockEntity.getGantryPinionModifier(stateFrom.getValue(GantryShaftBlock.FACING), + stateTo.getValue(GantryCarriageBlock.FACING)); + } + + @Override + public boolean isCustomConnection(KineticBlockEntity other, BlockState state, BlockState otherState) { + if (!AllBlocks.GANTRY_CARRIAGE.has(otherState)) + return false; + final BlockPos diff = other.getBlockPos() + .subtract(worldPosition); + Direction direction = Direction.getNearest(diff.getX(), diff.getY(), diff.getZ()); + return otherState.getValue(GantryCarriageBlock.FACING) == direction; + } + + public boolean canAssembleOn() { + BlockState blockState = getBlockState(); + if (!AllBlocks.GANTRY_SHAFT.has(blockState)) + return false; + if (blockState.getValue(GantryShaftBlock.POWERED)) + return false; + float speed = getPinionMovementSpeed(); + + switch (blockState.getValue(GantryShaftBlock.PART)) { + case END: + return speed < 0; + case MIDDLE: + return speed != 0; + case START: + return speed > 0; + case SINGLE: + default: + return false; + } + } + + public float getPinionMovementSpeed() { + BlockState blockState = getBlockState(); + if (!AllBlocks.GANTRY_SHAFT.has(blockState)) + return 0; + return Mth.clamp(convertToLinear(-getSpeed()), -.49f, .49f); + } + + @Override + protected boolean isNoisy() { + return false; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeBlock.java b/src/main/java/com/simibubi/create/content/kinetics/gauge/GaugeBlock.java similarity index 83% rename from src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeBlock.java rename to src/main/java/com/simibubi/create/content/kinetics/gauge/GaugeBlock.java index 76d4dc653..30fd76eca 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/gauge/GaugeBlock.java @@ -1,11 +1,11 @@ -package com.simibubi.create.content.contraptions.relays.gauge; +package com.simibubi.create.content.kinetics.gauge; import org.joml.Vector3f; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.DirectionalAxisKineticBlock; -import com.simibubi.create.content.contraptions.base.IRotate; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.content.kinetics.base.DirectionalAxisKineticBlock; +import com.simibubi.create.content.kinetics.base.IRotate; +import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.utility.Color; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Lang; @@ -32,7 +32,7 @@ import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; -public class GaugeBlock extends DirectionalAxisKineticBlock implements ITE { +public class GaugeBlock extends DirectionalAxisKineticBlock implements IBE { public static final GaugeShaper GAUGE = GaugeShaper.make(); protected Type type; @@ -120,13 +120,13 @@ public class GaugeBlock extends DirectionalAxisKineticBlock implements ITE 1 ? 4 : 1; + int particleCount = gaugeBE.dialTarget > 1 ? 4 : 1; if (particleCount == 1 && rand.nextFloat() > 1 / 4f) continue; @@ -168,10 +168,10 @@ public class GaugeBlock extends DirectionalAxisKineticBlock implements ITE getTileEntityClass() { - return GaugeTileEntity.class; + public Class getBlockEntityClass() { + return GaugeBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return type == Type.SPEED ? AllTileEntities.SPEEDOMETER.get() : AllTileEntities.STRESSOMETER.get(); + public BlockEntityType getBlockEntityType() { + return type == Type.SPEED ? AllBlockEntityTypes.SPEEDOMETER.get() : AllBlockEntityTypes.STRESSOMETER.get(); } } diff --git a/src/main/java/com/simibubi/create/content/kinetics/gauge/GaugeBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/gauge/GaugeBlockEntity.java new file mode 100644 index 000000000..ced8abf12 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/gauge/GaugeBlockEntity.java @@ -0,0 +1,56 @@ +package com.simibubi.create.content.kinetics.gauge; + +import java.util.List; + +import com.simibubi.create.content.equipment.goggles.IHaveGoggleInformation; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; + +public abstract class GaugeBlockEntity extends KineticBlockEntity implements IHaveGoggleInformation { + + public float dialTarget; + public float dialState; + public float prevDialState; + public int color; + + public GaugeBlockEntity(BlockEntityType typeIn, BlockPos pos, BlockState state) { + super(typeIn, pos, state); + } + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + compound.putFloat("Value", dialTarget); + compound.putInt("Color", color); + super.write(compound, clientPacket); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + dialTarget = compound.getFloat("Value"); + color = compound.getInt("Color"); + super.read(compound, clientPacket); + } + + @Override + public void tick() { + super.tick(); + prevDialState = dialState; + dialState += (dialTarget - dialState) * .125f; + if (dialState > 1 && level.random.nextFloat() < 1 / 2f) + dialState -= (dialState - 1) * level.random.nextFloat(); + } + + @Override + public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { + tooltip.add(componentSpacing.plainCopy().append(Lang.translateDirect("gui.gauge.info_header"))); + + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeGenerator.java b/src/main/java/com/simibubi/create/content/kinetics/gauge/GaugeGenerator.java similarity index 89% rename from src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeGenerator.java rename to src/main/java/com/simibubi/create/content/kinetics/gauge/GaugeGenerator.java index 1d319e6e0..079e033a4 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeGenerator.java +++ b/src/main/java/com/simibubi/create/content/kinetics/gauge/GaugeGenerator.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.relays.gauge; +package com.simibubi.create.content.kinetics.gauge; import com.simibubi.create.foundation.data.DirectionalAxisBlockStateGen; import com.tterrag.registrate.providers.DataGenContext; diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeInstance.java b/src/main/java/com/simibubi/create/content/kinetics/gauge/GaugeInstance.java similarity index 76% rename from src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeInstance.java rename to src/main/java/com/simibubi/create/content/kinetics/gauge/GaugeInstance.java index b27f44012..03d9b9dfc 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeInstance.java +++ b/src/main/java/com/simibubi/create/content/kinetics/gauge/GaugeInstance.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.relays.gauge; +package com.simibubi.create.content.kinetics.gauge; import java.util.ArrayList; @@ -8,9 +8,8 @@ import com.jozufozu.flywheel.api.instance.DynamicInstance; import com.jozufozu.flywheel.core.materials.model.ModelData; import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.relays.encased.ShaftInstance; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.ShaftInstance; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Iterate; @@ -18,28 +17,27 @@ import com.simibubi.create.foundation.utility.Iterate; import net.minecraft.core.Direction; import net.minecraft.util.Mth; -public abstract class GaugeInstance extends ShaftInstance implements DynamicInstance { +public abstract class GaugeInstance extends ShaftInstance implements DynamicInstance { protected final ArrayList faces; protected PoseStack ms; - protected GaugeInstance(MaterialManager dispatcher, KineticTileEntity tile) { - super(dispatcher, tile); + protected GaugeInstance(MaterialManager materialManager, GaugeBlockEntity blockEntity) { + super(materialManager, blockEntity); faces = new ArrayList<>(2); - GaugeTileEntity gaugeTile = (GaugeTileEntity) tile; GaugeBlock gaugeBlock = (GaugeBlock) blockState.getBlock(); - Instancer dialModel = getTransformMaterial().getModel(AllBlockPartials.GAUGE_DIAL, blockState); + Instancer dialModel = getTransformMaterial().getModel(AllPartialModels.GAUGE_DIAL, blockState); Instancer headModel = getHeadModel(); ms = new PoseStack(); TransformStack msr = TransformStack.cast(ms); msr.translate(getInstancePosition()); - float progress = Mth.lerp(AnimationTickHolder.getPartialTicks(), gaugeTile.prevDialState, gaugeTile.dialState); + float progress = Mth.lerp(AnimationTickHolder.getPartialTicks(), blockEntity.prevDialState, blockEntity.dialState); for (Direction facing : Iterate.directions) { if (!gaugeBlock.shouldRenderHeadOnFace(world, pos, blockState, facing)) @@ -59,12 +57,12 @@ public abstract class GaugeInstance extends ShaftInstance implements DynamicInst @Override public void beginFrame() { - GaugeTileEntity gaugeTile = (GaugeTileEntity) blockEntity; + GaugeBlockEntity gaugeBlockEntity = (GaugeBlockEntity) blockEntity; - if (Mth.equal(gaugeTile.prevDialState, gaugeTile.dialState)) + if (Mth.equal(gaugeBlockEntity.prevDialState, gaugeBlockEntity.dialState)) return; - float progress = Mth.lerp(AnimationTickHolder.getPartialTicks(), gaugeTile.prevDialState, gaugeTile.dialState); + float progress = Mth.lerp(AnimationTickHolder.getPartialTicks(), gaugeBlockEntity.prevDialState, gaugeBlockEntity.dialState); TransformStack msr = TransformStack.cast(ms); @@ -144,24 +142,24 @@ public abstract class GaugeInstance extends ShaftInstance implements DynamicInst } public static class Speed extends GaugeInstance { - public Speed(MaterialManager dispatcher, KineticTileEntity tile) { - super(dispatcher, tile); + public Speed(MaterialManager materialManager, GaugeBlockEntity blockEntity) { + super(materialManager, blockEntity); } @Override protected Instancer getHeadModel() { - return getTransformMaterial().getModel(AllBlockPartials.GAUGE_HEAD_SPEED, blockState); + return getTransformMaterial().getModel(AllPartialModels.GAUGE_HEAD_SPEED, blockState); } } public static class Stress extends GaugeInstance { - public Stress(MaterialManager dispatcher, KineticTileEntity tile) { - super(dispatcher, tile); + public Stress(MaterialManager materialManager, GaugeBlockEntity blockEntity) { + super(materialManager, blockEntity); } @Override protected Instancer getHeadModel() { - return getTransformMaterial().getModel(AllBlockPartials.GAUGE_HEAD_STRESS, blockState); + return getTransformMaterial().getModel(AllPartialModels.GAUGE_HEAD_STRESS, blockState); } } } diff --git a/src/main/java/com/simibubi/create/content/kinetics/gauge/GaugeObservedPacket.java b/src/main/java/com/simibubi/create/content/kinetics/gauge/GaugeObservedPacket.java new file mode 100644 index 000000000..bfcb0b6ff --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/gauge/GaugeObservedPacket.java @@ -0,0 +1,34 @@ +package com.simibubi.create.content.kinetics.gauge; + +import com.simibubi.create.foundation.networking.BlockEntityConfigurationPacket; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; + +public class GaugeObservedPacket extends BlockEntityConfigurationPacket { + + public GaugeObservedPacket(BlockPos pos) { + super(pos); + } + + public GaugeObservedPacket(FriendlyByteBuf buffer) { + super(buffer); + } + + @Override + protected void writeSettings(FriendlyByteBuf buffer) {} + + @Override + protected void readSettings(FriendlyByteBuf buffer) {} + + @Override + protected void applySettings(StressGaugeBlockEntity be) { + be.onObserved(); + } + + @Override + protected boolean causeUpdate() { + return false; + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/gauge/GaugeRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/gauge/GaugeRenderer.java new file mode 100644 index 000000000..404454fe8 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/gauge/GaugeRenderer.java @@ -0,0 +1,76 @@ +package com.simibubi.create.content.kinetics.gauge; + +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.core.PartialModel; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.ShaftRenderer; +import com.simibubi.create.content.kinetics.gauge.GaugeBlock.Type; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.Iterate; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; +import net.minecraft.world.level.block.state.BlockState; + +public class GaugeRenderer extends ShaftRenderer { + + protected GaugeBlock.Type type; + + public static GaugeRenderer speed(BlockEntityRendererProvider.Context context) { + return new GaugeRenderer(context, Type.SPEED); + } + + public static GaugeRenderer stress(BlockEntityRendererProvider.Context context) { + return new GaugeRenderer(context, Type.STRESS); + } + + protected GaugeRenderer(BlockEntityRendererProvider.Context context, GaugeBlock.Type type) { + super(context); + this.type = type; + } + + @Override + protected void renderSafe(GaugeBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + if (Backend.canUseInstancing(be.getLevel())) return; + + super.renderSafe(be, partialTicks, ms, buffer, light, overlay); + + BlockState gaugeState = be.getBlockState(); + GaugeBlockEntity gaugeBE = (GaugeBlockEntity) be; + + PartialModel partialModel = (type == Type.SPEED ? AllPartialModels.GAUGE_HEAD_SPEED : AllPartialModels.GAUGE_HEAD_STRESS); + SuperByteBuffer headBuffer = + CachedBufferer.partial(partialModel, gaugeState); + SuperByteBuffer dialBuffer = CachedBufferer.partial(AllPartialModels.GAUGE_DIAL, gaugeState); + + float dialPivot = 5.75f / 16; + float progress = Mth.lerp(partialTicks, gaugeBE.prevDialState, gaugeBE.dialState); + + for (Direction facing : Iterate.directions) { + if (!((GaugeBlock) gaugeState.getBlock()).shouldRenderHeadOnFace(be.getLevel(), be.getBlockPos(), gaugeState, + facing)) + continue; + + VertexConsumer vb = buffer.getBuffer(RenderType.solid()); + rotateBufferTowards(dialBuffer, facing).translate(0, dialPivot, dialPivot) + .rotate(Direction.EAST, (float) (Math.PI / 2 * -progress)) + .translate(0, -dialPivot, -dialPivot) + .light(light) + .renderInto(ms, vb); + rotateBufferTowards(headBuffer, facing).light(light) + .renderInto(ms, vb); + } + } + + protected SuperByteBuffer rotateBufferTowards(SuperByteBuffer buffer, Direction target) { + return buffer.rotateCentered(Direction.UP, (float) ((-target.toYRot() - 90) / 180 * Math.PI)); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeShaper.java b/src/main/java/com/simibubi/create/content/kinetics/gauge/GaugeShaper.java similarity index 94% rename from src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeShaper.java rename to src/main/java/com/simibubi/create/content/kinetics/gauge/GaugeShaper.java index b21d42d34..e149f1125 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeShaper.java +++ b/src/main/java/com/simibubi/create/content/kinetics/gauge/GaugeShaper.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.relays.gauge; +package com.simibubi.create.content.kinetics.gauge; import java.util.Arrays; diff --git a/src/main/java/com/simibubi/create/content/kinetics/gauge/SpeedGaugeBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/gauge/SpeedGaugeBlockEntity.java new file mode 100644 index 000000000..0a59523a3 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/gauge/SpeedGaugeBlockEntity.java @@ -0,0 +1,97 @@ +package com.simibubi.create.content.kinetics.gauge; + +import java.util.List; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.compat.computercraft.AbstractComputerBehaviour; +import com.simibubi.create.compat.computercraft.ComputerCraftProxy; +import com.simibubi.create.content.kinetics.base.IRotate.SpeedLevel; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.Color; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.minecraft.ChatFormatting; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.network.chat.Component; +import net.minecraft.util.Mth; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; + +public class SpeedGaugeBlockEntity extends GaugeBlockEntity { + + public AbstractComputerBehaviour computerBehaviour; + + public SpeedGaugeBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + public void addBehaviours(List behaviours) { + super.addBehaviours(behaviours); + behaviours.add(computerBehaviour = ComputerCraftProxy.behaviour(this)); + } + + @Override + public void onSpeedChanged(float prevSpeed) { + super.onSpeedChanged(prevSpeed); + float speed = Math.abs(getSpeed()); + + dialTarget = getDialTarget(speed); + color = Color.mixColors(SpeedLevel.of(speed) + .getColor(), 0xffffff, .25f); + + setChanged(); + } + + public static float getDialTarget(float speed) { + speed = Math.abs(speed); + float medium = AllConfigs.server().kinetics.mediumSpeed.get() + .floatValue(); + float fast = AllConfigs.server().kinetics.fastSpeed.get() + .floatValue(); + float max = AllConfigs.server().kinetics.maxRotationSpeed.get() + .floatValue(); + float target = 0; + if (speed == 0) + target = 0; + else if (speed < medium) + target = Mth.lerp(speed / medium, 0, .45f); + else if (speed < fast) + target = Mth.lerp((speed - medium) / (fast - medium), .45f, .75f); + else + target = Mth.lerp((speed - fast) / (max - fast), .75f, 1.125f); + return target; + } + + @Override + public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { + super.addToGoggleTooltip(tooltip, isPlayerSneaking); + Lang.translate("gui.speedometer.title") + .style(ChatFormatting.GRAY) + .forGoggles(tooltip); + SpeedLevel.getFormattedSpeedText(speed, isOverStressed()) + .forGoggles(tooltip); + return true; + } + + @NotNull + @Override + public LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction side) { + if (computerBehaviour.isPeripheralCap(cap)) + return computerBehaviour.getPeripheralCapability(); + return super.getCapability(cap, side); + } + + @Override + public void invalidateCaps() { + super.invalidateCaps(); + computerBehaviour.removePeripheral(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/gauge/StressGaugeBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/gauge/StressGaugeBlockEntity.java new file mode 100644 index 000000000..b0251d058 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/gauge/StressGaugeBlockEntity.java @@ -0,0 +1,169 @@ +package com.simibubi.create.content.kinetics.gauge; + +import java.util.List; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.AllPackets; +import com.simibubi.create.compat.computercraft.AbstractComputerBehaviour; +import com.simibubi.create.compat.computercraft.ComputerCraftProxy; +import com.simibubi.create.content.kinetics.base.IRotate.StressImpact; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.item.TooltipHelper; +import com.simibubi.create.foundation.utility.Color; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.LangBuilder; + +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.util.Mth; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; + +public class StressGaugeBlockEntity extends GaugeBlockEntity { + + public AbstractComputerBehaviour computerBehaviour; + + static BlockPos lastSent; + + public StressGaugeBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + public void addBehaviours(List behaviours) { + super.addBehaviours(behaviours); + behaviours.add(computerBehaviour = ComputerCraftProxy.behaviour(this)); + registerAwardables(behaviours, AllAdvancements.STRESSOMETER, AllAdvancements.STRESSOMETER_MAXED); + } + + @Override + public void updateFromNetwork(float maxStress, float currentStress, int networkSize) { + super.updateFromNetwork(maxStress, currentStress, networkSize); + + if (!StressImpact.isEnabled()) + dialTarget = 0; + else if (isOverStressed()) + dialTarget = 1.125f; + else if (maxStress == 0) + dialTarget = 0; + else + dialTarget = currentStress / maxStress; + + if (dialTarget > 0) { + if (dialTarget < .5f) + color = Color.mixColors(0x00FF00, 0xFFFF00, dialTarget * 2); + else if (dialTarget < 1) + color = Color.mixColors(0xFFFF00, 0xFF0000, (dialTarget) * 2 - 1); + else + color = 0xFF0000; + } + + sendData(); + setChanged(); + } + + @Override + public void onSpeedChanged(float prevSpeed) { + super.onSpeedChanged(prevSpeed); + if (getSpeed() == 0) { + dialTarget = 0; + setChanged(); + return; + } + + updateFromNetwork(capacity, stress, getOrCreateNetwork().getSize()); + } + + @Override + public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { + if (!StressImpact.isEnabled()) + return false; + + super.addToGoggleTooltip(tooltip, isPlayerSneaking); + + double capacity = getNetworkCapacity(); + double stressFraction = getNetworkStress() / (capacity == 0 ? 1 : capacity); + + Lang.translate("gui.stressometer.title") + .style(ChatFormatting.GRAY) + .forGoggles(tooltip); + + if (getTheoreticalSpeed() == 0) + Lang.text(TooltipHelper.makeProgressBar(3, 0)) + .translate("gui.stressometer.no_rotation") + .style(ChatFormatting.DARK_GRAY) + .forGoggles(tooltip); + else { + StressImpact.getFormattedStressText(stressFraction) + .forGoggles(tooltip); + Lang.translate("gui.stressometer.capacity") + .style(ChatFormatting.GRAY) + .forGoggles(tooltip); + + double remainingCapacity = capacity - getNetworkStress(); + + LangBuilder su = Lang.translate("generic.unit.stress"); + LangBuilder stressTip = Lang.number(remainingCapacity) + .add(su) + .style(StressImpact.of(stressFraction) + .getRelativeColor()); + + if (remainingCapacity != capacity) + stressTip.text(ChatFormatting.GRAY, " / ") + .add(Lang.number(capacity) + .add(su) + .style(ChatFormatting.DARK_GRAY)); + + stressTip.forGoggles(tooltip, 1); + } + + if (!worldPosition.equals(lastSent)) + AllPackets.getChannel().sendToServer(new GaugeObservedPacket(lastSent = worldPosition)); + + return true; + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + super.read(compound, clientPacket); + if (clientPacket && worldPosition != null && worldPosition.equals(lastSent)) + lastSent = null; + } + + public float getNetworkStress() { + return stress; + } + + public float getNetworkCapacity() { + return capacity; + } + + public void onObserved() { + award(AllAdvancements.STRESSOMETER); + if (Mth.equal(dialTarget, 1)) + award(AllAdvancements.STRESSOMETER_MAXED); + } + + @NotNull + @Override + public LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction side) { + if (computerBehaviour.isPeripheralCap(cap)) + return computerBehaviour.getPeripheralCapability(); + return super.getCapability(cap, side); + } + + @Override + public void invalidateCaps() { + super.invalidateCaps(); + computerBehaviour.removePeripheral(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxBlock.java b/src/main/java/com/simibubi/create/content/kinetics/gearbox/GearboxBlock.java similarity index 80% rename from src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxBlock.java rename to src/main/java/com/simibubi/create/content/kinetics/gearbox/GearboxBlock.java index bf7dcd4c9..674deb1b2 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/gearbox/GearboxBlock.java @@ -1,12 +1,12 @@ -package com.simibubi.create.content.contraptions.relays.gearbox; +package com.simibubi.create.content.kinetics.gearbox; import java.util.Arrays; import java.util.List; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllItems; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.content.kinetics.base.RotatedPillarKineticBlock; +import com.simibubi.create.foundation.block.IBE; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -22,7 +22,7 @@ import net.minecraft.world.level.material.PushReaction; import net.minecraft.world.level.storage.loot.LootContext.Builder; import net.minecraft.world.phys.HitResult; -public class GearboxBlock extends RotatedPillarKineticBlock implements ITE { +public class GearboxBlock extends RotatedPillarKineticBlock implements IBE { public GearboxBlock(Properties properties) { super(properties); @@ -67,12 +67,12 @@ public class GearboxBlock extends RotatedPillarKineticBlock implements ITE getTileEntityClass() { - return GearboxTileEntity.class; + public Class getBlockEntityClass() { + return GearboxBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.GEARBOX.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.GEARBOX.get(); } } diff --git a/src/main/java/com/simibubi/create/content/kinetics/gearbox/GearboxBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/gearbox/GearboxBlockEntity.java new file mode 100644 index 000000000..ee7537cda --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/gearbox/GearboxBlockEntity.java @@ -0,0 +1,20 @@ +package com.simibubi.create.content.kinetics.gearbox; + +import com.simibubi.create.content.kinetics.base.DirectionalShaftHalvesBlockEntity; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; + +public class GearboxBlockEntity extends DirectionalShaftHalvesBlockEntity { + + public GearboxBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + protected boolean isNoisy() { + return false; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxInstance.java b/src/main/java/com/simibubi/create/content/kinetics/gearbox/GearboxInstance.java similarity index 82% rename from src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxInstance.java rename to src/main/java/com/simibubi/create/content/kinetics/gearbox/GearboxInstance.java index ae7173155..03ce8bd04 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxInstance.java +++ b/src/main/java/com/simibubi/create/content/kinetics/gearbox/GearboxInstance.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.relays.gearbox; +package com.simibubi.create.content.kinetics.gearbox; import java.util.EnumMap; import java.util.Map; @@ -7,9 +7,9 @@ import com.jozufozu.flywheel.api.InstanceData; import com.jozufozu.flywheel.api.Instancer; import com.jozufozu.flywheel.api.Material; import com.jozufozu.flywheel.api.MaterialManager; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.KineticTileInstance; -import com.simibubi.create.content.contraptions.base.flwdata.RotatingData; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityInstance; +import com.simibubi.create.content.kinetics.base.flwdata.RotatingData; import com.simibubi.create.foundation.utility.Iterate; import net.minecraft.core.BlockPos; @@ -17,13 +17,13 @@ import net.minecraft.core.Direction; import net.minecraft.world.level.LightLayer; import net.minecraft.world.level.block.state.properties.BlockStateProperties; -public class GearboxInstance extends KineticTileInstance { +public class GearboxInstance extends KineticBlockEntityInstance { protected final EnumMap keys; protected Direction sourceFacing; - public GearboxInstance(MaterialManager modelManager, GearboxTileEntity tile) { - super(modelManager, tile); + public GearboxInstance(MaterialManager materialManager, GearboxBlockEntity blockEntity) { + super(materialManager, blockEntity); keys = new EnumMap<>(Direction.class); @@ -40,13 +40,13 @@ public class GearboxInstance extends KineticTileInstance { if (boxAxis == axis) continue; - Instancer shaft = rotatingMaterial.getModel(AllBlockPartials.SHAFT_HALF, blockState, direction); + Instancer shaft = rotatingMaterial.getModel(AllPartialModels.SHAFT_HALF, blockState, direction); RotatingData key = shaft.createInstance(); key.setRotationAxis(Direction.get(Direction.AxisDirection.POSITIVE, axis).step()) .setRotationalSpeed(getSpeed(direction)) - .setRotationOffset(getRotationOffset(axis)).setColor(tile) + .setRotationOffset(getRotationOffset(axis)).setColor(blockEntity) .setPosition(getInstancePosition()) .setBlockLight(blockLight) .setSkyLight(skyLight); diff --git a/src/main/java/com/simibubi/create/content/kinetics/gearbox/GearboxRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/gearbox/GearboxRenderer.java new file mode 100644 index 000000000..7a1260830 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/gearbox/GearboxRenderer.java @@ -0,0 +1,61 @@ +package com.simibubi.create.content.kinetics.gearbox; + +import com.jozufozu.flywheel.backend.Backend; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.Iterate; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; + +public class GearboxRenderer extends KineticBlockEntityRenderer { + + public GearboxRenderer(BlockEntityRendererProvider.Context context) { + super(context); + } + + @Override + protected void renderSafe(GearboxBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + if (Backend.canUseInstancing(be.getLevel())) return; + + final Axis boxAxis = be.getBlockState().getValue(BlockStateProperties.AXIS); + final BlockPos pos = be.getBlockPos(); + float time = AnimationTickHolder.getRenderTime(be.getLevel()); + + for (Direction direction : Iterate.directions) { + final Axis axis = direction.getAxis(); + if (boxAxis == axis) + continue; + + SuperByteBuffer shaft = CachedBufferer.partialFacing(AllPartialModels.SHAFT_HALF, be.getBlockState(), direction); + float offset = getRotationOffsetForPosition(be, pos, axis); + float angle = (time * be.getSpeed() * 3f / 10) % 360; + + if (be.getSpeed() != 0 && be.hasSource()) { + BlockPos source = be.source.subtract(be.getBlockPos()); + Direction sourceFacing = Direction.getNearest(source.getX(), source.getY(), source.getZ()); + if (sourceFacing.getAxis() == direction.getAxis()) + angle *= sourceFacing == direction ? 1 : -1; + else if (sourceFacing.getAxisDirection() == direction.getAxisDirection()) + angle *= -1; + } + + angle += offset; + angle = angle / 180f * (float) Math.PI; + + kineticRotationTransform(shaft, be, axis, angle, light); + shaft.renderInto(ms, buffer.getBuffer(RenderType.solid())); + } + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/VerticalGearboxItem.java b/src/main/java/com/simibubi/create/content/kinetics/gearbox/VerticalGearboxItem.java similarity index 93% rename from src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/VerticalGearboxItem.java rename to src/main/java/com/simibubi/create/content/kinetics/gearbox/VerticalGearboxItem.java index 3f5a07b01..6f59a1215 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/VerticalGearboxItem.java +++ b/src/main/java/com/simibubi/create/content/kinetics/gearbox/VerticalGearboxItem.java @@ -1,9 +1,9 @@ -package com.simibubi.create.content.contraptions.relays.gearbox; +package com.simibubi.create.content.kinetics.gearbox; import java.util.Map; import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.base.IRotate; +import com.simibubi.create.content.kinetics.base.IRotate; import com.simibubi.create.foundation.utility.Iterate; import net.minecraft.core.BlockPos; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/AllArmInteractionPointTypes.java b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/AllArmInteractionPointTypes.java similarity index 88% rename from src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/AllArmInteractionPointTypes.java rename to src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/AllArmInteractionPointTypes.java index 527bea4cb..3578a2c3e 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/AllArmInteractionPointTypes.java +++ b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/AllArmInteractionPointTypes.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.block.mechanicalArm; +package com.simibubi.create.content.kinetics.mechanicalArm; import java.util.Optional; import java.util.function.Function; @@ -9,27 +9,27 @@ import org.apache.commons.lang3.mutable.MutableBoolean; import com.simibubi.create.AllBlocks; import com.simibubi.create.Create; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.components.crafter.MechanicalCrafterBlock; -import com.simibubi.create.content.contraptions.components.crafter.MechanicalCrafterTileEntity; -import com.simibubi.create.content.contraptions.components.deployer.DeployerBlock; -import com.simibubi.create.content.contraptions.components.saw.SawBlock; -import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock; -import com.simibubi.create.content.contraptions.relays.belt.BeltHelper; -import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity; -import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelBlock; -import com.simibubi.create.content.logistics.block.chute.AbstractChuteBlock; -import com.simibubi.create.content.logistics.block.funnel.AbstractFunnelBlock; -import com.simibubi.create.content.logistics.block.funnel.BeltFunnelBlock; -import com.simibubi.create.content.logistics.block.funnel.BeltFunnelBlock.Shape; -import com.simibubi.create.content.logistics.block.funnel.FunnelBlock; -import com.simibubi.create.content.logistics.block.funnel.FunnelTileEntity; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.belt.BeltBlockEntity; +import com.simibubi.create.content.kinetics.belt.BeltHelper; +import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour; +import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour.TransportedResult; +import com.simibubi.create.content.kinetics.crafter.MechanicalCrafterBlock; +import com.simibubi.create.content.kinetics.crafter.MechanicalCrafterBlockEntity; +import com.simibubi.create.content.kinetics.deployer.DeployerBlock; +import com.simibubi.create.content.kinetics.saw.SawBlock; +import com.simibubi.create.content.logistics.chute.AbstractChuteBlock; +import com.simibubi.create.content.logistics.funnel.AbstractFunnelBlock; +import com.simibubi.create.content.logistics.funnel.BeltFunnelBlock; +import com.simibubi.create.content.logistics.funnel.BeltFunnelBlock.Shape; +import com.simibubi.create.content.logistics.funnel.FunnelBlock; +import com.simibubi.create.content.logistics.funnel.FunnelBlockEntity; +import com.simibubi.create.content.logistics.tunnel.BeltTunnelBlock; +import com.simibubi.create.content.processing.burner.BlazeBurnerBlock; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.inventory.InvManipulationBehaviour; import com.simibubi.create.foundation.item.SmartInventory; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour.TransportedResult; -import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.inventory.InvManipulationBehaviour; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.core.BlockPos; @@ -262,7 +262,7 @@ public class AllArmInteractionPointTypes { @Override public boolean canCreatePoint(Level level, BlockPos pos, BlockState state) { return AllBlocks.MECHANICAL_SAW.has(state) && state.getValue(SawBlock.FACING) == Direction.UP - && ((KineticTileEntity) level.getBlockEntity(pos)).getSpeed() != 0; + && ((KineticBlockEntity) level.getBlockEntity(pos)).getSpeed() != 0; } @Override @@ -377,11 +377,11 @@ public class AllArmInteractionPointTypes { @Override public void keepAlive() { super.keepAlive(); - BeltTileEntity beltTE = BeltHelper.getSegmentTE(level, pos); - if (beltTE == null) + BeltBlockEntity beltBE = BeltHelper.getSegmentBE(level, pos); + if (beltBE == null) return; TransportedItemStackHandlerBehaviour transport = - beltTE.getBehaviour(TransportedItemStackHandlerBehaviour.TYPE); + beltBE.getBehaviour(TransportedItemStackHandlerBehaviour.TYPE); if (transport == null) return; MutableBoolean found = new MutableBoolean(false); @@ -444,10 +444,10 @@ public class AllArmInteractionPointTypes { @Override public ItemStack extract(int slot, int amount, boolean simulate) { - BlockEntity te = level.getBlockEntity(pos); - if (!(te instanceof MechanicalCrafterTileEntity)) + BlockEntity be = level.getBlockEntity(pos); + if (!(be instanceof MechanicalCrafterBlockEntity)) return ItemStack.EMPTY; - MechanicalCrafterTileEntity crafter = (MechanicalCrafterTileEntity) te; + MechanicalCrafterBlockEntity crafter = (MechanicalCrafterBlockEntity) be; SmartInventory inventory = crafter.getInventory(); inventory.allowExtraction(); ItemStack extract = super.extract(slot, amount, simulate); @@ -525,8 +525,8 @@ public class AllArmInteractionPointTypes { @Override public ItemStack insert(ItemStack stack, boolean simulate) { - FilteringBehaviour filtering = TileEntityBehaviour.get(level, pos, FilteringBehaviour.TYPE); - InvManipulationBehaviour inserter = TileEntityBehaviour.get(level, pos, InvManipulationBehaviour.TYPE); + FilteringBehaviour filtering = BlockEntityBehaviour.get(level, pos, FilteringBehaviour.TYPE); + InvManipulationBehaviour inserter = BlockEntityBehaviour.get(level, pos, InvManipulationBehaviour.TYPE); if (cachedState.getOptionalValue(BlockStateProperties.POWERED) .orElse(false)) return stack; @@ -538,12 +538,12 @@ public class AllArmInteractionPointTypes { inserter.simulate(); ItemStack insert = inserter.insert(stack); if (!simulate && insert.getCount() != stack.getCount()) { - BlockEntity tileEntity = level.getBlockEntity(pos); - if (tileEntity instanceof FunnelTileEntity) { - FunnelTileEntity funnelTileEntity = (FunnelTileEntity) tileEntity; - funnelTileEntity.onTransfer(stack); - if (funnelTileEntity.hasFlap()) - funnelTileEntity.flap(true); + BlockEntity blockEntity = level.getBlockEntity(pos); + if (blockEntity instanceof FunnelBlockEntity) { + FunnelBlockEntity funnelBlockEntity = (FunnelBlockEntity) blockEntity; + funnelBlockEntity.onTransfer(stack); + if (funnelBlockEntity.hasFlap()) + funnelBlockEntity.flap(true); } } return insert; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmAngleTarget.java b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmAngleTarget.java similarity index 88% rename from src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmAngleTarget.java rename to src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmAngleTarget.java index 2181b41ae..59bc62aa2 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmAngleTarget.java +++ b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmAngleTarget.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.block.mechanicalArm; +package com.simibubi.create.content.kinetics.mechanicalArm; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.VecHelper; @@ -19,18 +19,15 @@ public class ArmAngleTarget { float headAngle; private ArmAngleTarget() { - lowerArmAngle = 155; - upperArmAngle = 60; - headAngle = -15; + lowerArmAngle = 135; + upperArmAngle = 45; + headAngle = 0; } public ArmAngleTarget(BlockPos armPos, Vec3 pointTarget, Direction clawFacing, boolean ceiling) { -// if (ceiling) -// clawFacing = clawFacing.getOpposite(); - Vec3 target = pointTarget; Vec3 origin = VecHelper.getCenterOf(armPos) - .add(0, ceiling ? -4 / 16f : 4 / 16f, 0); + .add(0, ceiling ? -6 / 16f : 6 / 16f, 0); Vec3 clawTarget = target; target = target.add(Vec3.atLowerCornerOf(clawFacing.getOpposite() .getNormal()) @@ -48,9 +45,9 @@ public class ArmAngleTarget { float alphaOffset = AngleHelper.deg(Mth.atan2(diff.y, horizontalDistance)); - float a = 18 / 16f; // lower arm length + float a = 14 / 16f; // lower arm length float a2 = a * a; - float b = 17 / 16f; // upper arm length + float b = 15 / 16f; // upper arm length float b2 = b * b; float diffLength = Mth.clamp(Mth.sqrt((float) (diff.y * diff.y + horizontalDistance * horizontalDistance)), 1 / 8f, a + b); diff --git a/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmBlock.java b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmBlock.java new file mode 100644 index 000000000..ea4c24eca --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmBlock.java @@ -0,0 +1,118 @@ +package com.simibubi.create.content.kinetics.mechanicalArm; + +import org.apache.commons.lang3.mutable.MutableBoolean; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllItems; +import com.simibubi.create.AllShapes; +import com.simibubi.create.content.kinetics.base.KineticBlock; +import com.simibubi.create.content.kinetics.mechanicalArm.ArmBlockEntity.Phase; +import com.simibubi.create.content.kinetics.simpleRelays.ICogWheel; +import com.simibubi.create.foundation.block.IBE; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +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.item.context.BlockPlaceContext; +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.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition.Builder; +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 ArmBlock extends KineticBlock implements IBE, ICogWheel { + + public static final BooleanProperty CEILING = BooleanProperty.create("ceiling"); + + public ArmBlock(Properties properties) { + super(properties); + registerDefaultState(defaultBlockState().setValue(CEILING, false)); + } + + @Override + protected void createBlockStateDefinition(Builder p_206840_1_) { + super.createBlockStateDefinition(p_206840_1_.add(CEILING)); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext ctx) { + return defaultBlockState().setValue(CEILING, ctx.getClickedFace() == Direction.DOWN); + } + + @Override + public VoxelShape getShape(BlockState state, BlockGetter p_220053_2_, BlockPos p_220053_3_, + CollisionContext p_220053_4_) { + return state.getValue(CEILING) ? AllShapes.MECHANICAL_ARM_CEILING : AllShapes.MECHANICAL_ARM; + } + + @Override + public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean isMoving) { + super.onPlace(state, world, pos, oldState, isMoving); + withBlockEntityDo(world, pos, ArmBlockEntity::redstoneUpdate); + } + + @Override + public void neighborChanged(BlockState state, Level world, BlockPos pos, Block p_220069_4_, + BlockPos p_220069_5_, boolean p_220069_6_) { + withBlockEntityDo(world, pos, ArmBlockEntity::redstoneUpdate); + } + + @Override + public Axis getRotationAxis(BlockState state) { + return Axis.Y; + } + + @Override + public Class getBlockEntityClass() { + return ArmBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.MECHANICAL_ARM.get(); + } + + @Override + public InteractionResult use(BlockState p_225533_1_, Level world, BlockPos pos, Player player, + InteractionHand hand, BlockHitResult p_225533_6_) { + ItemStack heldItem = player.getItemInHand(hand); + + if (AllItems.GOGGLES.isIn(heldItem)) { + InteractionResult gogglesResult = onBlockEntityUse(world, pos, ate -> { + if (ate.goggles) + return InteractionResult.PASS; + ate.goggles = true; + ate.notifyUpdate(); + return InteractionResult.SUCCESS; + }); + if (gogglesResult.consumesAction()) + return gogglesResult; + } + + MutableBoolean success = new MutableBoolean(false); + withBlockEntityDo(world, pos, be -> { + if (be.heldItem.isEmpty()) + return; + success.setTrue(); + if (world.isClientSide) + return; + player.getInventory().placeItemBackInInventory(be.heldItem); + be.heldItem = ItemStack.EMPTY; + be.phase = Phase.SEARCH_INPUTS; + be.setChanged(); + be.sendData(); + }); + + return success.booleanValue() ? InteractionResult.SUCCESS : InteractionResult.PASS; + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmBlockEntity.java new file mode 100644 index 000000000..c7f68656b --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmBlockEntity.java @@ -0,0 +1,656 @@ +package com.simibubi.create.content.kinetics.mechanicalArm; + +import java.util.ArrayList; +import java.util.List; + +import javax.annotation.Nullable; + +import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; +import com.simibubi.create.Create; +import com.simibubi.create.content.contraptions.ITransformableBlockEntity; +import com.simibubi.create.content.contraptions.StructureTransform; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.mechanicalArm.AllArmInteractionPointTypes.JukeboxPoint; +import com.simibubi.create.content.kinetics.mechanicalArm.ArmInteractionPoint.Mode; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.CenteredSideValueBoxTransform; +import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.INamedIconOptions; +import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollOptionBehaviour; +import com.simibubi.create.foundation.gui.AllIcons; +import com.simibubi.create.foundation.item.TooltipHelper; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.NBTHelper; +import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.SectionPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.Component; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.util.Mth; +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.JukeboxBlock; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.ChunkSource; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; + +public class ArmBlockEntity extends KineticBlockEntity implements ITransformableBlockEntity { + + // Server + List inputs; + List outputs; + ListTag interactionPointTag; + + // Both + float chasedPointProgress; + int chasedPointIndex; + ItemStack heldItem; + Phase phase; + boolean goggles; + + // Client + ArmAngleTarget previousTarget; + LerpedFloat lowerArmAngle; + LerpedFloat upperArmAngle; + LerpedFloat baseAngle; + LerpedFloat headAngle; + LerpedFloat clawAngle; + float previousBaseAngle; + boolean updateInteractionPoints; + int tooltipWarmup; + + // + protected ScrollOptionBehaviour selectionMode; + protected int lastInputIndex = -1; + protected int lastOutputIndex = -1; + protected boolean redstoneLocked; + + public enum Phase { + SEARCH_INPUTS, MOVE_TO_INPUT, SEARCH_OUTPUTS, MOVE_TO_OUTPUT, DANCING + } + + public ArmBlockEntity(BlockEntityType typeIn, BlockPos pos, BlockState state) { + super(typeIn, pos, state); + inputs = new ArrayList<>(); + outputs = new ArrayList<>(); + interactionPointTag = null; + heldItem = ItemStack.EMPTY; + phase = Phase.SEARCH_INPUTS; + previousTarget = ArmAngleTarget.NO_TARGET; + baseAngle = LerpedFloat.angular(); + baseAngle.startWithValue(previousTarget.baseAngle); + lowerArmAngle = LerpedFloat.angular(); + lowerArmAngle.startWithValue(previousTarget.lowerArmAngle); + upperArmAngle = LerpedFloat.angular(); + upperArmAngle.startWithValue(previousTarget.upperArmAngle); + headAngle = LerpedFloat.angular(); + headAngle.startWithValue(previousTarget.headAngle); + clawAngle = LerpedFloat.angular(); + previousBaseAngle = previousTarget.baseAngle; + updateInteractionPoints = true; + redstoneLocked = false; + tooltipWarmup = 15; + goggles = false; + } + + @Override + public void addBehaviours(List behaviours) { + super.addBehaviours(behaviours); + + selectionMode = new ScrollOptionBehaviour(SelectionMode.class, + Lang.translateDirect("logistics.when_multiple_outputs_available"), this, new SelectionModeValueBox()); + behaviours.add(selectionMode); + + registerAwardables(behaviours, AllAdvancements.ARM_BLAZE_BURNER, AllAdvancements.ARM_MANY_TARGETS, + AllAdvancements.MECHANICAL_ARM, AllAdvancements.MUSICAL_ARM); + } + + @Override + public void tick() { + super.tick(); + initInteractionPoints(); + boolean targetReached = tickMovementProgress(); + + if (tooltipWarmup > 0) + tooltipWarmup--; + if (chasedPointProgress < 1) { + if (phase == Phase.MOVE_TO_INPUT) { + ArmInteractionPoint point = getTargetedInteractionPoint(); + if (point != null) + point.keepAlive(); + } + return; + } + if (level.isClientSide) + return; + + if (phase == Phase.MOVE_TO_INPUT) + collectItem(); + else if (phase == Phase.MOVE_TO_OUTPUT) + depositItem(); + else if (phase == Phase.SEARCH_INPUTS || phase == Phase.DANCING) + searchForItem(); + + if (targetReached) + lazyTick(); + } + + @Override + public void lazyTick() { + super.lazyTick(); + + if (level.isClientSide) + return; + if (chasedPointProgress < .5f) + return; + if (phase == Phase.SEARCH_INPUTS || phase == Phase.DANCING) + checkForMusic(); + if (phase == Phase.SEARCH_OUTPUTS) + searchForDestination(); + } + + private void checkForMusic() { + boolean hasMusic = checkForMusicAmong(inputs) || checkForMusicAmong(outputs); + if (hasMusic != (phase == Phase.DANCING)) { + phase = hasMusic ? Phase.DANCING : Phase.SEARCH_INPUTS; + setChanged(); + sendData(); + } + } + + @Override + protected AABB createRenderBoundingBox() { + return super.createRenderBoundingBox().inflate(3); + } + + private boolean checkForMusicAmong(List list) { + for (ArmInteractionPoint armInteractionPoint : list) { + if (!(armInteractionPoint instanceof AllArmInteractionPointTypes.JukeboxPoint)) + continue; + BlockState state = level.getBlockState(armInteractionPoint.getPos()); + if (state.getOptionalValue(JukeboxBlock.HAS_RECORD) + .orElse(false)) + return true; + } + return false; + } + + private boolean tickMovementProgress() { + boolean targetReachedPreviously = chasedPointProgress >= 1; + chasedPointProgress += Math.min(256, Math.abs(getSpeed())) / 1024f; + if (chasedPointProgress > 1) + chasedPointProgress = 1; + if (!level.isClientSide) + return !targetReachedPreviously && chasedPointProgress >= 1; + + ArmInteractionPoint targetedInteractionPoint = getTargetedInteractionPoint(); + ArmAngleTarget previousTarget = this.previousTarget; + ArmAngleTarget target = targetedInteractionPoint == null ? ArmAngleTarget.NO_TARGET + : targetedInteractionPoint.getTargetAngles(worldPosition, isOnCeiling()); + + baseAngle.setValue(AngleHelper.angleLerp(chasedPointProgress, previousBaseAngle, + target == ArmAngleTarget.NO_TARGET ? previousBaseAngle : target.baseAngle)); + + // Arm's angles first backup to resting position and then continue + if (chasedPointProgress < .5f) + target = ArmAngleTarget.NO_TARGET; + else + previousTarget = ArmAngleTarget.NO_TARGET; + float progress = chasedPointProgress == 1 ? 1 : (chasedPointProgress % .5f) * 2; + + lowerArmAngle.setValue(Mth.lerp(progress, previousTarget.lowerArmAngle, target.lowerArmAngle)); + upperArmAngle.setValue(Mth.lerp(progress, previousTarget.upperArmAngle, target.upperArmAngle)); + headAngle.setValue(AngleHelper.angleLerp(progress, previousTarget.headAngle % 360, target.headAngle % 360)); + + return false; + } + + protected boolean isOnCeiling() { + BlockState state = getBlockState(); + return hasLevel() && state.getOptionalValue(ArmBlock.CEILING) + .orElse(false); + } + + @Override + public void destroy() { + super.destroy(); + if (!heldItem.isEmpty()) + Block.popResource(level, worldPosition, heldItem); + } + + @Nullable + private ArmInteractionPoint getTargetedInteractionPoint() { + if (chasedPointIndex == -1) + return null; + if (phase == Phase.MOVE_TO_INPUT && chasedPointIndex < inputs.size()) + return inputs.get(chasedPointIndex); + if (phase == Phase.MOVE_TO_OUTPUT && chasedPointIndex < outputs.size()) + return outputs.get(chasedPointIndex); + return null; + } + + protected void searchForItem() { + if (redstoneLocked) + return; + + boolean foundInput = false; + // for round robin, we start looking after the last used index, for default we + // start at 0; + int startIndex = selectionMode.get() == SelectionMode.PREFER_FIRST ? 0 : lastInputIndex + 1; + + // if we enforce round robin, only look at the next input in the list, + // otherwise, look at all inputs + int scanRange = selectionMode.get() == SelectionMode.FORCED_ROUND_ROBIN ? lastInputIndex + 2 : inputs.size(); + if (scanRange > inputs.size()) + scanRange = inputs.size(); + + InteractionPoints: for (int i = startIndex; i < scanRange; i++) { + ArmInteractionPoint armInteractionPoint = inputs.get(i); + if (!armInteractionPoint.isValid()) + continue; + for (int j = 0; j < armInteractionPoint.getSlotCount(); j++) { + if (getDistributableAmount(armInteractionPoint, j) == 0) + continue; + + selectIndex(true, i); + foundInput = true; + break InteractionPoints; + } + } + if (!foundInput && selectionMode.get() == SelectionMode.ROUND_ROBIN) { + // if we didn't find an input, but don't want to enforce round robin, reset the + // last index + lastInputIndex = -1; + } + if (lastInputIndex == inputs.size() - 1) { + // if we reached the last input in the list, reset the last index + lastInputIndex = -1; + } + } + + protected void searchForDestination() { + ItemStack held = heldItem.copy(); + + boolean foundOutput = false; + // for round robin, we start looking after the last used index, for default we + // start at 0; + int startIndex = selectionMode.get() == SelectionMode.PREFER_FIRST ? 0 : lastOutputIndex + 1; + + // if we enforce round robin, only look at the next index in the list, + // otherwise, look at all + int scanRange = selectionMode.get() == SelectionMode.FORCED_ROUND_ROBIN ? lastOutputIndex + 2 : outputs.size(); + if (scanRange > outputs.size()) + scanRange = outputs.size(); + + for (int i = startIndex; i < scanRange; i++) { + ArmInteractionPoint armInteractionPoint = outputs.get(i); + if (!armInteractionPoint.isValid()) + continue; + + ItemStack remainder = armInteractionPoint.insert(held, true); + if (remainder.equals(heldItem, false)) + continue; + + selectIndex(false, i); + foundOutput = true; + break; + } + + if (!foundOutput && selectionMode.get() == SelectionMode.ROUND_ROBIN) { + // if we didn't find an input, but don't want to enforce round robin, reset the + // last index + lastOutputIndex = -1; + } + if (lastOutputIndex == outputs.size() - 1) { + // if we reached the last input in the list, reset the last index + lastOutputIndex = -1; + } + } + + // input == true => select input, false => select output + private void selectIndex(boolean input, int index) { + phase = input ? Phase.MOVE_TO_INPUT : Phase.MOVE_TO_OUTPUT; + chasedPointIndex = index; + chasedPointProgress = 0; + if (input) + lastInputIndex = index; + else + lastOutputIndex = index; + sendData(); + setChanged(); + } + + protected int getDistributableAmount(ArmInteractionPoint armInteractionPoint, int i) { + ItemStack stack = armInteractionPoint.extract(i, true); + ItemStack remainder = simulateInsertion(stack); + if (stack.sameItem(remainder)) { + return stack.getCount() - remainder.getCount(); + } else { + return stack.getCount(); + } + } + + private ItemStack simulateInsertion(ItemStack stack) { + for (ArmInteractionPoint armInteractionPoint : outputs) { + if (armInteractionPoint.isValid()) + stack = armInteractionPoint.insert(stack, true); + if (stack.isEmpty()) + break; + } + return stack; + } + + protected void depositItem() { + ArmInteractionPoint armInteractionPoint = getTargetedInteractionPoint(); + if (armInteractionPoint != null && armInteractionPoint.isValid()) { + ItemStack toInsert = heldItem.copy(); + ItemStack remainder = armInteractionPoint.insert(toInsert, false); + heldItem = remainder; + + if (armInteractionPoint instanceof JukeboxPoint && remainder.isEmpty()) + award(AllAdvancements.MUSICAL_ARM); + } + + phase = heldItem.isEmpty() ? Phase.SEARCH_INPUTS : Phase.SEARCH_OUTPUTS; + chasedPointProgress = 0; + chasedPointIndex = -1; + sendData(); + setChanged(); + + if (!level.isClientSide) + award(AllAdvancements.MECHANICAL_ARM); + } + + protected void collectItem() { + ArmInteractionPoint armInteractionPoint = getTargetedInteractionPoint(); + if (armInteractionPoint != null && armInteractionPoint.isValid()) + for (int i = 0; i < armInteractionPoint.getSlotCount(); i++) { + int amountExtracted = getDistributableAmount(armInteractionPoint, i); + if (amountExtracted == 0) + continue; + + ItemStack prevHeld = heldItem; + heldItem = armInteractionPoint.extract(i, amountExtracted, false); + phase = Phase.SEARCH_OUTPUTS; + chasedPointProgress = 0; + chasedPointIndex = -1; + sendData(); + setChanged(); + + if (!prevHeld.sameItem(heldItem)) + level.playSound(null, worldPosition, SoundEvents.ITEM_PICKUP, SoundSource.BLOCKS, .125f, + .5f + Create.RANDOM.nextFloat() * .25f); + return; + } + + phase = Phase.SEARCH_INPUTS; + chasedPointProgress = 0; + chasedPointIndex = -1; + sendData(); + setChanged(); + } + + public void redstoneUpdate() { + if (level.isClientSide) + return; + boolean blockPowered = level.hasNeighborSignal(worldPosition); + if (blockPowered == redstoneLocked) + return; + redstoneLocked = blockPowered; + sendData(); + if (!redstoneLocked) + searchForItem(); + } + + @Override + public void transform(StructureTransform transform) { + if (interactionPointTag == null) + return; + + for (Tag tag : interactionPointTag) { + ArmInteractionPoint.transformPos((CompoundTag) tag, transform); + } + + notifyUpdate(); + } + + // ClientLevel#hasChunk (and consequently #isAreaLoaded) always returns true, + // so manually check the ChunkSource to avoid weird behavior on the client side + protected boolean isAreaActuallyLoaded(BlockPos center, int range) { + if (!level.isAreaLoaded(center, range)) { + return false; + } + if (level.isClientSide) { + int minY = center.getY() - range; + int maxY = center.getY() + range; + if (maxY < level.getMinBuildHeight() || minY >= level.getMaxBuildHeight()) { + return false; + } + + int minX = center.getX() - range; + int minZ = center.getZ() - range; + int maxX = center.getX() + range; + int maxZ = center.getZ() + range; + + int minChunkX = SectionPos.blockToSectionCoord(minX); + int maxChunkX = SectionPos.blockToSectionCoord(maxX); + int minChunkZ = SectionPos.blockToSectionCoord(minZ); + int maxChunkZ = SectionPos.blockToSectionCoord(maxZ); + + ChunkSource chunkSource = level.getChunkSource(); + for (int chunkX = minChunkX; chunkX <= maxChunkX; ++chunkX) { + for (int chunkZ = minChunkZ; chunkZ <= maxChunkZ; ++chunkZ) { + if (!chunkSource.hasChunk(chunkX, chunkZ)) { + return false; + } + } + } + } + return true; + } + + protected void initInteractionPoints() { + if (!updateInteractionPoints || interactionPointTag == null) + return; + if (!isAreaActuallyLoaded(worldPosition, getRange() + 1)) + return; + inputs.clear(); + outputs.clear(); + + boolean hasBlazeBurner = false; + for (Tag tag : interactionPointTag) { + ArmInteractionPoint point = ArmInteractionPoint.deserialize((CompoundTag) tag, level, worldPosition); + if (point == null) + continue; + if (point.getMode() == Mode.DEPOSIT) + outputs.add(point); + else if (point.getMode() == Mode.TAKE) + inputs.add(point); + hasBlazeBurner |= point instanceof AllArmInteractionPointTypes.BlazeBurnerPoint; + } + + if (!level.isClientSide) { + if (outputs.size() >= 10) + award(AllAdvancements.ARM_MANY_TARGETS); + if (hasBlazeBurner) + award(AllAdvancements.ARM_BLAZE_BURNER); + } + + updateInteractionPoints = false; + sendData(); + setChanged(); + } + + public void writeInteractionPoints(CompoundTag compound) { + if (updateInteractionPoints && interactionPointTag != null) { + compound.put("InteractionPoints", interactionPointTag); + } else { + ListTag pointsNBT = new ListTag(); + inputs.stream() + .map(aip -> aip.serialize(worldPosition)) + .forEach(pointsNBT::add); + outputs.stream() + .map(aip -> aip.serialize(worldPosition)) + .forEach(pointsNBT::add); + compound.put("InteractionPoints", pointsNBT); + } + } + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + super.write(compound, clientPacket); + + writeInteractionPoints(compound); + + NBTHelper.writeEnum(compound, "Phase", phase); + compound.putBoolean("Powered", redstoneLocked); + compound.putBoolean("Goggles", goggles); + compound.put("HeldItem", heldItem.serializeNBT()); + compound.putInt("TargetPointIndex", chasedPointIndex); + compound.putFloat("MovementProgress", chasedPointProgress); + } + + @Override + public void writeSafe(CompoundTag compound) { + super.writeSafe(compound); + + writeInteractionPoints(compound); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + int previousIndex = chasedPointIndex; + Phase previousPhase = phase; + ListTag interactionPointTagBefore = interactionPointTag; + + super.read(compound, clientPacket); + heldItem = ItemStack.of(compound.getCompound("HeldItem")); + phase = NBTHelper.readEnum(compound, "Phase", Phase.class); + chasedPointIndex = compound.getInt("TargetPointIndex"); + chasedPointProgress = compound.getFloat("MovementProgress"); + interactionPointTag = compound.getList("InteractionPoints", Tag.TAG_COMPOUND); + redstoneLocked = compound.getBoolean("Powered"); + + boolean hadGoggles = goggles; + goggles = compound.getBoolean("Goggles"); + + if (!clientPacket) + return; + + if (hadGoggles != goggles) + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(this)); + + boolean ceiling = isOnCeiling(); + if (interactionPointTagBefore == null || interactionPointTagBefore.size() != interactionPointTag.size()) + updateInteractionPoints = true; + if (previousIndex != chasedPointIndex || (previousPhase != phase)) { + ArmInteractionPoint previousPoint = null; + if (previousPhase == Phase.MOVE_TO_INPUT && previousIndex < inputs.size()) + previousPoint = inputs.get(previousIndex); + if (previousPhase == Phase.MOVE_TO_OUTPUT && previousIndex < outputs.size()) + previousPoint = outputs.get(previousIndex); + previousTarget = previousPoint == null ? ArmAngleTarget.NO_TARGET + : previousPoint.getTargetAngles(worldPosition, ceiling); + if (previousPoint != null) + previousBaseAngle = previousTarget.baseAngle; + + ArmInteractionPoint targetedPoint = getTargetedInteractionPoint(); + if (targetedPoint != null) + targetedPoint.updateCachedState(); + } + } + + public static int getRange() { + return AllConfigs.server().logistics.mechanicalArmRange.get(); + } + + @Override + public boolean addToTooltip(List tooltip, boolean isPlayerSneaking) { + if (super.addToTooltip(tooltip, isPlayerSneaking)) + return true; + if (isPlayerSneaking) + return false; + if (tooltipWarmup > 0) + return false; + if (!inputs.isEmpty()) + return false; + if (!outputs.isEmpty()) + return false; + + TooltipHelper.addHint(tooltip, "hint.mechanical_arm_no_targets"); + return true; + } + + public void setLevel(Level level) { + super.setLevel(level); + for (ArmInteractionPoint input : inputs) { + input.setLevel(level); + } + for (ArmInteractionPoint output : outputs) { + output.setLevel(level); + } + } + + private class SelectionModeValueBox extends CenteredSideValueBoxTransform { + + public SelectionModeValueBox() { + super((blockState, direction) -> !direction.getAxis() + .isVertical()); + } + + @Override + public Vec3 getLocalOffset(BlockState state) { + int yPos = state.getValue(ArmBlock.CEILING) ? 16 - 3 : 3; + Vec3 location = VecHelper.voxelSpace(8, yPos, 15.5); + location = VecHelper.rotateCentered(location, AngleHelper.horizontalAngle(getSide()), Direction.Axis.Y); + return location; + } + + @Override + public float getScale() { + return super.getScale(); + } + + } + + public enum SelectionMode implements INamedIconOptions { + ROUND_ROBIN(AllIcons.I_ARM_ROUND_ROBIN), + FORCED_ROUND_ROBIN(AllIcons.I_ARM_FORCED_ROUND_ROBIN), + PREFER_FIRST(AllIcons.I_ARM_PREFER_FIRST), + + ; + + private final String translationKey; + private final AllIcons icon; + + SelectionMode(AllIcons icon) { + this.icon = icon; + this.translationKey = "mechanical_arm.selection_mode." + Lang.asId(name()); + } + + @Override + public AllIcons getIcon() { + return icon; + } + + @Override + public String getTranslationKey() { + return translationKey; + } + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmInstance.java b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmInstance.java new file mode 100644 index 000000000..889620fe8 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmInstance.java @@ -0,0 +1,207 @@ +package com.simibubi.create.content.kinetics.mechanicalArm; + +import java.util.ArrayList; + +import com.google.common.collect.Lists; +import com.jozufozu.flywheel.api.InstanceData; +import com.jozufozu.flywheel.api.Instancer; +import com.jozufozu.flywheel.api.Material; +import com.jozufozu.flywheel.api.MaterialManager; +import com.jozufozu.flywheel.api.instance.DynamicInstance; +import com.jozufozu.flywheel.core.materials.model.ModelData; +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.SingleRotatingInstance; +import com.simibubi.create.content.kinetics.base.flwdata.RotatingData; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.Color; +import com.simibubi.create.foundation.utility.Iterate; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.entity.ItemRenderer; +import net.minecraft.util.Mth; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; + +public class ArmInstance extends SingleRotatingInstance implements DynamicInstance { + + final ModelData base; + final ModelData lowerBody; + final ModelData upperBody; + ModelData claw; + + private final ArrayList clawGrips; + + private final ArrayList models; + private final Boolean ceiling; + + private boolean firstRender = true; + + private float baseAngle = Float.NaN; + private float lowerArmAngle = Float.NaN; + private float upperArmAngle = Float.NaN; + private float headAngle = Float.NaN; + + public ArmInstance(MaterialManager materialManager, ArmBlockEntity blockEntity) { + super(materialManager, blockEntity); + + Material mat = getTransformMaterial(); + + base = mat.getModel(AllPartialModels.ARM_BASE, blockState) + .createInstance(); + lowerBody = mat.getModel(AllPartialModels.ARM_LOWER_BODY, blockState) + .createInstance(); + upperBody = mat.getModel(AllPartialModels.ARM_UPPER_BODY, blockState) + .createInstance(); + claw = mat + .getModel(blockEntity.goggles ? AllPartialModels.ARM_CLAW_BASE_GOGGLES : AllPartialModels.ARM_CLAW_BASE, + blockState) + .createInstance(); + + ModelData clawGrip1 = mat.getModel(AllPartialModels.ARM_CLAW_GRIP_UPPER, blockState) + .createInstance(); + ModelData clawGrip2 = mat.getModel(AllPartialModels.ARM_CLAW_GRIP_LOWER, blockState) + .createInstance(); + + clawGrips = Lists.newArrayList(clawGrip1, clawGrip2); + models = Lists.newArrayList(base, lowerBody, upperBody, claw, clawGrip1, clawGrip2); + ceiling = blockState.getValue(ArmBlock.CEILING); + + animateArm(false); + } + + @Override + public void beginFrame() { + if (blockEntity.phase == ArmBlockEntity.Phase.DANCING && blockEntity.getSpeed() != 0) { + animateArm(true); + firstRender = true; + return; + } + + float pt = AnimationTickHolder.getPartialTicks(); + + float baseAngleNow = blockEntity.baseAngle.getValue(pt); + float lowerArmAngleNow = blockEntity.lowerArmAngle.getValue(pt); + float upperArmAngleNow = blockEntity.upperArmAngle.getValue(pt); + float headAngleNow = blockEntity.headAngle.getValue(pt); + + boolean settled = Mth.equal(baseAngle, baseAngleNow) && Mth.equal(lowerArmAngle, lowerArmAngleNow) + && Mth.equal(upperArmAngle, upperArmAngleNow) && Mth.equal(headAngle, headAngleNow); + + this.baseAngle = baseAngleNow; + this.lowerArmAngle = lowerArmAngleNow; + this.upperArmAngle = upperArmAngleNow; + this.headAngle = headAngleNow; + + if (!settled || firstRender) + animateArm(false); + + if (firstRender) + firstRender = false; + } + + private void animateArm(boolean rave) { + float baseAngle; + float lowerArmAngle; + float upperArmAngle; + float headAngle; + int color; + + if (rave) { + float renderTick = + AnimationTickHolder.getRenderTime(blockEntity.getLevel()) + (blockEntity.hashCode() % 64); + baseAngle = (renderTick * 10) % 360; + lowerArmAngle = Mth.lerp((Mth.sin(renderTick / 4) + 1) / 2, -45, 15); + upperArmAngle = Mth.lerp((Mth.sin(renderTick / 8) + 1) / 4, -45, 95); + headAngle = -lowerArmAngle; + color = Color.rainbowColor(AnimationTickHolder.getTicks() * 100) + .getRGB(); + } else { + baseAngle = this.baseAngle; + lowerArmAngle = this.lowerArmAngle - 135; + upperArmAngle = this.upperArmAngle - 90; + headAngle = this.headAngle; + color = 0xFFFFFF; + } + + PoseStack msLocal = new PoseStack(); + TransformStack msr = TransformStack.cast(msLocal); + msr.translate(getInstancePosition()); + msr.centre(); + + if (ceiling) + msr.rotateX(180); + + ArmRenderer.transformBase(msr, baseAngle); + base.setTransform(msLocal); + + ArmRenderer.transformLowerArm(msr, lowerArmAngle); + lowerBody.setTransform(msLocal) + .setColor(color); + + ArmRenderer.transformUpperArm(msr, upperArmAngle); + upperBody.setTransform(msLocal) + .setColor(color); + + ArmRenderer.transformHead(msr, headAngle); + + if (ceiling && blockEntity.goggles) + msr.rotateZ(180); + + claw.setTransform(msLocal); + + if (ceiling && blockEntity.goggles) + msr.rotateZ(180); + + ItemStack item = blockEntity.heldItem; + ItemRenderer itemRenderer = Minecraft.getInstance() + .getItemRenderer(); + boolean hasItem = !item.isEmpty(); + boolean isBlockItem = hasItem && (item.getItem() instanceof BlockItem) + && itemRenderer.getModel(item, Minecraft.getInstance().level, null, 0) + .isGui3d(); + + for (int index : Iterate.zeroAndOne) { + msLocal.pushPose(); + int flip = index * 2 - 1; + ArmRenderer.transformClawHalf(msr, hasItem, isBlockItem, flip); + clawGrips.get(index) + .setTransform(msLocal); + msLocal.popPose(); + } + } + + @Override + public void update() { + super.update(); + models.remove(claw); + claw.delete(); + claw = getTransformMaterial() + .getModel(blockEntity.goggles ? AllPartialModels.ARM_CLAW_BASE_GOGGLES : AllPartialModels.ARM_CLAW_BASE, + blockState) + .createInstance(); + models.add(claw); + updateLight(); + animateArm(false); + } + + @Override + public void updateLight() { + super.updateLight(); + + relight(pos, models.stream()); + } + + @Override + protected Instancer getModel() { + return getRotatingMaterial().getModel(AllPartialModels.ARM_COG, blockEntity.getBlockState()); + } + + @Override + public void remove() { + super.remove(); + models.forEach(InstanceData::delete); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInteractionPoint.java b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmInteractionPoint.java similarity index 94% rename from src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInteractionPoint.java rename to src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmInteractionPoint.java index e4a129ded..562c59606 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInteractionPoint.java +++ b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmInteractionPoint.java @@ -1,8 +1,8 @@ -package com.simibubi.create.content.logistics.block.mechanicalArm; +package com.simibubi.create.content.kinetics.mechanicalArm; import javax.annotation.Nullable; -import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform; +import com.simibubi.create.content.contraptions.StructureTransform; import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.VecHelper; @@ -93,10 +93,10 @@ public class ArmInteractionPoint { @Nullable protected IItemHandler getHandler() { if (!cachedHandler.isPresent()) { - BlockEntity te = level.getBlockEntity(pos); - if (te == null) + BlockEntity be = level.getBlockEntity(pos); + if (be == null) return null; - cachedHandler = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, Direction.UP); + cachedHandler = be.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, Direction.UP); } return cachedHandler.orElse(null); } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInteractionPointHandler.java b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmInteractionPointHandler.java similarity index 92% rename from src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInteractionPointHandler.java rename to src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmInteractionPointHandler.java index 0fa1ed3d1..24cf515be 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInteractionPointHandler.java +++ b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmInteractionPointHandler.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.block.mechanicalArm; +package com.simibubi.create.content.kinetics.mechanicalArm; import java.util.ArrayList; import java.util.Collection; @@ -7,9 +7,9 @@ import java.util.List; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; +import com.simibubi.create.AllPackets; import com.simibubi.create.CreateClient; -import com.simibubi.create.content.logistics.block.mechanicalArm.ArmInteractionPoint.Mode; -import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.content.kinetics.mechanicalArm.ArmInteractionPoint.Mode; import com.simibubi.create.foundation.utility.Lang; import net.minecraft.ChatFormatting; @@ -96,7 +96,7 @@ public class ArmInteractionPointHandler { for (Iterator iterator = currentSelection.iterator(); iterator.hasNext();) { ArmInteractionPoint point = iterator.next(); if (point.getPos() - .closerThan(pos, ArmTileEntity.getRange())) + .closerThan(pos, ArmBlockEntity.getRange())) continue; iterator.remove(); removed++; @@ -124,7 +124,7 @@ public class ArmInteractionPointHandler { .sendStatus(player); } - AllPackets.channel.sendToServer(new ArmPlacementPacket(currentSelection, pos)); + AllPackets.getChannel().sendToServer(new ArmPlacementPacket(currentSelection, pos)); currentSelection.clear(); currentItem = null; } @@ -163,8 +163,8 @@ public class ArmInteractionPointHandler { BlockHitResult result = (BlockHitResult) objectMouseOver; BlockPos pos = result.getBlockPos(); - BlockEntity te = Minecraft.getInstance().level.getBlockEntity(pos); - if (!(te instanceof ArmTileEntity)) { + BlockEntity be = Minecraft.getInstance().level.getBlockEntity(pos); + if (!(be instanceof ArmBlockEntity)) { lastBlockPos = -1; currentSelection.clear(); return; @@ -172,7 +172,7 @@ public class ArmInteractionPointHandler { if (lastBlockPos == -1 || lastBlockPos != pos.asLong()) { currentSelection.clear(); - ArmTileEntity arm = (ArmTileEntity) te; + ArmBlockEntity arm = (ArmBlockEntity) be; arm.inputs.forEach(ArmInteractionPointHandler::put); arm.outputs.forEach(ArmInteractionPointHandler::put); lastBlockPos = pos.asLong(); diff --git a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInteractionPointType.java b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmInteractionPointType.java similarity index 96% rename from src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInteractionPointType.java rename to src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmInteractionPointType.java index 05a7fa3db..6e345f4c4 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInteractionPointType.java +++ b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmInteractionPointType.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.block.mechanicalArm; +package com.simibubi.create.content.kinetics.mechanicalArm; import java.util.ArrayList; import java.util.HashMap; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmItem.java b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmItem.java similarity index 85% rename from src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmItem.java rename to src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmItem.java index 3ca57ea7d..cd50a8b77 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmItem.java +++ b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmItem.java @@ -1,6 +1,6 @@ -package com.simibubi.create.content.logistics.block.mechanicalArm; +package com.simibubi.create.content.kinetics.mechanicalArm; -import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.AllPackets; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerPlayer; @@ -35,8 +35,8 @@ public class ArmItem extends BlockItem { protected boolean updateCustomBlockEntityTag(BlockPos pos, Level world, Player player, ItemStack p_195943_4_, BlockState p_195943_5_) { if (!world.isClientSide && player instanceof ServerPlayer sp) - AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> sp), - new ArmPlacementPacket.ClientBoundRequest(pos)); + AllPackets.getChannel() + .send(PacketDistributor.PLAYER.with(() -> sp), new ArmPlacementPacket.ClientBoundRequest(pos)); return super.updateCustomBlockEntityTag(pos, world, player, p_195943_4_, p_195943_5_); } diff --git a/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmPlacementPacket.java b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmPlacementPacket.java new file mode 100644 index 000000000..d5c053b80 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmPlacementPacket.java @@ -0,0 +1,93 @@ +package com.simibubi.create.content.kinetics.mechanicalArm; + +import java.util.Collection; + +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.network.NetworkEvent.Context; + +public class ArmPlacementPacket extends SimplePacketBase { + + private Collection points; + private ListTag receivedTag; + private BlockPos pos; + + public ArmPlacementPacket(Collection points, BlockPos pos) { + this.points = points; + this.pos = pos; + } + + public ArmPlacementPacket(FriendlyByteBuf buffer) { + CompoundTag nbt = buffer.readNbt(); + receivedTag = nbt.getList("Points", Tag.TAG_COMPOUND); + pos = buffer.readBlockPos(); + } + + @Override + public void write(FriendlyByteBuf buffer) { + CompoundTag nbt = new CompoundTag(); + ListTag pointsNBT = new ListTag(); + points.stream() + .map(aip -> aip.serialize(pos)) + .forEach(pointsNBT::add); + nbt.put("Points", pointsNBT); + buffer.writeNbt(nbt); + buffer.writeBlockPos(pos); + } + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> { + ServerPlayer player = context.getSender(); + if (player == null) + return; + Level world = player.level; + if (world == null || !world.isLoaded(pos)) + return; + BlockEntity blockEntity = world.getBlockEntity(pos); + if (!(blockEntity instanceof ArmBlockEntity)) + return; + + ArmBlockEntity arm = (ArmBlockEntity) blockEntity; + arm.interactionPointTag = receivedTag; + }); + return true; + } + + public static class ClientBoundRequest extends SimplePacketBase { + + BlockPos pos; + + public ClientBoundRequest(BlockPos pos) { + this.pos = pos; + } + + public ClientBoundRequest(FriendlyByteBuf buffer) { + this.pos = buffer.readBlockPos(); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeBlockPos(pos); + } + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, + () -> () -> ArmInteractionPointHandler.flushSettings(pos))); + return true; + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmRenderer.java new file mode 100644 index 000000000..159ac1749 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/mechanicalArm/ArmRenderer.java @@ -0,0 +1,206 @@ +package com.simibubi.create.content.kinetics.mechanicalArm; + +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.content.kinetics.mechanicalArm.ArmBlockEntity.Phase; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.Color; +import com.simibubi.create.foundation.utility.Iterate; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.block.model.ItemTransforms.TransformType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.client.renderer.entity.ItemRenderer; +import net.minecraft.util.Mth; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.state.BlockState; + +public class ArmRenderer extends KineticBlockEntityRenderer { + + public ArmRenderer(BlockEntityRendererProvider.Context context) { + super(context); + } + + @Override + protected void renderSafe(ArmBlockEntity be, float pt, PoseStack ms, MultiBufferSource buffer, int light, + int overlay) { + super.renderSafe(be, pt, ms, buffer, light, overlay); + + ItemStack item = be.heldItem; + boolean hasItem = !item.isEmpty(); + boolean usingFlywheel = Backend.canUseInstancing(be.getLevel()); + + if (usingFlywheel && !hasItem) + return; + + ItemRenderer itemRenderer = Minecraft.getInstance() + .getItemRenderer(); + + boolean isBlockItem = + hasItem && (item.getItem() instanceof BlockItem) && itemRenderer.getModel(item, be.getLevel(), null, 0) + .isGui3d(); + + VertexConsumer builder = buffer.getBuffer(be.goggles ? RenderType.cutout() : RenderType.solid()); + BlockState blockState = be.getBlockState(); + + PoseStack msLocal = new PoseStack(); + TransformStack msr = TransformStack.cast(msLocal); + + float baseAngle; + float lowerArmAngle; + float upperArmAngle; + float headAngle; + int color; + boolean inverted = blockState.getValue(ArmBlock.CEILING); + + boolean rave = be.phase == Phase.DANCING && be.getSpeed() != 0; + if (rave) { + float renderTick = AnimationTickHolder.getRenderTime(be.getLevel()) + (be.hashCode() % 64); + baseAngle = (renderTick * 10) % 360; + lowerArmAngle = Mth.lerp((Mth.sin(renderTick / 4) + 1) / 2, -45, 15); + upperArmAngle = Mth.lerp((Mth.sin(renderTick / 8) + 1) / 4, -45, 95); + headAngle = -lowerArmAngle; + color = Color.rainbowColor(AnimationTickHolder.getTicks() * 100) + .getRGB(); + } else { + baseAngle = be.baseAngle.getValue(pt); + lowerArmAngle = be.lowerArmAngle.getValue(pt) - 135; + upperArmAngle = be.upperArmAngle.getValue(pt) - 90; + headAngle = be.headAngle.getValue(pt); + color = 0xFFFFFF; + } + + msr.centre(); + + if (inverted) + msr.rotateX(180); + + if (usingFlywheel) + doItemTransforms(msr, baseAngle, lowerArmAngle, upperArmAngle, headAngle); + else + renderArm(builder, ms, msLocal, msr, blockState, color, baseAngle, lowerArmAngle, upperArmAngle, headAngle, + be.goggles, inverted && be.goggles, hasItem, isBlockItem, light); + + if (hasItem) { + ms.pushPose(); + float itemScale = isBlockItem ? .5f : .625f; + msr.rotateX(90); + msLocal.translate(0, isBlockItem ? -9 / 16f : -10 / 16f, 0); + msLocal.scale(itemScale, itemScale, itemScale); + + ms.last() + .pose() + .mul(msLocal.last() + .pose()); + + itemRenderer.renderStatic(item, TransformType.FIXED, light, overlay, ms, buffer, 0); + ms.popPose(); + } + + } + + private void renderArm(VertexConsumer builder, PoseStack ms, PoseStack msLocal, TransformStack msr, + BlockState blockState, int color, float baseAngle, float lowerArmAngle, float upperArmAngle, float headAngle, + boolean goggles, boolean inverted, boolean hasItem, boolean isBlockItem, int light) { + SuperByteBuffer base = CachedBufferer.partial(AllPartialModels.ARM_BASE, blockState) + .light(light); + SuperByteBuffer lowerBody = CachedBufferer.partial(AllPartialModels.ARM_LOWER_BODY, blockState) + .light(light); + SuperByteBuffer upperBody = CachedBufferer.partial(AllPartialModels.ARM_UPPER_BODY, blockState) + .light(light); + SuperByteBuffer claw = CachedBufferer + .partial(goggles ? AllPartialModels.ARM_CLAW_BASE_GOGGLES : AllPartialModels.ARM_CLAW_BASE, blockState) + .light(light); + SuperByteBuffer upperClawGrip = CachedBufferer.partial(AllPartialModels.ARM_CLAW_GRIP_UPPER, + blockState) + .light(light); + SuperByteBuffer lowerClawGrip = CachedBufferer.partial(AllPartialModels.ARM_CLAW_GRIP_LOWER, blockState) + .light(light); + + transformBase(msr, baseAngle); + base.transform(msLocal) + .renderInto(ms, builder); + + transformLowerArm(msr, lowerArmAngle); + lowerBody.color(color) + .transform(msLocal) + .renderInto(ms, builder); + + transformUpperArm(msr, upperArmAngle); + upperBody.color(color) + .transform(msLocal) + .renderInto(ms, builder); + + transformHead(msr, headAngle); + + if (inverted) + msr.rotateZ(180); + + claw.transform(msLocal) + .renderInto(ms, builder); + + if (inverted) + msr.rotateZ(180); + + for (int flip : Iterate.positiveAndNegative) { + msLocal.pushPose(); + transformClawHalf(msr, hasItem, isBlockItem, flip); + (flip > 0 ? lowerClawGrip : upperClawGrip).transform(msLocal) + .renderInto(ms, builder); + msLocal.popPose(); + } + } + + private void doItemTransforms(TransformStack msr, float baseAngle, float lowerArmAngle, float upperArmAngle, + float headAngle) { + + transformBase(msr, baseAngle); + transformLowerArm(msr, lowerArmAngle); + transformUpperArm(msr, upperArmAngle); + transformHead(msr, headAngle); + } + + public static void transformClawHalf(TransformStack msr, boolean hasItem, boolean isBlockItem, int flip) { + msr.translate(0, -flip * (hasItem ? isBlockItem ? 3 / 16f : 5 / 64f : 1 / 16f), -6 / 16d); + } + + public static void transformHead(TransformStack msr, float headAngle) { + msr.translate(0, 0, -15 / 16d); + msr.rotateX(headAngle - 45f); + } + + public static void transformUpperArm(TransformStack msr, float upperArmAngle) { + msr.translate(0, 0, -14 / 16d); + msr.rotateX(upperArmAngle - 90); + } + + public static void transformLowerArm(TransformStack msr, float lowerArmAngle) { + msr.translate(0, 2 / 16d, 0); + msr.rotateX(lowerArmAngle + 135); + } + + public static void transformBase(TransformStack msr, float baseAngle) { + msr.translate(0, 4 / 16d, 0); + msr.rotateY(baseAngle); + } + + @Override + public boolean shouldRenderOffScreen(ArmBlockEntity be) { + return true; + } + + @Override + protected SuperByteBuffer getRotatedModel(ArmBlockEntity be, BlockState state) { + return CachedBufferer.partial(AllPartialModels.ARM_COG, state); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/millstone/MillingRecipe.java b/src/main/java/com/simibubi/create/content/kinetics/millstone/MillingRecipe.java new file mode 100644 index 000000000..9c3f836f1 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/millstone/MillingRecipe.java @@ -0,0 +1,31 @@ +package com.simibubi.create.content.kinetics.millstone; + +import javax.annotation.ParametersAreNonnullByDefault; + +import com.simibubi.create.AllRecipeTypes; +import com.simibubi.create.content.kinetics.crusher.AbstractCrushingRecipe; +import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder.ProcessingRecipeParams; + +import net.minecraft.world.level.Level; +import net.minecraftforge.items.wrapper.RecipeWrapper; + +@ParametersAreNonnullByDefault +public class MillingRecipe extends AbstractCrushingRecipe { + + public MillingRecipe(ProcessingRecipeParams params) { + super(AllRecipeTypes.MILLING, params); + } + + @Override + public boolean matches(RecipeWrapper inv, Level worldIn) { + if (inv.isEmpty()) + return false; + return ingredients.get(0) + .test(inv.getItem(0)); + } + + @Override + protected int getMaxOutputCount() { + return 4; + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/millstone/MillstoneBlock.java b/src/main/java/com/simibubi/create/content/kinetics/millstone/MillstoneBlock.java similarity index 83% rename from src/main/java/com/simibubi/create/content/contraptions/components/millstone/MillstoneBlock.java rename to src/main/java/com/simibubi/create/content/kinetics/millstone/MillstoneBlock.java index dbb38aaf4..9d28f3124 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/millstone/MillstoneBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/millstone/MillstoneBlock.java @@ -1,10 +1,10 @@ -package com.simibubi.create.content.contraptions.components.millstone; +package com.simibubi.create.content.kinetics.millstone; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.KineticBlock; -import com.simibubi.create.content.contraptions.relays.elementary.ICogWheel; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.content.kinetics.base.KineticBlock; +import com.simibubi.create.content.kinetics.simpleRelays.ICogWheel; +import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.utility.Iterate; import net.minecraft.core.BlockPos; @@ -31,7 +31,7 @@ import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandlerModifiable; import net.minecraftforge.items.ItemStackHandler; -public class MillstoneBlock extends KineticBlock implements ITE, ICogWheel { +public class MillstoneBlock extends KineticBlock implements IBE, ICogWheel { public MillstoneBlock(Properties properties) { super(properties); @@ -56,7 +56,7 @@ public class MillstoneBlock extends KineticBlock implements ITE { + withBlockEntityDo(worldIn, pos, millstone -> { boolean emptyOutput = true; IItemHandlerModifiable inv = millstone.outputInv; for (int slot = 0; slot < inv.getSlots(); slot++) { @@ -95,10 +95,10 @@ public class MillstoneBlock extends KineticBlock implements ITE getTileEntityClass() { - return MillstoneTileEntity.class; + public Class getBlockEntityClass() { + return MillstoneBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.MILLSTONE.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.MILLSTONE.get(); } @Override diff --git a/src/main/java/com/simibubi/create/content/kinetics/millstone/MillstoneBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/millstone/MillstoneBlockEntity.java new file mode 100644 index 000000000..2b3e5bcaa --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/millstone/MillstoneBlockEntity.java @@ -0,0 +1,238 @@ +package com.simibubi.create.content.kinetics.millstone; + +import java.util.List; +import java.util.Optional; + +import com.simibubi.create.AllRecipeTypes; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.belt.behaviour.DirectBeltInputBehaviour; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.item.ItemHelper; +import com.simibubi.create.foundation.sound.SoundScapes; +import com.simibubi.create.foundation.sound.SoundScapes.AmbienceGroup; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.particles.ItemParticleOption; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.Mth; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemHandlerHelper; +import net.minecraftforge.items.ItemStackHandler; +import net.minecraftforge.items.wrapper.CombinedInvWrapper; +import net.minecraftforge.items.wrapper.RecipeWrapper; + +public class MillstoneBlockEntity extends KineticBlockEntity { + + public ItemStackHandler inputInv; + public ItemStackHandler outputInv; + public LazyOptional capability; + public int timer; + private MillingRecipe lastRecipe; + + public MillstoneBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + inputInv = new ItemStackHandler(1); + outputInv = new ItemStackHandler(9); + capability = LazyOptional.of(MillstoneInventoryHandler::new); + } + + @Override + public void addBehaviours(List behaviours) { + behaviours.add(new DirectBeltInputBehaviour(this)); + super.addBehaviours(behaviours); + registerAwardables(behaviours, AllAdvancements.MILLSTONE); + } + + @Override + @OnlyIn(Dist.CLIENT) + public void tickAudio() { + super.tickAudio(); + + if (getSpeed() == 0) + return; + if (inputInv.getStackInSlot(0) + .isEmpty()) + return; + + float pitch = Mth.clamp((Math.abs(getSpeed()) / 256f) + .45f, .85f, 1f); + SoundScapes.play(AmbienceGroup.MILLING, worldPosition, pitch); + } + + @Override + public void tick() { + super.tick(); + + if (getSpeed() == 0) + return; + for (int i = 0; i < outputInv.getSlots(); i++) + if (outputInv.getStackInSlot(i) + .getCount() == outputInv.getSlotLimit(i)) + return; + + if (timer > 0) { + timer -= getProcessingSpeed(); + + if (level.isClientSide) { + spawnParticles(); + return; + } + if (timer <= 0) + process(); + return; + } + + if (inputInv.getStackInSlot(0) + .isEmpty()) + return; + + RecipeWrapper inventoryIn = new RecipeWrapper(inputInv); + if (lastRecipe == null || !lastRecipe.matches(inventoryIn, level)) { + Optional recipe = AllRecipeTypes.MILLING.find(inventoryIn, level); + if (!recipe.isPresent()) { + timer = 100; + sendData(); + } else { + lastRecipe = recipe.get(); + timer = lastRecipe.getProcessingDuration(); + sendData(); + } + return; + } + + timer = lastRecipe.getProcessingDuration(); + sendData(); + } + + @Override + public void invalidate() { + super.invalidate(); + capability.invalidate(); + } + + @Override + public void destroy() { + super.destroy(); + ItemHelper.dropContents(level, worldPosition, inputInv); + ItemHelper.dropContents(level, worldPosition, outputInv); + } + + private void process() { + RecipeWrapper inventoryIn = new RecipeWrapper(inputInv); + + if (lastRecipe == null || !lastRecipe.matches(inventoryIn, level)) { + Optional recipe = AllRecipeTypes.MILLING.find(inventoryIn, level); + if (!recipe.isPresent()) + return; + lastRecipe = recipe.get(); + } + + ItemStack stackInSlot = inputInv.getStackInSlot(0); + stackInSlot.shrink(1); + inputInv.setStackInSlot(0, stackInSlot); + lastRecipe.rollResults() + .forEach(stack -> ItemHandlerHelper.insertItemStacked(outputInv, stack, false)); + award(AllAdvancements.MILLSTONE); + + sendData(); + setChanged(); + } + + public void spawnParticles() { + ItemStack stackInSlot = inputInv.getStackInSlot(0); + if (stackInSlot.isEmpty()) + return; + + ItemParticleOption data = new ItemParticleOption(ParticleTypes.ITEM, stackInSlot); + float angle = level.random.nextFloat() * 360; + Vec3 offset = new Vec3(0, 0, 0.5f); + offset = VecHelper.rotate(offset, angle, Axis.Y); + Vec3 target = VecHelper.rotate(offset, getSpeed() > 0 ? 25 : -25, Axis.Y); + + Vec3 center = offset.add(VecHelper.getCenterOf(worldPosition)); + target = VecHelper.offsetRandomly(target.subtract(offset), level.random, 1 / 128f); + level.addParticle(data, center.x, center.y, center.z, target.x, target.y, target.z); + } + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + compound.putInt("Timer", timer); + compound.put("InputInventory", inputInv.serializeNBT()); + compound.put("OutputInventory", outputInv.serializeNBT()); + super.write(compound, clientPacket); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + timer = compound.getInt("Timer"); + inputInv.deserializeNBT(compound.getCompound("InputInventory")); + outputInv.deserializeNBT(compound.getCompound("OutputInventory")); + super.read(compound, clientPacket); + } + + public int getProcessingSpeed() { + return Mth.clamp((int) Math.abs(getSpeed() / 16f), 1, 512); + } + + @Override + public LazyOptional getCapability(Capability cap, Direction side) { + if (isItemHandlerCap(cap)) + return capability.cast(); + return super.getCapability(cap, side); + } + + private boolean canProcess(ItemStack stack) { + ItemStackHandler tester = new ItemStackHandler(1); + tester.setStackInSlot(0, stack); + RecipeWrapper inventoryIn = new RecipeWrapper(tester); + + if (lastRecipe != null && lastRecipe.matches(inventoryIn, level)) + return true; + return AllRecipeTypes.MILLING.find(inventoryIn, level) + .isPresent(); + } + + private class MillstoneInventoryHandler extends CombinedInvWrapper { + + public MillstoneInventoryHandler() { + super(inputInv, outputInv); + } + + @Override + public boolean isItemValid(int slot, ItemStack stack) { + if (outputInv == getHandlerFromIndex(getIndexForSlot(slot))) + return false; + return canProcess(stack) && super.isItemValid(slot, stack); + } + + @Override + public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) { + if (outputInv == getHandlerFromIndex(getIndexForSlot(slot))) + return stack; + if (!isItemValid(slot, stack)) + return stack; + return super.insertItem(slot, stack, simulate); + } + + @Override + public ItemStack extractItem(int slot, int amount, boolean simulate) { + if (inputInv == getHandlerFromIndex(getIndexForSlot(slot))) + return ItemStack.EMPTY; + return super.extractItem(slot, amount, simulate); + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/millstone/MillstoneCogInstance.java b/src/main/java/com/simibubi/create/content/kinetics/millstone/MillstoneCogInstance.java new file mode 100644 index 000000000..545ebe8d2 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/millstone/MillstoneCogInstance.java @@ -0,0 +1,19 @@ +package com.simibubi.create.content.kinetics.millstone; + +import com.jozufozu.flywheel.api.Instancer; +import com.jozufozu.flywheel.api.MaterialManager; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.SingleRotatingInstance; +import com.simibubi.create.content.kinetics.base.flwdata.RotatingData; + +public class MillstoneCogInstance extends SingleRotatingInstance { + + public MillstoneCogInstance(MaterialManager materialManager, MillstoneBlockEntity blockEntity) { + super(materialManager, blockEntity); + } + + @Override + protected Instancer getModel() { + return getRotatingMaterial().getModel(AllPartialModels.MILLSTONE_COG, blockEntity.getBlockState()); + } +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/millstone/MillstoneRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/millstone/MillstoneRenderer.java new file mode 100644 index 000000000..5f3f344da --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/millstone/MillstoneRenderer.java @@ -0,0 +1,22 @@ +package com.simibubi.create.content.kinetics.millstone; + +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; + +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.world.level.block.state.BlockState; + +public class MillstoneRenderer extends KineticBlockEntityRenderer { + + public MillstoneRenderer(BlockEntityRendererProvider.Context context) { + super(context); + } + + @Override + protected SuperByteBuffer getRotatedModel(MillstoneBlockEntity be, BlockState state) { + return CachedBufferer.partial(AllPartialModels.MILLSTONE_COG, state); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/mixer/CompactingRecipe.java b/src/main/java/com/simibubi/create/content/kinetics/mixer/CompactingRecipe.java new file mode 100644 index 000000000..b099bab9a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/mixer/CompactingRecipe.java @@ -0,0 +1,13 @@ +package com.simibubi.create.content.kinetics.mixer; + +import com.simibubi.create.AllRecipeTypes; +import com.simibubi.create.content.processing.basin.BasinRecipe; +import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder.ProcessingRecipeParams; + +public class CompactingRecipe extends BasinRecipe { + + public CompactingRecipe(ProcessingRecipeParams params) { + super(AllRecipeTypes.COMPACTING, params); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MechanicalMixerBlock.java b/src/main/java/com/simibubi/create/content/kinetics/mixer/MechanicalMixerBlock.java similarity index 77% rename from src/main/java/com/simibubi/create/content/contraptions/components/mixer/MechanicalMixerBlock.java rename to src/main/java/com/simibubi/create/content/kinetics/mixer/MechanicalMixerBlock.java index f53f53a6f..62d987084 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MechanicalMixerBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/mixer/MechanicalMixerBlock.java @@ -1,11 +1,11 @@ -package com.simibubi.create.content.contraptions.components.mixer; +package com.simibubi.create.content.kinetics.mixer; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.KineticBlock; -import com.simibubi.create.content.contraptions.relays.elementary.ICogWheel; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.content.kinetics.base.KineticBlock; +import com.simibubi.create.content.kinetics.simpleRelays.ICogWheel; +import com.simibubi.create.foundation.block.IBE; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -20,7 +20,7 @@ import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.EntityCollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; -public class MechanicalMixerBlock extends KineticBlock implements ITE, ICogWheel { +public class MechanicalMixerBlock extends KineticBlock implements IBE, ICogWheel { public MechanicalMixerBlock(Properties properties) { super(properties); @@ -66,13 +66,13 @@ public class MechanicalMixerBlock extends KineticBlock implements ITE getTileEntityClass() { - return MechanicalMixerTileEntity.class; + public Class getBlockEntityClass() { + return MechanicalMixerBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.MECHANICAL_MIXER.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.MECHANICAL_MIXER.get(); } @Override diff --git a/src/main/java/com/simibubi/create/content/kinetics/mixer/MechanicalMixerBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/mixer/MechanicalMixerBlockEntity.java new file mode 100644 index 000000000..b5f6454ad --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/mixer/MechanicalMixerBlockEntity.java @@ -0,0 +1,314 @@ +package com.simibubi.create.content.kinetics.mixer; + +import java.util.List; +import java.util.Optional; + +import com.simibubi.create.AllRecipeTypes; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.content.fluids.FluidFX; +import com.simibubi.create.content.fluids.potion.PotionMixingRecipes; +import com.simibubi.create.content.kinetics.press.MechanicalPressBlockEntity; +import com.simibubi.create.content.processing.basin.BasinBlockEntity; +import com.simibubi.create.content.processing.basin.BasinOperatingBlockEntity; +import com.simibubi.create.content.processing.recipe.ProcessingRecipe; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.advancement.CreateAdvancement; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.fluid.SmartFluidTankBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.fluid.SmartFluidTankBehaviour.TankSegment; +import com.simibubi.create.foundation.item.SmartInventory; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.Couple; +import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.particles.ItemParticleOption; +import net.minecraft.core.particles.ParticleOptions; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.util.Mth; +import net.minecraft.world.Container; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.CraftingRecipe; +import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.common.crafting.IShapedRecipe; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; + +public class MechanicalMixerBlockEntity extends BasinOperatingBlockEntity { + + private static final Object shapelessOrMixingRecipesKey = new Object(); + + public int runningTicks; + public int processingTicks; + public boolean running; + + public MechanicalMixerBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + public float getRenderedHeadOffset(float partialTicks) { + int localTick; + float offset = 0; + if (running) { + if (runningTicks < 20) { + localTick = runningTicks; + float num = (localTick + partialTicks) / 20f; + num = ((2 - Mth.cos((float) (num * Math.PI))) / 2); + offset = num - .5f; + } else if (runningTicks <= 20) { + offset = 1; + } else { + localTick = 40 - runningTicks; + float num = (localTick - partialTicks) / 20f; + num = ((2 - Mth.cos((float) (num * Math.PI))) / 2); + offset = num - .5f; + } + } + return offset + 7 / 16f; + } + + public float getRenderedHeadRotationSpeed(float partialTicks) { + float speed = getSpeed(); + if (running) { + if (runningTicks < 15) { + return speed; + } + if (runningTicks <= 20) { + return speed * 2; + } + return speed; + } + return speed / 2; + } + + @Override + public void addBehaviours(List behaviours) { + super.addBehaviours(behaviours); + registerAwardables(behaviours, AllAdvancements.MIXER); + } + + @Override + protected AABB createRenderBoundingBox() { + return new AABB(worldPosition).expandTowards(0, -1.5, 0); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + running = compound.getBoolean("Running"); + runningTicks = compound.getInt("Ticks"); + super.read(compound, clientPacket); + + if (clientPacket && hasLevel()) + getBasin().ifPresent(bte -> bte.setAreFluidsMoving(running && runningTicks <= 20)); + } + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + compound.putBoolean("Running", running); + compound.putInt("Ticks", runningTicks); + super.write(compound, clientPacket); + } + + @Override + public void tick() { + super.tick(); + + if (runningTicks >= 40) { + running = false; + runningTicks = 0; + basinChecker.scheduleUpdate(); + return; + } + + float speed = Math.abs(getSpeed()); + if (running && level != null) { + if (level.isClientSide && runningTicks == 20) + renderParticles(); + + if ((!level.isClientSide || isVirtual()) && runningTicks == 20) { + if (processingTicks < 0) { + float recipeSpeed = 1; + if (currentRecipe instanceof ProcessingRecipe) { + int t = ((ProcessingRecipe) currentRecipe).getProcessingDuration(); + if (t != 0) + recipeSpeed = t / 100f; + } + + processingTicks = Mth.clamp((Mth.log2((int) (512 / speed))) * Mth.ceil(recipeSpeed * 15) + 1, 1, 512); + + Optional basin = getBasin(); + if (basin.isPresent()) { + Couple tanks = basin.get() + .getTanks(); + if (!tanks.getFirst() + .isEmpty() + || !tanks.getSecond() + .isEmpty()) + level.playSound(null, worldPosition, SoundEvents.BUBBLE_COLUMN_WHIRLPOOL_AMBIENT, + SoundSource.BLOCKS, .75f, speed < 65 ? .75f : 1.5f); + } + + } else { + processingTicks--; + if (processingTicks == 0) { + runningTicks++; + processingTicks = -1; + applyBasinRecipe(); + sendData(); + } + } + } + + if (runningTicks != 20) + runningTicks++; + } + } + + public void renderParticles() { + Optional basin = getBasin(); + if (!basin.isPresent() || level == null) + return; + + for (SmartInventory inv : basin.get() + .getInvs()) { + for (int slot = 0; slot < inv.getSlots(); slot++) { + ItemStack stackInSlot = inv.getItem(slot); + if (stackInSlot.isEmpty()) + continue; + ItemParticleOption data = new ItemParticleOption(ParticleTypes.ITEM, stackInSlot); + spillParticle(data); + } + } + + for (SmartFluidTankBehaviour behaviour : basin.get() + .getTanks()) { + if (behaviour == null) + continue; + for (TankSegment tankSegment : behaviour.getTanks()) { + if (tankSegment.isEmpty(0)) + continue; + spillParticle(FluidFX.getFluidParticle(tankSegment.getRenderedFluid())); + } + } + } + + protected void spillParticle(ParticleOptions data) { + float angle = level.random.nextFloat() * 360; + Vec3 offset = new Vec3(0, 0, 0.25f); + offset = VecHelper.rotate(offset, angle, Axis.Y); + Vec3 target = VecHelper.rotate(offset, getSpeed() > 0 ? 25 : -25, Axis.Y) + .add(0, .25f, 0); + Vec3 center = offset.add(VecHelper.getCenterOf(worldPosition)); + target = VecHelper.offsetRandomly(target.subtract(offset), level.random, 1 / 128f); + level.addParticle(data, center.x, center.y - 1.75f, center.z, target.x, target.y, target.z); + } + + @Override + protected List> getMatchingRecipes() { + List> matchingRecipes = super.getMatchingRecipes(); + + if (!AllConfigs.server().recipes.allowBrewingInMixer.get()) + return matchingRecipes; + + Optional basin = getBasin(); + if (!basin.isPresent()) + return matchingRecipes; + + BasinBlockEntity basinBlockEntity = basin.get(); + if (basin.isEmpty()) + return matchingRecipes; + + IItemHandler availableItems = basinBlockEntity + .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) + .orElse(null); + if (availableItems == null) + return matchingRecipes; + + for (int i = 0; i < availableItems.getSlots(); i++) { + ItemStack stack = availableItems.getStackInSlot(i); + if (stack.isEmpty()) + continue; + + List list = PotionMixingRecipes.BY_ITEM.get(stack.getItem()); + if (list == null) + continue; + for (MixingRecipe mixingRecipe : list) + if (matchBasinRecipe(mixingRecipe)) + matchingRecipes.add(mixingRecipe); + } + + return matchingRecipes; + } + + @Override + protected boolean matchStaticFilters(Recipe r) { + return ((r instanceof CraftingRecipe && !(r instanceof IShapedRecipe) + && AllConfigs.server().recipes.allowShapelessInMixer.get() && r.getIngredients() + .size() > 1 + && !MechanicalPressBlockEntity.canCompress(r)) && !AllRecipeTypes.shouldIgnoreInAutomation(r) + || r.getType() == AllRecipeTypes.MIXING.getType()); + } + + @Override + public void startProcessingBasin() { + if (running && runningTicks <= 20) + return; + super.startProcessingBasin(); + running = true; + runningTicks = 0; + } + + @Override + public boolean continueWithPreviousRecipe() { + runningTicks = 20; + return true; + } + + @Override + protected void onBasinRemoved() { + if (!running) + return; + runningTicks = 40; + running = false; + } + + @Override + protected Object getRecipeCacheKey() { + return shapelessOrMixingRecipesKey; + } + + @Override + protected boolean isRunning() { + return running; + } + + @Override + protected Optional getProcessedRecipeTrigger() { + return Optional.of(AllAdvancements.MIXER); + } + + @Override + @OnlyIn(Dist.CLIENT) + public void tickAudio() { + super.tickAudio(); + + // SoundEvents.BLOCK_STONE_BREAK + boolean slow = Math.abs(getSpeed()) < 65; + if (slow && AnimationTickHolder.getTicks() % 2 == 0) + return; + if (runningTicks == 20) + AllSoundEvents.MIXING.playAt(level, worldPosition, .75f, 1, true); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/mixer/MechanicalMixerRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/mixer/MechanicalMixerRenderer.java new file mode 100644 index 000000000..c5ebf0c3d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/mixer/MechanicalMixerRenderer.java @@ -0,0 +1,60 @@ +package com.simibubi.create.content.kinetics.mixer; + +import com.jozufozu.flywheel.backend.Backend; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.AnimationTickHolder; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.state.BlockState; + +public class MechanicalMixerRenderer extends KineticBlockEntityRenderer { + + public MechanicalMixerRenderer(BlockEntityRendererProvider.Context context) { + super(context); + } + + @Override + public boolean shouldRenderOffScreen(MechanicalMixerBlockEntity be) { + return true; + } + + @Override + protected void renderSafe(MechanicalMixerBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + + if (Backend.canUseInstancing(be.getLevel())) return; + + BlockState blockState = be.getBlockState(); + + VertexConsumer vb = buffer.getBuffer(RenderType.solid()); + + SuperByteBuffer superBuffer = CachedBufferer.partial(AllPartialModels.SHAFTLESS_COGWHEEL, blockState); + standardKineticRotationTransform(superBuffer, be, light).renderInto(ms, vb); + + float renderedHeadOffset = be.getRenderedHeadOffset(partialTicks); + float speed = be.getRenderedHeadRotationSpeed(partialTicks); + float time = AnimationTickHolder.getRenderTime(be.getLevel()); + float angle = ((time * speed * 6 / 10f) % 360) / 180 * (float) Math.PI; + + SuperByteBuffer poleRender = CachedBufferer.partial(AllPartialModels.MECHANICAL_MIXER_POLE, blockState); + poleRender.translate(0, -renderedHeadOffset, 0) + .light(light) + .renderInto(ms, vb); + + VertexConsumer vbCutout = buffer.getBuffer(RenderType.cutoutMipped()); + SuperByteBuffer headRender = CachedBufferer.partial(AllPartialModels.MECHANICAL_MIXER_HEAD, blockState); + headRender.rotateCentered(Direction.UP, angle) + .translate(0, -renderedHeadOffset, 0) + .light(light) + .renderInto(ms, vbCutout); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/mixer/MixerInstance.java b/src/main/java/com/simibubi/create/content/kinetics/mixer/MixerInstance.java new file mode 100644 index 000000000..fae937070 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/mixer/MixerInstance.java @@ -0,0 +1,90 @@ +package com.simibubi.create.content.kinetics.mixer; + +import com.jozufozu.flywheel.api.Instancer; +import com.jozufozu.flywheel.api.MaterialManager; +import com.jozufozu.flywheel.api.instance.DynamicInstance; +import com.jozufozu.flywheel.core.materials.oriented.OrientedData; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.flwdata.RotatingData; +import com.simibubi.create.content.kinetics.simpleRelays.encased.EncasedCogInstance; +import com.simibubi.create.foundation.render.AllMaterialSpecs; +import com.simibubi.create.foundation.utility.AnimationTickHolder; + +import net.minecraft.core.Direction; + +public class MixerInstance extends EncasedCogInstance implements DynamicInstance { + + private final RotatingData mixerHead; + private final OrientedData mixerPole; + private final MechanicalMixerBlockEntity mixer; + + public MixerInstance(MaterialManager materialManager, MechanicalMixerBlockEntity blockEntity) { + super(materialManager, blockEntity, false); + this.mixer = blockEntity; + + mixerHead = materialManager.defaultCutout() + .material(AllMaterialSpecs.ROTATING) + .getModel(AllPartialModels.MECHANICAL_MIXER_HEAD, blockState) + .createInstance(); + + mixerHead.setRotationAxis(Direction.Axis.Y); + + mixerPole = getOrientedMaterial() + .getModel(AllPartialModels.MECHANICAL_MIXER_POLE, blockState) + .createInstance(); + + + float renderedHeadOffset = getRenderedHeadOffset(); + + transformPole(renderedHeadOffset); + transformHead(renderedHeadOffset); + } + + @Override + protected Instancer getCogModel() { + return materialManager.defaultSolid() + .material(AllMaterialSpecs.ROTATING) + .getModel(AllPartialModels.SHAFTLESS_COGWHEEL, blockEntity.getBlockState()); + } + + @Override + public void beginFrame() { + + float renderedHeadOffset = getRenderedHeadOffset(); + + transformPole(renderedHeadOffset); + transformHead(renderedHeadOffset); + } + + private void transformHead(float renderedHeadOffset) { + float speed = mixer.getRenderedHeadRotationSpeed(AnimationTickHolder.getPartialTicks()); + + mixerHead.setPosition(getInstancePosition()) + .nudge(0, -renderedHeadOffset, 0) + .setRotationalSpeed(speed * 2); + } + + private void transformPole(float renderedHeadOffset) { + mixerPole.setPosition(getInstancePosition()) + .nudge(0, -renderedHeadOffset, 0); + } + + private float getRenderedHeadOffset() { + return mixer.getRenderedHeadOffset(AnimationTickHolder.getPartialTicks()); + } + + @Override + public void updateLight() { + super.updateLight(); + + relight(pos.below(), mixerHead); + relight(pos, mixerPole); + } + + @Override + public void remove() { + super.remove(); + mixerHead.delete(); + mixerPole.delete(); + } +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/mixer/MixingRecipe.java b/src/main/java/com/simibubi/create/content/kinetics/mixer/MixingRecipe.java new file mode 100644 index 000000000..b7fcdd799 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/mixer/MixingRecipe.java @@ -0,0 +1,13 @@ +package com.simibubi.create.content.kinetics.mixer; + +import com.simibubi.create.AllRecipeTypes; +import com.simibubi.create.content.processing.basin.BasinRecipe; +import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder.ProcessingRecipeParams; + +public class MixingRecipe extends BasinRecipe { + + public MixingRecipe(ProcessingRecipeParams params) { + super(AllRecipeTypes.MIXING, params); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/motor/CreativeMotorBlock.java b/src/main/java/com/simibubi/create/content/kinetics/motor/CreativeMotorBlock.java similarity index 78% rename from src/main/java/com/simibubi/create/content/contraptions/components/motor/CreativeMotorBlock.java rename to src/main/java/com/simibubi/create/content/kinetics/motor/CreativeMotorBlock.java index 8c5a2f971..caa6dcfb5 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/motor/CreativeMotorBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/motor/CreativeMotorBlock.java @@ -1,9 +1,9 @@ -package com.simibubi.create.content.contraptions.components.motor; +package com.simibubi.create.content.kinetics.motor; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.content.kinetics.base.DirectionalKineticBlock; +import com.simibubi.create.foundation.block.IBE; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -17,7 +17,7 @@ import net.minecraft.world.level.pathfinder.PathComputationType; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; -public class CreativeMotorBlock extends DirectionalKineticBlock implements ITE { +public class CreativeMotorBlock extends DirectionalKineticBlock implements IBE { public CreativeMotorBlock(Properties properties) { super(properties); @@ -61,13 +61,13 @@ public class CreativeMotorBlock extends DirectionalKineticBlock implements ITE getTileEntityClass() { - return CreativeMotorTileEntity.class; + public Class getBlockEntityClass() { + return CreativeMotorBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.MOTOR.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.MOTOR.get(); } } diff --git a/src/main/java/com/simibubi/create/content/kinetics/motor/CreativeMotorBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/motor/CreativeMotorBlockEntity.java new file mode 100644 index 000000000..b18cf5257 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/motor/CreativeMotorBlockEntity.java @@ -0,0 +1,96 @@ +package com.simibubi.create.content.kinetics.motor; + +import java.util.List; + +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.kinetics.base.GeneratingKineticBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; +import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollValueBehaviour; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class CreativeMotorBlockEntity extends GeneratingKineticBlockEntity { + + public static final int DEFAULT_SPEED = 16; + public static final int MAX_SPEED = 256; + + protected ScrollValueBehaviour generatedSpeed; + + public CreativeMotorBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + public void addBehaviours(List behaviours) { + super.addBehaviours(behaviours); + int max = MAX_SPEED; + generatedSpeed = new KineticScrollValueBehaviour(Lang.translateDirect("kinetics.creative_motor.rotation_speed"), + this, new MotorValueBox()); + generatedSpeed.between(-max, max); + generatedSpeed.value = DEFAULT_SPEED; + generatedSpeed.withCallback(i -> this.updateGeneratedRotation()); + behaviours.add(generatedSpeed); + } + + @Override + public void initialize() { + super.initialize(); + if (!hasSource() || getGeneratedSpeed() > getTheoreticalSpeed()) + updateGeneratedRotation(); + } + + @Override + public float getGeneratedSpeed() { + if (!AllBlocks.CREATIVE_MOTOR.has(getBlockState())) + return 0; + return convertToDirection(generatedSpeed.getValue(), getBlockState().getValue(CreativeMotorBlock.FACING)); + } + + class MotorValueBox extends ValueBoxTransform.Sided { + + @Override + protected Vec3 getSouthLocation() { + return VecHelper.voxelSpace(8, 8, 12.5); + } + + @Override + public Vec3 getLocalOffset(BlockState state) { + Direction facing = state.getValue(CreativeMotorBlock.FACING); + return super.getLocalOffset(state).add(Vec3.atLowerCornerOf(facing.getNormal()) + .scale(-1 / 16f)); + } + + @Override + public void rotate(BlockState state, PoseStack ms) { + super.rotate(state, ms); + Direction facing = state.getValue(CreativeMotorBlock.FACING); + if (facing.getAxis() == Axis.Y) + return; + if (getSide() != Direction.UP) + return; + TransformStack.cast(ms) + .rotateZ(-AngleHelper.horizontalAngle(facing) + 180); + } + + @Override + protected boolean isSideActive(BlockState state, Direction direction) { + Direction facing = state.getValue(CreativeMotorBlock.FACING); + if (facing.getAxis() != Axis.Y && direction == Direction.DOWN) + return false; + return direction.getAxis() != facing.getAxis(); + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/motor/CreativeMotorGenerator.java b/src/main/java/com/simibubi/create/content/kinetics/motor/CreativeMotorGenerator.java similarity index 94% rename from src/main/java/com/simibubi/create/content/contraptions/components/motor/CreativeMotorGenerator.java rename to src/main/java/com/simibubi/create/content/kinetics/motor/CreativeMotorGenerator.java index f774f4035..d62a2bbbe 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/motor/CreativeMotorGenerator.java +++ b/src/main/java/com/simibubi/create/content/kinetics/motor/CreativeMotorGenerator.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.motor; +package com.simibubi.create.content.kinetics.motor; import com.simibubi.create.foundation.data.AssetLookup; import com.simibubi.create.foundation.data.SpecialBlockStateGen; diff --git a/src/main/java/com/simibubi/create/content/kinetics/motor/CreativeMotorRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/motor/CreativeMotorRenderer.java new file mode 100644 index 000000000..452d088ef --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/motor/CreativeMotorRenderer.java @@ -0,0 +1,22 @@ +package com.simibubi.create.content.kinetics.motor; + +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; + +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.world.level.block.state.BlockState; + +public class CreativeMotorRenderer extends KineticBlockEntityRenderer { + + public CreativeMotorRenderer(BlockEntityRendererProvider.Context context) { + super(context); + } + + @Override + protected SuperByteBuffer getRotatedModel(CreativeMotorBlockEntity be, BlockState state) { + return CachedBufferer.partialFacing(AllPartialModels.SHAFT_HALF, state); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/motor/KineticScrollValueBehaviour.java b/src/main/java/com/simibubi/create/content/kinetics/motor/KineticScrollValueBehaviour.java new file mode 100644 index 000000000..bced99bc8 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/motor/KineticScrollValueBehaviour.java @@ -0,0 +1,60 @@ +package com.simibubi.create.content.kinetics.motor; + +import com.google.common.collect.ImmutableList; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsBoard; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsFormatter; +import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollValueBehaviour; +import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.phys.BlockHitResult; + +public class KineticScrollValueBehaviour extends ScrollValueBehaviour { + + public KineticScrollValueBehaviour(Component label, SmartBlockEntity be, ValueBoxTransform slot) { + super(label, be, slot); + withFormatter(v -> String.valueOf(Math.abs(v))); + } + + @Override + public ValueSettingsBoard createBoard(Player player, BlockHitResult hitResult) { + ImmutableList rows = ImmutableList.of(Components.literal("\u27f3") + .withStyle(ChatFormatting.BOLD), + Components.literal("\u27f2") + .withStyle(ChatFormatting.BOLD)); + ValueSettingsFormatter formatter = new ValueSettingsFormatter(this::formatSettings); + return new ValueSettingsBoard(label, 256, 32, rows, formatter); + } + + @Override + public void setValueSettings(Player player, ValueSettings valueSetting, boolean ctrlHeld) { + int value = Math.max(1, valueSetting.value()); + if (!valueSetting.equals(getValueSettings())) + playFeedbackSound(this); + setValue(valueSetting.row() == 0 ? -value : value); + } + + @Override + public ValueSettings getValueSettings() { + return new ValueSettings(value < 0 ? 0 : 1, Math.abs(value)); + } + + public MutableComponent formatSettings(ValueSettings settings) { + return Lang.number(Math.max(1, Math.abs(settings.value()))) + .add(Lang.text(settings.row() == 0 ? "\u27f3" : "\u27f2") + .style(ChatFormatting.BOLD)) + .component(); + } + + @Override + public String getClipboardKey() { + return "Speed"; + } + +} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/content/kinetics/press/BeltPressingCallbacks.java b/src/main/java/com/simibubi/create/content/kinetics/press/BeltPressingCallbacks.java new file mode 100644 index 000000000..900aab84b --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/press/BeltPressingCallbacks.java @@ -0,0 +1,83 @@ +package com.simibubi.create.content.kinetics.press; + +import static com.simibubi.create.content.kinetics.belt.behaviour.BeltProcessingBehaviour.ProcessingResult.HOLD; +import static com.simibubi.create.content.kinetics.belt.behaviour.BeltProcessingBehaviour.ProcessingResult.PASS; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import com.simibubi.create.Create; +import com.simibubi.create.content.kinetics.belt.BeltHelper; +import com.simibubi.create.content.kinetics.belt.behaviour.BeltProcessingBehaviour.ProcessingResult; +import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour; +import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour.TransportedResult; +import com.simibubi.create.content.kinetics.belt.transport.TransportedItemStack; +import com.simibubi.create.content.kinetics.press.PressingBehaviour.Mode; + +import net.minecraft.world.item.ItemStack; + +public class BeltPressingCallbacks { + + static ProcessingResult onItemReceived(TransportedItemStack transported, + TransportedItemStackHandlerBehaviour handler, PressingBehaviour behaviour) { + if (behaviour.specifics.getKineticSpeed() == 0) + return PASS; + if (behaviour.running) + return HOLD; + if (!behaviour.specifics.tryProcessOnBelt(transported, null, true)) + return PASS; + + behaviour.start(Mode.BELT); + return HOLD; + } + + static ProcessingResult whenItemHeld(TransportedItemStack transported, TransportedItemStackHandlerBehaviour handler, + PressingBehaviour behaviour) { + + if (behaviour.specifics.getKineticSpeed() == 0) + return PASS; + if (!behaviour.running) + return PASS; + if (behaviour.runningTicks != PressingBehaviour.CYCLE / 2) + return HOLD; + + behaviour.particleItems.clear(); + ArrayList results = new ArrayList<>(); + if (!behaviour.specifics.tryProcessOnBelt(transported, results, false)) + return PASS; + + boolean bulk = behaviour.specifics.canProcessInBulk() || transported.stack.getCount() == 1; + + List collect = results.stream() + .map(stack -> { + TransportedItemStack copy = transported.copy(); + boolean centered = BeltHelper.isItemUpright(stack); + copy.stack = stack; + copy.locked = true; + copy.angle = centered ? 180 : Create.RANDOM.nextInt(360); + return copy; + }) + .collect(Collectors.toList()); + + if (bulk) { + if (collect.isEmpty()) + handler.handleProcessingOnItem(transported, TransportedResult.removeItem()); + else + handler.handleProcessingOnItem(transported, TransportedResult.convertTo(collect)); + + } else { + TransportedItemStack left = transported.copy(); + left.stack.shrink(1); + + if (collect.isEmpty()) + handler.handleProcessingOnItem(transported, TransportedResult.convertTo(left)); + else + handler.handleProcessingOnItem(transported, TransportedResult.convertToAndLeaveHeld(collect, left)); + } + + behaviour.blockEntity.sendData(); + return HOLD; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/press/MechanicalPressBlock.java b/src/main/java/com/simibubi/create/content/kinetics/press/MechanicalPressBlock.java similarity index 80% rename from src/main/java/com/simibubi/create/content/contraptions/components/press/MechanicalPressBlock.java rename to src/main/java/com/simibubi/create/content/kinetics/press/MechanicalPressBlock.java index 2c37125c5..a95142162 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/press/MechanicalPressBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/press/MechanicalPressBlock.java @@ -1,10 +1,10 @@ -package com.simibubi.create.content.contraptions.components.press; +package com.simibubi.create.content.kinetics.press; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.HorizontalKineticBlock; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.content.kinetics.base.HorizontalKineticBlock; +import com.simibubi.create.foundation.block.IBE; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -20,7 +20,7 @@ import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.EntityCollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; -public class MechanicalPressBlock extends HorizontalKineticBlock implements ITE { +public class MechanicalPressBlock extends HorizontalKineticBlock implements IBE { public MechanicalPressBlock(Properties properties) { super(properties); @@ -61,13 +61,13 @@ public class MechanicalPressBlock extends HorizontalKineticBlock implements ITE< } @Override - public Class getTileEntityClass() { - return MechanicalPressTileEntity.class; + public Class getBlockEntityClass() { + return MechanicalPressBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.MECHANICAL_PRESS.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.MECHANICAL_PRESS.get(); } @Override diff --git a/src/main/java/com/simibubi/create/content/kinetics/press/MechanicalPressBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/press/MechanicalPressBlockEntity.java new file mode 100644 index 000000000..45fda1df0 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/press/MechanicalPressBlockEntity.java @@ -0,0 +1,253 @@ +package com.simibubi.create.content.kinetics.press; + +import java.util.List; +import java.util.Optional; + +import com.simibubi.create.AllRecipeTypes; +import com.simibubi.create.AllTags; +import com.simibubi.create.content.kinetics.belt.transport.TransportedItemStack; +import com.simibubi.create.content.kinetics.crafter.MechanicalCraftingRecipe; +import com.simibubi.create.content.kinetics.press.PressingBehaviour.Mode; +import com.simibubi.create.content.kinetics.press.PressingBehaviour.PressingBehaviourSpecifics; +import com.simibubi.create.content.processing.basin.BasinBlockEntity; +import com.simibubi.create.content.processing.basin.BasinOperatingBlockEntity; +import com.simibubi.create.content.processing.sequenced.SequencedAssemblyRecipe; +import com.simibubi.create.foundation.advancement.AdvancementBehaviour; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.advancement.CreateAdvancement; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.item.ItemHelper; +import com.simibubi.create.foundation.item.SmartInventory; +import com.simibubi.create.foundation.recipe.RecipeApplier; +import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.NonNullList; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.Container; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.CraftingRecipe; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.items.ItemHandlerHelper; +import net.minecraftforge.items.ItemStackHandler; +import net.minecraftforge.items.wrapper.RecipeWrapper; + +public class MechanicalPressBlockEntity extends BasinOperatingBlockEntity implements PressingBehaviourSpecifics { + + private static final Object compressingRecipesKey = new Object(); + + public PressingBehaviour pressingBehaviour; + private int tracksCreated; + + public MechanicalPressBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + protected AABB createRenderBoundingBox() { + return new AABB(worldPosition).expandTowards(0, -1.5, 0) + .expandTowards(0, 1, 0); + } + + @Override + public void addBehaviours(List behaviours) { + super.addBehaviours(behaviours); + pressingBehaviour = new PressingBehaviour(this); + behaviours.add(pressingBehaviour); + + registerAwardables(behaviours, AllAdvancements.PRESS, AllAdvancements.COMPACTING, + AllAdvancements.TRACK_CRAFTING); + } + + public void onItemPressed(ItemStack result) { + award(AllAdvancements.PRESS); + if (AllTags.AllBlockTags.TRACKS.matches(result)) + tracksCreated += result.getCount(); + if (tracksCreated >= 1000) { + award(AllAdvancements.TRACK_CRAFTING); + tracksCreated = 0; + } + } + + public PressingBehaviour getPressingBehaviour() { + return pressingBehaviour; + } + + @Override + public boolean tryProcessInBasin(boolean simulate) { + applyBasinRecipe(); + + Optional basin = getBasin(); + if (basin.isPresent()) { + SmartInventory inputs = basin.get() + .getInputInventory(); + for (int slot = 0; slot < inputs.getSlots(); slot++) { + ItemStack stackInSlot = inputs.getItem(slot); + if (stackInSlot.isEmpty()) + continue; + pressingBehaviour.particleItems.add(stackInSlot); + } + } + + return true; + } + + @Override + protected void write(CompoundTag compound, boolean clientPacket) { + super.write(compound, clientPacket); + if (getBehaviour(AdvancementBehaviour.TYPE).isOwnerPresent()) + compound.putInt("TracksCreated", tracksCreated); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + super.read(compound, clientPacket); + tracksCreated = compound.getInt("TracksCreated"); + } + + @Override + public boolean tryProcessInWorld(ItemEntity itemEntity, boolean simulate) { + ItemStack item = itemEntity.getItem(); + Optional recipe = getRecipe(item); + if (!recipe.isPresent()) + return false; + if (simulate) + return true; + + ItemStack itemCreated = ItemStack.EMPTY; + pressingBehaviour.particleItems.add(item); + if (canProcessInBulk() || item.getCount() == 1) { + RecipeApplier.applyRecipeOn(itemEntity, recipe.get()); + itemCreated = itemEntity.getItem() + .copy(); + } else { + for (ItemStack result : RecipeApplier.applyRecipeOn(ItemHandlerHelper.copyStackWithSize(item, 1), + recipe.get())) { + if (itemCreated.isEmpty()) + itemCreated = result.copy(); + ItemEntity created = + new ItemEntity(level, itemEntity.getX(), itemEntity.getY(), itemEntity.getZ(), result); + created.setDefaultPickUpDelay(); + created.setDeltaMovement(VecHelper.offsetRandomly(Vec3.ZERO, level.random, .05f)); + level.addFreshEntity(created); + } + item.shrink(1); + } + + if (!itemCreated.isEmpty()) + onItemPressed(itemCreated); + return true; + } + + @Override + public boolean tryProcessOnBelt(TransportedItemStack input, List outputList, boolean simulate) { + Optional recipe = getRecipe(input.stack); + if (!recipe.isPresent()) + return false; + if (simulate) + return true; + pressingBehaviour.particleItems.add(input.stack); + List outputs = RecipeApplier.applyRecipeOn( + canProcessInBulk() ? input.stack : ItemHandlerHelper.copyStackWithSize(input.stack, 1), recipe.get()); + + for (ItemStack created : outputs) { + if (!created.isEmpty()) { + onItemPressed(created); + break; + } + } + + outputList.addAll(outputs); + return true; + } + + @Override + public void onPressingCompleted() { + if (pressingBehaviour.onBasin() && matchBasinRecipe(currentRecipe) + && getBasin().filter(BasinBlockEntity::canContinueProcessing) + .isPresent()) + startProcessingBasin(); + else + basinChecker.scheduleUpdate(); + } + + private static final RecipeWrapper pressingInv = new RecipeWrapper(new ItemStackHandler(1)); + + public Optional getRecipe(ItemStack item) { + Optional assemblyRecipe = + SequencedAssemblyRecipe.getRecipe(level, item, AllRecipeTypes.PRESSING.getType(), PressingRecipe.class); + if (assemblyRecipe.isPresent()) + return assemblyRecipe; + + pressingInv.setItem(0, item); + return AllRecipeTypes.PRESSING.find(pressingInv, level); + } + + public static boolean canCompress(Recipe recipe) { + if (!(recipe instanceof CraftingRecipe) || !AllConfigs.server().recipes.allowShapedSquareInPress.get()) + return false; + NonNullList ingredients = recipe.getIngredients(); + return (ingredients.size() == 4 || ingredients.size() == 9) && ItemHelper.matchAllIngredients(ingredients); + } + + @Override + protected boolean matchStaticFilters(Recipe recipe) { + return (recipe instanceof CraftingRecipe && !(recipe instanceof MechanicalCraftingRecipe) && canCompress(recipe) + && !AllRecipeTypes.shouldIgnoreInAutomation(recipe)) + || recipe.getType() == AllRecipeTypes.COMPACTING.getType(); + } + + @Override + public float getKineticSpeed() { + return getSpeed(); + } + + @Override + public boolean canProcessInBulk() { + return AllConfigs.server().recipes.bulkPressing.get(); + } + + @Override + protected Object getRecipeCacheKey() { + return compressingRecipesKey; + } + + @Override + public int getParticleAmount() { + return 15; + } + + @Override + public void startProcessingBasin() { + if (pressingBehaviour.running && pressingBehaviour.runningTicks <= PressingBehaviour.CYCLE / 2) + return; + super.startProcessingBasin(); + pressingBehaviour.start(Mode.BASIN); + } + + @Override + protected void onBasinRemoved() { + pressingBehaviour.particleItems.clear(); + pressingBehaviour.running = false; + pressingBehaviour.runningTicks = 0; + sendData(); + } + + @Override + protected boolean isRunning() { + return pressingBehaviour.running; + } + + @Override + protected Optional getProcessedRecipeTrigger() { + return Optional.of(AllAdvancements.COMPACTING); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/press/MechanicalPressRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/press/MechanicalPressRenderer.java new file mode 100644 index 000000000..e6f1ef4ab --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/press/MechanicalPressRenderer.java @@ -0,0 +1,53 @@ +package com.simibubi.create.content.kinetics.press; + +import static net.minecraft.world.level.block.state.properties.BlockStateProperties.HORIZONTAL_FACING; + +import com.jozufozu.flywheel.backend.Backend; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.world.level.block.state.BlockState; + +public class MechanicalPressRenderer extends KineticBlockEntityRenderer { + + public MechanicalPressRenderer(BlockEntityRendererProvider.Context context) { + super(context); + } + + @Override + public boolean shouldRenderOffScreen(MechanicalPressBlockEntity be) { + return true; + } + + @Override + protected void renderSafe(MechanicalPressBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + super.renderSafe(be, partialTicks, ms, buffer, light, overlay); + + if (Backend.canUseInstancing(be.getLevel())) + return; + + BlockState blockState = be.getBlockState(); + PressingBehaviour pressingBehaviour = be.getPressingBehaviour(); + float renderedHeadOffset = + pressingBehaviour.getRenderedHeadOffset(partialTicks) * pressingBehaviour.mode.headOffset; + + SuperByteBuffer headRender = CachedBufferer.partialFacing(AllPartialModels.MECHANICAL_PRESS_HEAD, blockState, + blockState.getValue(HORIZONTAL_FACING)); + headRender.translate(0, -renderedHeadOffset, 0) + .light(light) + .renderInto(ms, buffer.getBuffer(RenderType.solid())); + } + + @Override + protected BlockState getRenderedBlockState(MechanicalPressBlockEntity be) { + return shaft(getRotationAxisOf(be)); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/press/PressInstance.java b/src/main/java/com/simibubi/create/content/kinetics/press/PressInstance.java new file mode 100644 index 000000000..7e2ed8090 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/press/PressInstance.java @@ -0,0 +1,65 @@ +package com.simibubi.create.content.kinetics.press; + +import org.joml.Quaternionf; + +import com.jozufozu.flywheel.api.MaterialManager; +import com.jozufozu.flywheel.api.instance.DynamicInstance; +import com.jozufozu.flywheel.core.Materials; +import com.jozufozu.flywheel.core.materials.oriented.OrientedData; +import com.mojang.math.Axis; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.ShaftInstance; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.AnimationTickHolder; + +public class PressInstance extends ShaftInstance implements DynamicInstance { + + private final OrientedData pressHead; + + public PressInstance(MaterialManager materialManager, MechanicalPressBlockEntity blockEntity) { + super(materialManager, blockEntity); + + pressHead = materialManager.defaultSolid() + .material(Materials.ORIENTED) + .getModel(AllPartialModels.MECHANICAL_PRESS_HEAD, blockState) + .createInstance(); + + Quaternionf q = Axis.YP + .rotationDegrees(AngleHelper.horizontalAngle(blockState.getValue(MechanicalPressBlock.HORIZONTAL_FACING))); + + pressHead.setRotation(q); + + transformModels(); + } + + @Override + public void beginFrame() { + transformModels(); + } + + private void transformModels() { + float renderedHeadOffset = getRenderedHeadOffset(blockEntity); + + pressHead.setPosition(getInstancePosition()) + .nudge(0, -renderedHeadOffset, 0); + } + + private float getRenderedHeadOffset(MechanicalPressBlockEntity press) { + PressingBehaviour pressingBehaviour = press.getPressingBehaviour(); + return pressingBehaviour.getRenderedHeadOffset(AnimationTickHolder.getPartialTicks()) + * pressingBehaviour.mode.headOffset; + } + + @Override + public void updateLight() { + super.updateLight(); + + relight(pos, pressHead); + } + + @Override + public void remove() { + super.remove(); + pressHead.delete(); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/press/PressingBehaviour.java b/src/main/java/com/simibubi/create/content/kinetics/press/PressingBehaviour.java similarity index 90% rename from src/main/java/com/simibubi/create/content/contraptions/components/press/PressingBehaviour.java rename to src/main/java/com/simibubi/create/content/kinetics/press/PressingBehaviour.java index 5297f1bb1..38200d4d4 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/press/PressingBehaviour.java +++ b/src/main/java/com/simibubi/create/content/kinetics/press/PressingBehaviour.java @@ -1,15 +1,15 @@ -package com.simibubi.create.content.contraptions.components.press; +package com.simibubi.create.content.kinetics.press; import java.util.ArrayList; import java.util.List; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProcessingBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour; +import com.simibubi.create.content.kinetics.belt.behaviour.BeltProcessingBehaviour; +import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour; +import com.simibubi.create.content.kinetics.belt.transport.TransportedItemStack; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.VecHelper; @@ -59,9 +59,9 @@ public class PressingBehaviour extends BeltProcessingBehaviour { public float getKineticSpeed(); } - public PressingBehaviour(T te) { - super(te); - this.specifics = te; + public PressingBehaviour(T be) { + super(be); + this.specifics = be; mode = Mode.WORLD; entityScanCooldown = ENTITY_SCAN; whenItemEnters((s, i) -> BeltPressingCallbacks.onItemReceived(s, i, this)); @@ -113,7 +113,7 @@ public class PressingBehaviour extends BeltProcessingBehaviour { prevRunningTicks = 0; runningTicks = 0; particleItems.clear(); - tileEntity.sendData(); + blockEntity.sendData(); } public boolean inWorld() { @@ -141,7 +141,7 @@ public class PressingBehaviour extends BeltProcessingBehaviour { if (entityScanCooldown <= 0) { entityScanCooldown = ENTITY_SCAN; - if (TileEntityBehaviour.get(level, worldPosition.below(2), + if (BlockEntityBehaviour.get(level, worldPosition.below(2), TransportedItemStackHandlerBehaviour.TYPE) != null) return; if (AllBlocks.BASIN.has(level.getBlockState(worldPosition.below(2)))) @@ -181,7 +181,7 @@ public class PressingBehaviour extends BeltProcessingBehaviour { .75f + (Math.abs(specifics.getKineticSpeed()) / 1024f)); if (!level.isClientSide) - tileEntity.sendData(); + blockEntity.sendData(); } if (!level.isClientSide && runningTicks > CYCLE) { @@ -189,7 +189,7 @@ public class PressingBehaviour extends BeltProcessingBehaviour { running = false; particleItems.clear(); specifics.onPressingCompleted(); - tileEntity.sendData(); + blockEntity.sendData(); return; } @@ -198,7 +198,7 @@ public class PressingBehaviour extends BeltProcessingBehaviour { if (prevRunningTicks < CYCLE / 2 && runningTicks >= CYCLE / 2) { runningTicks = CYCLE / 2; // Pause the ticks until a packet is received - if (level.isClientSide && !tileEntity.isVirtual()) + if (level.isClientSide && !blockEntity.isVirtual()) runningTicks = -(CYCLE / 2); } } @@ -209,7 +209,7 @@ public class PressingBehaviour extends BeltProcessingBehaviour { return; particleItems.clear(); if (specifics.tryProcessInBasin(false)) - tileEntity.sendData(); + blockEntity.sendData(); } protected void applyInWorld() { @@ -231,7 +231,7 @@ public class PressingBehaviour extends BeltProcessingBehaviour { entityScanCooldown = 0; if (specifics.tryProcessInWorld(itemEntity, false)) - tileEntity.sendData(); + blockEntity.sendData(); if (!bulk) break; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/press/PressingRecipe.java b/src/main/java/com/simibubi/create/content/kinetics/press/PressingRecipe.java similarity index 83% rename from src/main/java/com/simibubi/create/content/contraptions/components/press/PressingRecipe.java rename to src/main/java/com/simibubi/create/content/kinetics/press/PressingRecipe.java index 4ecff8535..5c6f8c521 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/press/PressingRecipe.java +++ b/src/main/java/com/simibubi/create/content/kinetics/press/PressingRecipe.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.press; +package com.simibubi.create.content.kinetics.press; import java.util.List; import java.util.Set; @@ -9,9 +9,9 @@ import javax.annotation.ParametersAreNonnullByDefault; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllRecipeTypes; import com.simibubi.create.compat.jei.category.sequencedAssembly.SequencedAssemblySubCategory; -import com.simibubi.create.content.contraptions.itemAssembly.IAssemblyRecipe; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipe; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder.ProcessingRecipeParams; +import com.simibubi.create.content.processing.recipe.ProcessingRecipe; +import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder.ProcessingRecipeParams; +import com.simibubi.create.content.processing.sequenced.IAssemblyRecipe; import com.simibubi.create.foundation.utility.Lang; import net.minecraft.network.chat.Component; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/saw/CuttingRecipe.java b/src/main/java/com/simibubi/create/content/kinetics/saw/CuttingRecipe.java similarity index 84% rename from src/main/java/com/simibubi/create/content/contraptions/components/saw/CuttingRecipe.java rename to src/main/java/com/simibubi/create/content/kinetics/saw/CuttingRecipe.java index 2c6c50c6d..11280224f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/saw/CuttingRecipe.java +++ b/src/main/java/com/simibubi/create/content/kinetics/saw/CuttingRecipe.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.saw; +package com.simibubi.create.content.kinetics.saw; import java.util.List; import java.util.Set; @@ -9,9 +9,9 @@ import javax.annotation.ParametersAreNonnullByDefault; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllRecipeTypes; import com.simibubi.create.compat.jei.category.sequencedAssembly.SequencedAssemblySubCategory; -import com.simibubi.create.content.contraptions.itemAssembly.IAssemblyRecipe; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipe; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder.ProcessingRecipeParams; +import com.simibubi.create.content.processing.recipe.ProcessingRecipe; +import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder.ProcessingRecipeParams; +import com.simibubi.create.content.processing.sequenced.IAssemblyRecipe; import com.simibubi.create.foundation.utility.Lang; import net.minecraft.network.chat.Component; diff --git a/src/main/java/com/simibubi/create/content/kinetics/saw/SawBlock.java b/src/main/java/com/simibubi/create/content/kinetics/saw/SawBlock.java new file mode 100644 index 000000000..d7bcabb60 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/saw/SawBlock.java @@ -0,0 +1,259 @@ +package com.simibubi.create.content.kinetics.saw; + +import java.util.List; +import java.util.function.Predicate; + +import javax.annotation.ParametersAreNonnullByDefault; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllShapes; +import com.simibubi.create.content.kinetics.base.DirectionalAxisKineticBlock; +import com.simibubi.create.content.kinetics.drill.DrillBlock; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.placement.IPlacementHelper; +import com.simibubi.create.foundation.placement.PlacementHelpers; +import com.simibubi.create.foundation.placement.PlacementOffset; + +import net.minecraft.MethodsReturnNonnullByDefault; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Mirror; +import net.minecraft.world.level.block.Rotation; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition.Builder; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.level.material.PushReaction; +import net.minecraft.world.level.pathfinder.PathComputationType; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +public class SawBlock extends DirectionalAxisKineticBlock implements IBE { + public static DamageSource damageSourceSaw = new DamageSource("create.mechanical_saw").bypassArmor(); + + public static final BooleanProperty FLIPPED = BooleanProperty.create("flipped"); + + private static final int placementHelperId = PlacementHelpers.register(new PlacementHelper()); + + public SawBlock(Properties properties) { + super(properties); + } + + @Override + protected void createBlockStateDefinition(Builder builder) { + super.createBlockStateDefinition(builder.add(FLIPPED)); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext context) { + BlockState stateForPlacement = super.getStateForPlacement(context); + Direction facing = stateForPlacement.getValue(FACING); + return stateForPlacement.setValue(FLIPPED, facing.getAxis() == Axis.Y && context.getHorizontalDirection() + .getAxisDirection() == AxisDirection.POSITIVE); + } + + @Override + public BlockState getRotatedBlockState(BlockState originalState, Direction targetedFace) { + BlockState newState = super.getRotatedBlockState(originalState, targetedFace); + if (newState.getValue(FACING) + .getAxis() != Axis.Y) + return newState; + if (targetedFace.getAxis() != Axis.Y) + return newState; + if (!originalState.getValue(AXIS_ALONG_FIRST_COORDINATE)) + newState = newState.cycle(FLIPPED); + return newState; + } + + @Override + public BlockState rotate(BlockState state, Rotation rot) { + BlockState newState = super.rotate(state, rot); + if (state.getValue(FACING) + .getAxis() != Axis.Y) + return newState; + + if (rot.ordinal() % 2 == 1 && (rot == Rotation.CLOCKWISE_90) != state.getValue(AXIS_ALONG_FIRST_COORDINATE)) + newState = newState.cycle(FLIPPED); + if (rot == Rotation.CLOCKWISE_180) + newState = newState.cycle(FLIPPED); + + return newState; + } + + @Override + public BlockState mirror(BlockState state, Mirror mirrorIn) { + BlockState newState = super.mirror(state, mirrorIn); + if (state.getValue(FACING) + .getAxis() != Axis.Y) + return newState; + + boolean alongX = state.getValue(AXIS_ALONG_FIRST_COORDINATE); + if (alongX && mirrorIn == Mirror.FRONT_BACK) + newState = newState.cycle(FLIPPED); + if (!alongX && mirrorIn == Mirror.LEFT_RIGHT) + newState = newState.cycle(FLIPPED); + + return newState; + } + + @Override + public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) { + return AllShapes.CASING_12PX.get(state.getValue(FACING)); + } + + @Override + public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, + BlockHitResult hit) { + ItemStack heldItem = player.getItemInHand(handIn); + IPlacementHelper placementHelper = PlacementHelpers.get(placementHelperId); + if (!player.isShiftKeyDown() && player.mayBuild()) { + if (placementHelper.matchesItem(heldItem) && placementHelper.getOffset(player, worldIn, state, pos, hit) + .placeInWorld(worldIn, (BlockItem) heldItem.getItem(), player, handIn, hit) + .consumesAction()) + return InteractionResult.SUCCESS; + } + + if (player.isSpectator() || !player.getItemInHand(handIn) + .isEmpty()) + return InteractionResult.PASS; + if (state.getOptionalValue(FACING) + .orElse(Direction.WEST) != Direction.UP) + return InteractionResult.PASS; + + return onBlockEntityUse(worldIn, pos, be -> { + for (int i = 0; i < be.inventory.getSlots(); i++) { + ItemStack heldItemStack = be.inventory.getStackInSlot(i); + if (!worldIn.isClientSide && !heldItemStack.isEmpty()) + player.getInventory() + .placeItemBackInInventory(heldItemStack); + } + be.inventory.clear(); + be.notifyUpdate(); + return InteractionResult.SUCCESS; + }); + } + + @Override + public void entityInside(BlockState state, Level worldIn, BlockPos pos, Entity entityIn) { + if (entityIn instanceof ItemEntity) + return; + if (!new AABB(pos).deflate(.1f) + .intersects(entityIn.getBoundingBox())) + return; + withBlockEntityDo(worldIn, pos, be -> { + if (be.getSpeed() == 0) + return; + entityIn.hurt(damageSourceSaw, (float) DrillBlock.getDamage(be.getSpeed())); + }); + } + + @Override + public void updateEntityAfterFallOn(BlockGetter worldIn, Entity entityIn) { + super.updateEntityAfterFallOn(worldIn, entityIn); + if (!(entityIn instanceof ItemEntity)) + return; + if (entityIn.level.isClientSide) + return; + + BlockPos pos = entityIn.blockPosition(); + withBlockEntityDo(entityIn.level, pos, be -> { + if (be.getSpeed() == 0) + return; + be.insertItem((ItemEntity) entityIn); + }); + } + + @Override + public PushReaction getPistonPushReaction(BlockState state) { + return PushReaction.NORMAL; + } + + public static boolean isHorizontal(BlockState state) { + return state.getValue(FACING) + .getAxis() + .isHorizontal(); + } + + @Override + public Axis getRotationAxis(BlockState state) { + return isHorizontal(state) ? state.getValue(FACING) + .getAxis() : super.getRotationAxis(state); + } + + @Override + public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) { + return isHorizontal(state) ? face == state.getValue(FACING) + .getOpposite() : super.hasShaftTowards(world, pos, state, face); + } + + @Override + public Class getBlockEntityClass() { + return SawBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.SAW.get(); + } + + @Override + public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) { + return false; + } + + @MethodsReturnNonnullByDefault + private static class PlacementHelper implements IPlacementHelper { + + @Override + public Predicate getItemPredicate() { + return AllBlocks.MECHANICAL_SAW::isIn; + } + + @Override + public Predicate getStatePredicate() { + return state -> AllBlocks.MECHANICAL_SAW.has(state); + } + + @Override + public PlacementOffset getOffset(Player player, Level world, BlockState state, BlockPos pos, + BlockHitResult ray) { + List directions = IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getLocation(), + state.getValue(FACING) + .getAxis(), + dir -> world.getBlockState(pos.relative(dir)) + .getMaterial() + .isReplaceable()); + + if (directions.isEmpty()) + return PlacementOffset.fail(); + else { + return PlacementOffset.success(pos.relative(directions.get(0)), + s -> s.setValue(FACING, state.getValue(FACING)) + .setValue(AXIS_ALONG_FIRST_COORDINATE, state.getValue(AXIS_ALONG_FIRST_COORDINATE)) + .setValue(FLIPPED, state.getValue(FLIPPED))); + } + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/saw/SawBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/saw/SawBlockEntity.java new file mode 100644 index 000000000..6f1d5fbf4 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/saw/SawBlockEntity.java @@ -0,0 +1,510 @@ +package com.simibubi.create.content.kinetics.saw; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; +import java.util.function.Predicate; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +import javax.annotation.ParametersAreNonnullByDefault; + +import com.google.common.base.Suppliers; +import com.google.common.collect.ImmutableList; +import com.simibubi.create.AllRecipeTypes; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.content.kinetics.base.BlockBreakingKineticBlockEntity; +import com.simibubi.create.content.kinetics.belt.behaviour.DirectBeltInputBehaviour; +import com.simibubi.create.content.processing.recipe.ProcessingInventory; +import com.simibubi.create.content.processing.sequenced.SequencedAssemblyRecipe; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.item.ItemHelper; +import com.simibubi.create.foundation.recipe.RecipeConditions; +import com.simibubi.create.foundation.recipe.RecipeFinder; +import com.simibubi.create.foundation.utility.AbstractBlockBreakQueue; +import com.simibubi.create.foundation.utility.TreeCutter; +import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.minecraft.MethodsReturnNonnullByDefault; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.particles.BlockParticleOption; +import net.minecraft.core.particles.ItemParticleOption; +import net.minecraft.core.particles.ParticleOptions; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.BlockTags; +import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.item.crafting.RecipeType; +import net.minecraft.world.item.crafting.StonecutterRecipe; +import net.minecraft.world.level.block.BambooStalkBlock; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.CactusBlock; +import net.minecraft.world.level.block.ChorusPlantBlock; +import net.minecraft.world.level.block.KelpBlock; +import net.minecraft.world.level.block.KelpPlantBlock; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.StemGrownBlock; +import net.minecraft.world.level.block.SugarCaneBlock; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.registries.ForgeRegistries; + +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +public class SawBlockEntity extends BlockBreakingKineticBlockEntity { + + private static final Object cuttingRecipesKey = new Object(); + public static final Supplier> woodcuttingRecipeType = + Suppliers.memoize(() -> ForgeRegistries.RECIPE_TYPES.getValue(new ResourceLocation("druidcraft", "woodcutting"))); + + public ProcessingInventory inventory; + private int recipeIndex; + private final LazyOptional invProvider; + private FilteringBehaviour filtering; + + private ItemStack playEvent; + + public SawBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + inventory = new ProcessingInventory(this::start).withSlotLimit(!AllConfigs.server().recipes.bulkCutting.get()); + inventory.remainingTime = -1; + recipeIndex = 0; + invProvider = LazyOptional.of(() -> inventory); + playEvent = ItemStack.EMPTY; + } + + @Override + public void addBehaviours(List behaviours) { + super.addBehaviours(behaviours); + filtering = new FilteringBehaviour(this, new SawFilterSlot()).forRecipes(); + behaviours.add(filtering); + behaviours.add(new DirectBeltInputBehaviour(this).allowingBeltFunnelsWhen(this::canProcess)); + registerAwardables(behaviours, AllAdvancements.SAW_PROCESSING); + } + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + compound.put("Inventory", inventory.serializeNBT()); + compound.putInt("RecipeIndex", recipeIndex); + super.write(compound, clientPacket); + + if (!clientPacket || playEvent.isEmpty()) + return; + compound.put("PlayEvent", playEvent.serializeNBT()); + playEvent = ItemStack.EMPTY; + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + super.read(compound, clientPacket); + inventory.deserializeNBT(compound.getCompound("Inventory")); + recipeIndex = compound.getInt("RecipeIndex"); + if (compound.contains("PlayEvent")) + playEvent = ItemStack.of(compound.getCompound("PlayEvent")); + } + + @Override + protected AABB createRenderBoundingBox() { + return new AABB(worldPosition).inflate(.125f); + } + + @Override + @OnlyIn(Dist.CLIENT) + public void tickAudio() { + super.tickAudio(); + if (getSpeed() == 0) + return; + + if (!playEvent.isEmpty()) { + boolean isWood = false; + Item item = playEvent.getItem(); + if (item instanceof BlockItem) { + Block block = ((BlockItem) item).getBlock(); + isWood = block.getSoundType(block.defaultBlockState(), level, worldPosition, null) == SoundType.WOOD; + } + spawnEventParticles(playEvent); + playEvent = ItemStack.EMPTY; + if (!isWood) + AllSoundEvents.SAW_ACTIVATE_STONE.playAt(level, worldPosition, 3, 1, true); + else + AllSoundEvents.SAW_ACTIVATE_WOOD.playAt(level, worldPosition, 3, 1, true); + return; + } + } + + @Override + public void tick() { + if (shouldRun() && ticksUntilNextProgress < 0) + destroyNextTick(); + super.tick(); + + if (!canProcess()) + return; + if (getSpeed() == 0) + return; + if (inventory.remainingTime == -1) { + if (!inventory.isEmpty() && !inventory.appliedRecipe) + start(inventory.getStackInSlot(0)); + return; + } + + float processingSpeed = Mth.clamp(Math.abs(getSpeed()) / 24, 1, 128); + inventory.remainingTime -= processingSpeed; + + if (inventory.remainingTime > 0) + spawnParticles(inventory.getStackInSlot(0)); + + if (inventory.remainingTime < 5 && !inventory.appliedRecipe) { + if (level.isClientSide && !isVirtual()) + return; + playEvent = inventory.getStackInSlot(0); + applyRecipe(); + inventory.appliedRecipe = true; + inventory.recipeDuration = 20; + inventory.remainingTime = 20; + sendData(); + return; + } + + Vec3 itemMovement = getItemMovementVec(); + Direction itemMovementFacing = Direction.getNearest(itemMovement.x, itemMovement.y, itemMovement.z); + if (inventory.remainingTime > 0) + return; + inventory.remainingTime = 0; + + for (int slot = 0; slot < inventory.getSlots(); slot++) { + ItemStack stack = inventory.getStackInSlot(slot); + if (stack.isEmpty()) + continue; + ItemStack tryExportingToBeltFunnel = getBehaviour(DirectBeltInputBehaviour.TYPE) + .tryExportingToBeltFunnel(stack, itemMovementFacing.getOpposite(), false); + if (tryExportingToBeltFunnel != null) { + if (tryExportingToBeltFunnel.getCount() != stack.getCount()) { + inventory.setStackInSlot(slot, tryExportingToBeltFunnel); + notifyUpdate(); + return; + } + if (!tryExportingToBeltFunnel.isEmpty()) + return; + } + } + + BlockPos nextPos = worldPosition.offset(itemMovement.x, itemMovement.y, itemMovement.z); + DirectBeltInputBehaviour behaviour = BlockEntityBehaviour.get(level, nextPos, DirectBeltInputBehaviour.TYPE); + if (behaviour != null) { + boolean changed = false; + if (!behaviour.canInsertFromSide(itemMovementFacing)) + return; + if (level.isClientSide && !isVirtual()) + return; + for (int slot = 0; slot < inventory.getSlots(); slot++) { + ItemStack stack = inventory.getStackInSlot(slot); + if (stack.isEmpty()) + continue; + ItemStack remainder = behaviour.handleInsertion(stack, itemMovementFacing, false); + if (remainder.equals(stack, false)) + continue; + inventory.setStackInSlot(slot, remainder); + changed = true; + } + if (changed) { + setChanged(); + sendData(); + } + return; + } + + // Eject Items + Vec3 outPos = VecHelper.getCenterOf(worldPosition) + .add(itemMovement.scale(.5f) + .add(0, .5, 0)); + Vec3 outMotion = itemMovement.scale(.0625) + .add(0, .125, 0); + for (int slot = 0; slot < inventory.getSlots(); slot++) { + ItemStack stack = inventory.getStackInSlot(slot); + if (stack.isEmpty()) + continue; + ItemEntity entityIn = new ItemEntity(level, outPos.x, outPos.y, outPos.z, stack); + entityIn.setDeltaMovement(outMotion); + level.addFreshEntity(entityIn); + } + inventory.clear(); + level.updateNeighbourForOutputSignal(worldPosition, getBlockState().getBlock()); + inventory.remainingTime = -1; + sendData(); + } + + @Override + public void invalidate() { + super.invalidate(); + invProvider.invalidate(); + } + + @Override + public void destroy() { + super.destroy(); + ItemHelper.dropContents(level, worldPosition, inventory); + } + + @Override + public LazyOptional getCapability(Capability cap, Direction side) { + if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY && side != Direction.DOWN) + return invProvider.cast(); + return super.getCapability(cap, side); + } + + protected void spawnEventParticles(ItemStack stack) { + if (stack == null || stack.isEmpty()) + return; + + ParticleOptions particleData = null; + if (stack.getItem() instanceof BlockItem) + particleData = new BlockParticleOption(ParticleTypes.BLOCK, ((BlockItem) stack.getItem()).getBlock() + .defaultBlockState()); + else + particleData = new ItemParticleOption(ParticleTypes.ITEM, stack); + + RandomSource r = level.random; + Vec3 v = VecHelper.getCenterOf(this.worldPosition) + .add(0, 5 / 16f, 0); + for (int i = 0; i < 10; i++) { + Vec3 m = VecHelper.offsetRandomly(new Vec3(0, 0.25f, 0), r, .125f); + level.addParticle(particleData, v.x, v.y, v.z, m.x, m.y, m.y); + } + } + + protected void spawnParticles(ItemStack stack) { + if (stack == null || stack.isEmpty()) + return; + + ParticleOptions particleData = null; + float speed = 1; + if (stack.getItem() instanceof BlockItem) + particleData = new BlockParticleOption(ParticleTypes.BLOCK, ((BlockItem) stack.getItem()).getBlock() + .defaultBlockState()); + else { + particleData = new ItemParticleOption(ParticleTypes.ITEM, stack); + speed = .125f; + } + + RandomSource r = level.random; + Vec3 vec = getItemMovementVec(); + Vec3 pos = VecHelper.getCenterOf(this.worldPosition); + float offset = inventory.recipeDuration != 0 ? (float) (inventory.remainingTime) / inventory.recipeDuration : 0; + offset /= 2; + if (inventory.appliedRecipe) + offset -= .5f; + level.addParticle(particleData, pos.x() + -vec.x * offset, pos.y() + .45f, pos.z() + -vec.z * offset, + -vec.x * speed, r.nextFloat() * speed, -vec.z * speed); + } + + public Vec3 getItemMovementVec() { + boolean alongX = !getBlockState().getValue(SawBlock.AXIS_ALONG_FIRST_COORDINATE); + int offset = getSpeed() < 0 ? -1 : 1; + return new Vec3(offset * (alongX ? 1 : 0), 0, offset * (alongX ? 0 : -1)); + } + + private void applyRecipe() { + List> recipes = getRecipes(); + if (recipes.isEmpty()) + return; + if (recipeIndex >= recipes.size()) + recipeIndex = 0; + + Recipe recipe = recipes.get(recipeIndex); + + int rolls = inventory.getStackInSlot(0) + .getCount(); + inventory.clear(); + + List list = new ArrayList<>(); + for (int roll = 0; roll < rolls; roll++) { + List results = new LinkedList(); + if (recipe instanceof CuttingRecipe) + results = ((CuttingRecipe) recipe).rollResults(); + else if (recipe instanceof StonecutterRecipe || recipe.getType() == woodcuttingRecipeType.get()) + results.add(recipe.getResultItem() + .copy()); + + for (int i = 0; i < results.size(); i++) { + ItemStack stack = results.get(i); + ItemHelper.addToList(stack, list); + } + } + + for (int slot = 0; slot < list.size() && slot + 1 < inventory.getSlots(); slot++) + inventory.setStackInSlot(slot + 1, list.get(slot)); + + award(AllAdvancements.SAW_PROCESSING); + } + + private List> getRecipes() { + Optional assemblyRecipe = SequencedAssemblyRecipe.getRecipe(level, inventory.getStackInSlot(0), + AllRecipeTypes.CUTTING.getType(), CuttingRecipe.class); + if (assemblyRecipe.isPresent() && filtering.test(assemblyRecipe.get() + .getResultItem())) + return ImmutableList.of(assemblyRecipe.get()); + + Predicate> types = RecipeConditions.isOfType(AllRecipeTypes.CUTTING.getType(), + AllConfigs.server().recipes.allowStonecuttingOnSaw.get() ? RecipeType.STONECUTTING : null, + AllConfigs.server().recipes.allowWoodcuttingOnSaw.get() ? woodcuttingRecipeType.get() : null); + + List> startedSearch = RecipeFinder.get(cuttingRecipesKey, level, types); + return startedSearch.stream() + .filter(RecipeConditions.outputMatchesFilter(filtering)) + .filter(RecipeConditions.firstIngredientMatches(inventory.getStackInSlot(0))) + .filter(r -> !AllRecipeTypes.shouldIgnoreInAutomation(r)) + .collect(Collectors.toList()); + } + + public void insertItem(ItemEntity entity) { + if (!canProcess()) + return; + if (!inventory.isEmpty()) + return; + if (!entity.isAlive()) + return; + if (level.isClientSide) + return; + + inventory.clear(); + ItemStack remainder = inventory.insertItem(0, entity.getItem() + .copy(), false); + if (remainder.isEmpty()) + entity.discard(); + else + entity.setItem(remainder); + } + + public void start(ItemStack inserted) { + if (!canProcess()) + return; + if (inventory.isEmpty()) + return; + if (level.isClientSide && !isVirtual()) + return; + + List> recipes = getRecipes(); + boolean valid = !recipes.isEmpty(); + int time = 50; + + if (recipes.isEmpty()) { + inventory.remainingTime = inventory.recipeDuration = 10; + inventory.appliedRecipe = false; + sendData(); + return; + } + + if (valid) { + recipeIndex++; + if (recipeIndex >= recipes.size()) + recipeIndex = 0; + } + + Recipe recipe = recipes.get(recipeIndex); + if (recipe instanceof CuttingRecipe) { + time = ((CuttingRecipe) recipe).getProcessingDuration(); + } + + inventory.remainingTime = time * Math.max(1, (inserted.getCount() / 5)); + inventory.recipeDuration = inventory.remainingTime; + inventory.appliedRecipe = false; + sendData(); + } + + protected boolean canProcess() { + return getBlockState().getValue(SawBlock.FACING) == Direction.UP; + } + + // Block Breaker + + @Override + protected boolean shouldRun() { + return getBlockState().getValue(SawBlock.FACING) + .getAxis() + .isHorizontal(); + } + + @Override + protected BlockPos getBreakingPos() { + return getBlockPos().relative(getBlockState().getValue(SawBlock.FACING)); + } + + @Override + public void onBlockBroken(BlockState stateToBreak) { + Optional dynamicTree = + TreeCutter.findDynamicTree(stateToBreak.getBlock(), breakingPos); + if (dynamicTree.isPresent()) { + dynamicTree.get() + .destroyBlocks(level, null, this::dropItemFromCutTree); + return; + } + + super.onBlockBroken(stateToBreak); + TreeCutter.findTree(level, breakingPos) + .destroyBlocks(level, null, this::dropItemFromCutTree); + } + + public void dropItemFromCutTree(BlockPos pos, ItemStack stack) { + float distance = (float) Math.sqrt(pos.distSqr(breakingPos)); + Vec3 dropPos = VecHelper.getCenterOf(pos); + ItemEntity entity = new ItemEntity(level, dropPos.x, dropPos.y, dropPos.z, stack); + entity.setDeltaMovement(Vec3.atLowerCornerOf(breakingPos.subtract(this.worldPosition)) + .scale(distance / 20f)); + level.addFreshEntity(entity); + } + + @Override + public boolean canBreak(BlockState stateToBreak, float blockHardness) { + boolean sawable = isSawable(stateToBreak); + return super.canBreak(stateToBreak, blockHardness) && sawable; + } + + public static boolean isSawable(BlockState stateToBreak) { + if (stateToBreak.is(BlockTags.SAPLINGS)) + return false; + if (TreeCutter.isLog(stateToBreak) || (stateToBreak.is(BlockTags.LEAVES))) + return true; + if (TreeCutter.isRoot(stateToBreak)) + return true; + Block block = stateToBreak.getBlock(); + if (block instanceof BambooStalkBlock) + return true; + if (block instanceof StemGrownBlock) + return true; + if (block instanceof CactusBlock) + return true; + if (block instanceof SugarCaneBlock) + return true; + if (block instanceof KelpPlantBlock) + return true; + if (block instanceof KelpBlock) + return true; + if (block instanceof ChorusPlantBlock) + return true; + if (TreeCutter.canDynamicTreeCutFrom(block)) + return true; + return false; + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/saw/SawFilterSlot.java b/src/main/java/com/simibubi/create/content/kinetics/saw/SawFilterSlot.java new file mode 100644 index 000000000..ceb9495d3 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/saw/SawFilterSlot.java @@ -0,0 +1,33 @@ +package com.simibubi.create.content.kinetics.saw; + +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class SawFilterSlot extends ValueBoxTransform { + + @Override + public Vec3 getLocalOffset(BlockState state) { + if (state.getValue(SawBlock.FACING) != Direction.UP) + return null; + int offset = state.getValue(SawBlock.FLIPPED) ? -3 : 3; + Vec3 x = VecHelper.voxelSpace(8, 12.5f, 8 + offset); + Vec3 z = VecHelper.voxelSpace(8 + offset, 12.5f, 8); + return state.getValue(SawBlock.AXIS_ALONG_FIRST_COORDINATE) ? z : x; + } + + @Override + public void rotate(BlockState state, PoseStack ms) { + int yRot = (state.getValue(SawBlock.AXIS_ALONG_FIRST_COORDINATE) ? 90 : 0) + + (state.getValue(SawBlock.FLIPPED) ? 0 : 180); + TransformStack.cast(ms) + .rotateY(yRot) + .rotateX(90); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawGenerator.java b/src/main/java/com/simibubi/create/content/kinetics/saw/SawGenerator.java similarity index 90% rename from src/main/java/com/simibubi/create/content/contraptions/components/saw/SawGenerator.java rename to src/main/java/com/simibubi/create/content/kinetics/saw/SawGenerator.java index 20e459310..90e90dfb1 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawGenerator.java +++ b/src/main/java/com/simibubi/create/content/kinetics/saw/SawGenerator.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.saw; +package com.simibubi.create.content.kinetics.saw; import com.simibubi.create.foundation.data.SpecialBlockStateGen; import com.tterrag.registrate.providers.DataGenContext; @@ -22,7 +22,7 @@ public class SawGenerator extends SpecialBlockStateGen { boolean axisAlongFirst = state.getValue(SawBlock.AXIS_ALONG_FIRST_COORDINATE); if (facing.getAxis() .isVertical()) - return axisAlongFirst ? 90 : 0; + return (axisAlongFirst ? 270 : 0) + (state.getValue(SawBlock.FLIPPED) ? 180 : 0); return horizontalAngle(facing); } diff --git a/src/main/java/com/simibubi/create/content/kinetics/saw/SawInstance.java b/src/main/java/com/simibubi/create/content/kinetics/saw/SawInstance.java new file mode 100644 index 000000000..9f0662d19 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/saw/SawInstance.java @@ -0,0 +1,32 @@ +package com.simibubi.create.content.kinetics.saw; + +import com.jozufozu.flywheel.api.Instancer; +import com.jozufozu.flywheel.api.MaterialManager; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.SingleRotatingInstance; +import com.simibubi.create.content.kinetics.base.flwdata.RotatingData; + +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.Rotation; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; + +public class SawInstance extends SingleRotatingInstance { + + public SawInstance(MaterialManager materialManager, SawBlockEntity blockEntity) { + super(materialManager, blockEntity); + } + + @Override + protected Instancer getModel() { + if (blockState.getValue(BlockStateProperties.FACING) + .getAxis() + .isHorizontal()) { + BlockState referenceState = blockState.rotate(blockEntity.getLevel(), blockEntity.getBlockPos(), Rotation.CLOCKWISE_180); + Direction facing = referenceState.getValue(BlockStateProperties.FACING); + return getRotatingMaterial().getModel(AllPartialModels.SHAFT_HALF, referenceState, facing); + } else { + return getRotatingMaterial().getModel(shaft()); + } + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/SawMovementBehaviour.java b/src/main/java/com/simibubi/create/content/kinetics/saw/SawMovementBehaviour.java similarity index 83% rename from src/main/java/com/simibubi/create/content/contraptions/components/actors/SawMovementBehaviour.java rename to src/main/java/com/simibubi/create/content/kinetics/saw/SawMovementBehaviour.java index 17965f864..77dee7634 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/SawMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/kinetics/saw/SawMovementBehaviour.java @@ -1,13 +1,11 @@ -package com.simibubi.create.content.contraptions.components.actors; +package com.simibubi.create.content.kinetics.saw; import java.util.Optional; import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; -import com.simibubi.create.content.contraptions.components.saw.SawBlock; -import com.simibubi.create.content.contraptions.components.saw.SawRenderer; -import com.simibubi.create.content.contraptions.components.saw.SawTileEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.contraptions.render.ContraptionMatrices; +import com.simibubi.create.content.kinetics.base.BlockBreakingMovementBehaviour; import com.simibubi.create.foundation.utility.AbstractBlockBreakQueue; import com.simibubi.create.foundation.utility.TreeCutter; import com.simibubi.create.foundation.utility.VecHelper; @@ -30,8 +28,9 @@ public class SawMovementBehaviour extends BlockBreakingMovementBehaviour { @Override public boolean isActive(MovementContext context) { - return !VecHelper.isVecPointingTowards(context.relativeMotion, context.state.getValue(SawBlock.FACING) - .getOpposite()); + return super.isActive(context) + && !VecHelper.isVecPointingTowards(context.relativeMotion, context.state.getValue(SawBlock.FACING) + .getOpposite()); } @Override @@ -58,7 +57,7 @@ public class SawMovementBehaviour extends BlockBreakingMovementBehaviour { @Override public boolean canBreak(Level world, BlockPos breakingPos, BlockState state) { - return super.canBreak(world, breakingPos, state) && SawTileEntity.isSawable(state); + return super.canBreak(world, breakingPos, state) && SawBlockEntity.isSawable(state); } @Override diff --git a/src/main/java/com/simibubi/create/content/kinetics/saw/SawRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/saw/SawRenderer.java new file mode 100644 index 000000000..5d8977553 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/saw/SawRenderer.java @@ -0,0 +1,205 @@ +package com.simibubi.create.content.kinetics.saw; + +import static net.minecraft.world.level.block.state.properties.BlockStateProperties.FACING; + +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.core.PartialModel; +import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Axis; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.contraptions.render.ContraptionMatrices; +import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringRenderer; +import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.block.model.ItemTransforms; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.client.renderer.entity.ItemRenderer; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.Rotation; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class SawRenderer extends SafeBlockEntityRenderer { + + public SawRenderer(BlockEntityRendererProvider.Context context) { + } + + @Override + protected void renderSafe(SawBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light, + int overlay) { + renderBlade(be, ms, buffer, light); + renderItems(be, partialTicks, ms, buffer, light, overlay); + FilteringRenderer.renderOnBlockEntity(be, partialTicks, ms, buffer, light, overlay); + + if (Backend.canUseInstancing(be.getLevel())) + return; + + renderShaft(be, ms, buffer, light, overlay); + } + + protected void renderBlade(SawBlockEntity be, PoseStack ms, MultiBufferSource buffer, int light) { + BlockState blockState = be.getBlockState(); + PartialModel partial; + float speed = be.getSpeed(); + boolean rotate = false; + + if (SawBlock.isHorizontal(blockState)) { + if (speed > 0) { + partial = AllPartialModels.SAW_BLADE_HORIZONTAL_ACTIVE; + } else if (speed < 0) { + partial = AllPartialModels.SAW_BLADE_HORIZONTAL_REVERSED; + } else { + partial = AllPartialModels.SAW_BLADE_HORIZONTAL_INACTIVE; + } + } else { + if (be.getSpeed() > 0) { + partial = AllPartialModels.SAW_BLADE_VERTICAL_ACTIVE; + } else if (speed < 0) { + partial = AllPartialModels.SAW_BLADE_VERTICAL_REVERSED; + } else { + partial = AllPartialModels.SAW_BLADE_VERTICAL_INACTIVE; + } + + if (blockState.getValue(SawBlock.AXIS_ALONG_FIRST_COORDINATE)) + rotate = true; + } + + SuperByteBuffer superBuffer = CachedBufferer.partialFacing(partial, blockState); + if (rotate) { + superBuffer.rotateCentered(Direction.UP, AngleHelper.rad(90)); + } + superBuffer.color(0xFFFFFF) + .light(light) + .renderInto(ms, buffer.getBuffer(RenderType.cutoutMipped())); + } + + protected void renderShaft(SawBlockEntity be, PoseStack ms, MultiBufferSource buffer, int light, int overlay) { + KineticBlockEntityRenderer.renderRotatingBuffer(be, getRotatedModel(be), ms, + buffer.getBuffer(RenderType.solid()), light); + } + + protected void renderItems(SawBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + boolean processingMode = be.getBlockState() + .getValue(SawBlock.FACING) == Direction.UP; + if (processingMode && !be.inventory.isEmpty()) { + boolean alongZ = !be.getBlockState() + .getValue(SawBlock.AXIS_ALONG_FIRST_COORDINATE); + ms.pushPose(); + + boolean moving = be.inventory.recipeDuration != 0; + float offset = moving ? (float) (be.inventory.remainingTime) / be.inventory.recipeDuration : 0; + float processingSpeed = Mth.clamp(Math.abs(be.getSpeed()) / 32, 1, 128); + if (moving) { + offset = Mth + .clamp(offset + ((-partialTicks + .5f) * processingSpeed) / be.inventory.recipeDuration, 0.125f, 1f); + if (!be.inventory.appliedRecipe) + offset += 1; + offset /= 2; + } + + if (be.getSpeed() == 0) + offset = .5f; + if (be.getSpeed() < 0 ^ alongZ) + offset = 1 - offset; + + for (int i = 0; i < be.inventory.getSlots(); i++) { + ItemStack stack = be.inventory.getStackInSlot(i); + if (stack.isEmpty()) + continue; + + ItemRenderer itemRenderer = Minecraft.getInstance() + .getItemRenderer(); + BakedModel modelWithOverrides = itemRenderer.getModel(stack, be.getLevel(), null, 0); + boolean blockItem = modelWithOverrides.isGui3d(); + + ms.translate(alongZ ? offset : .5, blockItem ? .925f : 13f / 16f, alongZ ? .5 : offset); + + ms.scale(.5f, .5f, .5f); + if (alongZ) + ms.mulPose(Axis.YP.rotationDegrees(90)); + ms.mulPose(Axis.XP.rotationDegrees(90)); + itemRenderer.renderStatic(stack, ItemTransforms.TransformType.FIXED, light, overlay, ms, buffer, 0); + break; + } + + ms.popPose(); + } + } + + protected SuperByteBuffer getRotatedModel(KineticBlockEntity be) { + BlockState state = be.getBlockState(); + if (state.getValue(FACING) + .getAxis() + .isHorizontal()) + return CachedBufferer.partialFacing(AllPartialModels.SHAFT_HALF, + state.rotate(be.getLevel(), be.getBlockPos(), Rotation.CLOCKWISE_180)); + return CachedBufferer.block(KineticBlockEntityRenderer.KINETIC_BLOCK, + getRenderedBlockState(be)); + } + + protected BlockState getRenderedBlockState(KineticBlockEntity be) { + return KineticBlockEntityRenderer.shaft(KineticBlockEntityRenderer.getRotationAxisOf(be)); + } + + public static void renderInContraption(MovementContext context, VirtualRenderWorld renderWorld, + ContraptionMatrices matrices, MultiBufferSource buffer) { + BlockState state = context.state; + Direction facing = state.getValue(SawBlock.FACING); + + Vec3 facingVec = Vec3.atLowerCornerOf(context.state.getValue(SawBlock.FACING) + .getNormal()); + facingVec = context.rotation.apply(facingVec); + + Direction closestToFacing = Direction.getNearest(facingVec.x, facingVec.y, facingVec.z); + + boolean horizontal = closestToFacing.getAxis() + .isHorizontal(); + boolean backwards = VecHelper.isVecPointingTowards(context.relativeMotion, facing.getOpposite()); + boolean moving = context.getAnimationSpeed() != 0; + boolean shouldAnimate = + (context.contraption.stalled && horizontal) || (!context.contraption.stalled && !backwards && moving); + + SuperByteBuffer superBuffer; + if (SawBlock.isHorizontal(state)) { + if (shouldAnimate) + superBuffer = CachedBufferer.partial(AllPartialModels.SAW_BLADE_HORIZONTAL_ACTIVE, state); + else + superBuffer = CachedBufferer.partial(AllPartialModels.SAW_BLADE_HORIZONTAL_INACTIVE, state); + } else { + if (shouldAnimate) + superBuffer = CachedBufferer.partial(AllPartialModels.SAW_BLADE_VERTICAL_ACTIVE, state); + else + superBuffer = CachedBufferer.partial(AllPartialModels.SAW_BLADE_VERTICAL_INACTIVE, state); + } + + superBuffer.transform(matrices.getModel()) + .centre() + .rotateY(AngleHelper.horizontalAngle(facing)) + .rotateX(AngleHelper.verticalAngle(facing)); + + if (!SawBlock.isHorizontal(state)) { + superBuffer.rotateZ(state.getValue(SawBlock.AXIS_ALONG_FIRST_COORDINATE) ? 90 : 0); + } + + superBuffer.unCentre() + .light(matrices.getWorld(), ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) + .renderInto(matrices.getViewProjection(), buffer.getBuffer(RenderType.cutoutMipped())); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/AbstractShaftBlock.java b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/AbstractShaftBlock.java similarity index 83% rename from src/main/java/com/simibubi/create/content/contraptions/relays/elementary/AbstractShaftBlock.java rename to src/main/java/com/simibubi/create/content/kinetics/simpleRelays/AbstractShaftBlock.java index a24d12d78..cca9ba71c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/AbstractShaftBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/AbstractShaftBlock.java @@ -1,8 +1,8 @@ -package com.simibubi.create.content.contraptions.relays.elementary; +package com.simibubi.create.content.kinetics.simpleRelays; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.base.RotatedPillarKineticBlock; +import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.block.ProperWaterloggedBlock; import net.minecraft.core.BlockPos; @@ -20,7 +20,7 @@ import net.minecraft.world.level.material.FluidState; import net.minecraft.world.level.pathfinder.PathComputationType; public abstract class AbstractShaftBlock extends RotatedPillarKineticBlock - implements ITE, ProperWaterloggedBlock { + implements IBE, ProperWaterloggedBlock { public AbstractShaftBlock(Properties properties) { super(properties); @@ -33,8 +33,8 @@ public abstract class AbstractShaftBlock extends RotatedPillarKineticBlock } @Override - public Class getTileEntityClass() { - return KineticTileEntity.class; + public Class getBlockEntityClass() { + return KineticBlockEntity.class; } @Override diff --git a/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/AbstractSimpleShaftBlock.java b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/AbstractSimpleShaftBlock.java new file mode 100644 index 000000000..d4ad89d44 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/AbstractSimpleShaftBlock.java @@ -0,0 +1,61 @@ +package com.simibubi.create.content.kinetics.simpleRelays; + +import java.util.Optional; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.content.decoration.bracket.BracketedBlockEntityBehaviour; +import com.simibubi.create.content.equipment.wrench.IWrenchableWithBracket; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.UseOnContext; +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.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.PushReaction; + +public abstract class AbstractSimpleShaftBlock extends AbstractShaftBlock implements IWrenchableWithBracket { + + public AbstractSimpleShaftBlock(Properties properties) { + super(properties); + } + + @Override + public InteractionResult onWrenched(BlockState state, UseOnContext context) { + return IWrenchableWithBracket.super.onWrenched(state, context); + } + + @Override + public PushReaction getPistonPushReaction(BlockState state) { + return PushReaction.NORMAL; + } + + @Override + public void onRemove(BlockState state, Level world, BlockPos pos, BlockState newState, boolean isMoving) { + if (state != newState && !isMoving) + removeBracket(world, pos, true).ifPresent(stack -> Block.popResource(world, pos, stack)); + super.onRemove(state, world, pos, newState, isMoving); + } + + @Override + public Optional removeBracket(BlockGetter world, BlockPos pos, boolean inOnReplacedContext) { + BracketedBlockEntityBehaviour behaviour = BlockEntityBehaviour.get(world, pos, BracketedBlockEntityBehaviour.TYPE); + if (behaviour == null) + return Optional.empty(); + BlockState bracket = behaviour.removeBracket(inOnReplacedContext); + if (bracket == null) + return Optional.empty(); + return Optional.of(new ItemStack(bracket.getBlock())); + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.BRACKETED_KINETIC.get(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/BracketedKineticBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/BracketedKineticBlockEntity.java new file mode 100644 index 000000000..ad1191d6d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/BracketedKineticBlockEntity.java @@ -0,0 +1,35 @@ +package com.simibubi.create.content.kinetics.simpleRelays; + +import java.util.List; + +import com.simibubi.create.content.contraptions.ITransformableBlockEntity; +import com.simibubi.create.content.contraptions.StructureTransform; +import com.simibubi.create.content.decoration.bracket.BracketedBlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; + +public class BracketedKineticBlockEntity extends SimpleKineticBlockEntity implements ITransformableBlockEntity { + + public BracketedKineticBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + public void addBehaviours(List behaviours) { + behaviours + .add(new BracketedBlockEntityBehaviour(this, state -> state.getBlock() instanceof AbstractSimpleShaftBlock)); + super.addBehaviours(behaviours); + } + + @Override + public void transform(StructureTransform transform) { + BracketedBlockEntityBehaviour bracketBehaviour = getBehaviour(BracketedBlockEntityBehaviour.TYPE); + if (bracketBehaviour != null) { + bracketBehaviour.transformBracket(transform); + } + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/BracketedKineticBlockEntityInstance.java b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/BracketedKineticBlockEntityInstance.java new file mode 100644 index 000000000..7d2b580f8 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/BracketedKineticBlockEntityInstance.java @@ -0,0 +1,91 @@ +package com.simibubi.create.content.kinetics.simpleRelays; + +import com.jozufozu.flywheel.api.Instancer; +import com.jozufozu.flywheel.api.MaterialManager; +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Axis; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.content.kinetics.base.SingleRotatingInstance; +import com.simibubi.create.content.kinetics.base.flwdata.RotatingData; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.AxisDirection; + +public class BracketedKineticBlockEntityInstance extends SingleRotatingInstance { + + protected RotatingData additionalShaft; + + public BracketedKineticBlockEntityInstance(MaterialManager materialManager, BracketedKineticBlockEntity blockEntity) { + super(materialManager, blockEntity); + } + + @Override + public void init() { + super.init(); + if (!ICogWheel.isLargeCog(blockEntity.getBlockState())) + return; + + // Large cogs sometimes have to offset their teeth by 11.25 degrees in order to + // mesh properly + + float speed = blockEntity.getSpeed(); + Direction.Axis axis = KineticBlockEntityRenderer.getRotationAxisOf(blockEntity); + BlockPos pos = blockEntity.getBlockPos(); + float offset = BracketedKineticBlockEntityRenderer.getShaftAngleOffset(axis, pos); + Direction facing = Direction.fromAxisAndDirection(axis, AxisDirection.POSITIVE); + Instancer half = getRotatingMaterial().getModel(AllPartialModels.COGWHEEL_SHAFT, blockState, + facing, () -> this.rotateToAxis(axis)); + + additionalShaft = setup(half.createInstance(), speed); + additionalShaft.setRotationOffset(offset); + } + + @Override + protected Instancer getModel() { + if (!ICogWheel.isLargeCog(blockEntity.getBlockState())) + return super.getModel(); + + Direction.Axis axis = KineticBlockEntityRenderer.getRotationAxisOf(blockEntity); + Direction facing = Direction.fromAxisAndDirection(axis, AxisDirection.POSITIVE); + return getRotatingMaterial().getModel(AllPartialModels.SHAFTLESS_LARGE_COGWHEEL, blockState, facing, + () -> this.rotateToAxis(axis)); + } + + private PoseStack rotateToAxis(Direction.Axis axis) { + Direction facing = Direction.fromAxisAndDirection(axis, AxisDirection.POSITIVE); + PoseStack poseStack = new PoseStack(); + TransformStack.cast(poseStack) + .centre() + .rotateToFace(facing) + .multiply(Axis.XN.rotationDegrees(-90)) + .unCentre(); + return poseStack; + } + + @Override + public void update() { + super.update(); + if (additionalShaft != null) { + updateRotation(additionalShaft); + additionalShaft.setRotationOffset(BracketedKineticBlockEntityRenderer.getShaftAngleOffset(axis, pos)); + } + } + + @Override + public void updateLight() { + super.updateLight(); + if (additionalShaft != null) + relight(pos, additionalShaft); + } + + @Override + public void remove() { + super.remove(); + if (additionalShaft != null) + additionalShaft.delete(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/BracketedKineticBlockEntityRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/BracketedKineticBlockEntityRenderer.java new file mode 100644 index 000000000..cf6763950 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/BracketedKineticBlockEntityRenderer.java @@ -0,0 +1,72 @@ +package com.simibubi.create.content.kinetics.simpleRelays; + +import com.jozufozu.flywheel.backend.Backend; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.AnimationTickHolder; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider.Context; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.Direction.AxisDirection; + +public class BracketedKineticBlockEntityRenderer extends KineticBlockEntityRenderer { + + public BracketedKineticBlockEntityRenderer(Context context) { + super(context); + } + + @Override + protected void renderSafe(BracketedKineticBlockEntity be, float partialTicks, PoseStack ms, + MultiBufferSource buffer, int light, int overlay) { + + if (Backend.canUseInstancing(be.getLevel())) + return; + + if (!AllBlocks.LARGE_COGWHEEL.has(be.getBlockState())) { + super.renderSafe(be, partialTicks, ms, buffer, light, overlay); + return; + } + + // Large cogs sometimes have to offset their teeth by 11.25 degrees in order to + // mesh properly + + Axis axis = getRotationAxisOf(be); + Direction facing = Direction.fromAxisAndDirection(axis, AxisDirection.POSITIVE); + renderRotatingBuffer(be, + CachedBufferer.partialFacingVertical(AllPartialModels.SHAFTLESS_LARGE_COGWHEEL, be.getBlockState(), facing), + ms, buffer.getBuffer(RenderType.solid()), light); + + float angle = getAngleForLargeCogShaft(be, axis); + SuperByteBuffer shaft = + CachedBufferer.partialFacingVertical(AllPartialModels.COGWHEEL_SHAFT, be.getBlockState(), facing); + kineticRotationTransform(shaft, be, axis, angle, light); + shaft.renderInto(ms, buffer.getBuffer(RenderType.solid())); + + } + + public static float getAngleForLargeCogShaft(SimpleKineticBlockEntity be, Axis axis) { + BlockPos pos = be.getBlockPos(); + float offset = getShaftAngleOffset(axis, pos); + float time = AnimationTickHolder.getRenderTime(be.getLevel()); + float angle = ((time * be.getSpeed() * 3f / 10 + offset) % 360) / 180 * (float) Math.PI; + return angle; + } + + public static float getShaftAngleOffset(Axis axis, BlockPos pos) { + float offset = 0; + double d = (((axis == Axis.X) ? 0 : pos.getX()) + ((axis == Axis.Y) ? 0 : pos.getY()) + + ((axis == Axis.Z) ? 0 : pos.getZ())) % 2; + if (d == 0) + offset = 22.5f; + return offset; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/BracketedKineticBlockModel.java b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/BracketedKineticBlockModel.java similarity index 81% rename from src/main/java/com/simibubi/create/content/contraptions/relays/elementary/BracketedKineticBlockModel.java rename to src/main/java/com/simibubi/create/content/kinetics/simpleRelays/BracketedKineticBlockModel.java index 0872227c1..3716bc865 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/BracketedKineticBlockModel.java +++ b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/BracketedKineticBlockModel.java @@ -1,10 +1,11 @@ -package com.simibubi.create.content.contraptions.relays.elementary; +package com.simibubi.create.content.kinetics.simpleRelays; import java.util.Collections; import java.util.List; import com.jozufozu.flywheel.core.model.ModelUtil; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; +import com.simibubi.create.content.decoration.bracket.BracketedBlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.RenderType; @@ -28,12 +29,12 @@ public class BracketedKineticBlockModel extends BakedModelWrapper { } @Override - public ModelData getModelData(BlockAndTintGetter world, BlockPos pos, BlockState state, ModelData tileData) { - if (ModelUtil.isVirtual(tileData)) - return tileData; + public ModelData getModelData(BlockAndTintGetter world, BlockPos pos, BlockState state, ModelData blockEntityData) { + if (ModelUtil.isVirtual(blockEntityData)) + return blockEntityData; BracketedModelData data = new BracketedModelData(); - BracketedTileEntityBehaviour attachmentBehaviour = - TileEntityBehaviour.get(world, pos, BracketedTileEntityBehaviour.TYPE); + BracketedBlockEntityBehaviour attachmentBehaviour = + BlockEntityBehaviour.get(world, pos, BracketedBlockEntityBehaviour.TYPE); if (attachmentBehaviour != null) data.putBracket(attachmentBehaviour.getBracket()); return ModelData.builder().with(BRACKET_PROPERTY, data) diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/CogWheelBlock.java b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/CogWheelBlock.java similarity index 95% rename from src/main/java/com/simibubi/create/content/contraptions/relays/elementary/CogWheelBlock.java rename to src/main/java/com/simibubi/create/content/kinetics/simpleRelays/CogWheelBlock.java index b0b11b568..c3be8c85c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/CogWheelBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/CogWheelBlock.java @@ -1,11 +1,12 @@ -package com.simibubi.create.content.contraptions.relays.elementary; +package com.simibubi.create.content.kinetics.simpleRelays; import javax.annotation.ParametersAreNonnullByDefault; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; -import com.simibubi.create.content.contraptions.base.IRotate; -import com.simibubi.create.content.contraptions.relays.advanced.SpeedControllerBlock; +import com.simibubi.create.content.decoration.encasing.EncasableBlock; +import com.simibubi.create.content.kinetics.base.IRotate; +import com.simibubi.create.content.kinetics.speedController.SpeedControllerBlock; import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.utility.Iterate; diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/CogwheelBlockItem.java b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/CogwheelBlockItem.java similarity index 93% rename from src/main/java/com/simibubi/create/content/contraptions/relays/elementary/CogwheelBlockItem.java rename to src/main/java/com/simibubi/create/content/kinetics/simpleRelays/CogwheelBlockItem.java index caabc7551..921d95748 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/CogwheelBlockItem.java +++ b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/CogwheelBlockItem.java @@ -1,19 +1,19 @@ -package com.simibubi.create.content.contraptions.relays.elementary; +package com.simibubi.create.content.kinetics.simpleRelays; -import static com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock.AXIS; +import static com.simibubi.create.content.kinetics.base.RotatedPillarKineticBlock.AXIS; import java.util.List; import java.util.function.Predicate; import com.simibubi.create.AllShapes; -import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock; -import com.simibubi.create.content.contraptions.base.HorizontalKineticBlock; -import com.simibubi.create.content.contraptions.base.IRotate; -import com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock; +import com.simibubi.create.content.kinetics.base.DirectionalKineticBlock; +import com.simibubi.create.content.kinetics.base.HorizontalKineticBlock; +import com.simibubi.create.content.kinetics.base.IRotate; +import com.simibubi.create.content.kinetics.base.RotatedPillarKineticBlock; +import com.simibubi.create.foundation.placement.IPlacementHelper; +import com.simibubi.create.foundation.placement.PlacementHelpers; +import com.simibubi.create.foundation.placement.PlacementOffset; import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.placement.IPlacementHelper; -import com.simibubi.create.foundation.utility.placement.PlacementHelpers; -import com.simibubi.create.foundation.utility.placement.PlacementOffset; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/ICogWheel.java b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/ICogWheel.java similarity index 92% rename from src/main/java/com/simibubi/create/content/contraptions/relays/elementary/ICogWheel.java rename to src/main/java/com/simibubi/create/content/kinetics/simpleRelays/ICogWheel.java index 619dbb390..b62373f6d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/ICogWheel.java +++ b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/ICogWheel.java @@ -1,6 +1,6 @@ -package com.simibubi.create.content.contraptions.relays.elementary; +package com.simibubi.create.content.kinetics.simpleRelays; -import com.simibubi.create.content.contraptions.base.IRotate; +import com.simibubi.create.content.kinetics.base.IRotate; import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.Item; diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/ShaftBlock.java b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/ShaftBlock.java similarity index 85% rename from src/main/java/com/simibubi/create/content/contraptions/relays/elementary/ShaftBlock.java rename to src/main/java/com/simibubi/create/content/kinetics/simpleRelays/ShaftBlock.java index 01d90e6a3..4a5686f49 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/ShaftBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/ShaftBlock.java @@ -1,17 +1,18 @@ -package com.simibubi.create.content.contraptions.relays.elementary; +package com.simibubi.create.content.kinetics.simpleRelays; import java.util.function.Predicate; import com.google.common.base.Predicates; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.components.steam.PoweredShaftBlock; -import com.simibubi.create.content.curiosities.girder.GirderEncasedShaftBlock; -import com.simibubi.create.foundation.utility.placement.IPlacementHelper; -import com.simibubi.create.foundation.utility.placement.PlacementHelpers; -import com.simibubi.create.foundation.utility.placement.PlacementOffset; -import com.simibubi.create.foundation.utility.placement.util.PoleHelper; +import com.simibubi.create.content.decoration.encasing.EncasableBlock; +import com.simibubi.create.content.decoration.girder.GirderEncasedShaftBlock; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.steamEngine.PoweredShaftBlock; +import com.simibubi.create.foundation.placement.IPlacementHelper; +import com.simibubi.create.foundation.placement.PlacementHelpers; +import com.simibubi.create.foundation.placement.PlacementOffset; +import com.simibubi.create.foundation.placement.PoleHelper; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; @@ -81,7 +82,7 @@ public class ShaftBlock extends AbstractSimpleShaftBlock implements EncasableBlo return result; if (AllBlocks.METAL_GIRDER.isIn(heldItem) && state.getValue(AXIS) != Axis.Y) { - KineticTileEntity.switchToBlockState(world, pos, AllBlocks.METAL_GIRDER_ENCASED_SHAFT.getDefaultState() + KineticBlockEntity.switchToBlockState(world, pos, AllBlocks.METAL_GIRDER_ENCASED_SHAFT.getDefaultState() .setValue(WATERLOGGED, state.getValue(WATERLOGGED)) .setValue(GirderEncasedShaftBlock.HORIZONTAL_AXIS, state.getValue(AXIS) == Axis.Z ? Axis.Z : Axis.X)); if (!world.isClientSide && !player.isCreative()) { diff --git a/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/SimpleKineticBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/SimpleKineticBlockEntity.java new file mode 100644 index 000000000..493b0f227 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/SimpleKineticBlockEntity.java @@ -0,0 +1,42 @@ +package com.simibubi.create.content.kinetics.simpleRelays; + +import java.util.List; + +import com.simibubi.create.content.kinetics.base.IRotate; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; + +public class SimpleKineticBlockEntity extends KineticBlockEntity { + + public SimpleKineticBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + protected AABB createRenderBoundingBox() { + return new AABB(worldPosition).inflate(1); + } + + @Override + public List addPropagationLocations(IRotate block, BlockState state, List neighbours) { + if (!ICogWheel.isLargeCog(state)) + return super.addPropagationLocations(block, state, neighbours); + + BlockPos.betweenClosedStream(new BlockPos(-1, -1, -1), new BlockPos(1, 1, 1)) + .forEach(offset -> { + if (offset.distSqr(BlockPos.ZERO) == 2) + neighbours.add(worldPosition.offset(offset)); + }); + return neighbours; + } + + @Override + protected boolean isNoisy() { + return false; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/EncasedCogCTBehaviour.java b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/encased/EncasedCogCTBehaviour.java similarity index 89% rename from src/main/java/com/simibubi/create/content/contraptions/relays/encased/EncasedCogCTBehaviour.java rename to src/main/java/com/simibubi/create/content/kinetics/simpleRelays/encased/EncasedCogCTBehaviour.java index bebb607d5..69ca1253b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/EncasedCogCTBehaviour.java +++ b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/encased/EncasedCogCTBehaviour.java @@ -1,11 +1,12 @@ -package com.simibubi.create.content.contraptions.relays.encased; +package com.simibubi.create.content.kinetics.simpleRelays.encased; -import static com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock.AXIS; +import static com.simibubi.create.content.kinetics.base.RotatedPillarKineticBlock.AXIS; import org.jetbrains.annotations.Nullable; -import com.simibubi.create.content.contraptions.base.IRotate; -import com.simibubi.create.content.contraptions.relays.elementary.ICogWheel; +import com.simibubi.create.content.decoration.encasing.EncasedCTBehaviour; +import com.simibubi.create.content.kinetics.base.IRotate; +import com.simibubi.create.content.kinetics.simpleRelays.ICogWheel; import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry; import com.simibubi.create.foundation.utility.Couple; diff --git a/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/encased/EncasedCogInstance.java b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/encased/EncasedCogInstance.java new file mode 100644 index 000000000..f6633776e --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/encased/EncasedCogInstance.java @@ -0,0 +1,111 @@ +package com.simibubi.create.content.kinetics.simpleRelays.encased; + +import java.util.Optional; + +import com.jozufozu.flywheel.api.InstanceData; +import com.jozufozu.flywheel.api.Instancer; +import com.jozufozu.flywheel.api.MaterialManager; +import com.jozufozu.flywheel.core.PartialModel; +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Axis; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.IRotate; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityInstance; +import com.simibubi.create.content.kinetics.base.flwdata.RotatingData; +import com.simibubi.create.content.kinetics.simpleRelays.BracketedKineticBlockEntityRenderer; +import com.simibubi.create.foundation.utility.Iterate; + +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; + +public class EncasedCogInstance extends KineticBlockEntityInstance { + + private boolean large; + + protected RotatingData rotatingModel; + protected Optional rotatingTopShaft; + protected Optional rotatingBottomShaft; + + public static EncasedCogInstance small(MaterialManager modelManager, KineticBlockEntity blockEntity) { + return new EncasedCogInstance(modelManager, blockEntity, false); + } + + public static EncasedCogInstance large(MaterialManager modelManager, KineticBlockEntity blockEntity) { + return new EncasedCogInstance(modelManager, blockEntity, true); + } + + public EncasedCogInstance(MaterialManager modelManager, KineticBlockEntity blockEntity, boolean large) { + super(modelManager, blockEntity); + this.large = large; + } + + @Override + public void init() { + rotatingModel = setup(getCogModel().createInstance()); + + Block block = blockState.getBlock(); + if (!(block instanceof IRotate)) + return; + + IRotate def = (IRotate) block; + rotatingTopShaft = Optional.empty(); + rotatingBottomShaft = Optional.empty(); + + for (Direction d : Iterate.directionsInAxis(axis)) { + if (!def.hasShaftTowards(blockEntity.getLevel(), blockEntity.getBlockPos(), blockState, d)) + continue; + RotatingData data = setup(getRotatingMaterial().getModel(AllPartialModels.SHAFT_HALF, blockState, d) + .createInstance()); + if (large) + data.setRotationOffset(BracketedKineticBlockEntityRenderer.getShaftAngleOffset(axis, pos)); + if (d.getAxisDirection() == AxisDirection.POSITIVE) + rotatingTopShaft = Optional.of(data); + else + rotatingBottomShaft = Optional.of(data); + } + } + + @Override + public void update() { + updateRotation(rotatingModel); + rotatingTopShaft.ifPresent(this::updateRotation); + rotatingBottomShaft.ifPresent(this::updateRotation); + } + + @Override + public void updateLight() { + relight(pos, rotatingModel); + rotatingTopShaft.ifPresent(d -> relight(pos, d)); + rotatingBottomShaft.ifPresent(d -> relight(pos, d)); + } + + @Override + public void remove() { + rotatingModel.delete(); + rotatingTopShaft.ifPresent(InstanceData::delete); + rotatingBottomShaft.ifPresent(InstanceData::delete); + } + + protected Instancer getCogModel() { + BlockState referenceState = blockEntity.getBlockState(); + Direction facing = + Direction.fromAxisAndDirection(referenceState.getValue(BlockStateProperties.AXIS), AxisDirection.POSITIVE); + PartialModel partial = large ? AllPartialModels.SHAFTLESS_LARGE_COGWHEEL : AllPartialModels.SHAFTLESS_COGWHEEL; + + return getRotatingMaterial().getModel(partial, referenceState, facing, () -> { + PoseStack poseStack = new PoseStack(); + TransformStack.cast(poseStack) + .centre() + .rotateToFace(facing) + .multiply(Axis.XN.rotationDegrees(90)) + .unCentre(); + return poseStack; + }); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/encased/EncasedCogRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/encased/EncasedCogRenderer.java new file mode 100644 index 000000000..8a03236a8 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/encased/EncasedCogRenderer.java @@ -0,0 +1,75 @@ +package com.simibubi.create.content.kinetics.simpleRelays.encased; + +import com.jozufozu.flywheel.backend.Backend; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.IRotate; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.content.kinetics.simpleRelays.BracketedKineticBlockEntityRenderer; +import com.simibubi.create.content.kinetics.simpleRelays.SimpleKineticBlockEntity; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.Iterate; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; + +public class EncasedCogRenderer extends KineticBlockEntityRenderer { + + private boolean large; + + public static EncasedCogRenderer small(BlockEntityRendererProvider.Context context) { + return new EncasedCogRenderer(context, false); + } + + public static EncasedCogRenderer large(BlockEntityRendererProvider.Context context) { + return new EncasedCogRenderer(context, true); + } + + public EncasedCogRenderer(BlockEntityRendererProvider.Context context, boolean large) { + super(context); + this.large = large; + } + + @Override + protected void renderSafe(SimpleKineticBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + super.renderSafe(be, partialTicks, ms, buffer, light, overlay); + if (Backend.canUseInstancing(be.getLevel())) + return; + + BlockState blockState = be.getBlockState(); + Block block = blockState.getBlock(); + if (!(block instanceof IRotate)) + return; + IRotate def = (IRotate) block; + + Axis axis = getRotationAxisOf(be); + BlockPos pos = be.getBlockPos(); + float angle = large ? BracketedKineticBlockEntityRenderer.getAngleForLargeCogShaft(be, axis) + : getAngleForTe(be, pos, axis); + + for (Direction d : Iterate.directionsInAxis(getRotationAxisOf(be))) { + if (!def.hasShaftTowards(be.getLevel(), be.getBlockPos(), blockState, d)) + continue; + SuperByteBuffer shaft = CachedBufferer.partialFacing(AllPartialModels.SHAFT_HALF, be.getBlockState(), d); + kineticRotationTransform(shaft, be, axis, angle, light); + shaft.renderInto(ms, buffer.getBuffer(RenderType.solid())); + } + } + + @Override + protected SuperByteBuffer getRotatedModel(SimpleKineticBlockEntity be, BlockState state) { + return CachedBufferer.partialFacingVertical( + large ? AllPartialModels.SHAFTLESS_LARGE_COGWHEEL : AllPartialModels.SHAFTLESS_COGWHEEL, state, + Direction.fromAxisAndDirection(state.getValue(EncasedCogwheelBlock.AXIS), AxisDirection.POSITIVE)); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/EncasedCogwheelBlock.java b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/encased/EncasedCogwheelBlock.java similarity index 83% rename from src/main/java/com/simibubi/create/content/contraptions/relays/encased/EncasedCogwheelBlock.java rename to src/main/java/com/simibubi/create/content/kinetics/simpleRelays/encased/EncasedCogwheelBlock.java index 686758056..b4d83eeca 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/EncasedCogwheelBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/encased/EncasedCogwheelBlock.java @@ -1,21 +1,21 @@ -package com.simibubi.create.content.contraptions.relays.encased; +package com.simibubi.create.content.kinetics.simpleRelays.encased; import java.util.function.Supplier; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.IRotate; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.ITransformableBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform; -import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock; -import com.simibubi.create.content.contraptions.relays.elementary.EncasedBlock; -import com.simibubi.create.content.contraptions.relays.elementary.ICogWheel; -import com.simibubi.create.content.contraptions.relays.elementary.SimpleKineticTileEntity; -import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement; -import com.simibubi.create.content.schematics.ItemRequirement; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.content.contraptions.ITransformableBlock; +import com.simibubi.create.content.contraptions.StructureTransform; +import com.simibubi.create.content.decoration.encasing.EncasedBlock; +import com.simibubi.create.content.kinetics.base.IRotate; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.base.RotatedPillarKineticBlock; +import com.simibubi.create.content.kinetics.simpleRelays.CogWheelBlock; +import com.simibubi.create.content.kinetics.simpleRelays.ICogWheel; +import com.simibubi.create.content.kinetics.simpleRelays.SimpleKineticBlockEntity; +import com.simibubi.create.content.schematics.requirement.ISpecialBlockItemRequirement; +import com.simibubi.create.content.schematics.requirement.ItemRequirement; +import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.VoxelShaper; @@ -44,7 +44,7 @@ import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; public class EncasedCogwheelBlock extends RotatedPillarKineticBlock - implements ICogWheel, ITE, ISpecialBlockItemRequirement, ITransformableBlock, EncasedBlock { + implements ICogWheel, IBE, ISpecialBlockItemRequirement, ITransformableBlock, EncasedBlock { public static final BooleanProperty TOP_SHAFT = BooleanProperty.create("top_shaft"); public static final BooleanProperty BOTTOM_SHAFT = BooleanProperty.create("bottom_shaft"); @@ -105,7 +105,7 @@ public class EncasedCogwheelBlock extends RotatedPillarKineticBlock return InteractionResult.SUCCESS; BlockPos pos = context.getClickedPos(); - KineticTileEntity.switchToBlockState(level, pos, state.cycle(context.getClickedFace() + KineticBlockEntity.switchToBlockState(level, pos, state.cycle(context.getClickedFace() .getAxisDirection() == AxisDirection.POSITIVE ? TOP_SHAFT : BOTTOM_SHAFT)); playRotateSound(level, pos); return InteractionResult.SUCCESS; @@ -127,7 +127,7 @@ public class EncasedCogwheelBlock extends RotatedPillarKineticBlock return InteractionResult.SUCCESS; context.getLevel() .levelEvent(2001, context.getClickedPos(), Block.getId(state)); - KineticTileEntity.switchToBlockState(context.getLevel(), context.getClickedPos(), + KineticBlockEntity.switchToBlockState(context.getLevel(), context.getClickedPos(), (isLarge ? AllBlocks.LARGE_COGWHEEL : AllBlocks.COGWHEEL).getDefaultState() .setValue(AXIS, state.getValue(AXIS))); return InteractionResult.SUCCESS; @@ -247,19 +247,19 @@ public class EncasedCogwheelBlock extends RotatedPillarKineticBlock } @Override - public ItemRequirement getRequiredItems(BlockState state, BlockEntity te) { + public ItemRequirement getRequiredItems(BlockState state, BlockEntity be) { return ItemRequirement - .of(isLarge ? AllBlocks.LARGE_COGWHEEL.getDefaultState() : AllBlocks.COGWHEEL.getDefaultState(), te); + .of(isLarge ? AllBlocks.LARGE_COGWHEEL.getDefaultState() : AllBlocks.COGWHEEL.getDefaultState(), be); } @Override - public Class getTileEntityClass() { - return SimpleKineticTileEntity.class; + public Class getBlockEntityClass() { + return SimpleKineticBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return isLarge ? AllTileEntities.ENCASED_LARGE_COGWHEEL.get() : AllTileEntities.ENCASED_COGWHEEL.get(); + public BlockEntityType getBlockEntityType() { + return isLarge ? AllBlockEntityTypes.ENCASED_LARGE_COGWHEEL.get() : AllBlockEntityTypes.ENCASED_COGWHEEL.get(); } @Override @@ -285,6 +285,6 @@ public class EncasedCogwheelBlock extends RotatedPillarKineticBlock : EncasedCogwheelBlock.BOTTOM_SHAFT); } - KineticTileEntity.switchToBlockState(level, pos, encasedState); + KineticBlockEntity.switchToBlockState(level, pos, encasedState); } } diff --git a/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/encased/EncasedShaftBlock.java b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/encased/EncasedShaftBlock.java new file mode 100644 index 000000000..584bc197c --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/simpleRelays/encased/EncasedShaftBlock.java @@ -0,0 +1,86 @@ +package com.simibubi.create.content.kinetics.simpleRelays.encased; + +import java.util.function.Supplier; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.decoration.encasing.EncasedBlock; +import com.simibubi.create.content.kinetics.base.AbstractEncasedShaftBlock; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.base.RotatedPillarKineticBlock; +import com.simibubi.create.content.schematics.requirement.ISpecialBlockItemRequirement; +import com.simibubi.create.content.schematics.requirement.ItemRequirement; +import com.simibubi.create.foundation.block.IBE; + +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.item.ItemStack; +import net.minecraft.world.item.context.UseOnContext; +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.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.HitResult; + +public class EncasedShaftBlock extends AbstractEncasedShaftBlock + implements IBE, ISpecialBlockItemRequirement, EncasedBlock { + + private final Supplier casing; + + public EncasedShaftBlock(Properties properties, Supplier casing) { + super(properties); + this.casing = casing; + } + + @Override + public InteractionResult onSneakWrenched(BlockState state, UseOnContext context) { + if (context.getLevel().isClientSide) + return InteractionResult.SUCCESS; + context.getLevel() + .levelEvent(2001, context.getClickedPos(), Block.getId(state)); + KineticBlockEntity.switchToBlockState(context.getLevel(), context.getClickedPos(), + AllBlocks.SHAFT.getDefaultState() + .setValue(AXIS, state.getValue(AXIS))); + return InteractionResult.SUCCESS; + } + + @Override + public ItemStack getCloneItemStack(BlockState state, HitResult target, BlockGetter world, BlockPos pos, Player player) { + if (target instanceof BlockHitResult) + return ((BlockHitResult) target).getDirection() + .getAxis() == getRotationAxis(state) ? AllBlocks.SHAFT.asStack() : getCasing().asItem().getDefaultInstance(); + return super.getCloneItemStack(state, target, world, pos, player); + } + + @Override + public ItemRequirement getRequiredItems(BlockState state, BlockEntity be) { + return ItemRequirement.of(AllBlocks.SHAFT.getDefaultState(), be); + } + + @Override + public Class getBlockEntityClass() { + return KineticBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.ENCASED_SHAFT.get(); + } + + @Override + public Block getCasing() { + return casing.get(); + } + + @Override + public void handleEncasing(BlockState state, Level level, BlockPos pos, ItemStack heldItem, Player player, InteractionHand hand, + BlockHitResult ray) { + KineticBlockEntity.switchToBlockState(level, pos, defaultBlockState() + .setValue(RotatedPillarKineticBlock.AXIS, state.getValue(RotatedPillarKineticBlock.AXIS))); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/SpeedControllerBlock.java b/src/main/java/com/simibubi/create/content/kinetics/speedController/SpeedControllerBlock.java similarity index 78% rename from src/main/java/com/simibubi/create/content/contraptions/relays/advanced/SpeedControllerBlock.java rename to src/main/java/com/simibubi/create/content/kinetics/speedController/SpeedControllerBlock.java index 681b117d9..911951c6c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/SpeedControllerBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/speedController/SpeedControllerBlock.java @@ -1,19 +1,19 @@ -package com.simibubi.create.content.contraptions.relays.advanced; +package com.simibubi.create.content.kinetics.speedController; import java.util.function.Predicate; import javax.annotation.ParametersAreNonnullByDefault; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.HorizontalAxisKineticBlock; -import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock; -import com.simibubi.create.content.contraptions.relays.elementary.ICogWheel; -import com.simibubi.create.foundation.block.ITE; -import com.simibubi.create.foundation.utility.placement.IPlacementHelper; -import com.simibubi.create.foundation.utility.placement.PlacementHelpers; -import com.simibubi.create.foundation.utility.placement.PlacementOffset; +import com.simibubi.create.content.kinetics.base.HorizontalAxisKineticBlock; +import com.simibubi.create.content.kinetics.simpleRelays.CogWheelBlock; +import com.simibubi.create.content.kinetics.simpleRelays.ICogWheel; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.placement.IPlacementHelper; +import com.simibubi.create.foundation.placement.PlacementHelpers; +import com.simibubi.create.foundation.placement.PlacementOffset; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; @@ -35,7 +35,7 @@ import net.minecraft.world.phys.shapes.VoxelShape; @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault -public class SpeedControllerBlock extends HorizontalAxisKineticBlock implements ITE { +public class SpeedControllerBlock extends HorizontalAxisKineticBlock implements IBE { private static final int placementHelperId = PlacementHelpers.register(new PlacementHelper()); @@ -58,7 +58,7 @@ public class SpeedControllerBlock extends HorizontalAxisKineticBlock implements public void neighborChanged(BlockState state, Level world, BlockPos pos, Block p_220069_4_, BlockPos neighbourPos, boolean p_220069_6_) { if (neighbourPos.equals(pos.above())) - withTileEntityDo(world, pos, SpeedControllerTileEntity::updateBracket); + withBlockEntityDo(world, pos, SpeedControllerBlockEntity::updateBracket); } @Override @@ -108,12 +108,12 @@ public class SpeedControllerBlock extends HorizontalAxisKineticBlock implements } @Override - public Class getTileEntityClass() { - return SpeedControllerTileEntity.class; + public Class getBlockEntityClass() { + return SpeedControllerBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.ROTATION_SPEED_CONTROLLER.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.ROTATION_SPEED_CONTROLLER.get(); } } diff --git a/src/main/java/com/simibubi/create/content/kinetics/speedController/SpeedControllerBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/speedController/SpeedControllerBlockEntity.java new file mode 100644 index 000000000..b76ecf974 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/speedController/SpeedControllerBlockEntity.java @@ -0,0 +1,173 @@ +package com.simibubi.create.content.kinetics.speedController; + +import java.util.List; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.compat.computercraft.AbstractComputerBehaviour; +import com.simibubi.create.compat.computercraft.ComputerCraftProxy; +import com.simibubi.create.content.kinetics.RotationPropagator; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.motor.KineticScrollValueBehaviour; +import com.simibubi.create.content.kinetics.simpleRelays.CogWheelBlock; +import com.simibubi.create.content.kinetics.simpleRelays.ICogWheel; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; +import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollValueBehaviour; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; + +public class SpeedControllerBlockEntity extends KineticBlockEntity { + + public static final int DEFAULT_SPEED = 16; + public ScrollValueBehaviour targetSpeed; + public AbstractComputerBehaviour computerBehaviour; + + boolean hasBracket; + + public SpeedControllerBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + hasBracket = false; + } + + @Override + public void lazyTick() { + super.lazyTick(); + updateBracket(); + } + + @Override + public void addBehaviours(List behaviours) { + super.addBehaviours(behaviours); + Integer max = AllConfigs.server().kinetics.maxRotationSpeed.get(); + + targetSpeed = new KineticScrollValueBehaviour(Lang.translateDirect("kinetics.speed_controller.rotation_speed"), + this, new ControllerValueBoxTransform()); + targetSpeed.between(-max, max); + targetSpeed.value = DEFAULT_SPEED; + targetSpeed.withCallback(i -> this.updateTargetRotation()); + behaviours.add(targetSpeed); + behaviours.add(computerBehaviour = ComputerCraftProxy.behaviour(this)); + + registerAwardables(behaviours, AllAdvancements.SPEED_CONTROLLER); + } + + private void updateTargetRotation() { + if (hasNetwork()) + getOrCreateNetwork().remove(this); + RotationPropagator.handleRemoved(level, worldPosition, this); + removeSource(); + attachKinetics(); + + if (isCogwheelPresent() && getSpeed() != 0) + award(AllAdvancements.SPEED_CONTROLLER); + } + + public static float getConveyedSpeed(KineticBlockEntity cogWheel, KineticBlockEntity speedControllerIn, + boolean targetingController) { + if (!(speedControllerIn instanceof SpeedControllerBlockEntity)) + return 0; + + float speed = speedControllerIn.getTheoreticalSpeed(); + float wheelSpeed = cogWheel.getTheoreticalSpeed(); + float desiredOutputSpeed = getDesiredOutputSpeed(cogWheel, speedControllerIn, targetingController); + + float compareSpeed = targetingController ? speed : wheelSpeed; + if (desiredOutputSpeed >= 0 && compareSpeed >= 0) + return Math.max(desiredOutputSpeed, compareSpeed); + if (desiredOutputSpeed < 0 && compareSpeed < 0) + return Math.min(desiredOutputSpeed, compareSpeed); + + return desiredOutputSpeed; + } + + public static float getDesiredOutputSpeed(KineticBlockEntity cogWheel, KineticBlockEntity speedControllerIn, + boolean targetingController) { + SpeedControllerBlockEntity speedController = (SpeedControllerBlockEntity) speedControllerIn; + float targetSpeed = speedController.targetSpeed.getValue(); + float speed = speedControllerIn.getTheoreticalSpeed(); + float wheelSpeed = cogWheel.getTheoreticalSpeed(); + + if (targetSpeed == 0) + return 0; + if (targetingController && wheelSpeed == 0) + return 0; + if (!speedController.hasSource()) { + if (targetingController) + return targetSpeed; + return 0; + } + + boolean wheelPowersController = speedController.source.equals(cogWheel.getBlockPos()); + + if (wheelPowersController) { + if (targetingController) + return targetSpeed; + return wheelSpeed; + } + + if (targetingController) + return speed; + return targetSpeed; + } + + public void updateBracket() { + if (level != null && level.isClientSide) + hasBracket = isCogwheelPresent(); + } + + private boolean isCogwheelPresent() { + BlockState stateAbove = level.getBlockState(worldPosition.above()); + return ICogWheel.isDedicatedCogWheel(stateAbove.getBlock()) && ICogWheel.isLargeCog(stateAbove) + && stateAbove.getValue(CogWheelBlock.AXIS) + .isHorizontal(); + } + + @NotNull + @Override + public LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction side) { + if (computerBehaviour.isPeripheralCap(cap)) + return computerBehaviour.getPeripheralCapability(); + return super.getCapability(cap, side); + } + + @Override + public void invalidateCaps() { + super.invalidateCaps(); + computerBehaviour.removePeripheral(); + } + + private class ControllerValueBoxTransform extends ValueBoxTransform.Sided { + + @Override + protected Vec3 getSouthLocation() { + return VecHelper.voxelSpace(8, 11f, 15.5f); + } + + @Override + protected boolean isSideActive(BlockState state, Direction direction) { + if (direction.getAxis() + .isVertical()) + return false; + return state.getValue(SpeedControllerBlock.HORIZONTAL_AXIS) != direction.getAxis(); + } + + @Override + public float getScale() { + return 0.5f; + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/speedController/SpeedControllerRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/speedController/SpeedControllerRenderer.java new file mode 100644 index 000000000..a4a57086d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/speedController/SpeedControllerRenderer.java @@ -0,0 +1,59 @@ +package com.simibubi.create.content.kinetics.speedController; + +import com.jozufozu.flywheel.backend.Backend; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.foundation.blockEntity.renderer.SmartBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; + +import net.minecraft.client.renderer.LevelRenderer; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; + +public class SpeedControllerRenderer extends SmartBlockEntityRenderer { + + public SpeedControllerRenderer(BlockEntityRendererProvider.Context context) { + super(context); + } + + @Override + protected void renderSafe(SpeedControllerBlockEntity blockEntity, float partialTicks, PoseStack ms, + MultiBufferSource buffer, int light, int overlay) { + super.renderSafe(blockEntity, partialTicks, ms, buffer, light, overlay); + + VertexConsumer builder = buffer.getBuffer(RenderType.solid()); + if (!Backend.canUseInstancing(blockEntity.getLevel())) { + KineticBlockEntityRenderer.renderRotatingBuffer(blockEntity, getRotatedModel(blockEntity), ms, builder, light); + } + + if (!blockEntity.hasBracket) + return; + + BlockPos pos = blockEntity.getBlockPos(); + Level world = blockEntity.getLevel(); + BlockState blockState = blockEntity.getBlockState(); + boolean alongX = blockState.getValue(SpeedControllerBlock.HORIZONTAL_AXIS) == Axis.X; + + SuperByteBuffer bracket = CachedBufferer.partial(AllPartialModels.SPEED_CONTROLLER_BRACKET, blockState); + bracket.translate(0, 1, 0); + bracket.rotateCentered(Direction.UP, + (float) (alongX ? Math.PI : Math.PI / 2)); + bracket.light(LevelRenderer.getLightColor(world, pos.above())); + bracket.renderInto(ms, builder); + } + + private SuperByteBuffer getRotatedModel(SpeedControllerBlockEntity blockEntity) { + return CachedBufferer.block(KineticBlockEntityRenderer.KINETIC_BLOCK, + KineticBlockEntityRenderer.shaft(KineticBlockEntityRenderer.getRotationAxisOf(blockEntity))); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/steam/PoweredShaftBlock.java b/src/main/java/com/simibubi/create/content/kinetics/steamEngine/PoweredShaftBlock.java similarity index 85% rename from src/main/java/com/simibubi/create/content/contraptions/components/steam/PoweredShaftBlock.java rename to src/main/java/com/simibubi/create/content/kinetics/steamEngine/PoweredShaftBlock.java index f5378a633..0e59ef17f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/steam/PoweredShaftBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/steamEngine/PoweredShaftBlock.java @@ -1,14 +1,14 @@ -package com.simibubi.create.content.contraptions.components.steam; +package com.simibubi.create.content.kinetics.steamEngine; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.relays.elementary.AbstractShaftBlock; -import com.simibubi.create.content.contraptions.relays.elementary.ShaftBlock; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.simpleRelays.AbstractShaftBlock; +import com.simibubi.create.content.kinetics.simpleRelays.ShaftBlock; +import com.simibubi.create.foundation.placement.IPlacementHelper; +import com.simibubi.create.foundation.placement.PlacementHelpers; import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.placement.IPlacementHelper; -import com.simibubi.create.foundation.utility.placement.PlacementHelpers; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -41,8 +41,8 @@ public class PoweredShaftBlock extends AbstractShaftBlock { } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.POWERED_SHAFT.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.POWERED_SHAFT.get(); } @Override diff --git a/src/main/java/com/simibubi/create/content/kinetics/steamEngine/PoweredShaftBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/steamEngine/PoweredShaftBlockEntity.java new file mode 100644 index 000000000..98685d5e7 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/steamEngine/PoweredShaftBlockEntity.java @@ -0,0 +1,140 @@ +package com.simibubi.create.content.kinetics.steamEngine; + +import java.util.List; + +import com.simibubi.create.content.kinetics.BlockStressValues; +import com.simibubi.create.content.kinetics.base.GeneratingKineticBlockEntity; +import com.simibubi.create.foundation.utility.RegisteredObjects; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction.Axis; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.registries.ForgeRegistries; + +public class PoweredShaftBlockEntity extends GeneratingKineticBlockEntity { + + public BlockPos enginePos; + public float engineEfficiency; + public int movementDirection; + public int initialTicks; + public Block capacityKey; + + public PoweredShaftBlockEntity(BlockEntityType typeIn, BlockPos pos, BlockState state) { + super(typeIn, pos, state); + movementDirection = 1; + initialTicks = 3; + } + + @Override + public void tick() { + super.tick(); + if (initialTicks > 0) + initialTicks--; + } + + public void update(BlockPos sourcePos, int direction, float efficiency) { + BlockPos key = worldPosition.subtract(sourcePos); + enginePos = key; + float prev = engineEfficiency; + engineEfficiency = efficiency; + int prevDirection = this.movementDirection; + if (Mth.equal(efficiency, prev) && prevDirection == direction) + return; + + capacityKey = level.getBlockState(sourcePos) + .getBlock(); + this.movementDirection = direction; + updateGeneratedRotation(); + } + + public void remove(BlockPos sourcePos) { + if (!isPoweredBy(sourcePos)) + return; + + enginePos = null; + engineEfficiency = 0; + movementDirection = 0; + capacityKey = null; + updateGeneratedRotation(); + } + + public boolean canBePoweredBy(BlockPos globalPos) { + return initialTicks == 0 && (enginePos == null || isPoweredBy(globalPos)); + } + + public boolean isPoweredBy(BlockPos globalPos) { + BlockPos key = worldPosition.subtract(globalPos); + return key.equals(enginePos); + } + + @Override + protected void write(CompoundTag compound, boolean clientPacket) { + compound.putInt("Direction", movementDirection); + if (initialTicks > 0) + compound.putInt("Warmup", initialTicks); + if (enginePos != null && capacityKey != null) { + compound.put("EnginePos", NbtUtils.writeBlockPos(enginePos)); + compound.putFloat("EnginePower", engineEfficiency); + compound.putString("EngineType", RegisteredObjects.getKeyOrThrow(capacityKey) + .toString()); + } + super.write(compound, clientPacket); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + super.read(compound, clientPacket); + movementDirection = compound.getInt("Direction"); + initialTicks = compound.getInt("Warmup"); + enginePos = null; + engineEfficiency = 0; + if (compound.contains("EnginePos")) { + enginePos = NbtUtils.readBlockPos(compound.getCompound("EnginePos")); + engineEfficiency = compound.getFloat("EnginePower"); + capacityKey = ForgeRegistries.BLOCKS.getValue(new ResourceLocation(compound.getString("EngineType"))); + } + } + + @Override + public float getGeneratedSpeed() { + return getCombinedCapacity() > 0 ? movementDirection * 16 * getSpeedModifier() : 0; + } + + private float getCombinedCapacity() { + return capacityKey == null ? 0 : (float) (engineEfficiency * BlockStressValues.getCapacity(capacityKey)); + } + + private int getSpeedModifier() { + return (int) (1 + (engineEfficiency >= 1 ? 3 : Math.min(2, Math.floor(engineEfficiency * 4)))); + } + + @Override + public float calculateAddedStressCapacity() { + float capacity = getCombinedCapacity() / getSpeedModifier(); + this.lastCapacityProvided = capacity; + return capacity; + } + + @Override + public int getRotationAngleOffset(Axis axis) { + int combinedCoords = axis.choose(worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()); + return super.getRotationAngleOffset(axis) + (combinedCoords % 2 == 0 ? 180 : 0); + } + + @Override + public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { + return false; + } + + public boolean addToEngineTooltip(List tooltip, boolean isPlayerSneaking) { + return super.addToGoggleTooltip(tooltip, isPlayerSneaking); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/steam/SteamEngineBlock.java b/src/main/java/com/simibubi/create/content/kinetics/steamEngine/SteamEngineBlock.java similarity index 89% rename from src/main/java/com/simibubi/create/content/contraptions/components/steam/SteamEngineBlock.java rename to src/main/java/com/simibubi/create/content/kinetics/steamEngine/SteamEngineBlock.java index e6df5d808..92f8f6d53 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/steam/SteamEngineBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/steamEngine/SteamEngineBlock.java @@ -1,22 +1,22 @@ -package com.simibubi.create.content.contraptions.components.steam; +package com.simibubi.create.content.kinetics.steamEngine; import static net.minecraft.world.level.block.state.properties.BlockStateProperties.WATERLOGGED; import java.util.function.Predicate; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.fluids.tank.FluidTankBlock; -import com.simibubi.create.content.contraptions.relays.elementary.ShaftBlock; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.content.fluids.tank.FluidTankBlock; +import com.simibubi.create.content.kinetics.simpleRelays.ShaftBlock; import com.simibubi.create.foundation.advancement.AdvancementBehaviour; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.placement.IPlacementHelper; +import com.simibubi.create.foundation.placement.PlacementHelpers; +import com.simibubi.create.foundation.placement.PlacementOffset; import com.simibubi.create.foundation.utility.BlockHelper; import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.placement.IPlacementHelper; -import com.simibubi.create.foundation.utility.placement.PlacementHelpers; -import com.simibubi.create.foundation.utility.placement.PlacementOffset; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; @@ -48,7 +48,7 @@ import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; public class SteamEngineBlock extends FaceAttachedHorizontalDirectionalBlock - implements SimpleWaterloggedBlock, IWrenchable, ITE { + implements SimpleWaterloggedBlock, IWrenchable, IBE { private static final int placementHelperId = PlacementHelpers.register(new PlacementHelper()); @@ -163,13 +163,13 @@ public class SteamEngineBlock extends FaceAttachedHorizontalDirectionalBlock } @Override - public Class getTileEntityClass() { - return SteamEngineTileEntity.class; + public Class getBlockEntityClass() { + return SteamEngineBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.STEAM_ENGINE.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.STEAM_ENGINE.get(); } @MethodsReturnNonnullByDefault diff --git a/src/main/java/com/simibubi/create/content/kinetics/steamEngine/SteamEngineBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/steamEngine/SteamEngineBlockEntity.java new file mode 100644 index 000000000..f0dd30fcd --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/steamEngine/SteamEngineBlockEntity.java @@ -0,0 +1,269 @@ +package com.simibubi.create.content.kinetics.steamEngine; + +import java.lang.ref.WeakReference; +import java.util.List; + +import javax.annotation.Nullable; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.content.contraptions.bearing.WindmillBearingBlockEntity.RotationDirection; +import com.simibubi.create.content.equipment.goggles.IHaveGoggleInformation; +import com.simibubi.create.content.fluids.tank.FluidTankBlockEntity; +import com.simibubi.create.content.kinetics.base.GeneratingKineticBlockEntity; +import com.simibubi.create.content.kinetics.base.IRotate; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollOptionBehaviour; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.network.chat.Component; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.util.Mth; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.fml.DistExecutor; + +public class SteamEngineBlockEntity extends SmartBlockEntity implements IHaveGoggleInformation { + + protected ScrollOptionBehaviour movementDirection; + + public WeakReference target; + public WeakReference source; + + public SteamEngineBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + source = new WeakReference<>(null); + target = new WeakReference<>(null); + } + + @Override + public void addBehaviours(List behaviours) { + movementDirection = new ScrollOptionBehaviour<>(RotationDirection.class, + Lang.translateDirect("contraptions.windmill.rotation_direction"), this, new SteamEngineValueBox()); + movementDirection.onlyActiveWhen(() -> { + PoweredShaftBlockEntity shaft = getShaft(); + return shaft == null || !shaft.hasSource(); + }); + movementDirection.withCallback($ -> onDirectionChanged()); + behaviours.add(movementDirection); + + registerAwardables(behaviours, AllAdvancements.STEAM_ENGINE); + } + + private void onDirectionChanged() {} + + @Override + public void tick() { + super.tick(); + FluidTankBlockEntity tank = getTank(); + PoweredShaftBlockEntity shaft = getShaft(); + + if (tank == null || shaft == null) { + if (level.isClientSide()) + return; + if (shaft == null) + return; + if (!shaft.getBlockPos() + .subtract(worldPosition) + .equals(shaft.enginePos)) + return; + if (shaft.engineEfficiency == 0) + return; + Direction facing = SteamEngineBlock.getFacing(getBlockState()); + if (level.isLoaded(worldPosition.relative(facing.getOpposite()))) + shaft.update(worldPosition, 0, 0); + return; + } + + boolean verticalTarget = false; + BlockState shaftState = shaft.getBlockState(); + Axis targetAxis = Axis.X; + if (shaftState.getBlock()instanceof IRotate ir) + targetAxis = ir.getRotationAxis(shaftState); + verticalTarget = targetAxis == Axis.Y; + + BlockState blockState = getBlockState(); + if (!AllBlocks.STEAM_ENGINE.has(blockState)) + return; + Direction facing = SteamEngineBlock.getFacing(blockState); + if (facing.getAxis() == Axis.Y) + facing = blockState.getValue(SteamEngineBlock.FACING); + + float efficiency = Mth.clamp(tank.boiler.getEngineEfficiency(tank.getTotalTankSize()), 0, 1); + if (efficiency > 0) + + award(AllAdvancements.STEAM_ENGINE); + + int conveyedSpeedLevel = + efficiency == 0 ? 1 : verticalTarget ? 1 : (int) GeneratingKineticBlockEntity.convertToDirection(1, facing); + if (targetAxis == Axis.Z) + conveyedSpeedLevel *= -1; + if (movementDirection.get() == RotationDirection.COUNTER_CLOCKWISE) + conveyedSpeedLevel *= -1; + + float shaftSpeed = shaft.getTheoreticalSpeed(); + if (shaft.hasSource() && shaftSpeed != 0 && conveyedSpeedLevel != 0 + && (shaftSpeed > 0) != (conveyedSpeedLevel > 0)) { + movementDirection.setValue(1 - movementDirection.get() + .ordinal()); + conveyedSpeedLevel *= -1; + } + + shaft.update(worldPosition, conveyedSpeedLevel, efficiency); + + if (!level.isClientSide) + return; + + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> this::spawnParticles); + } + + @Override + public void remove() { + PoweredShaftBlockEntity shaft = getShaft(); + if (shaft != null) + shaft.remove(worldPosition); + super.remove(); + } + + @Override + @OnlyIn(Dist.CLIENT) + protected AABB createRenderBoundingBox() { + return super.createRenderBoundingBox().inflate(2); + } + + public PoweredShaftBlockEntity getShaft() { + PoweredShaftBlockEntity shaft = target.get(); + if (shaft == null || shaft.isRemoved() || !shaft.canBePoweredBy(worldPosition)) { + if (shaft != null) + target = new WeakReference<>(null); + Direction facing = SteamEngineBlock.getFacing(getBlockState()); + BlockEntity anyShaftAt = level.getBlockEntity(worldPosition.relative(facing, 2)); + if (anyShaftAt instanceof PoweredShaftBlockEntity ps && ps.canBePoweredBy(worldPosition)) + target = new WeakReference<>(shaft = ps); + } + return shaft; + } + + public FluidTankBlockEntity getTank() { + FluidTankBlockEntity tank = source.get(); + if (tank == null || tank.isRemoved()) { + if (tank != null) + source = new WeakReference<>(null); + Direction facing = SteamEngineBlock.getFacing(getBlockState()); + BlockEntity be = level.getBlockEntity(worldPosition.relative(facing.getOpposite())); + if (be instanceof FluidTankBlockEntity tankBe) + source = new WeakReference<>(tank = tankBe); + } + if (tank == null) + return null; + return tank.getControllerBE(); + } + + float prevAngle = 0; + + @OnlyIn(Dist.CLIENT) + private void spawnParticles() { + Float targetAngle = getTargetAngle(); + PoweredShaftBlockEntity ste = target.get(); + if (ste == null) + return; + if (!ste.isPoweredBy(worldPosition) || ste.engineEfficiency == 0) + return; + if (targetAngle == null) + return; + + float angle = AngleHelper.deg(targetAngle); + angle += (angle < 0) ? -180 + 75 : 360 - 75; + angle %= 360; + + PoweredShaftBlockEntity shaft = getShaft(); + if (shaft == null || shaft.getSpeed() == 0) + return; + + if (angle >= 0 && !(prevAngle > 180 && angle < 180)) { + prevAngle = angle; + return; + } + if (angle < 0 && !(prevAngle < -180 && angle > -180)) { + prevAngle = angle; + return; + } + + FluidTankBlockEntity sourceBE = source.get(); + if (sourceBE != null) { + FluidTankBlockEntity controller = sourceBE.getControllerBE(); + if (controller != null && controller.boiler != null) { + float volume = 3f / Math.max(2, controller.boiler.attachedEngines / 6); + float pitch = 1.18f - level.random.nextFloat() * .25f; + level.playLocalSound(worldPosition.getX(), worldPosition.getY(), worldPosition.getZ(), + SoundEvents.CANDLE_EXTINGUISH, SoundSource.BLOCKS, volume, pitch, false); + AllSoundEvents.STEAM.playAt(level, worldPosition, volume / 16, .8f, false); + } + } + + Direction facing = SteamEngineBlock.getFacing(getBlockState()); + + Vec3 offset = VecHelper.rotate(new Vec3(0, 0, 1).add(VecHelper.offsetRandomly(Vec3.ZERO, level.random, 1) + .multiply(1, 1, 0) + .normalize() + .scale(.5f)), AngleHelper.verticalAngle(facing), Axis.X); + offset = VecHelper.rotate(offset, AngleHelper.horizontalAngle(facing), Axis.Y); + Vec3 v = offset.scale(.5f) + .add(Vec3.atCenterOf(worldPosition)); + Vec3 m = offset.subtract(Vec3.atLowerCornerOf(facing.getNormal()) + .scale(.75f)); + level.addParticle(new SteamJetParticleData(1), v.x, v.y, v.z, m.x, m.y, m.z); + + prevAngle = angle; + } + + @Nullable + @OnlyIn(Dist.CLIENT) + public Float getTargetAngle() { + float angle = 0; + BlockState blockState = getBlockState(); + if (!AllBlocks.STEAM_ENGINE.has(blockState)) + return null; + + Direction facing = SteamEngineBlock.getFacing(blockState); + PoweredShaftBlockEntity shaft = getShaft(); + Axis facingAxis = facing.getAxis(); + Axis axis = Axis.Y; + + if (shaft == null) + return null; + + axis = KineticBlockEntityRenderer.getRotationAxisOf(shaft); + angle = KineticBlockEntityRenderer.getAngleForTe(shaft, shaft.getBlockPos(), axis); + + if (axis == facingAxis) + return null; + if (axis.isHorizontal() && (facingAxis == Axis.X ^ facing.getAxisDirection() == AxisDirection.POSITIVE)) + angle *= -1; + if (axis == Axis.X && facing == Direction.DOWN) + angle *= -1; + return angle; + } + + @Override + public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { + PoweredShaftBlockEntity shaft = getShaft(); + return shaft == null ? false : shaft.addToEngineTooltip(tooltip, isPlayerSneaking); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/steam/SteamEngineInstance.java b/src/main/java/com/simibubi/create/content/kinetics/steamEngine/SteamEngineInstance.java similarity index 81% rename from src/main/java/com/simibubi/create/content/contraptions/components/steam/SteamEngineInstance.java rename to src/main/java/com/simibubi/create/content/kinetics/steamEngine/SteamEngineInstance.java index 2313e9039..b65ce3742 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/steam/SteamEngineInstance.java +++ b/src/main/java/com/simibubi/create/content/kinetics/steamEngine/SteamEngineInstance.java @@ -1,38 +1,38 @@ -package com.simibubi.create.content.contraptions.components.steam; +package com.simibubi.create.content.kinetics.steamEngine; import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.api.instance.DynamicInstance; import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance; import com.jozufozu.flywheel.core.Materials; import com.jozufozu.flywheel.core.materials.model.ModelData; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; import com.simibubi.create.foundation.utility.AngleHelper; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; import net.minecraft.util.Mth; -public class SteamEngineInstance extends BlockEntityInstance implements DynamicInstance { +public class SteamEngineInstance extends BlockEntityInstance implements DynamicInstance { protected final ModelData piston; protected final ModelData linkage; protected final ModelData connector; - public SteamEngineInstance(MaterialManager materialManager, SteamEngineTileEntity blockEntity) { + public SteamEngineInstance(MaterialManager materialManager, SteamEngineBlockEntity blockEntity) { super(materialManager, blockEntity); piston = materialManager.defaultSolid() .material(Materials.TRANSFORMED) - .getModel(AllBlockPartials.ENGINE_PISTON, blockState) + .getModel(AllPartialModels.ENGINE_PISTON, blockState) .createInstance(); linkage = materialManager.defaultSolid() .material(Materials.TRANSFORMED) - .getModel(AllBlockPartials.ENGINE_LINKAGE, blockState) + .getModel(AllPartialModels.ENGINE_LINKAGE, blockState) .createInstance(); connector = materialManager.defaultSolid() .material(Materials.TRANSFORMED) - .getModel(AllBlockPartials.ENGINE_CONNECTOR, blockState) + .getModel(AllPartialModels.ENGINE_CONNECTOR, blockState) .createInstance(); } @@ -50,9 +50,9 @@ public class SteamEngineInstance extends BlockEntityInstance { + + public SteamEngineRenderer(BlockEntityRendererProvider.Context context) {} + + @Override + protected void renderSafe(SteamEngineBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + if (Backend.canUseInstancing(be.getLevel())) + return; + + Float angle = be.getTargetAngle(); + if (angle == null) + return; + + BlockState blockState = be.getBlockState(); + Direction facing = SteamEngineBlock.getFacing(blockState); + Axis facingAxis = facing.getAxis(); + Axis axis = Axis.Y; + + PoweredShaftBlockEntity shaft = be.getShaft(); + if (shaft != null) + axis = KineticBlockEntityRenderer.getRotationAxisOf(shaft); + + boolean roll90 = facingAxis.isHorizontal() && axis == Axis.Y || facingAxis.isVertical() && axis == Axis.Z; + float sine = Mth.sin(angle); + float sine2 = Mth.sin(angle - Mth.HALF_PI); + float piston = ((1 - sine) / 4) * 24 / 16f; + + VertexConsumer vb = buffer.getBuffer(RenderType.solid()); + + transformed(AllPartialModels.ENGINE_PISTON, blockState, facing, roll90) + .translate(0, piston, 0) + .light(light) + .renderInto(ms, vb); + + transformed(AllPartialModels.ENGINE_LINKAGE, blockState, facing, roll90) + .centre() + .translate(0, 1, 0) + .unCentre() + .translate(0, piston, 0) + .translate(0, 4 / 16f, 8 / 16f) + .rotateX(sine2 * 23f) + .translate(0, -4 / 16f, -8 / 16f) + .light(light) + .renderInto(ms, vb); + + transformed(AllPartialModels.ENGINE_CONNECTOR, blockState, facing, roll90) + .translate(0, 2, 0) + .centre() + .rotateXRadians(-angle + Mth.HALF_PI) + .unCentre() + .light(light) + .renderInto(ms, vb); + } + + private SuperByteBuffer transformed(PartialModel model, BlockState blockState, Direction facing, boolean roll90) { + return CachedBufferer.partial(model, blockState) + .centre() + .rotateY(AngleHelper.horizontalAngle(facing)) + .rotateX(AngleHelper.verticalAngle(facing) + 90) + .rotateY(roll90 ? -90 : 0) + .unCentre(); + } + + @Override + public int getViewDistance() { + return 128; + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/steamEngine/SteamEngineValueBox.java b/src/main/java/com/simibubi/create/content/kinetics/steamEngine/SteamEngineValueBox.java new file mode 100644 index 000000000..a7ae50b05 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/steamEngine/SteamEngineValueBox.java @@ -0,0 +1,87 @@ +package com.simibubi.create.content.kinetics.steamEngine; + +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.Pointing; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class SteamEngineValueBox extends ValueBoxTransform.Sided { + + @Override + protected boolean isSideActive(BlockState state, Direction side) { + Direction engineFacing = SteamEngineBlock.getFacing(state); + if (engineFacing.getAxis() == side.getAxis()) + return false; + + float roll = 0; + for (Pointing p : Pointing.values()) + if (p.getCombinedDirection(engineFacing) == side) + roll = p.getXRotation(); + if (engineFacing == Direction.UP) + roll += 180; + + boolean recessed = roll % 180 == 0; + if (engineFacing.getAxis() == Axis.Y) + recessed ^= state.getValue(SteamEngineBlock.FACING) + .getAxis() == Axis.X; + + return !recessed; + } + + @Override + public Vec3 getLocalOffset(BlockState state) { + Direction side = getSide(); + Direction engineFacing = SteamEngineBlock.getFacing(state); + + float roll = 0; + for (Pointing p : Pointing.values()) + if (p.getCombinedDirection(engineFacing) == side) + roll = p.getXRotation(); + if (engineFacing == Direction.UP) + roll += 180; + + float horizontalAngle = AngleHelper.horizontalAngle(engineFacing); + float verticalAngle = AngleHelper.verticalAngle(engineFacing); + Vec3 local = VecHelper.voxelSpace(8, 14.5, 9); + + local = VecHelper.rotateCentered(local, roll, Axis.Z); + local = VecHelper.rotateCentered(local, horizontalAngle, Axis.Y); + local = VecHelper.rotateCentered(local, verticalAngle, Axis.X); + + return local; + } + + @Override + public void rotate(BlockState state, PoseStack ms) { + Direction facing = SteamEngineBlock.getFacing(state); + + if (facing.getAxis() == Axis.Y) { + super.rotate(state, ms); + return; + } + + float roll = 0; + for (Pointing p : Pointing.values()) + if (p.getCombinedDirection(facing) == getSide()) + roll = p.getXRotation(); + + float yRot = AngleHelper.horizontalAngle(facing) + (facing == Direction.DOWN ? 180 : 0); + TransformStack.cast(ms) + .rotateY(yRot) + .rotateX(facing == Direction.DOWN ? -90 : 90) + .rotateY(roll); + } + + @Override + protected Vec3 getSouthLocation() { + return Vec3.ZERO; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/steam/SteamJetParticle.java b/src/main/java/com/simibubi/create/content/kinetics/steamEngine/SteamJetParticle.java similarity index 98% rename from src/main/java/com/simibubi/create/content/contraptions/components/steam/SteamJetParticle.java rename to src/main/java/com/simibubi/create/content/kinetics/steamEngine/SteamJetParticle.java index 35030de4b..7bca4dd11 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/steam/SteamJetParticle.java +++ b/src/main/java/com/simibubi/create/content/kinetics/steamEngine/SteamJetParticle.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.steam; +package com.simibubi.create.content.kinetics.steamEngine; import org.joml.Quaternionf; import org.joml.Vector3f; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/steam/SteamJetParticleData.java b/src/main/java/com/simibubi/create/content/kinetics/steamEngine/SteamJetParticleData.java similarity index 93% rename from src/main/java/com/simibubi/create/content/contraptions/components/steam/SteamJetParticleData.java rename to src/main/java/com/simibubi/create/content/kinetics/steamEngine/SteamJetParticleData.java index 6b20e0405..263eccb5e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/steam/SteamJetParticleData.java +++ b/src/main/java/com/simibubi/create/content/kinetics/steamEngine/SteamJetParticleData.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.steam; +package com.simibubi.create.content.kinetics.steamEngine; import java.util.Locale; @@ -7,7 +7,7 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; import com.simibubi.create.AllParticleTypes; -import com.simibubi.create.content.contraptions.particle.ICustomParticleDataWithSprite; +import com.simibubi.create.foundation.particle.ICustomParticleDataWithSprite; import net.minecraft.client.particle.ParticleEngine.SpriteParticleRegistration; import net.minecraft.core.particles.ParticleOptions; diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/ClutchBlock.java b/src/main/java/com/simibubi/create/content/kinetics/transmission/ClutchBlock.java similarity index 77% rename from src/main/java/com/simibubi/create/content/contraptions/relays/encased/ClutchBlock.java rename to src/main/java/com/simibubi/create/content/kinetics/transmission/ClutchBlock.java index 9ad315163..8f356d778 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/ClutchBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/transmission/ClutchBlock.java @@ -1,6 +1,6 @@ -package com.simibubi.create.content.contraptions.relays.encased; +package com.simibubi.create.content.kinetics.transmission; -import com.simibubi.create.AllTileEntities; +import com.simibubi.create.AllBlockEntityTypes; import net.minecraft.core.BlockPos; import net.minecraft.world.level.Level; @@ -28,8 +28,8 @@ public class ClutchBlock extends GearshiftBlock { } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.CLUTCH.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.CLUTCH.get(); } } diff --git a/src/main/java/com/simibubi/create/content/kinetics/transmission/ClutchBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/transmission/ClutchBlockEntity.java new file mode 100644 index 000000000..86c10d86e --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/transmission/ClutchBlockEntity.java @@ -0,0 +1,24 @@ +package com.simibubi.create.content.kinetics.transmission; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; + +public class ClutchBlockEntity extends SplitShaftBlockEntity { + + public ClutchBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + public float getRotationSpeedModifier(Direction face) { + if (hasSource()) { + if (face != getSourceFacing() && getBlockState().getValue(BlockStateProperties.POWERED)) + return 0; + } + return 1; + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/transmission/GearshiftBlock.java b/src/main/java/com/simibubi/create/content/kinetics/transmission/GearshiftBlock.java new file mode 100644 index 000000000..b67d01d47 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/transmission/GearshiftBlock.java @@ -0,0 +1,86 @@ +package com.simibubi.create.content.kinetics.transmission; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.content.kinetics.RotationPropagator; +import com.simibubi.create.content.kinetics.base.AbstractEncasedShaftBlock; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.foundation.block.IBE; + +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.item.context.BlockPlaceContext; +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.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition.Builder; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.ticks.TickPriority; + +public class GearshiftBlock extends AbstractEncasedShaftBlock implements IBE { + + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; + + public GearshiftBlock(Properties properties) { + super(properties); + registerDefaultState(defaultBlockState().setValue(POWERED, false)); + } + + @Override + protected void createBlockStateDefinition(Builder builder) { + builder.add(POWERED); + super.createBlockStateDefinition(builder); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext context) { + return super.getStateForPlacement(context).setValue(POWERED, + context.getLevel().hasNeighborSignal(context.getClickedPos())); + } + + @Override + public void neighborChanged(BlockState state, Level worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, + boolean isMoving) { + if (worldIn.isClientSide) + return; + + boolean previouslyPowered = state.getValue(POWERED); + if (previouslyPowered != worldIn.hasNeighborSignal(pos)) { + detachKinetics(worldIn, pos, true); + worldIn.setBlock(pos, state.cycle(POWERED), 2); + } + } + + @Override + public Class getBlockEntityClass() { + return SplitShaftBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.GEARSHIFT.get(); + } + + public void detachKinetics(Level worldIn, BlockPos pos, boolean reAttachNextTick) { + BlockEntity be = worldIn.getBlockEntity(pos); + if (be == null || !(be instanceof KineticBlockEntity)) + return; + RotationPropagator.handleRemoved(worldIn, pos, (KineticBlockEntity) be); + + // Re-attach next tick + if (reAttachNextTick) + worldIn.scheduleTick(pos, this, 0, TickPriority.EXTREMELY_HIGH); + } + + @Override + public void tick(BlockState state, ServerLevel worldIn, BlockPos pos, RandomSource random) { + BlockEntity be = worldIn.getBlockEntity(pos); + if (be == null || !(be instanceof KineticBlockEntity)) + return; + KineticBlockEntity kte = (KineticBlockEntity) be; + RotationPropagator.handleAdded(worldIn, pos, kte); + } +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/transmission/GearshiftBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/transmission/GearshiftBlockEntity.java new file mode 100644 index 000000000..7147a07d2 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/transmission/GearshiftBlockEntity.java @@ -0,0 +1,24 @@ +package com.simibubi.create.content.kinetics.transmission; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; + +public class GearshiftBlockEntity extends SplitShaftBlockEntity { + + public GearshiftBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + public float getRotationSpeedModifier(Direction face) { + if (hasSource()) { + if (face != getSourceFacing() && getBlockState().getValue(BlockStateProperties.POWERED)) + return -1; + } + return 1; + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/transmission/SplitShaftBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/transmission/SplitShaftBlockEntity.java new file mode 100644 index 000000000..9c3d8e8f0 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/transmission/SplitShaftBlockEntity.java @@ -0,0 +1,18 @@ +package com.simibubi.create.content.kinetics.transmission; + +import com.simibubi.create.content.kinetics.base.DirectionalShaftHalvesBlockEntity; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; + +public abstract class SplitShaftBlockEntity extends DirectionalShaftHalvesBlockEntity { + + public SplitShaftBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + public abstract float getRotationSpeedModifier(Direction face); + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/transmission/SplitShaftInstance.java b/src/main/java/com/simibubi/create/content/kinetics/transmission/SplitShaftInstance.java new file mode 100644 index 000000000..1c5848359 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/transmission/SplitShaftInstance.java @@ -0,0 +1,64 @@ +package com.simibubi.create.content.kinetics.transmission; + +import java.util.ArrayList; + +import com.jozufozu.flywheel.api.InstanceData; +import com.jozufozu.flywheel.api.Instancer; +import com.jozufozu.flywheel.api.Material; +import com.jozufozu.flywheel.api.MaterialManager; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.IRotate; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityInstance; +import com.simibubi.create.content.kinetics.base.flwdata.RotatingData; +import com.simibubi.create.foundation.utility.Iterate; + +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.Block; + +public class SplitShaftInstance extends KineticBlockEntityInstance { + + protected final ArrayList keys; + + public SplitShaftInstance(MaterialManager modelManager, SplitShaftBlockEntity blockEntity) { + super(modelManager, blockEntity); + + keys = new ArrayList<>(2); + + float speed = blockEntity.getSpeed(); + + Material rotatingMaterial = getRotatingMaterial(); + + for (Direction dir : Iterate.directionsInAxis(getRotationAxis())) { + + Instancer half = rotatingMaterial.getModel(AllPartialModels.SHAFT_HALF, blockState, dir); + + float splitSpeed = speed * blockEntity.getRotationSpeedModifier(dir); + + keys.add(setup(half.createInstance(), splitSpeed)); + } + } + + @Override + public void update() { + Block block = blockState.getBlock(); + final Direction.Axis boxAxis = ((IRotate) block).getRotationAxis(blockState); + + Direction[] directions = Iterate.directionsInAxis(boxAxis); + + for (int i : Iterate.zeroAndOne) { + updateRotation(keys.get(i), blockEntity.getSpeed() * blockEntity.getRotationSpeedModifier(directions[i])); + } + } + + @Override + public void updateLight() { + relight(pos, keys.stream()); + } + + @Override + public void remove() { + keys.forEach(InstanceData::delete); + keys.clear(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/transmission/SplitShaftRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/transmission/SplitShaftRenderer.java new file mode 100644 index 000000000..0846740c8 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/transmission/SplitShaftRenderer.java @@ -0,0 +1,57 @@ +package com.simibubi.create.content.kinetics.transmission; + +import com.jozufozu.flywheel.backend.Backend; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.IRotate; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.Iterate; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.world.level.block.Block; + +public class SplitShaftRenderer extends KineticBlockEntityRenderer { + + public SplitShaftRenderer(BlockEntityRendererProvider.Context context) { + super(context); + } + + @Override + protected void renderSafe(SplitShaftBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + if (Backend.canUseInstancing(be.getLevel())) return; + + Block block = be.getBlockState().getBlock(); + final Axis boxAxis = ((IRotate) block).getRotationAxis(be.getBlockState()); + final BlockPos pos = be.getBlockPos(); + float time = AnimationTickHolder.getRenderTime(be.getLevel()); + + for (Direction direction : Iterate.directions) { + Axis axis = direction.getAxis(); + if (boxAxis != axis) + continue; + + float offset = getRotationOffsetForPosition(be, pos, axis); + float angle = (time * be.getSpeed() * 3f / 10) % 360; + float modifier = be.getRotationSpeedModifier(direction); + + angle *= modifier; + angle += offset; + angle = angle / 180f * (float) Math.PI; + + SuperByteBuffer superByteBuffer = + CachedBufferer.partialFacing(AllPartialModels.SHAFT_HALF, be.getBlockState(), direction); + kineticRotationTransform(superByteBuffer, be, axis, angle, light); + superByteBuffer.renderInto(ms, buffer.getBuffer(RenderType.solid())); + } + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/ConfigureSequencedGearshiftPacket.java b/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/ConfigureSequencedGearshiftPacket.java new file mode 100644 index 000000000..4c00bd0a1 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/ConfigureSequencedGearshiftPacket.java @@ -0,0 +1,46 @@ +package com.simibubi.create.content.kinetics.transmission.sequencer; + +import com.simibubi.create.foundation.networking.BlockEntityConfigurationPacket; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.FriendlyByteBuf; + +public class ConfigureSequencedGearshiftPacket extends BlockEntityConfigurationPacket { + + private ListTag instructions; + + public ConfigureSequencedGearshiftPacket(BlockPos pos, ListTag instructions) { + super(pos); + this.instructions = instructions; + } + + public ConfigureSequencedGearshiftPacket(FriendlyByteBuf buffer) { + super(buffer); + } + + @Override + protected void readSettings(FriendlyByteBuf buffer) { + instructions = buffer.readNbt().getList("data", Tag.TAG_COMPOUND); + } + + @Override + protected void writeSettings(FriendlyByteBuf buffer) { + CompoundTag tag = new CompoundTag(); + tag.put("data", instructions); + buffer.writeNbt(tag); + } + + @Override + protected void applySettings(SequencedGearshiftBlockEntity be) { + if (be.computerBehaviour.hasAttachedComputer()) + return; + + be.run(-1); + be.instructions = Instruction.deserializeAll(instructions); + be.sendData(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/Instruction.java b/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/Instruction.java similarity index 76% rename from src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/Instruction.java rename to src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/Instruction.java index 9335285d1..f23c7935e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/Instruction.java +++ b/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/Instruction.java @@ -1,8 +1,8 @@ -package com.simibubi.create.content.contraptions.relays.advanced.sequencer; +package com.simibubi.create.content.kinetics.transmission.sequencer; import java.util.Vector; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; import com.simibubi.create.foundation.utility.NBTHelper; import net.minecraft.nbt.CompoundTag; @@ -19,36 +19,35 @@ public class Instruction { } public Instruction(SequencerInstructions instruction, int value) { + this(instruction, InstructionSpeedModifiers.FORWARD, value); + } + + public Instruction(SequencerInstructions instruction, InstructionSpeedModifiers speedModifier, int value) { this.instruction = instruction; - speedModifier = InstructionSpeedModifiers.FORWARD; + this.speedModifier = speedModifier; this.value = value; } int getDuration(float currentProgress, float speed) { speed *= speedModifier.value; speed = Math.abs(speed); - double target = value - currentProgress; switch (instruction) { + // Always overshoot, target will stop early case TURN_ANGLE: - double degreesPerTick = KineticTileEntity.convertToAngular(speed); - int ticks = (int) (target / degreesPerTick); - double degreesErr = target - degreesPerTick*ticks; - return ticks + (degreesPerTick > 2*degreesErr ? 0 : 1); - + double degreesPerTick = KineticBlockEntity.convertToAngular(speed); + return (int) Math.ceil(target / degreesPerTick) + 2; case TURN_DISTANCE: - double metersPerTick = KineticTileEntity.convertToLinear(speed); - int offset = speed > 0 && speedModifier.value < 0 ? 1 : 2; - return (int) (target / metersPerTick + offset); + double metersPerTick = KineticBlockEntity.convertToLinear(speed); + return (int) Math.ceil(target / metersPerTick) + 2; + // Timing instructions case DELAY: return (int) target; - case AWAIT: return -1; - case END: default: break; @@ -58,13 +57,13 @@ public class Instruction { } float getTickProgress(float speed) { - switch(instruction) { + switch (instruction) { case TURN_ANGLE: - return KineticTileEntity.convertToAngular(speed); + return KineticBlockEntity.convertToAngular(speed); case TURN_DISTANCE: - return KineticTileEntity.convertToLinear(speed); + return KineticBlockEntity.convertToLinear(speed); case DELAY: return 1; diff --git a/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/InstructionSpeedModifiers.java b/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/InstructionSpeedModifiers.java new file mode 100644 index 000000000..db3a5d598 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/InstructionSpeedModifiers.java @@ -0,0 +1,47 @@ +package com.simibubi.create.content.kinetics.transmission.sequencer; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.network.chat.Component; + +public enum InstructionSpeedModifiers { + + FORWARD_FAST(2, ">>"), FORWARD(1, "->"), BACK(-1, "<-"), BACK_FAST(-2, "<<"), + + ; + + String translationKey; + int value; + Component label; + + private InstructionSpeedModifiers(int modifier, Component label) { + this.label = label; + translationKey = "gui.sequenced_gearshift.speed." + Lang.asId(name()); + value = modifier; + } + private InstructionSpeedModifiers(int modifier, String label) { + this.label = Components.literal(label); + translationKey = "gui.sequenced_gearshift.speed." + Lang.asId(name()); + value = modifier; + } + + static List getOptions() { + List options = new ArrayList<>(); + for (InstructionSpeedModifiers entry : values()) + options.add(Lang.translateDirect(entry.translationKey)); + return options; + } + + public static InstructionSpeedModifiers getByModifier(int modifier) { + return Arrays.stream(InstructionSpeedModifiers.values()) + .filter(speedModifier -> speedModifier.value == modifier) + .findAny() + .orElse(InstructionSpeedModifiers.FORWARD); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/OnIsPoweredResult.java b/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/OnIsPoweredResult.java new file mode 100644 index 000000000..328dbad04 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/OnIsPoweredResult.java @@ -0,0 +1,6 @@ +package com.simibubi.create.content.kinetics.transmission.sequencer; + +public enum OnIsPoweredResult { + NOTHING, + CONTINUE +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftBlock.java b/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/SequencedGearshiftBlock.java similarity index 81% rename from src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftBlock.java rename to src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/SequencedGearshiftBlock.java index fd7b0bde7..d765dd9b6 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/SequencedGearshiftBlock.java @@ -1,13 +1,13 @@ -package com.simibubi.create.content.contraptions.relays.advanced.sequencer; +package com.simibubi.create.content.kinetics.transmission.sequencer; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllItems; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.HorizontalAxisKineticBlock; -import com.simibubi.create.content.contraptions.base.KineticBlock; -import com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.ITransformableBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.content.contraptions.ITransformableBlock; +import com.simibubi.create.content.contraptions.StructureTransform; +import com.simibubi.create.content.kinetics.base.HorizontalAxisKineticBlock; +import com.simibubi.create.content.kinetics.base.KineticBlock; +import com.simibubi.create.content.kinetics.base.RotatedPillarKineticBlock; +import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.gui.ScreenOpener; import net.minecraft.client.player.LocalPlayer; @@ -36,7 +36,7 @@ import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.fml.DistExecutor; -public class SequencedGearshiftBlock extends HorizontalAxisKineticBlock implements ITE, ITransformableBlock { +public class SequencedGearshiftBlock extends HorizontalAxisKineticBlock implements IBE, ITransformableBlock { public static final BooleanProperty VERTICAL = BooleanProperty.create("vertical"); public static final IntegerProperty STATE = IntegerProperty.create("state", 0, 5); @@ -69,7 +69,7 @@ public class SequencedGearshiftBlock extends HorizontalAxisKineticBlock implemen public void tick(BlockState state, ServerLevel worldIn, BlockPos pos, RandomSource r) { boolean previouslyPowered = state.getValue(STATE) != 0; boolean isPowered = worldIn.hasNeighborSignal(pos); - withTileEntityDo(worldIn, pos, sgte -> sgte.onRedstoneUpdate(isPowered, previouslyPowered)); + withBlockEntityDo(worldIn, pos, sgte -> sgte.onRedstoneUpdate(isPowered, previouslyPowered)); } @Override @@ -98,14 +98,14 @@ public class SequencedGearshiftBlock extends HorizontalAxisKineticBlock implemen } DistExecutor.unsafeRunWhenOn(Dist.CLIENT, - () -> () -> withTileEntityDo(worldIn, pos, te -> this.displayScreen(te, player))); + () -> () -> withBlockEntityDo(worldIn, pos, be -> this.displayScreen(be, player))); return InteractionResult.SUCCESS; } @OnlyIn(value = Dist.CLIENT) - protected void displayScreen(SequencedGearshiftTileEntity te, Player player) { + protected void displayScreen(SequencedGearshiftBlockEntity be, Player player) { if (player instanceof LocalPlayer) - ScreenOpener.open(new SequencedGearshiftScreen(te)); + ScreenOpener.open(new SequencedGearshiftScreen(be)); } @Override @@ -147,13 +147,13 @@ public class SequencedGearshiftBlock extends HorizontalAxisKineticBlock implemen } @Override - public Class getTileEntityClass() { - return SequencedGearshiftTileEntity.class; + public Class getBlockEntityClass() { + return SequencedGearshiftBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.SEQUENCED_GEARSHIFT.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.SEQUENCED_GEARSHIFT.get(); } @Override diff --git a/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/SequencedGearshiftBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/SequencedGearshiftBlockEntity.java new file mode 100644 index 000000000..a114c3728 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/SequencedGearshiftBlockEntity.java @@ -0,0 +1,249 @@ +package com.simibubi.create.content.kinetics.transmission.sequencer; + +import java.util.List; +import java.util.Vector; + +import javax.annotation.Nullable; + +import org.jetbrains.annotations.NotNull; + +import com.simibubi.create.compat.computercraft.AbstractComputerBehaviour; +import com.simibubi.create.compat.computercraft.ComputerCraftProxy; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.transmission.SplitShaftBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.NBTHelper; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; + +public class SequencedGearshiftBlockEntity extends SplitShaftBlockEntity { + + Vector instructions; + int currentInstruction; + int currentInstructionDuration; + float currentInstructionProgress; + int timer; + boolean poweredPreviously; + + public AbstractComputerBehaviour computerBehaviour; + + public record SequenceContext(SequencerInstructions instruction, double relativeValue) { + + public static SequenceContext fromGearshift(SequencerInstructions instruction, double kineticSpeed, + int absoluteValue) { + return instruction.needsPropagation() + ? new SequenceContext(instruction, kineticSpeed == 0 ? 0 : absoluteValue / kineticSpeed) + : null; + } + + public double getEffectiveValue(double speedAtTarget) { + return Math.abs(relativeValue * speedAtTarget); + } + + public CompoundTag serializeNBT() { + CompoundTag nbt = new CompoundTag(); + NBTHelper.writeEnum(nbt, "Mode", instruction); + nbt.putDouble("Value", relativeValue); + return nbt; + } + + public static SequenceContext fromNBT(CompoundTag nbt) { + if (nbt.isEmpty()) + return null; + return new SequenceContext(NBTHelper.readEnum(nbt, "Mode", SequencerInstructions.class), + nbt.getDouble("Value")); + } + + } + + public SequencedGearshiftBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + instructions = Instruction.createDefault(); + currentInstruction = -1; + currentInstructionDuration = -1; + currentInstructionProgress = 0; + timer = 0; + poweredPreviously = false; + } + + @Override + public void addBehaviours(List behaviours) { + super.addBehaviours(behaviours); + behaviours.add(computerBehaviour = ComputerCraftProxy.behaviour(this)); + } + + @Override + public void tick() { + super.tick(); + + if (isIdle()) + return; + if (level.isClientSide) + return; + if (currentInstructionDuration < 0) + return; + if (timer < currentInstructionDuration) { + timer++; + currentInstructionProgress += getInstruction(currentInstruction).getTickProgress(speed); + return; + } + run(currentInstruction + 1); + } + + @Override + public void onSpeedChanged(float previousSpeed) { + super.onSpeedChanged(previousSpeed); + if (isIdle()) + return; + float currentSpeed = Math.abs(speed); + if (Math.abs(previousSpeed) == currentSpeed) + return; + Instruction instruction = getInstruction(currentInstruction); + if (instruction == null) + return; + if (getSpeed() == 0) + run(-1); + + // Update instruction time with regards to new speed + currentInstructionDuration = instruction.getDuration(currentInstructionProgress, getTheoreticalSpeed()); + timer = 0; + } + + public boolean isIdle() { + return currentInstruction == -1; + } + + public void onRedstoneUpdate(boolean isPowered, boolean isRunning) { + if (computerBehaviour.hasAttachedComputer()) + return; + if (!poweredPreviously && isPowered) + risingFlank(); + poweredPreviously = isPowered; + if (!isIdle()) + return; + if (isPowered == isRunning) + return; + if (!level.hasNeighborSignal(worldPosition)) { + level.setBlock(worldPosition, getBlockState().setValue(SequencedGearshiftBlock.STATE, 0), 3); + return; + } + if (getSpeed() == 0) + return; + run(0); + } + + public void risingFlank() { + Instruction instruction = getInstruction(currentInstruction); + if (instruction == null) + return; + if (poweredPreviously) + return; + poweredPreviously = true; + + switch (instruction.onRedstonePulse()) { + case CONTINUE: + run(currentInstruction + 1); + break; + default: + break; + } + } + + public void run(int instructionIndex) { + Instruction instruction = getInstruction(instructionIndex); + if (instruction == null || instruction.instruction == SequencerInstructions.END) { + if (getModifier() != 0) + detachKinetics(); + currentInstruction = -1; + currentInstructionDuration = -1; + currentInstructionProgress = 0; + sequenceContext = null; + timer = 0; + if (!level.hasNeighborSignal(worldPosition)) + level.setBlock(worldPosition, getBlockState().setValue(SequencedGearshiftBlock.STATE, 0), 3); + else + sendData(); + return; + } + + detachKinetics(); + currentInstructionDuration = instruction.getDuration(0, getTheoreticalSpeed()); + currentInstruction = instructionIndex; + currentInstructionProgress = 0; + sequenceContext = SequenceContext.fromGearshift(instruction.instruction, getTheoreticalSpeed() * getModifier(), + instruction.value); + timer = 0; + level.setBlock(worldPosition, getBlockState().setValue(SequencedGearshiftBlock.STATE, instructionIndex + 1), 3); + } + + public Instruction getInstruction(int instructionIndex) { + return instructionIndex >= 0 && instructionIndex < instructions.size() ? instructions.get(instructionIndex) + : null; + } + + @Override + protected void copySequenceContextFrom(KineticBlockEntity sourceBE) {} + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + compound.putInt("InstructionIndex", currentInstruction); + compound.putInt("InstructionDuration", currentInstructionDuration); + compound.putFloat("InstructionProgress", currentInstructionProgress); + compound.putInt("Timer", timer); + compound.putBoolean("PrevPowered", poweredPreviously); + compound.put("Instructions", Instruction.serializeAll(instructions)); + super.write(compound, clientPacket); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + currentInstruction = compound.getInt("InstructionIndex"); + currentInstructionDuration = compound.getInt("InstructionDuration"); + currentInstructionProgress = compound.getFloat("InstructionProgress"); + poweredPreviously = compound.getBoolean("PrevPowered"); + timer = compound.getInt("Timer"); + instructions = Instruction.deserializeAll(compound.getList("Instructions", Tag.TAG_COMPOUND)); + super.read(compound, clientPacket); + } + + @NotNull + @Override + public LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction side) { + if (computerBehaviour.isPeripheralCap(cap)) + return computerBehaviour.getPeripheralCapability(); + return super.getCapability(cap, side); + } + + @Override + public void invalidateCaps() { + super.invalidateCaps(); + computerBehaviour.removePeripheral(); + } + + @Override + public float getRotationSpeedModifier(Direction face) { + if (isVirtual()) + return 1; + return (!hasSource() || face == getSourceFacing()) ? 1 : getModifier(); + } + + public int getModifier() { + if (currentInstruction >= instructions.size()) + return 0; + return isIdle() ? 0 + : instructions.get(currentInstruction) + .getSpeedModifier(); + } + + public Vector getInstructions() { + return this.instructions; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftGenerator.java b/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/SequencedGearshiftGenerator.java similarity index 93% rename from src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftGenerator.java rename to src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/SequencedGearshiftGenerator.java index 5c3ce9079..c27cc05a5 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftGenerator.java +++ b/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/SequencedGearshiftGenerator.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.relays.advanced.sequencer; +package com.simibubi.create.content.kinetics.transmission.sequencer; import com.simibubi.create.foundation.data.SpecialBlockStateGen; import com.tterrag.registrate.providers.DataGenContext; diff --git a/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/SequencedGearshiftScreen.java b/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/SequencedGearshiftScreen.java new file mode 100644 index 000000000..1546802ed --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/SequencedGearshiftScreen.java @@ -0,0 +1,227 @@ +package com.simibubi.create.content.kinetics.transmission.sequencer; + +import java.util.Vector; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPackets; +import com.simibubi.create.compat.computercraft.ComputerScreen; +import com.simibubi.create.foundation.gui.AbstractSimiScreen; +import com.simibubi.create.foundation.gui.AllGuiTextures; +import com.simibubi.create.foundation.gui.AllIcons; +import com.simibubi.create.foundation.gui.element.GuiGameElement; +import com.simibubi.create.foundation.gui.widget.IconButton; +import com.simibubi.create.foundation.gui.widget.ScrollInput; +import com.simibubi.create.foundation.gui.widget.SelectionScrollInput; +import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.nbt.ListTag; +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.ItemStack; + +public class SequencedGearshiftScreen extends AbstractSimiScreen { + + private final ItemStack renderedItem = AllBlocks.SEQUENCED_GEARSHIFT.asStack(); + private final AllGuiTextures background = AllGuiTextures.SEQUENCER; + private IconButton confirmButton; + private SequencedGearshiftBlockEntity be; + + private ListTag compareTag; + private Vector instructions; + + private Vector> inputs; + + public SequencedGearshiftScreen(SequencedGearshiftBlockEntity be) { + super(Lang.translateDirect("gui.sequenced_gearshift.title")); + this.instructions = be.instructions; + this.be = be; + compareTag = Instruction.serializeAll(instructions); + } + + @Override + protected void init() { + if (be.computerBehaviour.hasAttachedComputer()) + minecraft.setScreen( + new ComputerScreen(title, this::renderAdditional, this, be.computerBehaviour::hasAttachedComputer)); + + setWindowSize(background.width, background.height); + setWindowOffset(-20, 0); + super.init(); + + int x = guiLeft; + int y = guiTop; + + inputs = new Vector<>(5); + for (int row = 0; row < inputs.capacity(); row++) + inputs.add(new Vector<>(3)); + + for (int row = 0; row < instructions.size(); row++) + initInputsOfRow(row, x, y); + + confirmButton = new IconButton(x + background.width - 33, y + background.height - 24, AllIcons.I_CONFIRM); + confirmButton.withCallback(() -> { + onClose(); + }); + addRenderableWidget(confirmButton); + } + + public void initInputsOfRow(int row, int backgroundX, int backgroundY) { + int x = backgroundX + 30; + int y = backgroundY + 20; + int rowHeight = 22; + + Vector rowInputs = inputs.get(row); + removeWidgets(rowInputs); + rowInputs.clear(); + int index = row; + Instruction instruction = instructions.get(row); + + ScrollInput type = + new SelectionScrollInput(x, y + rowHeight * row, 50, 18).forOptions(SequencerInstructions.getOptions()) + .calling(state -> instructionUpdated(index, state)) + .setState(instruction.instruction.ordinal()) + .titled(Lang.translateDirect("gui.sequenced_gearshift.instruction")); + ScrollInput value = + new ScrollInput(x + 58, y + rowHeight * row, 28, 18).calling(state -> instruction.value = state); + ScrollInput direction = new SelectionScrollInput(x + 88, y + rowHeight * row, 28, 18) + .forOptions(InstructionSpeedModifiers.getOptions()) + .calling(state -> instruction.speedModifier = InstructionSpeedModifiers.values()[state]) + .titled(Lang.translateDirect("gui.sequenced_gearshift.speed")); + + rowInputs.add(type); + rowInputs.add(value); + rowInputs.add(direction); + + addRenderableWidgets(rowInputs); + updateParamsOfRow(row); + } + + public void updateParamsOfRow(int row) { + Instruction instruction = instructions.get(row); + Vector rowInputs = inputs.get(row); + SequencerInstructions def = instruction.instruction; + boolean hasValue = def.hasValueParameter; + boolean hasModifier = def.hasSpeedParameter; + + ScrollInput value = rowInputs.get(1); + value.active = value.visible = hasValue; + if (hasValue) + value.withRange(1, def.maxValue + 1) + .titled(Lang.translateDirect(def.parameterKey)) + .withShiftStep(def.shiftStep) + .setState(instruction.value) + .onChanged(); + if (def == SequencerInstructions.DELAY) { + value.withStepFunction(context -> { + int v = context.currentValue; + if (!context.forward) + v--; + if (v < 20) + return context.shift ? 20 : 1; + return context.shift ? 100 : 20; + }); + } else + value.withStepFunction(value.standardStep()); + + ScrollInput modifier = rowInputs.get(2); + modifier.active = modifier.visible = hasModifier; + if (hasModifier) + modifier.setState(instruction.speedModifier.ordinal()); + } + + @Override + public void tick() { + super.tick(); + + if (be.computerBehaviour.hasAttachedComputer()) + minecraft.setScreen( + new ComputerScreen(title, this::renderAdditional, this, be.computerBehaviour::hasAttachedComputer)); + } + + @Override + protected void renderWindow(PoseStack ms, int mouseX, int mouseY, float partialTicks) { + int x = guiLeft; + int y = guiTop; + + background.render(ms, x, y, this); + + for (int row = 0; row < instructions.capacity(); row++) { + AllGuiTextures toDraw = AllGuiTextures.SEQUENCER_EMPTY; + int yOffset = toDraw.height * row; + + toDraw.render(ms, x, y + 16 + yOffset, this); + } + + for (int row = 0; row < instructions.capacity(); row++) { + AllGuiTextures toDraw = AllGuiTextures.SEQUENCER_EMPTY; + int yOffset = toDraw.height * row; + if (row >= instructions.size()) { + toDraw.render(ms, x, y + 16 + yOffset, this); + continue; + } + + Instruction instruction = instructions.get(row); + SequencerInstructions def = instruction.instruction; + def.background.render(ms, x, y + 16 + yOffset, this); + + label(ms, 36, yOffset - 1, Lang.translateDirect(def.translationKey)); + if (def.hasValueParameter) { + String text = def.formatValue(instruction.value); + int stringWidth = font.width(text); + label(ms, 90 + (12 - stringWidth / 2), yOffset - 1, Components.literal(text)); + } + if (def.hasSpeedParameter) + label(ms, 127, yOffset - 1, instruction.speedModifier.label); + } + + font.draw(ms, title, x + (background.width - 8) / 2 - font.width(title) / 2, y + 4, 0x592424); + renderAdditional(ms, mouseX, mouseY, partialTicks, x, y, background); + } + + private void renderAdditional(PoseStack ms, int mouseX, int mouseY, float partialTicks, int guiLeft, int guiTop, + AllGuiTextures background) { + GuiGameElement.of(renderedItem).at(guiLeft + background.width + 6, guiTop + background.height - 56, 100) + .scale(5) + .render(ms); + } + + private void label(PoseStack ms, int x, int y, Component text) { + font.drawShadow(ms, text, guiLeft + x, guiTop + 26 + y, 0xFFFFEE); + } + + public void sendPacket() { + ListTag serialized = Instruction.serializeAll(instructions); + if (serialized.equals(compareTag)) + return; + AllPackets.getChannel() + .sendToServer(new ConfigureSequencedGearshiftPacket(be.getBlockPos(), serialized)); + } + + @Override + public void removed() { + sendPacket(); + } + + private void instructionUpdated(int index, int state) { + SequencerInstructions newValue = SequencerInstructions.values()[state]; + instructions.get(index).instruction = newValue; + instructions.get(index).value = newValue.defaultValue; + updateParamsOfRow(index); + if (newValue == SequencerInstructions.END) { + for (int i = instructions.size() - 1; i > index; i--) { + instructions.remove(i); + Vector rowInputs = inputs.get(i); + removeWidgets(rowInputs); + rowInputs.clear(); + } + } else { + if (index + 1 < instructions.capacity() && index + 1 == instructions.size()) { + instructions.add(new Instruction(SequencerInstructions.END)); + initInputsOfRow(index + 1, guiLeft, guiTop); + } + } + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencerInstructions.java b/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/SequencerInstructions.java similarity index 92% rename from src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencerInstructions.java rename to src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/SequencerInstructions.java index 060a0df7e..6ba463772 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencerInstructions.java +++ b/src/main/java/com/simibubi/create/content/kinetics/transmission/sequencer/SequencerInstructions.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.relays.advanced.sequencer; +package com.simibubi.create.content.kinetics.transmission.sequencer; import java.util.ArrayList; import java.util.List; @@ -44,6 +44,10 @@ public enum SequencerInstructions { descriptiveTranslationKey = translationKey + ".descriptive"; parameterKey = translationKey + "." + parameterName; } + + public boolean needsPropagation() { + return this == TURN_ANGLE || this == TURN_DISTANCE; + } static List getOptions() { List options = new ArrayList<>(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/turntable/TurntableBlock.java b/src/main/java/com/simibubi/create/content/kinetics/turntable/TurntableBlock.java similarity index 79% rename from src/main/java/com/simibubi/create/content/contraptions/components/turntable/TurntableBlock.java rename to src/main/java/com/simibubi/create/content/kinetics/turntable/TurntableBlock.java index f4908cb45..57efdd765 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/turntable/TurntableBlock.java +++ b/src/main/java/com/simibubi/create/content/kinetics/turntable/TurntableBlock.java @@ -1,10 +1,10 @@ -package com.simibubi.create.content.contraptions.components.turntable; +package com.simibubi.create.content.kinetics.turntable; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.KineticBlock; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.content.kinetics.base.KineticBlock; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.core.BlockPos; @@ -25,7 +25,7 @@ import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; -public class TurntableBlock extends KineticBlock implements ITE { +public class TurntableBlock extends KineticBlock implements IBE { public TurntableBlock(Properties properties) { super(properties); @@ -50,8 +50,8 @@ public class TurntableBlock extends KineticBlock implements ITE { - float speed = ((KineticTileEntity) te).getSpeed() * 3 / 10; + withBlockEntityDo(worldIn, pos, be -> { + float speed = ((KineticBlockEntity) be).getSpeed() * 3 / 10; if (speed == 0) return; @@ -99,13 +99,13 @@ public class TurntableBlock extends KineticBlock implements ITE getTileEntityClass() { - return TurntableTileEntity.class; + public Class getBlockEntityClass() { + return TurntableBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.TURNTABLE.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.TURNTABLE.get(); } @Override diff --git a/src/main/java/com/simibubi/create/content/kinetics/turntable/TurntableBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/turntable/TurntableBlockEntity.java new file mode 100644 index 000000000..c2fe73a86 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/turntable/TurntableBlockEntity.java @@ -0,0 +1,15 @@ +package com.simibubi.create.content.kinetics.turntable; + +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; + +public class TurntableBlockEntity extends KineticBlockEntity { + + public TurntableBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/turntable/TurntableHandler.java b/src/main/java/com/simibubi/create/content/kinetics/turntable/TurntableHandler.java similarity index 81% rename from src/main/java/com/simibubi/create/content/contraptions/components/turntable/TurntableHandler.java rename to src/main/java/com/simibubi/create/content/kinetics/turntable/TurntableHandler.java index 2a8a7f1f9..5fca562e3 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/turntable/TurntableHandler.java +++ b/src/main/java/com/simibubi/create/content/kinetics/turntable/TurntableHandler.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.turntable; +package com.simibubi.create.content.kinetics.turntable; import com.simibubi.create.AllBlocks; import com.simibubi.create.foundation.utility.AnimationTickHolder; @@ -23,11 +23,11 @@ public class TurntableHandler { if (mc.isPaused()) return; - BlockEntity tileEntity = mc.level.getBlockEntity(pos); - if (!(tileEntity instanceof TurntableTileEntity)) + BlockEntity blockEntity = mc.level.getBlockEntity(pos); + if (!(blockEntity instanceof TurntableBlockEntity)) return; - TurntableTileEntity turnTable = (TurntableTileEntity) tileEntity; + TurntableBlockEntity turnTable = (TurntableBlockEntity) blockEntity; float speed = turnTable.getSpeed() * 3/10; if (speed == 0) diff --git a/src/main/java/com/simibubi/create/content/kinetics/waterwheel/LargeWaterWheelBlock.java b/src/main/java/com/simibubi/create/content/kinetics/waterwheel/LargeWaterWheelBlock.java new file mode 100644 index 000000000..1d8ecc2c6 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/waterwheel/LargeWaterWheelBlock.java @@ -0,0 +1,172 @@ +package com.simibubi.create.content.kinetics.waterwheel; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.kinetics.base.RotatedPillarKineticBlock; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.utility.Couple; +import com.simibubi.create.foundation.utility.Iterate; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.item.context.UseOnContext; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.RenderShape; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition.Builder; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.phys.BlockHitResult; + +public class LargeWaterWheelBlock extends RotatedPillarKineticBlock implements IBE { + + public static final BooleanProperty EXTENSION = BooleanProperty.create("extension"); + + public LargeWaterWheelBlock(Properties properties) { + super(properties); + registerDefaultState(defaultBlockState().setValue(EXTENSION, false)); + } + + @Override + protected void createBlockStateDefinition(Builder builder) { + super.createBlockStateDefinition(builder.add(EXTENSION)); + } + + public Axis getAxisForPlacement(BlockPlaceContext context) { + return super.getStateForPlacement(context).getValue(AXIS); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext context) { + BlockState stateForPlacement = super.getStateForPlacement(context); + BlockPos pos = context.getClickedPos(); + Axis axis = stateForPlacement.getValue(AXIS); + + for (int x = -1; x <= 1; x++) { + for (int y = -1; y <= 1; y++) { + for (int z = -1; z <= 1; z++) { + if (axis.choose(x, y, z) != 0) + continue; + BlockPos offset = new BlockPos(x, y, z); + if (offset.equals(BlockPos.ZERO)) + continue; + BlockState occupiedState = context.getLevel() + .getBlockState(pos.offset(offset)); + if (!occupiedState.getMaterial() + .isReplaceable()) + return null; + } + } + } + + if (context.getLevel() + .getBlockState(pos.relative(Direction.fromAxisAndDirection(axis, AxisDirection.NEGATIVE))) + .is(this)) + stateForPlacement = stateForPlacement.setValue(EXTENSION, true); + + return stateForPlacement; + } + + @Override + public InteractionResult use(BlockState pState, Level pLevel, BlockPos pPos, Player pPlayer, InteractionHand pHand, + BlockHitResult pHit) { + return onBlockEntityUse(pLevel, pPos, wwt -> wwt.applyMaterialIfValid(pPlayer.getItemInHand(pHand))); + } + + @Override + public InteractionResult onWrenched(BlockState state, UseOnContext context) { + return InteractionResult.PASS; + } + + @Override + public BlockState updateShape(BlockState pState, Direction pDirection, BlockState pNeighborState, + LevelAccessor pLevel, BlockPos pCurrentPos, BlockPos pNeighborPos) { + if (pDirection != Direction.fromAxisAndDirection(pState.getValue(AXIS), AxisDirection.NEGATIVE)) + return pState; + return pState.setValue(EXTENSION, pNeighborState.is(this)); + } + + @Override + public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) { + super.onPlace(state, level, pos, oldState, isMoving); + if (!level.getBlockTicks() + .hasScheduledTick(pos, this)) + level.scheduleTick(pos, this, 1); + } + + @Override + public void tick(BlockState pState, ServerLevel pLevel, BlockPos pPos, RandomSource pRandom) { + Axis axis = pState.getValue(AXIS); + for (Direction side : Iterate.directions) { + if (side.getAxis() == axis) + continue; + for (boolean secondary : Iterate.falseAndTrue) { + Direction targetSide = secondary ? side.getClockWise(axis) : side; + BlockPos structurePos = (secondary ? pPos.relative(side) : pPos).relative(targetSide); + BlockState occupiedState = pLevel.getBlockState(structurePos); + BlockState requiredStructure = AllBlocks.WATER_WHEEL_STRUCTURAL.getDefaultState() + .setValue(WaterWheelStructuralBlock.FACING, targetSide.getOpposite()); + if (occupiedState == requiredStructure) + continue; + if (!occupiedState.getMaterial() + .isReplaceable()) { + pLevel.destroyBlock(pPos, false); + return; + } + pLevel.setBlockAndUpdate(structurePos, requiredStructure); + } + } + withBlockEntityDo(pLevel, pPos, WaterWheelBlockEntity::determineAndApplyFlowScore); + } + + @Override + public RenderShape getRenderShape(BlockState pState) { + return RenderShape.ENTITYBLOCK_ANIMATED; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.LARGE_WATER_WHEEL.get(); + } + + @Override + public Class getBlockEntityClass() { + return LargeWaterWheelBlockEntity.class; + } + + @Override + public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) { + return face.getAxis() == getRotationAxis(state); + } + + @Override + public Axis getRotationAxis(BlockState state) { + return state.getValue(AXIS); + } + + @Override + public float getParticleTargetRadius() { + return 2.5f; + } + + @Override + public float getParticleInitialRadius() { + return 2.25f; + } + + public static Couple getSpeedRange() { + return Couple.create(4, 4); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/waterwheel/LargeWaterWheelBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/waterwheel/LargeWaterWheelBlockEntity.java new file mode 100644 index 000000000..6d21f526d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/waterwheel/LargeWaterWheelBlockEntity.java @@ -0,0 +1,18 @@ +package com.simibubi.create.content.kinetics.waterwheel; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; + +public class LargeWaterWheelBlockEntity extends WaterWheelBlockEntity { + + public LargeWaterWheelBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + protected int getSize() { + return 2; + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/waterwheel/LargeWaterWheelBlockItem.java b/src/main/java/com/simibubi/create/content/kinetics/waterwheel/LargeWaterWheelBlockItem.java new file mode 100644 index 000000000..9fb7e0e44 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/waterwheel/LargeWaterWheelBlockItem.java @@ -0,0 +1,59 @@ +package com.simibubi.create.content.kinetics.waterwheel; + +import com.simibubi.create.CreateClient; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.Pair; + +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.fml.DistExecutor; + +public class LargeWaterWheelBlockItem extends BlockItem { + + public LargeWaterWheelBlockItem(Block pBlock, Properties pProperties) { + super(pBlock, pProperties); + } + + @Override + public InteractionResult place(BlockPlaceContext ctx) { + InteractionResult result = super.place(ctx); + if (result != InteractionResult.FAIL) + return result; + Direction clickedFace = ctx.getClickedFace(); + if (clickedFace.getAxis() != ((LargeWaterWheelBlock) getBlock()).getAxisForPlacement(ctx)) + result = super.place(BlockPlaceContext.at(ctx, ctx.getClickedPos() + .relative(clickedFace), clickedFace)); + if (result == InteractionResult.FAIL && ctx.getLevel() + .isClientSide()) + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> showBounds(ctx)); + return result; + } + + @OnlyIn(Dist.CLIENT) + public void showBounds(BlockPlaceContext context) { + BlockPos pos = context.getClickedPos(); + Axis axis = ((LargeWaterWheelBlock) getBlock()).getAxisForPlacement(context); + Vec3 contract = Vec3.atLowerCornerOf(Direction.get(AxisDirection.POSITIVE, axis) + .getNormal()); + if (!(context.getPlayer()instanceof LocalPlayer localPlayer)) + return; + CreateClient.OUTLINER.showAABB(Pair.of("waterwheel", pos), new AABB(pos).inflate(1) + .deflate(contract.x, contract.y, contract.z)) + .colored(0xFF_ff5d6c); + Lang.translate("large_water_wheel.not_enough_space") + .color(0xFF_ff5d6c) + .sendStatus(localPlayer); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelBlock.java b/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelBlock.java new file mode 100644 index 000000000..adb7e6423 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelBlock.java @@ -0,0 +1,133 @@ +package com.simibubi.create.content.kinetics.waterwheel; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.kinetics.base.DirectionalKineticBlock; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.utility.Couple; +import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; + +public class WaterWheelBlock extends DirectionalKineticBlock implements IBE { + + public WaterWheelBlock(Properties properties) { + super(properties); + } + + @Override + public boolean canSurvive(BlockState state, LevelReader worldIn, BlockPos pos) { + for (Direction direction : Iterate.directions) { + BlockPos neighbourPos = pos.relative(direction); + BlockState neighbourState = worldIn.getBlockState(neighbourPos); + if (!AllBlocks.WATER_WHEEL.has(neighbourState)) + continue; + Axis axis = state.getValue(FACING) + .getAxis(); + if (neighbourState.getValue(FACING) + .getAxis() != axis || axis != direction.getAxis()) + return false; + } + return true; + } + + @Override + public InteractionResult use(BlockState pState, Level pLevel, BlockPos pPos, Player pPlayer, InteractionHand pHand, + BlockHitResult pHit) { + return onBlockEntityUse(pLevel, pPos, wwt -> wwt.applyMaterialIfValid(pPlayer.getItemInHand(pHand))); + } + + @Override + public BlockState updateShape(BlockState stateIn, Direction facing, BlockState facingState, LevelAccessor worldIn, + BlockPos currentPos, BlockPos facingPos) { + if (worldIn instanceof WrappedWorld) + return stateIn; + if (worldIn.isClientSide()) + return stateIn; + if (!worldIn.getBlockTicks() + .hasScheduledTick(currentPos, this)) + worldIn.scheduleTick(currentPos, this, 1); + return stateIn; + } + + @Override + public void onPlace(BlockState state, Level worldIn, BlockPos pos, BlockState oldState, boolean isMoving) { + super.onPlace(state, worldIn, pos, oldState, isMoving); + if (worldIn.isClientSide()) + return; + if (!worldIn.getBlockTicks() + .hasScheduledTick(pos, this)) + worldIn.scheduleTick(pos, this, 1); + } + + @Override + public void tick(BlockState pState, ServerLevel pLevel, BlockPos pPos, RandomSource pRandom) { + withBlockEntityDo(pLevel, pPos, WaterWheelBlockEntity::determineAndApplyFlowScore); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext context) { + BlockState state = super.getStateForPlacement(context); + state.setValue(FACING, Direction.get(AxisDirection.POSITIVE, state.getValue(FACING) + .getAxis())); + return state; + } + + @Override + public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) { + return state.getValue(FACING) + .getAxis() == face.getAxis(); + } + + @Override + public Axis getRotationAxis(BlockState state) { + return state.getValue(FACING) + .getAxis(); + } + + @Override + public float getParticleTargetRadius() { + return 1.125f; + } + + @Override + public float getParticleInitialRadius() { + return 1f; + } + + @Override + public boolean hideStressImpact() { + return true; + } + + @Override + public Class getBlockEntityClass() { + return WaterWheelBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.WATER_WHEEL.get(); + } + + public static Couple getSpeedRange() { + return Couple.create(8, 8); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelBlockEntity.java new file mode 100644 index 000000000..b2470ae41 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelBlockEntity.java @@ -0,0 +1,220 @@ +package com.simibubi.create.content.kinetics.waterwheel; + +import java.util.EnumMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import com.simibubi.create.content.kinetics.base.GeneratingKineticBlockEntity; +import com.simibubi.create.content.kinetics.base.IRotate; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.fluid.FluidHelper; +import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.core.Vec3i; +import net.minecraft.core.registries.Registries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.tags.BlockTags; +import net.minecraft.util.Mth; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.item.BlockItem; +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.BubbleColumnBlock; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; + +public class WaterWheelBlockEntity extends GeneratingKineticBlockEntity { + + public static final Map> SMALL_OFFSETS = new EnumMap<>(Axis.class); + public static final Map> LARGE_OFFSETS = new EnumMap<>(Axis.class); + + static { + for (Axis axis : Iterate.axes) { + HashSet offsets = new HashSet<>(); + for (Direction d : Iterate.directions) + if (d.getAxis() != axis) + offsets.add(BlockPos.ZERO.relative(d)); + SMALL_OFFSETS.put(axis, offsets); + + offsets = new HashSet<>(); + for (Direction d : Iterate.directions) { + if (d.getAxis() == axis) + continue; + BlockPos centralOffset = BlockPos.ZERO.relative(d, 2); + offsets.add(centralOffset); + for (Direction d2 : Iterate.directions) { + if (d2.getAxis() == axis) + continue; + if (d2.getAxis() == d.getAxis()) + continue; + offsets.add(centralOffset.relative(d2)); + } + } + LARGE_OFFSETS.put(axis, offsets); + } + } + + public int flowScore; + public BlockState material; + + public WaterWheelBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + material = Blocks.SPRUCE_PLANKS.defaultBlockState(); + setLazyTickRate(60); + } + + protected int getSize() { + return 1; + } + + protected Set getOffsetsToCheck() { + return (getSize() == 1 ? SMALL_OFFSETS : LARGE_OFFSETS).get(getAxis()); + } + + public InteractionResult applyMaterialIfValid(ItemStack stack) { + if (!(stack.getItem()instanceof BlockItem blockItem)) + return InteractionResult.PASS; + BlockState material = blockItem.getBlock() + .defaultBlockState(); + if (material == this.material) + return InteractionResult.PASS; + if (!material.is(BlockTags.PLANKS)) + return InteractionResult.PASS; + if (level.isClientSide() && !isVirtual()) + return InteractionResult.SUCCESS; + this.material = material; + notifyUpdate(); + level.levelEvent(2001, worldPosition, Block.getId(material)); + return InteractionResult.SUCCESS; + } + + protected Axis getAxis() { + Axis axis = Axis.X; + BlockState blockState = getBlockState(); + if (blockState.getBlock()instanceof IRotate irotate) + axis = irotate.getRotationAxis(blockState); + return axis; + } + + @Override + public void lazyTick() { + super.lazyTick(); + + // Water can change flow direction without notifying neighbours + determineAndApplyFlowScore(); + } + + public void determineAndApplyFlowScore() { + Vec3 wheelPlane = + Vec3.atLowerCornerOf(new Vec3i(1, 1, 1).subtract(Direction.get(AxisDirection.POSITIVE, getAxis()) + .getNormal())); + + int flowScore = 0; + boolean lava = false; + for (BlockPos blockPos : getOffsetsToCheck()) { + BlockPos targetPos = blockPos.offset(worldPosition); + Vec3 flowAtPos = getFlowVectorAtPosition(targetPos).multiply(wheelPlane); + lava |= FluidHelper.isLava(level.getFluidState(targetPos) + .getType()); + + if (flowAtPos.lengthSqr() == 0) + continue; + + flowAtPos = flowAtPos.normalize(); + Vec3 normal = Vec3.atLowerCornerOf(blockPos) + .normalize(); + + Vec3 positiveMotion = VecHelper.rotate(normal, 90, getAxis()); + double dot = flowAtPos.dot(positiveMotion); + if (Math.abs(dot) > .5) + flowScore += Math.signum(dot); + } + + if (flowScore != 0 && !level.isClientSide()) + award(lava ? AllAdvancements.LAVA_WHEEL : AllAdvancements.WATER_WHEEL); + + setFlowScoreAndUpdate(flowScore); + } + + public Vec3 getFlowVectorAtPosition(BlockPos pos) { + FluidState fluid = level.getFluidState(pos); + Vec3 vec = fluid.getFlow(level, pos); + BlockState blockState = level.getBlockState(pos); + if (blockState.getBlock() == Blocks.BUBBLE_COLUMN) + vec = new Vec3(0, blockState.getValue(BubbleColumnBlock.DRAG_DOWN) ? -1 : 1, 0); + return vec; + } + + public void setFlowScoreAndUpdate(int score) { + if (flowScore == score) + return; + flowScore = score; + updateGeneratedRotation(); + setChanged(); + } + + private void redraw() { + if (!isVirtual()) + requestModelDataUpdate(); + if (hasLevel()) { + level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 16); + level.getChunkSource() + .getLightEngine() + .checkBlock(worldPosition); + } + } + + @Override + public void addBehaviours(List behaviours) { + super.addBehaviours(behaviours); + registerAwardables(behaviours, AllAdvancements.LAVA_WHEEL, AllAdvancements.WATER_WHEEL); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + super.read(compound, clientPacket); + flowScore = compound.getInt("FlowScore"); + + BlockState prevMaterial = material; + if (!compound.contains("Material")) + return; + + material = NbtUtils.readBlockState(level.holderLookup(Registries.BLOCK), compound.getCompound("Material")); + if (material.isAir()) + material = Blocks.SPRUCE_PLANKS.defaultBlockState(); + + if (clientPacket && prevMaterial != material) + redraw(); + } + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + super.write(compound, clientPacket); + compound.putInt("FlowScore", flowScore); + compound.put("Material", NbtUtils.writeBlockState(material)); + } + + @Override + protected AABB createRenderBoundingBox() { + return new AABB(worldPosition).inflate(getSize()); + } + + @Override + public float getGeneratedSpeed() { + return Mth.clamp(flowScore, -1, 1) * 8 / getSize(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelInstance.java b/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelInstance.java new file mode 100644 index 000000000..b00ca8464 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelInstance.java @@ -0,0 +1,55 @@ +package com.simibubi.create.content.kinetics.waterwheel; + +import com.jozufozu.flywheel.api.Instancer; +import com.jozufozu.flywheel.api.MaterialManager; +import com.jozufozu.flywheel.core.model.BlockModel; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.content.kinetics.base.CutoutRotatingInstance; +import com.simibubi.create.content.kinetics.base.flwdata.RotatingData; +import com.simibubi.create.foundation.render.CachedBufferer; + +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; + +public class WaterWheelInstance extends CutoutRotatingInstance { + protected final boolean large; + protected final WaterWheelModelKey key; + + public WaterWheelInstance(MaterialManager materialManager, T blockEntity, boolean large) { + super(materialManager, blockEntity); + this.large = large; + key = new WaterWheelModelKey(large, getRenderedBlockState(), blockEntity.material); + } + + public static WaterWheelInstance standard(MaterialManager materialManager, T blockEntity) { + return new WaterWheelInstance<>(materialManager, blockEntity, false); + } + + public static WaterWheelInstance large(MaterialManager materialManager, T blockEntity) { + return new WaterWheelInstance<>(materialManager, blockEntity, true); + } + + @Override + public boolean shouldReset() { + return super.shouldReset() || key.material() != blockEntity.material; + } + + @Override + protected Instancer getModel() { + return getRotatingMaterial().model(key, () -> { + BakedModel model = WaterWheelRenderer.generateModel(key); + BlockState state = key.state(); + Direction dir; + if (key.large()) { + dir = Direction.fromAxisAndDirection(state.getValue(LargeWaterWheelBlock.AXIS), AxisDirection.POSITIVE); + } else { + dir = state.getValue(WaterWheelBlock.FACING); + } + PoseStack transform = CachedBufferer.rotateToFaceVertical(dir).get(); + return new BlockModel(model, Blocks.AIR.defaultBlockState(), transform); + }); + } +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelModelKey.java b/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelModelKey.java new file mode 100644 index 000000000..4999cb96d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelModelKey.java @@ -0,0 +1,6 @@ +package com.simibubi.create.content.kinetics.waterwheel; + +import net.minecraft.world.level.block.state.BlockState; + +public record WaterWheelModelKey(boolean large, BlockState state, BlockState material) { +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelRenderer.java b/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelRenderer.java new file mode 100644 index 000000000..fb74bb386 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelRenderer.java @@ -0,0 +1,152 @@ +package com.simibubi.create.content.kinetics.waterwheel; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import com.jozufozu.flywheel.core.StitchedSprite; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.CreateClient; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; +import com.simibubi.create.foundation.model.BakedModelHelper; +import com.simibubi.create.foundation.render.BakedModelRenderHelper; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.render.SuperByteBufferCache.Compartment; +import com.simibubi.create.foundation.utility.RegisteredObjects; + +import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider.Context; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.core.Holder; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.client.model.data.ModelData; +import net.minecraftforge.registries.ForgeRegistries; + +public class WaterWheelRenderer extends KineticBlockEntityRenderer { + public static final Compartment WATER_WHEEL = new Compartment<>(); + + public static final StitchedSprite OAK_PLANKS_TEMPLATE = new StitchedSprite(new ResourceLocation("block/oak_planks")); + public static final StitchedSprite OAK_LOG_TEMPLATE = new StitchedSprite(new ResourceLocation("block/oak_log")); + public static final StitchedSprite OAK_LOG_TOP_TEMPLATE = new StitchedSprite(new ResourceLocation("block/oak_log_top")); + + private static final String[] LOG_SUFFIXES = new String[] { "_log", "_stem" }; + + protected final boolean large; + + public WaterWheelRenderer(Context context, boolean large) { + super(context); + this.large = large; + } + + public static WaterWheelRenderer standard(Context context) { + return new WaterWheelRenderer<>(context, false); + } + + public static WaterWheelRenderer large(Context context) { + return new WaterWheelRenderer<>(context, true); + } + + @Override + protected SuperByteBuffer getRotatedModel(T be, BlockState state) { + WaterWheelModelKey key = new WaterWheelModelKey(large, state, be.material); + return CreateClient.BUFFER_CACHE.get(WATER_WHEEL, key, () -> { + BakedModel model = generateModel(key); + BlockState state1 = key.state(); + Direction dir; + if (key.large()) { + dir = Direction.fromAxisAndDirection(state1.getValue(LargeWaterWheelBlock.AXIS), AxisDirection.POSITIVE); + } else { + dir = state1.getValue(WaterWheelBlock.FACING); + } + PoseStack transform = CachedBufferer.rotateToFaceVertical(dir).get(); + return BakedModelRenderHelper.standardModelRender(model, Blocks.AIR.defaultBlockState(), transform); + }); + } + + public static BakedModel generateModel(WaterWheelModelKey key) { + BakedModel template; + if (key.large()) { + boolean extension = key.state() + .getValue(LargeWaterWheelBlock.EXTENSION); + if (extension) { + template = AllPartialModels.LARGE_WATER_WHEEL_EXTENSION.get(); + } else { + template = AllPartialModels.LARGE_WATER_WHEEL.get(); + } + } else { + template = AllPartialModels.WATER_WHEEL.get(); + } + + return generateModel(template, key.material()); + } + + public static BakedModel generateModel(BakedModel template, BlockState planksBlockState) { + Block planksBlock = planksBlockState.getBlock(); + ResourceLocation id = RegisteredObjects.getKeyOrThrow(planksBlock); + String path = id.getPath(); + + if (path.endsWith("_planks")) { + String namespace = id.getNamespace(); + String wood = path.substring(0, path.length() - 7); + BlockState logBlockState = getLogBlockState(namespace, wood); + + Map map = new Reference2ReferenceOpenHashMap<>(); + map.put(OAK_PLANKS_TEMPLATE.get(), getSpriteOnSide(planksBlockState, Direction.UP)); + map.put(OAK_LOG_TEMPLATE.get(), getSpriteOnSide(logBlockState, Direction.SOUTH)); + map.put(OAK_LOG_TOP_TEMPLATE.get(), getSpriteOnSide(logBlockState, Direction.UP)); + + return BakedModelHelper.generateModel(template, map::get); + } + + return BakedModelHelper.generateModel(template, sprite -> null); + } + + private static BlockState getLogBlockState(String namespace, String wood) { + for (String suffix : LOG_SUFFIXES) { + Optional state = + ForgeRegistries.BLOCKS.getHolder(new ResourceLocation(namespace, wood + suffix)) + .map(Holder::value) + .map(Block::defaultBlockState); + if (state.isPresent()) + return state.get(); + } + return Blocks.OAK_LOG.defaultBlockState(); + } + + private static TextureAtlasSprite getSpriteOnSide(BlockState state, Direction side) { + BakedModel model = Minecraft.getInstance() + .getBlockRenderer() + .getBlockModel(state); + if (model == null) + return null; + RandomSource random = RandomSource.create(); + random.setSeed(42L); + List quads = model.getQuads(state, side, random, ModelData.EMPTY, null); + if (!quads.isEmpty()) { + return quads.get(0) + .getSprite(); + } + random.setSeed(42L); + quads = model.getQuads(state, null, random, ModelData.EMPTY, null); + if (!quads.isEmpty()) { + for (BakedQuad quad : quads) { + if (quad.getDirection() == side) { + return quad.getSprite(); + } + } + } + return model.getParticleIcon(ModelData.EMPTY); + } + +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelStructuralBlock.java b/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelStructuralBlock.java new file mode 100644 index 000000000..525bb1152 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/kinetics/waterwheel/WaterWheelStructuralBlock.java @@ -0,0 +1,209 @@ +package com.simibubi.create.content.kinetics.waterwheel; + +import java.util.HashSet; +import java.util.Set; +import java.util.function.Consumer; + +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.equipment.goggles.IProxyHoveringInformation; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.foundation.block.render.MultiPosDestructionHandler; + +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.particle.ParticleEngine; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +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.item.context.UseOnContext; +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.Blocks; +import net.minecraft.world.level.block.DirectionalBlock; +import net.minecraft.world.level.block.RenderShape; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition.Builder; +import net.minecraft.world.level.material.PushReaction; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.HitResult; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.client.extensions.common.IClientBlockExtensions; + +public class WaterWheelStructuralBlock extends DirectionalBlock implements IWrenchable, IProxyHoveringInformation { + + public WaterWheelStructuralBlock(Properties p_52591_) { + super(p_52591_); + } + + @Override + protected void createBlockStateDefinition(Builder pBuilder) { + super.createBlockStateDefinition(pBuilder.add(FACING)); + } + + @Override + public RenderShape getRenderShape(BlockState pState) { + return RenderShape.INVISIBLE; + } + + @Override + public PushReaction getPistonPushReaction(BlockState pState) { + return PushReaction.BLOCK; + } + + @Override + public InteractionResult onWrenched(BlockState state, UseOnContext context) { + return InteractionResult.PASS; + } + + @Override + public ItemStack getCloneItemStack(BlockGetter pLevel, BlockPos pPos, BlockState pState) { + return AllBlocks.LARGE_WATER_WHEEL.asStack(); + } + + @Override + public InteractionResult onSneakWrenched(BlockState state, UseOnContext context) { + BlockPos clickedPos = context.getClickedPos(); + Level level = context.getLevel(); + + if (stillValid(level, clickedPos, state, false)) { + BlockPos masterPos = getMaster(level, clickedPos, state); + context = new UseOnContext(level, context.getPlayer(), context.getHand(), context.getItemInHand(), + new BlockHitResult(context.getClickLocation(), context.getClickedFace(), masterPos, + context.isInside())); + state = level.getBlockState(masterPos); + } + + return IWrenchable.super.onSneakWrenched(state, context); + } + + @Override + public InteractionResult use(BlockState pState, Level pLevel, BlockPos pPos, Player pPlayer, InteractionHand pHand, + BlockHitResult pHit) { + if (!stillValid(pLevel, pPos, pState, false)) + return InteractionResult.FAIL; + if (!(pLevel.getBlockEntity(getMaster(pLevel, pPos, pState))instanceof WaterWheelBlockEntity wwt)) + return InteractionResult.FAIL; + return wwt.applyMaterialIfValid(pPlayer.getItemInHand(pHand)); + } + + @Override + public void onRemove(BlockState pState, Level pLevel, BlockPos pPos, BlockState pNewState, boolean pIsMoving) { + if (stillValid(pLevel, pPos, pState, false)) + pLevel.destroyBlock(getMaster(pLevel, pPos, pState), true); + } + + public void playerWillDestroy(Level pLevel, BlockPos pPos, BlockState pState, Player pPlayer) { + if (stillValid(pLevel, pPos, pState, false)) { + BlockPos masterPos = getMaster(pLevel, pPos, pState); + pLevel.destroyBlockProgress(masterPos.hashCode(), masterPos, -1); + if (!pLevel.isClientSide() && pPlayer.isCreative()) + pLevel.destroyBlock(masterPos, false); + } + super.playerWillDestroy(pLevel, pPos, pState, pPlayer); + } + + @Override + public BlockState updateShape(BlockState pState, Direction pFacing, BlockState pFacingState, LevelAccessor pLevel, + BlockPos pCurrentPos, BlockPos pFacingPos) { + if (stillValid(pLevel, pCurrentPos, pState, false)) { + BlockPos masterPos = getMaster(pLevel, pCurrentPos, pState); + if (!pLevel.getBlockTicks() + .hasScheduledTick(masterPos, AllBlocks.LARGE_WATER_WHEEL.get())) + pLevel.scheduleTick(masterPos, AllBlocks.LARGE_WATER_WHEEL.get(), 1); + return pState; + } + if (!(pLevel instanceof Level level) || level.isClientSide()) + return pState; + if (!level.getBlockTicks() + .hasScheduledTick(pCurrentPos, this)) + level.scheduleTick(pCurrentPos, this, 1); + return pState; + } + + public static BlockPos getMaster(BlockGetter level, BlockPos pos, BlockState state) { + Direction direction = state.getValue(FACING); + BlockPos targetedPos = pos.relative(direction); + BlockState targetedState = level.getBlockState(targetedPos); + if (targetedState.is(AllBlocks.WATER_WHEEL_STRUCTURAL.get())) + return getMaster(level, targetedPos, targetedState); + return targetedPos; + } + + public boolean stillValid(BlockGetter level, BlockPos pos, BlockState state, boolean directlyAdjacent) { + if (!state.is(this)) + return false; + + Direction direction = state.getValue(FACING); + BlockPos targetedPos = pos.relative(direction); + BlockState targetedState = level.getBlockState(targetedPos); + + if (!directlyAdjacent && stillValid(level, targetedPos, targetedState, true)) + return true; + return targetedState.getBlock() instanceof LargeWaterWheelBlock + && targetedState.getValue(LargeWaterWheelBlock.AXIS) != direction.getAxis(); + } + + @Override + public void tick(BlockState pState, ServerLevel pLevel, BlockPos pPos, RandomSource pRandom) { + if (!stillValid(pLevel, pPos, pState, false)) + pLevel.setBlockAndUpdate(pPos, Blocks.AIR.defaultBlockState()); + } + + @OnlyIn(Dist.CLIENT) + public void initializeClient(Consumer consumer) { + consumer.accept(new RenderProperties()); + } + + @Override + public boolean addLandingEffects(BlockState state1, ServerLevel level, BlockPos pos, BlockState state2, + LivingEntity entity, int numberOfParticles) { + return true; + } + + public static class RenderProperties implements IClientBlockExtensions, MultiPosDestructionHandler { + + @Override + public boolean addDestroyEffects(BlockState state, Level Level, BlockPos pos, ParticleEngine manager) { + return true; + } + + @Override + public boolean addHitEffects(BlockState state, Level level, HitResult target, ParticleEngine manager) { + if (target instanceof BlockHitResult bhr) { + BlockPos targetPos = bhr.getBlockPos(); + WaterWheelStructuralBlock waterWheelStructuralBlock = AllBlocks.WATER_WHEEL_STRUCTURAL.get(); + if (waterWheelStructuralBlock.stillValid(level, targetPos, state, false)) + manager.crack(WaterWheelStructuralBlock.getMaster(level, targetPos, state), bhr.getDirection()); + return true; + } + return IClientBlockExtensions.super.addHitEffects(state, level, target, manager); + } + + @Override + @Nullable + public Set getExtraPositions(ClientLevel level, BlockPos pos, BlockState blockState, int progress) { + WaterWheelStructuralBlock waterWheelStructuralBlock = AllBlocks.WATER_WHEEL_STRUCTURAL.get(); + if (!waterWheelStructuralBlock.stillValid(level, pos, blockState, false)) + return null; + HashSet set = new HashSet<>(); + set.add(WaterWheelStructuralBlock.getMaster(level, pos, blockState)); + return set; + } + } + + @Override + public BlockPos getInformationSource(Level level, BlockPos pos, BlockState state) { + return stillValid(level, pos, state, false) ? getMaster(level, pos, state) : pos; + } + +} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/content/curiosities/ChromaticCompoundColor.java b/src/main/java/com/simibubi/create/content/legacy/ChromaticCompoundColor.java similarity index 95% rename from src/main/java/com/simibubi/create/content/curiosities/ChromaticCompoundColor.java rename to src/main/java/com/simibubi/create/content/legacy/ChromaticCompoundColor.java index 64b108331..6d00c28a1 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/ChromaticCompoundColor.java +++ b/src/main/java/com/simibubi/create/content/legacy/ChromaticCompoundColor.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities; +package com.simibubi.create.content.legacy; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.Color; diff --git a/src/main/java/com/simibubi/create/content/curiosities/ChromaticCompoundItem.java b/src/main/java/com/simibubi/create/content/legacy/ChromaticCompoundItem.java similarity index 87% rename from src/main/java/com/simibubi/create/content/curiosities/ChromaticCompoundItem.java rename to src/main/java/com/simibubi/create/content/legacy/ChromaticCompoundItem.java index 33f0b0934..c79c2f07d 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/ChromaticCompoundItem.java +++ b/src/main/java/com/simibubi/create/content/legacy/ChromaticCompoundItem.java @@ -1,16 +1,16 @@ -package com.simibubi.create.content.curiosities; +package com.simibubi.create.content.legacy; import org.apache.commons.lang3.mutable.MutableBoolean; import com.simibubi.create.AllItems; -import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.config.CRecipes; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour.TransportedResult; +import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour; +import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour.TransportedResult; +import com.simibubi.create.content.kinetics.belt.transport.TransportedItemStack; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.utility.Color; import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.infrastructure.config.AllConfigs; +import com.simibubi.create.infrastructure.config.CRecipes; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -51,13 +51,13 @@ public class ChromaticCompoundItem extends Item { @Override public int getBarWidth(ItemStack stack) { - return Math.round(13.0F * getLight(stack) / AllConfigs.SERVER.recipes.lightSourceCountForRefinedRadiance.get()); + return Math.round(13.0F * getLight(stack) / AllConfigs.server().recipes.lightSourceCountForRefinedRadiance.get()); } @Override public int getBarColor(ItemStack stack) { return Color.mixColors(0x413c69, 0xFFFFFF, - getLight(stack) / (float) AllConfigs.SERVER.recipes.lightSourceCountForRefinedRadiance.get()); + getLight(stack) / (float) AllConfigs.server().recipes.lightSourceCountForRefinedRadiance.get()); } @Override @@ -71,7 +71,7 @@ public class ChromaticCompoundItem extends Item { CompoundTag itemData = entity.getItem() .getOrCreateTag(); Vec3 positionVec = entity.position(); - CRecipes config = AllConfigs.SERVER.recipes; + CRecipes config = AllConfigs.server().recipes; if (world.isClientSide) { int light = itemData.getInt("CollectingLight"); @@ -133,12 +133,12 @@ public class ChromaticCompoundItem extends Item { if (state.getLightBlock(world, testPos) >= 15 && state.getBlock() != Blocks.BEDROCK) break; if (state.getBlock() == Blocks.BEACON) { - BlockEntity te = world.getBlockEntity(testPos); + BlockEntity be = world.getBlockEntity(testPos); - if (!(te instanceof BeaconBlockEntity)) + if (!(be instanceof BeaconBlockEntity)) break; - BeaconBlockEntity bte = (BeaconBlockEntity) te; + BeaconBlockEntity bte = (BeaconBlockEntity) be; if (!bte.beamSections.isEmpty()) isOverBeacon = true; @@ -166,7 +166,7 @@ public class ChromaticCompoundItem extends Item { BlockState state = world.getBlockState(randomOffset); TransportedItemStackHandlerBehaviour behaviour = - TileEntityBehaviour.get(world, randomOffset, TransportedItemStackHandlerBehaviour.TYPE); + BlockEntityBehaviour.get(world, randomOffset, TransportedItemStackHandlerBehaviour.TYPE); // Find a placed light source if (behaviour == null) { diff --git a/src/main/java/com/simibubi/create/content/curiosities/NoGravMagicalDohickyItem.java b/src/main/java/com/simibubi/create/content/legacy/NoGravMagicalDohickyItem.java similarity index 97% rename from src/main/java/com/simibubi/create/content/curiosities/NoGravMagicalDohickyItem.java rename to src/main/java/com/simibubi/create/content/legacy/NoGravMagicalDohickyItem.java index 66939bb34..fa2fd441d 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/NoGravMagicalDohickyItem.java +++ b/src/main/java/com/simibubi/create/content/legacy/NoGravMagicalDohickyItem.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities; +package com.simibubi.create.content.legacy; import com.simibubi.create.foundation.utility.VecHelper; diff --git a/src/main/java/com/simibubi/create/content/curiosities/RefinedRadianceItem.java b/src/main/java/com/simibubi/create/content/legacy/RefinedRadianceItem.java similarity index 91% rename from src/main/java/com/simibubi/create/content/curiosities/RefinedRadianceItem.java rename to src/main/java/com/simibubi/create/content/legacy/RefinedRadianceItem.java index 03ca5850b..577f0051c 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/RefinedRadianceItem.java +++ b/src/main/java/com/simibubi/create/content/legacy/RefinedRadianceItem.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities; +package com.simibubi.create.content.legacy; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.entity.item.ItemEntity; diff --git a/src/main/java/com/simibubi/create/content/curiosities/ShadowSteelItem.java b/src/main/java/com/simibubi/create/content/legacy/ShadowSteelItem.java similarity index 93% rename from src/main/java/com/simibubi/create/content/curiosities/ShadowSteelItem.java rename to src/main/java/com/simibubi/create/content/legacy/ShadowSteelItem.java index fa7c42ca8..9d85d2b1a 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/ShadowSteelItem.java +++ b/src/main/java/com/simibubi/create/content/legacy/ShadowSteelItem.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities; +package com.simibubi.create.content.legacy; import net.minecraft.nbt.CompoundTag; import net.minecraft.util.Mth; diff --git a/src/main/java/com/simibubi/create/content/logistics/IRedstoneLinkable.java b/src/main/java/com/simibubi/create/content/logistics/IRedstoneLinkable.java deleted file mode 100644 index 1fa782796..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/IRedstoneLinkable.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.simibubi.create.content.logistics; - -import com.simibubi.create.content.logistics.RedstoneLinkNetworkHandler.Frequency; -import com.simibubi.create.foundation.utility.Couple; - -import net.minecraft.core.BlockPos; - -public interface IRedstoneLinkable { - - public int getTransmittedStrength(); - - public void setReceivedStrength(int power); - - public boolean isListening(); - - public boolean isAlive(); - - public Couple getNetworkKey(); - - public BlockPos getLocation(); - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelRenderer.java b/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelRenderer.java deleted file mode 100644 index fbf919596..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelRenderer.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.simibubi.create.content.logistics.block.belts.tunnel; - -import com.jozufozu.flywheel.backend.Backend; -import com.jozufozu.flywheel.util.transform.TransformStack; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.tileEntity.renderer.SmartTileEntityRenderer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.util.Mth; -import net.minecraft.world.phys.Vec3; - -public class BeltTunnelRenderer extends SmartTileEntityRenderer { - - public BeltTunnelRenderer(BlockEntityRendererProvider.Context context) { - super(context); - } - - @Override - protected void renderSafe(BeltTunnelTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - super.renderSafe(te, partialTicks, ms, buffer, light, overlay); - - if (Backend.canUseInstancing(te.getLevel())) - return; - - SuperByteBuffer flapBuffer = CachedBufferer.partial(AllBlockPartials.BELT_TUNNEL_FLAP, te.getBlockState()); - VertexConsumer vb = buffer.getBuffer(RenderType.solid()); - Vec3 pivot = VecHelper.voxelSpace(0, 10, 1f); - TransformStack msr = TransformStack.cast(ms); - - for (Direction direction : Iterate.directions) { - if (!te.flaps.containsKey(direction)) - continue; - - float horizontalAngle = AngleHelper.horizontalAngle(direction.getOpposite()); - float f = te.flaps.get(direction) - .getValue(partialTicks); - - ms.pushPose(); - msr.centre() - .rotateY(horizontalAngle) - .unCentre(); - - for (int segment = 0; segment <= 3; segment++) { - ms.pushPose(); - float intensity = segment == 3 ? 1.5f : segment + 1; - float abs = Math.abs(f); - float flapAngle = Mth.sin((float) ((1 - abs) * Math.PI * intensity)) * 30 * f - * (direction.getAxis() == Axis.X ? 1 : -1); - if (f > 0) - flapAngle *= .5f; - - msr.translate(pivot) - .rotateX(flapAngle) - .translateBack(pivot); - flapBuffer.light(light) - .renderInto(ms, vb); - - ms.popPose(); - ms.translate(-3 / 16f, 0, 0); - } - ms.popPose(); - } - - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelTileEntity.java deleted file mode 100644 index f6b2e5b90..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelTileEntity.java +++ /dev/null @@ -1,212 +0,0 @@ -package com.simibubi.create.content.logistics.block.belts.tunnel; - -import java.util.EnumMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.apache.commons.lang3.tuple.Pair; - -import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; -import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelBlock.Shape; -import com.simibubi.create.content.logistics.block.funnel.BeltFunnelBlock; -import com.simibubi.create.content.logistics.packet.TunnelFlapPacket; -import com.simibubi.create.foundation.networking.AllPackets; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.core.Direction.AxisDirection; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.IntTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.Tag; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.fml.DistExecutor; -import net.minecraftforge.items.CapabilityItemHandler; -import net.minecraftforge.items.IItemHandler; - -public class BeltTunnelTileEntity extends SmartTileEntity { - - public Map flaps; - public Set sides; - - protected LazyOptional cap = LazyOptional.empty(); - protected List> flapsToSend; - - public BeltTunnelTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - flaps = new EnumMap<>(Direction.class); - sides = new HashSet<>(); - flapsToSend = new LinkedList<>(); - } - - @Override - public void invalidate() { - super.invalidate(); - cap.invalidate(); - } - - protected void writeFlapsAndSides(CompoundTag compound) { - ListTag flapsNBT = new ListTag(); - for (Direction direction : flaps.keySet()) - flapsNBT.add(IntTag.valueOf(direction.get3DDataValue())); - compound.put("Flaps", flapsNBT); - - ListTag sidesNBT = new ListTag(); - for (Direction direction : sides) - sidesNBT.add(IntTag.valueOf(direction.get3DDataValue())); - compound.put("Sides", sidesNBT); - } - - @Override - public void writeSafe(CompoundTag tag) { - writeFlapsAndSides(tag); - super.writeSafe(tag); - } - - @Override - public void write(CompoundTag compound, boolean clientPacket) { - writeFlapsAndSides(compound); - super.write(compound, clientPacket); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - Set newFlaps = new HashSet<>(6); - ListTag flapsNBT = compound.getList("Flaps", Tag.TAG_INT); - for (Tag inbt : flapsNBT) - if (inbt instanceof IntTag) - newFlaps.add(Direction.from3DDataValue(((IntTag) inbt).getAsInt())); - - sides.clear(); - ListTag sidesNBT = compound.getList("Sides", Tag.TAG_INT); - for (Tag inbt : sidesNBT) - if (inbt instanceof IntTag) - sides.add(Direction.from3DDataValue(((IntTag) inbt).getAsInt())); - - for (Direction d : Iterate.directions) - if (!newFlaps.contains(d)) - flaps.remove(d); - else if (!flaps.containsKey(d)) - flaps.put(d, createChasingFlap()); - - // Backwards compat - if (!compound.contains("Sides") && compound.contains("Flaps")) - sides.addAll(flaps.keySet()); - super.read(compound, clientPacket); - if (clientPacket) - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(this)); - } - - private LerpedFloat createChasingFlap() { - return LerpedFloat.linear() - .startWithValue(.25f) - .chase(0, .05f, Chaser.EXP); - } - - public void updateTunnelConnections() { - flaps.clear(); - sides.clear(); - BlockState tunnelState = getBlockState(); - for (Direction direction : Iterate.horizontalDirections) { - if (direction.getAxis() != tunnelState.getValue(BlockStateProperties.HORIZONTAL_AXIS)) { - boolean positive = - direction.getAxisDirection() == AxisDirection.POSITIVE ^ direction.getAxis() == Axis.Z; - Shape shape = tunnelState.getValue(BeltTunnelBlock.SHAPE); - if (BeltTunnelBlock.isStraight(tunnelState)) - continue; - if (positive && shape == Shape.T_LEFT) - continue; - if (!positive && shape == Shape.T_RIGHT) - continue; - } - - sides.add(direction); - - // Flap might be occluded - BlockState nextState = level.getBlockState(worldPosition.relative(direction)); - if (nextState.getBlock() instanceof BeltTunnelBlock) - continue; - if (nextState.getBlock() instanceof BeltFunnelBlock) - if (nextState.getValue(BeltFunnelBlock.SHAPE) == BeltFunnelBlock.Shape.EXTENDED - && nextState.getValue(BeltFunnelBlock.HORIZONTAL_FACING) == direction.getOpposite()) - continue; - - flaps.put(direction, createChasingFlap()); - } - sendData(); - } - - public void flap(Direction side, boolean inward) { - if (level.isClientSide) { - if (flaps.containsKey(side)) - flaps.get(side) - .setValue(inward ^ side.getAxis() == Axis.Z ? -1 : 1); - return; - } - - flapsToSend.add(Pair.of(side, inward)); - } - - @Override - public void initialize() { - super.initialize(); - updateTunnelConnections(); - } - - @Override - public void tick() { - super.tick(); - if (!level.isClientSide) { - if (!flapsToSend.isEmpty()) - sendFlaps(); - return; - } - flaps.forEach((d, value) -> value.tickChaser()); - } - - private void sendFlaps() { - AllPackets.channel.send(packetTarget(), new TunnelFlapPacket(this, flapsToSend)); - - flapsToSend.clear(); - } - - @Override - public void addBehaviours(List behaviours) {} - - @Override - public LazyOptional getCapability(Capability capability, Direction side) { - if (capability != CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) - return super.getCapability(capability, side); - - if (!this.cap.isPresent()) { - if (AllBlocks.BELT.has(level.getBlockState(worldPosition.below()))) { - BlockEntity teBelow = level.getBlockEntity(worldPosition.below()); - if (teBelow != null) { - T capBelow = teBelow.getCapability(capability, Direction.UP) - .orElse(null); - if (capBelow != null) { - cap = LazyOptional.of(() -> capBelow) - .cast(); - } - } - } - } - return this.cap.cast(); - } -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BrassTunnelCTBehaviour.java b/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BrassTunnelCTBehaviour.java deleted file mode 100644 index a903c7497..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BrassTunnelCTBehaviour.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.simibubi.create.content.logistics.block.belts.tunnel; - -import org.jetbrains.annotations.Nullable; - -import com.simibubi.create.AllSpriteShifts; -import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry; -import com.simibubi.create.foundation.block.connected.ConnectedTextureBehaviour; - -import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.BlockAndTintGetter; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; - -public class BrassTunnelCTBehaviour extends ConnectedTextureBehaviour.Base { - - @Override - public CTSpriteShiftEntry getShift(BlockState state, Direction direction, @Nullable TextureAtlasSprite sprite) { - return direction == Direction.UP ? AllSpriteShifts.BRASS_TUNNEL_TOP : null; - } - - @Override - public boolean connectsTo(BlockState state, BlockState other, BlockAndTintGetter reader, BlockPos pos, BlockPos otherPos, - Direction face) { - int yDiff = otherPos.getY() - pos.getY(); - int zDiff = otherPos.getZ() - pos.getZ(); - if (yDiff != 0) - return false; - - BlockEntity te = reader.getBlockEntity(pos); - if (!(te instanceof BrassTunnelTileEntity)) - return false; - BrassTunnelTileEntity tunnelTE = (BrassTunnelTileEntity) te; - boolean leftSide = zDiff > 0; - return tunnelTE.isConnected(leftSide); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BrassTunnelFilterSlot.java b/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BrassTunnelFilterSlot.java deleted file mode 100644 index 66c9aa1d9..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BrassTunnelFilterSlot.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.simibubi.create.content.logistics.block.belts.tunnel; - -import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.world.phys.Vec3; - -public class BrassTunnelFilterSlot extends ValueBoxTransform.Sided { - - @Override - protected Vec3 getSouthLocation() { - return VecHelper.voxelSpace(8, 13, 15.5f); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BrassTunnelItemHandler.java b/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BrassTunnelItemHandler.java deleted file mode 100644 index c9d7b1017..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BrassTunnelItemHandler.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.simibubi.create.content.logistics.block.belts.tunnel; - -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.items.IItemHandler; - -public class BrassTunnelItemHandler implements IItemHandler { - - private BrassTunnelTileEntity te; - - public BrassTunnelItemHandler(BrassTunnelTileEntity te) { - this.te = te; - } - - @Override - public int getSlots() { - return 1; - } - - @Override - public ItemStack getStackInSlot(int slot) { - return te.stackToDistribute; - } - - @Override - public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) { - if (!te.hasDistributionBehaviour()) { - LazyOptional beltCapability = te.getBeltCapability(); - if (!beltCapability.isPresent()) - return stack; - return beltCapability.orElse(null).insertItem(slot, stack, simulate); - } - - if (!te.canTakeItems()) - return stack; - if (!simulate) - te.setStackToDistribute(stack, null); - return ItemStack.EMPTY; - } - - @Override - public ItemStack extractItem(int slot, int amount, boolean simulate) { - LazyOptional beltCapability = te.getBeltCapability(); - if (!beltCapability.isPresent()) - return ItemStack.EMPTY; - return beltCapability.orElse(null).extractItem(slot, amount, simulate); - } - - @Override - public int getSlotLimit(int slot) { - return te.stackToDistribute.isEmpty() ? 64 : te.stackToDistribute.getMaxStackSize(); - } - - @Override - public boolean isItemValid(int slot, ItemStack stack) { - return true; - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BrassTunnelTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BrassTunnelTileEntity.java deleted file mode 100644 index c45ceff6b..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BrassTunnelTileEntity.java +++ /dev/null @@ -1,802 +0,0 @@ -package com.simibubi.create.content.logistics.block.belts.tunnel; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.IdentityHashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Random; -import java.util.Set; - -import javax.annotation.Nullable; - -import org.apache.commons.lang3.tuple.Pair; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation; -import com.simibubi.create.content.contraptions.relays.belt.BeltHelper; -import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity; -import com.simibubi.create.content.logistics.block.funnel.BeltFunnelBlock; -import com.simibubi.create.content.logistics.block.funnel.BeltFunnelBlock.Shape; -import com.simibubi.create.content.logistics.block.funnel.FunnelBlock; -import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.CenteredSideValueBoxTransform; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.filtering.SidedFilteringBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.INamedIconOptions; -import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollOptionBehaviour; -import com.simibubi.create.foundation.utility.BlockHelper; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.NBTHelper; - -import net.minecraft.ChatFormatting; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.core.Direction.AxisDirection; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtUtils; -import net.minecraft.nbt.Tag; -import net.minecraft.network.chat.Component; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.items.CapabilityItemHandler; -import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.ItemHandlerHelper; - -public class BrassTunnelTileEntity extends BeltTunnelTileEntity implements IHaveGoggleInformation { - - SidedFilteringBehaviour filtering; - - boolean connectedLeft; - boolean connectedRight; - - ItemStack stackToDistribute; - Direction stackEnteredFrom; - - float distributionProgress; - int distributionDistanceLeft; - int distributionDistanceRight; - int previousOutputIndex; - - // - Couple>> distributionTargets; - - private boolean syncedOutputActive; - private Set syncSet; - - protected ScrollOptionBehaviour selectionMode; - private LazyOptional beltCapability; - private LazyOptional tunnelCapability; - - public BrassTunnelTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - distributionTargets = Couple.create(ArrayList::new); - syncSet = new HashSet<>(); - stackToDistribute = ItemStack.EMPTY; - stackEnteredFrom = null; - beltCapability = LazyOptional.empty(); - tunnelCapability = LazyOptional.of(() -> new BrassTunnelItemHandler(this)); - previousOutputIndex = 0; - syncedOutputActive = false; - } - - @Override - public void addBehaviours(List behaviours) { - super.addBehaviours(behaviours); - behaviours.add(selectionMode = new ScrollOptionBehaviour<>(SelectionMode.class, - Lang.translateDirect("logistics.when_multiple_outputs_available"), this, - new CenteredSideValueBoxTransform((state, d) -> d == Direction.UP))); - selectionMode.requiresWrench(); - - // Propagate settings across connected tunnels - selectionMode.withCallback(setting -> { - for (boolean side : Iterate.trueAndFalse) { - if (!isConnected(side)) - continue; - BrassTunnelTileEntity adjacent = getAdjacent(side); - if (adjacent != null) - adjacent.selectionMode.setValue(setting); - } - }); - } - - @Override - public void tick() { - super.tick(); - BeltTileEntity beltBelow = BeltHelper.getSegmentTE(level, worldPosition.below()); - - if (distributionProgress > 0) - distributionProgress--; - if (beltBelow == null || beltBelow.getSpeed() == 0) - return; - if (stackToDistribute.isEmpty() && !syncedOutputActive) - return; - if (level.isClientSide && !isVirtual()) - return; - - if (distributionProgress == -1) { - distributionTargets.forEach(List::clear); - distributionDistanceLeft = 0; - distributionDistanceRight = 0; - - syncSet.clear(); - List> validOutputs = gatherValidOutputs(); - if (selectionMode.get() == SelectionMode.SYNCHRONIZE) { - boolean allEmpty = true; - boolean allFull = true; - for (BrassTunnelTileEntity te : syncSet) { - boolean hasStack = !te.stackToDistribute.isEmpty(); - allEmpty &= !hasStack; - allFull &= hasStack; - } - final boolean notifySyncedOut = !allEmpty; - if (allFull || allEmpty) - syncSet.forEach(te -> te.syncedOutputActive = notifySyncedOut); - } - - if (validOutputs == null) - return; - if (stackToDistribute.isEmpty()) - return; - - for (Pair pair : validOutputs) { - BrassTunnelTileEntity tunnel = pair.getKey(); - Direction output = pair.getValue(); - if (insertIntoTunnel(tunnel, output, stackToDistribute, true) == null) - continue; - distributionTargets.get(!tunnel.flapFilterEmpty(output)) - .add(Pair.of(tunnel.worldPosition, output)); - int distance = tunnel.worldPosition.getX() + tunnel.worldPosition.getZ() - worldPosition.getX() - worldPosition.getZ(); - if (distance < 0) - distributionDistanceLeft = Math.max(distributionDistanceLeft, -distance); - else - distributionDistanceRight = Math.max(distributionDistanceRight, distance); - } - - if (distributionTargets.getFirst() - .isEmpty() - && distributionTargets.getSecond() - .isEmpty()) - return; - - if (selectionMode.get() != SelectionMode.SYNCHRONIZE || syncedOutputActive) { - distributionProgress = 10; - sendData(); - } - return; - } - - if (distributionProgress != 0) - return; - - distributionTargets.forEach(list -> { - if (stackToDistribute.isEmpty()) - return; - List> validTargets = new ArrayList<>(); - for (Pair pair : list) { - BlockPos tunnelPos = pair.getKey(); - Direction output = pair.getValue(); - if (tunnelPos.equals(worldPosition) && output == stackEnteredFrom) - continue; - BlockEntity te = level.getBlockEntity(tunnelPos); - if (!(te instanceof BrassTunnelTileEntity)) - continue; - validTargets.add(Pair.of((BrassTunnelTileEntity) te, output)); - } - distribute(validTargets); - distributionProgress = -1; - }); - } - - private static Random rand = new Random(); - private static Map, ItemStack> distributed = new IdentityHashMap<>(); - private static Set> full = new HashSet<>(); - - private void distribute(List> validTargets) { - int amountTargets = validTargets.size(); - if (amountTargets == 0) - return; - - distributed.clear(); - full.clear(); - - int indexStart = previousOutputIndex % amountTargets; - SelectionMode mode = selectionMode.get(); - boolean force = mode == SelectionMode.FORCED_ROUND_ROBIN || mode == SelectionMode.FORCED_SPLIT; - boolean split = mode == SelectionMode.FORCED_SPLIT || mode == SelectionMode.SPLIT; - boolean robin = mode == SelectionMode.FORCED_ROUND_ROBIN || mode == SelectionMode.ROUND_ROBIN; - - if (mode == SelectionMode.RANDOMIZE) - indexStart = rand.nextInt(amountTargets); - if (mode == SelectionMode.PREFER_NEAREST || mode == SelectionMode.SYNCHRONIZE) - indexStart = 0; - - ItemStack toDistribute = stackToDistribute.copy(); - for (boolean distributeAgain : Iterate.trueAndFalse) { - ItemStack toDistributeThisCycle = null; - int remainingOutputs = amountTargets; - int leftovers = 0; - - for (boolean simulate : Iterate.trueAndFalse) { - if (remainingOutputs == 0) - break; - - leftovers = 0; - int index = indexStart; - int stackSize = toDistribute.getCount(); - int splitStackSize = stackSize / remainingOutputs; - int splitRemainder = stackSize % remainingOutputs; - int visited = 0; - - toDistributeThisCycle = toDistribute.copy(); - if (!(force || split) && simulate) - continue; - - while (visited < amountTargets) { - Pair pair = validTargets.get(index); - BrassTunnelTileEntity tunnel = pair.getKey(); - Direction side = pair.getValue(); - index = (index + 1) % amountTargets; - visited++; - - if (full.contains(pair)) { - if (split && simulate) - remainingOutputs--; - continue; - } - - int count = split ? splitStackSize + (splitRemainder > 0 ? 1 : 0) : stackSize; - ItemStack toOutput = ItemHandlerHelper.copyStackWithSize(toDistributeThisCycle, count); - - // Grow by 1 to determine if target is full even after a successful transfer - boolean testWithIncreasedCount = distributed.containsKey(pair); - int increasedCount = testWithIncreasedCount ? distributed.get(pair) - .getCount() : 0; - if (testWithIncreasedCount) - toOutput.grow(increasedCount); - - ItemStack remainder = insertIntoTunnel(tunnel, side, toOutput, true); - - if (remainder == null || remainder.getCount() == (testWithIncreasedCount ? count + 1 : count)) { - if (force) - return; - if (split && simulate) - remainingOutputs--; - if (!simulate) - full.add(pair); - if (robin) - break; - continue; - } else if (!remainder.isEmpty() && !simulate) { - full.add(pair); - } - - if (!simulate) { - toOutput.shrink(remainder.getCount()); - distributed.put(pair, toOutput); - } - - leftovers += remainder.getCount(); - toDistributeThisCycle.shrink(count); - if (toDistributeThisCycle.isEmpty()) - break; - splitRemainder--; - if (!split) - break; - } - } - - toDistribute.setCount(toDistributeThisCycle.getCount() + leftovers); - if (leftovers == 0 && distributeAgain) - break; - if (!split) - break; - } - - int failedTransferrals = 0; - for (Entry, ItemStack> entry : distributed.entrySet()) { - Pair pair = entry.getKey(); - failedTransferrals += insertIntoTunnel(pair.getKey(), pair.getValue(), entry.getValue(), false).getCount(); - } - - toDistribute.grow(failedTransferrals); - stackToDistribute = ItemHandlerHelper.copyStackWithSize(stackToDistribute, toDistribute.getCount()); - if (stackToDistribute.isEmpty()) - stackEnteredFrom = null; - previousOutputIndex++; - previousOutputIndex %= amountTargets; - notifyUpdate(); - } - - public void setStackToDistribute(ItemStack stack, @Nullable Direction enteredFrom) { - stackToDistribute = stack; - stackEnteredFrom = enteredFrom; - distributionProgress = -1; - sendData(); - setChanged(); - } - - public ItemStack getStackToDistribute() { - return stackToDistribute; - } - - public List grabAllStacksOfGroup(boolean simulate) { - List list = new ArrayList<>(); - - ItemStack own = getStackToDistribute(); - if (!own.isEmpty()) { - list.add(own); - if (!simulate) - setStackToDistribute(ItemStack.EMPTY, null); - } - - for (boolean left : Iterate.trueAndFalse) { - BrassTunnelTileEntity adjacent = this; - while (adjacent != null) { - if (!level.isLoaded(adjacent.getBlockPos())) - return null; - adjacent = adjacent.getAdjacent(left); - if (adjacent == null) - continue; - ItemStack other = adjacent.getStackToDistribute(); - if (other.isEmpty()) - continue; - list.add(other); - if (!simulate) - adjacent.setStackToDistribute(ItemStack.EMPTY, null); - } - } - - return list; - } - - @Nullable - protected ItemStack insertIntoTunnel(BrassTunnelTileEntity tunnel, Direction side, ItemStack stack, - boolean simulate) { - if (stack.isEmpty()) - return stack; - if (!tunnel.testFlapFilter(side, stack)) - return null; - - BeltTileEntity below = BeltHelper.getSegmentTE(level, tunnel.worldPosition.below()); - if (below == null) - return null; - BlockPos offset = tunnel.getBlockPos() - .below() - .relative(side); - DirectBeltInputBehaviour sideOutput = TileEntityBehaviour.get(level, offset, DirectBeltInputBehaviour.TYPE); - if (sideOutput != null) { - if (!sideOutput.canInsertFromSide(side)) - return null; - ItemStack result = sideOutput.handleInsertion(stack, side, simulate); - if (result.isEmpty() && !simulate) - tunnel.flap(side, false); - return result; - } - - Direction movementFacing = below.getMovementFacing(); - if (side == movementFacing) - if (!BlockHelper.hasBlockSolidSide(level.getBlockState(offset), level, offset, side.getOpposite())) { - BeltTileEntity controllerTE = below.getControllerTE(); - if (controllerTE == null) - return null; - - if (!simulate) { - tunnel.flap(side, true); - ItemStack ejected = stack; - float beltMovementSpeed = below.getDirectionAwareBeltMovementSpeed(); - float movementSpeed = Math.max(Math.abs(beltMovementSpeed), 1 / 8f); - int additionalOffset = beltMovementSpeed > 0 ? 1 : 0; - Vec3 outPos = BeltHelper.getVectorForOffset(controllerTE, below.index + additionalOffset); - Vec3 outMotion = Vec3.atLowerCornerOf(side.getNormal()) - .scale(movementSpeed) - .add(0, 1 / 8f, 0); - outPos.add(outMotion.normalize()); - ItemEntity entity = new ItemEntity(level, outPos.x, outPos.y + 6 / 16f, outPos.z, ejected); - entity.setDeltaMovement(outMotion); - entity.setDefaultPickUpDelay(); - entity.hurtMarked = true; - level.addFreshEntity(entity); - } - - return ItemStack.EMPTY; - } - - return null; - } - - public boolean testFlapFilter(Direction side, ItemStack stack) { - if (filtering == null) - return false; - if (filtering.get(side) == null) { - FilteringBehaviour adjacentFilter = - TileEntityBehaviour.get(level, worldPosition.relative(side), FilteringBehaviour.TYPE); - if (adjacentFilter == null) - return true; - return adjacentFilter.test(stack); - } - return filtering.test(side, stack); - } - - public boolean flapFilterEmpty(Direction side) { - if (filtering == null) - return false; - if (filtering.get(side) == null) { - FilteringBehaviour adjacentFilter = - TileEntityBehaviour.get(level, worldPosition.relative(side), FilteringBehaviour.TYPE); - if (adjacentFilter == null) - return true; - return adjacentFilter.getFilter() - .isEmpty(); - } - return filtering.getFilter(side) - .isEmpty(); - } - - @Override - public void initialize() { - if (filtering == null) { - filtering = createSidedFilter(); - attachBehaviourLate(filtering); - } - super.initialize(); - } - - public boolean canInsert(Direction side, ItemStack stack) { - if (filtering != null && !filtering.test(side, stack)) - return false; - if (!hasDistributionBehaviour()) - return true; - if (!stackToDistribute.isEmpty()) - return false; - return true; - } - - public boolean hasDistributionBehaviour() { - if (flaps.isEmpty()) - return false; - if (connectedLeft || connectedRight) - return true; - BlockState blockState = getBlockState(); - if (!AllBlocks.BRASS_TUNNEL.has(blockState)) - return false; - Axis axis = blockState.getValue(BrassTunnelBlock.HORIZONTAL_AXIS); - for (Direction direction : flaps.keySet()) - if (direction.getAxis() != axis) - return true; - return false; - } - - private List> gatherValidOutputs() { - List> validOutputs = new ArrayList<>(); - boolean synchronize = selectionMode.get() == SelectionMode.SYNCHRONIZE; - addValidOutputsOf(this, validOutputs); - - for (boolean left : Iterate.trueAndFalse) { - BrassTunnelTileEntity adjacent = this; - while (adjacent != null) { - if (!level.isLoaded(adjacent.getBlockPos())) - return null; - adjacent = adjacent.getAdjacent(left); - if (adjacent == null) - continue; - addValidOutputsOf(adjacent, validOutputs); - } - } - - if (!syncedOutputActive && synchronize) - return null; - return validOutputs; - } - - private void addValidOutputsOf(BrassTunnelTileEntity tunnelTE, - List> validOutputs) { - syncSet.add(tunnelTE); - BeltTileEntity below = BeltHelper.getSegmentTE(level, tunnelTE.worldPosition.below()); - if (below == null) - return; - Direction movementFacing = below.getMovementFacing(); - BlockState blockState = getBlockState(); - if (!AllBlocks.BRASS_TUNNEL.has(blockState)) - return; - - boolean prioritizeSides = tunnelTE == this; - - for (boolean sidePass : Iterate.trueAndFalse) { - if (!prioritizeSides && sidePass) - continue; - for (Direction direction : Iterate.horizontalDirections) { - if (direction == movementFacing && below.getSpeed() == 0) - continue; - if (prioritizeSides && sidePass == (direction.getAxis() == movementFacing.getAxis())) - continue; - if (direction == movementFacing.getOpposite()) - continue; - if (!tunnelTE.sides.contains(direction)) - continue; - - BlockPos offset = tunnelTE.worldPosition.below() - .relative(direction); - - BlockState potentialFunnel = level.getBlockState(offset.above()); - if (potentialFunnel.getBlock() instanceof BeltFunnelBlock - && potentialFunnel.getValue(BeltFunnelBlock.SHAPE) == Shape.PULLING - && FunnelBlock.getFunnelFacing(potentialFunnel) == direction) - continue; - - DirectBeltInputBehaviour inputBehaviour = - TileEntityBehaviour.get(level, offset, DirectBeltInputBehaviour.TYPE); - if (inputBehaviour == null) { - if (direction == movementFacing) - if (!BlockHelper.hasBlockSolidSide(level.getBlockState(offset), level, offset, - direction.getOpposite())) - validOutputs.add(Pair.of(tunnelTE, direction)); - continue; - } - if (inputBehaviour.canInsertFromSide(direction)) - validOutputs.add(Pair.of(tunnelTE, direction)); - continue; - } - } - } - - @Override - public void addBehavioursDeferred(List behaviours) { - super.addBehavioursDeferred(behaviours); - filtering = createSidedFilter(); - behaviours.add(filtering); - } - - protected SidedFilteringBehaviour createSidedFilter() { - return new SidedFilteringBehaviour(this, new BrassTunnelFilterSlot(), this::makeFilter, - this::isValidFaceForFilter); - } - - private FilteringBehaviour makeFilter(Direction side, FilteringBehaviour filter) { - return filter; - } - - private boolean isValidFaceForFilter(Direction side) { - return sides.contains(side); - } - - @Override - public void write(CompoundTag compound, boolean clientPacket) { - compound.putBoolean("SyncedOutput", syncedOutputActive); - compound.putBoolean("ConnectedLeft", connectedLeft); - compound.putBoolean("ConnectedRight", connectedRight); - - compound.put("StackToDistribute", stackToDistribute.serializeNBT()); - if (stackEnteredFrom != null) - NBTHelper.writeEnum(compound, "StackEnteredFrom", stackEnteredFrom); - - compound.putFloat("DistributionProgress", distributionProgress); - compound.putInt("PreviousIndex", previousOutputIndex); - compound.putInt("DistanceLeft", distributionDistanceLeft); - compound.putInt("DistanceRight", distributionDistanceRight); - - for (boolean filtered : Iterate.trueAndFalse) { - compound.put(filtered ? "FilteredTargets" : "Targets", - NBTHelper.writeCompoundList(distributionTargets.get(filtered), pair -> { - CompoundTag nbt = new CompoundTag(); - nbt.put("Pos", NbtUtils.writeBlockPos(pair.getKey())); - nbt.putInt("Face", pair.getValue() - .get3DDataValue()); - return nbt; - })); - } - - super.write(compound, clientPacket); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - boolean wasConnectedLeft = connectedLeft; - boolean wasConnectedRight = connectedRight; - - syncedOutputActive = compound.getBoolean("SyncedOutput"); - connectedLeft = compound.getBoolean("ConnectedLeft"); - connectedRight = compound.getBoolean("ConnectedRight"); - - stackToDistribute = ItemStack.of(compound.getCompound("StackToDistribute")); - stackEnteredFrom = - compound.contains("StackEnteredFrom") ? NBTHelper.readEnum(compound, "StackEnteredFrom", Direction.class) - : null; - - distributionProgress = compound.getFloat("DistributionProgress"); - previousOutputIndex = compound.getInt("PreviousIndex"); - distributionDistanceLeft = compound.getInt("DistanceLeft"); - distributionDistanceRight = compound.getInt("DistanceRight"); - - for (boolean filtered : Iterate.trueAndFalse) { - distributionTargets.set(filtered, NBTHelper - .readCompoundList(compound.getList(filtered ? "FilteredTargets" : "Targets", Tag.TAG_COMPOUND), nbt -> { - BlockPos pos = NbtUtils.readBlockPos(nbt.getCompound("Pos")); - Direction face = Direction.from3DDataValue(nbt.getInt("Face")); - return Pair.of(pos, face); - })); - } - - super.read(compound, clientPacket); - - if (!clientPacket) - return; - if (wasConnectedLeft != connectedLeft || wasConnectedRight != connectedRight) { - requestModelDataUpdate(); - if (hasLevel()) - level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 16); - } - filtering.updateFilterPresence(); - } - - public boolean isConnected(boolean leftSide) { - return leftSide ? connectedLeft : connectedRight; - } - - @Override - public void updateTunnelConnections() { - super.updateTunnelConnections(); - boolean connectivityChanged = false; - boolean nowConnectedLeft = determineIfConnected(true); - boolean nowConnectedRight = determineIfConnected(false); - - if (connectedLeft != nowConnectedLeft) { - connectedLeft = nowConnectedLeft; - connectivityChanged = true; - BrassTunnelTileEntity adjacent = getAdjacent(true); - if (adjacent != null && !level.isClientSide) { - adjacent.updateTunnelConnections(); - adjacent.selectionMode.setValue(selectionMode.getValue()); - } - } - - if (connectedRight != nowConnectedRight) { - connectedRight = nowConnectedRight; - connectivityChanged = true; - BrassTunnelTileEntity adjacent = getAdjacent(false); - if (adjacent != null && !level.isClientSide) { - adjacent.updateTunnelConnections(); - adjacent.selectionMode.setValue(selectionMode.getValue()); - } - } - - if (filtering != null) - filtering.updateFilterPresence(); - if (connectivityChanged) - sendData(); - } - - protected boolean determineIfConnected(boolean leftSide) { - if (flaps.isEmpty()) - return false; - BrassTunnelTileEntity adjacentTunnelTE = getAdjacent(leftSide); - return adjacentTunnelTE != null && !adjacentTunnelTE.flaps.isEmpty(); - } - - @Nullable - protected BrassTunnelTileEntity getAdjacent(boolean leftSide) { - if (!hasLevel()) - return null; - - BlockState blockState = getBlockState(); - if (!AllBlocks.BRASS_TUNNEL.has(blockState)) - return null; - - Axis axis = blockState.getValue(BrassTunnelBlock.HORIZONTAL_AXIS); - Direction baseDirection = Direction.get(AxisDirection.POSITIVE, axis); - Direction direction = leftSide ? baseDirection.getCounterClockWise() : baseDirection.getClockWise(); - BlockPos adjacentPos = worldPosition.relative(direction); - BlockState adjacentBlockState = level.getBlockState(adjacentPos); - - if (!AllBlocks.BRASS_TUNNEL.has(adjacentBlockState)) - return null; - if (adjacentBlockState.getValue(BrassTunnelBlock.HORIZONTAL_AXIS) != axis) - return null; - BlockEntity adjacentTE = level.getBlockEntity(adjacentPos); - if (adjacentTE.isRemoved()) - return null; - if (!(adjacentTE instanceof BrassTunnelTileEntity)) - return null; - return (BrassTunnelTileEntity) adjacentTE; - } - - @Override - public void invalidate() { - super.invalidate(); - tunnelCapability.invalidate(); - } - - @Override - public void destroy() { - super.destroy(); - Block.popResource(level, worldPosition, stackToDistribute); - stackEnteredFrom = null; - } - - @Override - public LazyOptional getCapability(Capability capability, Direction side) { - if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) - return tunnelCapability.cast(); - return super.getCapability(capability, side); - } - - public LazyOptional getBeltCapability() { - if (!beltCapability.isPresent()) { - BlockEntity tileEntity = level.getBlockEntity(worldPosition.below()); - if (tileEntity != null) - beltCapability = tileEntity.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY); - } - return beltCapability; - } - - public enum SelectionMode implements INamedIconOptions { - SPLIT(AllIcons.I_TUNNEL_SPLIT), - FORCED_SPLIT(AllIcons.I_TUNNEL_FORCED_SPLIT), - ROUND_ROBIN(AllIcons.I_TUNNEL_ROUND_ROBIN), - FORCED_ROUND_ROBIN(AllIcons.I_TUNNEL_FORCED_ROUND_ROBIN), - PREFER_NEAREST(AllIcons.I_TUNNEL_PREFER_NEAREST), - RANDOMIZE(AllIcons.I_TUNNEL_RANDOMIZE), - SYNCHRONIZE(AllIcons.I_TUNNEL_SYNCHRONIZE), - - ; - - private final String translationKey; - private final AllIcons icon; - - SelectionMode(AllIcons icon) { - this.icon = icon; - this.translationKey = "tunnel.selection_mode." + Lang.asId(name()); - } - - @Override - public AllIcons getIcon() { - return icon; - } - - @Override - public String getTranslationKey() { - return translationKey; - } - } - - public boolean canTakeItems() { - return stackToDistribute.isEmpty() && !syncedOutputActive; - } - - @Override - public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { - List allStacks = grabAllStacksOfGroup(true); - if (allStacks.isEmpty()) - return false; - - tooltip.add(componentSpacing.plainCopy() - .append(Lang.translateDirect("tooltip.brass_tunnel.contains")) - .withStyle(ChatFormatting.WHITE)); - for (ItemStack item : allStacks) { - tooltip.add(componentSpacing.plainCopy() - .append(Lang.translateDirect("tooltip.brass_tunnel.contains_entry", Components.translatable(item.getDescriptionId()) - .getString(), item.getCount())) - .withStyle(ChatFormatting.GRAY)); - } - tooltip.add(componentSpacing.plainCopy() - .append(Lang.translateDirect("tooltip.brass_tunnel.retrieve")) - .withStyle(ChatFormatting.DARK_GRAY)); - - return true; - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/chute/ChuteBlock.java b/src/main/java/com/simibubi/create/content/logistics/block/chute/ChuteBlock.java deleted file mode 100644 index df7f411d3..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/chute/ChuteBlock.java +++ /dev/null @@ -1,155 +0,0 @@ -package com.simibubi.create.content.logistics.block.chute; - -import java.util.HashMap; -import java.util.Map; - -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.logistics.block.funnel.FunnelBlock; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Lang; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.util.StringRepresentable; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.item.context.UseOnContext; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition.Builder; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.block.state.properties.DirectionProperty; -import net.minecraft.world.level.block.state.properties.EnumProperty; -import net.minecraft.world.level.block.state.properties.Property; -import net.minecraft.world.level.pathfinder.PathComputationType; - -public class ChuteBlock extends AbstractChuteBlock { - - public static final Property SHAPE = EnumProperty.create("shape", Shape.class); - public static final DirectionProperty FACING = BlockStateProperties.FACING_HOPPER; - - public ChuteBlock(Properties p_i48440_1_) { - super(p_i48440_1_); - registerDefaultState(defaultBlockState().setValue(SHAPE, Shape.NORMAL) - .setValue(FACING, Direction.DOWN)); - } - - public enum Shape implements StringRepresentable { - INTERSECTION, WINDOW, NORMAL; - - @Override - public String getSerializedName() { - return Lang.asId(name()); - } - } - - @Override - public Direction getFacing(BlockState state) { - return state.getValue(FACING); - } - - @Override - public boolean isOpen(BlockState state) { - return state.getValue(FACING) == Direction.DOWN || state.getValue(SHAPE) == Shape.INTERSECTION; - } - - @Override - public boolean isTransparent(BlockState state) { - return state.getValue(SHAPE) == Shape.WINDOW; - } - - @Override - public InteractionResult onWrenched(BlockState state, UseOnContext context) { - Shape shape = state.getValue(SHAPE); - boolean down = state.getValue(FACING) == Direction.DOWN; - if (!context.getLevel().isClientSide && down && shape != Shape.INTERSECTION) { - context.getLevel() - .setBlockAndUpdate(context.getClickedPos(), - state.setValue(SHAPE, shape == Shape.WINDOW ? Shape.NORMAL : Shape.WINDOW)); - } - return InteractionResult.SUCCESS; - } - - @Override - public BlockState getStateForPlacement(BlockPlaceContext ctx) { - BlockState state = super.getStateForPlacement(ctx); - Direction face = ctx.getClickedFace(); - if (face.getAxis() - .isHorizontal() && !ctx.isSecondaryUseActive()) { - Level world = ctx.getLevel(); - BlockPos pos = ctx.getClickedPos(); - return updateChuteState(state.setValue(FACING, face), world.getBlockState(pos.above()), world, pos); - } - return state; - } - - @Override - protected void createBlockStateDefinition(Builder p_206840_1_) { - super.createBlockStateDefinition(p_206840_1_.add(SHAPE, FACING)); - } - - @Override - public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { - BlockState above = world.getBlockState(pos.above()); - return !isChute(above) || getChuteFacing(above) == Direction.DOWN; - } - - @Override - public BlockState updateChuteState(BlockState state, BlockState above, BlockGetter world, BlockPos pos) { - if (!(state.getBlock() instanceof ChuteBlock)) - return state; - - Map connections = new HashMap<>(); - int amtConnections = 0; - Direction facing = state.getValue(FACING); - boolean vertical = facing == Direction.DOWN; - - if (!vertical) { - BlockState target = world.getBlockState(pos.below() - .relative(facing.getOpposite())); - if (!isChute(target)) - return state.setValue(FACING, Direction.DOWN) - .setValue(SHAPE, Shape.NORMAL); - } - - for (Direction direction : Iterate.horizontalDirections) { - BlockState diagonalInputChute = world.getBlockState(pos.above() - .relative(direction)); - boolean value = - diagonalInputChute.getBlock() instanceof ChuteBlock && diagonalInputChute.getValue(FACING) == direction; - connections.put(direction, value); - if (value) - amtConnections++; - } - - boolean noConnections = amtConnections == 0; - if (vertical) - return state.setValue(SHAPE, - noConnections ? state.getValue(SHAPE) == Shape.WINDOW ? Shape.WINDOW : Shape.NORMAL : Shape.INTERSECTION); - if (noConnections) - return state.setValue(SHAPE, Shape.INTERSECTION); - if (connections.get(Direction.NORTH) && connections.get(Direction.SOUTH)) - return state.setValue(SHAPE, Shape.INTERSECTION); - if (connections.get(Direction.EAST) && connections.get(Direction.WEST)) - return state.setValue(SHAPE, Shape.INTERSECTION); - if (amtConnections == 1 && connections.get(facing) && !(getChuteFacing(above) == Direction.DOWN) - && !(above.getBlock() instanceof FunnelBlock && FunnelBlock.getFunnelFacing(above) == Direction.DOWN)) - return state.setValue(SHAPE, Shape.NORMAL); - return state.setValue(SHAPE, Shape.INTERSECTION); - } - - @Override - public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) { - return false; - } - - @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.CHUTE.get(); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/chute/ChuteItemHandler.java b/src/main/java/com/simibubi/create/content/logistics/block/chute/ChuteItemHandler.java deleted file mode 100644 index b1bb46ff9..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/chute/ChuteItemHandler.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.simibubi.create.content.logistics.block.chute; - -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.items.IItemHandler; - -public class ChuteItemHandler implements IItemHandler { - - private ChuteTileEntity te; - - public ChuteItemHandler(ChuteTileEntity te) { - this.te = te; - } - - @Override - public int getSlots() { - return 1; - } - - @Override - public ItemStack getStackInSlot(int slot) { - return te.item; - } - - @Override - public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) { - if (!te.canAcceptItem(stack)) - return stack; - if (!simulate) - te.setItem(stack); - return ItemStack.EMPTY; - } - - @Override - public ItemStack extractItem(int slot, int amount, boolean simulate) { - ItemStack remainder = te.item.copy(); - ItemStack split = remainder.split(amount); - if (!simulate) - te.setItem(remainder); - return split; - } - - @Override - public int getSlotLimit(int slot) { - return Math.min(64, getStackInSlot(slot).getMaxStackSize()); - } - - @Override - public boolean isItemValid(int slot, ItemStack stack) { - return true; - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/chute/ChuteRenderer.java b/src/main/java/com/simibubi/create/content/logistics/block/chute/ChuteRenderer.java deleted file mode 100644 index 169d45a91..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/chute/ChuteRenderer.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.simibubi.create.content.logistics.block.chute; - -import com.jozufozu.flywheel.util.transform.TransformStack; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.content.logistics.block.chute.ChuteBlock.Shape; -import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.block.model.ItemTransforms.TransformType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.client.renderer.entity.ItemRenderer; -import net.minecraft.core.Direction; -import net.minecraft.world.level.block.state.BlockState; - -public class ChuteRenderer extends SafeTileEntityRenderer { - - public ChuteRenderer(BlockEntityRendererProvider.Context context) {} - - @Override - protected void renderSafe(ChuteTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light, - int overlay) { - if (te.item.isEmpty()) - return; - BlockState blockState = te.getBlockState(); - if (blockState.getValue(ChuteBlock.FACING) != Direction.DOWN) - return; - if (blockState.getValue(ChuteBlock.SHAPE) != Shape.WINDOW - && (te.bottomPullDistance == 0 || te.itemPosition.getValue(partialTicks) > .5f)) - return; - - renderItem(te, partialTicks, ms, buffer, light, overlay); - } - - public static void renderItem(ChuteTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - ItemRenderer itemRenderer = Minecraft.getInstance() - .getItemRenderer(); - TransformStack msr = TransformStack.cast(ms); - ms.pushPose(); - msr.centre(); - float itemScale = .5f; - float itemPosition = te.itemPosition.getValue(partialTicks); - ms.translate(0, -.5 + itemPosition, 0); - ms.scale(itemScale, itemScale, itemScale); - msr.rotateX(itemPosition * 180); - msr.rotateY(itemPosition * 180); - itemRenderer.renderStatic(te.item, TransformType.FIXED, light, overlay, ms, buffer, 0); - ms.popPose(); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/chute/ChuteTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/chute/ChuteTileEntity.java deleted file mode 100644 index 5a854dc9c..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/chute/ChuteTileEntity.java +++ /dev/null @@ -1,788 +0,0 @@ -package com.simibubi.create.content.logistics.block.chute; - -import java.util.LinkedList; -import java.util.List; -import java.util.function.Predicate; - -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.Create; -import com.simibubi.create.content.contraptions.components.fan.AirCurrent; -import com.simibubi.create.content.contraptions.components.fan.EncasedFanBlock; -import com.simibubi.create.content.contraptions.components.fan.EncasedFanTileEntity; -import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation; -import com.simibubi.create.content.contraptions.particle.AirParticleData; -import com.simibubi.create.content.logistics.block.funnel.FunnelBlock; -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.item.ItemHelper; -import com.simibubi.create.foundation.item.ItemHelper.ExtractionCountMode; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour.TransportedResult; -import com.simibubi.create.foundation.utility.BlockHelper; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; - -import net.minecraft.ChatFormatting; -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.particles.ItemParticleOption; -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.util.Mth; -import net.minecraft.world.Containers; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.items.CapabilityItemHandler; -import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.ItemHandlerHelper; - -@ParametersAreNonnullByDefault -@MethodsReturnNonnullByDefault -/* - * Commented Code: Chutes create air streams and act similarly to encased fans - * (Unfinished) - */ -public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInformation { // , IAirCurrentSource { - - // public AirCurrent airCurrent; - - float pull; - float push; - - ItemStack item; - LerpedFloat itemPosition; - ChuteItemHandler itemHandler; - LazyOptional lazyHandler; - boolean canPickUpItems; - - float bottomPullDistance; - float beltBelowOffset; - TransportedItemStackHandlerBehaviour beltBelow; - boolean updateAirFlow; - int airCurrentUpdateCooldown; - int entitySearchCooldown; - - LazyOptional capAbove; - LazyOptional capBelow; - - public ChuteTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - item = ItemStack.EMPTY; - itemPosition = LerpedFloat.linear(); - itemHandler = new ChuteItemHandler(this); - lazyHandler = LazyOptional.of(() -> itemHandler); - canPickUpItems = false; - capAbove = LazyOptional.empty(); - capBelow = LazyOptional.empty(); - bottomPullDistance = 0; - // airCurrent = new AirCurrent(this); - updateAirFlow = true; - } - - @Override - public void addBehaviours(List behaviours) { - behaviours.add(new DirectBeltInputBehaviour(this).onlyInsertWhen((d) -> canDirectlyInsertCached())); - registerAwardables(behaviours, AllAdvancements.CHUTE); - } - - // Cached per-tick, useful when a lot of items are waiting on top of it - public boolean canDirectlyInsertCached() { - return canPickUpItems; - } - - private boolean canDirectlyInsert() { - BlockState blockState = getBlockState(); - BlockState blockStateAbove = level.getBlockState(worldPosition.above()); - if (!AbstractChuteBlock.isChute(blockState)) - return false; - if (AbstractChuteBlock.getChuteFacing(blockStateAbove) == Direction.DOWN) - return false; - if (getItemMotion() > 0 && getInputChutes().isEmpty()) - return false; - return AbstractChuteBlock.isOpenChute(blockState); - } - - @Override - public void initialize() { - super.initialize(); - onAdded(); - } - - @Override - protected AABB createRenderBoundingBox() { - return new AABB(worldPosition).expandTowards(0, -3, 0); - } - - @Override - public void tick() { - super.tick(); - - if (!level.isClientSide) - canPickUpItems = canDirectlyInsert(); - - boolean clientSide = level != null && level.isClientSide && !isVirtual(); - float itemMotion = getItemMotion(); - if (itemMotion != 0 && level != null && level.isClientSide) - spawnParticles(itemMotion); - tickAirStreams(itemMotion); - - if (item.isEmpty() && !clientSide) { - if (itemMotion < 0) - handleInputFromAbove(); - if (itemMotion > 0) - handleInputFromBelow(); - return; - } - - float nextOffset = itemPosition.getValue() + itemMotion; - - if (itemMotion < 0) { - if (nextOffset < .5f) { - if (!handleDownwardOutput(true)) - nextOffset = .5f; - else if (nextOffset < 0) { - handleDownwardOutput(clientSide); - nextOffset = itemPosition.getValue(); - } - } - } else if (itemMotion > 0) { - if (nextOffset > .5f) { - if (!handleUpwardOutput(true)) - nextOffset = .5f; - else if (nextOffset > 1) { - handleUpwardOutput(clientSide); - nextOffset = itemPosition.getValue(); - } - } - } - - itemPosition.setValue(nextOffset); - } - - private void updateAirFlow(float itemSpeed) { - updateAirFlow = false; - // airCurrent.rebuild(); - if (itemSpeed > 0 && level != null && !level.isClientSide) { - float speed = pull - push; - beltBelow = null; - - float maxPullDistance; - if (speed >= 128) - maxPullDistance = 3; - else if (speed >= 64) - maxPullDistance = 2; - else if (speed >= 32) - maxPullDistance = 1; - else - maxPullDistance = Mth.lerp(speed / 32, 0, 1); - - if (AbstractChuteBlock.isChute(level.getBlockState(worldPosition.below()))) - maxPullDistance = 0; - float flowLimit = maxPullDistance; - if (flowLimit > 0) - flowLimit = AirCurrent.getFlowLimit(level, worldPosition, maxPullDistance, Direction.DOWN); - - for (int i = 1; i <= flowLimit + 1; i++) { - TransportedItemStackHandlerBehaviour behaviour = - TileEntityBehaviour.get(level, worldPosition.below(i), TransportedItemStackHandlerBehaviour.TYPE); - if (behaviour == null) - continue; - beltBelow = behaviour; - beltBelowOffset = i - 1; - break; - } - this.bottomPullDistance = Math.max(0, flowLimit); - } - sendData(); - } - - private void findEntities(float itemSpeed) { - // if (getSpeed() != 0) - // airCurrent.findEntities(); - if (bottomPullDistance <= 0 && !getItem().isEmpty() || itemSpeed <= 0 || level == null || level.isClientSide) - return; - if (!canCollectItemsFromBelow()) - return; - Vec3 center = VecHelper.getCenterOf(worldPosition); - AABB searchArea = new AABB(center.add(0, -bottomPullDistance - 0.5, 0), center.add(0, -0.5, 0)).inflate(.45f); - for (ItemEntity itemEntity : level.getEntitiesOfClass(ItemEntity.class, searchArea)) { - if (!itemEntity.isAlive()) - continue; - ItemStack entityItem = itemEntity.getItem(); - if (!canAcceptItem(entityItem)) - continue; - setItem(entityItem.copy(), (float) (itemEntity.getBoundingBox() - .getCenter().y - worldPosition.getY())); - itemEntity.discard(); - break; - } - } - - private void extractFromBelt(float itemSpeed) { - if (itemSpeed <= 0 || level == null || level.isClientSide) - return; - if (getItem().isEmpty() && beltBelow != null) { - beltBelow.handleCenteredProcessingOnAllItems(.5f, ts -> { - if (canAcceptItem(ts.stack)) { - setItem(ts.stack.copy(), -beltBelowOffset); - return TransportedResult.removeItem(); - } - return TransportedResult.doNothing(); - }); - } - } - - private void tickAirStreams(float itemSpeed) { - if (!level.isClientSide && airCurrentUpdateCooldown-- <= 0) { - airCurrentUpdateCooldown = AllConfigs.SERVER.kinetics.fanBlockCheckRate.get(); - updateAirFlow = true; - } - - if (updateAirFlow) { - updateAirFlow(itemSpeed); - } - - if (entitySearchCooldown-- <= 0 && item.isEmpty()) { - entitySearchCooldown = 5; - findEntities(itemSpeed); - } - - extractFromBelt(itemSpeed); - // if (getSpeed() != 0) - // airCurrent.tick(); - } - - public void blockBelowChanged() { - updateAirFlow = true; - capBelow = LazyOptional.empty(); - } - - private void spawnParticles(float itemMotion) { - // todo: reduce the amount of particles - if (level == null) - return; - BlockState blockState = getBlockState(); - boolean up = itemMotion > 0; - float absMotion = up ? itemMotion : -itemMotion; - if (blockState == null || !AbstractChuteBlock.isChute(blockState)) - return; - if (push == 0 && pull == 0) - return; - - if (up && AbstractChuteBlock.isOpenChute(blockState) - && BlockHelper.noCollisionInSpace(level, worldPosition.above())) - spawnAirFlow(1, 2, absMotion, .5f); - - if (AbstractChuteBlock.getChuteFacing(blockState) != Direction.DOWN) - return; - - if (AbstractChuteBlock.isTransparentChute(blockState)) - spawnAirFlow(up ? 0 : 1, up ? 1 : 0, absMotion, 1); - - if (!up && BlockHelper.noCollisionInSpace(level, worldPosition.below())) - spawnAirFlow(0, -1, absMotion, .5f); - - if (up && canCollectItemsFromBelow() && bottomPullDistance > 0) { - spawnAirFlow(-bottomPullDistance, 0, absMotion, 2); - spawnAirFlow(-bottomPullDistance, 0, absMotion, 2); - } - } - - private void spawnAirFlow(float verticalStart, float verticalEnd, float motion, float drag) { - if (level == null) - return; - AirParticleData airParticleData = new AirParticleData(drag, motion); - Vec3 origin = Vec3.atLowerCornerOf(worldPosition); - float xOff = Create.RANDOM.nextFloat() * .5f + .25f; - float zOff = Create.RANDOM.nextFloat() * .5f + .25f; - Vec3 v = origin.add(xOff, verticalStart, zOff); - Vec3 d = origin.add(xOff, verticalEnd, zOff) - .subtract(v); - if (Create.RANDOM.nextFloat() < 2 * motion) - level.addAlwaysVisibleParticle(airParticleData, v.x, v.y, v.z, d.x, d.y, d.z); - } - - private void handleInputFromAbove() { - if (!capAbove.isPresent()) - capAbove = grabCapability(Direction.UP); - handleInput(capAbove.orElse(null), 1); - } - - private void handleInputFromBelow() { - if (!capBelow.isPresent()) - capBelow = grabCapability(Direction.DOWN); - handleInput(capBelow.orElse(null), 0); - } - - private void handleInput(IItemHandler inv, float startLocation) { - if (inv == null) - return; - Predicate canAccept = this::canAcceptItem; - int count = getExtractionAmount(); - ExtractionCountMode mode = getExtractionMode(); - if (mode == ExtractionCountMode.UPTO || !ItemHelper.extract(inv, canAccept, mode, count, true) - .isEmpty()) { - ItemStack extracted = ItemHelper.extract(inv, canAccept, mode, count, false); - if (!extracted.isEmpty()) - setItem(extracted, startLocation); - } - } - - private boolean handleDownwardOutput(boolean simulate) { - BlockState blockState = getBlockState(); - ChuteTileEntity targetChute = getTargetChute(blockState); - Direction direction = AbstractChuteBlock.getChuteFacing(blockState); - - if (level == null || direction == null || !this.canOutputItems()) - return false; - if (!capBelow.isPresent()) - capBelow = grabCapability(Direction.DOWN); - if (capBelow.isPresent()) { - if (level.isClientSide && !isVirtual()) - return false; - ItemStack remainder = ItemHandlerHelper.insertItemStacked(capBelow.orElse(null), item, simulate); - ItemStack held = getItem(); - if (!simulate) - setItem(remainder, itemPosition.getValue(0)); - if (remainder.getCount() != held.getCount()) - return true; - if (direction == Direction.DOWN) - return false; - } - - if (targetChute != null) { - boolean canInsert = targetChute.canAcceptItem(item); - if (!simulate && canInsert) { - targetChute.setItem(item, direction == Direction.DOWN ? 1 : .51f); - setItem(ItemStack.EMPTY); - } - return canInsert; - } - - // Diagonal chutes cannot drop items - if (direction.getAxis() - .isHorizontal()) - return false; - - if (FunnelBlock.getFunnelFacing(level.getBlockState(worldPosition.below())) == Direction.DOWN) - return false; - if (Block.canSupportRigidBlock(level, worldPosition.below())) - return false; - - if (!simulate) { - Vec3 dropVec = VecHelper.getCenterOf(worldPosition) - .add(0, -12 / 16f, 0); - ItemEntity dropped = new ItemEntity(level, dropVec.x, dropVec.y, dropVec.z, item.copy()); - dropped.setDefaultPickUpDelay(); - dropped.setDeltaMovement(0, -.25f, 0); - level.addFreshEntity(dropped); - setItem(ItemStack.EMPTY); - } - - return true; - } - - private boolean handleUpwardOutput(boolean simulate) { - BlockState stateAbove = level.getBlockState(worldPosition.above()); - - if (level == null || !this.canOutputItems()) - return false; - - if (AbstractChuteBlock.isOpenChute(getBlockState())) { - if (!capAbove.isPresent()) - capAbove = grabCapability(Direction.UP); - if (capAbove.isPresent()) { - if (level.isClientSide && !isVirtual() && !ChuteBlock.isChute(stateAbove)) - return false; - int countBefore = item.getCount(); - ItemStack remainder = ItemHandlerHelper.insertItemStacked(capAbove.orElse(null), item, simulate); - if (!simulate) - item = remainder; - return countBefore != remainder.getCount(); - } - } - - ChuteTileEntity bestOutput = null; - List inputChutes = getInputChutes(); - for (ChuteTileEntity targetChute : inputChutes) { - if (!targetChute.canAcceptItem(item)) - continue; - float itemMotion = targetChute.getItemMotion(); - if (itemMotion < 0) - continue; - if (bestOutput == null || bestOutput.getItemMotion() < itemMotion) { - bestOutput = targetChute; - } - } - - if (bestOutput != null) { - if (!simulate) { - bestOutput.setItem(item, 0); - setItem(ItemStack.EMPTY); - } - return true; - } - - if (FunnelBlock.getFunnelFacing(level.getBlockState(worldPosition.above())) == Direction.UP) - return false; - if (BlockHelper.hasBlockSolidSide(stateAbove, level, worldPosition.above(), Direction.DOWN)) - return false; - if (!inputChutes.isEmpty()) - return false; - - if (!simulate) { - Vec3 dropVec = VecHelper.getCenterOf(worldPosition) - .add(0, 8 / 16f, 0); - ItemEntity dropped = new ItemEntity(level, dropVec.x, dropVec.y, dropVec.z, item.copy()); - dropped.setDefaultPickUpDelay(); - dropped.setDeltaMovement(0, getItemMotion() * 2, 0); - level.addFreshEntity(dropped); - setItem(ItemStack.EMPTY); - } - return true; - } - - protected boolean canAcceptItem(ItemStack stack) { - return item.isEmpty(); - } - - protected int getExtractionAmount() { - return 16; - } - - protected ExtractionCountMode getExtractionMode() { - return ExtractionCountMode.UPTO; - } - - protected boolean canCollectItemsFromBelow() { - return true; - } - - protected boolean canOutputItems() { - return true; - } - - private LazyOptional grabCapability(Direction side) { - BlockPos pos = this.worldPosition.relative(side); - if (level == null) - return LazyOptional.empty(); - BlockEntity te = level.getBlockEntity(pos); - if (te == null) - return LazyOptional.empty(); - if (te instanceof ChuteTileEntity) { - if (side != Direction.DOWN || !(te instanceof SmartChuteTileEntity) || getItemMotion() > 0) - return LazyOptional.empty(); - } - return te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side.getOpposite()); - } - - public void setItem(ItemStack stack) { - setItem(stack, getItemMotion() < 0 ? 1 : 0); - } - - public void setItem(ItemStack stack, float insertionPos) { - item = stack; - itemPosition.startWithValue(insertionPos); - if (!level.isClientSide) { - notifyUpdate(); - award(AllAdvancements.CHUTE); - } - } - - @Override - public void invalidate() { - if (lazyHandler != null) - lazyHandler.invalidate(); - super.invalidate(); - } - - @Override - public void write(CompoundTag compound, boolean clientPacket) { - compound.put("Item", item.serializeNBT()); - compound.putFloat("ItemPosition", itemPosition.getValue()); - compound.putFloat("Pull", pull); - compound.putFloat("Push", push); - compound.putFloat("BottomAirFlowDistance", bottomPullDistance); - super.write(compound, clientPacket); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - ItemStack previousItem = item; - item = ItemStack.of(compound.getCompound("Item")); - itemPosition.startWithValue(compound.getFloat("ItemPosition")); - pull = compound.getFloat("Pull"); - push = compound.getFloat("Push"); - bottomPullDistance = compound.getFloat("BottomAirFlowDistance"); - super.read(compound, clientPacket); -// if (clientPacket) -// airCurrent.rebuild(); - - if (hasLevel() && level != null && level.isClientSide && !previousItem.equals(item, false) && !item.isEmpty()) { - if (level.random.nextInt(3) != 0) - return; - Vec3 p = VecHelper.getCenterOf(worldPosition); - p = VecHelper.offsetRandomly(p, level.random, .5f); - Vec3 m = Vec3.ZERO; - level.addParticle(new ItemParticleOption(ParticleTypes.ITEM, item), p.x, p.y, p.z, m.x, m.y, m.z); - } - } - - public float getItemMotion() { - // Chutes per second - final float fanSpeedModifier = 1 / 64f; - final float maxItemSpeed = 20f; - final float gravity = 4f; - - float motion = (push + pull) * fanSpeedModifier; - return (Mth.clamp(motion, -maxItemSpeed, maxItemSpeed) + (motion <= 0 ? -gravity : 0)) / 20f; - } - - @Override - public void destroy() { - super.destroy(); - ChuteTileEntity targetChute = getTargetChute(getBlockState()); - List inputChutes = getInputChutes(); - if (!item.isEmpty() && level != null) - Containers.dropItemStack(level, worldPosition.getX(), worldPosition.getY(), worldPosition.getZ(), item); - setRemoved(); - if (targetChute != null) { - targetChute.updatePull(); - targetChute.propagatePush(); - } - inputChutes.forEach(c -> c.updatePush(inputChutes.size())); - } - - public void onAdded() { - refreshBlockState(); - updatePull(); - ChuteTileEntity targetChute = getTargetChute(getBlockState()); - if (targetChute != null) - targetChute.propagatePush(); - else - updatePush(1); - } - - public void updatePull() { - float totalPull = calculatePull(); - if (pull == totalPull) - return; - pull = totalPull; - updateAirFlow = true; - sendData(); - ChuteTileEntity targetChute = getTargetChute(getBlockState()); - if (targetChute != null) - targetChute.updatePull(); - } - - public void updatePush(int branchCount) { - float totalPush = calculatePush(branchCount); - if (push == totalPush) - return; - updateAirFlow = true; - push = totalPush; - sendData(); - propagatePush(); - } - - public void propagatePush() { - List inputs = getInputChutes(); - inputs.forEach(c -> c.updatePush(inputs.size())); - } - - protected float calculatePull() { - BlockState blockStateAbove = level.getBlockState(worldPosition.above()); - if (AllBlocks.ENCASED_FAN.has(blockStateAbove) - && blockStateAbove.getValue(EncasedFanBlock.FACING) == Direction.DOWN) { - BlockEntity te = level.getBlockEntity(worldPosition.above()); - if (te instanceof EncasedFanTileEntity && !te.isRemoved()) { - EncasedFanTileEntity fan = (EncasedFanTileEntity) te; - return fan.getSpeed(); - } - } - - float totalPull = 0; - for (Direction d : Iterate.directions) { - ChuteTileEntity inputChute = getInputChute(d); - if (inputChute == null) - continue; - totalPull += inputChute.pull; - } - return totalPull; - } - - protected float calculatePush(int branchCount) { - if (level == null) - return 0; - BlockState blockStateBelow = level.getBlockState(worldPosition.below()); - if (AllBlocks.ENCASED_FAN.has(blockStateBelow) - && blockStateBelow.getValue(EncasedFanBlock.FACING) == Direction.UP) { - BlockEntity te = level.getBlockEntity(worldPosition.below()); - if (te instanceof EncasedFanTileEntity && !te.isRemoved()) { - EncasedFanTileEntity fan = (EncasedFanTileEntity) te; - return fan.getSpeed(); - } - } - - ChuteTileEntity targetChute = getTargetChute(getBlockState()); - if (targetChute == null) - return 0; - return targetChute.push / branchCount; - } - - @Nullable - private ChuteTileEntity getTargetChute(BlockState state) { - if (level == null) - return null; - Direction targetDirection = AbstractChuteBlock.getChuteFacing(state); - if (targetDirection == null) - return null; - BlockPos chutePos = worldPosition.below(); - if (targetDirection.getAxis() - .isHorizontal()) - chutePos = chutePos.relative(targetDirection.getOpposite()); - BlockState chuteState = level.getBlockState(chutePos); - if (!AbstractChuteBlock.isChute(chuteState)) - return null; - BlockEntity te = level.getBlockEntity(chutePos); - if (te instanceof ChuteTileEntity) - return (ChuteTileEntity) te; - return null; - } - - private List getInputChutes() { - List inputs = new LinkedList<>(); - for (Direction d : Iterate.directions) { - ChuteTileEntity inputChute = getInputChute(d); - if (inputChute == null) - continue; - inputs.add(inputChute); - } - return inputs; - } - - @Nullable - private ChuteTileEntity getInputChute(Direction direction) { - if (level == null || direction == Direction.DOWN) - return null; - direction = direction.getOpposite(); - BlockPos chutePos = worldPosition.above(); - if (direction.getAxis() - .isHorizontal()) - chutePos = chutePos.relative(direction); - BlockState chuteState = level.getBlockState(chutePos); - Direction chuteFacing = AbstractChuteBlock.getChuteFacing(chuteState); - if (chuteFacing != direction) - return null; - BlockEntity te = level.getBlockEntity(chutePos); - if (te instanceof ChuteTileEntity && !te.isRemoved()) - return (ChuteTileEntity) te; - return null; - } - - public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { - boolean downward = getItemMotion() < 0; - tooltip.add(componentSpacing.plainCopy() - .append(Lang.translateDirect("tooltip.chute.header"))); - if (pull == 0 && push == 0) - tooltip.add(componentSpacing.plainCopy() - .append(Lang.translateDirect("tooltip.chute.no_fans_attached")) - .withStyle(ChatFormatting.GRAY)); - if (pull != 0) - tooltip.add(componentSpacing.plainCopy() - .append(Lang.translateDirect("tooltip.chute.fans_" + (pull > 0 ? "pull_up" : "push_down")) - .withStyle(ChatFormatting.GRAY))); - if (push != 0) - tooltip.add(componentSpacing.plainCopy() - .append(Lang.translateDirect("tooltip.chute.fans_" + (push > 0 ? "push_up" : "pull_down")) - .withStyle(ChatFormatting.GRAY))); - tooltip.add(componentSpacing.plainCopy() - .append("-> ") - .append(Lang.translateDirect("tooltip.chute.items_move_" + (downward ? "down" : "up")) - .withStyle(ChatFormatting.YELLOW))); - if (!item.isEmpty()) { - tooltip.add(componentSpacing.plainCopy() - .append(Lang.translateDirect("tooltip.chute.contains", Components.translatable(item.getDescriptionId()) - .getString(), item.getCount())) - .withStyle(ChatFormatting.GREEN)); - } - return true; - } - - @Override - public LazyOptional getCapability(Capability cap, @Nullable Direction side) { - if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) - return lazyHandler.cast(); - return super.getCapability(cap, side); - } - - public ItemStack getItem() { - return item; - } - - // @Override - // @Nullable - // public AirCurrent getAirCurrent() { - // return airCurrent; - // } - // - // @Nullable - // @Override - // public World getAirCurrentWorld() { - // return world; - // } - // - // @Override - // public BlockPos getAirCurrentPos() { - // return pos; - // } - // - // @Override - // public float getSpeed() { - // if (getBlockState().get(ChuteBlock.SHAPE) == Shape.NORMAL && - // getBlockState().get(ChuteBlock.FACING) != Direction.DOWN) - // return 0; - // return pull + push; - // } - // - // @Override - // @Nullable - // public Direction getAirFlowDirection() { - // float speed = getSpeed(); - // if (speed == 0) - // return null; - // return speed > 0 ? Direction.UP : Direction.DOWN; - // } - // - // @Override - // public boolean isSourceRemoved() { - // return removed; - // } - // - // @Override - // public Direction getAirflowOriginSide() { - // return world != null && !(world.getTileEntity(pos.down()) instanceof - // IAirCurrentSource) - // && getBlockState().get(ChuteBlock.FACING) == Direction.DOWN ? Direction.DOWN - // : Direction.UP; - // } -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/chute/SmartChuteRenderer.java b/src/main/java/com/simibubi/create/content/logistics/block/chute/SmartChuteRenderer.java deleted file mode 100644 index f31cee7b8..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/chute/SmartChuteRenderer.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.simibubi.create.content.logistics.block.chute; - -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.foundation.tileEntity.renderer.SmartTileEntityRenderer; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; - -public class SmartChuteRenderer extends SmartTileEntityRenderer { - - public SmartChuteRenderer(BlockEntityRendererProvider.Context context) { - super(context); - } - - @Override - protected void renderSafe(SmartChuteTileEntity tileEntityIn, float partialTicks, PoseStack ms, - MultiBufferSource buffer, int light, int overlay) { - super.renderSafe(tileEntityIn, partialTicks, ms, buffer, light, overlay); - if (tileEntityIn.item.isEmpty()) - return; - if (tileEntityIn.itemPosition.getValue(partialTicks) > 0) - return; - ChuteRenderer.renderItem(tileEntityIn, partialTicks, ms, buffer, light, overlay); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/chute/SmartChuteTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/chute/SmartChuteTileEntity.java deleted file mode 100644 index a740833cf..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/chute/SmartChuteTileEntity.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.simibubi.create.content.logistics.block.chute; - -import java.util.List; - -import com.simibubi.create.foundation.item.ItemHelper.ExtractionCountMode; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; - -public class SmartChuteTileEntity extends ChuteTileEntity { - - FilteringBehaviour filtering; - - public SmartChuteTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - @Override - protected boolean canAcceptItem(ItemStack stack) { - return super.canAcceptItem(stack) && canCollectItemsFromBelow() && filtering.test(stack); - } - - @Override - protected int getExtractionAmount() { - return filtering.isCountVisible() && !filtering.anyAmount() ? filtering.getAmount() : 64; - } - - @Override - protected ExtractionCountMode getExtractionMode() { - return filtering.isCountVisible() && !filtering.anyAmount() ? ExtractionCountMode.EXACTLY - : ExtractionCountMode.UPTO; - } - - @Override - protected boolean canCollectItemsFromBelow() { - BlockState blockState = getBlockState(); - return blockState.hasProperty(SmartChuteBlock.POWERED) && !blockState.getValue(SmartChuteBlock.POWERED); - } - - @Override - protected boolean canOutputItems() { - BlockState blockState = getBlockState(); - return blockState.hasProperty(SmartChuteBlock.POWERED) && !blockState.getValue(SmartChuteBlock.POWERED); - } - - @Override - public void addBehaviours(List behaviours) { - behaviours.add(filtering = - new FilteringBehaviour(this, new SmartChuteFilterSlotPositioning()).showCountWhen(this::isExtracting)); - super.addBehaviours(behaviours); - } - - private boolean isExtracting() { - boolean up = getItemMotion() < 0; - BlockPos chutePos = worldPosition.relative(up ? Direction.UP : Direction.DOWN); - BlockState blockState = level.getBlockState(chutePos); - return !AbstractChuteBlock.isChute(blockState) && !blockState.getMaterial() - .isReplaceable(); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/depot/DepotBlock.java b/src/main/java/com/simibubi/create/content/logistics/block/depot/DepotBlock.java deleted file mode 100644 index 2defa56e8..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/depot/DepotBlock.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.simibubi.create.content.logistics.block.depot; - -import javax.annotation.ParametersAreNonnullByDefault; - -import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; -import com.simibubi.create.foundation.block.ITE; - -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.core.BlockPos; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.Entity; -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.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.pathfinder.PathComputationType; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.VoxelShape; - -@ParametersAreNonnullByDefault -@MethodsReturnNonnullByDefault -public class DepotBlock extends Block implements ITE, IWrenchable { - - public DepotBlock(Properties p_i48440_1_) { - super(p_i48440_1_); - } - - @Override - public VoxelShape getShape(BlockState p_220053_1_, BlockGetter p_220053_2_, BlockPos p_220053_3_, - CollisionContext p_220053_4_) { - return AllShapes.DEPOT; - } - - @Override - public Class getTileEntityClass() { - return DepotTileEntity.class; - } - - @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.DEPOT.get(); - } - - @Override - public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, - BlockHitResult ray) { - return SharedDepotBlockMethods.onUse(state, world, pos, player, hand, ray); - } - - @Override - public void onRemove(BlockState state, Level worldIn, BlockPos pos, BlockState newState, boolean isMoving) { - ITE.onRemove(state, worldIn, pos, newState); - } - - @Override - public void updateEntityAfterFallOn(BlockGetter worldIn, Entity entityIn) { - super.updateEntityAfterFallOn(worldIn, entityIn); - SharedDepotBlockMethods.onLanded(worldIn, entityIn); - } - - @Override - public boolean hasAnalogOutputSignal(BlockState state) { - return true; - } - - @Override - public int getAnalogOutputSignal(BlockState blockState, Level worldIn, BlockPos pos) { - return SharedDepotBlockMethods.getComparatorInputOverride(blockState, worldIn, pos); - } - - @Override - public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) { - return false; - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/depot/DepotItemHandler.java b/src/main/java/com/simibubi/create/content/logistics/block/depot/DepotItemHandler.java deleted file mode 100644 index e7b9a4473..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/depot/DepotItemHandler.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.simibubi.create.content.logistics.block.depot; - -import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack; - -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.items.IItemHandler; - -public class DepotItemHandler implements IItemHandler { - - private static final int MAIN_SLOT = 0; - private DepotBehaviour te; - - public DepotItemHandler(DepotBehaviour te) { - this.te = te; - } - - @Override - public int getSlots() { - return 9; - } - - @Override - public ItemStack getStackInSlot(int slot) { - return slot == MAIN_SLOT ? te.getHeldItemStack() : te.processingOutputBuffer.getStackInSlot(slot - 1); - } - - @Override - public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) { - if (slot != MAIN_SLOT) - return stack; - if (!te.getHeldItemStack() - .isEmpty() && !te.canMergeItems()) - return stack; - if (!te.isOutputEmpty() && !te.canMergeItems()) - return stack; - - ItemStack remainder = te.insert(new TransportedItemStack(stack), simulate); - if (!simulate && remainder != stack) - te.tileEntity.notifyUpdate(); - return remainder; - } - - @Override - public ItemStack extractItem(int slot, int amount, boolean simulate) { - if (slot != MAIN_SLOT) - return te.processingOutputBuffer.extractItem(slot - 1, amount, simulate); - - TransportedItemStack held = te.heldItem; - if (held == null) - return ItemStack.EMPTY; - ItemStack stack = held.stack.copy(); - ItemStack extracted = stack.split(amount); - if (!simulate) { - te.heldItem.stack = stack; - if (stack.isEmpty()) - te.heldItem = null; - te.tileEntity.notifyUpdate(); - } - return extracted; - } - - @Override - public int getSlotLimit(int slot) { - return slot == MAIN_SLOT ? te.maxStackSize.get() : 64; - } - - @Override - public boolean isItemValid(int slot, ItemStack stack) { - return slot == MAIN_SLOT && te.isItemValid(stack); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/depot/DepotTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/depot/DepotTileEntity.java deleted file mode 100644 index 308237dec..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/depot/DepotTileEntity.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.simibubi.create.content.logistics.block.depot; - -import java.util.List; - -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.items.CapabilityItemHandler; - -public class DepotTileEntity extends SmartTileEntity { - - DepotBehaviour depotBehaviour; - - public DepotTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - @Override - public void addBehaviours(List behaviours) { - behaviours.add(depotBehaviour = new DepotBehaviour(this)); - depotBehaviour.addSubBehaviours(behaviours); - } - - @Override - public LazyOptional getCapability(Capability cap, Direction side) { - if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) - return depotBehaviour.getItemCapability(cap, side); - return super.getCapability(cap, side); - } -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorAwardPacket.java b/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorAwardPacket.java deleted file mode 100644 index d9c698bbf..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorAwardPacket.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.simibubi.create.content.logistics.block.depot; - -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.networking.TileEntityConfigurationPacket; - -import net.minecraft.core.BlockPos; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.server.level.ServerPlayer; - -public class EjectorAwardPacket extends TileEntityConfigurationPacket { - - public EjectorAwardPacket(FriendlyByteBuf buffer) { - super(buffer); - } - - public EjectorAwardPacket(BlockPos pos) { - super(pos); - } - - @Override - protected void writeSettings(FriendlyByteBuf buffer) {} - - @Override - protected void readSettings(FriendlyByteBuf buffer) {} - - @Override - protected void applySettings(ServerPlayer player, EjectorTileEntity te) { - AllAdvancements.EJECTOR_MAXED.awardTo(player); - } - - @Override - protected void applySettings(EjectorTileEntity te) {} - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorBlock.java b/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorBlock.java deleted file mode 100644 index 349963a33..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorBlock.java +++ /dev/null @@ -1,165 +0,0 @@ -package com.simibubi.create.content.logistics.block.depot; - -import java.util.Optional; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllItems; -import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.HorizontalKineticBlock; -import com.simibubi.create.content.logistics.block.depot.EjectorTileEntity.State; -import com.simibubi.create.foundation.block.ITE; -import com.simibubi.create.foundation.networking.AllPackets; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.pathfinder.PathComputationType; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.world.phys.Vec3; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.VoxelShape; - -public class EjectorBlock extends HorizontalKineticBlock implements ITE { - - public EjectorBlock(Properties properties) { - super(properties); - } - - @Override - public VoxelShape getShape(BlockState p_220053_1_, BlockGetter p_220053_2_, BlockPos p_220053_3_, - CollisionContext p_220053_4_) { - return AllShapes.DEPOT; - } - - @Override - public float getFriction(BlockState state, LevelReader world, BlockPos pos, Entity entity) { - return getTileEntityOptional(world, pos).filter(ete -> ete.state == State.LAUNCHING) - .map($ -> 1f) - .orElse(super.getFriction(state, world, pos, entity)); - } - - @Override - public void neighborChanged(BlockState state, Level world, BlockPos pos, Block p_220069_4_, BlockPos p_220069_5_, - boolean p_220069_6_) { - withTileEntityDo(world, pos, EjectorTileEntity::updateSignal); - } - - @Override - public void fallOn(Level p_180658_1_, BlockState p_152427_, BlockPos p_180658_2_, Entity p_180658_3_, - float p_180658_4_) { - Optional tileEntityOptional = getTileEntityOptional(p_180658_1_, p_180658_2_); - if (tileEntityOptional.isPresent() && !p_180658_3_.isSuppressingBounce()) { - p_180658_3_.causeFallDamage(p_180658_4_, 1.0F, DamageSource.FALL); - return; - } - super.fallOn(p_180658_1_, p_152427_, p_180658_2_, p_180658_3_, p_180658_4_); - } - - @Override - public void updateEntityAfterFallOn(BlockGetter worldIn, Entity entityIn) { - super.updateEntityAfterFallOn(worldIn, entityIn); - BlockPos position = entityIn.blockPosition(); - if (!AllBlocks.WEIGHTED_EJECTOR.has(worldIn.getBlockState(position))) - return; - if (!entityIn.isAlive()) - return; - if (entityIn.isSuppressingBounce()) - return; - if (entityIn instanceof ItemEntity) { - SharedDepotBlockMethods.onLanded(worldIn, entityIn); - return; - } - - Optional teProvider = getTileEntityOptional(worldIn, position); - if (!teProvider.isPresent()) - return; - - EjectorTileEntity ejectorTileEntity = teProvider.get(); - if (ejectorTileEntity.getState() == State.RETRACTING) - return; - if (ejectorTileEntity.powered) - return; - if (ejectorTileEntity.launcher.getHorizontalDistance() == 0) - return; - - if (entityIn.isOnGround()) { - entityIn.setOnGround(false); - Vec3 center = VecHelper.getCenterOf(position) - .add(0, 7 / 16f, 0); - Vec3 positionVec = entityIn.position(); - double diff = center.distanceTo(positionVec); - entityIn.setDeltaMovement(0, -0.125, 0); - Vec3 vec = center.add(positionVec) - .scale(.5f); - if (diff > 4 / 16f) { - entityIn.setPos(vec.x, vec.y, vec.z); - return; - } - } - - ejectorTileEntity.activate(); - ejectorTileEntity.notifyUpdate(); - if (entityIn.level.isClientSide) - AllPackets.channel.sendToServer(new EjectorTriggerPacket(ejectorTileEntity.getBlockPos())); - } - - @Override - public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, - BlockHitResult ray) { - if (AllItems.WRENCH.isIn(player.getItemInHand(hand))) - return InteractionResult.PASS; - return SharedDepotBlockMethods.onUse(state, world, pos, player, hand, ray); - } - - @Override - public Axis getRotationAxis(BlockState state) { - return state.getValue(HORIZONTAL_FACING) - .getClockWise() - .getAxis(); - } - - @Override - public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) { - return getRotationAxis(state) == face.getAxis(); - } - - @Override - public Class getTileEntityClass() { - return EjectorTileEntity.class; - } - - @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.WEIGHTED_EJECTOR.get(); - } - - @Override - public boolean hasAnalogOutputSignal(BlockState state) { - return true; - } - - @Override - public int getAnalogOutputSignal(BlockState blockState, Level worldIn, BlockPos pos) { - return SharedDepotBlockMethods.getComparatorInputOverride(blockState, worldIn, pos); - } - - @Override - public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) { - return false; - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorElytraPacket.java b/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorElytraPacket.java deleted file mode 100644 index f2058d433..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorElytraPacket.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.simibubi.create.content.logistics.block.depot; - -import java.util.function.Supplier; - -import com.simibubi.create.foundation.networking.SimplePacketBase; - -import net.minecraft.core.BlockPos; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraftforge.network.NetworkEvent.Context; - -public class EjectorElytraPacket extends SimplePacketBase { - - private BlockPos pos; - - public EjectorElytraPacket(BlockPos pos) { - this.pos = pos; - } - - public EjectorElytraPacket(FriendlyByteBuf buffer) { - pos = buffer.readBlockPos(); - } - - @Override - public void write(FriendlyByteBuf buffer) { - buffer.writeBlockPos(pos); - } - - @Override - public void handle(Supplier context) { - context.get() - .enqueueWork(() -> { - ServerPlayer player = context.get() - .getSender(); - if (player == null) - return; - Level world = player.level; - if (world == null || !world.isLoaded(pos)) - return; - BlockEntity tileEntity = world.getBlockEntity(pos); - if (tileEntity instanceof EjectorTileEntity) - ((EjectorTileEntity) tileEntity).deployElytra(player); - }); - context.get() - .setPacketHandled(true); - - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorInstance.java b/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorInstance.java deleted file mode 100644 index 1a37a1141..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorInstance.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.simibubi.create.content.logistics.block.depot; - -import com.jozufozu.flywheel.api.MaterialManager; -import com.jozufozu.flywheel.api.instance.DynamicInstance; -import com.jozufozu.flywheel.core.materials.model.ModelData; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.relays.encased.ShaftInstance; -import com.simibubi.create.foundation.utility.AnimationTickHolder; - -import net.minecraft.util.Mth; - -public class EjectorInstance extends ShaftInstance implements DynamicInstance { - - protected final EjectorTileEntity tile; - - protected final ModelData plate; - - private float lastProgress = Float.NaN; - - public EjectorInstance(MaterialManager dispatcher, EjectorTileEntity tile) { - super(dispatcher, tile); - this.tile = tile; - - plate = getTransformMaterial().getModel(AllBlockPartials.EJECTOR_TOP, blockState).createInstance(); - - pivotPlate(); - } - - @Override - public void beginFrame() { - float lidProgress = getLidProgress(); - - if (Mth.equal(lidProgress, lastProgress)) return; - - pivotPlate(lidProgress); - lastProgress = lidProgress; - } - - @Override - public void updateLight() { - super.updateLight(); - relight(pos, plate); - } - - @Override - public void remove() { - super.remove(); - plate.delete(); - } - - private void pivotPlate() { - pivotPlate(getLidProgress()); - } - - private float getLidProgress() { - return tile.getLidProgress(AnimationTickHolder.getPartialTicks()); - } - - private void pivotPlate(float lidProgress) { - float angle = lidProgress * 70; - - EjectorRenderer.applyLidAngle(tile, angle, plate.loadIdentity().translate(getInstancePosition())); - } -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorPlacementPacket.java b/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorPlacementPacket.java deleted file mode 100644 index 1ed70b699..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorPlacementPacket.java +++ /dev/null @@ -1,98 +0,0 @@ -package com.simibubi.create.content.logistics.block.depot; - -import java.util.function.Supplier; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.foundation.networking.SimplePacketBase; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.fml.DistExecutor; -import net.minecraftforge.network.NetworkEvent.Context; - -public class EjectorPlacementPacket extends SimplePacketBase { - - private int h, v; - private BlockPos pos; - private Direction facing; - - public EjectorPlacementPacket(int h, int v, BlockPos pos, Direction facing) { - this.h = h; - this.v = v; - this.pos = pos; - this.facing = facing; - } - - public EjectorPlacementPacket(FriendlyByteBuf buffer) { - h = buffer.readInt(); - v = buffer.readInt(); - pos = buffer.readBlockPos(); - facing = Direction.from3DDataValue(buffer.readVarInt()); - } - - @Override - public void write(FriendlyByteBuf buffer) { - buffer.writeInt(h); - buffer.writeInt(v); - buffer.writeBlockPos(pos); - buffer.writeVarInt(facing.get3DDataValue()); - } - - @Override - public void handle(Supplier context) { - context.get() - .enqueueWork(() -> { - ServerPlayer player = context.get() - .getSender(); - if (player == null) - return; - Level world = player.level; - if (world == null || !world.isLoaded(pos)) - return; - BlockEntity tileEntity = world.getBlockEntity(pos); - BlockState state = world.getBlockState(pos); - if (tileEntity instanceof EjectorTileEntity) - ((EjectorTileEntity) tileEntity).setTarget(h, v); - if (AllBlocks.WEIGHTED_EJECTOR.has(state)) - world.setBlockAndUpdate(pos, state.setValue(EjectorBlock.HORIZONTAL_FACING, facing)); - }); - context.get() - .setPacketHandled(true); - - } - - public static class ClientBoundRequest extends SimplePacketBase { - - BlockPos pos; - - public ClientBoundRequest(BlockPos pos) { - this.pos = pos; - } - - public ClientBoundRequest(FriendlyByteBuf buffer) { - this.pos = buffer.readBlockPos(); - } - - @Override - public void write(FriendlyByteBuf buffer) { - buffer.writeBlockPos(pos); - } - - @Override - public void handle(Supplier context) { - context.get() - .enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, - () -> () -> EjectorTargetHandler.flushSettings(pos))); - context.get() - .setPacketHandled(true); - } - - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorRenderer.java b/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorRenderer.java deleted file mode 100644 index 9a60342e8..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorRenderer.java +++ /dev/null @@ -1,113 +0,0 @@ -package com.simibubi.create.content.logistics.block.depot; - -import com.jozufozu.flywheel.backend.Backend; -import com.jozufozu.flywheel.util.transform.Rotate; -import com.jozufozu.flywheel.util.transform.TransformStack; -import com.jozufozu.flywheel.util.transform.Translate; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.IntAttached; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.block.model.ItemTransforms.TransformType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; - -public class EjectorRenderer extends KineticTileEntityRenderer { - - static final Vec3 pivot = VecHelper.voxelSpace(0, 11.25, 0.75); - - public EjectorRenderer(BlockEntityRendererProvider.Context context) { - super(context); - } - - @Override - public boolean shouldRenderOffScreen(KineticTileEntity p_188185_1_) { - return true; - } - - @Override - protected void renderSafe(KineticTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - super.renderSafe(te, partialTicks, ms, buffer, light, overlay); - - EjectorTileEntity ejector = (EjectorTileEntity) te; - VertexConsumer vertexBuilder = buffer.getBuffer(RenderType.solid()); - float lidProgress = ((EjectorTileEntity) te).getLidProgress(partialTicks); - float angle = lidProgress * 70; - - if (!Backend.canUseInstancing(te.getLevel())) { - SuperByteBuffer model = CachedBufferer.partial(AllBlockPartials.EJECTOR_TOP, te.getBlockState()); - applyLidAngle(te, angle, model); - model.light(light) - .renderInto(ms, vertexBuilder); - } - - TransformStack msr = TransformStack.cast(ms); - - float maxTime = - (float) (ejector.earlyTarget != null ? ejector.earlyTargetTime : ejector.launcher.getTotalFlyingTicks()); - for (IntAttached intAttached : ejector.launchedItems) { - float time = intAttached.getFirst() + partialTicks; - if (time > maxTime) - continue; - - ms.pushPose(); - Vec3 launchedItemLocation = ejector.getLaunchedItemLocation(time); - msr.translate(launchedItemLocation.subtract(Vec3.atLowerCornerOf(te.getBlockPos()))); - Vec3 itemRotOffset = VecHelper.voxelSpace(0, 3, 0); - msr.translate(itemRotOffset); - msr.rotateY(AngleHelper.horizontalAngle(ejector.getFacing())); - msr.rotateX(time * 40); - msr.translateBack(itemRotOffset); - Minecraft.getInstance() - .getItemRenderer() - .renderStatic(intAttached.getValue(), TransformType.GROUND, light, overlay, ms, buffer, 0); - ms.popPose(); - } - - DepotBehaviour behaviour = te.getBehaviour(DepotBehaviour.TYPE); - if (behaviour == null || behaviour.isEmpty()) - return; - - ms.pushPose(); - applyLidAngle(te, angle, msr); - msr.centre() - .rotateY(-180 - AngleHelper.horizontalAngle(te.getBlockState() - .getValue(EjectorBlock.HORIZONTAL_FACING))) - .unCentre(); - DepotRenderer.renderItemsOf(te, partialTicks, ms, buffer, light, overlay, behaviour); - ms.popPose(); - } - - static & Rotate> void applyLidAngle(KineticTileEntity te, float angle, T tr) { - applyLidAngle(te, pivot, angle, tr); - } - - static & Rotate> void applyLidAngle(KineticTileEntity te, Vec3 rotationOffset, float angle, T tr) { - tr.centre() - .rotateY(180 + AngleHelper.horizontalAngle(te.getBlockState() - .getValue(EjectorBlock.HORIZONTAL_FACING))) - .unCentre() - .translate(rotationOffset) - .rotateX(-angle) - .translateBack(rotationOffset); - } - - @Override - protected BlockState getRenderedBlockState(KineticTileEntity te) { - return shaft(getRotationAxisOf(te)); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorTileEntity.java deleted file mode 100644 index bcbdb9305..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorTileEntity.java +++ /dev/null @@ -1,655 +0,0 @@ -package com.simibubi.create.content.logistics.block.depot; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import javax.annotation.Nullable; - -import com.jozufozu.flywheel.util.transform.TransformStack; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack; -import com.simibubi.create.content.logistics.block.funnel.AbstractFunnelBlock; -import com.simibubi.create.content.logistics.block.funnel.FunnelBlock; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.networking.AllPackets; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueBehaviour; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.IntAttached; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.Pair; -import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtUtils; -import net.minecraft.nbt.Tag; -import net.minecraft.network.syncher.SynchedEntityData; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.util.Mth; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ElytraItem; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.ClipContext; -import net.minecraft.world.level.ClipContext.Block; -import net.minecraft.world.level.ClipContext.Fluid; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.ObserverBlock; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.PushReaction; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.world.phys.HitResult.Type; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.items.ItemStackHandler; - -public class EjectorTileEntity extends KineticTileEntity { - - List> launchedItems; - ScrollValueBehaviour maxStackSize; - DepotBehaviour depotBehaviour; - EntityLauncher launcher; - LerpedFloat lidProgress; - boolean powered; - boolean launch; - State state; - - // item collision - @Nullable - Pair earlyTarget; - float earlyTargetTime; - // runtime stuff - int scanCooldown; - ItemStack trackedItem; - - public enum State { - CHARGED, LAUNCHING, RETRACTING; - } - - public EjectorTileEntity(BlockEntityType typeIn, BlockPos pos, BlockState state) { - super(typeIn, pos, state); - launcher = new EntityLauncher(1, 0); - lidProgress = LerpedFloat.linear() - .startWithValue(1); - this.state = State.RETRACTING; - launchedItems = new ArrayList<>(); - powered = false; - } - - @Override - public void addBehaviours(List behaviours) { - super.addBehaviours(behaviours); - behaviours.add(depotBehaviour = new DepotBehaviour(this)); - - maxStackSize = new ScrollValueBehaviour(Lang.translateDirect("weighted_ejector.stack_size"), this, new EjectorSlot()) - .between(0, 64) - .withFormatter(i -> i == 0 ? "*" : String.valueOf(i)) - .onlyActiveWhen(() -> state == State.CHARGED) - .requiresWrench(); - behaviours.add(maxStackSize); - - depotBehaviour.maxStackSize = () -> maxStackSize.getValue(); - depotBehaviour.canAcceptItems = () -> state == State.CHARGED; - depotBehaviour.canFunnelsPullFrom = side -> side != getFacing(); - depotBehaviour.enableMerging(); - depotBehaviour.addSubBehaviours(behaviours); - } - - @Override - public void initialize() { - super.initialize(); - updateSignal(); - } - - public void activate() { - launch = true; - nudgeEntities(); - } - - protected boolean cannotLaunch() { - return state != State.CHARGED && !(level.isClientSide && state == State.LAUNCHING); - } - - public void activateDeferred() { - if (cannotLaunch()) - return; - Direction facing = getFacing(); - List entities = - level.getEntitiesOfClass(Entity.class, new AABB(worldPosition).inflate(-1 / 16f, 0, -1 / 16f)); - - // Launch Items - boolean doLogic = !level.isClientSide || isVirtual(); - if (doLogic) - launchItems(); - - // Launch Entities - for (Entity entity : entities) { - boolean isPlayerEntity = entity instanceof Player; - if (!entity.isAlive()) - continue; - if (entity instanceof ItemEntity) - continue; - if (entity.getPistonPushReaction() == PushReaction.IGNORE) - continue; - - entity.setOnGround(false); - - if (isPlayerEntity != level.isClientSide) - continue; - - entity.setPos(worldPosition.getX() + .5f, worldPosition.getY() + 1, worldPosition.getZ() + .5f); - launcher.applyMotion(entity, facing); - - if (!isPlayerEntity) - continue; - - Player playerEntity = (Player) entity; - - if (launcher.getHorizontalDistance() * launcher.getHorizontalDistance() - + launcher.getVerticalDistance() * launcher.getVerticalDistance() >= 25 * 25) - AllPackets.channel.sendToServer(new EjectorAwardPacket(worldPosition)); - - if (!(playerEntity.getItemBySlot(EquipmentSlot.CHEST) - .getItem() instanceof ElytraItem)) - continue; - - playerEntity.setXRot(-35); - playerEntity.setYRot(facing.toYRot()); - playerEntity.setDeltaMovement(playerEntity.getDeltaMovement() - .scale(.75f)); - deployElytra(playerEntity); - AllPackets.channel.sendToServer(new EjectorElytraPacket(worldPosition)); - } - - if (doLogic) { - lidProgress.chase(1, .8f, Chaser.EXP); - state = State.LAUNCHING; - if (!level.isClientSide) { - level.playSound(null, worldPosition, SoundEvents.WOODEN_TRAPDOOR_CLOSE, SoundSource.BLOCKS, .35f, 1f); - level.playSound(null, worldPosition, SoundEvents.CHEST_OPEN, SoundSource.BLOCKS, .1f, 1.4f); - } - } - } - - public void deployElytra(Player playerEntity) { - EntityHack.setElytraFlying(playerEntity); - } - - protected void launchItems() { - ItemStack heldItemStack = depotBehaviour.getHeldItemStack(); - Direction funnelFacing = getFacing().getOpposite(); - - if (AbstractFunnelBlock.getFunnelFacing(level.getBlockState(worldPosition.above())) == funnelFacing) { - DirectBeltInputBehaviour directOutput = getBehaviour(DirectBeltInputBehaviour.TYPE); - - if (depotBehaviour.heldItem != null) { - ItemStack remainder = directOutput.tryExportingToBeltFunnel(heldItemStack, funnelFacing, false); - if (remainder == null) - ; - else if (remainder.isEmpty()) - depotBehaviour.removeHeldItem(); - else if (remainder.getCount() != heldItemStack.getCount()) - depotBehaviour.heldItem.stack = remainder; - } - - for (Iterator iterator = depotBehaviour.incoming.iterator(); iterator.hasNext();) { - TransportedItemStack transportedItemStack = iterator.next(); - ItemStack stack = transportedItemStack.stack; - ItemStack remainder = directOutput.tryExportingToBeltFunnel(stack, funnelFacing, false); - if (remainder == null) - ; - else if (remainder.isEmpty()) - iterator.remove(); - else if (!remainder.sameItem(stack)) - transportedItemStack.stack = remainder; - } - - ItemStackHandler outputs = depotBehaviour.processingOutputBuffer; - for (int i = 0; i < outputs.getSlots(); i++) { - ItemStack remainder = - directOutput.tryExportingToBeltFunnel(outputs.getStackInSlot(i), funnelFacing, false); - if (remainder != null) - outputs.setStackInSlot(i, remainder); - } - return; - } - - if (!level.isClientSide) - for (Direction d : Iterate.directions) { - BlockState blockState = level.getBlockState(worldPosition.relative(d)); - if (!(blockState.getBlock() instanceof ObserverBlock)) - continue; - if (blockState.getValue(ObserverBlock.FACING) != d.getOpposite()) - continue; - blockState.updateShape(d.getOpposite(), blockState, level, worldPosition.relative(d), worldPosition); - } - - if (depotBehaviour.heldItem != null) { - addToLaunchedItems(heldItemStack); - depotBehaviour.removeHeldItem(); - } - - for (TransportedItemStack transportedItemStack : depotBehaviour.incoming) - addToLaunchedItems(transportedItemStack.stack); - depotBehaviour.incoming.clear(); - - ItemStackHandler outputs = depotBehaviour.processingOutputBuffer; - for (int i = 0; i < outputs.getSlots(); i++) { - ItemStack extractItem = outputs.extractItem(i, 64, false); - if (!extractItem.isEmpty()) - addToLaunchedItems(extractItem); - } - } - - protected boolean addToLaunchedItems(ItemStack stack) { - if ((!level.isClientSide || isVirtual()) && trackedItem == null && scanCooldown == 0) { - scanCooldown = AllConfigs.SERVER.kinetics.ejectorScanInterval.get(); - trackedItem = stack; - } - return launchedItems.add(IntAttached.withZero(stack)); - } - - protected Direction getFacing() { - BlockState blockState = getBlockState(); - if (!AllBlocks.WEIGHTED_EJECTOR.has(blockState)) - return Direction.UP; - Direction facing = blockState.getValue(EjectorBlock.HORIZONTAL_FACING); - return facing; - } - - @Override - public void tick() { - super.tick(); - - boolean doLogic = !level.isClientSide || isVirtual(); - State prevState = state; - float totalTime = Math.max(3, (float) launcher.getTotalFlyingTicks()); - - if (scanCooldown > 0) - scanCooldown--; - - if (launch) { - launch = false; - activateDeferred(); - } - - for (Iterator> iterator = launchedItems.iterator(); iterator.hasNext();) { - IntAttached intAttached = iterator.next(); - boolean hit = false; - if (intAttached.getSecond() == trackedItem) - hit = scanTrajectoryForObstacles(intAttached.getFirst()); - float maxTime = earlyTarget != null ? Math.min(earlyTargetTime, totalTime) : totalTime; - if (hit || intAttached.exceeds((int) maxTime)) { - placeItemAtTarget(doLogic, maxTime, intAttached); - iterator.remove(); - } - intAttached.increment(); - } - - if (state == State.LAUNCHING) { - lidProgress.chase(1, .8f, Chaser.EXP); - lidProgress.tickChaser(); - if (lidProgress.getValue() > 1 - 1 / 16f && doLogic) { - state = State.RETRACTING; - lidProgress.setValue(1); - } - } - - if (state == State.CHARGED) { - lidProgress.setValue(0); - lidProgress.updateChaseSpeed(0); - if (doLogic) - ejectIfTriggered(); - } - - if (state == State.RETRACTING) { - if (lidProgress.getChaseTarget() == 1 && !lidProgress.settled()) { - lidProgress.tickChaser(); - } else { - lidProgress.updateChaseTarget(0); - lidProgress.updateChaseSpeed(0); - if (lidProgress.getValue() == 0 && doLogic) { - state = State.CHARGED; - lidProgress.setValue(0); - sendData(); - } - - float value = Mth.clamp(lidProgress.getValue() - getWindUpSpeed(), 0, 1); - lidProgress.setValue(value); - - int soundRate = (int) (1 / (getWindUpSpeed() * 5)) + 1; - float volume = .125f; - float pitch = 1.5f - lidProgress.getValue(); - if (((int) level.getGameTime()) % soundRate == 0 && doLogic) - level.playSound(null, worldPosition, SoundEvents.WOODEN_BUTTON_CLICK_OFF, SoundSource.BLOCKS, - volume, pitch); - } - } - - if (state != prevState) - notifyUpdate(); - } - - private boolean scanTrajectoryForObstacles(int time) { - if (time <= 2) - return false; - - Vec3 source = getLaunchedItemLocation(time); - Vec3 target = getLaunchedItemLocation(time + 1); - - BlockHitResult rayTraceBlocks = level.clip(new ClipContext(source, target, Block.COLLIDER, Fluid.NONE, null)); - boolean miss = rayTraceBlocks.getType() == Type.MISS; - - if (!miss && rayTraceBlocks.getType() == Type.BLOCK) { - BlockState blockState = level.getBlockState(rayTraceBlocks.getBlockPos()); - if (FunnelBlock.isFunnel(blockState) && blockState.hasProperty(FunnelBlock.EXTRACTING) - && blockState.getValue(FunnelBlock.EXTRACTING)) - miss = true; - } - - if (miss) { - if (earlyTarget != null && earlyTargetTime < time + 1) { - earlyTarget = null; - earlyTargetTime = 0; - } - return false; - } - - Vec3 vec = rayTraceBlocks.getLocation(); - earlyTarget = Pair.of(vec.add(Vec3.atLowerCornerOf(rayTraceBlocks.getDirection() - .getNormal()) - .scale(.25f)), rayTraceBlocks.getBlockPos()); - earlyTargetTime = (float) (time + (source.distanceTo(vec) / source.distanceTo(target))); - sendData(); - return true; - } - - protected void nudgeEntities() { - for (Entity entity : level.getEntitiesOfClass(Entity.class, - new AABB(worldPosition).inflate(-1 / 16f, 0, -1 / 16f))) { - if (!entity.isAlive()) - continue; - if (entity.getPistonPushReaction() == PushReaction.IGNORE) - continue; - if (!(entity instanceof Player)) - entity.setPos(entity.getX(), entity.getY() + .125f, entity.getZ()); - } - } - - protected void ejectIfTriggered() { - if (powered) - return; - int presentStackSize = depotBehaviour.getPresentStackSize(); - if (presentStackSize == 0) - return; - if (presentStackSize < maxStackSize.getValue()) - return; - if (depotBehaviour.heldItem != null && depotBehaviour.heldItem.beltPosition < .49f) - return; - - Direction funnelFacing = getFacing().getOpposite(); - ItemStack held = depotBehaviour.getHeldItemStack(); - if (AbstractFunnelBlock.getFunnelFacing(level.getBlockState(worldPosition.above())) == funnelFacing) { - DirectBeltInputBehaviour directOutput = getBehaviour(DirectBeltInputBehaviour.TYPE); - if (depotBehaviour.heldItem != null) { - ItemStack tryFunnel = directOutput.tryExportingToBeltFunnel(held, funnelFacing, true); - if (tryFunnel == null || !tryFunnel.isEmpty()) - return; - } - } - - DirectBeltInputBehaviour targetOpenInv = getTargetOpenInv(); - - // Do not eject if target cannot accept held item - if (targetOpenInv != null && depotBehaviour.heldItem != null - && targetOpenInv.handleInsertion(held, Direction.UP, true) - .getCount() == held.getCount()) - return; - - activate(); - notifyUpdate(); - } - - protected void placeItemAtTarget(boolean doLogic, float maxTime, IntAttached intAttached) { - if (!doLogic) - return; - if (intAttached.getSecond() == trackedItem) - trackedItem = null; - - DirectBeltInputBehaviour targetOpenInv = getTargetOpenInv(); - if (targetOpenInv != null) { - ItemStack remainder = targetOpenInv.handleInsertion(intAttached.getValue(), Direction.UP, false); - intAttached.setSecond(remainder); - } - - if (intAttached.getValue() - .isEmpty()) - return; - - Vec3 ejectVec = earlyTarget != null ? earlyTarget.getFirst() : getLaunchedItemLocation(maxTime); - Vec3 ejectMotionVec = getLaunchedItemMotion(maxTime); - ItemEntity item = new ItemEntity(level, ejectVec.x, ejectVec.y, ejectVec.z, intAttached.getValue()); - item.setDeltaMovement(ejectMotionVec); - item.setDefaultPickUpDelay(); - level.addFreshEntity(item); - } - - public DirectBeltInputBehaviour getTargetOpenInv() { - BlockPos targetPos = earlyTarget != null ? earlyTarget.getSecond() - : worldPosition.above(launcher.getVerticalDistance()) - .relative(getFacing(), Math.max(1, launcher.getHorizontalDistance())); - return TileEntityBehaviour.get(level, targetPos, DirectBeltInputBehaviour.TYPE); - } - - public Vec3 getLaunchedItemLocation(float time) { - return launcher.getGlobalPos(time, getFacing().getOpposite(), worldPosition); - } - - public Vec3 getLaunchedItemMotion(float time) { - return launcher.getGlobalVelocity(time, getFacing().getOpposite(), worldPosition) - .scale(.5f); - } - - @Override - public void destroy() { - super.destroy(); - dropFlyingItems(); - } - - public void dropFlyingItems() { - for (IntAttached intAttached : launchedItems) { - Vec3 ejectVec = getLaunchedItemLocation(intAttached.getFirst()); - Vec3 ejectMotionVec = getLaunchedItemMotion(intAttached.getFirst()); - ItemEntity item = new ItemEntity(level, 0, 0, 0, intAttached.getValue()); - item.setPosRaw(ejectVec.x, ejectVec.y, ejectVec.z); - item.setDeltaMovement(ejectMotionVec); - item.setDefaultPickUpDelay(); - level.addFreshEntity(item); - } - launchedItems.clear(); - } - - public float getWindUpSpeed() { - int hd = launcher.getHorizontalDistance(); - int vd = launcher.getVerticalDistance(); - - float speedFactor = Math.abs(getSpeed()) / 256f; - float distanceFactor; - if (hd == 0 && vd == 0) - distanceFactor = 1; - else - distanceFactor = 1 * Mth.sqrt(hd * hd + vd * vd); - return speedFactor / distanceFactor; - } - - @Override - protected void write(CompoundTag compound, boolean clientPacket) { - super.write(compound, clientPacket); - compound.putInt("HorizontalDistance", launcher.getHorizontalDistance()); - compound.putInt("VerticalDistance", launcher.getVerticalDistance()); - compound.putBoolean("Powered", powered); - NBTHelper.writeEnum(compound, "State", state); - compound.put("Lid", lidProgress.writeNBT()); - compound.put("LaunchedItems", - NBTHelper.writeCompoundList(launchedItems, ia -> ia.serializeNBT(ItemStack::serializeNBT))); - - if (earlyTarget != null) { - compound.put("EarlyTarget", VecHelper.writeNBT(earlyTarget.getFirst())); - compound.put("EarlyTargetPos", NbtUtils.writeBlockPos(earlyTarget.getSecond())); - compound.putFloat("EarlyTargetTime", earlyTargetTime); - } - } - - @Override - public void writeSafe(CompoundTag compound) { - super.writeSafe(compound); - compound.putInt("HorizontalDistance", launcher.getHorizontalDistance()); - compound.putInt("VerticalDistance", launcher.getVerticalDistance()); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - super.read(compound, clientPacket); - int horizontalDistance = compound.getInt("HorizontalDistance"); - int verticalDistance = compound.getInt("VerticalDistance"); - - if (launcher.getHorizontalDistance() != horizontalDistance - || launcher.getVerticalDistance() != verticalDistance) { - launcher.set(horizontalDistance, verticalDistance); - launcher.clamp(AllConfigs.SERVER.kinetics.maxEjectorDistance.get()); - } - - powered = compound.getBoolean("Powered"); - state = NBTHelper.readEnum(compound, "State", State.class); - lidProgress.readNBT(compound.getCompound("Lid"), false); - launchedItems = NBTHelper.readCompoundList(compound.getList("LaunchedItems", Tag.TAG_COMPOUND), - nbt -> IntAttached.read(nbt, ItemStack::of)); - - earlyTarget = null; - earlyTargetTime = 0; - if (compound.contains("EarlyTarget")) { - earlyTarget = Pair.of(VecHelper.readNBT(compound.getList("EarlyTarget", Tag.TAG_DOUBLE)), - NbtUtils.readBlockPos(compound.getCompound("EarlyTargetPos"))); - earlyTargetTime = compound.getFloat("EarlyTargetTime"); - } - - if (compound.contains("ForceAngle")) - lidProgress.startWithValue(compound.getFloat("ForceAngle")); - } - - public void updateSignal() { - boolean shoudPower = level.hasNeighborSignal(worldPosition); - if (shoudPower == powered) - return; - powered = shoudPower; - sendData(); - } - - public void setTarget(int horizontalDistance, int verticalDistance) { - launcher.set(Math.max(1, horizontalDistance), verticalDistance); - sendData(); - } - - public BlockPos getTargetPosition() { - BlockState blockState = getBlockState(); - if (!AllBlocks.WEIGHTED_EJECTOR.has(blockState)) - return worldPosition; - Direction facing = blockState.getValue(EjectorBlock.HORIZONTAL_FACING); - return worldPosition.relative(facing, launcher.getHorizontalDistance()) - .above(launcher.getVerticalDistance()); - } - - @Override - public LazyOptional getCapability(Capability cap, Direction side) { - if (isItemHandlerCap(cap)) - return depotBehaviour.getItemCapability(cap, side); - return super.getCapability(cap, side); - } - - public float getLidProgress(float pt) { - return lidProgress.getValue(pt); - } - - public State getState() { - return state; - } - - @Override - @OnlyIn(Dist.CLIENT) - public AABB getRenderBoundingBox() { - return INFINITE_EXTENT_AABB; - } - - private static abstract class EntityHack extends Entity { - - public EntityHack(EntityType p_i48580_1_, Level p_i48580_2_) { - super(p_i48580_1_, p_i48580_2_); - } - - public static void setElytraFlying(Entity e) { - SynchedEntityData data = e.getEntityData(); - data.set(DATA_SHARED_FLAGS_ID, (byte) (data.get(DATA_SHARED_FLAGS_ID) | 1 << 7)); - } - - } - - private static class EjectorSlot extends ValueBoxTransform.Sided { - - @Override - protected Vec3 getLocalOffset(BlockState state) { - return new Vec3(.5, 13 / 16f, .5).add(VecHelper.rotate(new Vec3(0, 0, -.3), angle(state), Axis.Y)); - } - - @Override - protected void rotate(BlockState state, PoseStack ms) { - TransformStack.cast(ms) - .rotateY(angle(state)) - .rotateX(90); - } - - protected float angle(BlockState state) { - float horizontalAngle = AllBlocks.WEIGHTED_EJECTOR.has(state) - ? AngleHelper.horizontalAngle(state.getValue(EjectorBlock.HORIZONTAL_FACING)) - : 0; - return horizontalAngle; - } - - @Override - protected boolean isSideActive(BlockState state, Direction direction) { - return direction == Direction.UP; - } - - @Override - protected float getScale() { - return 0.2f; - } - - @Override - protected Vec3 getSouthLocation() { - return Vec3.ZERO; - } - - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorTriggerPacket.java b/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorTriggerPacket.java deleted file mode 100644 index 342787693..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorTriggerPacket.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.simibubi.create.content.logistics.block.depot; - -import com.simibubi.create.foundation.networking.TileEntityConfigurationPacket; - -import net.minecraft.core.BlockPos; -import net.minecraft.network.FriendlyByteBuf; - -public class EjectorTriggerPacket extends TileEntityConfigurationPacket { - - public EjectorTriggerPacket(BlockPos pos) { - super(pos); - } - - public EjectorTriggerPacket(FriendlyByteBuf buffer) { - super(buffer); - } - - @Override - protected void writeSettings(FriendlyByteBuf buffer) {} - - @Override - protected void readSettings(FriendlyByteBuf buffer) {} - - @Override - protected void applySettings(EjectorTileEntity te) { - te.activate(); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/diodes/AbstractDiodeBlock.java b/src/main/java/com/simibubi/create/content/logistics/block/diodes/AbstractDiodeBlock.java deleted file mode 100644 index 3b1c7d2b8..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/diodes/AbstractDiodeBlock.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.simibubi.create.content.logistics.block.diodes; - -import com.simibubi.create.content.contraptions.wrench.IWrenchable; - -import net.minecraft.world.level.block.DiodeBlock; -import net.minecraft.world.level.block.state.BlockState; - -public abstract class AbstractDiodeBlock extends DiodeBlock implements IWrenchable { - - public AbstractDiodeBlock(Properties builder) { - super(builder); - } - - @Override - public boolean isSignalSource(BlockState state) { - return true; - } -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/diodes/BrassDiodeInstance.java b/src/main/java/com/simibubi/create/content/logistics/block/diodes/BrassDiodeInstance.java deleted file mode 100644 index 450726b17..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/diodes/BrassDiodeInstance.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.simibubi.create.content.logistics.block.diodes; - -import com.jozufozu.flywheel.api.MaterialManager; -import com.jozufozu.flywheel.api.instance.TickableInstance; -import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance; -import com.jozufozu.flywheel.core.Materials; -import com.jozufozu.flywheel.core.materials.model.ModelData; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.foundation.utility.Color; - -public class BrassDiodeInstance extends BlockEntityInstance implements TickableInstance { - - protected final ModelData indicator; - - protected int previousState; - - public BrassDiodeInstance(MaterialManager modelManager, BrassDiodeTileEntity tile) { - super(modelManager, tile); - - indicator = modelManager.defaultSolid() - .material(Materials.TRANSFORMED) - .getModel(AllBlockPartials.FLEXPEATER_INDICATOR, blockState).createInstance(); - - indicator.loadIdentity() - .translate(getInstancePosition()) - .setColor(getColor()); - - previousState = tile.state; - } - - @Override - public void tick() { - if (previousState == blockEntity.state) return; - - indicator.setColor(getColor()); - - previousState = blockEntity.state; - } - - @Override - public void updateLight() { - relight(pos, indicator); - } - - @Override - public void remove() { - indicator.delete(); - } - - protected int getColor() { - return Color.mixColors(0x2c0300, 0xcd0000, blockEntity.getProgress()); - } -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/diodes/BrassDiodeRenderer.java b/src/main/java/com/simibubi/create/content/logistics/block/diodes/BrassDiodeRenderer.java deleted file mode 100644 index f7cdaf99d..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/diodes/BrassDiodeRenderer.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.simibubi.create.content.logistics.block.diodes; - -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.tileEntity.renderer.ColoredOverlayTileEntityRenderer; -import com.simibubi.create.foundation.utility.Color; - -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; - -public class BrassDiodeRenderer extends ColoredOverlayTileEntityRenderer { - - public BrassDiodeRenderer(BlockEntityRendererProvider.Context context) { - super(context); - } - - @Override - protected int getColor(BrassDiodeTileEntity te, float partialTicks) { - return Color.mixColors(0x2C0300, 0xCD0000, te.getProgress()); - } - - @Override - protected SuperByteBuffer getOverlayBuffer(BrassDiodeTileEntity te) { - return CachedBufferer.partial(AllBlockPartials.FLEXPEATER_INDICATOR, te.getBlockState()); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/diodes/BrassDiodeScrollSlot.java b/src/main/java/com/simibubi/create/content/logistics/block/diodes/BrassDiodeScrollSlot.java deleted file mode 100644 index 540a0638a..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/diodes/BrassDiodeScrollSlot.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.simibubi.create.content.logistics.block.diodes; - -import com.jozufozu.flywheel.util.transform.TransformStack; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.phys.Vec3; - -public class BrassDiodeScrollSlot extends ValueBoxTransform { - - @Override - protected Vec3 getLocalOffset(BlockState state) { - return VecHelper.voxelSpace(8, 3f, 8); - } - - @Override - protected void rotate(BlockState state, PoseStack ms) { - float yRot = AngleHelper.horizontalAngle(state.getValue(BlockStateProperties.HORIZONTAL_FACING)) + 180; - TransformStack.cast(ms) - .rotateY(yRot) - .rotateX(90); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/diodes/BrassDiodeTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/diodes/BrassDiodeTileEntity.java deleted file mode 100644 index 0e08276e8..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/diodes/BrassDiodeTileEntity.java +++ /dev/null @@ -1,107 +0,0 @@ -package com.simibubi.create.content.logistics.block.diodes; - -import static com.simibubi.create.content.logistics.block.diodes.BrassDiodeBlock.POWERING; - -import java.util.List; - -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueBehaviour.StepContext; -import com.simibubi.create.foundation.utility.Lang; - -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.util.Mth; -import net.minecraft.world.level.block.DiodeBlock; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; - -public abstract class BrassDiodeTileEntity extends SmartTileEntity { - - protected int state; - ScrollValueBehaviour maxState; - - public BrassDiodeTileEntity(BlockEntityType tileEntityTypeIn, BlockPos pos, BlockState state) { - super(tileEntityTypeIn, pos, state); - } - - @Override - public void addBehaviours(List behaviours) { - maxState = new ScrollValueBehaviour(Lang.translateDirect("generic.delay"), this, new BrassDiodeScrollSlot()) - .between(2, 60 * 20 * 30); - maxState.withStepFunction(this::step); - maxState.withFormatter(this::format); - maxState.withUnit(this::getUnit); - maxState.withCallback(this::onMaxDelayChanged); - behaviours.add(maxState); - } - - public float getProgress() { - int max = Math.max(2, maxState.getValue()); - return Mth.clamp(state, 0, max) / (float) max; - } - - public boolean isIdle() { - return state == 0; - } - - @Override - public void tick() { - super.tick(); - boolean powered = getBlockState().getValue(DiodeBlock.POWERED); - boolean powering = getBlockState().getValue(POWERING); - boolean atMax = state >= maxState.getValue(); - boolean atMin = state <= 0; - updateState(powered, powering, atMax, atMin); - } - - protected abstract void updateState(boolean powered, boolean powering, boolean atMax, boolean atMin); - - private void onMaxDelayChanged(int newMax) { - state = Mth.clamp(state, 0, newMax); - sendData(); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - state = compound.getInt("State"); - super.read(compound, clientPacket); - } - - @Override - public void write(CompoundTag compound, boolean clientPacket) { - compound.putInt("State", state); - super.write(compound, clientPacket); - } - - private int step(StepContext context) { - int value = context.currentValue; - if (!context.forward) - value--; - - if (value < 20) - return 1; - if (value < 20 * 60) - return 20; - return 20 * 60; - } - - private String format(int value) { - if (value < 20) - return value + "t"; - if (value < 20 * 60) - return (value / 20) + "s"; - return (value / 20 / 60) + "m"; - } - - private Component getUnit(int value) { - if (value < 20) - return Lang.translateDirect("generic.unit.ticks"); - if (value < 20 * 60) - return Lang.translateDirect("generic.unit.seconds"); - return Lang.translateDirect("generic.unit.minutes"); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/diodes/PulseExtenderTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/diodes/PulseExtenderTileEntity.java deleted file mode 100644 index b73cd2403..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/diodes/PulseExtenderTileEntity.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.simibubi.create.content.logistics.block.diodes; - -import static com.simibubi.create.content.logistics.block.diodes.BrassDiodeBlock.POWERING; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; - -public class PulseExtenderTileEntity extends BrassDiodeTileEntity { - - public PulseExtenderTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - @Override - protected void updateState(boolean powered, boolean powering, boolean atMax, boolean atMin) { - if (atMin && !powered) - return; - if (atMin || powered) { - level.setBlockAndUpdate(worldPosition, getBlockState().setValue(POWERING, true)); - state = maxState.getValue(); - return; - } - - if (state == 1) { - if (powering && !level.isClientSide) - level.setBlockAndUpdate(worldPosition, getBlockState().setValue(POWERING, false)); - if (!powered) - state = 0; - return; - } - - if (!powered) - state--; - } -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/diodes/PulseRepeaterTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/diodes/PulseRepeaterTileEntity.java deleted file mode 100644 index 330c7889a..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/diodes/PulseRepeaterTileEntity.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.simibubi.create.content.logistics.block.diodes; - -import static com.simibubi.create.content.logistics.block.diodes.BrassDiodeBlock.POWERING; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; - -public class PulseRepeaterTileEntity extends BrassDiodeTileEntity { - - public PulseRepeaterTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - @Override - protected void updateState(boolean powered, boolean powering, boolean atMax, boolean atMin) { - if (atMin && !powered) - return; - if (state > maxState.getValue() + 1) { - if (!powered && !powering) - state = 0; - return; - } - - state++; - if (level.isClientSide) - return; - - if (state == maxState.getValue() - 1 && !powering) - level.setBlockAndUpdate(worldPosition, getBlockState().cycle(POWERING)); - if (state == maxState.getValue() + 1 && powering) - level.setBlockAndUpdate(worldPosition, getBlockState().cycle(POWERING)); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/AllDisplayBehaviours.java b/src/main/java/com/simibubi/create/content/logistics/block/display/AllDisplayBehaviours.java deleted file mode 100644 index badc3f562..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/AllDisplayBehaviours.java +++ /dev/null @@ -1,230 +0,0 @@ -package com.simibubi.create.content.logistics.block.display; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.annotation.Nullable; - -import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.block.display.source.DeathCounterDisplaySource; -import com.simibubi.create.content.logistics.block.display.source.DisplaySource; -import com.simibubi.create.content.logistics.block.display.source.EnchantPowerDisplaySource; -import com.simibubi.create.content.logistics.block.display.source.RedstonePowerDisplaySource; -import com.simibubi.create.content.logistics.block.display.source.ScoreboardDisplaySource; -import com.simibubi.create.content.logistics.block.display.target.DisplayTarget; -import com.simibubi.create.content.logistics.block.display.target.LecternDisplayTarget; -import com.simibubi.create.content.logistics.block.display.target.SignDisplayTarget; -import com.simibubi.create.foundation.utility.CreateRegistry; -import com.simibubi.create.foundation.utility.RegisteredObjects; -import com.tterrag.registrate.util.nullness.NonNullConsumer; - -import net.minecraft.core.BlockPos; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.registries.ForgeRegistries; - -public class AllDisplayBehaviours { - public static final Map GATHERER_BEHAVIOURS = new HashMap<>(); - - private static final CreateRegistry> SOURCES_BY_BLOCK = new CreateRegistry<>(ForgeRegistries.BLOCKS); - private static final CreateRegistry, List> SOURCES_BY_TILE = new CreateRegistry<>(ForgeRegistries.BLOCK_ENTITY_TYPES); - - private static final CreateRegistry TARGETS_BY_BLOCK = new CreateRegistry<>(ForgeRegistries.BLOCKS); - private static final CreateRegistry, DisplayTarget> TARGETS_BY_TILE = new CreateRegistry<>(ForgeRegistries.BLOCK_ENTITY_TYPES); - - public static DisplayBehaviour register(ResourceLocation id, DisplayBehaviour behaviour) { - behaviour.id = id; - GATHERER_BEHAVIOURS.put(id, behaviour); - return behaviour; - } - - public static void assignBlock(DisplayBehaviour behaviour, ResourceLocation block) { - if (behaviour instanceof DisplaySource source) { - List sources = SOURCES_BY_BLOCK.get(block); - if (sources == null) { - sources = new ArrayList<>(); - SOURCES_BY_BLOCK.register(block, sources); - } - sources.add(source); - } - if (behaviour instanceof DisplayTarget target) { - TARGETS_BY_BLOCK.register(block, target); - } - } - - public static void assignTile(DisplayBehaviour behaviour, ResourceLocation teType) { - if (behaviour instanceof DisplaySource source) { - List sources = SOURCES_BY_TILE.get(teType); - if (sources == null) { - sources = new ArrayList<>(); - SOURCES_BY_TILE.register(teType, sources); - } - sources.add(source); - } - if (behaviour instanceof DisplayTarget target) { - TARGETS_BY_TILE.register(teType, target); - } - } - - public static void assignBlock(DisplayBehaviour behaviour, Block block) { - if (behaviour instanceof DisplaySource source) { - List sources = SOURCES_BY_BLOCK.get(block); - if (sources == null) { - sources = new ArrayList<>(); - SOURCES_BY_BLOCK.register(block, sources); - } - sources.add(source); - } - if (behaviour instanceof DisplayTarget target) { - TARGETS_BY_BLOCK.register(block, target); - } - } - - public static void assignTile(DisplayBehaviour behaviour, BlockEntityType teType) { - if (behaviour instanceof DisplaySource source) { - List sources = SOURCES_BY_TILE.get(teType); - if (sources == null) { - sources = new ArrayList<>(); - SOURCES_BY_TILE.register(teType, sources); - } - sources.add(source); - } - if (behaviour instanceof DisplayTarget target) { - TARGETS_BY_TILE.register(teType, target); - } - } - - public static NonNullConsumer assignDataBehaviour(DisplayBehaviour behaviour, - String... suffix) { - return b -> { - ResourceLocation registryName = RegisteredObjects.getKeyOrThrow(b); - String idSuffix = behaviour instanceof DisplaySource ? "_source" : "_target"; - if (suffix.length > 0) - idSuffix += "_" + suffix[0]; - assignBlock(register(new ResourceLocation(registryName.getNamespace(), registryName.getPath() + idSuffix), - behaviour), registryName); - }; - } - - public static > NonNullConsumer assignDataBehaviourTE( - DisplayBehaviour behaviour, String... suffix) { - return b -> { - ResourceLocation registryName = RegisteredObjects.getKeyOrThrow(b); - String idSuffix = behaviour instanceof DisplaySource ? "_source" : "_target"; - if (suffix.length > 0) - idSuffix += "_" + suffix[0]; - assignTile( - register(new ResourceLocation(registryName.getNamespace(), registryName.getPath() + idSuffix), - behaviour), - registryName); - }; - } - - // - - @Nullable - public static DisplaySource getSource(ResourceLocation resourceLocation) { - DisplayBehaviour available = GATHERER_BEHAVIOURS.getOrDefault(resourceLocation, null); - if (available instanceof DisplaySource source) - return source; - return null; - } - - @Nullable - public static DisplayTarget getTarget(ResourceLocation resourceLocation) { - DisplayBehaviour available = GATHERER_BEHAVIOURS.getOrDefault(resourceLocation, null); - if (available instanceof DisplayTarget target) - return target; - return null; - } - - // - - public static List sourcesOf(Block block) { - List sources = SOURCES_BY_BLOCK.get(block); - if (sources == null) { - return Collections.emptyList(); - } - return sources; - } - - public static List sourcesOf(BlockState state) { - return sourcesOf(state.getBlock()); - } - - public static List sourcesOf(BlockEntityType tileEntityType) { - List sources = SOURCES_BY_TILE.get(tileEntityType); - if (sources == null) { - return Collections.emptyList(); - } - return sources; - } - - public static List sourcesOf(BlockEntity tileEntity) { - return sourcesOf(tileEntity.getType()); - } - - @Nullable - public static DisplayTarget targetOf(Block block) { - return TARGETS_BY_BLOCK.get(block); - } - - @Nullable - public static DisplayTarget targetOf(BlockState state) { - return targetOf(state.getBlock()); - } - - @Nullable - public static DisplayTarget targetOf(BlockEntityType tileEntityType) { - return TARGETS_BY_TILE.get(tileEntityType); - } - - @Nullable - public static DisplayTarget targetOf(BlockEntity tileEntity) { - return targetOf(tileEntity.getType()); - } - - public static List sourcesOf(LevelAccessor level, BlockPos pos) { - BlockState blockState = level.getBlockState(pos); - BlockEntity blockEntity = level.getBlockEntity(pos); - - List sourcesOfBlock = sourcesOf(blockState); - List sourcesOfTE = blockEntity == null ? Collections.emptyList() : sourcesOf(blockEntity); - - if (sourcesOfTE.isEmpty()) - return sourcesOfBlock; - return sourcesOfTE; - } - - @Nullable - public static DisplayTarget targetOf(LevelAccessor level, BlockPos pos) { - BlockState blockState = level.getBlockState(pos); - BlockEntity blockEntity = level.getBlockEntity(pos); - - DisplayTarget targetOfBlock = targetOf(blockState); - DisplayTarget targetOfTE = blockEntity == null ? null : targetOf(blockEntity); - - if (targetOfTE == null) - return targetOfBlock; - return targetOfTE; - } - - // - - public static void registerDefaults() { - assignTile(register(Create.asResource("sign_display_target"), new SignDisplayTarget()), BlockEntityType.SIGN); - assignTile(register(Create.asResource("lectern_display_target"), new LecternDisplayTarget()), BlockEntityType.LECTERN); - assignBlock(register(Create.asResource("death_count_display_source"), new DeathCounterDisplaySource()), Blocks.RESPAWN_ANCHOR); - assignTile(register(Create.asResource("scoreboard_display_source"), new ScoreboardDisplaySource()), BlockEntityType.COMMAND_BLOCK); - assignTile(register(Create.asResource("enchant_power_display_source"), new EnchantPowerDisplaySource()), BlockEntityType.ENCHANTING_TABLE); - assignBlock(register(Create.asResource("redstone_power_display_source"), new RedstonePowerDisplaySource()), Blocks.TARGET); - } -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/DisplayBehaviour.java b/src/main/java/com/simibubi/create/content/logistics/block/display/DisplayBehaviour.java deleted file mode 100644 index 712c85d6b..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/DisplayBehaviour.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.simibubi.create.content.logistics.block.display; - -import net.minecraft.resources.ResourceLocation; - -public abstract class DisplayBehaviour { - - public ResourceLocation id; - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/DisplayLinkConfigurationPacket.java b/src/main/java/com/simibubi/create/content/logistics/block/display/DisplayLinkConfigurationPacket.java deleted file mode 100644 index c83d6894a..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/DisplayLinkConfigurationPacket.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.simibubi.create.content.logistics.block.display; - -import com.simibubi.create.content.logistics.block.display.source.DisplaySource; -import com.simibubi.create.foundation.networking.TileEntityConfigurationPacket; - -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.resources.ResourceLocation; - -public class DisplayLinkConfigurationPacket extends TileEntityConfigurationPacket { - - private CompoundTag configData; - private int targetLine; - - public DisplayLinkConfigurationPacket(BlockPos pos, CompoundTag configData, int targetLine) { - super(pos); - this.configData = configData; - this.targetLine = targetLine; - } - - public DisplayLinkConfigurationPacket(FriendlyByteBuf buffer) { - super(buffer); - } - - @Override - protected void writeSettings(FriendlyByteBuf buffer) { - buffer.writeNbt(configData); - buffer.writeInt(targetLine); - } - - @Override - protected void readSettings(FriendlyByteBuf buffer) { - configData = buffer.readNbt(); - targetLine = buffer.readInt(); - } - - @Override - protected void applySettings(DisplayLinkTileEntity te) { - te.targetLine = targetLine; - - if (!configData.contains("Id")) { - te.notifyUpdate(); - return; - } - - ResourceLocation id = new ResourceLocation(configData.getString("Id")); - DisplaySource source = AllDisplayBehaviours.getSource(id); - if (source == null) { - te.notifyUpdate(); - return; - } - - if (te.activeSource == null || te.activeSource != source) { - te.activeSource = source; - te.setSourceConfig(configData.copy()); - } else { - te.getSourceConfig() - .merge(configData); - } - - te.updateGatheredData(); - te.notifyUpdate(); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/DisplayLinkContext.java b/src/main/java/com/simibubi/create/content/logistics/block/display/DisplayLinkContext.java deleted file mode 100644 index 49477f76b..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/DisplayLinkContext.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.simibubi.create.content.logistics.block.display; - -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.BlockEntity; - -public class DisplayLinkContext { - - private Level level; - private DisplayLinkTileEntity te; - - public Object flapDisplayContext; - - public DisplayLinkContext(Level level, DisplayLinkTileEntity te) { - this.level = level; - this.te = te; - } - - public Level level() { - return level; - } - - public DisplayLinkTileEntity te() { - return te; - } - - public BlockEntity getSourceTE() { - return level.getBlockEntity(getSourcePos()); - } - - public BlockPos getSourcePos() { - return te.getSourcePosition(); - } - - public BlockEntity getTargetTE() { - return level.getBlockEntity(getTargetPos()); - } - - public BlockPos getTargetPos() { - return te.getTargetPosition(); - } - - public CompoundTag sourceConfig() { - return te.getSourceConfig(); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/DisplayLinkRenderer.java b/src/main/java/com/simibubi/create/content/logistics/block/display/DisplayLinkRenderer.java deleted file mode 100644 index 3650b2554..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/DisplayLinkRenderer.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.simibubi.create.content.logistics.block.display; - -import com.jozufozu.flywheel.util.transform.TransformStack; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.RenderTypes; -import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; -import com.simibubi.create.foundation.utility.AngleHelper; - -import net.minecraft.client.renderer.LightTexture; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.Direction; -import net.minecraft.util.Mth; -import net.minecraft.world.level.block.state.BlockState; - -public class DisplayLinkRenderer extends SafeTileEntityRenderer { - - public DisplayLinkRenderer(BlockEntityRendererProvider.Context context) {} - - @Override - protected void renderSafe(DisplayLinkTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - float glow = te.glow.getValue(partialTicks); - if (glow < .125f) - return; - - glow = (float) (1 - (2 * Math.pow(glow - .75f, 2))); - glow = Mth.clamp(glow, -1, 1); - - int color = (int) (200 * glow); - - BlockState blockState = te.getBlockState(); - TransformStack msr = TransformStack.cast(ms); - - Direction face = blockState.getOptionalValue(DisplayLinkBlock.FACING) - .orElse(Direction.UP); - - if (face.getAxis() - .isHorizontal()) - face = face.getOpposite(); - - ms.pushPose(); - - msr.centre() - .rotateY(AngleHelper.horizontalAngle(face)) - .rotateX(-AngleHelper.verticalAngle(face) - 90) - .unCentre(); - - CachedBufferer.partial(AllBlockPartials.DISPLAY_LINK_TUBE, blockState) - .light(LightTexture.FULL_BRIGHT) - .renderInto(ms, buffer.getBuffer(RenderType.translucent())); - - CachedBufferer.partial(AllBlockPartials.DISPLAY_LINK_GLOW, blockState) - .light(LightTexture.FULL_BRIGHT) - .color(color, color, color, 255) - .disableDiffuse() - .renderInto(ms, buffer.getBuffer(RenderTypes.getAdditive())); - - ms.popPose(); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/DisplayLinkTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/display/DisplayLinkTileEntity.java deleted file mode 100644 index 9d9a5f606..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/DisplayLinkTileEntity.java +++ /dev/null @@ -1,202 +0,0 @@ -package com.simibubi.create.content.logistics.block.display; - -import java.util.List; - -import com.simibubi.create.content.logistics.block.display.source.DisplaySource; -import com.simibubi.create.content.logistics.block.display.target.DisplayTarget; -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtUtils; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; - -public class DisplayLinkTileEntity extends SmartTileEntity { - - protected BlockPos targetOffset; - - public DisplaySource activeSource; - private CompoundTag sourceConfig; - - public DisplayTarget activeTarget; - public int targetLine; - - public LerpedFloat glow; - private boolean sendPulse; - - public int refreshTicks; - - public DisplayLinkTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - targetOffset = BlockPos.ZERO; - sourceConfig = new CompoundTag(); - targetLine = 0; - glow = LerpedFloat.linear() - .startWithValue(0); - glow.chase(0, 0.5f, Chaser.EXP); - } - - @Override - public void tick() { - super.tick(); - - if (isVirtual()) { - glow.tickChaser(); - return; - } - - if (activeSource == null) - return; - if (level.isClientSide) { - glow.tickChaser(); - return; - } - - refreshTicks++; - if (refreshTicks < activeSource.getPassiveRefreshTicks()) - return; - tickSource(); - } - - public void tickSource() { - refreshTicks = 0; - if (getBlockState().getOptionalValue(DisplayLinkBlock.POWERED) - .orElse(true)) - return; - if (!level.isClientSide) - updateGatheredData(); - } - - public void onNoLongerPowered() { - if (activeSource == null) - return; - refreshTicks = 0; - activeSource.onSignalReset(new DisplayLinkContext(level, this)); - updateGatheredData(); - } - - public void updateGatheredData() { - BlockPos sourcePosition = getSourcePosition(); - BlockPos targetPosition = getTargetPosition(); - - if (!level.isLoaded(targetPosition) || !level.isLoaded(sourcePosition)) - return; - - DisplayTarget target = AllDisplayBehaviours.targetOf(level, targetPosition); - List sources = AllDisplayBehaviours.sourcesOf(level, sourcePosition); - boolean notify = false; - - if (activeTarget != target) { - activeTarget = target; - notify = true; - } - - if (activeSource != null && !sources.contains(activeSource)) { - activeSource = null; - sourceConfig = new CompoundTag(); - notify = true; - } - - if (notify) - notifyUpdate(); - if (activeSource == null || activeTarget == null) - return; - - DisplayLinkContext context = new DisplayLinkContext(level, this); - activeSource.transferData(context, activeTarget, targetLine); - sendPulse = true; - sendData(); - - award(AllAdvancements.DISPLAY_LINK); - } - - @Override - public void addBehaviours(List behaviours) { - registerAwardables(behaviours, AllAdvancements.DISPLAY_LINK, AllAdvancements.DISPLAY_BOARD); - } - - @Override - public void writeSafe(CompoundTag tag) { - super.writeSafe(tag); - writeGatheredData(tag); - } - - @Override - protected void write(CompoundTag tag, boolean clientPacket) { - super.write(tag, clientPacket); - writeGatheredData(tag); - if (clientPacket && activeTarget != null) - tag.putString("TargetType", activeTarget.id.toString()); - if (clientPacket && sendPulse) { - sendPulse = false; - NBTHelper.putMarker(tag, "Pulse"); - } - } - - private void writeGatheredData(CompoundTag tag) { - tag.put("TargetOffset", NbtUtils.writeBlockPos(targetOffset)); - tag.putInt("TargetLine", targetLine); - - if (activeSource != null) { - CompoundTag data = sourceConfig.copy(); - data.putString("Id", activeSource.id.toString()); - tag.put("Source", data); - } - } - - @Override - protected void read(CompoundTag tag, boolean clientPacket) { - super.read(tag, clientPacket); - targetOffset = NbtUtils.readBlockPos(tag.getCompound("TargetOffset")); - targetLine = tag.getInt("TargetLine"); - - if (clientPacket && tag.contains("TargetType")) - activeTarget = AllDisplayBehaviours.getTarget(new ResourceLocation(tag.getString("TargetType"))); - if (clientPacket && tag.contains("Pulse")) - glow.setValue(2); - - if (!tag.contains("Source")) - return; - - CompoundTag data = tag.getCompound("Source"); - activeSource = AllDisplayBehaviours.getSource(new ResourceLocation(data.getString("Id"))); - sourceConfig = new CompoundTag(); - if (activeSource != null) - sourceConfig = data.copy(); - } - - public void target(BlockPos targetPosition) { - this.targetOffset = targetPosition.subtract(worldPosition); - } - - public BlockPos getSourcePosition() { - return worldPosition.relative(getDirection()); - } - - public CompoundTag getSourceConfig() { - return sourceConfig; - } - - public void setSourceConfig(CompoundTag sourceConfig) { - this.sourceConfig = sourceConfig; - } - - public Direction getDirection() { - return getBlockState().getOptionalValue(DisplayLinkBlock.FACING) - .orElse(Direction.UP) - .getOpposite(); - } - - public BlockPos getTargetPosition() { - return worldPosition.offset(targetOffset); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/AccumulatedItemCountDisplaySource.java b/src/main/java/com/simibubi/create/content/logistics/block/display/source/AccumulatedItemCountDisplaySource.java deleted file mode 100644 index 623871b58..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/AccumulatedItemCountDisplaySource.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.simibubi.create.content.logistics.block.display.source; - -import com.simibubi.create.content.logistics.block.display.DisplayLinkBlock; -import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; -import com.simibubi.create.content.logistics.block.display.DisplayLinkTileEntity; -import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats; -import com.simibubi.create.foundation.utility.Components; - -import net.minecraft.network.chat.MutableComponent; - -public class AccumulatedItemCountDisplaySource extends NumericSingleLineDisplaySource { - - @Override - protected MutableComponent provideLine(DisplayLinkContext context, DisplayTargetStats stats) { - return Components.literal(String.valueOf(context.sourceConfig() - .getInt("Collected"))); - } - - public void itemReceived(DisplayLinkTileEntity te, int amount) { - if (te.getBlockState() - .getOptionalValue(DisplayLinkBlock.POWERED) - .orElse(true)) - return; - - int collected = te.getSourceConfig() - .getInt("Collected"); - te.getSourceConfig() - .putInt("Collected", collected + amount); - te.updateGatheredData(); - } - - @Override - protected String getTranslationKey() { - return "accumulate_items"; - } - - @Override - public int getPassiveRefreshTicks() { - return 200; - } - - @Override - public void onSignalReset(DisplayLinkContext context) { - context.sourceConfig() - .remove("Collected"); - } - - @Override - protected boolean allowsLabeling(DisplayLinkContext context) { - return true; - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/EntityNameDisplaySource.java b/src/main/java/com/simibubi/create/content/logistics/block/display/source/EntityNameDisplaySource.java deleted file mode 100644 index 0f6375a73..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/EntityNameDisplaySource.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.simibubi.create.content.logistics.block.display.source; - -import java.util.List; - -import com.simibubi.create.content.contraptions.components.actors.SeatEntity; -import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; -import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats; - -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.phys.AABB; - -public class EntityNameDisplaySource extends SingleLineDisplaySource { - @Override - protected MutableComponent provideLine(DisplayLinkContext context, DisplayTargetStats stats) { - List seats = context.level().getEntitiesOfClass(SeatEntity.class, new AABB(context.getSourcePos())); - - if (seats.isEmpty()) - return EMPTY_LINE; - - SeatEntity seatEntity = seats.get(0); - List passengers = seatEntity.getPassengers(); - - if (passengers.isEmpty()) - return EMPTY_LINE; - - return passengers.get(0).getDisplayName().copy(); - } - - @Override - protected String getTranslationKey() { - return "entity_name"; - } - - @Override - protected boolean allowsLabeling(DisplayLinkContext context) { - return true; - } -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/FluidAmountDisplaySource.java b/src/main/java/com/simibubi/create/content/logistics/block/display/source/FluidAmountDisplaySource.java deleted file mode 100644 index a9ed75db8..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/FluidAmountDisplaySource.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.simibubi.create.content.logistics.block.display.source; - -import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; -import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats; -import com.simibubi.create.content.logistics.block.redstone.ContentObserverTileEntity; -import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.inventory.TankManipulationBehaviour; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.FluidFormatter; - -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.capability.IFluidHandler; - -public class FluidAmountDisplaySource extends SingleLineDisplaySource { - - @Override - protected MutableComponent provideLine(DisplayLinkContext context, DisplayTargetStats stats) { - BlockEntity sourceTE = context.getSourceTE(); - if (!(sourceTE instanceof ContentObserverTileEntity cote)) - return EMPTY_LINE; - - TankManipulationBehaviour tankManipulationBehaviour = cote.getBehaviour(TankManipulationBehaviour.OBSERVE); - FilteringBehaviour filteringBehaviour = cote.getBehaviour(FilteringBehaviour.TYPE); - IFluidHandler handler = tankManipulationBehaviour.getInventory(); - - if (handler == null) - return EMPTY_LINE; - - long collected = 0; - for (int i = 0; i < handler.getTanks(); i++) { - FluidStack stack = handler.getFluidInTank(i); - if (stack.isEmpty()) - continue; - if (!filteringBehaviour.test(stack)) - continue; - collected += stack.getAmount(); - } - - return Components.literal(FluidFormatter.asString(collected, false)); - } - - @Override - protected String getTranslationKey() { - return "fluid_amount"; - } - - @Override - protected boolean allowsLabeling(DisplayLinkContext context) { - return true; - } -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/ItemCountDisplaySource.java b/src/main/java/com/simibubi/create/content/logistics/block/display/source/ItemCountDisplaySource.java deleted file mode 100644 index 599f73ca0..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/ItemCountDisplaySource.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.simibubi.create.content.logistics.block.display.source; - -import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; -import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats; -import com.simibubi.create.content.logistics.block.redstone.ContentObserverTileEntity; -import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.inventory.InvManipulationBehaviour; -import com.simibubi.create.foundation.utility.Components; - -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraftforge.items.IItemHandler; - -public class ItemCountDisplaySource extends NumericSingleLineDisplaySource { - - @Override - protected MutableComponent provideLine(DisplayLinkContext context, DisplayTargetStats stats) { - BlockEntity sourceTE = context.getSourceTE(); - if (!(sourceTE instanceof ContentObserverTileEntity cote)) - return ZERO.copy(); - - InvManipulationBehaviour invManipulationBehaviour = cote.getBehaviour(InvManipulationBehaviour.TYPE); - FilteringBehaviour filteringBehaviour = cote.getBehaviour(FilteringBehaviour.TYPE); - IItemHandler handler = invManipulationBehaviour.getInventory(); - - if (handler == null) - return ZERO.copy(); - - int collected = 0; - for (int i = 0; i < handler.getSlots(); i++) { - ItemStack stack = handler.extractItem(i, handler.getSlotLimit(i), true); - if (stack.isEmpty()) - continue; - if (!filteringBehaviour.test(stack)) - continue; - collected += stack.getCount(); - } - - return Components.literal(String.valueOf(collected)); - } - - @Override - protected String getTranslationKey() { - return "count_items"; - } - - @Override - protected boolean allowsLabeling(DisplayLinkContext context) { - return true; - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/ItemListDisplaySource.java b/src/main/java/com/simibubi/create/content/logistics/block/display/source/ItemListDisplaySource.java deleted file mode 100644 index 4e9768dbd..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/ItemListDisplaySource.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.simibubi.create.content.logistics.block.display.source; - -import java.util.stream.Stream; - -import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; -import com.simibubi.create.content.logistics.block.redstone.ContentObserverTileEntity; -import com.simibubi.create.foundation.item.CountedItemStackList; -import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.inventory.InvManipulationBehaviour; -import com.simibubi.create.foundation.utility.IntAttached; - -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraftforge.items.IItemHandler; - -public class ItemListDisplaySource extends ValueListDisplaySource { - - @Override - protected Stream> provideEntries(DisplayLinkContext context, int maxRows) { - BlockEntity sourceTE = context.getSourceTE(); - if (!(sourceTE instanceof ContentObserverTileEntity cote)) - return Stream.empty(); - - InvManipulationBehaviour invManipulationBehaviour = cote.getBehaviour(InvManipulationBehaviour.TYPE); - FilteringBehaviour filteringBehaviour = cote.getBehaviour(FilteringBehaviour.TYPE); - IItemHandler handler = invManipulationBehaviour.getInventory(); - - if (handler == null) - return Stream.empty(); - - return new CountedItemStackList(handler, filteringBehaviour).getTopNames(maxRows); - } - - @Override - protected String getTranslationKey() { - return "list_items"; - } - - @Override - protected boolean valueFirst() { - return true; - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/ItemNameDisplaySource.java b/src/main/java/com/simibubi/create/content/logistics/block/display/source/ItemNameDisplaySource.java deleted file mode 100644 index 922b0a206..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/ItemNameDisplaySource.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.simibubi.create.content.logistics.block.display.source; - -import org.apache.commons.lang3.mutable.MutableObject; - -import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; -import com.simibubi.create.content.logistics.block.display.DisplayLinkTileEntity; -import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour.TransportedResult; - -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Direction; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.item.ItemStack; - -public class ItemNameDisplaySource extends SingleLineDisplaySource { - - @Override - protected MutableComponent provideLine(DisplayLinkContext context, DisplayTargetStats stats) { - DisplayLinkTileEntity gatherer = context.te(); - Direction direction = gatherer.getDirection(); - MutableBlockPos pos = gatherer.getSourcePosition() - .mutable(); - - MutableComponent combined = EMPTY_LINE.copy(); - - for (int i = 0; i < 32; i++) { - TransportedItemStackHandlerBehaviour behaviour = - TileEntityBehaviour.get(context.level(), pos, TransportedItemStackHandlerBehaviour.TYPE); - pos.move(direction); - - if (behaviour == null) - break; - - MutableObject stackHolder = new MutableObject<>(); - behaviour.handleCenteredProcessingOnAllItems(.25f, tis -> { - stackHolder.setValue(tis.stack); - return TransportedResult.doNothing(); - }); - - ItemStack stack = stackHolder.getValue(); - if (stack != null && !stack.isEmpty()) - combined = combined.append(stack.getHoverName()); - } - - return combined; - } - - @Override - protected String getTranslationKey() { - return "combine_item_names"; - } - - @Override - protected boolean allowsLabeling(DisplayLinkContext context) { - return true; - } - - @Override - protected String getFlapDisplayLayoutName(DisplayLinkContext context) { - return "Number"; - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/KineticSpeedDisplaySource.java b/src/main/java/com/simibubi/create/content/logistics/block/display/source/KineticSpeedDisplaySource.java deleted file mode 100644 index c9c1e7e73..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/KineticSpeedDisplaySource.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.simibubi.create.content.logistics.block.display.source; - -import com.simibubi.create.content.contraptions.relays.gauge.SpeedGaugeTileEntity; -import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; -import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats; -import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; -import com.simibubi.create.foundation.utility.Lang; - -import net.minecraft.network.chat.MutableComponent; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -public class KineticSpeedDisplaySource extends NumericSingleLineDisplaySource { - - @Override - protected MutableComponent provideLine(DisplayLinkContext context, DisplayTargetStats stats) { - if (!(context.getSourceTE() instanceof SpeedGaugeTileEntity gaugeTile)) - return ZERO.copy(); - - boolean absoluteValue = context.sourceConfig() - .getInt("Directional") == 0; - float speed = absoluteValue ? Math.abs(gaugeTile.getSpeed()) : gaugeTile.getSpeed(); - return Lang.number(speed) - .space() - .translate("generic.unit.rpm") - .component(); - } - - @Override - protected String getTranslationKey() { - return "kinetic_speed"; - } - - @Override - @OnlyIn(Dist.CLIENT) - public void initConfigurationWidgets(DisplayLinkContext context, ModularGuiLineBuilder builder, - boolean isFirstLine) { - super.initConfigurationWidgets(context, builder, isFirstLine); - if (isFirstLine) - return; - - builder.addSelectionScrollInput(0, 95, (selectionScrollInput, label) -> { - selectionScrollInput - .forOptions(Lang.translatedOptions("display_source.kinetic_speed", "absolute", "directional")); - }, "Directional"); - } - - @Override - protected boolean allowsLabeling(DisplayLinkContext context) { - return true; - } -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/NixieTubeDisplaySource.java b/src/main/java/com/simibubi/create/content/logistics/block/display/source/NixieTubeDisplaySource.java deleted file mode 100644 index d2e0fa28c..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/NixieTubeDisplaySource.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.simibubi.create.content.logistics.block.display.source; - -import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; -import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats; -import com.simibubi.create.content.logistics.block.display.target.NixieTubeDisplayTarget; -import com.simibubi.create.content.logistics.block.redstone.NixieTubeTileEntity; -import com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection; - -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.level.block.entity.BlockEntity; - -public class NixieTubeDisplaySource extends SingleLineDisplaySource { - - @Override - protected String getTranslationKey() { - return "nixie_tube"; - } - - @Override - protected MutableComponent provideLine(DisplayLinkContext context, DisplayTargetStats stats) { - BlockEntity sourceTE = context.getSourceTE(); - if (!(sourceTE instanceof NixieTubeTileEntity nte)) - return EMPTY_LINE; - - MutableComponent text = nte.getFullText(); - - try { - String line = text.getString(); - Integer.valueOf(line); - context.flapDisplayContext = Boolean.TRUE; - } catch (NumberFormatException e) { - } - - return text; - } - - @Override - protected boolean allowsLabeling(DisplayLinkContext context) { - return !(context.te().activeTarget instanceof NixieTubeDisplayTarget); - } - - @Override - protected String getFlapDisplayLayoutName(DisplayLinkContext context) { - if (isNumeric(context)) - return "Number"; - return super.getFlapDisplayLayoutName(context); - } - - @Override - protected FlapDisplaySection createSectionForValue(DisplayLinkContext context, int size) { - if (isNumeric(context)) - return new FlapDisplaySection(size * FlapDisplaySection.MONOSPACE, "numeric", false, false); - return super.createSectionForValue(context, size); - } - - protected boolean isNumeric(DisplayLinkContext context) { - return context.flapDisplayContext == Boolean.TRUE; - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/NumericSingleLineDisplaySource.java b/src/main/java/com/simibubi/create/content/logistics/block/display/source/NumericSingleLineDisplaySource.java deleted file mode 100644 index 001d2cd91..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/NumericSingleLineDisplaySource.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.simibubi.create.content.logistics.block.display.source; - -import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; -import com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection; -import com.simibubi.create.foundation.utility.Components; - -import net.minecraft.network.chat.Component; - -public abstract class NumericSingleLineDisplaySource extends SingleLineDisplaySource { - - protected static final Component ZERO = Components.literal("0"); - - @Override - protected String getFlapDisplayLayoutName(DisplayLinkContext context) { - return "Number"; - } - - @Override - protected FlapDisplaySection createSectionForValue(DisplayLinkContext context, int size) { - return new FlapDisplaySection(size * FlapDisplaySection.MONOSPACE, "numeric", false, false); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/ObservedTrainNameSource.java b/src/main/java/com/simibubi/create/content/logistics/block/display/source/ObservedTrainNameSource.java deleted file mode 100644 index e58916197..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/ObservedTrainNameSource.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.simibubi.create.content.logistics.block.display.source; - -import java.util.UUID; - -import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; -import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats; -import com.simibubi.create.content.logistics.trains.entity.Train; -import com.simibubi.create.content.logistics.trains.management.edgePoint.observer.TrackObserver; -import com.simibubi.create.content.logistics.trains.management.edgePoint.observer.TrackObserverTileEntity; - -import net.minecraft.network.chat.MutableComponent; - -public class ObservedTrainNameSource extends SingleLineDisplaySource { - - @Override - protected MutableComponent provideLine(DisplayLinkContext context, DisplayTargetStats stats) { - if (!(context.getSourceTE() instanceof TrackObserverTileEntity observerTE)) - return EMPTY_LINE; - TrackObserver observer = observerTE.getObserver(); - if (observer == null) - return EMPTY_LINE; - UUID currentTrain = observer.getCurrentTrain(); - if (currentTrain == null) - return EMPTY_LINE; - Train train = Create.RAILWAYS.trains.get(currentTrain); - if (train == null) - return EMPTY_LINE; - return train.name.copy(); - } - - @Override - public int getPassiveRefreshTicks() { - return 400; - } - - @Override - protected String getTranslationKey() { - return "observed_train_name"; - } - - @Override - protected boolean allowsLabeling(DisplayLinkContext context) { - return true; - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/StopWatchDisplaySource.java b/src/main/java/com/simibubi/create/content/logistics/block/display/source/StopWatchDisplaySource.java deleted file mode 100644 index 250a65e5c..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/StopWatchDisplaySource.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.simibubi.create.content.logistics.block.display.source; - -import com.simibubi.create.content.contraptions.components.clock.CuckooClockTileEntity; -import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; -import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats; -import com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection; -import com.simibubi.create.foundation.utility.Components; - -import net.minecraft.network.chat.MutableComponent; - -public class StopWatchDisplaySource extends SingleLineDisplaySource { - - @Override - protected MutableComponent provideLine(DisplayLinkContext context, DisplayTargetStats stats) { - if (!(context.getSourceTE()instanceof CuckooClockTileEntity ccte)) - return TimeOfDayDisplaySource.EMPTY_TIME; - if (ccte.getSpeed() == 0) - return TimeOfDayDisplaySource.EMPTY_TIME; - - if (!context.sourceConfig() - .contains("StartTime")) - onSignalReset(context); - - long started = context.sourceConfig() - .getLong("StartTime"); - long current = context.te() - .getLevel() - .getGameTime(); - - int diff = (int) (current - started); - int hours = (diff / 60 / 60 / 20); - int minutes = (diff / 60 / 20) % 60; - int seconds = (diff / 20) % 60; - - MutableComponent component = Components.literal((hours == 0 ? "" : (hours < 10 ? " " : "") + hours + ":") - + (minutes < 10 ? hours == 0 ? " " : "0" : "") + minutes + ":" + (seconds < 10 ? "0" : "") + seconds); - - return component; - } - - @Override - public void onSignalReset(DisplayLinkContext context) { - context.sourceConfig() - .putLong("StartTime", context.te() - .getLevel() - .getGameTime()); - } - - @Override - public int getPassiveRefreshTicks() { - return 20; - } - - @Override - protected boolean allowsLabeling(DisplayLinkContext context) { - return true; - } - - @Override - protected String getFlapDisplayLayoutName(DisplayLinkContext context) { - return "Instant"; - } - - @Override - protected FlapDisplaySection createSectionForValue(DisplayLinkContext context, int size) { - return new FlapDisplaySection(size * FlapDisplaySection.MONOSPACE, "instant", false, false); - } - - @Override - protected String getTranslationKey() { - return "stop_watch"; - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/TrainStatusDisplaySource.java b/src/main/java/com/simibubi/create/content/logistics/block/display/source/TrainStatusDisplaySource.java deleted file mode 100644 index cda2d9e84..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/TrainStatusDisplaySource.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.simibubi.create.content.logistics.block.display.source; - -import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; -import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats; -import com.simibubi.create.content.logistics.trains.entity.Train; -import com.simibubi.create.content.logistics.trains.management.edgePoint.station.GlobalStation; -import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationTileEntity; -import com.simibubi.create.content.logistics.trains.management.schedule.Schedule; -import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleRuntime; -import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleRuntime.State; - -import net.minecraft.network.chat.MutableComponent; - -public class TrainStatusDisplaySource extends SingleLineDisplaySource { - - @Override - protected MutableComponent provideLine(DisplayLinkContext context, DisplayTargetStats stats) { - if (!(context.getSourceTE() instanceof StationTileEntity observerTE)) - return EMPTY_LINE; - GlobalStation observer = observerTE.getStation(); - if (observer == null) - return EMPTY_LINE; - Train currentTrain = observer.getPresentTrain(); - if (currentTrain == null) - return EMPTY_LINE; - - ScheduleRuntime runtime = currentTrain.runtime; - Schedule schedule = runtime.getSchedule(); - if (schedule == null) - return EMPTY_LINE; - if (runtime.paused) - return EMPTY_LINE; - if (runtime.state != State.POST_TRANSIT) - return EMPTY_LINE; - if (runtime.currentEntry == schedule.entries.size() - 1 && !schedule.cyclic) - return EMPTY_LINE; - - return runtime.getWaitingStatus(context.level()); - } - - @Override - protected boolean allowsLabeling(DisplayLinkContext context) { - return false; - } - - @Override - protected String getTranslationKey() { - return "train_status"; - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/target/DisplayBoardTarget.java b/src/main/java/com/simibubi/create/content/logistics/block/display/target/DisplayBoardTarget.java deleted file mode 100644 index b12501abe..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/target/DisplayBoardTarget.java +++ /dev/null @@ -1,109 +0,0 @@ -package com.simibubi.create.content.logistics.block.display.target; - -import java.util.List; - -import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; -import com.simibubi.create.content.logistics.block.display.source.DisplaySource; -import com.simibubi.create.content.logistics.block.display.source.SingleLineDisplaySource; -import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayLayout; -import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayTileEntity; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Vec3i; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.phys.AABB; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -public class DisplayBoardTarget extends DisplayTarget { - - @Override - public void acceptText(int line, List text, DisplayLinkContext context) {} - - public void acceptFlapText(int line, List> text, DisplayLinkContext context) { - FlapDisplayTileEntity controller = getController(context); - if (controller == null) - return; - if (!controller.isSpeedRequirementFulfilled()) - return; - - DisplaySource source = context.te().activeSource; - List lines = controller.getLines(); - for (int i = 0; i + line < lines.size(); i++) { - - if (i == 0) - reserve(i + line, controller, context); - if (i > 0 && isReserved(i + line, controller, context)) - break; - - FlapDisplayLayout layout = lines.get(i + line); - - if (i >= text.size()) { - if (source instanceof SingleLineDisplaySource) - break; - controller.applyTextManually(i + line, null); - continue; - } - - source.loadFlapDisplayLayout(context, controller, layout, i); - - for (int sectionIndex = 0; sectionIndex < layout.getSections() - .size(); sectionIndex++) { - List textLine = text.get(i); - if (textLine.size() <= sectionIndex) - break; - layout.getSections() - .get(sectionIndex) - .setText(textLine.get(sectionIndex)); - } - } - - controller.sendData(); - } - - @Override - public boolean isReserved(int line, BlockEntity target, DisplayLinkContext context) { - return super.isReserved(line, target, context) - || target instanceof FlapDisplayTileEntity fdte && fdte.manualLines.length > line && fdte.manualLines[line]; - } - - @Override - public DisplayTargetStats provideStats(DisplayLinkContext context) { - FlapDisplayTileEntity controller = getController(context); - if (controller == null) - return new DisplayTargetStats(1, 1, this); - return new DisplayTargetStats(controller.ySize * 2, controller.getMaxCharCount(), this); - } - - private FlapDisplayTileEntity getController(DisplayLinkContext context) { - BlockEntity teIn = context.getTargetTE(); - if (!(teIn instanceof FlapDisplayTileEntity te)) - return null; - return te.getController(); - } - - @Override - @OnlyIn(Dist.CLIENT) - public AABB getMultiblockBounds(LevelAccessor level, BlockPos pos) { - AABB baseShape = super.getMultiblockBounds(level, pos); - BlockEntity te = level.getBlockEntity(pos); - - if (!(te instanceof FlapDisplayTileEntity fdte)) - return baseShape; - - FlapDisplayTileEntity controller = fdte.getController(); - if (controller == null) - return baseShape; - - Vec3i normal = controller.getDirection() - .getClockWise() - .getNormal(); - return baseShape.move(controller.getBlockPos() - .subtract(pos)) - .expandTowards(normal.getX() * (controller.xSize - 1), 1 - controller.ySize, - normal.getZ() * (controller.xSize - 1)); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/target/DisplayTargetStats.java b/src/main/java/com/simibubi/create/content/logistics/block/display/target/DisplayTargetStats.java deleted file mode 100644 index 4381fc021..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/target/DisplayTargetStats.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.simibubi.create.content.logistics.block.display.target; - -public record DisplayTargetStats(int maxRows, int maxColumns, DisplayTarget type) { - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/flap/package-info.java b/src/main/java/com/simibubi/create/content/logistics/block/flap/package-info.java deleted file mode 100644 index 2ec0735b8..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/flap/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault -package com.simibubi.create.content.logistics.block.flap; - -import javax.annotation.ParametersAreNonnullByDefault; - -import net.minecraft.MethodsReturnNonnullByDefault; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/funnel/AbstractFunnelBlock.java b/src/main/java/com/simibubi/create/content/logistics/block/funnel/AbstractFunnelBlock.java deleted file mode 100644 index b6d26ee7c..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/funnel/AbstractFunnelBlock.java +++ /dev/null @@ -1,144 +0,0 @@ -package com.simibubi.create.content.logistics.block.funnel; - -import java.util.function.Consumer; - -import javax.annotation.Nullable; - -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; -import com.simibubi.create.foundation.block.ITE; -import com.simibubi.create.foundation.block.render.ReducedDestroyEffects; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.inventory.InvManipulationBehaviour; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.util.RandomSource; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition.Builder; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.block.state.properties.BooleanProperty; -import net.minecraft.world.level.pathfinder.PathComputationType; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.client.extensions.common.IClientBlockExtensions; - -public abstract class AbstractFunnelBlock extends Block implements ITE, IWrenchable { - - public static final BooleanProperty POWERED = BlockStateProperties.POWERED; - - protected AbstractFunnelBlock(Properties p_i48377_1_) { - super(p_i48377_1_); - registerDefaultState(defaultBlockState().setValue(POWERED, false)); - } - - @OnlyIn(Dist.CLIENT) - public void initializeClient(Consumer consumer) { - consumer.accept(new ReducedDestroyEffects()); - } - - @Override - public BlockState getStateForPlacement(BlockPlaceContext context) { - return defaultBlockState().setValue(POWERED, context.getLevel() - .hasNeighborSignal(context.getClickedPos())); - } - - @Override - public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) { - return false; - } - - @Override - protected void createBlockStateDefinition(Builder builder) { - super.createBlockStateDefinition(builder.add(POWERED)); - } - - @Override - public void neighborChanged(BlockState state, Level worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, - boolean isMoving) { - if (worldIn.isClientSide) - return; - InvManipulationBehaviour behaviour = TileEntityBehaviour.get(worldIn, pos, InvManipulationBehaviour.TYPE); - if (behaviour != null) - behaviour.onNeighborChanged(fromPos); - if (!worldIn.getBlockTicks() - .willTickThisTick(pos, this)) - worldIn.scheduleTick(pos, this, 0); - } - - @Override - public void tick(BlockState state, ServerLevel worldIn, BlockPos pos, RandomSource r) { - boolean previouslyPowered = state.getValue(POWERED); - if (previouslyPowered != worldIn.hasNeighborSignal(pos)) - worldIn.setBlock(pos, state.cycle(POWERED), 2); - } - - public static ItemStack tryInsert(Level worldIn, BlockPos pos, ItemStack toInsert, boolean simulate) { - FilteringBehaviour filter = TileEntityBehaviour.get(worldIn, pos, FilteringBehaviour.TYPE); - InvManipulationBehaviour inserter = TileEntityBehaviour.get(worldIn, pos, InvManipulationBehaviour.TYPE); - if (inserter == null) - return toInsert; - if (filter != null && !filter.test(toInsert)) - return toInsert; - if (simulate) - inserter.simulate(); - ItemStack insert = inserter.insert(toInsert); - - if (!simulate && insert.getCount() != toInsert.getCount()) { - BlockEntity tileEntity = worldIn.getBlockEntity(pos); - if (tileEntity instanceof FunnelTileEntity) { - FunnelTileEntity funnelTileEntity = (FunnelTileEntity) tileEntity; - funnelTileEntity.onTransfer(toInsert); - if (funnelTileEntity.hasFlap()) - funnelTileEntity.flap(true); - } - } - return insert; - } - - @Override - public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { - Block block = world.getBlockState(pos.relative(getFunnelFacing(state).getOpposite())) - .getBlock(); - return !(block instanceof AbstractFunnelBlock); - } - - @Nullable - public static boolean isFunnel(BlockState state) { - return state.getBlock() instanceof AbstractFunnelBlock; - } - - @Nullable - public static Direction getFunnelFacing(BlockState state) { - if (!(state.getBlock() instanceof AbstractFunnelBlock)) - return null; - return ((AbstractFunnelBlock) state.getBlock()).getFacing(state); - } - - protected abstract Direction getFacing(BlockState state); - - @Override - public void onRemove(BlockState state, Level world, BlockPos pos, BlockState newState, boolean isMoving) { - ITE.onRemove(state, world, pos, newState); - } - - @Override - public Class getTileEntityClass() { - return FunnelTileEntity.class; - } - - public BlockEntityType getTileEntityType() { - return AllTileEntities.FUNNEL.get(); - }; - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/funnel/BeltFunnelGenerator.java b/src/main/java/com/simibubi/create/content/logistics/block/funnel/BeltFunnelGenerator.java deleted file mode 100644 index 8e0ccaaea..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/funnel/BeltFunnelGenerator.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.simibubi.create.content.logistics.block.funnel; - -import com.simibubi.create.foundation.data.SpecialBlockStateGen; -import com.tterrag.registrate.providers.DataGenContext; -import com.tterrag.registrate.providers.RegistrateBlockstateProvider; - -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraftforge.client.model.generators.ModelFile; - -public class BeltFunnelGenerator extends SpecialBlockStateGen { - - private String type; - private ResourceLocation materialBlockTexture; - - public BeltFunnelGenerator(String type, ResourceLocation materialBlockTexture) { - this.type = type; - this.materialBlockTexture = materialBlockTexture; - } - - @Override - protected int getXRotation(BlockState state) { - return 0; - } - - @Override - protected int getYRotation(BlockState state) { - return horizontalAngle(state.getValue(BeltFunnelBlock.HORIZONTAL_FACING)) + 180; - } - - @Override - public ModelFile getModel(DataGenContext ctx, RegistrateBlockstateProvider prov, - BlockState state) { - String shapeName = state.getValue(BeltFunnelBlock.SHAPE) - .getSerializedName(); - boolean powered = state.getOptionalValue(BlockStateProperties.POWERED).orElse(false); - String poweredSuffix = powered ? "_powered" : ""; - String name = ctx.getName() + "_" + shapeName + poweredSuffix; - - return prov.models() - .withExistingParent(name, prov.modLoc("block/belt_funnel/block_" + shapeName)) - .texture("particle", materialBlockTexture) - .texture("2", prov.modLoc("block/" + type + "_funnel_neutral")) - .texture("2_1", prov.modLoc("block/" + type + "_funnel_push")) - .texture("2_2", prov.modLoc("block/" + type + "_funnel_pull")) - .texture("3", prov.modLoc("block/" + type + "_funnel_back")) - .texture("5", prov.modLoc("block/" + type + "_funnel_tall" + poweredSuffix)) - .texture("6", prov.modLoc("block/" + type + "_funnel" + poweredSuffix)) - .texture("7", prov.modLoc("block/" + type + "_funnel_plating")); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelGenerator.java b/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelGenerator.java deleted file mode 100644 index 1d5f390ce..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelGenerator.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.simibubi.create.content.logistics.block.funnel; - -import com.simibubi.create.Create; -import com.simibubi.create.foundation.data.SpecialBlockStateGen; -import com.tterrag.registrate.providers.DataGenContext; -import com.tterrag.registrate.providers.RegistrateBlockstateProvider; -import com.tterrag.registrate.providers.RegistrateItemModelProvider; -import com.tterrag.registrate.util.nullness.NonNullBiConsumer; - -import net.minecraft.core.Direction; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.Item; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.client.model.generators.BlockModelBuilder; -import net.minecraftforge.client.model.generators.ModelFile; - -public class FunnelGenerator extends SpecialBlockStateGen { - - private String type; - private ResourceLocation particleTexture; - private boolean hasFilter; - - public FunnelGenerator(String type, boolean hasFilter) { - this.type = type; - this.hasFilter = hasFilter; - this.particleTexture = Create.asResource("block/" + type + "_casing"); - } - - @Override - protected int getXRotation(BlockState state) { - return state.getValue(FunnelBlock.FACING) == Direction.DOWN ? 180 : 0; - } - - @Override - protected int getYRotation(BlockState state) { - return horizontalAngle(state.getValue(FunnelBlock.FACING)) + 180; - } - - @Override - public ModelFile getModel(DataGenContext c, RegistrateBlockstateProvider p, - BlockState s) { - String powered = s.getValue(FunnelBlock.POWERED) ? "_powered" : ""; - String closed = s.getValue(FunnelBlock.POWERED) ? "_closed" : "_open"; - String extracting = s.getValue(FunnelBlock.EXTRACTING) ? "_push" : "_pull"; - Direction facing = s.getValue(FunnelBlock.FACING); - boolean horizontal = facing.getAxis() - .isHorizontal(); - String parent = horizontal ? "horizontal" : hasFilter ? "vertical" : "vertical_filterless"; - - BlockModelBuilder model = p.models() - .withExistingParent("block/" + type + "_funnel_" + parent + extracting + powered, - p.modLoc("block/funnel/block_" + parent)) - .texture("particle", particleTexture) - .texture("7", p.modLoc("block/" + type + "_funnel_plating")) - .texture("5", p.modLoc("block/" + type + "_funnel_tall" + powered)) - .texture("2_2", p.modLoc("block/" + type + "_funnel" + extracting)) - .texture("3", p.modLoc("block/" + type + "_funnel_back")); - - if (horizontal) - return model.texture("6", p.modLoc("block/" + type + "_funnel" + powered)); - - return model.texture("8", particleTexture) - .texture("9", p.modLoc("block/" + type + "_funnel_slope")) - .texture("10", p.modLoc("block/funnel" + closed)); - } - - public static NonNullBiConsumer, RegistrateItemModelProvider> itemModel( - String type) { - ResourceLocation particleTexture = Create.asResource("block/" + type + "_casing"); - return (c, p) -> { - p.withExistingParent("item/" + type + "_funnel", p.modLoc("block/funnel/item")) - .texture("particle", particleTexture) - .texture("7", p.modLoc("block/" + type + "_funnel_plating")) - .texture("2", p.modLoc("block/" + type + "_funnel_neutral")) - .texture("6", p.modLoc("block/" + type + "_funnel")) - .texture("5", p.modLoc("block/" + type + "_funnel_tall")) - .texture("3", p.modLoc("block/" + type + "_funnel_back")); - }; - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelInstance.java b/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelInstance.java deleted file mode 100644 index 24e44245e..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelInstance.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.simibubi.create.content.logistics.block.funnel; - -import java.util.ArrayList; - -import com.jozufozu.flywheel.api.InstanceData; -import com.jozufozu.flywheel.api.Instancer; -import com.jozufozu.flywheel.api.MaterialManager; -import com.jozufozu.flywheel.api.instance.DynamicInstance; -import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance; -import com.jozufozu.flywheel.core.PartialModel; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.logistics.block.flap.FlapData; -import com.simibubi.create.foundation.render.AllMaterialSpecs; -import com.simibubi.create.foundation.utility.AnimationTickHolder; - -import net.minecraft.core.Direction; -import net.minecraft.world.level.LightLayer; - -public class FunnelInstance extends BlockEntityInstance implements DynamicInstance { - - private final ArrayList flaps; - - public FunnelInstance(MaterialManager modelManager, FunnelTileEntity tile) { - super(modelManager, tile); - - flaps = new ArrayList<>(4); - - if (!tile.hasFlap()) return; - - PartialModel flapPartial = (blockState.getBlock() instanceof FunnelBlock ? AllBlockPartials.FUNNEL_FLAP - : AllBlockPartials.BELT_FUNNEL_FLAP); - Instancer model = modelManager.defaultSolid() - .material(AllMaterialSpecs.FLAPS) - .getModel(flapPartial, blockState); - - int blockLight = world.getBrightness(LightLayer.BLOCK, pos); - int skyLight = world.getBrightness(LightLayer.SKY, pos); - - Direction direction = FunnelBlock.getFunnelFacing(blockState); - - float flapness = tile.flap.getValue(AnimationTickHolder.getPartialTicks()); - float horizontalAngle = direction.getOpposite().toYRot(); - - for (int segment = 0; segment <= 3; segment++) { - float intensity = segment == 3 ? 1.5f : segment + 1; - float segmentOffset = -3 / 16f * segment; - - FlapData key = model.createInstance(); - - key.setPosition(getInstancePosition()) - .setSegmentOffset(segmentOffset, 0, -tile.getFlapOffset()) - .setBlockLight(blockLight) - .setSkyLight(skyLight) - .setHorizontalAngle(horizontalAngle) - .setFlapness(flapness) - .setFlapScale(-1) - .setPivotVoxelSpace(0, 10, 9.5f) - .setIntensity(intensity); - - flaps.add(key); - } - } - - @Override - public void beginFrame() { - if (flaps == null) return; - - float flapness = blockEntity.flap.getValue(AnimationTickHolder.getPartialTicks()); - - for (FlapData flap : flaps) { - flap.setFlapness(flapness); - } - } - - @Override - public void updateLight() { - if (flaps != null) - relight(pos, flaps.stream()); - } - - @Override - public void remove() { - if (flaps == null) return; - - flaps.forEach(InstanceData::delete); - } -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelRenderer.java b/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelRenderer.java deleted file mode 100644 index 1e62bf553..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelRenderer.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.simibubi.create.content.logistics.block.funnel; - -import com.jozufozu.flywheel.backend.Backend; -import com.jozufozu.flywheel.core.PartialModel; -import com.jozufozu.flywheel.util.transform.TransformStack; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.tileEntity.renderer.SmartTileEntityRenderer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.util.Mth; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; - -public class FunnelRenderer extends SmartTileEntityRenderer { - - public FunnelRenderer(BlockEntityRendererProvider.Context context) { - super(context); - } - - @Override - protected void renderSafe(FunnelTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - super.renderSafe(te, partialTicks, ms, buffer, light, overlay); - - if (!te.hasFlap() || Backend.canUseInstancing(te.getLevel())) - return; - - BlockState blockState = te.getBlockState(); - VertexConsumer vb = buffer.getBuffer(RenderType.solid()); - PartialModel partialModel = (blockState.getBlock() instanceof FunnelBlock ? AllBlockPartials.FUNNEL_FLAP - : AllBlockPartials.BELT_FUNNEL_FLAP); - SuperByteBuffer flapBuffer = CachedBufferer.partial(partialModel, blockState); - Vec3 pivot = VecHelper.voxelSpace(0, 10, 9.5f); - TransformStack msr = TransformStack.cast(ms); - - float horizontalAngle = AngleHelper.horizontalAngle(FunnelBlock.getFunnelFacing(blockState) - .getOpposite()); - float f = te.flap.getValue(partialTicks); - - ms.pushPose(); - msr.centre() - .rotateY(horizontalAngle) - .unCentre(); - ms.translate(0, 0, -te.getFlapOffset()); - - for (int segment = 0; segment <= 3; segment++) { - ms.pushPose(); - - float intensity = segment == 3 ? 1.5f : segment + 1; - float abs = Math.abs(f); - float flapAngle = Mth.sin((float) ((1 - abs) * Math.PI * intensity)) * 30 * -f; - if (f > 0) - flapAngle *= .5f; - - msr.translate(pivot) - .rotateX(flapAngle) - .translateBack(pivot); - - flapBuffer.light(light) - .renderInto(ms, vb); - - ms.popPose(); - ms.translate(-3 / 16f, 0, 0); - } - ms.popPose(); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelTileEntity.java deleted file mode 100644 index b48342493..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelTileEntity.java +++ /dev/null @@ -1,346 +0,0 @@ -package com.simibubi.create.content.logistics.block.funnel; - -import java.lang.ref.WeakReference; -import java.util.List; - -import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; -import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.content.contraptions.goggles.IHaveHoveringInformation; -import com.simibubi.create.content.contraptions.relays.belt.BeltHelper; -import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity; -import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack; -import com.simibubi.create.content.logistics.block.funnel.BeltFunnelBlock.Shape; -import com.simibubi.create.content.logistics.packet.FunnelFlapPacket; -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.networking.AllPackets; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.inventory.InvManipulationBehaviour; -import com.simibubi.create.foundation.utility.BlockFace; -import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.fml.DistExecutor; - -public class FunnelTileEntity extends SmartTileEntity implements IHaveHoveringInformation { - - private FilteringBehaviour filtering; - private InvManipulationBehaviour invManipulation; - private int extractionCooldown; - - private WeakReference lastObserved; // In-world Extractors only - - LerpedFloat flap; - - static enum Mode { - INVALID, PAUSED, COLLECT, PUSHING_TO_BELT, TAKING_FROM_BELT, EXTRACT - } - - public FunnelTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - extractionCooldown = 0; - flap = createChasingFlap(); - } - - public Mode determineCurrentMode() { - BlockState state = getBlockState(); - if (!FunnelBlock.isFunnel(state)) - return Mode.INVALID; - if (state.getOptionalValue(BlockStateProperties.POWERED) - .orElse(false)) - return Mode.PAUSED; - if (state.getBlock() instanceof BeltFunnelBlock) { - Shape shape = state.getValue(BeltFunnelBlock.SHAPE); - if (shape == Shape.PULLING) - return Mode.TAKING_FROM_BELT; - if (shape == Shape.PUSHING) - return Mode.PUSHING_TO_BELT; - - BeltTileEntity belt = BeltHelper.getSegmentTE(level, worldPosition.below()); - if (belt != null) - return belt.getMovementFacing() == state.getValue(BeltFunnelBlock.HORIZONTAL_FACING) ? Mode.PUSHING_TO_BELT - : Mode.TAKING_FROM_BELT; - return Mode.INVALID; - } - if (state.getBlock() instanceof FunnelBlock) - return state.getValue(FunnelBlock.EXTRACTING) ? Mode.EXTRACT : Mode.COLLECT; - - return Mode.INVALID; - } - - @Override - public void tick() { - super.tick(); - flap.tickChaser(); - Mode mode = determineCurrentMode(); - if (level.isClientSide) - return; - - // Redstone resets the extraction cooldown - if (mode == Mode.PAUSED) - extractionCooldown = 0; - if (mode == Mode.TAKING_FROM_BELT) - return; - - if (extractionCooldown > 0) { - extractionCooldown--; - return; - } - - if (mode == Mode.PUSHING_TO_BELT) - activateExtractingBeltFunnel(); - if (mode == Mode.EXTRACT) - activateExtractor(); - } - - private void activateExtractor() { - BlockState blockState = getBlockState(); - Direction facing = AbstractFunnelBlock.getFunnelFacing(blockState); - - if (facing == null) - return; - - boolean trackingEntityPresent = true; - AABB area = getEntityOverflowScanningArea(); - - // Check if last item is still blocking the extractor - if (lastObserved == null) { - trackingEntityPresent = false; - } else { - ItemEntity lastEntity = lastObserved.get(); - if (lastEntity == null || !lastEntity.isAlive() || !lastEntity.getBoundingBox() - .intersects(area)) { - trackingEntityPresent = false; - lastObserved = null; - } - } - - if (trackingEntityPresent) - return; - - // Find other entities blocking the extract (only if necessary) - int amountToExtract = getAmountToExtract(); - ItemStack stack = invManipulation.simulate() - .extract(amountToExtract); - if (stack.isEmpty()) - return; - for (ItemEntity itemEntity : level.getEntitiesOfClass(ItemEntity.class, area)) { - lastObserved = new WeakReference<>(itemEntity); - return; - } - - // Extract - stack = invManipulation.extract(amountToExtract); - if (stack.isEmpty()) - return; - - flap(false); - onTransfer(stack); - - Vec3 outputPos = VecHelper.getCenterOf(worldPosition); - boolean vertical = facing.getAxis() - .isVertical(); - boolean up = facing == Direction.UP; - - outputPos = outputPos.add(Vec3.atLowerCornerOf(facing.getNormal()) - .scale(vertical ? up ? .15f : .5f : .25f)); - if (!vertical) - outputPos = outputPos.subtract(0, .45f, 0); - - Vec3 motion = Vec3.ZERO; - if (up) - motion = new Vec3(0, 4 / 16f, 0); - - ItemEntity item = new ItemEntity(level, outputPos.x, outputPos.y, outputPos.z, stack.copy()); - item.setDefaultPickUpDelay(); - item.setDeltaMovement(motion); - level.addFreshEntity(item); - lastObserved = new WeakReference<>(item); - - startCooldown(); - } - - static final AABB coreBB = - new AABB(VecHelper.CENTER_OF_ORIGIN, VecHelper.CENTER_OF_ORIGIN).inflate(.75f); - - private AABB getEntityOverflowScanningArea() { - Direction facing = AbstractFunnelBlock.getFunnelFacing(getBlockState()); - AABB bb = coreBB.move(worldPosition); - if (facing == null || facing == Direction.UP) - return bb; - return bb.expandTowards(0, -1, 0); - } - - private void activateExtractingBeltFunnel() { - BlockState blockState = getBlockState(); - Direction facing = blockState.getValue(BeltFunnelBlock.HORIZONTAL_FACING); - DirectBeltInputBehaviour inputBehaviour = - TileEntityBehaviour.get(level, worldPosition.below(), DirectBeltInputBehaviour.TYPE); - - if (inputBehaviour == null) - return; - if (!inputBehaviour.canInsertFromSide(facing)) - return; - - int amountToExtract = getAmountToExtract(); - ItemStack stack = invManipulation.extract(amountToExtract, s -> inputBehaviour.handleInsertion(s, facing, true) - .isEmpty()); - if (stack.isEmpty()) - return; - flap(false); - onTransfer(stack); - inputBehaviour.handleInsertion(stack, facing, false); - startCooldown(); - } - - public int getAmountToExtract() { - if (!supportsAmountOnFilter()) - return -1; - int amountToExtract = invManipulation.getAmountFromFilter(); - if (!filtering.isActive()) - amountToExtract = 1; - return amountToExtract; - } - - private int startCooldown() { - return extractionCooldown = AllConfigs.SERVER.logistics.defaultExtractionTimer.get(); - } - - @Override - public void addBehaviours(List behaviours) { - invManipulation = - new InvManipulationBehaviour(this, (w, p, s) -> new BlockFace(p, AbstractFunnelBlock.getFunnelFacing(s) - .getOpposite())); - behaviours.add(invManipulation); - - filtering = new FilteringBehaviour(this, new FunnelFilterSlotPositioning()); - filtering.showCountWhen(this::supportsAmountOnFilter); - filtering.onlyActiveWhen(this::supportsFiltering); - behaviours.add(filtering); - - behaviours.add(new DirectBeltInputBehaviour(this).onlyInsertWhen(this::supportsDirectBeltInput) - .setInsertionHandler(this::handleDirectBeltInput)); - registerAwardables(behaviours, AllAdvancements.FUNNEL); - } - - private boolean supportsAmountOnFilter() { - BlockState blockState = getBlockState(); - boolean beltFunnelsupportsAmount = false; - if (blockState.getBlock() instanceof BeltFunnelBlock) { - Shape shape = blockState.getValue(BeltFunnelBlock.SHAPE); - if (shape == Shape.PUSHING) - beltFunnelsupportsAmount = true; - else - beltFunnelsupportsAmount = BeltHelper.getSegmentTE(level, worldPosition.below()) != null; - } - boolean extractor = blockState.getBlock() instanceof FunnelBlock && blockState.getValue(FunnelBlock.EXTRACTING); - return beltFunnelsupportsAmount || extractor; - } - - private boolean supportsDirectBeltInput(Direction side) { - BlockState blockState = getBlockState(); - if (blockState == null) - return false; - if (!(blockState.getBlock() instanceof FunnelBlock)) - return false; - if (blockState.getValue(FunnelBlock.EXTRACTING)) - return false; - return FunnelBlock.getFunnelFacing(blockState) == Direction.UP; - } - - private boolean supportsFiltering() { - BlockState blockState = getBlockState(); - return AllBlocks.BRASS_BELT_FUNNEL.has(blockState) || AllBlocks.BRASS_FUNNEL.has(blockState); - } - - private ItemStack handleDirectBeltInput(TransportedItemStack stack, Direction side, boolean simulate) { - ItemStack inserted = stack.stack; - if (!filtering.test(inserted)) - return inserted; - if (determineCurrentMode() == Mode.PAUSED) - return inserted; - if (simulate) - invManipulation.simulate(); - if (!simulate) - onTransfer(inserted); - return invManipulation.insert(inserted); - } - - public void flap(boolean inward) { - if (!level.isClientSide) { - AllPackets.channel.send(packetTarget(), new FunnelFlapPacket(this, inward)); - } else { - flap.setValue(inward ? 1 : -1); - AllSoundEvents.FUNNEL_FLAP.playAt(level, worldPosition, 1, 1, true); - } - } - - public boolean hasFlap() { - BlockState blockState = getBlockState(); - if (!AbstractFunnelBlock.getFunnelFacing(blockState) - .getAxis() - .isHorizontal()) - return false; - return true; - } - - public float getFlapOffset() { - BlockState blockState = getBlockState(); - if (!(blockState.getBlock() instanceof BeltFunnelBlock)) - return -1 / 16f; - switch (blockState.getValue(BeltFunnelBlock.SHAPE)) { - default: - case RETRACTED: - return 0; - case EXTENDED: - return 8 / 16f; - case PULLING: - case PUSHING: - return -2 / 16f; - } - } - - @Override - protected void write(CompoundTag compound, boolean clientPacket) { - super.write(compound, clientPacket); - compound.putInt("TransferCooldown", extractionCooldown); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - super.read(compound, clientPacket); - extractionCooldown = compound.getInt("TransferCooldown"); - - if (clientPacket) - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(this)); - } - - public void onTransfer(ItemStack stack) { - AllBlocks.CONTENT_OBSERVER.get() - .onFunnelTransfer(level, worldPosition, stack); - award(AllAdvancements.FUNNEL); - } - - private LerpedFloat createChasingFlap() { - return LerpedFloat.linear() - .startWithValue(.25f) - .chase(0, .05f, Chaser.EXP); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/inventories/CrateTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/inventories/CrateTileEntity.java deleted file mode 100644 index 44ce5ca60..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/inventories/CrateTileEntity.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.simibubi.create.content.logistics.block.inventories; - -import java.util.List; - -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; - -public abstract class CrateTileEntity extends SmartTileEntity { - - public CrateTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - @Override - public void addBehaviours(List behaviours) {} - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/inventories/CreativeCrateBlock.java b/src/main/java/com/simibubi/create/content/logistics/block/inventories/CreativeCrateBlock.java deleted file mode 100644 index df3ca8171..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/inventories/CreativeCrateBlock.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.simibubi.create.content.logistics.block.inventories; - -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.foundation.block.ITE; - -import net.minecraft.world.level.block.entity.BlockEntityType; - -public class CreativeCrateBlock extends CrateBlock implements ITE { - - public CreativeCrateBlock(Properties p_i48415_1_) { - super(p_i48415_1_); - } - - @Override - public Class getTileEntityClass() { - return CreativeCrateTileEntity.class; - } - - @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.CREATIVE_CRATE.get(); - } -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/inventories/CreativeCrateTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/inventories/CreativeCrateTileEntity.java deleted file mode 100644 index d2c2c8e47..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/inventories/CreativeCrateTileEntity.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.simibubi.create.content.logistics.block.inventories; - -import java.util.List; - -import com.jozufozu.flywheel.util.transform.TransformStack; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform; -import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.items.CapabilityItemHandler; -import net.minecraftforge.items.IItemHandler; - -public class CreativeCrateTileEntity extends CrateTileEntity { - - public CreativeCrateTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - inv = new BottomlessItemHandler(filtering::getFilter); - itemHandler = LazyOptional.of(() -> inv); - } - - FilteringBehaviour filtering; - LazyOptional itemHandler; - private BottomlessItemHandler inv; - - @Override - public void addBehaviours(List behaviours) { - behaviours.add(filtering = createFilter()); - } - - @Override - public void invalidate() { - super.invalidate(); - if (itemHandler != null) - itemHandler.invalidate(); - } - - @Override - public LazyOptional getCapability(Capability cap, Direction side) { - if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) - return itemHandler.cast(); - return super.getCapability(cap, side); - } - - public FilteringBehaviour createFilter() { - return new FilteringBehaviour(this, new ValueBoxTransform() { - - @Override - protected void rotate(BlockState state, PoseStack ms) { - TransformStack.cast(ms) - .rotateX(90); - } - - @Override - protected Vec3 getLocalOffset(BlockState state) { - return new Vec3(0.5, 13 / 16d, 0.5); - } - - protected float getScale() { - return super.getScale() * 1.5f; - }; - - }); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmBlock.java b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmBlock.java deleted file mode 100644 index 099575a5a..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmBlock.java +++ /dev/null @@ -1,103 +0,0 @@ -package com.simibubi.create.content.logistics.block.mechanicalArm; - -import org.apache.commons.lang3.mutable.MutableBoolean; - -import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.KineticBlock; -import com.simibubi.create.content.contraptions.relays.elementary.ICogWheel; -import com.simibubi.create.content.logistics.block.mechanicalArm.ArmTileEntity.Phase; -import com.simibubi.create.foundation.block.ITE; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -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.item.context.BlockPlaceContext; -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.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition.Builder; -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 ArmBlock extends KineticBlock implements ITE, ICogWheel { - - public static final BooleanProperty CEILING = BooleanProperty.create("ceiling"); - - public ArmBlock(Properties properties) { - super(properties); - registerDefaultState(defaultBlockState().setValue(CEILING, false)); - } - - @Override - protected void createBlockStateDefinition(Builder p_206840_1_) { - super.createBlockStateDefinition(p_206840_1_.add(CEILING)); - } - - @Override - public BlockState getStateForPlacement(BlockPlaceContext ctx) { - return defaultBlockState().setValue(CEILING, ctx.getClickedFace() == Direction.DOWN); - } - - @Override - public VoxelShape getShape(BlockState state, BlockGetter p_220053_2_, BlockPos p_220053_3_, - CollisionContext p_220053_4_) { - return state.getValue(CEILING) ? AllShapes.MECHANICAL_ARM_CEILING : AllShapes.MECHANICAL_ARM; - } - - @Override - public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean isMoving) { - super.onPlace(state, world, pos, oldState, isMoving); - withTileEntityDo(world, pos, ArmTileEntity::redstoneUpdate); - } - - @Override - public void neighborChanged(BlockState state, Level world, BlockPos pos, Block p_220069_4_, - BlockPos p_220069_5_, boolean p_220069_6_) { - withTileEntityDo(world, pos, ArmTileEntity::redstoneUpdate); - } - - @Override - public Axis getRotationAxis(BlockState state) { - return Axis.Y; - } - - @Override - public Class getTileEntityClass() { - return ArmTileEntity.class; - } - - @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.MECHANICAL_ARM.get(); - } - - @Override - public InteractionResult use(BlockState p_225533_1_, Level world, BlockPos pos, Player player, - InteractionHand p_225533_5_, BlockHitResult p_225533_6_) { - MutableBoolean success = new MutableBoolean(false); - withTileEntityDo(world, pos, te -> { - if (te.heldItem.isEmpty()) - return; - success.setTrue(); - if (world.isClientSide) - return; - player.getInventory().placeItemBackInInventory(te.heldItem); - te.heldItem = ItemStack.EMPTY; - te.phase = Phase.SEARCH_INPUTS; - te.setChanged(); - te.sendData(); - }); - - return success.booleanValue() ? InteractionResult.SUCCESS : InteractionResult.PASS; - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInstance.java b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInstance.java deleted file mode 100644 index ab27c8f6a..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInstance.java +++ /dev/null @@ -1,189 +0,0 @@ -package com.simibubi.create.content.logistics.block.mechanicalArm; - -import java.util.ArrayList; - -import com.google.common.collect.Lists; -import com.jozufozu.flywheel.api.InstanceData; -import com.jozufozu.flywheel.api.Instancer; -import com.jozufozu.flywheel.api.Material; -import com.jozufozu.flywheel.api.MaterialManager; -import com.jozufozu.flywheel.api.instance.DynamicInstance; -import com.jozufozu.flywheel.core.materials.model.ModelData; -import com.jozufozu.flywheel.util.transform.TransformStack; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.SingleRotatingInstance; -import com.simibubi.create.content.contraptions.base.flwdata.RotatingData; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.Color; -import com.simibubi.create.foundation.utility.Iterate; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.entity.ItemRenderer; -import net.minecraft.util.Mth; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.ItemStack; - -public class ArmInstance extends SingleRotatingInstance implements DynamicInstance { - - final ModelData base; - final ModelData lowerBody; - final ModelData upperBody; - final ModelData head; - final ModelData claw; - private final ArrayList clawGrips; - - private final ArrayList models; - private final ArmTileEntity arm; - private final Boolean ceiling; - - private boolean firstRender = true; - - private float baseAngle = Float.NaN; - private float lowerArmAngle = Float.NaN; - private float upperArmAngle = Float.NaN; - private float headAngle = Float.NaN; - - public ArmInstance(MaterialManager modelManager, ArmTileEntity tile) { - super(modelManager, tile); - - Material mat = getTransformMaterial(); - - base = mat.getModel(AllBlockPartials.ARM_BASE, blockState) - .createInstance(); - lowerBody = mat.getModel(AllBlockPartials.ARM_LOWER_BODY, blockState) - .createInstance(); - upperBody = mat.getModel(AllBlockPartials.ARM_UPPER_BODY, blockState) - .createInstance(); - head = mat.getModel(AllBlockPartials.ARM_HEAD, blockState) - .createInstance(); - claw = mat.getModel(AllBlockPartials.ARM_CLAW_BASE, blockState) - .createInstance(); - - Instancer clawHalfModel = mat.getModel(AllBlockPartials.ARM_CLAW_GRIP, blockState); - ModelData clawGrip1 = clawHalfModel.createInstance(); - ModelData clawGrip2 = clawHalfModel.createInstance(); - - clawGrips = Lists.newArrayList(clawGrip1, clawGrip2); - models = Lists.newArrayList(base, lowerBody, upperBody, head, claw, clawGrip1, clawGrip2); - arm = tile; - ceiling = blockState.getValue(ArmBlock.CEILING); - - animateArm(false); - } - - @Override - public void beginFrame() { - if (arm.phase == ArmTileEntity.Phase.DANCING && blockEntity.getSpeed() != 0) { - animateArm(true); - firstRender = true; - return; - } - - float pt = AnimationTickHolder.getPartialTicks(); - - float baseAngleNow = arm.baseAngle.getValue(pt); - float lowerArmAngleNow = arm.lowerArmAngle.getValue(pt); - float upperArmAngleNow = arm.upperArmAngle.getValue(pt); - float headAngleNow = arm.headAngle.getValue(pt); - - boolean settled = Mth.equal(baseAngle, baseAngleNow) && Mth.equal(lowerArmAngle, lowerArmAngleNow) - && Mth.equal(upperArmAngle, upperArmAngleNow) && Mth.equal(headAngle, headAngleNow); - - this.baseAngle = baseAngleNow; - this.lowerArmAngle = lowerArmAngleNow; - this.upperArmAngle = upperArmAngleNow; - this.headAngle = headAngleNow; - - if (!settled || firstRender) - animateArm(false); - - if (firstRender) - firstRender = false; - } - - private void animateArm(boolean rave) { - float baseAngle; - float lowerArmAngle; - float upperArmAngle; - float headAngle; - int color; - - if (rave) { - float renderTick = AnimationTickHolder.getRenderTime(this.arm.getLevel()) + (blockEntity.hashCode() % 64); - baseAngle = (renderTick * 10) % 360; - lowerArmAngle = Mth.lerp((Mth.sin(renderTick / 4) + 1) / 2, -45, 15); - upperArmAngle = Mth.lerp((Mth.sin(renderTick / 8) + 1) / 4, -45, 95); - headAngle = -lowerArmAngle; - color = Color.rainbowColor(AnimationTickHolder.getTicks() * 100) - .getRGB(); - } else { - baseAngle = this.baseAngle; - lowerArmAngle = this.lowerArmAngle - 135; - upperArmAngle = this.upperArmAngle - 90; - headAngle = this.headAngle; - color = 0xFFFFFF; - } - - PoseStack msLocal = new PoseStack(); - TransformStack msr = TransformStack.cast(msLocal); - msr.translate(getInstancePosition()); - msr.centre(); - - if (ceiling) - msr.rotateX(180); - - ArmRenderer.transformBase(msr, baseAngle); - base.setTransform(msLocal); - - ArmRenderer.transformLowerArm(msr, lowerArmAngle); - lowerBody.setTransform(msLocal) - .setColor(color); - - ArmRenderer.transformUpperArm(msr, upperArmAngle); - upperBody.setTransform(msLocal) - .setColor(color); - - ArmRenderer.transformHead(msr, headAngle); - head.setTransform(msLocal); - - ArmRenderer.transformClaw(msr); - claw.setTransform(msLocal); - - ItemStack item = this.arm.heldItem; - ItemRenderer itemRenderer = Minecraft.getInstance() - .getItemRenderer(); - boolean hasItem = !item.isEmpty(); - boolean isBlockItem = hasItem && (item.getItem() instanceof BlockItem) - && itemRenderer.getModel(item, Minecraft.getInstance().level, null, 0) - .isGui3d(); - - for (int index : Iterate.zeroAndOne) { - msLocal.pushPose(); - int flip = index * 2 - 1; - ArmRenderer.transformClawHalf(msr, hasItem, isBlockItem, flip); - clawGrips.get(index) - .setTransform(msLocal); - msLocal.popPose(); - } - } - - @Override - public void updateLight() { - super.updateLight(); - - relight(pos, models.stream()); - } - - @Override - protected Instancer getModel() { - return getRotatingMaterial().getModel(AllBlockPartials.ARM_COG, blockEntity.getBlockState()); - } - - @Override - public void remove() { - super.remove(); - models.forEach(InstanceData::delete); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmPlacementPacket.java b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmPlacementPacket.java deleted file mode 100644 index f760e3aba..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmPlacementPacket.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.simibubi.create.content.logistics.block.mechanicalArm; - -import java.util.Collection; -import java.util.function.Supplier; - -import com.simibubi.create.foundation.networking.SimplePacketBase; - -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.Tag; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.fml.DistExecutor; -import net.minecraftforge.network.NetworkEvent.Context; - -public class ArmPlacementPacket extends SimplePacketBase { - - private Collection points; - private ListTag receivedTag; - private BlockPos pos; - - public ArmPlacementPacket(Collection points, BlockPos pos) { - this.points = points; - this.pos = pos; - } - - public ArmPlacementPacket(FriendlyByteBuf buffer) { - CompoundTag nbt = buffer.readNbt(); - receivedTag = nbt.getList("Points", Tag.TAG_COMPOUND); - pos = buffer.readBlockPos(); - } - - @Override - public void write(FriendlyByteBuf buffer) { - CompoundTag nbt = new CompoundTag(); - ListTag pointsNBT = new ListTag(); - points.stream() - .map(aip -> aip.serialize(pos)) - .forEach(pointsNBT::add); - nbt.put("Points", pointsNBT); - buffer.writeNbt(nbt); - buffer.writeBlockPos(pos); - } - - @Override - public void handle(Supplier context) { - context.get() - .enqueueWork(() -> { - ServerPlayer player = context.get() - .getSender(); - if (player == null) - return; - Level world = player.level; - if (world == null || !world.isLoaded(pos)) - return; - BlockEntity tileEntity = world.getBlockEntity(pos); - if (!(tileEntity instanceof ArmTileEntity)) - return; - - ArmTileEntity arm = (ArmTileEntity) tileEntity; - arm.interactionPointTag = receivedTag; - }); - context.get() - .setPacketHandled(true); - - } - - public static class ClientBoundRequest extends SimplePacketBase { - - BlockPos pos; - - public ClientBoundRequest(BlockPos pos) { - this.pos = pos; - } - - public ClientBoundRequest(FriendlyByteBuf buffer) { - this.pos = buffer.readBlockPos(); - } - - @Override - public void write(FriendlyByteBuf buffer) { - buffer.writeBlockPos(pos); - } - - @Override - public void handle(Supplier context) { - context.get() - .enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, - () -> () -> ArmInteractionPointHandler.flushSettings(pos))); - context.get() - .setPacketHandled(true); - } - - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmRenderer.java b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmRenderer.java deleted file mode 100644 index ef387b3c7..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmRenderer.java +++ /dev/null @@ -1,209 +0,0 @@ -package com.simibubi.create.content.logistics.block.mechanicalArm; - -import com.jozufozu.flywheel.backend.Backend; -import com.jozufozu.flywheel.util.transform.TransformStack; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.content.logistics.block.mechanicalArm.ArmTileEntity.Phase; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.Color; -import com.simibubi.create.foundation.utility.Iterate; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.block.model.ItemTransforms.TransformType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.client.renderer.entity.ItemRenderer; -import net.minecraft.util.Mth; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.state.BlockState; - -public class ArmRenderer extends KineticTileEntityRenderer { - - public ArmRenderer(BlockEntityRendererProvider.Context context) { - super(context); - } - - @Override - protected void renderSafe(KineticTileEntity te, float pt, PoseStack ms, MultiBufferSource buffer, int light, - int overlay) { - super.renderSafe(te, pt, ms, buffer, light, overlay); - - ArmTileEntity arm = (ArmTileEntity) te; - ItemStack item = arm.heldItem; - boolean hasItem = !item.isEmpty(); - boolean usingFlywheel = Backend.canUseInstancing(te.getLevel()); - - if (usingFlywheel && !hasItem) - return; - - ItemRenderer itemRenderer = Minecraft.getInstance() - .getItemRenderer(); - - boolean isBlockItem = - hasItem && (item.getItem() instanceof BlockItem) && itemRenderer.getModel(item, te.getLevel(), null, 0) - .isGui3d(); - - VertexConsumer builder = buffer.getBuffer(RenderType.solid()); - BlockState blockState = te.getBlockState(); - - PoseStack msLocal = new PoseStack(); - TransformStack msr = TransformStack.cast(msLocal); - - float baseAngle; - float lowerArmAngle; - float upperArmAngle; - float headAngle; - int color; - - boolean rave = arm.phase == Phase.DANCING && te.getSpeed() != 0; - if (rave) { - float renderTick = AnimationTickHolder.getRenderTime(te.getLevel()) + (te.hashCode() % 64); - baseAngle = (renderTick * 10) % 360; - lowerArmAngle = Mth.lerp((Mth.sin(renderTick / 4) + 1) / 2, -45, 15); - upperArmAngle = Mth.lerp((Mth.sin(renderTick / 8) + 1) / 4, -45, 95); - headAngle = -lowerArmAngle; - color = Color.rainbowColor(AnimationTickHolder.getTicks() * 100) - .getRGB(); - } else { - baseAngle = arm.baseAngle.getValue(pt); - lowerArmAngle = arm.lowerArmAngle.getValue(pt) - 135; - upperArmAngle = arm.upperArmAngle.getValue(pt) - 90; - headAngle = arm.headAngle.getValue(pt); - color = 0xFFFFFF; - } - - msr.centre(); - - if (blockState.getValue(ArmBlock.CEILING)) - msr.rotateX(180); - - if (usingFlywheel) - doItemTransforms(msr, baseAngle, lowerArmAngle, upperArmAngle, headAngle); - else - renderArm(builder, ms, msLocal, msr, blockState, color, baseAngle, lowerArmAngle, upperArmAngle, headAngle, - hasItem, isBlockItem, light); - - if (hasItem) { - ms.pushPose(); - float itemScale = isBlockItem ? .5f : .625f; - msr.rotateX(90); - msLocal.translate(0, -4 / 16f, 0); - msLocal.scale(itemScale, itemScale, itemScale); - - ms.last() - .pose() - .mul(msLocal.last() - .pose()); - - itemRenderer.renderStatic(item, TransformType.FIXED, light, overlay, ms, buffer, 0); - ms.popPose(); - } - - } - - private void renderArm(VertexConsumer builder, PoseStack ms, PoseStack msLocal, TransformStack msr, - BlockState blockState, int color, float baseAngle, float lowerArmAngle, float upperArmAngle, float headAngle, - boolean hasItem, boolean isBlockItem, int light) { - SuperByteBuffer base = CachedBufferer.partial(AllBlockPartials.ARM_BASE, blockState) - .light(light); - SuperByteBuffer lowerBody = CachedBufferer.partial(AllBlockPartials.ARM_LOWER_BODY, blockState) - .light(light); - SuperByteBuffer upperBody = CachedBufferer.partial(AllBlockPartials.ARM_UPPER_BODY, blockState) - .light(light); - SuperByteBuffer head = CachedBufferer.partial(AllBlockPartials.ARM_HEAD, blockState) - .light(light); - SuperByteBuffer claw = CachedBufferer.partial(AllBlockPartials.ARM_CLAW_BASE, blockState) - .light(light); - SuperByteBuffer clawGrip = CachedBufferer.partial(AllBlockPartials.ARM_CLAW_GRIP, blockState); - - transformBase(msr, baseAngle); - base.transform(msLocal) - .renderInto(ms, builder); - - transformLowerArm(msr, lowerArmAngle); - lowerBody.color(color) - .transform(msLocal) - .renderInto(ms, builder); - - transformUpperArm(msr, upperArmAngle); - upperBody.color(color) - .transform(msLocal) - .renderInto(ms, builder); - - transformHead(msr, headAngle); - head.transform(msLocal) - .renderInto(ms, builder); - - transformClaw(msr); - claw.transform(msLocal) - .renderInto(ms, builder); - - for (int flip : Iterate.positiveAndNegative) { - msLocal.pushPose(); - transformClawHalf(msr, hasItem, isBlockItem, flip); - clawGrip.light(light) - .transform(msLocal) - .renderInto(ms, builder); - msLocal.popPose(); - } - } - - private void doItemTransforms(TransformStack msr, float baseAngle, float lowerArmAngle, float upperArmAngle, - float headAngle) { - - transformBase(msr, baseAngle); - transformLowerArm(msr, lowerArmAngle); - transformUpperArm(msr, upperArmAngle); - transformHead(msr, headAngle); - transformClaw(msr); - } - - public static void transformClawHalf(TransformStack msr, boolean hasItem, boolean isBlockItem, int flip) { - msr.translate(0, flip * 3 / 16d, -1 / 16d); - msr.rotateX(flip * (hasItem ? isBlockItem ? 0 : -35 : 0)); - } - - public static void transformClaw(TransformStack msr) { - msr.translate(0, 0, -4 / 16d); - } - - public static void transformHead(TransformStack msr, float headAngle) { - msr.translate(0, 11 / 16d, -11 / 16d); - msr.rotateX(headAngle); - } - - public static void transformUpperArm(TransformStack msr, float upperArmAngle) { - msr.translate(0, 12 / 16d, 12 / 16d); - msr.rotateX(upperArmAngle); - } - - public static void transformLowerArm(TransformStack msr, float lowerArmAngle) { - msr.translate(0, 1 / 16d, -2 / 16d); - msr.rotateX(lowerArmAngle); - msr.translate(0, -1 / 16d, 0); - } - - public static void transformBase(TransformStack msr, float baseAngle) { - msr.translate(0, 4 / 16d, 0); - msr.rotateY(baseAngle); - } - - @Override - public boolean shouldRenderOffScreen(KineticTileEntity te) { - return true; - } - - @Override - protected SuperByteBuffer getRotatedModel(KineticTileEntity te, BlockState state) { - return CachedBufferer.partial(AllBlockPartials.ARM_COG, state); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmTileEntity.java deleted file mode 100644 index fcae09028..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmTileEntity.java +++ /dev/null @@ -1,645 +0,0 @@ -package com.simibubi.create.content.logistics.block.mechanicalArm; - -import java.util.ArrayList; -import java.util.List; - -import javax.annotation.Nullable; - -import com.simibubi.create.Create; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.ITransformableTE; -import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform; -import com.simibubi.create.content.logistics.block.mechanicalArm.AllArmInteractionPointTypes.JukeboxPoint; -import com.simibubi.create.content.logistics.block.mechanicalArm.ArmInteractionPoint.Mode; -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.item.TooltipHelper; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.CenteredSideValueBoxTransform; -import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.INamedIconOptions; -import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollOptionBehaviour; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.SectionPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.Tag; -import net.minecraft.network.chat.Component; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.util.Mth; -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.JukeboxBlock; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.chunk.ChunkSource; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.Vec3; - -public class ArmTileEntity extends KineticTileEntity implements ITransformableTE { - - // Server - List inputs; - List outputs; - ListTag interactionPointTag; - - // Both - float chasedPointProgress; - int chasedPointIndex; - ItemStack heldItem; - Phase phase; - - // Client - ArmAngleTarget previousTarget; - LerpedFloat lowerArmAngle; - LerpedFloat upperArmAngle; - LerpedFloat baseAngle; - LerpedFloat headAngle; - LerpedFloat clawAngle; - float previousBaseAngle; - boolean updateInteractionPoints; - int tooltipWarmup; - - // - protected ScrollOptionBehaviour selectionMode; - protected int lastInputIndex = -1; - protected int lastOutputIndex = -1; - protected boolean redstoneLocked; - - public enum Phase { - SEARCH_INPUTS, MOVE_TO_INPUT, SEARCH_OUTPUTS, MOVE_TO_OUTPUT, DANCING - } - - public ArmTileEntity(BlockEntityType typeIn, BlockPos pos, BlockState state) { - super(typeIn, pos, state); - inputs = new ArrayList<>(); - outputs = new ArrayList<>(); - interactionPointTag = null; - heldItem = ItemStack.EMPTY; - phase = Phase.SEARCH_INPUTS; - previousTarget = ArmAngleTarget.NO_TARGET; - baseAngle = LerpedFloat.angular(); - baseAngle.startWithValue(previousTarget.baseAngle); - lowerArmAngle = LerpedFloat.angular(); - lowerArmAngle.startWithValue(previousTarget.lowerArmAngle); - upperArmAngle = LerpedFloat.angular(); - upperArmAngle.startWithValue(previousTarget.upperArmAngle); - headAngle = LerpedFloat.angular(); - headAngle.startWithValue(previousTarget.headAngle); - clawAngle = LerpedFloat.angular(); - previousBaseAngle = previousTarget.baseAngle; - updateInteractionPoints = true; - redstoneLocked = false; - tooltipWarmup = 15; - } - - @Override - public void addBehaviours(List behaviours) { - super.addBehaviours(behaviours); - - selectionMode = new ScrollOptionBehaviour(SelectionMode.class, - Lang.translateDirect("logistics.when_multiple_outputs_available"), this, new SelectionModeValueBox()); - selectionMode.requiresWrench(); - behaviours.add(selectionMode); - - registerAwardables(behaviours, AllAdvancements.ARM_BLAZE_BURNER, AllAdvancements.ARM_MANY_TARGETS, - AllAdvancements.MECHANICAL_ARM, AllAdvancements.MUSICAL_ARM); - } - - @Override - public void tick() { - super.tick(); - initInteractionPoints(); - boolean targetReached = tickMovementProgress(); - - if (tooltipWarmup > 0) - tooltipWarmup--; - if (chasedPointProgress < 1) { - if (phase == Phase.MOVE_TO_INPUT) { - ArmInteractionPoint point = getTargetedInteractionPoint(); - if (point != null) - point.keepAlive(); - } - return; - } - if (level.isClientSide) - return; - - if (phase == Phase.MOVE_TO_INPUT) - collectItem(); - else if (phase == Phase.MOVE_TO_OUTPUT) - depositItem(); - else if (phase == Phase.SEARCH_INPUTS || phase == Phase.DANCING) - searchForItem(); - - if (targetReached) - lazyTick(); - } - - @Override - public void lazyTick() { - super.lazyTick(); - - if (level.isClientSide) - return; - if (chasedPointProgress < .5f) - return; - if (phase == Phase.SEARCH_INPUTS || phase == Phase.DANCING) - checkForMusic(); - if (phase == Phase.SEARCH_OUTPUTS) - searchForDestination(); - } - - private void checkForMusic() { - boolean hasMusic = checkForMusicAmong(inputs) || checkForMusicAmong(outputs); - if (hasMusic != (phase == Phase.DANCING)) { - phase = hasMusic ? Phase.DANCING : Phase.SEARCH_INPUTS; - setChanged(); - sendData(); - } - } - - @Override - protected AABB createRenderBoundingBox() { - return super.createRenderBoundingBox().inflate(3); - } - - private boolean checkForMusicAmong(List list) { - for (ArmInteractionPoint armInteractionPoint : list) { - if (!(armInteractionPoint instanceof AllArmInteractionPointTypes.JukeboxPoint)) - continue; - BlockState state = level.getBlockState(armInteractionPoint.getPos()); - if (state.getOptionalValue(JukeboxBlock.HAS_RECORD) - .orElse(false)) - return true; - } - return false; - } - - private boolean tickMovementProgress() { - boolean targetReachedPreviously = chasedPointProgress >= 1; - chasedPointProgress += Math.min(256, Math.abs(getSpeed())) / 1024f; - if (chasedPointProgress > 1) - chasedPointProgress = 1; - if (!level.isClientSide) - return !targetReachedPreviously && chasedPointProgress >= 1; - - ArmInteractionPoint targetedInteractionPoint = getTargetedInteractionPoint(); - ArmAngleTarget previousTarget = this.previousTarget; - ArmAngleTarget target = targetedInteractionPoint == null ? ArmAngleTarget.NO_TARGET - : targetedInteractionPoint.getTargetAngles(worldPosition, isOnCeiling()); - - baseAngle.setValue(AngleHelper.angleLerp(chasedPointProgress, previousBaseAngle, - target == ArmAngleTarget.NO_TARGET ? previousBaseAngle : target.baseAngle)); - - // Arm's angles first backup to resting position and then continue - if (chasedPointProgress < .5f) - target = ArmAngleTarget.NO_TARGET; - else - previousTarget = ArmAngleTarget.NO_TARGET; - float progress = chasedPointProgress == 1 ? 1 : (chasedPointProgress % .5f) * 2; - - lowerArmAngle.setValue(Mth.lerp(progress, previousTarget.lowerArmAngle, target.lowerArmAngle)); - upperArmAngle.setValue(Mth.lerp(progress, previousTarget.upperArmAngle, target.upperArmAngle)); - headAngle.setValue(AngleHelper.angleLerp(progress, previousTarget.headAngle % 360, target.headAngle % 360)); - - return false; - } - - protected boolean isOnCeiling() { - BlockState state = getBlockState(); - return hasLevel() && state.getOptionalValue(ArmBlock.CEILING) - .orElse(false); - } - - @Override - public void destroy() { - super.destroy(); - if (!heldItem.isEmpty()) - Block.popResource(level, worldPosition, heldItem); - } - - @Nullable - private ArmInteractionPoint getTargetedInteractionPoint() { - if (chasedPointIndex == -1) - return null; - if (phase == Phase.MOVE_TO_INPUT && chasedPointIndex < inputs.size()) - return inputs.get(chasedPointIndex); - if (phase == Phase.MOVE_TO_OUTPUT && chasedPointIndex < outputs.size()) - return outputs.get(chasedPointIndex); - return null; - } - - protected void searchForItem() { - if (redstoneLocked) - return; - - boolean foundInput = false; - // for round robin, we start looking after the last used index, for default we - // start at 0; - int startIndex = selectionMode.get() == SelectionMode.PREFER_FIRST ? 0 : lastInputIndex + 1; - - // if we enforce round robin, only look at the next input in the list, - // otherwise, look at all inputs - int scanRange = selectionMode.get() == SelectionMode.FORCED_ROUND_ROBIN ? lastInputIndex + 2 : inputs.size(); - if (scanRange > inputs.size()) - scanRange = inputs.size(); - - InteractionPoints: for (int i = startIndex; i < scanRange; i++) { - ArmInteractionPoint armInteractionPoint = inputs.get(i); - if (!armInteractionPoint.isValid()) - continue; - for (int j = 0; j < armInteractionPoint.getSlotCount(); j++) { - if (getDistributableAmount(armInteractionPoint, j) == 0) - continue; - - selectIndex(true, i); - foundInput = true; - break InteractionPoints; - } - } - if (!foundInput && selectionMode.get() == SelectionMode.ROUND_ROBIN) { - // if we didn't find an input, but don't want to enforce round robin, reset the - // last index - lastInputIndex = -1; - } - if (lastInputIndex == inputs.size() - 1) { - // if we reached the last input in the list, reset the last index - lastInputIndex = -1; - } - } - - protected void searchForDestination() { - ItemStack held = heldItem.copy(); - - boolean foundOutput = false; - // for round robin, we start looking after the last used index, for default we - // start at 0; - int startIndex = selectionMode.get() == SelectionMode.PREFER_FIRST ? 0 : lastOutputIndex + 1; - - // if we enforce round robin, only look at the next index in the list, - // otherwise, look at all - int scanRange = selectionMode.get() == SelectionMode.FORCED_ROUND_ROBIN ? lastOutputIndex + 2 : outputs.size(); - if (scanRange > outputs.size()) - scanRange = outputs.size(); - - for (int i = startIndex; i < scanRange; i++) { - ArmInteractionPoint armInteractionPoint = outputs.get(i); - if (!armInteractionPoint.isValid()) - continue; - - ItemStack remainder = armInteractionPoint.insert(held, true); - if (remainder.equals(heldItem, false)) - continue; - - selectIndex(false, i); - foundOutput = true; - break; - } - - if (!foundOutput && selectionMode.get() == SelectionMode.ROUND_ROBIN) { - // if we didn't find an input, but don't want to enforce round robin, reset the - // last index - lastOutputIndex = -1; - } - if (lastOutputIndex == outputs.size() - 1) { - // if we reached the last input in the list, reset the last index - lastOutputIndex = -1; - } - } - - // input == true => select input, false => select output - private void selectIndex(boolean input, int index) { - phase = input ? Phase.MOVE_TO_INPUT : Phase.MOVE_TO_OUTPUT; - chasedPointIndex = index; - chasedPointProgress = 0; - if (input) - lastInputIndex = index; - else - lastOutputIndex = index; - sendData(); - setChanged(); - } - - protected int getDistributableAmount(ArmInteractionPoint armInteractionPoint, int i) { - ItemStack stack = armInteractionPoint.extract(i, true); - ItemStack remainder = simulateInsertion(stack); - if (stack.sameItem(remainder)) { - return stack.getCount() - remainder.getCount(); - } else { - return stack.getCount(); - } - } - - private ItemStack simulateInsertion(ItemStack stack) { - for (ArmInteractionPoint armInteractionPoint : outputs) { - if (armInteractionPoint.isValid()) - stack = armInteractionPoint.insert(stack, true); - if (stack.isEmpty()) - break; - } - return stack; - } - - protected void depositItem() { - ArmInteractionPoint armInteractionPoint = getTargetedInteractionPoint(); - if (armInteractionPoint != null && armInteractionPoint.isValid()) { - ItemStack toInsert = heldItem.copy(); - ItemStack remainder = armInteractionPoint.insert(toInsert, false); - heldItem = remainder; - - if (armInteractionPoint instanceof JukeboxPoint && remainder.isEmpty()) - award(AllAdvancements.MUSICAL_ARM); - } - - phase = heldItem.isEmpty() ? Phase.SEARCH_INPUTS : Phase.SEARCH_OUTPUTS; - chasedPointProgress = 0; - chasedPointIndex = -1; - sendData(); - setChanged(); - - if (!level.isClientSide) - award(AllAdvancements.MECHANICAL_ARM); - } - - protected void collectItem() { - ArmInteractionPoint armInteractionPoint = getTargetedInteractionPoint(); - if (armInteractionPoint != null && armInteractionPoint.isValid()) - for (int i = 0; i < armInteractionPoint.getSlotCount(); i++) { - int amountExtracted = getDistributableAmount(armInteractionPoint, i); - if (amountExtracted == 0) - continue; - - ItemStack prevHeld = heldItem; - heldItem = armInteractionPoint.extract(i, amountExtracted, false); - phase = Phase.SEARCH_OUTPUTS; - chasedPointProgress = 0; - chasedPointIndex = -1; - sendData(); - setChanged(); - - if (!prevHeld.sameItem(heldItem)) - level.playSound(null, worldPosition, SoundEvents.ITEM_PICKUP, SoundSource.BLOCKS, .125f, - .5f + Create.RANDOM.nextFloat() * .25f); - return; - } - - phase = Phase.SEARCH_INPUTS; - chasedPointProgress = 0; - chasedPointIndex = -1; - sendData(); - setChanged(); - } - - public void redstoneUpdate() { - if (level.isClientSide) - return; - boolean blockPowered = level.hasNeighborSignal(worldPosition); - if (blockPowered == redstoneLocked) - return; - redstoneLocked = blockPowered; - sendData(); - if (!redstoneLocked) - searchForItem(); - } - - @Override - public void transform(StructureTransform transform) { - if (interactionPointTag == null) - return; - - for (Tag tag : interactionPointTag) { - ArmInteractionPoint.transformPos((CompoundTag) tag, transform); - } - - notifyUpdate(); - } - - // ClientLevel#hasChunk (and consequently #isAreaLoaded) always returns true, - // so manually check the ChunkSource to avoid weird behavior on the client side - protected boolean isAreaActuallyLoaded(BlockPos center, int range) { - if (!level.isAreaLoaded(center, range)) { - return false; - } - if (level.isClientSide) { - int minY = center.getY() - range; - int maxY = center.getY() + range; - if (maxY < level.getMinBuildHeight() || minY >= level.getMaxBuildHeight()) { - return false; - } - - int minX = center.getX() - range; - int minZ = center.getZ() - range; - int maxX = center.getX() + range; - int maxZ = center.getZ() + range; - - int minChunkX = SectionPos.blockToSectionCoord(minX); - int maxChunkX = SectionPos.blockToSectionCoord(maxX); - int minChunkZ = SectionPos.blockToSectionCoord(minZ); - int maxChunkZ = SectionPos.blockToSectionCoord(maxZ); - - ChunkSource chunkSource = level.getChunkSource(); - for (int chunkX = minChunkX; chunkX <= maxChunkX; ++chunkX) { - for (int chunkZ = minChunkZ; chunkZ <= maxChunkZ; ++chunkZ) { - if (!chunkSource.hasChunk(chunkX, chunkZ)) { - return false; - } - } - } - } - return true; - } - - protected void initInteractionPoints() { - if (!updateInteractionPoints || interactionPointTag == null) - return; - if (!isAreaActuallyLoaded(worldPosition, getRange() + 1)) - return; - inputs.clear(); - outputs.clear(); - - boolean hasBlazeBurner = false; - for (Tag tag : interactionPointTag) { - ArmInteractionPoint point = ArmInteractionPoint.deserialize((CompoundTag) tag, level, worldPosition); - if (point == null) - continue; - if (point.getMode() == Mode.DEPOSIT) - outputs.add(point); - else if (point.getMode() == Mode.TAKE) - inputs.add(point); - hasBlazeBurner |= point instanceof AllArmInteractionPointTypes.BlazeBurnerPoint; - } - - if (!level.isClientSide) { - if (outputs.size() >= 10) - award(AllAdvancements.ARM_MANY_TARGETS); - if (hasBlazeBurner) - award(AllAdvancements.ARM_BLAZE_BURNER); - } - - updateInteractionPoints = false; - sendData(); - setChanged(); - } - - public void writeInteractionPoints(CompoundTag compound) { - if (updateInteractionPoints && interactionPointTag != null) { - compound.put("InteractionPoints", interactionPointTag); - } else { - ListTag pointsNBT = new ListTag(); - inputs.stream() - .map(aip -> aip.serialize(worldPosition)) - .forEach(pointsNBT::add); - outputs.stream() - .map(aip -> aip.serialize(worldPosition)) - .forEach(pointsNBT::add); - compound.put("InteractionPoints", pointsNBT); - } - } - - @Override - public void write(CompoundTag compound, boolean clientPacket) { - super.write(compound, clientPacket); - - writeInteractionPoints(compound); - - NBTHelper.writeEnum(compound, "Phase", phase); - compound.putBoolean("Powered", redstoneLocked); - compound.put("HeldItem", heldItem.serializeNBT()); - compound.putInt("TargetPointIndex", chasedPointIndex); - compound.putFloat("MovementProgress", chasedPointProgress); - } - - @Override - public void writeSafe(CompoundTag compound) { - super.writeSafe(compound); - - writeInteractionPoints(compound); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - int previousIndex = chasedPointIndex; - Phase previousPhase = phase; - ListTag interactionPointTagBefore = interactionPointTag; - - super.read(compound, clientPacket); - heldItem = ItemStack.of(compound.getCompound("HeldItem")); - phase = NBTHelper.readEnum(compound, "Phase", Phase.class); - chasedPointIndex = compound.getInt("TargetPointIndex"); - chasedPointProgress = compound.getFloat("MovementProgress"); - interactionPointTag = compound.getList("InteractionPoints", Tag.TAG_COMPOUND); - redstoneLocked = compound.getBoolean("Powered"); - - if (!clientPacket) - return; - - boolean ceiling = isOnCeiling(); - if (interactionPointTagBefore == null || interactionPointTagBefore.size() != interactionPointTag.size()) - updateInteractionPoints = true; - if (previousIndex != chasedPointIndex || (previousPhase != phase)) { - ArmInteractionPoint previousPoint = null; - if (previousPhase == Phase.MOVE_TO_INPUT && previousIndex < inputs.size()) - previousPoint = inputs.get(previousIndex); - if (previousPhase == Phase.MOVE_TO_OUTPUT && previousIndex < outputs.size()) - previousPoint = outputs.get(previousIndex); - previousTarget = previousPoint == null ? ArmAngleTarget.NO_TARGET - : previousPoint.getTargetAngles(worldPosition, ceiling); - if (previousPoint != null) - previousBaseAngle = previousTarget.baseAngle; - - ArmInteractionPoint targetedPoint = getTargetedInteractionPoint(); - if (targetedPoint != null) - targetedPoint.updateCachedState(); - } - } - - public static int getRange() { - return AllConfigs.SERVER.logistics.mechanicalArmRange.get(); - } - - @Override - public boolean addToTooltip(List tooltip, boolean isPlayerSneaking) { - if (super.addToTooltip(tooltip, isPlayerSneaking)) - return true; - if (isPlayerSneaking) - return false; - if (tooltipWarmup > 0) - return false; - if (!inputs.isEmpty()) - return false; - if (!outputs.isEmpty()) - return false; - - TooltipHelper.addHint(tooltip, "hint.mechanical_arm_no_targets"); - return true; - } - - public void setLevel(Level level) { - super.setLevel(level); - for (ArmInteractionPoint input : inputs) { - input.setLevel(level); - } - for (ArmInteractionPoint output : outputs) { - output.setLevel(level); - } - } - - private class SelectionModeValueBox extends CenteredSideValueBoxTransform { - - public SelectionModeValueBox() { - super((blockState, direction) -> !direction.getAxis() - .isVertical()); - } - - @Override - protected Vec3 getLocalOffset(BlockState state) { - int yPos = state.getValue(ArmBlock.CEILING) ? 16 - 3 : 3; - Vec3 location = VecHelper.voxelSpace(8, yPos, 15.95); - location = VecHelper.rotateCentered(location, AngleHelper.horizontalAngle(getSide()), Direction.Axis.Y); - return location; - } - - @Override - protected float getScale() { - return .3f; - } - - } - - public enum SelectionMode implements INamedIconOptions { - ROUND_ROBIN(AllIcons.I_ARM_ROUND_ROBIN), - FORCED_ROUND_ROBIN(AllIcons.I_ARM_FORCED_ROUND_ROBIN), - PREFER_FIRST(AllIcons.I_ARM_PREFER_FIRST), - - ; - - private final String translationKey; - private final AllIcons icon; - - SelectionMode(AllIcons icon) { - this.icon = icon; - this.translationKey = "mechanical_arm.selection_mode." + Lang.asId(name()); - } - - @Override - public AllIcons getIcon() { - return icon; - } - - @Override - public String getTranslationKey() { - return translationKey; - } - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/AnalogLeverRenderer.java b/src/main/java/com/simibubi/create/content/logistics/block/redstone/AnalogLeverRenderer.java deleted file mode 100644 index 8fb88fd82..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/AnalogLeverRenderer.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.simibubi.create.content.logistics.block.redstone; - -import com.jozufozu.flywheel.backend.Backend; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.Color; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.Direction; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.AttachFace; - -public class AnalogLeverRenderer extends SafeTileEntityRenderer { - - public AnalogLeverRenderer(BlockEntityRendererProvider.Context context) { - } - - @Override - protected void renderSafe(AnalogLeverTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - - if (Backend.canUseInstancing(te.getLevel())) return; - - BlockState leverState = te.getBlockState(); - float state = te.clientState.getValue(partialTicks); - - VertexConsumer vb = buffer.getBuffer(RenderType.solid()); - - // Handle - SuperByteBuffer handle = CachedBufferer.partial(AllBlockPartials.ANALOG_LEVER_HANDLE, leverState); - float angle = (float) ((state / 15) * 90 / 180 * Math.PI); - transform(handle, leverState).translate(1 / 2f, 1 / 16f, 1 / 2f) - .rotate(Direction.EAST, angle) - .translate(-1 / 2f, -1 / 16f, -1 / 2f); - handle.light(light) - .renderInto(ms, vb); - - // Indicator - int color = Color.mixColors(0x2C0300, 0xCD0000, state / 15f); - SuperByteBuffer indicator = transform(CachedBufferer.partial(AllBlockPartials.ANALOG_LEVER_INDICATOR, leverState), leverState); - indicator.light(light) - .color(color) - .renderInto(ms, vb); - } - - private SuperByteBuffer transform(SuperByteBuffer buffer, BlockState leverState) { - AttachFace face = leverState.getValue(AnalogLeverBlock.FACE); - float rX = face == AttachFace.FLOOR ? 0 : face == AttachFace.WALL ? 90 : 180; - float rY = AngleHelper.horizontalAngle(leverState.getValue(AnalogLeverBlock.FACING)); - buffer.rotateCentered(Direction.UP, (float) (rY / 180 * Math.PI)); - buffer.rotateCentered(Direction.EAST, (float) (rX / 180 * Math.PI)); - return buffer; - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/AnalogLeverTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/redstone/AnalogLeverTileEntity.java deleted file mode 100644 index d7bd93f53..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/AnalogLeverTileEntity.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.simibubi.create.content.logistics.block.redstone; - -import java.util.List; - -import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; - -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.util.Mth; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; - -public class AnalogLeverTileEntity extends SmartTileEntity implements IHaveGoggleInformation { - - int state = 0; - int lastChange; - LerpedFloat clientState; - - public AnalogLeverTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - clientState = LerpedFloat.linear(); - } - - @Override - public void write(CompoundTag compound, boolean clientPacket) { - compound.putInt("State", state); - compound.putInt("ChangeTimer", lastChange); - super.write(compound, clientPacket); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - state = compound.getInt("State"); - lastChange = compound.getInt("ChangeTimer"); - clientState.chase(state, 0.2f, Chaser.EXP); - super.read(compound, clientPacket); - } - - @Override - public void tick() { - super.tick(); - if (lastChange > 0) { - lastChange--; - if (lastChange == 0) - updateOutput(); - } - if (level.isClientSide) - clientState.tickChaser(); - } - - @Override - public void initialize() { - super.initialize(); - - } - - private void updateOutput() { - AnalogLeverBlock.updateNeighbors(getBlockState(), level, worldPosition); - } - - @Override - public void addBehaviours(List behaviours) { - } - - public void changeState(boolean back) { - int prevState = state; - state += back ? -1 : 1; - state = Mth.clamp(state, 0, 15); - if (prevState != state) - lastChange = 15; - sendData(); - } - - @Override - public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { - tooltip.add(componentSpacing.plainCopy().append(Lang.translateDirect("tooltip.analogStrength", this.state))); - - return true; - } - - public int getState() { - return state; - } -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/ContactMovementBehaviour.java b/src/main/java/com/simibubi/create/content/logistics/block/redstone/ContactMovementBehaviour.java deleted file mode 100644 index fe7539064..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/ContactMovementBehaviour.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.simibubi.create.content.logistics.block.redstone; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.NbtUtils; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; -import net.minecraft.world.ticks.TickPriority; - -public class ContactMovementBehaviour implements MovementBehaviour { - - @Override - public Vec3 getActiveAreaOffset(MovementContext context) { - return Vec3.atLowerCornerOf(context.state.getValue(RedstoneContactBlock.FACING).getNormal()).scale(.65f); - } - - @Override - public void visitNewPosition(MovementContext context, BlockPos pos) { - BlockState block = context.state; - Level world = context.world; - - if (world.isClientSide) - return; - if (context.firstMovement) - return; - - deactivateLastVisitedContact(context); - BlockState visitedState = world.getBlockState(pos); - if (!AllBlocks.REDSTONE_CONTACT.has(visitedState)) - return; - - Vec3 contact = Vec3.atLowerCornerOf(block.getValue(RedstoneContactBlock.FACING).getNormal()); - contact = context.rotation.apply(contact); - Direction direction = Direction.getNearest(contact.x, contact.y, contact.z); - - if (!RedstoneContactBlock.hasValidContact(world, pos.relative(direction.getOpposite()), direction)) - return; - world.setBlockAndUpdate(pos, visitedState.setValue(RedstoneContactBlock.POWERED, true)); - context.data.put("lastContact", NbtUtils.writeBlockPos(pos)); - return; - } - - @Override - public void stopMoving(MovementContext context) { - deactivateLastVisitedContact(context); - } - - @Override - public void cancelStall(MovementContext context) { - MovementBehaviour.super.cancelStall(context); - deactivateLastVisitedContact(context); - } - - public void deactivateLastVisitedContact(MovementContext context) { - if (context.data.contains("lastContact")) { - BlockPos last = NbtUtils.readBlockPos(context.data.getCompound("lastContact")); - context.world.scheduleTick(last, AllBlocks.REDSTONE_CONTACT.get(), 1, TickPriority.NORMAL); - context.data.remove("lastContact"); - } - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/ContentObserverBlock.java b/src/main/java/com/simibubi/create/content/logistics/block/redstone/ContentObserverBlock.java deleted file mode 100644 index 6f7171508..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/ContentObserverBlock.java +++ /dev/null @@ -1,168 +0,0 @@ -package com.simibubi.create.content.logistics.block.redstone; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.fluids.FluidTransportBehaviour; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; -import com.simibubi.create.content.logistics.block.funnel.FunnelTileEntity; -import com.simibubi.create.foundation.block.ITE; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.inventory.InvManipulationBehaviour; -import com.simibubi.create.foundation.utility.Iterate; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.util.RandomSource; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.context.BlockPlaceContext; -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.HorizontalDirectionalBlock; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition.Builder; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.block.state.properties.BooleanProperty; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.VoxelShape; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.fluids.capability.CapabilityFluidHandler; -import net.minecraftforge.fluids.capability.IFluidHandler; -import net.minecraftforge.items.CapabilityItemHandler; -import net.minecraftforge.items.IItemHandler; - -public class ContentObserverBlock extends HorizontalDirectionalBlock implements ITE, IWrenchable { - - public static final BooleanProperty POWERED = BlockStateProperties.POWERED; - - public ContentObserverBlock(Properties properties) { - super(properties); - registerDefaultState(defaultBlockState().setValue(POWERED, false)); - } - - @Override - public VoxelShape getShape(BlockState state, BlockGetter p_220053_2_, BlockPos p_220053_3_, - CollisionContext p_220053_4_) { - return AllShapes.CONTENT_OBSERVER.get(state.getValue(FACING)); - } - - @Override - protected void createBlockStateDefinition(Builder builder) { - builder.add(POWERED, FACING); - super.createBlockStateDefinition(builder); - } - - @Override - public BlockState getStateForPlacement(BlockPlaceContext context) { - BlockState state = defaultBlockState(); - Capability itemCap = CapabilityItemHandler.ITEM_HANDLER_CAPABILITY; - Capability fluidCap = CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY; - - Direction preferredFacing = null; - for (Direction face : Iterate.horizontalDirections) { - BlockPos offsetPos = context.getClickedPos() - .relative(face); - Level world = context.getLevel(); - boolean canDetect = false; - BlockEntity tileEntity = world.getBlockEntity(offsetPos); - - if (TileEntityBehaviour.get(tileEntity, TransportedItemStackHandlerBehaviour.TYPE) != null) - canDetect = true; - else if (TileEntityBehaviour.get(tileEntity, FluidTransportBehaviour.TYPE) != null) - canDetect = true; - else if (tileEntity != null && (tileEntity.getCapability(itemCap) - .isPresent() - || tileEntity.getCapability(fluidCap) - .isPresent())) - canDetect = true; - else if (tileEntity instanceof FunnelTileEntity) - canDetect = true; - - if (canDetect) { - if (preferredFacing != null) { - preferredFacing = null; - break; - } - preferredFacing = face; - } - - } - - if (preferredFacing != null) - return state.setValue(FACING, preferredFacing); - return state.setValue(FACING, context.getHorizontalDirection() - .getOpposite()); - } - - @Override - public boolean isSignalSource(BlockState state) { - return state.getValue(POWERED); - } - - @Override - public int getSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { - return isSignalSource(blockState) && (side == null || side != blockState.getValue(FACING) - .getOpposite()) ? 15 : 0; - } - - @Override - public void tick(BlockState state, ServerLevel worldIn, BlockPos pos, RandomSource random) { - worldIn.setBlock(pos, state.setValue(POWERED, false), 2); - worldIn.updateNeighborsAt(pos, this); - } - - @Override - public boolean canConnectRedstone(BlockState state, BlockGetter world, BlockPos pos, Direction side) { - return side != state.getValue(FACING) - .getOpposite(); - } - - @Override - public void onRemove(BlockState state, Level worldIn, BlockPos pos, BlockState newState, boolean isMoving) { - ITE.onRemove(state, worldIn, pos, newState); - } - - @Override - public void neighborChanged(BlockState state, Level worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, - boolean isMoving) { - InvManipulationBehaviour behaviour = TileEntityBehaviour.get(worldIn, pos, InvManipulationBehaviour.TYPE); - if (behaviour != null) - behaviour.onNeighborChanged(fromPos); - } - - public void onFunnelTransfer(Level world, BlockPos funnelPos, ItemStack transferred) { - for (Direction direction : Iterate.horizontalDirections) { - BlockPos detectorPos = funnelPos.relative(direction); - BlockState detectorState = world.getBlockState(detectorPos); - if (!AllBlocks.CONTENT_OBSERVER.has(detectorState)) - continue; - if (detectorState.getValue(FACING) != direction.getOpposite()) - continue; - withTileEntityDo(world, detectorPos, te -> { - FilteringBehaviour filteringBehaviour = TileEntityBehaviour.get(te, FilteringBehaviour.TYPE); - if (filteringBehaviour == null) - return; - if (!filteringBehaviour.test(transferred)) - return; - te.activate(4); - }); - } - } - - @Override - public Class getTileEntityClass() { - return ContentObserverTileEntity.class; - } - - @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.CONTENT_OBSERVER.get(); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/ContentObserverTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/redstone/ContentObserverTileEntity.java deleted file mode 100644 index 7d2dc71a2..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/ContentObserverTileEntity.java +++ /dev/null @@ -1,136 +0,0 @@ -package com.simibubi.create.content.logistics.block.redstone; - -import java.util.List; - -import com.simibubi.create.content.contraptions.fluids.FluidTransportBehaviour; -import com.simibubi.create.content.contraptions.fluids.PipeConnection.Flow; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour.TransportedResult; -import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.inventory.CapManipulationBehaviourBase.InterfaceProvider; -import com.simibubi.create.foundation.tileEntity.behaviour.inventory.InvManipulationBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.inventory.TankManipulationBehaviour; -import com.simibubi.create.foundation.utility.Iterate; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; - -public class ContentObserverTileEntity extends SmartTileEntity { - - private static final int DEFAULT_DELAY = 6; - private FilteringBehaviour filtering; - private InvManipulationBehaviour observedInventory; - private TankManipulationBehaviour observedTank; - public int turnOffTicks = 0; - - public ContentObserverTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - setLazyTickRate(20); - } - - @Override - public void addBehaviours(List behaviours) { - filtering = new FilteringBehaviour(this, new FilteredDetectorFilterSlot()).moveText(new Vec3(0, 5, 0)); - behaviours.add(filtering); - - InterfaceProvider towardBlockFacing = InterfaceProvider.towardBlockFacing(); - behaviours.add(observedInventory = new InvManipulationBehaviour(this, towardBlockFacing).bypassSidedness()); - behaviours.add(observedTank = new TankManipulationBehaviour(this, towardBlockFacing).bypassSidedness()); - } - - @Override - public void tick() { - super.tick(); - BlockState state = getBlockState(); - if (turnOffTicks > 0) { - turnOffTicks--; - if (turnOffTicks == 0) - level.scheduleTick(worldPosition, state.getBlock(), 1); - } - - if (!isActive()) - return; - - Direction facing = state.getValue(ContentObserverBlock.FACING); - BlockPos targetPos = worldPosition.relative(facing); - - // Detect items on belt - TransportedItemStackHandlerBehaviour behaviour = - TileEntityBehaviour.get(level, targetPos, TransportedItemStackHandlerBehaviour.TYPE); - if (behaviour != null) { - behaviour.handleCenteredProcessingOnAllItems(.45f, stack -> { - if (!filtering.test(stack.stack) || turnOffTicks == 6) - return TransportedResult.doNothing(); - activate(); - return TransportedResult.doNothing(); - }); - return; - } - - // Detect fluids in pipe - FluidTransportBehaviour fluidBehaviour = - TileEntityBehaviour.get(level, targetPos, FluidTransportBehaviour.TYPE); - if (fluidBehaviour != null) { - for (Direction side : Iterate.directions) { - Flow flow = fluidBehaviour.getFlow(side); - if (flow == null || !flow.inbound || !flow.complete) - continue; - if (!filtering.test(flow.fluid)) - continue; - activate(); - return; - } - return; - } - - if (!observedInventory.simulate() - .extract() - .isEmpty()) { - activate(); - return; - } - - if (!observedTank.simulate() - .extractAny() - .isEmpty()) { - activate(); - return; - } - } - - public void activate() { - activate(DEFAULT_DELAY); - } - - public void activate(int ticks) { - BlockState state = getBlockState(); - turnOffTicks = ticks; - if (state.getValue(ContentObserverBlock.POWERED)) - return; - level.setBlockAndUpdate(worldPosition, state.setValue(ContentObserverBlock.POWERED, true)); - level.updateNeighborsAt(worldPosition, state.getBlock()); - } - - private boolean isActive() { - return true; - } - - @Override - public void write(CompoundTag compound, boolean clientPacket) { - compound.putInt("TurnOff", turnOffTicks); - super.write(compound, clientPacket); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - super.read(compound, clientPacket); - turnOffTicks = compound.getInt("TurnOff"); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/FilteredDetectorFilterSlot.java b/src/main/java/com/simibubi/create/content/logistics/block/redstone/FilteredDetectorFilterSlot.java deleted file mode 100644 index b7436efe0..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/FilteredDetectorFilterSlot.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.simibubi.create.content.logistics.block.redstone; - -import com.jozufozu.flywheel.util.transform.TransformStack; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.world.level.block.HorizontalDirectionalBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; - -public class FilteredDetectorFilterSlot extends ValueBoxTransform { - Vec3 position = VecHelper.voxelSpace(8f, 15.5f, 11f); - - @Override - protected Vec3 getLocalOffset(BlockState state) { - return rotateHorizontally(state, position); - } - - @Override - protected void rotate(BlockState state, PoseStack ms) { - float yRot = AngleHelper.horizontalAngle(state.getValue(HorizontalDirectionalBlock.FACING)) + 180; - TransformStack.cast(ms) - .rotateY(yRot) - .rotateX(90); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/NixieTubeRenderer.java b/src/main/java/com/simibubi/create/content/logistics/block/redstone/NixieTubeRenderer.java deleted file mode 100644 index 4428908fa..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/NixieTubeRenderer.java +++ /dev/null @@ -1,205 +0,0 @@ -package com.simibubi.create.content.logistics.block.redstone; - -import java.util.Random; - -import com.jozufozu.flywheel.util.transform.TransformStack; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.logistics.block.redstone.DoubleFaceAttachedBlock.DoubleAttachFace; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.RenderTypes; -import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.Color; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.DyeHelper; -import com.simibubi.create.foundation.utility.Iterate; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.Font; -import net.minecraft.client.gui.font.glyphs.BakedGlyph; -import net.minecraft.client.renderer.LightTexture; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.MultiBufferSource.BufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.Direction; -import net.minecraft.network.chat.Style; -import net.minecraft.world.item.DyeColor; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; - -public class NixieTubeRenderer extends SafeTileEntityRenderer { - - private static Random r = new Random(); - - public NixieTubeRenderer(BlockEntityRendererProvider.Context context) {} - - @Override - protected void renderSafe(NixieTubeTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - ms.pushPose(); - BlockState blockState = te.getBlockState(); - DoubleAttachFace face = blockState.getValue(NixieTubeBlock.FACE); - float yRot = AngleHelper.horizontalAngle(blockState.getValue(NixieTubeBlock.FACING)) - 90 - + (face == DoubleAttachFace.WALL_REVERSED ? 180 : 0); - float xRot = face == DoubleAttachFace.WALL ? -90 : face == DoubleAttachFace.WALL_REVERSED ? 90 : 0; - - TransformStack msr = TransformStack.cast(ms); - msr.centre() - .rotateY(yRot) - .rotateZ(xRot) - .unCentre(); - - if (te.signalState != null) { - renderAsSignal(te, partialTicks, ms, buffer, light, overlay); - ms.popPose(); - return; - } - - msr.centre(); - - float height = face == DoubleAttachFace.CEILING ? 5 : 3; - float scale = 1 / 20f; - - Couple s = te.getDisplayedStrings(); - DyeColor color = NixieTubeBlock.colorOf(te.getBlockState()); - - ms.pushPose(); - ms.translate(-4 / 16f, 0, 0); - ms.scale(scale, -scale, scale); - drawTube(ms, buffer, s.getFirst(), height, color); - ms.popPose(); - - ms.pushPose(); - ms.translate(4 / 16f, 0, 0); - ms.scale(scale, -scale, scale); - drawTube(ms, buffer, s.getSecond(), height, color); - ms.popPose(); - - ms.popPose(); - } - - public static void drawTube(PoseStack ms, MultiBufferSource buffer, String c, float height, DyeColor color) { - Font fontRenderer = Minecraft.getInstance().font; - float charWidth = fontRenderer.width(c); - float shadowOffset = .5f; - float flicker = r.nextFloat(); - Couple couple = DyeHelper.DYE_TABLE.get(color); - int brightColor = couple.getFirst(); - int darkColor = couple.getSecond(); - int flickeringBrightColor = Color.mixColors(brightColor, darkColor, flicker / 4); - - ms.pushPose(); - ms.translate((charWidth - shadowOffset) / -2f, -height, 0); - drawChar(ms, buffer, c, flickeringBrightColor); - ms.pushPose(); - ms.translate(shadowOffset, shadowOffset, -1 / 16f); - drawChar(ms, buffer, c, darkColor); - ms.popPose(); - ms.popPose(); - - ms.pushPose(); - ms.scale(-1, 1, 1); - ms.translate((charWidth - shadowOffset) / -2f, -height, 0); - drawChar(ms, buffer, c, darkColor); - ms.pushPose(); - ms.translate(-shadowOffset, shadowOffset, -1 / 16f); - drawChar(ms, buffer, c, Color.mixColors(darkColor, 0, .35f)); - ms.popPose(); - ms.popPose(); - } - - private static void drawChar(PoseStack ms, MultiBufferSource buffer, String c, int color) { - Font fontRenderer = Minecraft.getInstance().font; - fontRenderer.drawInBatch(c, 0, 0, color, false, ms.last() - .pose(), buffer, false, 0, LightTexture.FULL_BRIGHT); - if (buffer instanceof BufferSource) { - BakedGlyph texturedglyph = fontRenderer.getFontSet(Style.DEFAULT_FONT) - .whiteGlyph(); - ((BufferSource) buffer).endBatch(texturedglyph.renderType(Font.DisplayMode.NORMAL)); - } - } - - private void renderAsSignal(NixieTubeTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - BlockState blockState = te.getBlockState(); - Direction facing = NixieTubeBlock.getFacing(blockState); - Vec3 observerVec = Minecraft.getInstance().cameraEntity.getEyePosition(partialTicks); - TransformStack msr = TransformStack.cast(ms); - - if (facing == Direction.DOWN) - msr.centre() - .rotateZ(180) - .unCentre(); - - boolean invertTubes = - facing == Direction.DOWN || blockState.getValue(NixieTubeBlock.FACE) == DoubleAttachFace.WALL_REVERSED; - - CachedBufferer.partial(AllBlockPartials.SIGNAL_PANEL, blockState) - .light(light) - .renderInto(ms, buffer.getBuffer(RenderType.solid())); - - ms.pushPose(); - ms.translate(1 / 2f, 7.5f / 16f, 1 / 2f); - float renderTime = AnimationTickHolder.getRenderTime(te.getLevel()); - - for (boolean first : Iterate.trueAndFalse) { - Vec3 lampVec = Vec3.atCenterOf(te.getBlockPos()); - Vec3 diff = lampVec.subtract(observerVec); - - if (first && !te.signalState.isRedLight(renderTime)) - continue; - if (!first && !te.signalState.isGreenLight(renderTime) && !te.signalState.isYellowLight(renderTime)) - continue; - - boolean flip = first == invertTubes; - boolean yellow = te.signalState.isYellowLight(renderTime); - - ms.pushPose(); - ms.translate(flip ? 4 / 16f : -4 / 16f, 0, 0); - - if (diff.lengthSqr() < 96 * 96) { - boolean vert = first ^ facing.getAxis() - .isHorizontal(); - float longSide = yellow ? 1 : 4; - float longSideGlow = yellow ? 2 : 5.125f; - - CachedBufferer.partial(AllBlockPartials.SIGNAL_WHITE_CUBE, blockState) - .light(0xf000f0) - .disableDiffuse() - .scale(vert ? longSide : 1, vert ? 1 : longSide, 1) - .renderInto(ms, buffer.getBuffer(RenderType.translucent())); - - CachedBufferer - .partial( - first ? AllBlockPartials.SIGNAL_RED_GLOW - : yellow ? AllBlockPartials.SIGNAL_YELLOW_GLOW : AllBlockPartials.SIGNAL_WHITE_GLOW, - blockState) - .light(0xf000f0) - .disableDiffuse() - .scale(vert ? longSideGlow : 2, vert ? 2 : longSideGlow, 2) - .renderInto(ms, buffer.getBuffer(RenderTypes.getAdditive())); - } - - CachedBufferer - .partial(first ? AllBlockPartials.SIGNAL_RED - : yellow ? AllBlockPartials.SIGNAL_YELLOW : AllBlockPartials.SIGNAL_WHITE, blockState) - .light(0xF000F0) - .disableDiffuse() - .scale(1 + 1 / 16f) - .renderInto(ms, buffer.getBuffer(RenderTypes.getAdditive())); - - ms.popPose(); - } - ms.popPose(); - - } - - @Override - public int getViewDistance() { - return 128; - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/NixieTubeTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/redstone/NixieTubeTileEntity.java deleted file mode 100644 index 28afb42ed..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/NixieTubeTileEntity.java +++ /dev/null @@ -1,170 +0,0 @@ -package com.simibubi.create.content.logistics.block.redstone; - -import java.lang.ref.WeakReference; -import java.util.List; -import java.util.Optional; - -import com.simibubi.create.content.logistics.block.display.DisplayLinkBlock; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalTileEntity; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalTileEntity.SignalState; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.DynamicComponent; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.MutableComponent; -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 class NixieTubeTileEntity extends SmartTileEntity { - - private static final Couple EMPTY = Couple.create("", ""); - - private int redstoneStrength; - private Optional customText; - private int nixieIndex; - private Couple displayedStrings; - - private WeakReference cachedSignalTE; - public SignalState signalState; - - public NixieTubeTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - customText = Optional.empty(); - redstoneStrength = 0; - cachedSignalTE = new WeakReference<>(null); - } - - @Override - public void tick() { - super.tick(); - if (!level.isClientSide) - return; - - signalState = null; - SignalTileEntity signalTileEntity = cachedSignalTE.get(); - - if (signalTileEntity == null || signalTileEntity.isRemoved()) { - Direction facing = NixieTubeBlock.getFacing(getBlockState()); - BlockEntity blockEntity = level.getBlockEntity(worldPosition.relative(facing.getOpposite())); - if (blockEntity instanceof SignalTileEntity signal) { - signalState = signal.getState(); - cachedSignalTE = new WeakReference<>(signal); - } - return; - } - - signalState = signalTileEntity.getState(); - } - - @Override - public void initialize() { - if (level.isClientSide) - updateDisplayedStrings(); - } - - // - - public boolean reactsToRedstone() { - return customText.isEmpty(); - } - - public Couple getDisplayedStrings() { - if (displayedStrings == null) - return EMPTY; - return displayedStrings; - } - - public MutableComponent getFullText() { - return customText.map(DynamicComponent::get) - .orElse(Components.literal("" + redstoneStrength)); - } - - public void updateRedstoneStrength(int signalStrength) { - clearCustomText(); - redstoneStrength = signalStrength; - DisplayLinkBlock.notifyGatherers(level, worldPosition); - notifyUpdate(); - } - - public void displayCustomText(String tagElement, int nixiePositionInRow) { - if (tagElement == null) - return; - if (customText.filter(d -> d.sameAs(tagElement)) - .isPresent()) - return; - - DynamicComponent component = customText.orElseGet(DynamicComponent::new); - component.displayCustomText(level, worldPosition, tagElement); - customText = Optional.of(component); - nixieIndex = nixiePositionInRow; - DisplayLinkBlock.notifyGatherers(level, worldPosition); - notifyUpdate(); - } - - public void updateDisplayedStrings() { - if (signalState != null) - return; - customText.map(DynamicComponent::resolve) - .ifPresentOrElse( - fullText -> displayedStrings = - Couple.create(charOrEmpty(fullText, nixieIndex * 2), charOrEmpty(fullText, nixieIndex * 2 + 1)), - () -> displayedStrings = - Couple.create(redstoneStrength < 10 ? "0" : "1", String.valueOf(redstoneStrength % 10))); - } - - public void clearCustomText() { - nixieIndex = 0; - customText = Optional.empty(); - } - - // - - @Override - protected void read(CompoundTag nbt, boolean clientPacket) { - super.read(nbt, clientPacket); - - if (nbt.contains("CustomText")) { - DynamicComponent component = customText.orElseGet(DynamicComponent::new); - component.read(level, worldPosition, nbt); - - if (component.isValid()) { - customText = Optional.of(component); - nixieIndex = nbt.getInt("CustomTextIndex"); - } else { - customText = Optional.empty(); - nixieIndex = 0; - } - } - - if (customText.isEmpty()) - redstoneStrength = nbt.getInt("RedstoneStrength"); - if (clientPacket) - updateDisplayedStrings(); - } - - @Override - protected void write(CompoundTag nbt, boolean clientPacket) { - super.write(nbt, clientPacket); - - if (customText.isPresent()) { - nbt.putInt("CustomTextIndex", nixieIndex); - customText.get() - .write(nbt); - } else - nbt.putInt("RedstoneStrength", redstoneStrength); - } - - private String charOrEmpty(String string, int index) { - return string.length() <= index ? " " : string.substring(index, index + 1); - } - - @Override - public void addBehaviours(List behaviours) {} - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/RedstoneContactBlock.java b/src/main/java/com/simibubi/create/content/logistics/block/redstone/RedstoneContactBlock.java deleted file mode 100644 index 03ee8b5e6..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/RedstoneContactBlock.java +++ /dev/null @@ -1,109 +0,0 @@ -package com.simibubi.create.content.logistics.block.redstone; - -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.foundation.block.WrenchableDirectionalBlock; - -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.util.RandomSource; -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.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition.Builder; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.block.state.properties.BooleanProperty; - -@ParametersAreNonnullByDefault -@MethodsReturnNonnullByDefault -public class RedstoneContactBlock extends WrenchableDirectionalBlock { - - public static final BooleanProperty POWERED = BlockStateProperties.POWERED; - - public RedstoneContactBlock(Properties properties) { - super(properties); - registerDefaultState(defaultBlockState().setValue(POWERED, false) - .setValue(FACING, Direction.UP)); - } - - @Override - protected void createBlockStateDefinition(Builder builder) { - builder.add(POWERED); - super.createBlockStateDefinition(builder); - } - - @Override - public BlockState getStateForPlacement(BlockPlaceContext context) { - BlockState state = defaultBlockState().setValue(FACING, context.getNearestLookingDirection() - .getOpposite()); - Direction placeDirection = context.getClickedFace() - .getOpposite(); - - if ((context.getPlayer() != null && context.getPlayer() - .isShiftKeyDown()) || hasValidContact(context.getLevel(), context.getClickedPos(), placeDirection)) - state = state.setValue(FACING, placeDirection); - if (hasValidContact(context.getLevel(), context.getClickedPos(), state.getValue(FACING))) - state = state.setValue(POWERED, true); - - return state; - } - - @Override - public BlockState updateShape(BlockState stateIn, Direction facing, BlockState facingState, LevelAccessor worldIn, - BlockPos currentPos, BlockPos facingPos) { - if (facing != stateIn.getValue(FACING)) - return stateIn; - boolean hasValidContact = hasValidContact(worldIn, currentPos, facing); - if (stateIn.getValue(POWERED) != hasValidContact) { - return stateIn.setValue(POWERED, hasValidContact); - } - return stateIn; - } - - @SuppressWarnings("deprecation") - @Override - public void onRemove(BlockState state, Level worldIn, BlockPos pos, BlockState newState, boolean isMoving) { - if (state.getBlock() == this && newState.getBlock() == this) { - if (state == newState.cycle(POWERED)) - worldIn.updateNeighborsAt(pos, this); - } - super.onRemove(state, worldIn, pos, newState, isMoving); - } - - @Override - public void tick(BlockState state, ServerLevel worldIn, BlockPos pos, RandomSource random) { - boolean hasValidContact = hasValidContact(worldIn, pos, state.getValue(FACING)); - if (state.getValue(POWERED) != hasValidContact) - worldIn.setBlockAndUpdate(pos, state.setValue(POWERED, hasValidContact)); - } - - public static boolean hasValidContact(LevelAccessor world, BlockPos pos, Direction direction) { - BlockState blockState = world.getBlockState(pos.relative(direction)); - return AllBlocks.REDSTONE_CONTACT.has(blockState) && blockState.getValue(FACING) == direction.getOpposite(); - } - - @Override - public boolean isSignalSource(BlockState state) { - return state.getValue(POWERED); - } - - @Override - public boolean canConnectRedstone(BlockState state, BlockGetter world, BlockPos pos, @Nullable Direction side) { - if (side == null) - return true; - return state.getValue(FACING) != side.getOpposite(); - } - - @Override - public int getSignal(BlockState state, BlockGetter blockAccess, BlockPos pos, Direction side) { - return state.getValue(POWERED) ? 15 : 0; - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/RedstoneLinkTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/redstone/RedstoneLinkTileEntity.java deleted file mode 100644 index 408436d68..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/RedstoneLinkTileEntity.java +++ /dev/null @@ -1,130 +0,0 @@ -package com.simibubi.create.content.logistics.block.redstone; - -import java.util.List; - -import org.apache.commons.lang3.tuple.Pair; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform; -import com.simibubi.create.foundation.tileEntity.behaviour.linked.LinkBehaviour; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; - -public class RedstoneLinkTileEntity extends SmartTileEntity { - - private boolean receivedSignalChanged; - private int receivedSignal; - private int transmittedSignal; - private LinkBehaviour link; - private boolean transmitter; - - public RedstoneLinkTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - @Override - public void addBehaviours(List behaviours) {} - - @Override - public void addBehavioursDeferred(List behaviours) { - createLink(); - behaviours.add(link); - } - - protected void createLink() { - Pair slots = - ValueBoxTransform.Dual.makeSlots(RedstoneLinkFrequencySlot::new); - link = transmitter ? LinkBehaviour.transmitter(this, slots, this::getSignal) - : LinkBehaviour.receiver(this, slots, this::setSignal); - } - - public int getSignal() { - return transmittedSignal; - } - - public void setSignal(int power) { - if (receivedSignal != power) - receivedSignalChanged = true; - receivedSignal = power; - } - - public void transmit(int strength) { - transmittedSignal = strength; - if (link != null) - link.notifySignalChange(); - } - - @Override - public void write(CompoundTag compound, boolean clientPacket) { - compound.putBoolean("Transmitter", transmitter); - compound.putInt("Receive", getReceivedSignal()); - compound.putBoolean("ReceivedChanged", receivedSignalChanged); - compound.putInt("Transmit", transmittedSignal); - super.write(compound, clientPacket); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - transmitter = compound.getBoolean("Transmitter"); - super.read(compound, clientPacket); - - receivedSignal = compound.getInt("Receive"); - receivedSignalChanged = compound.getBoolean("ReceivedChanged"); - if (level == null || level.isClientSide || !link.newPosition) - transmittedSignal = compound.getInt("Transmit"); - } - - @Override - public void tick() { - super.tick(); - - if (isTransmitterBlock() != transmitter) { - transmitter = isTransmitterBlock(); - LinkBehaviour prevlink = link; - removeBehaviour(LinkBehaviour.TYPE); - createLink(); - link.copyItemsFrom(prevlink); - attachBehaviourLate(link); - } - - if (transmitter) - return; - if (level.isClientSide) - return; - - BlockState blockState = getBlockState(); - if (!AllBlocks.REDSTONE_LINK.has(blockState)) - return; - - if ((getReceivedSignal() > 0) != blockState.getValue(RedstoneLinkBlock.POWERED)) { - receivedSignalChanged = true; - level.setBlockAndUpdate(worldPosition, blockState.cycle(RedstoneLinkBlock.POWERED)); - } - - if (receivedSignalChanged) { - Direction attachedFace = blockState.getValue(RedstoneLinkBlock.FACING) - .getOpposite(); - BlockPos attachedPos = worldPosition.relative(attachedFace); - level.blockUpdated(worldPosition, level.getBlockState(worldPosition) - .getBlock()); - level.blockUpdated(attachedPos, level.getBlockState(attachedPos) - .getBlock()); - receivedSignalChanged = false; - } - } - - protected Boolean isTransmitterBlock() { - return !getBlockState().getValue(RedstoneLinkBlock.RECEIVER); - } - - public int getReceivedSignal() { - return receivedSignal; - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/StockpileSwitchBlock.java b/src/main/java/com/simibubi/create/content/logistics/block/redstone/StockpileSwitchBlock.java deleted file mode 100644 index f2152a9b5..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/StockpileSwitchBlock.java +++ /dev/null @@ -1,167 +0,0 @@ -package com.simibubi.create.content.logistics.block.redstone; - -import com.simibubi.create.AllItems; -import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; -import com.simibubi.create.foundation.block.ITE; -import com.simibubi.create.foundation.gui.ScreenOpener; -import com.simibubi.create.foundation.utility.Iterate; - -import net.minecraft.client.player.LocalPlayer; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.util.RandomSource; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -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.LevelReader; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.HorizontalDirectionalBlock; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition.Builder; -import net.minecraft.world.level.block.state.properties.IntegerProperty; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.VoxelShape; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.fluids.capability.CapabilityFluidHandler; -import net.minecraftforge.fluids.capability.IFluidHandler; -import net.minecraftforge.fml.DistExecutor; -import net.minecraftforge.items.CapabilityItemHandler; -import net.minecraftforge.items.IItemHandler; - -public class StockpileSwitchBlock extends HorizontalDirectionalBlock - implements ITE, IWrenchable { - - public static final IntegerProperty INDICATOR = IntegerProperty.create("indicator", 0, 6); - - public StockpileSwitchBlock(Properties p_i48377_1_) { - super(p_i48377_1_); - } - - @Override - public void onPlace(BlockState state, Level worldIn, BlockPos pos, BlockState oldState, boolean isMoving) { - updateObservedInventory(state, worldIn, pos); - } - - @Override - public void onNeighborChange(BlockState state, LevelReader world, BlockPos pos, BlockPos neighbor) { -// if (world.isClientSide()) -// return; -// if (!isObserving(state, pos, neighbor)) -// return; -// updateObservedInventory(state, world, pos); - } - - @Override - public VoxelShape getShape(BlockState state, BlockGetter p_220053_2_, BlockPos p_220053_3_, - CollisionContext p_220053_4_) { - return AllShapes.STOCKPILE_SWITCH.get(state.getValue(FACING)); - } - - private void updateObservedInventory(BlockState state, LevelReader world, BlockPos pos) { - withTileEntityDo(world, pos, StockpileSwitchTileEntity::updateCurrentLevel); - } - - @Override - public boolean canConnectRedstone(BlockState state, BlockGetter world, BlockPos pos, Direction side) { - return side != null && side.getOpposite() != state.getValue(FACING); - } - - @Override - public boolean isSignalSource(BlockState state) { - return true; - } - - @Override - public int getSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { - if (side == blockState.getValue(FACING) - .getOpposite()) - return 0; - return getTileEntityOptional(blockAccess, pos).filter(StockpileSwitchTileEntity::isPowered) - .map($ -> 15) - .orElse(0); - } - - @Override - public void tick(BlockState blockState, ServerLevel world, BlockPos pos, RandomSource random) { - getTileEntityOptional(world, pos).ifPresent(StockpileSwitchTileEntity::updatePowerAfterDelay); - } - - @Override - protected void createBlockStateDefinition(Builder builder) { - builder.add(FACING, INDICATOR); - super.createBlockStateDefinition(builder); - } - - @Override - public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, - BlockHitResult hit) { - if (player != null && AllItems.WRENCH.isIn(player.getItemInHand(handIn))) - return InteractionResult.PASS; - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, - () -> () -> withTileEntityDo(worldIn, pos, te -> this.displayScreen(te, player))); - return InteractionResult.SUCCESS; - } - - @OnlyIn(value = Dist.CLIENT) - protected void displayScreen(StockpileSwitchTileEntity te, Player player) { - if (player instanceof LocalPlayer) - ScreenOpener.open(new StockpileSwitchScreen(te)); - } - - @Override - public BlockState getStateForPlacement(BlockPlaceContext context) { - BlockState state = defaultBlockState(); - Capability itemCap = CapabilityItemHandler.ITEM_HANDLER_CAPABILITY; - Capability fluidCap = CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY; - - Direction preferredFacing = null; - for (Direction face : Iterate.horizontalDirections) { - BlockEntity te = context.getLevel() - .getBlockEntity(context.getClickedPos() - .relative(face)); - if (te != null && (te.getCapability(itemCap) - .isPresent() - || te.getCapability(fluidCap) - .isPresent())) - if (preferredFacing == null) - preferredFacing = face; - else { - preferredFacing = null; - break; - } - } - - if (preferredFacing != null) - return state.setValue(FACING, preferredFacing); - - Direction facing = context.getClickedFace() - .getAxis() - .isHorizontal() ? context.getClickedFace() - : context.getHorizontalDirection() - .getOpposite(); - return state.setValue(FACING, context.getPlayer() != null && context.getPlayer() - .isSteppingCarefully() ? facing.getOpposite() : facing); - } - - @Override - public Class getTileEntityClass() { - return StockpileSwitchTileEntity.class; - } - - @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.STOCKPILE_SWITCH.get(); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/StockpileSwitchObservable.java b/src/main/java/com/simibubi/create/content/logistics/block/redstone/StockpileSwitchObservable.java deleted file mode 100644 index 1c4eff748..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/StockpileSwitchObservable.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.simibubi.create.content.logistics.block.redstone; - -public interface StockpileSwitchObservable { - - public float getPercent(); - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/StockpileSwitchScreen.java b/src/main/java/com/simibubi/create/content/logistics/block/redstone/StockpileSwitchScreen.java deleted file mode 100644 index c83e45c62..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/StockpileSwitchScreen.java +++ /dev/null @@ -1,170 +0,0 @@ -package com.simibubi.create.content.logistics.block.redstone; - -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.logistics.packet.ConfigureStockswitchPacket; -import com.simibubi.create.foundation.gui.AbstractSimiScreen; -import com.simibubi.create.foundation.gui.AllGuiTextures; -import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.gui.element.GuiGameElement; -import com.simibubi.create.foundation.gui.widget.IconButton; -import com.simibubi.create.foundation.gui.widget.ScrollInput; -import com.simibubi.create.foundation.networking.AllPackets; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; - -import net.minecraft.network.chat.Component; -import net.minecraft.world.item.ItemStack; - -public class StockpileSwitchScreen extends AbstractSimiScreen { - - private ScrollInput offBelow; - private ScrollInput onAbove; - private IconButton confirmButton; - private IconButton flipSignals; - - private final Component invertSignal = Lang.translateDirect("gui.stockpile_switch.invert_signal"); - private final ItemStack renderedItem = new ItemStack(AllBlocks.STOCKPILE_SWITCH.get()); - - private AllGuiTextures background; - private StockpileSwitchTileEntity te; - private int lastModification; - - private LerpedFloat cursor; - private LerpedFloat cursorLane; - - public StockpileSwitchScreen(StockpileSwitchTileEntity te) { - super(Lang.translateDirect("gui.stockpile_switch.title")); - background = AllGuiTextures.STOCKSWITCH; - this.te = te; - lastModification = -1; - } - - @Override - protected void init() { - setWindowSize(background.width, background.height); - setWindowOffset(-20, 0); - super.init(); - - int x = guiLeft; - int y = guiTop; - - cursor = LerpedFloat.linear() - .startWithValue(te.getLevelForDisplay()); - cursorLane = LerpedFloat.linear() - .startWithValue(te.getState() ? 1 : 0); - - offBelow = new ScrollInput(x + 36, y + 40, 102, 18).withRange(0, 100) - .titled(Components.empty()) - .calling(state -> { - lastModification = 0; - offBelow.titled(Lang.translateDirect("gui.stockpile_switch.move_to_upper_at", state)); - if (onAbove.getState() <= state) { - onAbove.setState(state + 1); - onAbove.onChanged(); - } - }) - .setState((int) (te.offWhenBelow * 100)); - - onAbove = new ScrollInput(x + 36, y + 18, 102, 18).withRange(1, 101) - .titled(Components.empty()) - .calling(state -> { - lastModification = 0; - onAbove.titled(Lang.translateDirect("gui.stockpile_switch.move_to_lower_at", state)); - if (offBelow.getState() >= state) { - offBelow.setState(state - 1); - offBelow.onChanged(); - } - }) - .setState((int) (te.onWhenAbove * 100)); - - onAbove.onChanged(); - offBelow.onChanged(); - - addRenderableWidget(onAbove); - addRenderableWidget(offBelow); - - confirmButton = - new IconButton(x + background.width - 33, y + background.height - 24, AllIcons.I_CONFIRM); - confirmButton.withCallback(() -> { - onClose(); - }); - addRenderableWidget(confirmButton); - - flipSignals = new IconButton(x + 14, y + 40, AllIcons.I_FLIP); - flipSignals.withCallback(() -> { - send(!te.isInverted()); - }); - flipSignals.setToolTip(invertSignal); - addRenderableWidget(flipSignals); - } - - @Override - protected void renderWindow(PoseStack ms, int mouseX, int mouseY, float partialTicks) { - int x = guiLeft; - int y = guiTop; - - background.render(ms, x, y, this); - - AllGuiTextures.STOCKSWITCH_POWERED_LANE.render(ms, x + 36, y + (te.isInverted() ? 18 : 40), this); - AllGuiTextures.STOCKSWITCH_UNPOWERED_LANE.render(ms, x + 36, y + (te.isInverted() ? 40 : 18), this); - drawCenteredString(ms, font, title, x + (background.width - 8) / 2, y + 3, 0xFFFFFF); - - AllGuiTextures sprite = AllGuiTextures.STOCKSWITCH_INTERVAL; - float lowerBound = offBelow.getState(); - float upperBound = onAbove.getState(); - - sprite.bind(); - blit(ms, (int) (x + upperBound) + 37, y + 18, (int) (sprite.startX + upperBound), sprite.startY, - (int) (sprite.width - upperBound), sprite.height); - blit(ms, x + 37, y + 40, sprite.startX, sprite.startY, (int) (lowerBound), sprite.height); - - AllGuiTextures.STOCKSWITCH_ARROW_UP.render(ms, (int) (x + lowerBound + 36) - 2, y + 35, this); - AllGuiTextures.STOCKSWITCH_ARROW_DOWN.render(ms, (int) (x + upperBound + 36) - 3, y + 17, this); - - if (te.currentLevel != -1) { - AllGuiTextures cursor = AllGuiTextures.STOCKSWITCH_CURSOR; - ms.pushPose(); - ms.translate(Math.min(99, this.cursor.getValue(partialTicks) * sprite.width), - cursorLane.getValue(partialTicks) * 22, 0); - cursor.render(ms, x + 34, y + 19, this); - ms.popPose(); - } - - GuiGameElement.of(renderedItem) - .at(x + background.width + 6, y + background.height - 56, -200) - .scale(5) - .render(ms); - } - - @Override - public void tick() { - super.tick(); - - cursor.chase(te.getLevelForDisplay(), 1 / 4f, Chaser.EXP); - cursor.tickChaser(); - cursorLane.chase(te.getState() ? 1 : 0, 1 / 4f, Chaser.EXP); - cursorLane.tickChaser(); - - if (lastModification >= 0) - lastModification++; - - if (lastModification >= 20) { - lastModification = -1; - send(te.isInverted()); - } - } - - @Override - public void removed() { - send(te.isInverted()); - } - - protected void send(boolean invert) { - AllPackets.channel.sendToServer(new ConfigureStockswitchPacket(te.getBlockPos(), offBelow.getState() / 100f, - onAbove.getState() / 100f, invert)); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/StockpileSwitchTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/redstone/StockpileSwitchTileEntity.java deleted file mode 100644 index 1e66ec0c9..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/StockpileSwitchTileEntity.java +++ /dev/null @@ -1,237 +0,0 @@ -package com.simibubi.create.content.logistics.block.redstone; - -import java.util.List; - -import com.simibubi.create.compat.storageDrawers.StorageDrawers; -import com.simibubi.create.content.logistics.block.display.DisplayLinkBlock; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.inventory.CapManipulationBehaviourBase.InterfaceProvider; -import com.simibubi.create.foundation.tileEntity.behaviour.inventory.InvManipulationBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.inventory.TankManipulationBehaviour; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.util.Mth; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; -import net.minecraft.world.ticks.TickPriority; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.capability.IFluidHandler; -import net.minecraftforge.items.IItemHandler; - -public class StockpileSwitchTileEntity extends SmartTileEntity { - - public float onWhenAbove; - public float offWhenBelow; - public float currentLevel; - private boolean redstoneState; - private boolean inverted; - private boolean poweredAfterDelay; - - private FilteringBehaviour filtering; - private InvManipulationBehaviour observedInventory; - private TankManipulationBehaviour observedTank; - - public StockpileSwitchTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - onWhenAbove = .75f; - offWhenBelow = .25f; - currentLevel = -1; - redstoneState = false; - inverted = false; - poweredAfterDelay = false; - setLazyTickRate(10); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - onWhenAbove = compound.getFloat("OnAbove"); - offWhenBelow = compound.getFloat("OffBelow"); - currentLevel = compound.getFloat("Current"); - redstoneState = compound.getBoolean("Powered"); - inverted = compound.getBoolean("Inverted"); - poweredAfterDelay = compound.getBoolean("PoweredAfterDelay"); - super.read(compound, clientPacket); - } - - protected void writeCommon(CompoundTag compound) { - compound.putFloat("OnAbove", onWhenAbove); - compound.putFloat("OffBelow", offWhenBelow); - compound.putBoolean("Inverted", inverted); - } - - @Override - public void write(CompoundTag compound, boolean clientPacket) { - writeCommon(compound); - compound.putFloat("Current", currentLevel); - compound.putBoolean("Powered", redstoneState); - compound.putBoolean("PoweredAfterDelay", poweredAfterDelay); - super.write(compound, clientPacket); - } - - @Override - public void writeSafe(CompoundTag compound) { - writeCommon(compound); - super.writeSafe(compound); - } - - public float getStockLevel() { - return currentLevel; - } - - public void updateCurrentLevel() { - boolean changed = false; - float occupied = 0; - float totalSpace = 0; - float prevLevel = currentLevel; - - observedInventory.findNewCapability(); - observedTank.findNewCapability(); - - BlockPos target = worldPosition.relative(getBlockState().getOptionalValue(StockpileSwitchBlock.FACING) - .orElse(Direction.NORTH)); - BlockEntity targetTile = level.getBlockEntity(target); - - if (targetTile instanceof StockpileSwitchObservable observable) { - currentLevel = observable.getPercent() / 100f; - - } else if (StorageDrawers.isDrawer(targetTile) && observedInventory.hasInventory()) { - currentLevel = StorageDrawers.getTrueFillLevel(observedInventory.getInventory(), filtering); - - } else if (observedInventory.hasInventory() || observedTank.hasInventory()) { - if (observedInventory.hasInventory()) { - // Item inventory - IItemHandler inv = observedInventory.getInventory(); - for (int slot = 0; slot < inv.getSlots(); slot++) { - ItemStack stackInSlot = inv.getStackInSlot(slot); - int space = Math.min(stackInSlot.getMaxStackSize(), inv.getSlotLimit(slot)); - int count = stackInSlot.getCount(); - if (space == 0) - continue; - - totalSpace += 1; - if (filtering.test(stackInSlot)) - occupied += count * (1f / space); - } - } - - if (observedTank.hasInventory()) { - // Fluid inventory - IFluidHandler tank = observedTank.getInventory(); - for (int slot = 0; slot < tank.getTanks(); slot++) { - FluidStack stackInSlot = tank.getFluidInTank(slot); - int space = tank.getTankCapacity(slot); - int count = stackInSlot.getAmount(); - if (space == 0) - continue; - - totalSpace += 1; - if (filtering.test(stackInSlot)) - occupied += count * (1f / space); - } - } - - currentLevel = occupied / totalSpace; - - } else { - // No compatible inventories found - if (currentLevel == -1) - return; - level.setBlock(worldPosition, getBlockState().setValue(StockpileSwitchBlock.INDICATOR, 0), 3); - currentLevel = -1; - redstoneState = false; - sendData(); - scheduleBlockTick(); - return; - } - - currentLevel = Mth.clamp(currentLevel, 0, 1); - changed = currentLevel != prevLevel; - - boolean previouslyPowered = redstoneState; - if (redstoneState && currentLevel <= offWhenBelow) - redstoneState = false; - else if (!redstoneState && currentLevel >= onWhenAbove) - redstoneState = true; - boolean update = previouslyPowered != redstoneState; - - int displayLevel = 0; - if (currentLevel > 0) - displayLevel = (int) (currentLevel * 6); - level.setBlock(worldPosition, getBlockState().setValue(StockpileSwitchBlock.INDICATOR, displayLevel), - update ? 3 : 2); - - if (update) - scheduleBlockTick(); - - if (changed || update) { - DisplayLinkBlock.notifyGatherers(level, worldPosition); - notifyUpdate(); - } - } - - protected void scheduleBlockTick() { - Block block = getBlockState().getBlock(); - if (!level.getBlockTicks() - .willTickThisTick(worldPosition, block)) - level.scheduleTick(worldPosition, block, 2, TickPriority.NORMAL); - } - - @Override - public void lazyTick() { - super.lazyTick(); - if (level.isClientSide) - return; - updateCurrentLevel(); - } - - @Override - public void addBehaviours(List behaviours) { - filtering = new FilteringBehaviour(this, new FilteredDetectorFilterSlot()).moveText(new Vec3(0, 5, 0)) - .withCallback($ -> updateCurrentLevel()); - behaviours.add(filtering); - - InterfaceProvider towardBlockFacing = InterfaceProvider.towardBlockFacing(); - behaviours.add(observedInventory = new InvManipulationBehaviour(this, towardBlockFacing).bypassSidedness()); - behaviours.add(observedTank = new TankManipulationBehaviour(this, towardBlockFacing).bypassSidedness()); - } - - public float getLevelForDisplay() { - return currentLevel == -1 ? 0 : currentLevel; - } - - public boolean getState() { - return redstoneState; - } - - public boolean shouldBePowered() { - return inverted != redstoneState; - } - - public void updatePowerAfterDelay() { - poweredAfterDelay = shouldBePowered(); - level.blockUpdated(worldPosition, getBlockState().getBlock()); - } - - public boolean isPowered() { - return poweredAfterDelay; - } - - public boolean isInverted() { - return inverted; - } - - public void setInverted(boolean inverted) { - if (inverted == this.inverted) - return; - this.inverted = inverted; - updatePowerAfterDelay(); - } -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/vault/ItemVaultTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/vault/ItemVaultTileEntity.java deleted file mode 100644 index 9975112c8..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/vault/ItemVaultTileEntity.java +++ /dev/null @@ -1,312 +0,0 @@ -package com.simibubi.create.content.logistics.block.vault; - -import java.util.List; - -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.api.connectivity.ConnectivityHandler; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.tileEntity.IMultiTileContainer; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtUtils; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.ItemStackHandler; -import net.minecraftforge.items.wrapper.CombinedInvWrapper; - -public class ItemVaultTileEntity extends SmartTileEntity implements IMultiTileContainer.Inventory { - - protected LazyOptional itemCapability; - - protected ItemStackHandler inventory; - protected BlockPos controller; - protected BlockPos lastKnownPos; - protected boolean updateConnectivity; - protected int radius; - protected int length; - protected Axis axis; - - public ItemVaultTileEntity(BlockEntityType tileEntityTypeIn, BlockPos pos, BlockState state) { - super(tileEntityTypeIn, pos, state); - - inventory = new ItemStackHandler(AllConfigs.SERVER.logistics.vaultCapacity.get()) { - @Override - protected void onContentsChanged(int slot) { - super.onContentsChanged(slot); - updateComparators(); - } - }; - - itemCapability = LazyOptional.empty(); - radius = 1; - length = 1; - } - - @Override - public void addBehaviours(List behaviours) {} - - protected void updateConnectivity() { - updateConnectivity = false; - if (level.isClientSide()) - return; - if (!isController()) - return; - ConnectivityHandler.formMulti(this); - } - - protected void updateComparators() { - ItemVaultTileEntity controllerTE = getControllerTE(); - if (controllerTE == null) - return; - - level.blockEntityChanged(controllerTE.worldPosition); - - BlockPos pos = controllerTE.getBlockPos(); - for (int y = 0; y < controllerTE.radius; y++) { - for (int z = 0; z < (controllerTE.axis == Axis.X ? controllerTE.radius : controllerTE.length); z++) { - for (int x = 0; x < (controllerTE.axis == Axis.Z ? controllerTE.radius : controllerTE.length); x++) { - level.updateNeighbourForOutputSignal(pos.offset(x, y, z), getBlockState().getBlock()); - } - } - } - } - - @Override - public void tick() { - super.tick(); - - if (lastKnownPos == null) - lastKnownPos = getBlockPos(); - else if (!lastKnownPos.equals(worldPosition) && worldPosition != null) { - onPositionChanged(); - return; - } - - if (updateConnectivity) - updateConnectivity(); - } - - @Override - public BlockPos getLastKnownPos() { - return lastKnownPos; - } - - @Override - public boolean isController() { - return controller == null || worldPosition.getX() == controller.getX() - && worldPosition.getY() == controller.getY() && worldPosition.getZ() == controller.getZ(); - } - - private void onPositionChanged() { - removeController(true); - lastKnownPos = worldPosition; - } - - @SuppressWarnings("unchecked") - @Override - public ItemVaultTileEntity getControllerTE() { - if (isController()) - return this; - BlockEntity tileEntity = level.getBlockEntity(controller); - if (tileEntity instanceof ItemVaultTileEntity) - return (ItemVaultTileEntity) tileEntity; - return null; - } - - public void removeController(boolean keepContents) { - if (level.isClientSide()) - return; - updateConnectivity = true; - controller = null; - radius = 1; - length = 1; - - BlockState state = getBlockState(); - if (ItemVaultBlock.isVault(state)) { - state = state.setValue(ItemVaultBlock.LARGE, false); - getLevel().setBlock(worldPosition, state, 22); - } - - itemCapability.invalidate(); - setChanged(); - sendData(); - } - - @Override - public void setController(BlockPos controller) { - if (level.isClientSide && !isVirtual()) - return; - if (controller.equals(this.controller)) - return; - this.controller = controller; - itemCapability.invalidate(); - setChanged(); - sendData(); - } - - @Override - public BlockPos getController() { - return isController() ? worldPosition : controller; - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - super.read(compound, clientPacket); - - BlockPos controllerBefore = controller; - int prevSize = radius; - int prevLength = length; - - updateConnectivity = compound.contains("Uninitialized"); - controller = null; - lastKnownPos = null; - - if (compound.contains("LastKnownPos")) - lastKnownPos = NbtUtils.readBlockPos(compound.getCompound("LastKnownPos")); - if (compound.contains("Controller")) - controller = NbtUtils.readBlockPos(compound.getCompound("Controller")); - - if (isController()) { - radius = compound.getInt("Size"); - length = compound.getInt("Length"); - } - - if (!clientPacket) { - inventory.deserializeNBT(compound.getCompound("Inventory")); - return; - } - - boolean changeOfController = - controllerBefore == null ? controller != null : !controllerBefore.equals(controller); - if (hasLevel() && (changeOfController || prevSize != radius || prevLength != length)) - level.setBlocksDirty(getBlockPos(), Blocks.AIR.defaultBlockState(), getBlockState()); - } - - @Override - protected void write(CompoundTag compound, boolean clientPacket) { - if (updateConnectivity) - compound.putBoolean("Uninitialized", true); - if (lastKnownPos != null) - compound.put("LastKnownPos", NbtUtils.writeBlockPos(lastKnownPos)); - if (!isController()) - compound.put("Controller", NbtUtils.writeBlockPos(controller)); - if (isController()) { - compound.putInt("Size", radius); - compound.putInt("Length", length); - } - - super.write(compound, clientPacket); - - if (!clientPacket) { - compound.putString("StorageType", "CombinedInv"); - compound.put("Inventory", inventory.serializeNBT()); - } - } - - public ItemStackHandler getInventoryOfBlock() { - return inventory; - } - - public void applyInventoryToBlock(ItemStackHandler handler) { - for (int i = 0; i < inventory.getSlots(); i++) - inventory.setStackInSlot(i, i < handler.getSlots() ? handler.getStackInSlot(i) : ItemStack.EMPTY); - } - - @Override - public LazyOptional getCapability(Capability cap, Direction side) { - if (isItemHandlerCap(cap)) { - initCapability(); - return itemCapability.cast(); - } - return super.getCapability(cap, side); - } - - private void initCapability() { - if (itemCapability.isPresent()) - return; - if (!isController()) { - ItemVaultTileEntity controllerTE = getControllerTE(); - if (controllerTE == null) - return; - controllerTE.initCapability(); - itemCapability = controllerTE.itemCapability; - return; - } - - boolean alongZ = ItemVaultBlock.getVaultBlockAxis(getBlockState()) == Axis.Z; - IItemHandlerModifiable[] invs = new IItemHandlerModifiable[length * radius * radius]; - for (int yOffset = 0; yOffset < length; yOffset++) { - for (int xOffset = 0; xOffset < radius; xOffset++) { - for (int zOffset = 0; zOffset < radius; zOffset++) { - BlockPos vaultPos = alongZ ? worldPosition.offset(xOffset, zOffset, yOffset) - : worldPosition.offset(yOffset, xOffset, zOffset); - ItemVaultTileEntity vaultAt = - ConnectivityHandler.partAt(AllTileEntities.ITEM_VAULT.get(), level, vaultPos); - invs[yOffset * radius * radius + xOffset * radius + zOffset] = - vaultAt != null ? vaultAt.inventory : new ItemStackHandler(); - } - } - } - - CombinedInvWrapper combinedInvWrapper = new CombinedInvWrapper(invs); - itemCapability = LazyOptional.of(() -> combinedInvWrapper); - } - - public static int getMaxLength(int radius) { - return radius * 3; - } - - @Override - public void preventConnectivityUpdate() { updateConnectivity = false; } - - @Override - public void notifyMultiUpdated() { - BlockState state = this.getBlockState(); - if (ItemVaultBlock.isVault(state)) { // safety - level.setBlock(getBlockPos(), state.setValue(ItemVaultBlock.LARGE, radius > 2), 6); - } - itemCapability.invalidate(); - setChanged(); - } - - @Override - public Direction.Axis getMainConnectionAxis() { return getMainAxisOf(this); } - - @Override - public int getMaxLength(Direction.Axis longAxis, int width) { - if (longAxis == Direction.Axis.Y) return getMaxWidth(); - return getMaxLength(width); - } - - @Override - public int getMaxWidth() { - return 3; - } - - @Override - public int getHeight() { return length; } - - @Override - public int getWidth() { return radius; } - - @Override - public void setHeight(int height) { this.length = height; } - - @Override - public void setWidth(int width) { this.radius = width; } - - @Override - public boolean hasInventory() { return true; } -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/chute/AbstractChuteBlock.java b/src/main/java/com/simibubi/create/content/logistics/chute/AbstractChuteBlock.java similarity index 76% rename from src/main/java/com/simibubi/create/content/logistics/block/chute/AbstractChuteBlock.java rename to src/main/java/com/simibubi/create/content/logistics/chute/AbstractChuteBlock.java index ddc909bac..351f5b458 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/chute/AbstractChuteBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/chute/AbstractChuteBlock.java @@ -1,19 +1,21 @@ -package com.simibubi.create.content.logistics.block.chute; +package com.simibubi.create.content.logistics.chute; import java.util.function.Consumer; import javax.annotation.Nullable; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.content.kinetics.belt.behaviour.DirectBeltInputBehaviour; import com.simibubi.create.foundation.advancement.AdvancementBehaviour; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.block.render.ReducedDestroyEffects; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.utility.Iterate; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.Entity; @@ -34,12 +36,12 @@ import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.client.extensions.common.IClientBlockExtensions; import net.minecraftforge.common.util.LazyOptional; -public abstract class AbstractChuteBlock extends Block implements IWrenchable, ITE { +public abstract class AbstractChuteBlock extends Block implements IWrenchable, IBE { public AbstractChuteBlock(Properties p_i48440_1_) { super(p_i48440_1_); } - + @OnlyIn(Dist.CLIENT) public void initializeClient(Consumer consumer) { consumer.accept(new ReducedDestroyEffects()); @@ -79,7 +81,7 @@ public abstract class AbstractChuteBlock extends Block implements IWrenchable, I super.setPlacedBy(pLevel, pPos, pState, pPlacer, pStack); AdvancementBehaviour.setPlacedBy(pLevel, pPos, pPlacer); } - + @Override public void updateEntityAfterFallOn(BlockGetter worldIn, Entity entityIn) { super.updateEntityAfterFallOn(worldIn, entityIn); @@ -89,7 +91,7 @@ public abstract class AbstractChuteBlock extends Block implements IWrenchable, I return; if (!entityIn.isAlive()) return; - DirectBeltInputBehaviour input = TileEntityBehaviour.get(entityIn.level, new BlockPos(entityIn.position() + DirectBeltInputBehaviour input = BlockEntityBehaviour.get(entityIn.level, new BlockPos(entityIn.position() .add(0, 0.5f, 0)).below(), DirectBeltInputBehaviour.TYPE); if (input == null) return; @@ -108,9 +110,7 @@ public abstract class AbstractChuteBlock extends Block implements IWrenchable, I @Override public void onPlace(BlockState state, Level world, BlockPos pos, BlockState p_220082_4_, boolean p_220082_5_) { - withTileEntityDo(world, pos, ChuteTileEntity::onAdded); - if (p_220082_5_) - return; + withBlockEntityDo(world, pos, ChuteBlockEntity::onAdded); updateDiagonalNeighbour(state, world, pos); } @@ -125,16 +125,16 @@ public abstract class AbstractChuteBlock extends Block implements IWrenchable, I toUpdate = toUpdate.relative(facing.getOpposite()); BlockState stateToUpdate = world.getBlockState(toUpdate); - BlockState updated = updateChuteState(stateToUpdate, world.getBlockState(toUpdate.above()), world, toUpdate); - if (stateToUpdate != updated && !world.isClientSide) - world.setBlockAndUpdate(toUpdate, updated); + if (isChute(stateToUpdate) && !world.getBlockTicks() + .hasScheduledTick(toUpdate, stateToUpdate.getBlock())) + world.scheduleTick(toUpdate, stateToUpdate.getBlock(), 1); } @Override public void onRemove(BlockState state, Level world, BlockPos pos, BlockState newState, boolean isMoving) { - ITE.onRemove(state, world, pos, newState); - - if (isMoving || state.is(newState.getBlock())) + IBE.onRemove(state, world, pos, newState); + + if (state.is(newState.getBlock())) return; updateDiagonalNeighbour(state, world, pos); @@ -143,15 +143,19 @@ public abstract class AbstractChuteBlock extends Block implements IWrenchable, I BlockPos toUpdate = pos.above() .relative(direction); BlockState stateToUpdate = world.getBlockState(toUpdate); - if (!isChute(stateToUpdate)) - continue; - BlockState updated = ((AbstractChuteBlock) stateToUpdate.getBlock()).updateChuteState(stateToUpdate, - world.getBlockState(toUpdate.above()), world, toUpdate); - if (stateToUpdate != updated && !world.isClientSide) - world.setBlockAndUpdate(toUpdate, updated); + if (isChute(stateToUpdate) && !world.getBlockTicks() + .hasScheduledTick(toUpdate, stateToUpdate.getBlock())) + world.scheduleTick(toUpdate, stateToUpdate.getBlock(), 1); } } + @Override + public void tick(BlockState pState, ServerLevel pLevel, BlockPos pPos, RandomSource pRandom) { + BlockState updated = updateChuteState(pState, pLevel.getBlockState(pPos.above()), pLevel, pPos); + if (pState != updated) + pLevel.setBlockAndUpdate(pPos, updated); + } + @Override public BlockState updateShape(BlockState state, Direction direction, BlockState above, LevelAccessor world, BlockPos pos, BlockPos p_196271_6_) { @@ -165,10 +169,10 @@ public abstract class AbstractChuteBlock extends Block implements IWrenchable, I BlockPos neighbourPos, boolean p_220069_6_) { if (pos.below() .equals(neighbourPos)) - withTileEntityDo(world, pos, ChuteTileEntity::blockBelowChanged); + withBlockEntityDo(world, pos, ChuteBlockEntity::blockBelowChanged); else if (pos.above() .equals(neighbourPos)) - withTileEntityDo(world, pos, chute -> chute.capAbove = LazyOptional.empty()); + withBlockEntityDo(world, pos, chute -> chute.capAbove = LazyOptional.empty()); } public abstract BlockState updateChuteState(BlockState state, BlockState above, BlockGetter world, BlockPos pos); @@ -186,24 +190,25 @@ public abstract class AbstractChuteBlock extends Block implements IWrenchable, I } @Override - public Class getTileEntityClass() { - return ChuteTileEntity.class; + public Class getBlockEntityClass() { + return ChuteBlockEntity.class; } @Override public InteractionResult use(BlockState p_225533_1_, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult p_225533_6_) { if (!player.getItemInHand(hand) - .isEmpty()) + .isEmpty()) return InteractionResult.PASS; if (world.isClientSide) return InteractionResult.SUCCESS; - return onTileEntityUse(world, pos, te -> { - if (te.item.isEmpty()) + return onBlockEntityUse(world, pos, be -> { + if (be.item.isEmpty()) return InteractionResult.PASS; - player.getInventory().placeItemBackInInventory(te.item); - te.setItem(ItemStack.EMPTY); + player.getInventory() + .placeItemBackInInventory(be.item); + be.setItem(ItemStack.EMPTY); return InteractionResult.SUCCESS; }); } diff --git a/src/main/java/com/simibubi/create/content/logistics/chute/ChuteBlock.java b/src/main/java/com/simibubi/create/content/logistics/chute/ChuteBlock.java new file mode 100644 index 000000000..09cb3490b --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/chute/ChuteBlock.java @@ -0,0 +1,216 @@ +package com.simibubi.create.content.logistics.chute; + +import java.util.HashMap; +import java.util.Map; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.logistics.funnel.FunnelBlock; +import com.simibubi.create.foundation.block.ProperWaterloggedBlock; +import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.util.StringRepresentable; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.item.context.UseOnContext; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Mirror; +import net.minecraft.world.level.block.Rotation; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition.Builder; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.DirectionProperty; +import net.minecraft.world.level.block.state.properties.EnumProperty; +import net.minecraft.world.level.block.state.properties.Property; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.level.pathfinder.PathComputationType; +import net.minecraft.world.phys.BlockHitResult; + +public class ChuteBlock extends AbstractChuteBlock implements ProperWaterloggedBlock { + + public static final Property SHAPE = EnumProperty.create("shape", Shape.class); + public static final DirectionProperty FACING = BlockStateProperties.FACING_HOPPER; + + public ChuteBlock(Properties p_i48440_1_) { + super(p_i48440_1_); + registerDefaultState(defaultBlockState().setValue(SHAPE, Shape.NORMAL) + .setValue(FACING, Direction.DOWN) + .setValue(WATERLOGGED, false)); + } + + public enum Shape implements StringRepresentable { + INTERSECTION, WINDOW, NORMAL, ENCASED; + + @Override + public String getSerializedName() { + return Lang.asId(name()); + } + } + + @Override + public Direction getFacing(BlockState state) { + return state.getValue(FACING); + } + + @Override + public boolean isOpen(BlockState state) { + return state.getValue(FACING) == Direction.DOWN || state.getValue(SHAPE) == Shape.INTERSECTION; + } + + @Override + public boolean isTransparent(BlockState state) { + return state.getValue(SHAPE) == Shape.WINDOW; + } + + @Override + public FluidState getFluidState(BlockState pState) { + return fluidState(pState); + } + + @Override + public InteractionResult onWrenched(BlockState state, UseOnContext context) { + Shape shape = state.getValue(SHAPE); + boolean down = state.getValue(FACING) == Direction.DOWN; + if (shape == Shape.INTERSECTION) + return InteractionResult.PASS; + Level level = context.getLevel(); + if (level.isClientSide) + return InteractionResult.SUCCESS; + if (shape == Shape.ENCASED) { + level.setBlockAndUpdate(context.getClickedPos(), state.setValue(SHAPE, Shape.NORMAL)); + level.levelEvent(2001, context.getClickedPos(), + Block.getId(AllBlocks.INDUSTRIAL_IRON_BLOCK.getDefaultState())); + return InteractionResult.SUCCESS; + } + if (down) + level.setBlockAndUpdate(context.getClickedPos(), + state.setValue(SHAPE, shape != Shape.NORMAL ? Shape.NORMAL : Shape.WINDOW)); + return InteractionResult.SUCCESS; + } + + @Override + public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, + BlockHitResult hitResult) { + Shape shape = state.getValue(SHAPE); + if (!AllBlocks.INDUSTRIAL_IRON_BLOCK.isIn(player.getItemInHand(hand))) + return super.use(state, level, pos, player, hand, hitResult); + if (shape == Shape.INTERSECTION || shape == Shape.ENCASED) + return super.use(state, level, pos, player, hand, hitResult); + if (player == null || level.isClientSide) + return InteractionResult.SUCCESS; + + level.setBlockAndUpdate(pos, state.setValue(SHAPE, Shape.ENCASED)); + level.playSound(null, pos, SoundEvents.NETHERITE_BLOCK_HIT, SoundSource.BLOCKS, 0.5f, 1.05f); + return InteractionResult.SUCCESS; + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext ctx) { + BlockState state = withWater(super.getStateForPlacement(ctx), ctx); + Direction face = ctx.getClickedFace(); + if (face.getAxis() + .isHorizontal() && !ctx.isSecondaryUseActive()) { + Level world = ctx.getLevel(); + BlockPos pos = ctx.getClickedPos(); + return updateChuteState(state.setValue(FACING, face), world.getBlockState(pos.above()), world, pos); + } + return state; + } + + @Override + public BlockState updateShape(BlockState state, Direction direction, BlockState above, LevelAccessor world, + BlockPos pos, BlockPos p_196271_6_) { + updateWater(world, state, pos); + return super.updateShape(state, direction, above, world, pos, p_196271_6_); + } + + @Override + protected void createBlockStateDefinition(Builder p_206840_1_) { + super.createBlockStateDefinition(p_206840_1_.add(SHAPE, FACING, WATERLOGGED)); + } + + @Override + public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { + BlockState above = world.getBlockState(pos.above()); + return !isChute(above) || getChuteFacing(above) == Direction.DOWN; + } + + @Override + public BlockState updateChuteState(BlockState state, BlockState above, BlockGetter world, BlockPos pos) { + if (!(state.getBlock() instanceof ChuteBlock)) + return state; + + Map connections = new HashMap<>(); + int amtConnections = 0; + Direction facing = state.getValue(FACING); + boolean vertical = facing == Direction.DOWN; + + if (!vertical) { + BlockState target = world.getBlockState(pos.below() + .relative(facing.getOpposite())); + if (!isChute(target)) + return state.setValue(FACING, Direction.DOWN) + .setValue(SHAPE, Shape.NORMAL); + } + + for (Direction direction : Iterate.horizontalDirections) { + BlockState diagonalInputChute = world.getBlockState(pos.above() + .relative(direction)); + boolean value = + diagonalInputChute.getBlock() instanceof ChuteBlock && diagonalInputChute.getValue(FACING) == direction; + connections.put(direction, value); + if (value) + amtConnections++; + } + + boolean noConnections = amtConnections == 0; + if (vertical) + return state.setValue(SHAPE, + noConnections ? state.getValue(SHAPE) == Shape.INTERSECTION ? Shape.NORMAL : state.getValue(SHAPE) + : Shape.INTERSECTION); + if (noConnections) + return state.setValue(SHAPE, Shape.INTERSECTION); + if (connections.get(Direction.NORTH) && connections.get(Direction.SOUTH)) + return state.setValue(SHAPE, Shape.INTERSECTION); + if (connections.get(Direction.EAST) && connections.get(Direction.WEST)) + return state.setValue(SHAPE, Shape.INTERSECTION); + if (amtConnections == 1 && connections.get(facing) && !(getChuteFacing(above) == Direction.DOWN) + && !(above.getBlock() instanceof FunnelBlock && FunnelBlock.getFunnelFacing(above) == Direction.DOWN)) + return state.setValue(SHAPE, state.getValue(SHAPE) == Shape.ENCASED ? Shape.ENCASED : Shape.NORMAL); + return state.setValue(SHAPE, Shape.INTERSECTION); + } + + @Override + public BlockState rotate(BlockState pState, Rotation pRot) { + return pState.setValue(FACING, pRot.rotate(pState.getValue(FACING))); + } + + @Override + @SuppressWarnings("deprecation") + public BlockState mirror(BlockState pState, Mirror pMirror) { + return pState.rotate(pMirror.getRotation(pState.getValue(FACING))); + } + + @Override + public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) { + return false; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.CHUTE.get(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/chute/ChuteBlockEntity.java b/src/main/java/com/simibubi/create/content/logistics/chute/ChuteBlockEntity.java new file mode 100644 index 000000000..0a1a4fd5f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/chute/ChuteBlockEntity.java @@ -0,0 +1,790 @@ +package com.simibubi.create.content.logistics.chute; + +import java.util.LinkedList; +import java.util.List; +import java.util.function.Predicate; + +import javax.annotation.Nullable; +import javax.annotation.ParametersAreNonnullByDefault; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.Create; +import com.simibubi.create.content.equipment.goggles.IHaveGoggleInformation; +import com.simibubi.create.content.kinetics.belt.behaviour.DirectBeltInputBehaviour; +import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour; +import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour.TransportedResult; +import com.simibubi.create.content.kinetics.fan.AirCurrent; +import com.simibubi.create.content.kinetics.fan.EncasedFanBlock; +import com.simibubi.create.content.kinetics.fan.EncasedFanBlockEntity; +import com.simibubi.create.content.logistics.funnel.FunnelBlock; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.item.ItemHelper; +import com.simibubi.create.foundation.item.ItemHelper.ExtractionCountMode; +import com.simibubi.create.foundation.particle.AirParticleData; +import com.simibubi.create.foundation.utility.BlockHelper; +import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.minecraft.ChatFormatting; +import net.minecraft.MethodsReturnNonnullByDefault; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.particles.ItemParticleOption; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.util.Mth; +import net.minecraft.world.Containers; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemHandlerHelper; + +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +/* + * Commented Code: Chutes create air streams and act similarly to encased fans + * (Unfinished) + */ +public class ChuteBlockEntity extends SmartBlockEntity implements IHaveGoggleInformation { // , IAirCurrentSource { + + // public AirCurrent airCurrent; + + float pull; + float push; + + ItemStack item; + LerpedFloat itemPosition; + ChuteItemHandler itemHandler; + LazyOptional lazyHandler; + boolean canPickUpItems; + + float bottomPullDistance; + float beltBelowOffset; + TransportedItemStackHandlerBehaviour beltBelow; + boolean updateAirFlow; + int airCurrentUpdateCooldown; + int entitySearchCooldown; + + LazyOptional capAbove; + LazyOptional capBelow; + + public ChuteBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + item = ItemStack.EMPTY; + itemPosition = LerpedFloat.linear(); + itemHandler = new ChuteItemHandler(this); + lazyHandler = LazyOptional.of(() -> itemHandler); + canPickUpItems = false; + capAbove = LazyOptional.empty(); + capBelow = LazyOptional.empty(); + bottomPullDistance = 0; + // airCurrent = new AirCurrent(this); + updateAirFlow = true; + } + + @Override + public void addBehaviours(List behaviours) { + behaviours.add(new DirectBeltInputBehaviour(this).onlyInsertWhen((d) -> canDirectlyInsertCached())); + registerAwardables(behaviours, AllAdvancements.CHUTE); + } + + // Cached per-tick, useful when a lot of items are waiting on top of it + public boolean canDirectlyInsertCached() { + return canPickUpItems; + } + + private boolean canDirectlyInsert() { + BlockState blockState = getBlockState(); + BlockState blockStateAbove = level.getBlockState(worldPosition.above()); + if (!AbstractChuteBlock.isChute(blockState)) + return false; + if (AbstractChuteBlock.getChuteFacing(blockStateAbove) == Direction.DOWN) + return false; + if (getItemMotion() > 0 && getInputChutes().isEmpty()) + return false; + return AbstractChuteBlock.isOpenChute(blockState); + } + + @Override + public void initialize() { + super.initialize(); + onAdded(); + } + + @Override + protected AABB createRenderBoundingBox() { + return new AABB(worldPosition).expandTowards(0, -3, 0); + } + + @Override + public void tick() { + super.tick(); + + if (!level.isClientSide) + canPickUpItems = canDirectlyInsert(); + + boolean clientSide = level != null && level.isClientSide && !isVirtual(); + float itemMotion = getItemMotion(); + if (itemMotion != 0 && level != null && level.isClientSide) + spawnParticles(itemMotion); + tickAirStreams(itemMotion); + + if (item.isEmpty() && !clientSide) { + if (itemMotion < 0) + handleInputFromAbove(); + if (itemMotion > 0) + handleInputFromBelow(); + return; + } + + float nextOffset = itemPosition.getValue() + itemMotion; + + if (itemMotion < 0) { + if (nextOffset < .5f) { + if (!handleDownwardOutput(true)) + nextOffset = .5f; + else if (nextOffset < 0) { + handleDownwardOutput(clientSide); + nextOffset = itemPosition.getValue(); + } + } + } else if (itemMotion > 0) { + if (nextOffset > .5f) { + if (!handleUpwardOutput(true)) + nextOffset = .5f; + else if (nextOffset > 1) { + handleUpwardOutput(clientSide); + nextOffset = itemPosition.getValue(); + } + } + } + + itemPosition.setValue(nextOffset); + } + + private void updateAirFlow(float itemSpeed) { + updateAirFlow = false; + // airCurrent.rebuild(); + if (itemSpeed > 0 && level != null && !level.isClientSide) { + float speed = pull - push; + beltBelow = null; + + float maxPullDistance; + if (speed >= 128) + maxPullDistance = 3; + else if (speed >= 64) + maxPullDistance = 2; + else if (speed >= 32) + maxPullDistance = 1; + else + maxPullDistance = Mth.lerp(speed / 32, 0, 1); + + if (AbstractChuteBlock.isChute(level.getBlockState(worldPosition.below()))) + maxPullDistance = 0; + float flowLimit = maxPullDistance; + if (flowLimit > 0) + flowLimit = AirCurrent.getFlowLimit(level, worldPosition, maxPullDistance, Direction.DOWN); + + for (int i = 1; i <= flowLimit + 1; i++) { + TransportedItemStackHandlerBehaviour behaviour = + BlockEntityBehaviour.get(level, worldPosition.below(i), TransportedItemStackHandlerBehaviour.TYPE); + if (behaviour == null) + continue; + beltBelow = behaviour; + beltBelowOffset = i - 1; + break; + } + this.bottomPullDistance = Math.max(0, flowLimit); + } + sendData(); + } + + private void findEntities(float itemSpeed) { + // if (getSpeed() != 0) + // airCurrent.findEntities(); + if (bottomPullDistance <= 0 && !getItem().isEmpty() || itemSpeed <= 0 || level == null || level.isClientSide) + return; + if (!canCollectItemsFromBelow()) + return; + Vec3 center = VecHelper.getCenterOf(worldPosition); + AABB searchArea = new AABB(center.add(0, -bottomPullDistance - 0.5, 0), center.add(0, -0.5, 0)).inflate(.45f); + for (ItemEntity itemEntity : level.getEntitiesOfClass(ItemEntity.class, searchArea)) { + if (!itemEntity.isAlive()) + continue; + ItemStack entityItem = itemEntity.getItem(); + if (!canAcceptItem(entityItem)) + continue; + setItem(entityItem.copy(), (float) (itemEntity.getBoundingBox() + .getCenter().y - worldPosition.getY())); + itemEntity.discard(); + break; + } + } + + private void extractFromBelt(float itemSpeed) { + if (itemSpeed <= 0 || level == null || level.isClientSide) + return; + if (getItem().isEmpty() && beltBelow != null) { + beltBelow.handleCenteredProcessingOnAllItems(.5f, ts -> { + if (canAcceptItem(ts.stack)) { + setItem(ts.stack.copy(), -beltBelowOffset); + return TransportedResult.removeItem(); + } + return TransportedResult.doNothing(); + }); + } + } + + private void tickAirStreams(float itemSpeed) { + if (!level.isClientSide && airCurrentUpdateCooldown-- <= 0) { + airCurrentUpdateCooldown = AllConfigs.server().kinetics.fanBlockCheckRate.get(); + updateAirFlow = true; + } + + if (updateAirFlow) { + updateAirFlow(itemSpeed); + } + + if (entitySearchCooldown-- <= 0 && item.isEmpty()) { + entitySearchCooldown = 5; + findEntities(itemSpeed); + } + + extractFromBelt(itemSpeed); + // if (getSpeed() != 0) + // airCurrent.tick(); + } + + public void blockBelowChanged() { + updateAirFlow = true; + capBelow = LazyOptional.empty(); + } + + private void spawnParticles(float itemMotion) { + // todo: reduce the amount of particles + if (level == null) + return; + BlockState blockState = getBlockState(); + boolean up = itemMotion > 0; + float absMotion = up ? itemMotion : -itemMotion; + if (blockState == null || !AbstractChuteBlock.isChute(blockState)) + return; + if (push == 0 && pull == 0) + return; + + if (up && AbstractChuteBlock.isOpenChute(blockState) + && BlockHelper.noCollisionInSpace(level, worldPosition.above())) + spawnAirFlow(1, 2, absMotion, .5f); + + if (AbstractChuteBlock.getChuteFacing(blockState) != Direction.DOWN) + return; + + if (AbstractChuteBlock.isTransparentChute(blockState)) + spawnAirFlow(up ? 0 : 1, up ? 1 : 0, absMotion, 1); + + if (!up && BlockHelper.noCollisionInSpace(level, worldPosition.below())) + spawnAirFlow(0, -1, absMotion, .5f); + + if (up && canCollectItemsFromBelow() && bottomPullDistance > 0) { + spawnAirFlow(-bottomPullDistance, 0, absMotion, 2); + spawnAirFlow(-bottomPullDistance, 0, absMotion, 2); + } + } + + private void spawnAirFlow(float verticalStart, float verticalEnd, float motion, float drag) { + if (level == null) + return; + AirParticleData airParticleData = new AirParticleData(drag, motion); + Vec3 origin = Vec3.atLowerCornerOf(worldPosition); + float xOff = Create.RANDOM.nextFloat() * .5f + .25f; + float zOff = Create.RANDOM.nextFloat() * .5f + .25f; + Vec3 v = origin.add(xOff, verticalStart, zOff); + Vec3 d = origin.add(xOff, verticalEnd, zOff) + .subtract(v); + if (Create.RANDOM.nextFloat() < 2 * motion) + level.addAlwaysVisibleParticle(airParticleData, v.x, v.y, v.z, d.x, d.y, d.z); + } + + private void handleInputFromAbove() { + if (!capAbove.isPresent()) + capAbove = grabCapability(Direction.UP); + handleInput(capAbove.orElse(null), 1); + } + + private void handleInputFromBelow() { + if (!capBelow.isPresent()) + capBelow = grabCapability(Direction.DOWN); + handleInput(capBelow.orElse(null), 0); + } + + private void handleInput(IItemHandler inv, float startLocation) { + if (inv == null) + return; + Predicate canAccept = this::canAcceptItem; + int count = getExtractionAmount(); + ExtractionCountMode mode = getExtractionMode(); + if (mode == ExtractionCountMode.UPTO || !ItemHelper.extract(inv, canAccept, mode, count, true) + .isEmpty()) { + ItemStack extracted = ItemHelper.extract(inv, canAccept, mode, count, false); + if (!extracted.isEmpty()) + setItem(extracted, startLocation); + } + } + + private boolean handleDownwardOutput(boolean simulate) { + BlockState blockState = getBlockState(); + ChuteBlockEntity targetChute = getTargetChute(blockState); + Direction direction = AbstractChuteBlock.getChuteFacing(blockState); + + if (level == null || direction == null || !this.canOutputItems()) + return false; + if (!capBelow.isPresent()) + capBelow = grabCapability(Direction.DOWN); + if (capBelow.isPresent()) { + if (level.isClientSide && !isVirtual()) + return false; + ItemStack remainder = ItemHandlerHelper.insertItemStacked(capBelow.orElse(null), item, simulate); + ItemStack held = getItem(); + if (!simulate) + setItem(remainder, itemPosition.getValue(0)); + if (remainder.getCount() != held.getCount()) + return true; + if (direction == Direction.DOWN) + return false; + } + + if (targetChute != null) { + boolean canInsert = targetChute.canAcceptItem(item); + if (!simulate && canInsert) { + targetChute.setItem(item, direction == Direction.DOWN ? 1 : .51f); + setItem(ItemStack.EMPTY); + } + return canInsert; + } + + // Diagonal chutes cannot drop items + if (direction.getAxis() + .isHorizontal()) + return false; + + if (FunnelBlock.getFunnelFacing(level.getBlockState(worldPosition.below())) == Direction.DOWN) + return false; + if (Block.canSupportRigidBlock(level, worldPosition.below())) + return false; + + if (!simulate) { + Vec3 dropVec = VecHelper.getCenterOf(worldPosition) + .add(0, -12 / 16f, 0); + ItemEntity dropped = new ItemEntity(level, dropVec.x, dropVec.y, dropVec.z, item.copy()); + dropped.setDefaultPickUpDelay(); + dropped.setDeltaMovement(0, -.25f, 0); + level.addFreshEntity(dropped); + setItem(ItemStack.EMPTY); + } + + return true; + } + + private boolean handleUpwardOutput(boolean simulate) { + BlockState stateAbove = level.getBlockState(worldPosition.above()); + + if (level == null || !this.canOutputItems()) + return false; + + if (AbstractChuteBlock.isOpenChute(getBlockState())) { + if (!capAbove.isPresent()) + capAbove = grabCapability(Direction.UP); + if (capAbove.isPresent()) { + if (level.isClientSide && !isVirtual() && !ChuteBlock.isChute(stateAbove)) + return false; + int countBefore = item.getCount(); + ItemStack remainder = ItemHandlerHelper.insertItemStacked(capAbove.orElse(null), item, simulate); + if (!simulate) + item = remainder; + return countBefore != remainder.getCount(); + } + } + + ChuteBlockEntity bestOutput = null; + List inputChutes = getInputChutes(); + for (ChuteBlockEntity targetChute : inputChutes) { + if (!targetChute.canAcceptItem(item)) + continue; + float itemMotion = targetChute.getItemMotion(); + if (itemMotion < 0) + continue; + if (bestOutput == null || bestOutput.getItemMotion() < itemMotion) { + bestOutput = targetChute; + } + } + + if (bestOutput != null) { + if (!simulate) { + bestOutput.setItem(item, 0); + setItem(ItemStack.EMPTY); + } + return true; + } + + if (FunnelBlock.getFunnelFacing(level.getBlockState(worldPosition.above())) == Direction.UP) + return false; + if (BlockHelper.hasBlockSolidSide(stateAbove, level, worldPosition.above(), Direction.DOWN)) + return false; + if (!inputChutes.isEmpty()) + return false; + + if (!simulate) { + Vec3 dropVec = VecHelper.getCenterOf(worldPosition) + .add(0, 8 / 16f, 0); + ItemEntity dropped = new ItemEntity(level, dropVec.x, dropVec.y, dropVec.z, item.copy()); + dropped.setDefaultPickUpDelay(); + dropped.setDeltaMovement(0, getItemMotion() * 2, 0); + level.addFreshEntity(dropped); + setItem(ItemStack.EMPTY); + } + return true; + } + + protected boolean canAcceptItem(ItemStack stack) { + return item.isEmpty(); + } + + protected int getExtractionAmount() { + return 16; + } + + protected ExtractionCountMode getExtractionMode() { + return ExtractionCountMode.UPTO; + } + + protected boolean canCollectItemsFromBelow() { + return true; + } + + protected boolean canOutputItems() { + return true; + } + + private LazyOptional grabCapability(Direction side) { + BlockPos pos = this.worldPosition.relative(side); + if (level == null) + return LazyOptional.empty(); + BlockEntity be = level.getBlockEntity(pos); + if (be == null) + return LazyOptional.empty(); + if (be instanceof ChuteBlockEntity) { + if (side != Direction.DOWN || !(be instanceof SmartChuteBlockEntity) || getItemMotion() > 0) + return LazyOptional.empty(); + } + return be.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side.getOpposite()); + } + + public void setItem(ItemStack stack) { + setItem(stack, getItemMotion() < 0 ? 1 : 0); + } + + public void setItem(ItemStack stack, float insertionPos) { + item = stack; + itemPosition.startWithValue(insertionPos); + if (!level.isClientSide) { + notifyUpdate(); + award(AllAdvancements.CHUTE); + } + } + + @Override + public void invalidate() { + if (lazyHandler != null) + lazyHandler.invalidate(); + super.invalidate(); + } + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + compound.put("Item", item.serializeNBT()); + compound.putFloat("ItemPosition", itemPosition.getValue()); + compound.putFloat("Pull", pull); + compound.putFloat("Push", push); + compound.putFloat("BottomAirFlowDistance", bottomPullDistance); + super.write(compound, clientPacket); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + ItemStack previousItem = item; + item = ItemStack.of(compound.getCompound("Item")); + itemPosition.startWithValue(compound.getFloat("ItemPosition")); + pull = compound.getFloat("Pull"); + push = compound.getFloat("Push"); + bottomPullDistance = compound.getFloat("BottomAirFlowDistance"); + super.read(compound, clientPacket); +// if (clientPacket) +// airCurrent.rebuild(); + + if (hasLevel() && level != null && level.isClientSide && !previousItem.equals(item, false) && !item.isEmpty()) { + if (level.random.nextInt(3) != 0) + return; + Vec3 p = VecHelper.getCenterOf(worldPosition); + p = VecHelper.offsetRandomly(p, level.random, .5f); + Vec3 m = Vec3.ZERO; + level.addParticle(new ItemParticleOption(ParticleTypes.ITEM, item), p.x, p.y, p.z, m.x, m.y, m.z); + } + } + + public float getItemMotion() { + // Chutes per second + final float fanSpeedModifier = 1 / 64f; + final float maxItemSpeed = 20f; + final float gravity = 4f; + + float motion = (push + pull) * fanSpeedModifier; + return (Mth.clamp(motion, -maxItemSpeed, maxItemSpeed) + (motion <= 0 ? -gravity : 0)) / 20f; + } + + @Override + public void destroy() { + super.destroy(); + ChuteBlockEntity targetChute = getTargetChute(getBlockState()); + List inputChutes = getInputChutes(); + if (!item.isEmpty() && level != null) + Containers.dropItemStack(level, worldPosition.getX(), worldPosition.getY(), worldPosition.getZ(), item); + setRemoved(); + if (targetChute != null) { + targetChute.updatePull(); + targetChute.propagatePush(); + } + inputChutes.forEach(c -> c.updatePush(inputChutes.size())); + } + + public void onAdded() { + refreshBlockState(); + updatePull(); + ChuteBlockEntity targetChute = getTargetChute(getBlockState()); + if (targetChute != null) + targetChute.propagatePush(); + else + updatePush(1); + } + + public void updatePull() { + float totalPull = calculatePull(); + if (pull == totalPull) + return; + pull = totalPull; + updateAirFlow = true; + sendData(); + ChuteBlockEntity targetChute = getTargetChute(getBlockState()); + if (targetChute != null) + targetChute.updatePull(); + } + + public void updatePush(int branchCount) { + float totalPush = calculatePush(branchCount); + if (push == totalPush) + return; + updateAirFlow = true; + push = totalPush; + sendData(); + propagatePush(); + } + + public void propagatePush() { + List inputs = getInputChutes(); + inputs.forEach(c -> c.updatePush(inputs.size())); + } + + protected float calculatePull() { + BlockState blockStateAbove = level.getBlockState(worldPosition.above()); + if (AllBlocks.ENCASED_FAN.has(blockStateAbove) + && blockStateAbove.getValue(EncasedFanBlock.FACING) == Direction.DOWN) { + BlockEntity be = level.getBlockEntity(worldPosition.above()); + if (be instanceof EncasedFanBlockEntity && !be.isRemoved()) { + EncasedFanBlockEntity fan = (EncasedFanBlockEntity) be; + return fan.getSpeed(); + } + } + + float totalPull = 0; + for (Direction d : Iterate.directions) { + ChuteBlockEntity inputChute = getInputChute(d); + if (inputChute == null) + continue; + totalPull += inputChute.pull; + } + return totalPull; + } + + protected float calculatePush(int branchCount) { + if (level == null) + return 0; + BlockState blockStateBelow = level.getBlockState(worldPosition.below()); + if (AllBlocks.ENCASED_FAN.has(blockStateBelow) + && blockStateBelow.getValue(EncasedFanBlock.FACING) == Direction.UP) { + BlockEntity be = level.getBlockEntity(worldPosition.below()); + if (be instanceof EncasedFanBlockEntity && !be.isRemoved()) { + EncasedFanBlockEntity fan = (EncasedFanBlockEntity) be; + return fan.getSpeed(); + } + } + + ChuteBlockEntity targetChute = getTargetChute(getBlockState()); + if (targetChute == null) + return 0; + return targetChute.push / branchCount; + } + + @Nullable + private ChuteBlockEntity getTargetChute(BlockState state) { + if (level == null) + return null; + Direction targetDirection = AbstractChuteBlock.getChuteFacing(state); + if (targetDirection == null) + return null; + BlockPos chutePos = worldPosition.below(); + if (targetDirection.getAxis() + .isHorizontal()) + chutePos = chutePos.relative(targetDirection.getOpposite()); + BlockState chuteState = level.getBlockState(chutePos); + if (!AbstractChuteBlock.isChute(chuteState)) + return null; + BlockEntity be = level.getBlockEntity(chutePos); + if (be instanceof ChuteBlockEntity) + return (ChuteBlockEntity) be; + return null; + } + + private List getInputChutes() { + List inputs = new LinkedList<>(); + for (Direction d : Iterate.directions) { + ChuteBlockEntity inputChute = getInputChute(d); + if (inputChute == null) + continue; + inputs.add(inputChute); + } + return inputs; + } + + @Nullable + private ChuteBlockEntity getInputChute(Direction direction) { + if (level == null || direction == Direction.DOWN) + return null; + direction = direction.getOpposite(); + BlockPos chutePos = worldPosition.above(); + if (direction.getAxis() + .isHorizontal()) + chutePos = chutePos.relative(direction); + BlockState chuteState = level.getBlockState(chutePos); + Direction chuteFacing = AbstractChuteBlock.getChuteFacing(chuteState); + if (chuteFacing != direction) + return null; + BlockEntity be = level.getBlockEntity(chutePos); + if (be instanceof ChuteBlockEntity && !be.isRemoved()) + return (ChuteBlockEntity) be; + return null; + } + + public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { + boolean downward = getItemMotion() < 0; + Lang.translate("tooltip.chute.header") + .forGoggles(tooltip); + + if (pull == 0 && push == 0) + Lang.translate("tooltip.chute.no_fans_attached") + .style(ChatFormatting.GRAY) + .forGoggles(tooltip); + if (pull != 0) + Lang.translate("tooltip.chute.fans_" + (pull > 0 ? "pull_up" : "push_down")) + .style(ChatFormatting.GRAY) + .forGoggles(tooltip); + if (push != 0) + Lang.translate("tooltip.chute.fans_" + (push > 0 ? "push_up" : "pull_down")) + .style(ChatFormatting.GRAY) + .forGoggles(tooltip); + + Lang.text("-> ") + .add(Lang.translate("tooltip.chute.items_move_" + (downward ? "down" : "up"))) + .style(ChatFormatting.YELLOW) + .forGoggles(tooltip); + if (!item.isEmpty()) + Lang.translate("tooltip.chute.contains", Components.translatable(item.getDescriptionId()) + .getString(), item.getCount()) + .style(ChatFormatting.GREEN) + .forGoggles(tooltip); + + return true; + } + + @Override + public LazyOptional getCapability(Capability cap, @Nullable Direction side) { + if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) + return lazyHandler.cast(); + return super.getCapability(cap, side); + } + + public ItemStack getItem() { + return item; + } + + // @Override + // @Nullable + // public AirCurrent getAirCurrent() { + // return airCurrent; + // } + // + // @Nullable + // @Override + // public World getAirCurrentWorld() { + // return world; + // } + // + // @Override + // public BlockPos getAirCurrentPos() { + // return pos; + // } + // + // @Override + // public float getSpeed() { + // if (getBlockState().get(ChuteBlock.SHAPE) == Shape.NORMAL && + // getBlockState().get(ChuteBlock.FACING) != Direction.DOWN) + // return 0; + // return pull + push; + // } + // + // @Override + // @Nullable + // public Direction getAirFlowDirection() { + // float speed = getSpeed(); + // if (speed == 0) + // return null; + // return speed > 0 ? Direction.UP : Direction.DOWN; + // } + // + // @Override + // public boolean isSourceRemoved() { + // return removed; + // } + // + // @Override + // public Direction getAirflowOriginSide() { + // return world != null && !(world.getBlockEntity(pos.down()) instanceof + // IAirCurrentSource) + // && getBlockState().get(ChuteBlock.FACING) == Direction.DOWN ? Direction.DOWN + // : Direction.UP; + // } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/chute/ChuteGenerator.java b/src/main/java/com/simibubi/create/content/logistics/chute/ChuteGenerator.java similarity index 75% rename from src/main/java/com/simibubi/create/content/logistics/block/chute/ChuteGenerator.java rename to src/main/java/com/simibubi/create/content/logistics/chute/ChuteGenerator.java index a7e637f1e..6c7098f23 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/chute/ChuteGenerator.java +++ b/src/main/java/com/simibubi/create/content/logistics/chute/ChuteGenerator.java @@ -1,6 +1,6 @@ -package com.simibubi.create.content.logistics.block.chute; +package com.simibubi.create.content.logistics.chute; -import com.simibubi.create.content.logistics.block.chute.ChuteBlock.Shape; +import com.simibubi.create.content.logistics.chute.ChuteBlock.Shape; import com.simibubi.create.foundation.data.AssetLookup; import com.simibubi.create.foundation.data.SpecialBlockStateGen; import com.tterrag.registrate.providers.DataGenContext; @@ -31,10 +31,12 @@ public class ChuteGenerator extends SpecialBlockStateGen { if (!horizontal) return shape == Shape.NORMAL ? AssetLookup.partialBaseModel(ctx, prov) - : shape == Shape.INTERSECTION ? AssetLookup.partialBaseModel(ctx, prov, "intersection") + : shape == Shape.INTERSECTION || shape == Shape.ENCASED + ? AssetLookup.partialBaseModel(ctx, prov, "intersection") : AssetLookup.partialBaseModel(ctx, prov, "windowed"); return shape == Shape.INTERSECTION ? AssetLookup.partialBaseModel(ctx, prov, "diagonal", "intersection") - : AssetLookup.partialBaseModel(ctx, prov, "diagonal"); + : shape == Shape.ENCASED ? AssetLookup.partialBaseModel(ctx, prov, "diagonal", "encased") + : AssetLookup.partialBaseModel(ctx, prov, "diagonal"); } } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/chute/ChuteItem.java b/src/main/java/com/simibubi/create/content/logistics/chute/ChuteItem.java similarity index 81% rename from src/main/java/com/simibubi/create/content/logistics/block/chute/ChuteItem.java rename to src/main/java/com/simibubi/create/content/logistics/chute/ChuteItem.java index 926e4b147..0ece9042e 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/chute/ChuteItem.java +++ b/src/main/java/com/simibubi/create/content/logistics/chute/ChuteItem.java @@ -1,4 +1,6 @@ -package com.simibubi.create.content.logistics.block.chute; +package com.simibubi.create.content.logistics.chute; + +import com.simibubi.create.foundation.block.ProperWaterloggedBlock; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -41,8 +43,11 @@ public class ChuteItem extends BlockItem { return InteractionResult.FAIL; AbstractChuteBlock block = (AbstractChuteBlock) blockState.getBlock(); if (block.getFacing(blockState) == Direction.DOWN) { - world.setBlockAndUpdate(correctPos, block.updateChuteState(blockState.setValue(ChuteBlock.FACING, face), - world.getBlockState(correctPos.above()), world, correctPos)); + world.setBlockAndUpdate(correctPos, + ProperWaterloggedBlock.withWater(world, + block.updateChuteState(blockState.setValue(ChuteBlock.FACING, face), + world.getBlockState(correctPos.above()), world, correctPos), + correctPos)); return InteractionResult.SUCCESS; } return InteractionResult.FAIL; diff --git a/src/main/java/com/simibubi/create/content/logistics/chute/ChuteItemHandler.java b/src/main/java/com/simibubi/create/content/logistics/chute/ChuteItemHandler.java new file mode 100644 index 000000000..72a77ff01 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/chute/ChuteItemHandler.java @@ -0,0 +1,52 @@ +package com.simibubi.create.content.logistics.chute; + +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.items.IItemHandler; + +public class ChuteItemHandler implements IItemHandler { + + private ChuteBlockEntity blockEntity; + + public ChuteItemHandler(ChuteBlockEntity be) { + this.blockEntity = be; + } + + @Override + public int getSlots() { + return 1; + } + + @Override + public ItemStack getStackInSlot(int slot) { + return blockEntity.item; + } + + @Override + public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) { + if (!blockEntity.canAcceptItem(stack)) + return stack; + if (!simulate) + blockEntity.setItem(stack); + return ItemStack.EMPTY; + } + + @Override + public ItemStack extractItem(int slot, int amount, boolean simulate) { + ItemStack remainder = blockEntity.item.copy(); + ItemStack split = remainder.split(amount); + if (!simulate) + blockEntity.setItem(remainder); + return split; + } + + @Override + public int getSlotLimit(int slot) { + return Math.min(64, getStackInSlot(slot).getMaxStackSize()); + } + + @Override + public boolean isItemValid(int slot, ItemStack stack) { + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/chute/ChuteRenderer.java b/src/main/java/com/simibubi/create/content/logistics/chute/ChuteRenderer.java new file mode 100644 index 000000000..c04a44e1c --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/chute/ChuteRenderer.java @@ -0,0 +1,52 @@ +package com.simibubi.create.content.logistics.chute; + +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.content.logistics.chute.ChuteBlock.Shape; +import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.block.model.ItemTransforms.TransformType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.client.renderer.entity.ItemRenderer; +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.state.BlockState; + +public class ChuteRenderer extends SafeBlockEntityRenderer { + + public ChuteRenderer(BlockEntityRendererProvider.Context context) {} + + @Override + protected void renderSafe(ChuteBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light, + int overlay) { + if (be.item.isEmpty()) + return; + BlockState blockState = be.getBlockState(); + if (blockState.getValue(ChuteBlock.FACING) != Direction.DOWN) + return; + if (blockState.getValue(ChuteBlock.SHAPE) != Shape.WINDOW + && (be.bottomPullDistance == 0 || be.itemPosition.getValue(partialTicks) > .5f)) + return; + + renderItem(be, partialTicks, ms, buffer, light, overlay); + } + + public static void renderItem(ChuteBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + ItemRenderer itemRenderer = Minecraft.getInstance() + .getItemRenderer(); + TransformStack msr = TransformStack.cast(ms); + ms.pushPose(); + msr.centre(); + float itemScale = .5f; + float itemPosition = be.itemPosition.getValue(partialTicks); + ms.translate(0, -.5 + itemPosition, 0); + ms.scale(itemScale, itemScale, itemScale); + msr.rotateX(itemPosition * 180); + msr.rotateY(itemPosition * 180); + itemRenderer.renderStatic(be.item, TransformType.FIXED, light, overlay, ms, buffer, 0); + ms.popPose(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/chute/ChuteShapes.java b/src/main/java/com/simibubi/create/content/logistics/chute/ChuteShapes.java similarity index 90% rename from src/main/java/com/simibubi/create/content/logistics/block/chute/ChuteShapes.java rename to src/main/java/com/simibubi/create/content/logistics/chute/ChuteShapes.java index 9a34c9018..6d6735a41 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/chute/ChuteShapes.java +++ b/src/main/java/com/simibubi/create/content/logistics/chute/ChuteShapes.java @@ -1,11 +1,11 @@ -package com.simibubi.create.content.logistics.block.chute; +package com.simibubi.create.content.logistics.chute; import java.util.HashMap; import java.util.Map; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; -import com.simibubi.create.content.logistics.block.chute.ChuteBlock.Shape; +import com.simibubi.create.content.logistics.chute.ChuteBlock.Shape; import net.minecraft.core.Direction; import net.minecraft.world.level.block.Block; @@ -24,12 +24,12 @@ public class ChuteShapes { public static VoxelShape createShape(BlockState state) { if (AllBlocks.SMART_CHUTE.has(state)) - return AllShapes.SMART_CHUTE; + return Shapes.block(); Direction direction = state.getValue(ChuteBlock.FACING); Shape shape = state.getValue(ChuteBlock.SHAPE); - boolean intersection = shape == Shape.INTERSECTION; + boolean intersection = shape == Shape.INTERSECTION || shape == Shape.ENCASED; if (direction == Direction.DOWN) return intersection ? Shapes.block() : AllShapes.CHUTE; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/chute/SmartChuteBlock.java b/src/main/java/com/simibubi/create/content/logistics/chute/SmartChuteBlock.java similarity index 91% rename from src/main/java/com/simibubi/create/content/logistics/block/chute/SmartChuteBlock.java rename to src/main/java/com/simibubi/create/content/logistics/chute/SmartChuteBlock.java index 88a5a4c14..5575d6883 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/chute/SmartChuteBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/chute/SmartChuteBlock.java @@ -1,6 +1,6 @@ -package com.simibubi.create.content.logistics.block.chute; +package com.simibubi.create.content.logistics.chute; -import com.simibubi.create.AllTileEntities; +import com.simibubi.create.AllBlockEntityTypes; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; @@ -55,8 +55,8 @@ public class SmartChuteBlock extends AbstractChuteBlock { } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.SMART_CHUTE.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.SMART_CHUTE.get(); } @Override diff --git a/src/main/java/com/simibubi/create/content/logistics/chute/SmartChuteBlockEntity.java b/src/main/java/com/simibubi/create/content/logistics/chute/SmartChuteBlockEntity.java new file mode 100644 index 000000000..0ac591938 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/chute/SmartChuteBlockEntity.java @@ -0,0 +1,66 @@ +package com.simibubi.create.content.logistics.chute; + +import java.util.List; + +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.item.ItemHelper.ExtractionCountMode; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; + +public class SmartChuteBlockEntity extends ChuteBlockEntity { + + FilteringBehaviour filtering; + + public SmartChuteBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + protected boolean canAcceptItem(ItemStack stack) { + return super.canAcceptItem(stack) && canCollectItemsFromBelow() && filtering.test(stack); + } + + @Override + protected int getExtractionAmount() { + return filtering.isCountVisible() && !filtering.anyAmount() ? filtering.getAmount() : 64; + } + + @Override + protected ExtractionCountMode getExtractionMode() { + return filtering.isCountVisible() && !filtering.anyAmount() && !filtering.upTo ? ExtractionCountMode.EXACTLY + : ExtractionCountMode.UPTO; + } + + @Override + protected boolean canCollectItemsFromBelow() { + BlockState blockState = getBlockState(); + return blockState.hasProperty(SmartChuteBlock.POWERED) && !blockState.getValue(SmartChuteBlock.POWERED); + } + + @Override + protected boolean canOutputItems() { + BlockState blockState = getBlockState(); + return blockState.hasProperty(SmartChuteBlock.POWERED) && !blockState.getValue(SmartChuteBlock.POWERED); + } + + @Override + public void addBehaviours(List behaviours) { + behaviours.add(filtering = + new FilteringBehaviour(this, new SmartChuteFilterSlotPositioning()).showCountWhen(this::isExtracting)); + super.addBehaviours(behaviours); + } + + private boolean isExtracting() { + boolean up = getItemMotion() < 0; + BlockPos chutePos = worldPosition.relative(up ? Direction.UP : Direction.DOWN); + BlockState blockState = level.getBlockState(chutePos); + return !AbstractChuteBlock.isChute(blockState) && !blockState.getMaterial() + .isReplaceable(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/chute/SmartChuteFilterSlotPositioning.java b/src/main/java/com/simibubi/create/content/logistics/chute/SmartChuteFilterSlotPositioning.java similarity index 75% rename from src/main/java/com/simibubi/create/content/logistics/block/chute/SmartChuteFilterSlotPositioning.java rename to src/main/java/com/simibubi/create/content/logistics/chute/SmartChuteFilterSlotPositioning.java index c28d77587..cbc53fb03 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/chute/SmartChuteFilterSlotPositioning.java +++ b/src/main/java/com/simibubi/create/content/logistics/chute/SmartChuteFilterSlotPositioning.java @@ -1,6 +1,6 @@ -package com.simibubi.create.content.logistics.block.chute; +package com.simibubi.create.content.logistics.chute; -import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.VecHelper; @@ -12,10 +12,10 @@ import net.minecraft.world.phys.Vec3; public class SmartChuteFilterSlotPositioning extends ValueBoxTransform.Sided { @Override - protected Vec3 getLocalOffset(BlockState state) { + public Vec3 getLocalOffset(BlockState state) { Direction side = getSide(); float horizontalAngle = AngleHelper.horizontalAngle(side); - Vec3 southLocation = VecHelper.voxelSpace(8, 12, 15.5f); + Vec3 southLocation = VecHelper.voxelSpace(8, 11, 15.5f); return VecHelper.rotateCentered(southLocation, horizontalAngle, Axis.Y); } diff --git a/src/main/java/com/simibubi/create/content/logistics/chute/SmartChuteRenderer.java b/src/main/java/com/simibubi/create/content/logistics/chute/SmartChuteRenderer.java new file mode 100644 index 000000000..f34bcecbd --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/chute/SmartChuteRenderer.java @@ -0,0 +1,26 @@ +package com.simibubi.create.content.logistics.chute; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.foundation.blockEntity.renderer.SmartBlockEntityRenderer; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; + +public class SmartChuteRenderer extends SmartBlockEntityRenderer { + + public SmartChuteRenderer(BlockEntityRendererProvider.Context context) { + super(context); + } + + @Override + protected void renderSafe(SmartChuteBlockEntity blockEntity, float partialTicks, PoseStack ms, + MultiBufferSource buffer, int light, int overlay) { + super.renderSafe(blockEntity, partialTicks, ms, buffer, light, overlay); + if (blockEntity.item.isEmpty()) + return; + if (blockEntity.itemPosition.getValue(partialTicks) > 0) + return; + ChuteRenderer.renderItem(blockEntity, partialTicks, ms, buffer, light, overlay); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/inventories/BottomlessItemHandler.java b/src/main/java/com/simibubi/create/content/logistics/crate/BottomlessItemHandler.java similarity index 96% rename from src/main/java/com/simibubi/create/content/logistics/block/inventories/BottomlessItemHandler.java rename to src/main/java/com/simibubi/create/content/logistics/crate/BottomlessItemHandler.java index 1df0af6a2..6a2adf1db 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/inventories/BottomlessItemHandler.java +++ b/src/main/java/com/simibubi/create/content/logistics/crate/BottomlessItemHandler.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.block.inventories; +package com.simibubi.create.content.logistics.crate; import java.util.function.Supplier; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/inventories/CrateBlock.java b/src/main/java/com/simibubi/create/content/logistics/crate/CrateBlock.java similarity index 87% rename from src/main/java/com/simibubi/create/content/logistics/block/inventories/CrateBlock.java rename to src/main/java/com/simibubi/create/content/logistics/crate/CrateBlock.java index 6550f3bc6..ce54c2f77 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/inventories/CrateBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/crate/CrateBlock.java @@ -1,7 +1,7 @@ -package com.simibubi.create.content.logistics.block.inventories; +package com.simibubi.create.content.logistics.crate; import com.simibubi.create.AllShapes; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; +import com.simibubi.create.content.equipment.wrench.IWrenchable; import com.simibubi.create.foundation.block.WrenchableDirectionalBlock; import net.minecraft.core.BlockPos; diff --git a/src/main/java/com/simibubi/create/content/logistics/crate/CrateBlockEntity.java b/src/main/java/com/simibubi/create/content/logistics/crate/CrateBlockEntity.java new file mode 100644 index 000000000..9a7e2ccea --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/crate/CrateBlockEntity.java @@ -0,0 +1,21 @@ +package com.simibubi.create.content.logistics.crate; + +import java.util.List; + +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; + +public abstract class CrateBlockEntity extends SmartBlockEntity { + + public CrateBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + public void addBehaviours(List behaviours) {} + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/crate/CreativeCrateBlock.java b/src/main/java/com/simibubi/create/content/logistics/crate/CreativeCrateBlock.java new file mode 100644 index 000000000..a436839ec --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/crate/CreativeCrateBlock.java @@ -0,0 +1,23 @@ +package com.simibubi.create.content.logistics.crate; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.foundation.block.IBE; + +import net.minecraft.world.level.block.entity.BlockEntityType; + +public class CreativeCrateBlock extends CrateBlock implements IBE { + + public CreativeCrateBlock(Properties p_i48415_1_) { + super(p_i48415_1_); + } + + @Override + public Class getBlockEntityClass() { + return CreativeCrateBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.CREATIVE_CRATE.get(); + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/crate/CreativeCrateBlockEntity.java b/src/main/java/com/simibubi/create/content/logistics/crate/CreativeCrateBlockEntity.java new file mode 100644 index 000000000..0d23295a4 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/crate/CreativeCrateBlockEntity.java @@ -0,0 +1,75 @@ +package com.simibubi.create.content.logistics.crate; + +import java.util.List; + +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; + +public class CreativeCrateBlockEntity extends CrateBlockEntity { + + public CreativeCrateBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + inv = new BottomlessItemHandler(filtering::getFilter); + itemHandler = LazyOptional.of(() -> inv); + } + + FilteringBehaviour filtering; + LazyOptional itemHandler; + private BottomlessItemHandler inv; + + @Override + public void addBehaviours(List behaviours) { + behaviours.add(filtering = createFilter()); + filtering.setLabel(Lang.translateDirect("logistics.creative_crate.supply")); + } + + @Override + public void invalidate() { + super.invalidate(); + if (itemHandler != null) + itemHandler.invalidate(); + } + + @Override + public LazyOptional getCapability(Capability cap, Direction side) { + if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) + return itemHandler.cast(); + return super.getCapability(cap, side); + } + + public FilteringBehaviour createFilter() { + return new FilteringBehaviour(this, new ValueBoxTransform() { + + @Override + public void rotate(BlockState state, PoseStack ms) { + TransformStack.cast(ms) + .rotateX(90); + } + + @Override + public Vec3 getLocalOffset(BlockState state) { + return new Vec3(0.5, 13.5 / 16d, 0.5); + } + + public float getScale() { + return super.getScale(); + }; + + }); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/depot/DepotBehaviour.java b/src/main/java/com/simibubi/create/content/logistics/depot/DepotBehaviour.java similarity index 83% rename from src/main/java/com/simibubi/create/content/logistics/block/depot/DepotBehaviour.java rename to src/main/java/com/simibubi/create/content/logistics/depot/DepotBehaviour.java index 8e31cce1b..97c9bd475 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/depot/DepotBehaviour.java +++ b/src/main/java/com/simibubi/create/content/logistics/depot/DepotBehaviour.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.block.depot; +package com.simibubi.create.content.logistics.depot; import java.util.ArrayList; import java.util.Iterator; @@ -9,18 +9,18 @@ import java.util.function.Predicate; import java.util.function.Supplier; import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.content.contraptions.relays.belt.BeltHelper; -import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack; -import com.simibubi.create.content.logistics.block.funnel.AbstractFunnelBlock; +import com.simibubi.create.content.kinetics.belt.BeltHelper; +import com.simibubi.create.content.kinetics.belt.behaviour.BeltProcessingBehaviour; +import com.simibubi.create.content.kinetics.belt.behaviour.BeltProcessingBehaviour.ProcessingResult; +import com.simibubi.create.content.kinetics.belt.behaviour.DirectBeltInputBehaviour; +import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour; +import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour.TransportedResult; +import com.simibubi.create.content.kinetics.belt.transport.TransportedItemStack; +import com.simibubi.create.content.logistics.funnel.AbstractFunnelBlock; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.item.ItemHelper; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProcessingBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProcessingBehaviour.ProcessingResult; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour.TransportedResult; import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.VecHelper; @@ -40,7 +40,7 @@ import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.items.ItemStackHandler; -public class DepotBehaviour extends TileEntityBehaviour { +public class DepotBehaviour extends BlockEntityBehaviour { public static final BehaviourType TYPE = new BehaviourType<>(); @@ -57,8 +57,8 @@ public class DepotBehaviour extends TileEntityBehaviour { Predicate acceptedItems; boolean allowMerge; - public DepotBehaviour(SmartTileEntity te) { - super(te); + public DepotBehaviour(SmartBlockEntity be) { + super(be); maxStackSize = () -> 64; canAcceptItems = () -> true; canFunnelsPullFrom = $ -> true; @@ -70,7 +70,7 @@ public class DepotBehaviour extends TileEntityBehaviour { lazyItemHandler = LazyOptional.of(() -> itemHandler); processingOutputBuffer = new ItemStackHandler(8) { protected void onContentsChanged(int slot) { - te.notifyUpdate(); + be.notifyUpdate(); }; }; } @@ -93,26 +93,26 @@ public class DepotBehaviour extends TileEntityBehaviour { public void tick() { super.tick(); - Level world = tileEntity.getLevel(); + Level world = blockEntity.getLevel(); for (Iterator iterator = incoming.iterator(); iterator.hasNext();) { TransportedItemStack ts = iterator.next(); if (!tick(ts)) continue; - if (world.isClientSide && !tileEntity.isVirtual()) + if (world.isClientSide && !blockEntity.isVirtual()) continue; if (heldItem == null) { heldItem = ts; } else { if (!ItemHelper.canItemStackAmountsStack(heldItem.stack, ts.stack)) { - Vec3 vec = VecHelper.getCenterOf(tileEntity.getBlockPos()); - Containers.dropItemStack(tileEntity.getLevel(), vec.x, vec.y + .5f, vec.z, ts.stack); + Vec3 vec = VecHelper.getCenterOf(blockEntity.getBlockPos()); + Containers.dropItemStack(blockEntity.getLevel(), vec.x, vec.y + .5f, vec.z, ts.stack); } else { heldItem.stack.grow(ts.stack.getCount()); } } iterator.remove(); - tileEntity.notifyUpdate(); + blockEntity.notifyUpdate(); } if (heldItem == null) @@ -120,7 +120,7 @@ public class DepotBehaviour extends TileEntityBehaviour { if (!tick(heldItem)) return; - BlockPos pos = tileEntity.getBlockPos(); + BlockPos pos = blockEntity.getBlockPos(); if (world.isClientSide) return; @@ -128,7 +128,7 @@ public class DepotBehaviour extends TileEntityBehaviour { return; BeltProcessingBehaviour processingBehaviour = - TileEntityBehaviour.get(world, pos.above(2), BeltProcessingBehaviour.TYPE); + BlockEntityBehaviour.get(world, pos.above(2), BeltProcessingBehaviour.TYPE); if (processingBehaviour == null) return; if (!heldItem.locked && BeltProcessingBehaviour.isBlocked(world, pos)) @@ -140,13 +140,13 @@ public class DepotBehaviour extends TileEntityBehaviour { : processingBehaviour.handleReceivedItem(heldItem, transportedHandler); if (result == ProcessingResult.REMOVE) { heldItem = null; - tileEntity.sendData(); + blockEntity.sendData(); return; } heldItem.locked = result == ProcessingResult.HOLD; if (heldItem.locked != wasLocked || !previousItem.equals(heldItem.stack, false)) - tileEntity.sendData(); + blockEntity.sendData(); } protected boolean tick(TransportedItemStack heldItem) { @@ -171,19 +171,19 @@ public class DepotBehaviour extends TileEntityBehaviour { ItemStack previousItem = processingOutputBuffer.getStackInSlot(slot); if (previousItem.isEmpty()) continue; - ItemStack afterInsert = tileEntity.getBehaviour(DirectBeltInputBehaviour.TYPE) + ItemStack afterInsert = blockEntity.getBehaviour(DirectBeltInputBehaviour.TYPE) .tryExportingToBeltFunnel(previousItem, null, false); if (afterInsert == null) return false; if (previousItem.getCount() != afterInsert.getCount()) { processingOutputBuffer.setStackInSlot(slot, afterInsert); - tileEntity.notifyUpdate(); + blockEntity.notifyUpdate(); return true; } } ItemStack previousItem = heldItem.stack; - ItemStack afterInsert = tileEntity.getBehaviour(DirectBeltInputBehaviour.TYPE) + ItemStack afterInsert = blockEntity.getBehaviour(DirectBeltInputBehaviour.TYPE) .tryExportingToBeltFunnel(previousItem, null, false); if (afterInsert == null) return false; @@ -192,7 +192,7 @@ public class DepotBehaviour extends TileEntityBehaviour { heldItem = null; else heldItem.stack = afterInsert; - tileEntity.notifyUpdate(); + blockEntity.notifyUpdate(); return true; } @@ -238,10 +238,10 @@ public class DepotBehaviour extends TileEntityBehaviour { } } - public void addSubBehaviours(List behaviours) { - behaviours.add(new DirectBeltInputBehaviour(tileEntity).allowingBeltFunnels() + public void addSubBehaviours(List behaviours) { + behaviours.add(new DirectBeltInputBehaviour(blockEntity).allowingBeltFunnels() .setInsertionHandler(this::tryInsertingFromSide)); - transportedHandler = new TransportedItemStackHandlerBehaviour(tileEntity, this::applyToAllItems) + transportedHandler = new TransportedItemStackHandlerBehaviour(blockEntity, this::applyToAllItems) .withStackPlacement(this::getWorldPositionOf); behaviours.add(transportedHandler); } @@ -358,7 +358,7 @@ public class DepotBehaviour extends TileEntityBehaviour { transportedStack.prevBeltPosition = transportedStack.beltPosition; ItemStack remainder = insert(transportedStack, simulate); if (remainder.getCount() != size) - tileEntity.notifyUpdate(); + blockEntity.notifyUpdate(); return remainder; } @@ -388,12 +388,12 @@ public class DepotBehaviour extends TileEntityBehaviour { continue; } ItemStack remainder = ItemHandlerHelper.insertItemStacked(processingOutputBuffer, added.stack, false); - Vec3 vec = VecHelper.getCenterOf(tileEntity.getBlockPos()); - Containers.dropItemStack(tileEntity.getLevel(), vec.x, vec.y + .5f, vec.z, remainder); + Vec3 vec = VecHelper.getCenterOf(blockEntity.getBlockPos()); + Containers.dropItemStack(blockEntity.getLevel(), vec.x, vec.y + .5f, vec.z, remainder); } if (dirty) - tileEntity.notifyUpdate(); + blockEntity.notifyUpdate(); } public boolean isEmpty() { @@ -409,7 +409,7 @@ public class DepotBehaviour extends TileEntityBehaviour { } private Vec3 getWorldPositionOf(TransportedItemStack transported) { - return VecHelper.getCenterOf(tileEntity.getBlockPos()); + return VecHelper.getCenterOf(blockEntity.getBlockPos()); } @Override diff --git a/src/main/java/com/simibubi/create/content/logistics/depot/DepotBlock.java b/src/main/java/com/simibubi/create/content/logistics/depot/DepotBlock.java new file mode 100644 index 000000000..e664309dc --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/depot/DepotBlock.java @@ -0,0 +1,111 @@ +package com.simibubi.create.content.logistics.depot; + +import javax.annotation.ParametersAreNonnullByDefault; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllShapes; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.block.ProperWaterloggedBlock; + +import net.minecraft.MethodsReturnNonnullByDefault; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.Entity; +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.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition.Builder; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.level.pathfinder.PathComputationType; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +public class DepotBlock extends Block implements IBE, IWrenchable, ProperWaterloggedBlock { + + public DepotBlock(Properties p_i48440_1_) { + super(p_i48440_1_); + registerDefaultState(defaultBlockState().setValue(WATERLOGGED, false)); + } + + @Override + protected void createBlockStateDefinition(Builder pBuilder) { + super.createBlockStateDefinition(pBuilder.add(WATERLOGGED)); + } + + @Override + public FluidState getFluidState(BlockState pState) { + return fluidState(pState); + } + + @Override + public BlockState updateShape(BlockState pState, Direction pDirection, BlockState pNeighborState, + LevelAccessor pLevel, BlockPos pCurrentPos, BlockPos pNeighborPos) { + updateWater(pLevel, pState, pCurrentPos); + return pState; + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext pContext) { + return withWater(super.getStateForPlacement(pContext), pContext); + } + + @Override + public VoxelShape getShape(BlockState p_220053_1_, BlockGetter p_220053_2_, BlockPos p_220053_3_, + CollisionContext p_220053_4_) { + return AllShapes.CASING_13PX.get(Direction.UP); + } + + @Override + public Class getBlockEntityClass() { + return DepotBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.DEPOT.get(); + } + + @Override + public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, + BlockHitResult ray) { + return SharedDepotBlockMethods.onUse(state, world, pos, player, hand, ray); + } + + @Override + public void onRemove(BlockState state, Level worldIn, BlockPos pos, BlockState newState, boolean isMoving) { + IBE.onRemove(state, worldIn, pos, newState); + } + + @Override + public void updateEntityAfterFallOn(BlockGetter worldIn, Entity entityIn) { + super.updateEntityAfterFallOn(worldIn, entityIn); + SharedDepotBlockMethods.onLanded(worldIn, entityIn); + } + + @Override + public boolean hasAnalogOutputSignal(BlockState state) { + return true; + } + + @Override + public int getAnalogOutputSignal(BlockState blockState, Level worldIn, BlockPos pos) { + return SharedDepotBlockMethods.getComparatorInputOverride(blockState, worldIn, pos); + } + + @Override + public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) { + return false; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/depot/DepotBlockEntity.java b/src/main/java/com/simibubi/create/content/logistics/depot/DepotBlockEntity.java new file mode 100644 index 000000000..af3356704 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/depot/DepotBlockEntity.java @@ -0,0 +1,41 @@ +package com.simibubi.create.content.logistics.depot; + +import java.util.List; + +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.items.CapabilityItemHandler; + +public class DepotBlockEntity extends SmartBlockEntity { + + DepotBehaviour depotBehaviour; + + public DepotBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + public void addBehaviours(List behaviours) { + behaviours.add(depotBehaviour = new DepotBehaviour(this)); + depotBehaviour.addSubBehaviours(behaviours); + } + + @Override + public LazyOptional getCapability(Capability cap, Direction side) { + if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) + return depotBehaviour.getItemCapability(cap, side); + return super.getCapability(cap, side); + } + + public ItemStack getHeldItem() { + return depotBehaviour.getHeldItemStack(); + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/depot/DepotItemHandler.java b/src/main/java/com/simibubi/create/content/logistics/depot/DepotItemHandler.java new file mode 100644 index 000000000..c4873ec2c --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/depot/DepotItemHandler.java @@ -0,0 +1,72 @@ +package com.simibubi.create.content.logistics.depot; + +import com.simibubi.create.content.kinetics.belt.transport.TransportedItemStack; + +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.items.IItemHandler; + +public class DepotItemHandler implements IItemHandler { + + private static final int MAIN_SLOT = 0; + private DepotBehaviour behaviour; + + public DepotItemHandler(DepotBehaviour behaviour) { + this.behaviour = behaviour; + } + + @Override + public int getSlots() { + return 9; + } + + @Override + public ItemStack getStackInSlot(int slot) { + return slot == MAIN_SLOT ? behaviour.getHeldItemStack() : behaviour.processingOutputBuffer.getStackInSlot(slot - 1); + } + + @Override + public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) { + if (slot != MAIN_SLOT) + return stack; + if (!behaviour.getHeldItemStack() + .isEmpty() && !behaviour.canMergeItems()) + return stack; + if (!behaviour.isOutputEmpty() && !behaviour.canMergeItems()) + return stack; + + ItemStack remainder = behaviour.insert(new TransportedItemStack(stack), simulate); + if (!simulate && remainder != stack) + behaviour.blockEntity.notifyUpdate(); + return remainder; + } + + @Override + public ItemStack extractItem(int slot, int amount, boolean simulate) { + if (slot != MAIN_SLOT) + return behaviour.processingOutputBuffer.extractItem(slot - 1, amount, simulate); + + TransportedItemStack held = behaviour.heldItem; + if (held == null) + return ItemStack.EMPTY; + ItemStack stack = held.stack.copy(); + ItemStack extracted = stack.split(amount); + if (!simulate) { + behaviour.heldItem.stack = stack; + if (stack.isEmpty()) + behaviour.heldItem = null; + behaviour.blockEntity.notifyUpdate(); + } + return extracted; + } + + @Override + public int getSlotLimit(int slot) { + return slot == MAIN_SLOT ? behaviour.maxStackSize.get() : 64; + } + + @Override + public boolean isItemValid(int slot, ItemStack stack) { + return slot == MAIN_SLOT && behaviour.isItemValid(stack); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/depot/DepotRenderer.java b/src/main/java/com/simibubi/create/content/logistics/depot/DepotRenderer.java similarity index 84% rename from src/main/java/com/simibubi/create/content/logistics/block/depot/DepotRenderer.java rename to src/main/java/com/simibubi/create/content/logistics/depot/DepotRenderer.java index 501f7dba3..36ce13267 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/depot/DepotRenderer.java +++ b/src/main/java/com/simibubi/create/content/logistics/depot/DepotRenderer.java @@ -1,14 +1,14 @@ -package com.simibubi.create.content.logistics.block.depot; +package com.simibubi.create.content.logistics.depot; import java.util.Random; import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Axis; -import com.simibubi.create.content.contraptions.relays.belt.BeltHelper; -import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; +import com.simibubi.create.content.kinetics.belt.BeltHelper; +import com.simibubi.create.content.kinetics.belt.transport.TransportedItemStack; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.client.Minecraft; @@ -22,23 +22,23 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.phys.Vec3; -public class DepotRenderer extends SafeTileEntityRenderer { +public class DepotRenderer extends SafeBlockEntityRenderer { public DepotRenderer(BlockEntityRendererProvider.Context context) { } @Override - protected void renderSafe(DepotTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, + protected void renderSafe(DepotBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light, int overlay) { - renderItemsOf(te, partialTicks, ms, buffer, light, overlay, te.depotBehaviour); + renderItemsOf(be, partialTicks, ms, buffer, light, overlay, be.depotBehaviour); } - public static void renderItemsOf(SmartTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, + public static void renderItemsOf(SmartBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light, int overlay, DepotBehaviour depotBehaviour) { TransportedItemStack transported = depotBehaviour.heldItem; TransformStack msr = TransformStack.cast(ms); - Vec3 itemPosition = VecHelper.getCenterOf(te.getBlockPos()); + Vec3 itemPosition = VecHelper.getCenterOf(be.getBlockPos()); ms.pushPose(); ms.translate(.5f, 15 / 16f, .5f); diff --git a/src/main/java/com/simibubi/create/content/logistics/depot/EjectorAwardPacket.java b/src/main/java/com/simibubi/create/content/logistics/depot/EjectorAwardPacket.java new file mode 100644 index 000000000..ecc786c0d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/depot/EjectorAwardPacket.java @@ -0,0 +1,34 @@ +package com.simibubi.create.content.logistics.depot; + +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.networking.BlockEntityConfigurationPacket; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; + +public class EjectorAwardPacket extends BlockEntityConfigurationPacket { + + public EjectorAwardPacket(FriendlyByteBuf buffer) { + super(buffer); + } + + public EjectorAwardPacket(BlockPos pos) { + super(pos); + } + + @Override + protected void writeSettings(FriendlyByteBuf buffer) {} + + @Override + protected void readSettings(FriendlyByteBuf buffer) {} + + @Override + protected void applySettings(ServerPlayer player, EjectorBlockEntity be) { + AllAdvancements.EJECTOR_MAXED.awardTo(player); + } + + @Override + protected void applySettings(EjectorBlockEntity be) {} + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/depot/EjectorBlock.java b/src/main/java/com/simibubi/create/content/logistics/depot/EjectorBlock.java new file mode 100644 index 000000000..a75404840 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/depot/EjectorBlock.java @@ -0,0 +1,193 @@ +package com.simibubi.create.content.logistics.depot; + +import java.util.Optional; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllItems; +import com.simibubi.create.AllPackets; +import com.simibubi.create.AllShapes; +import com.simibubi.create.content.kinetics.base.HorizontalKineticBlock; +import com.simibubi.create.content.logistics.depot.EjectorBlockEntity.State; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.block.ProperWaterloggedBlock; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.item.ItemEntity; +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.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition.Builder; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.level.pathfinder.PathComputationType; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +public class EjectorBlock extends HorizontalKineticBlock implements IBE, ProperWaterloggedBlock { + + public EjectorBlock(Properties properties) { + super(properties); + registerDefaultState(defaultBlockState().setValue(WATERLOGGED, false)); + } + + @Override + protected void createBlockStateDefinition(Builder pBuilder) { + super.createBlockStateDefinition(pBuilder.add(WATERLOGGED)); + } + + @Override + public FluidState getFluidState(BlockState pState) { + return fluidState(pState); + } + + @Override + public BlockState updateShape(BlockState pState, Direction pDirection, BlockState pNeighborState, + LevelAccessor pLevel, BlockPos pCurrentPos, BlockPos pNeighborPos) { + updateWater(pLevel, pState, pCurrentPos); + return pState; + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext pContext) { + return withWater(super.getStateForPlacement(pContext), pContext); + } + + @Override + public VoxelShape getShape(BlockState p_220053_1_, BlockGetter p_220053_2_, BlockPos p_220053_3_, + CollisionContext p_220053_4_) { + return AllShapes.CASING_13PX.get(Direction.UP); + } + + @Override + public float getFriction(BlockState state, LevelReader world, BlockPos pos, Entity entity) { + return getBlockEntityOptional(world, pos).filter(ete -> ete.state == State.LAUNCHING) + .map($ -> 1f) + .orElse(super.getFriction(state, world, pos, entity)); + } + + @Override + public void neighborChanged(BlockState state, Level world, BlockPos pos, Block p_220069_4_, BlockPos p_220069_5_, + boolean p_220069_6_) { + withBlockEntityDo(world, pos, EjectorBlockEntity::updateSignal); + } + + @Override + public void fallOn(Level p_180658_1_, BlockState p_152427_, BlockPos p_180658_2_, Entity p_180658_3_, + float p_180658_4_) { + Optional blockEntityOptional = getBlockEntityOptional(p_180658_1_, p_180658_2_); + if (blockEntityOptional.isPresent() && !p_180658_3_.isSuppressingBounce()) { + p_180658_3_.causeFallDamage(p_180658_4_, 1.0F, DamageSource.FALL); + return; + } + super.fallOn(p_180658_1_, p_152427_, p_180658_2_, p_180658_3_, p_180658_4_); + } + + @Override + public void updateEntityAfterFallOn(BlockGetter worldIn, Entity entityIn) { + super.updateEntityAfterFallOn(worldIn, entityIn); + BlockPos position = entityIn.blockPosition(); + if (!AllBlocks.WEIGHTED_EJECTOR.has(worldIn.getBlockState(position))) + return; + if (!entityIn.isAlive()) + return; + if (entityIn.isSuppressingBounce()) + return; + if (entityIn instanceof ItemEntity) { + SharedDepotBlockMethods.onLanded(worldIn, entityIn); + return; + } + + Optional teProvider = getBlockEntityOptional(worldIn, position); + if (!teProvider.isPresent()) + return; + + EjectorBlockEntity ejectorBlockEntity = teProvider.get(); + if (ejectorBlockEntity.getState() == State.RETRACTING) + return; + if (ejectorBlockEntity.powered) + return; + if (ejectorBlockEntity.launcher.getHorizontalDistance() == 0) + return; + + if (entityIn.isOnGround()) { + entityIn.setOnGround(false); + Vec3 center = VecHelper.getCenterOf(position) + .add(0, 7 / 16f, 0); + Vec3 positionVec = entityIn.position(); + double diff = center.distanceTo(positionVec); + entityIn.setDeltaMovement(0, -0.125, 0); + Vec3 vec = center.add(positionVec) + .scale(.5f); + if (diff > 4 / 16f) { + entityIn.setPos(vec.x, vec.y, vec.z); + return; + } + } + + ejectorBlockEntity.activate(); + ejectorBlockEntity.notifyUpdate(); + if (entityIn.level.isClientSide) + AllPackets.getChannel().sendToServer(new EjectorTriggerPacket(ejectorBlockEntity.getBlockPos())); + } + + @Override + public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, + BlockHitResult ray) { + if (AllItems.WRENCH.isIn(player.getItemInHand(hand))) + return InteractionResult.PASS; + return SharedDepotBlockMethods.onUse(state, world, pos, player, hand, ray); + } + + @Override + public Axis getRotationAxis(BlockState state) { + return state.getValue(HORIZONTAL_FACING) + .getClockWise() + .getAxis(); + } + + @Override + public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) { + return getRotationAxis(state) == face.getAxis(); + } + + @Override + public Class getBlockEntityClass() { + return EjectorBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.WEIGHTED_EJECTOR.get(); + } + + @Override + public boolean hasAnalogOutputSignal(BlockState state) { + return true; + } + + @Override + public int getAnalogOutputSignal(BlockState blockState, Level worldIn, BlockPos pos) { + return SharedDepotBlockMethods.getComparatorInputOverride(blockState, worldIn, pos); + } + + @Override + public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) { + return false; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/depot/EjectorBlockEntity.java b/src/main/java/com/simibubi/create/content/logistics/depot/EjectorBlockEntity.java new file mode 100644 index 000000000..83f6d089f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/depot/EjectorBlockEntity.java @@ -0,0 +1,659 @@ +package com.simibubi.create.content.logistics.depot; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javax.annotation.Nullable; + +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPackets; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.belt.behaviour.DirectBeltInputBehaviour; +import com.simibubi.create.content.kinetics.belt.transport.TransportedItemStack; +import com.simibubi.create.content.logistics.funnel.AbstractFunnelBlock; +import com.simibubi.create.content.logistics.funnel.FunnelBlock; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; +import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollValueBehaviour; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.IntAttached; +import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.NBTHelper; +import com.simibubi.create.foundation.utility.Pair; +import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.nbt.Tag; +import net.minecraft.network.syncher.SynchedEntityData; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ElytraItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.ClipContext; +import net.minecraft.world.level.ClipContext.Block; +import net.minecraft.world.level.ClipContext.Fluid; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.ObserverBlock; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.PushReaction; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.HitResult.Type; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.items.ItemStackHandler; + +public class EjectorBlockEntity extends KineticBlockEntity { + + List> launchedItems; + ScrollValueBehaviour maxStackSize; + DepotBehaviour depotBehaviour; + EntityLauncher launcher; + LerpedFloat lidProgress; + boolean powered; + boolean launch; + State state; + + // item collision + @Nullable + Pair earlyTarget; + float earlyTargetTime; + // runtime stuff + int scanCooldown; + ItemStack trackedItem; + + public enum State { + CHARGED, LAUNCHING, RETRACTING; + } + + public EjectorBlockEntity(BlockEntityType typeIn, BlockPos pos, BlockState state) { + super(typeIn, pos, state); + launcher = new EntityLauncher(1, 0); + lidProgress = LerpedFloat.linear() + .startWithValue(1); + this.state = State.RETRACTING; + launchedItems = new ArrayList<>(); + powered = false; + } + + @Override + public void addBehaviours(List behaviours) { + super.addBehaviours(behaviours); + behaviours.add(depotBehaviour = new DepotBehaviour(this)); + + maxStackSize = + new ScrollValueBehaviour(Lang.translateDirect("weighted_ejector.stack_size"), this, new EjectorSlot()) + .between(0, 64) + .withFormatter(i -> i == 0 ? "*" : String.valueOf(i)); + behaviours.add(maxStackSize); + + depotBehaviour.maxStackSize = () -> maxStackSize.getValue(); + depotBehaviour.canAcceptItems = () -> state == State.CHARGED; + depotBehaviour.canFunnelsPullFrom = side -> side != getFacing(); + depotBehaviour.enableMerging(); + depotBehaviour.addSubBehaviours(behaviours); + } + + @Override + public void initialize() { + super.initialize(); + updateSignal(); + } + + public void activate() { + launch = true; + nudgeEntities(); + } + + protected boolean cannotLaunch() { + return state != State.CHARGED && !(level.isClientSide && state == State.LAUNCHING); + } + + public void activateDeferred() { + if (cannotLaunch()) + return; + Direction facing = getFacing(); + List entities = + level.getEntitiesOfClass(Entity.class, new AABB(worldPosition).inflate(-1 / 16f, 0, -1 / 16f)); + + // Launch Items + boolean doLogic = !level.isClientSide || isVirtual(); + if (doLogic) + launchItems(); + + // Launch Entities + for (Entity entity : entities) { + boolean isPlayerEntity = entity instanceof Player; + if (!entity.isAlive()) + continue; + if (entity instanceof ItemEntity) + continue; + if (entity.getPistonPushReaction() == PushReaction.IGNORE) + continue; + + entity.setOnGround(false); + + if (isPlayerEntity != level.isClientSide) + continue; + + entity.setPos(worldPosition.getX() + .5f, worldPosition.getY() + 1, worldPosition.getZ() + .5f); + launcher.applyMotion(entity, facing); + + if (!isPlayerEntity) + continue; + + Player playerEntity = (Player) entity; + + if (launcher.getHorizontalDistance() * launcher.getHorizontalDistance() + + launcher.getVerticalDistance() * launcher.getVerticalDistance() >= 25 * 25) + AllPackets.getChannel() + .sendToServer(new EjectorAwardPacket(worldPosition)); + + if (!(playerEntity.getItemBySlot(EquipmentSlot.CHEST) + .getItem() instanceof ElytraItem)) + continue; + + playerEntity.setXRot(-35); + playerEntity.setYRot(facing.toYRot()); + playerEntity.setDeltaMovement(playerEntity.getDeltaMovement() + .scale(.75f)); + deployElytra(playerEntity); + AllPackets.getChannel() + .sendToServer(new EjectorElytraPacket(worldPosition)); + } + + if (doLogic) { + lidProgress.chase(1, .8f, Chaser.EXP); + state = State.LAUNCHING; + if (!level.isClientSide) { + level.playSound(null, worldPosition, SoundEvents.WOODEN_TRAPDOOR_CLOSE, SoundSource.BLOCKS, .35f, 1f); + level.playSound(null, worldPosition, SoundEvents.CHEST_OPEN, SoundSource.BLOCKS, .1f, 1.4f); + } + } + } + + public void deployElytra(Player playerEntity) { + EntityHack.setElytraFlying(playerEntity); + } + + protected void launchItems() { + ItemStack heldItemStack = depotBehaviour.getHeldItemStack(); + Direction funnelFacing = getFacing().getOpposite(); + + if (AbstractFunnelBlock.getFunnelFacing(level.getBlockState(worldPosition.above())) == funnelFacing) { + DirectBeltInputBehaviour directOutput = getBehaviour(DirectBeltInputBehaviour.TYPE); + + if (depotBehaviour.heldItem != null) { + ItemStack remainder = directOutput.tryExportingToBeltFunnel(heldItemStack, funnelFacing, false); + if (remainder == null) + ; + else if (remainder.isEmpty()) + depotBehaviour.removeHeldItem(); + else if (remainder.getCount() != heldItemStack.getCount()) + depotBehaviour.heldItem.stack = remainder; + } + + for (Iterator iterator = depotBehaviour.incoming.iterator(); iterator.hasNext();) { + TransportedItemStack transportedItemStack = iterator.next(); + ItemStack stack = transportedItemStack.stack; + ItemStack remainder = directOutput.tryExportingToBeltFunnel(stack, funnelFacing, false); + if (remainder == null) + ; + else if (remainder.isEmpty()) + iterator.remove(); + else if (!remainder.sameItem(stack)) + transportedItemStack.stack = remainder; + } + + ItemStackHandler outputs = depotBehaviour.processingOutputBuffer; + for (int i = 0; i < outputs.getSlots(); i++) { + ItemStack remainder = + directOutput.tryExportingToBeltFunnel(outputs.getStackInSlot(i), funnelFacing, false); + if (remainder != null) + outputs.setStackInSlot(i, remainder); + } + return; + } + + if (!level.isClientSide) + for (Direction d : Iterate.directions) { + BlockState blockState = level.getBlockState(worldPosition.relative(d)); + if (!(blockState.getBlock() instanceof ObserverBlock)) + continue; + if (blockState.getValue(ObserverBlock.FACING) != d.getOpposite()) + continue; + blockState.updateShape(d.getOpposite(), blockState, level, worldPosition.relative(d), worldPosition); + } + + if (depotBehaviour.heldItem != null) { + addToLaunchedItems(heldItemStack); + depotBehaviour.removeHeldItem(); + } + + for (TransportedItemStack transportedItemStack : depotBehaviour.incoming) + addToLaunchedItems(transportedItemStack.stack); + depotBehaviour.incoming.clear(); + + ItemStackHandler outputs = depotBehaviour.processingOutputBuffer; + for (int i = 0; i < outputs.getSlots(); i++) { + ItemStack extractItem = outputs.extractItem(i, 64, false); + if (!extractItem.isEmpty()) + addToLaunchedItems(extractItem); + } + } + + protected boolean addToLaunchedItems(ItemStack stack) { + if ((!level.isClientSide || isVirtual()) && trackedItem == null && scanCooldown == 0) { + scanCooldown = AllConfigs.server().kinetics.ejectorScanInterval.get(); + trackedItem = stack; + } + return launchedItems.add(IntAttached.withZero(stack)); + } + + protected Direction getFacing() { + BlockState blockState = getBlockState(); + if (!AllBlocks.WEIGHTED_EJECTOR.has(blockState)) + return Direction.UP; + Direction facing = blockState.getValue(EjectorBlock.HORIZONTAL_FACING); + return facing; + } + + @Override + public void tick() { + super.tick(); + + boolean doLogic = !level.isClientSide || isVirtual(); + State prevState = state; + float totalTime = Math.max(3, (float) launcher.getTotalFlyingTicks()); + + if (scanCooldown > 0) + scanCooldown--; + + if (launch) { + launch = false; + activateDeferred(); + } + + for (Iterator> iterator = launchedItems.iterator(); iterator.hasNext();) { + IntAttached intAttached = iterator.next(); + boolean hit = false; + if (intAttached.getSecond() == trackedItem) + hit = scanTrajectoryForObstacles(intAttached.getFirst()); + float maxTime = earlyTarget != null ? Math.min(earlyTargetTime, totalTime) : totalTime; + if (hit || intAttached.exceeds((int) maxTime)) { + placeItemAtTarget(doLogic, maxTime, intAttached); + iterator.remove(); + } + intAttached.increment(); + } + + if (state == State.LAUNCHING) { + lidProgress.chase(1, .8f, Chaser.EXP); + lidProgress.tickChaser(); + if (lidProgress.getValue() > 1 - 1 / 16f && doLogic) { + state = State.RETRACTING; + lidProgress.setValue(1); + } + } + + if (state == State.CHARGED) { + lidProgress.setValue(0); + lidProgress.updateChaseSpeed(0); + if (doLogic) + ejectIfTriggered(); + } + + if (state == State.RETRACTING) { + if (lidProgress.getChaseTarget() == 1 && !lidProgress.settled()) { + lidProgress.tickChaser(); + } else { + lidProgress.updateChaseTarget(0); + lidProgress.updateChaseSpeed(0); + if (lidProgress.getValue() == 0 && doLogic) { + state = State.CHARGED; + lidProgress.setValue(0); + sendData(); + } + + float value = Mth.clamp(lidProgress.getValue() - getWindUpSpeed(), 0, 1); + lidProgress.setValue(value); + + int soundRate = (int) (1 / (getWindUpSpeed() * 5)) + 1; + float volume = .125f; + float pitch = 1.5f - lidProgress.getValue(); + if (((int) level.getGameTime()) % soundRate == 0 && doLogic) + level.playSound(null, worldPosition, SoundEvents.WOODEN_BUTTON_CLICK_OFF, SoundSource.BLOCKS, + volume, pitch); + } + } + + if (state != prevState) + notifyUpdate(); + } + + private boolean scanTrajectoryForObstacles(int time) { + if (time <= 2) + return false; + + Vec3 source = getLaunchedItemLocation(time); + Vec3 target = getLaunchedItemLocation(time + 1); + + BlockHitResult rayTraceBlocks = level.clip(new ClipContext(source, target, Block.COLLIDER, Fluid.NONE, null)); + boolean miss = rayTraceBlocks.getType() == Type.MISS; + + if (!miss && rayTraceBlocks.getType() == Type.BLOCK) { + BlockState blockState = level.getBlockState(rayTraceBlocks.getBlockPos()); + if (FunnelBlock.isFunnel(blockState) && blockState.hasProperty(FunnelBlock.EXTRACTING) + && blockState.getValue(FunnelBlock.EXTRACTING)) + miss = true; + } + + if (miss) { + if (earlyTarget != null && earlyTargetTime < time + 1) { + earlyTarget = null; + earlyTargetTime = 0; + } + return false; + } + + Vec3 vec = rayTraceBlocks.getLocation(); + earlyTarget = Pair.of(vec.add(Vec3.atLowerCornerOf(rayTraceBlocks.getDirection() + .getNormal()) + .scale(.25f)), rayTraceBlocks.getBlockPos()); + earlyTargetTime = (float) (time + (source.distanceTo(vec) / source.distanceTo(target))); + sendData(); + return true; + } + + protected void nudgeEntities() { + for (Entity entity : level.getEntitiesOfClass(Entity.class, + new AABB(worldPosition).inflate(-1 / 16f, 0, -1 / 16f))) { + if (!entity.isAlive()) + continue; + if (entity.getPistonPushReaction() == PushReaction.IGNORE) + continue; + if (!(entity instanceof Player)) + entity.setPos(entity.getX(), entity.getY() + .125f, entity.getZ()); + } + } + + protected void ejectIfTriggered() { + if (powered) + return; + int presentStackSize = depotBehaviour.getPresentStackSize(); + if (presentStackSize == 0) + return; + if (presentStackSize < maxStackSize.getValue()) + return; + if (depotBehaviour.heldItem != null && depotBehaviour.heldItem.beltPosition < .49f) + return; + + Direction funnelFacing = getFacing().getOpposite(); + ItemStack held = depotBehaviour.getHeldItemStack(); + if (AbstractFunnelBlock.getFunnelFacing(level.getBlockState(worldPosition.above())) == funnelFacing) { + DirectBeltInputBehaviour directOutput = getBehaviour(DirectBeltInputBehaviour.TYPE); + if (depotBehaviour.heldItem != null) { + ItemStack tryFunnel = directOutput.tryExportingToBeltFunnel(held, funnelFacing, true); + if (tryFunnel == null || !tryFunnel.isEmpty()) + return; + } + } + + DirectBeltInputBehaviour targetOpenInv = getTargetOpenInv(); + + // Do not eject if target cannot accept held item + if (targetOpenInv != null && depotBehaviour.heldItem != null + && targetOpenInv.handleInsertion(held, Direction.UP, true) + .getCount() == held.getCount()) + return; + + activate(); + notifyUpdate(); + } + + protected void placeItemAtTarget(boolean doLogic, float maxTime, IntAttached intAttached) { + if (!doLogic) + return; + if (intAttached.getSecond() == trackedItem) + trackedItem = null; + + DirectBeltInputBehaviour targetOpenInv = getTargetOpenInv(); + if (targetOpenInv != null) { + ItemStack remainder = targetOpenInv.handleInsertion(intAttached.getValue(), Direction.UP, false); + intAttached.setSecond(remainder); + } + + if (intAttached.getValue() + .isEmpty()) + return; + + Vec3 ejectVec = earlyTarget != null ? earlyTarget.getFirst() : getLaunchedItemLocation(maxTime); + Vec3 ejectMotionVec = getLaunchedItemMotion(maxTime); + ItemEntity item = new ItemEntity(level, ejectVec.x, ejectVec.y, ejectVec.z, intAttached.getValue()); + item.setDeltaMovement(ejectMotionVec); + item.setDefaultPickUpDelay(); + level.addFreshEntity(item); + } + + public DirectBeltInputBehaviour getTargetOpenInv() { + BlockPos targetPos = earlyTarget != null ? earlyTarget.getSecond() + : worldPosition.above(launcher.getVerticalDistance()) + .relative(getFacing(), Math.max(1, launcher.getHorizontalDistance())); + return BlockEntityBehaviour.get(level, targetPos, DirectBeltInputBehaviour.TYPE); + } + + public Vec3 getLaunchedItemLocation(float time) { + return launcher.getGlobalPos(time, getFacing().getOpposite(), worldPosition); + } + + public Vec3 getLaunchedItemMotion(float time) { + return launcher.getGlobalVelocity(time, getFacing().getOpposite(), worldPosition) + .scale(.5f); + } + + @Override + public void destroy() { + super.destroy(); + dropFlyingItems(); + } + + public void dropFlyingItems() { + for (IntAttached intAttached : launchedItems) { + Vec3 ejectVec = getLaunchedItemLocation(intAttached.getFirst()); + Vec3 ejectMotionVec = getLaunchedItemMotion(intAttached.getFirst()); + ItemEntity item = new ItemEntity(level, 0, 0, 0, intAttached.getValue()); + item.setPosRaw(ejectVec.x, ejectVec.y, ejectVec.z); + item.setDeltaMovement(ejectMotionVec); + item.setDefaultPickUpDelay(); + level.addFreshEntity(item); + } + launchedItems.clear(); + } + + public float getWindUpSpeed() { + int hd = launcher.getHorizontalDistance(); + int vd = launcher.getVerticalDistance(); + + float speedFactor = Math.abs(getSpeed()) / 256f; + float distanceFactor; + if (hd == 0 && vd == 0) + distanceFactor = 1; + else + distanceFactor = 1 * Mth.sqrt(hd * hd + vd * vd); + return speedFactor / distanceFactor; + } + + @Override + protected void write(CompoundTag compound, boolean clientPacket) { + super.write(compound, clientPacket); + compound.putInt("HorizontalDistance", launcher.getHorizontalDistance()); + compound.putInt("VerticalDistance", launcher.getVerticalDistance()); + compound.putBoolean("Powered", powered); + NBTHelper.writeEnum(compound, "State", state); + compound.put("Lid", lidProgress.writeNBT()); + compound.put("LaunchedItems", + NBTHelper.writeCompoundList(launchedItems, ia -> ia.serializeNBT(ItemStack::serializeNBT))); + + if (earlyTarget != null) { + compound.put("EarlyTarget", VecHelper.writeNBT(earlyTarget.getFirst())); + compound.put("EarlyTargetPos", NbtUtils.writeBlockPos(earlyTarget.getSecond())); + compound.putFloat("EarlyTargetTime", earlyTargetTime); + } + } + + @Override + public void writeSafe(CompoundTag compound) { + super.writeSafe(compound); + compound.putInt("HorizontalDistance", launcher.getHorizontalDistance()); + compound.putInt("VerticalDistance", launcher.getVerticalDistance()); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + super.read(compound, clientPacket); + int horizontalDistance = compound.getInt("HorizontalDistance"); + int verticalDistance = compound.getInt("VerticalDistance"); + + if (launcher.getHorizontalDistance() != horizontalDistance + || launcher.getVerticalDistance() != verticalDistance) { + launcher.set(horizontalDistance, verticalDistance); + launcher.clamp(AllConfigs.server().kinetics.maxEjectorDistance.get()); + } + + powered = compound.getBoolean("Powered"); + state = NBTHelper.readEnum(compound, "State", State.class); + lidProgress.readNBT(compound.getCompound("Lid"), false); + launchedItems = NBTHelper.readCompoundList(compound.getList("LaunchedItems", Tag.TAG_COMPOUND), + nbt -> IntAttached.read(nbt, ItemStack::of)); + + earlyTarget = null; + earlyTargetTime = 0; + if (compound.contains("EarlyTarget")) { + earlyTarget = Pair.of(VecHelper.readNBT(compound.getList("EarlyTarget", Tag.TAG_DOUBLE)), + NbtUtils.readBlockPos(compound.getCompound("EarlyTargetPos"))); + earlyTargetTime = compound.getFloat("EarlyTargetTime"); + } + + if (compound.contains("ForceAngle")) + lidProgress.startWithValue(compound.getFloat("ForceAngle")); + } + + public void updateSignal() { + boolean shoudPower = level.hasNeighborSignal(worldPosition); + if (shoudPower == powered) + return; + powered = shoudPower; + sendData(); + } + + public void setTarget(int horizontalDistance, int verticalDistance) { + launcher.set(Math.max(1, horizontalDistance), verticalDistance); + sendData(); + } + + public BlockPos getTargetPosition() { + BlockState blockState = getBlockState(); + if (!AllBlocks.WEIGHTED_EJECTOR.has(blockState)) + return worldPosition; + Direction facing = blockState.getValue(EjectorBlock.HORIZONTAL_FACING); + return worldPosition.relative(facing, launcher.getHorizontalDistance()) + .above(launcher.getVerticalDistance()); + } + + @Override + public LazyOptional getCapability(Capability cap, Direction side) { + if (isItemHandlerCap(cap)) + return depotBehaviour.getItemCapability(cap, side); + return super.getCapability(cap, side); + } + + public float getLidProgress(float pt) { + return lidProgress.getValue(pt); + } + + public State getState() { + return state; + } + + @Override + @OnlyIn(Dist.CLIENT) + public AABB getRenderBoundingBox() { + return INFINITE_EXTENT_AABB; + } + + private static abstract class EntityHack extends Entity { + + public EntityHack(EntityType p_i48580_1_, Level p_i48580_2_) { + super(p_i48580_1_, p_i48580_2_); + } + + public static void setElytraFlying(Entity e) { + SynchedEntityData data = e.getEntityData(); + data.set(DATA_SHARED_FLAGS_ID, (byte) (data.get(DATA_SHARED_FLAGS_ID) | 1 << 7)); + } + + } + + private class EjectorSlot extends ValueBoxTransform.Sided { + + @Override + public Vec3 getLocalOffset(BlockState state) { + if (direction != Direction.UP) + return super.getLocalOffset(state); + return new Vec3(.5, 10.5 / 16f, .5).add(VecHelper.rotate(VecHelper.voxelSpace(0, 0, -5), angle(state), Axis.Y)); + } + + @Override + public void rotate(BlockState state, PoseStack ms) { + if (direction != Direction.UP) { + super.rotate(state, ms); + return; + } + TransformStack.cast(ms) + .rotateY(angle(state)) + .rotateX(90); + } + + protected float angle(BlockState state) { + float horizontalAngle = AllBlocks.WEIGHTED_EJECTOR.has(state) + ? AngleHelper.horizontalAngle(state.getValue(EjectorBlock.HORIZONTAL_FACING)) + : 0; + return horizontalAngle; + } + + @Override + protected boolean isSideActive(BlockState state, Direction direction) { + return direction.getAxis() == state.getValue(EjectorBlock.HORIZONTAL_FACING) + .getAxis() + || direction == Direction.UP && EjectorBlockEntity.this.state != EjectorBlockEntity.State.CHARGED; + } + + @Override + protected Vec3 getSouthLocation() { + return direction == Direction.UP ? Vec3.ZERO : VecHelper.voxelSpace(8, 6, 15.5); + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/depot/EjectorElytraPacket.java b/src/main/java/com/simibubi/create/content/logistics/depot/EjectorElytraPacket.java new file mode 100644 index 000000000..c625f91c9 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/depot/EjectorElytraPacket.java @@ -0,0 +1,45 @@ +package com.simibubi.create.content.logistics.depot; + +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraftforge.network.NetworkEvent.Context; + +public class EjectorElytraPacket extends SimplePacketBase { + + private BlockPos pos; + + public EjectorElytraPacket(BlockPos pos) { + this.pos = pos; + } + + public EjectorElytraPacket(FriendlyByteBuf buffer) { + pos = buffer.readBlockPos(); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeBlockPos(pos); + } + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> { + ServerPlayer player = context.getSender(); + if (player == null) + return; + Level world = player.level; + if (world == null || !world.isLoaded(pos)) + return; + BlockEntity blockEntity = world.getBlockEntity(pos); + if (blockEntity instanceof EjectorBlockEntity) + ((EjectorBlockEntity) blockEntity).deployElytra(player); + }); + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/depot/EjectorInstance.java b/src/main/java/com/simibubi/create/content/logistics/depot/EjectorInstance.java new file mode 100644 index 000000000..10b0b4d5d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/depot/EjectorInstance.java @@ -0,0 +1,61 @@ +package com.simibubi.create.content.logistics.depot; + +import com.jozufozu.flywheel.api.MaterialManager; +import com.jozufozu.flywheel.api.instance.DynamicInstance; +import com.jozufozu.flywheel.core.materials.model.ModelData; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.ShaftInstance; +import com.simibubi.create.foundation.utility.AnimationTickHolder; + +import net.minecraft.util.Mth; + +public class EjectorInstance extends ShaftInstance implements DynamicInstance { + + protected final ModelData plate; + + private float lastProgress = Float.NaN; + + public EjectorInstance(MaterialManager dispatcher, EjectorBlockEntity blockEntity) { + super(dispatcher, blockEntity); + + plate = getTransformMaterial().getModel(AllPartialModels.EJECTOR_TOP, blockState).createInstance(); + + pivotPlate(); + } + + @Override + public void beginFrame() { + float lidProgress = getLidProgress(); + + if (Mth.equal(lidProgress, lastProgress)) return; + + pivotPlate(lidProgress); + lastProgress = lidProgress; + } + + @Override + public void updateLight() { + super.updateLight(); + relight(pos, plate); + } + + @Override + public void remove() { + super.remove(); + plate.delete(); + } + + private void pivotPlate() { + pivotPlate(getLidProgress()); + } + + private float getLidProgress() { + return blockEntity.getLidProgress(AnimationTickHolder.getPartialTicks()); + } + + private void pivotPlate(float lidProgress) { + float angle = lidProgress * 70; + + EjectorRenderer.applyLidAngle(blockEntity, angle, plate.loadIdentity().translate(getInstancePosition())); + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorItem.java b/src/main/java/com/simibubi/create/content/logistics/depot/EjectorItem.java similarity index 87% rename from src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorItem.java rename to src/main/java/com/simibubi/create/content/logistics/depot/EjectorItem.java index a11995884..d1f59d626 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorItem.java +++ b/src/main/java/com/simibubi/create/content/logistics/depot/EjectorItem.java @@ -1,6 +1,6 @@ -package com.simibubi.create.content.logistics.block.depot; +package com.simibubi.create.content.logistics.depot; -import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.AllPackets; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerPlayer; @@ -41,8 +41,8 @@ public class EjectorItem extends BlockItem { protected boolean updateCustomBlockEntityTag(BlockPos pos, Level world, Player player, ItemStack p_195943_4_, BlockState p_195943_5_) { if (!world.isClientSide && player instanceof ServerPlayer sp) - AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> sp), - new EjectorPlacementPacket.ClientBoundRequest(pos)); + AllPackets.getChannel() + .send(PacketDistributor.PLAYER.with(() -> sp), new EjectorPlacementPacket.ClientBoundRequest(pos)); return super.updateCustomBlockEntityTag(pos, world, player, p_195943_4_, p_195943_5_); } diff --git a/src/main/java/com/simibubi/create/content/logistics/depot/EjectorPlacementPacket.java b/src/main/java/com/simibubi/create/content/logistics/depot/EjectorPlacementPacket.java new file mode 100644 index 000000000..32cdfc8e7 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/depot/EjectorPlacementPacket.java @@ -0,0 +1,90 @@ +package com.simibubi.create.content.logistics.depot; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.network.NetworkEvent.Context; + +public class EjectorPlacementPacket extends SimplePacketBase { + + private int h, v; + private BlockPos pos; + private Direction facing; + + public EjectorPlacementPacket(int h, int v, BlockPos pos, Direction facing) { + this.h = h; + this.v = v; + this.pos = pos; + this.facing = facing; + } + + public EjectorPlacementPacket(FriendlyByteBuf buffer) { + h = buffer.readInt(); + v = buffer.readInt(); + pos = buffer.readBlockPos(); + facing = Direction.from3DDataValue(buffer.readVarInt()); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeInt(h); + buffer.writeInt(v); + buffer.writeBlockPos(pos); + buffer.writeVarInt(facing.get3DDataValue()); + } + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> { + ServerPlayer player = context.getSender(); + if (player == null) + return; + Level world = player.level; + if (world == null || !world.isLoaded(pos)) + return; + BlockEntity blockEntity = world.getBlockEntity(pos); + BlockState state = world.getBlockState(pos); + if (blockEntity instanceof EjectorBlockEntity) + ((EjectorBlockEntity) blockEntity).setTarget(h, v); + if (AllBlocks.WEIGHTED_EJECTOR.has(state)) + world.setBlockAndUpdate(pos, state.setValue(EjectorBlock.HORIZONTAL_FACING, facing)); + }); + return true; + } + + public static class ClientBoundRequest extends SimplePacketBase { + + BlockPos pos; + + public ClientBoundRequest(BlockPos pos) { + this.pos = pos; + } + + public ClientBoundRequest(FriendlyByteBuf buffer) { + this.pos = buffer.readBlockPos(); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeBlockPos(pos); + } + + @Override + public boolean handle(Context context) { + context.enqueueWork( + () -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> EjectorTargetHandler.flushSettings(pos))); + return true; + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/depot/EjectorRenderer.java b/src/main/java/com/simibubi/create/content/logistics/depot/EjectorRenderer.java new file mode 100644 index 000000000..a03ded18b --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/depot/EjectorRenderer.java @@ -0,0 +1,106 @@ +package com.simibubi.create.content.logistics.depot; + +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.util.transform.Rotate; +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.jozufozu.flywheel.util.transform.Translate; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.base.ShaftRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.IntAttached; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.block.model.ItemTransforms.TransformType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.Vec3; + +public class EjectorRenderer extends ShaftRenderer { + + static final Vec3 pivot = VecHelper.voxelSpace(0, 11.25, 0.75); + + public EjectorRenderer(BlockEntityRendererProvider.Context context) { + super(context); + } + + @Override + public boolean shouldRenderOffScreen(EjectorBlockEntity p_188185_1_) { + return true; + } + + @Override + protected void renderSafe(EjectorBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + super.renderSafe(be, partialTicks, ms, buffer, light, overlay); + + VertexConsumer vertexBuilder = buffer.getBuffer(RenderType.solid()); + float lidProgress = be.getLidProgress(partialTicks); + float angle = lidProgress * 70; + + if (!Backend.canUseInstancing(be.getLevel())) { + SuperByteBuffer model = CachedBufferer.partial(AllPartialModels.EJECTOR_TOP, be.getBlockState()); + applyLidAngle(be, angle, model); + model.light(light) + .renderInto(ms, vertexBuilder); + } + + TransformStack msr = TransformStack.cast(ms); + + float maxTime = + (float) (be.earlyTarget != null ? be.earlyTargetTime : be.launcher.getTotalFlyingTicks()); + for (IntAttached intAttached : be.launchedItems) { + float time = intAttached.getFirst() + partialTicks; + if (time > maxTime) + continue; + + ms.pushPose(); + Vec3 launchedItemLocation = be.getLaunchedItemLocation(time); + msr.translate(launchedItemLocation.subtract(Vec3.atLowerCornerOf(be.getBlockPos()))); + Vec3 itemRotOffset = VecHelper.voxelSpace(0, 3, 0); + msr.translate(itemRotOffset); + msr.rotateY(AngleHelper.horizontalAngle(be.getFacing())); + msr.rotateX(time * 40); + msr.translateBack(itemRotOffset); + Minecraft.getInstance() + .getItemRenderer() + .renderStatic(intAttached.getValue(), TransformType.GROUND, light, overlay, ms, buffer, 0); + ms.popPose(); + } + + DepotBehaviour behaviour = be.getBehaviour(DepotBehaviour.TYPE); + if (behaviour == null || behaviour.isEmpty()) + return; + + ms.pushPose(); + applyLidAngle(be, angle, msr); + msr.centre() + .rotateY(-180 - AngleHelper.horizontalAngle(be.getBlockState() + .getValue(EjectorBlock.HORIZONTAL_FACING))) + .unCentre(); + DepotRenderer.renderItemsOf(be, partialTicks, ms, buffer, light, overlay, behaviour); + ms.popPose(); + } + + static & Rotate> void applyLidAngle(KineticBlockEntity be, float angle, T tr) { + applyLidAngle(be, pivot, angle, tr); + } + + static & Rotate> void applyLidAngle(KineticBlockEntity be, Vec3 rotationOffset, float angle, T tr) { + tr.centre() + .rotateY(180 + AngleHelper.horizontalAngle(be.getBlockState() + .getValue(EjectorBlock.HORIZONTAL_FACING))) + .unCentre() + .translate(rotationOffset) + .rotateX(-angle) + .translateBack(rotationOffset); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorTargetHandler.java b/src/main/java/com/simibubi/create/content/logistics/depot/EjectorTargetHandler.java similarity index 94% rename from src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorTargetHandler.java rename to src/main/java/com/simibubi/create/content/logistics/depot/EjectorTargetHandler.java index 952f437f0..661845f5d 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorTargetHandler.java +++ b/src/main/java/com/simibubi/create/content/logistics/depot/EjectorTargetHandler.java @@ -1,16 +1,16 @@ -package com.simibubi.create.content.logistics.block.depot; +package com.simibubi.create.content.logistics.depot; import org.joml.Vector3f; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; +import com.simibubi.create.AllPackets; import com.simibubi.create.CreateClient; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.Color; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; @@ -118,7 +118,7 @@ public class EjectorTargetHandler { h = Math.abs(diff.getX() + diff.getZ()); v = -diff.getY(); - AllPackets.channel.sendToServer(new EjectorPlacementPacket(h, v, pos, validTargetDirection)); + AllPackets.getChannel().sendToServer(new EjectorPlacementPacket(h, v, pos, validTargetDirection)); currentSelection = null; currentItem = null; @@ -132,7 +132,7 @@ public class EjectorTargetHandler { int xDiff = currentSelection.getX() - pos.getX(); int zDiff = currentSelection.getZ() - pos.getZ(); - int max = AllConfigs.SERVER.kinetics.maxEjectorDistance.get(); + int max = AllConfigs.server().kinetics.maxEjectorDistance.get(); if (Math.abs(xDiff) > max || Math.abs(zDiff) > max) return null; @@ -232,15 +232,15 @@ public class EjectorTargetHandler { BlockHitResult result = (BlockHitResult) objectMouseOver; BlockPos pos = result.getBlockPos(); - BlockEntity te = Minecraft.getInstance().level.getBlockEntity(pos); - if (!(te instanceof EjectorTileEntity)) { + BlockEntity be = Minecraft.getInstance().level.getBlockEntity(pos); + if (!(be instanceof EjectorBlockEntity)) { lastHoveredBlockPos = -1; currentSelection = null; return; } if (lastHoveredBlockPos == -1 || lastHoveredBlockPos != pos.asLong()) { - EjectorTileEntity ejector = (EjectorTileEntity) te; + EjectorBlockEntity ejector = (EjectorBlockEntity) be; if (!ejector.getTargetPosition() .equals(ejector.getBlockPos())) currentSelection = ejector.getTargetPosition(); diff --git a/src/main/java/com/simibubi/create/content/logistics/depot/EjectorTriggerPacket.java b/src/main/java/com/simibubi/create/content/logistics/depot/EjectorTriggerPacket.java new file mode 100644 index 000000000..94e359149 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/depot/EjectorTriggerPacket.java @@ -0,0 +1,29 @@ +package com.simibubi.create.content.logistics.depot; + +import com.simibubi.create.foundation.networking.BlockEntityConfigurationPacket; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; + +public class EjectorTriggerPacket extends BlockEntityConfigurationPacket { + + public EjectorTriggerPacket(BlockPos pos) { + super(pos); + } + + public EjectorTriggerPacket(FriendlyByteBuf buffer) { + super(buffer); + } + + @Override + protected void writeSettings(FriendlyByteBuf buffer) {} + + @Override + protected void readSettings(FriendlyByteBuf buffer) {} + + @Override + protected void applySettings(EjectorBlockEntity be) { + be.activate(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/depot/EntityLauncher.java b/src/main/java/com/simibubi/create/content/logistics/depot/EntityLauncher.java similarity index 98% rename from src/main/java/com/simibubi/create/content/logistics/block/depot/EntityLauncher.java rename to src/main/java/com/simibubi/create/content/logistics/depot/EntityLauncher.java index ac7101318..3495a7d20 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/depot/EntityLauncher.java +++ b/src/main/java/com/simibubi/create/content/logistics/depot/EntityLauncher.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.block.depot; +package com.simibubi.create.content.logistics.depot; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.VecHelper; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/depot/SharedDepotBlockMethods.java b/src/main/java/com/simibubi/create/content/logistics/depot/SharedDepotBlockMethods.java similarity index 87% rename from src/main/java/com/simibubi/create/content/logistics/block/depot/SharedDepotBlockMethods.java rename to src/main/java/com/simibubi/create/content/logistics/depot/SharedDepotBlockMethods.java index 9f16c24c8..9fea80749 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/depot/SharedDepotBlockMethods.java +++ b/src/main/java/com/simibubi/create/content/logistics/depot/SharedDepotBlockMethods.java @@ -1,11 +1,11 @@ -package com.simibubi.create.content.logistics.block.depot; +package com.simibubi.create.content.logistics.depot; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllSoundEvents; import com.simibubi.create.Create; -import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour; +import com.simibubi.create.content.kinetics.belt.behaviour.DirectBeltInputBehaviour; +import com.simibubi.create.content.kinetics.belt.transport.TransportedItemStack; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -27,7 +27,7 @@ import net.minecraftforge.items.ItemStackHandler; public class SharedDepotBlockMethods { protected static DepotBehaviour get(BlockGetter worldIn, BlockPos pos) { - return TileEntityBehaviour.get(worldIn, pos, DepotBehaviour.TYPE); + return BlockEntityBehaviour.get(worldIn, pos, DepotBehaviour.TYPE); } public static InteractionResult onUse(BlockState state, Level world, BlockPos pos, Player player, @@ -70,7 +70,7 @@ public class SharedDepotBlockMethods { AllSoundEvents.DEPOT_SLIDE.playOnServer(world, pos); } - behaviour.tileEntity.notifyUpdate(); + behaviour.blockEntity.notifyUpdate(); return InteractionResult.SUCCESS; } @@ -84,7 +84,7 @@ public class SharedDepotBlockMethods { ItemEntity itemEntity = (ItemEntity) entityIn; DirectBeltInputBehaviour inputBehaviour = - TileEntityBehaviour.get(worldIn, entityIn.blockPosition(), DirectBeltInputBehaviour.TYPE); + BlockEntityBehaviour.get(worldIn, entityIn.blockPosition(), DirectBeltInputBehaviour.TYPE); if (inputBehaviour == null) return; ItemStack remainder = inputBehaviour.handleInsertion(itemEntity.getItem(), Direction.DOWN, false); diff --git a/src/main/java/com/simibubi/create/content/logistics/filter/AbstractFilterMenu.java b/src/main/java/com/simibubi/create/content/logistics/filter/AbstractFilterMenu.java new file mode 100644 index 000000000..4a3d58625 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/filter/AbstractFilterMenu.java @@ -0,0 +1,65 @@ +package com.simibubi.create.content.logistics.filter; + +import com.simibubi.create.foundation.gui.menu.GhostItemMenu; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.ClickType; +import net.minecraft.world.inventory.MenuType; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public abstract class AbstractFilterMenu extends GhostItemMenu { + + protected AbstractFilterMenu(MenuType type, int id, Inventory inv, FriendlyByteBuf extraData) { + super(type, id, inv, extraData); + } + + protected AbstractFilterMenu(MenuType type, int id, Inventory inv, ItemStack contentHolder) { + super(type, id, inv, contentHolder); + } + + @Override + public void clicked(int slotId, int dragType, ClickType clickTypeIn, Player player) { + if (slotId == playerInventory.selected && clickTypeIn != ClickType.THROW) + return; + super.clicked(slotId, dragType, clickTypeIn, player); + } + + @Override + protected boolean allowRepeats() { + return false; + } + + @Override + @OnlyIn(Dist.CLIENT) + protected ItemStack createOnClient(FriendlyByteBuf extraData) { + return extraData.readItem(); + } + + protected abstract int getPlayerInventoryXOffset(); + + protected abstract int getPlayerInventoryYOffset(); + + protected abstract void addFilterSlots(); + + @Override + protected void addSlots() { + addPlayerSlots(getPlayerInventoryXOffset(), getPlayerInventoryYOffset()); + addFilterSlots(); + } + + @Override + protected void saveData(ItemStack contentHolder) { + contentHolder.getOrCreateTag() + .put("Items", ghostInventory.serializeNBT()); + } + + @Override + public boolean stillValid(Player player) { + return playerInventory.getSelected() == contentHolder; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/filter/AbstractFilterScreen.java b/src/main/java/com/simibubi/create/content/logistics/filter/AbstractFilterScreen.java new file mode 100644 index 000000000..f2ec3ab46 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/filter/AbstractFilterScreen.java @@ -0,0 +1,160 @@ +package com.simibubi.create.content.logistics.filter; + +import static com.simibubi.create.foundation.gui.AllGuiTextures.PLAYER_INVENTORY; + +import java.util.Collections; +import java.util.List; + +import com.google.common.collect.ImmutableList; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllItems; +import com.simibubi.create.AllPackets; +import com.simibubi.create.content.logistics.filter.FilterScreenPacket.Option; +import com.simibubi.create.foundation.gui.AllGuiTextures; +import com.simibubi.create.foundation.gui.AllIcons; +import com.simibubi.create.foundation.gui.element.GuiGameElement; +import com.simibubi.create.foundation.gui.menu.AbstractSimiContainerScreen; +import com.simibubi.create.foundation.gui.widget.IconButton; +import com.simibubi.create.foundation.gui.widget.Indicator; +import com.simibubi.create.foundation.gui.widget.Indicator.State; +import com.simibubi.create.foundation.item.TooltipHelper; +import com.simibubi.create.foundation.item.TooltipHelper.Palette; + +import net.minecraft.client.renderer.Rect2i; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.world.entity.player.Inventory; + +public abstract class AbstractFilterScreen extends AbstractSimiContainerScreen { + + protected AllGuiTextures background; + private List extraAreas = Collections.emptyList(); + + private IconButton resetButton; + private IconButton confirmButton; + + protected AbstractFilterScreen(F menu, Inventory inv, Component title, AllGuiTextures background) { + super(menu, inv, title); + this.background = background; + } + + @Override + protected void init() { + setWindowSize(Math.max(background.width, PLAYER_INVENTORY.width), + background.height + 4 + PLAYER_INVENTORY.height); + super.init(); + + int x = leftPos; + int y = topPos; + + resetButton = new IconButton(x + background.width - 62, y + background.height - 24, AllIcons.I_TRASH); + resetButton.withCallback(() -> { + menu.clearContents(); + contentsCleared(); + menu.sendClearPacket(); + }); + confirmButton = new IconButton(x + background.width - 33, y + background.height - 24, AllIcons.I_CONFIRM); + confirmButton.withCallback(() -> { + minecraft.player.closeContainer(); + }); + + addRenderableWidget(resetButton); + addRenderableWidget(confirmButton); + + extraAreas = ImmutableList.of(new Rect2i(x + background.width, y + background.height - 40, 80, 48)); + } + + @Override + protected void renderBg(PoseStack ms, float partialTicks, int mouseX, int mouseY) { + int invX = getLeftOfCentered(PLAYER_INVENTORY.width); + int invY = topPos + background.height + 4; + renderPlayerInventory(ms, invX, invY); + + int x = leftPos; + int y = topPos; + + background.render(ms, x, y, this); + font.draw(ms, title, x + (background.width - 8) / 2 - font.width(title) / 2, y + 4, + AllItems.FILTER.isIn(menu.contentHolder) ? 0x303030 : 0x592424); + + GuiGameElement.of(menu.contentHolder).at(x + background.width + 8, y + background.height - 52, -200) + .scale(4) + .render(ms); + } + + @Override + protected void containerTick() { + if (!menu.player.getMainHandItem() + .equals(menu.contentHolder, false)) + menu.player.closeContainer(); + + super.containerTick(); + + handleTooltips(); + handleIndicators(); + } + + protected void handleTooltips() { + List tooltipButtons = getTooltipButtons(); + + for (IconButton button : tooltipButtons) { + if (!button.getToolTip() + .isEmpty()) { + button.setToolTip(button.getToolTip() + .get(0)); + button.getToolTip() + .add(TooltipHelper.holdShift(Palette.YELLOW, hasShiftDown())); + } + } + + if (hasShiftDown()) { + List tooltipDescriptions = getTooltipDescriptions(); + for (int i = 0; i < tooltipButtons.size(); i++) + fillToolTip(tooltipButtons.get(i), tooltipDescriptions.get(i)); + } + } + + public void handleIndicators() { + for (IconButton button : getTooltipButtons()) + button.active = isButtonEnabled(button); + for (Indicator indicator : getIndicators()) + indicator.state = isIndicatorOn(indicator) ? State.ON : State.OFF; + } + + protected abstract boolean isButtonEnabled(IconButton button); + + protected abstract boolean isIndicatorOn(Indicator indicator); + + protected List getTooltipButtons() { + return Collections.emptyList(); + } + + protected List getTooltipDescriptions() { + return Collections.emptyList(); + } + + protected List getIndicators() { + return Collections.emptyList(); + } + + private void fillToolTip(IconButton button, Component tooltip) { + if (!button.isHoveredOrFocused()) + return; + List tip = button.getToolTip(); + tip.addAll(TooltipHelper.cutTextComponent(tooltip, Palette.ALL_GRAY)); + } + + protected void contentsCleared() {} + + protected void sendOptionUpdate(Option option) { + AllPackets.getChannel() + .sendToServer(new FilterScreenPacket(option)); + } + + @Override + public List getExtraAreas() { + return extraAreas; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/filter/AttributeFilterMenu.java b/src/main/java/com/simibubi/create/content/logistics/filter/AttributeFilterMenu.java new file mode 100644 index 000000000..b66c6f31a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/filter/AttributeFilterMenu.java @@ -0,0 +1,163 @@ +package com.simibubi.create.content.logistics.filter; + +import java.util.ArrayList; +import java.util.List; + +import com.simibubi.create.AllMenuTypes; +import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.Pair; + +import net.minecraft.ChatFormatting; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +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.minecraft.world.item.Items; +import net.minecraftforge.items.ItemStackHandler; +import net.minecraftforge.items.SlotItemHandler; + +public class AttributeFilterMenu extends AbstractFilterMenu { + + public enum WhitelistMode { + WHITELIST_DISJ, WHITELIST_CONJ, BLACKLIST; + } + + WhitelistMode whitelistMode; + List> selectedAttributes; + + public AttributeFilterMenu(MenuType type, int id, Inventory inv, FriendlyByteBuf extraData) { + super(type, id, inv, extraData); + } + + public AttributeFilterMenu(MenuType type, int id, Inventory inv, ItemStack stack) { + super(type, id, inv, stack); + } + + public static AttributeFilterMenu create(int id, Inventory inv, ItemStack stack) { + return new AttributeFilterMenu(AllMenuTypes.ATTRIBUTE_FILTER.get(), id, inv, stack); + } + + public void appendSelectedAttribute(ItemAttribute itemAttribute, boolean inverted) { + selectedAttributes.add(Pair.of(itemAttribute, inverted)); + } + + @Override + protected void init(Inventory inv, ItemStack contentHolder) { + super.init(inv, contentHolder); + ItemStack stack = new ItemStack(Items.NAME_TAG); + stack.setHoverName( + Components.literal("Selected Tags").withStyle(ChatFormatting.RESET, ChatFormatting.BLUE)); + ghostInventory.setStackInSlot(1, stack); + } + + @Override + protected int getPlayerInventoryXOffset() { + return 51; + } + + @Override + protected int getPlayerInventoryYOffset() { + return 107; + } + + @Override + protected void addFilterSlots() { + this.addSlot(new SlotItemHandler(ghostInventory, 0, 16, 24)); + this.addSlot(new SlotItemHandler(ghostInventory, 1, 22, 59) { + @Override + public boolean mayPickup(Player playerIn) { + return false; + } + }); + } + + @Override + protected ItemStackHandler createGhostInventory() { + return new ItemStackHandler(2); + } + + @Override + public void clearContents() { + selectedAttributes.clear(); + } + + @Override + public void clicked(int slotId, int dragType, ClickType clickTypeIn, Player player) { + if (slotId == 37) + return; + super.clicked(slotId, dragType, clickTypeIn, player); + } + + @Override + public boolean canDragTo(Slot slotIn) { + if (slotIn.index == 37) + return false; + return super.canDragTo(slotIn); + } + + @Override + public boolean canTakeItemForPickAll(ItemStack stack, Slot slotIn) { + if (slotIn.index == 37) + return false; + return super.canTakeItemForPickAll(stack, slotIn); + } + + @Override + public ItemStack quickMoveStack(Player playerIn, int index) { + if (index == 37) + return ItemStack.EMPTY; + if (index == 36) { + ghostInventory.setStackInSlot(37, ItemStack.EMPTY); + return ItemStack.EMPTY; + } + if (index < 36) { + ItemStack stackToInsert = playerInventory.getItem(index); + ItemStack copy = stackToInsert.copy(); + copy.setCount(1); + ghostInventory.setStackInSlot(0, copy); + } + return ItemStack.EMPTY; + } + + @Override + protected void initAndReadInventory(ItemStack filterItem) { + super.initAndReadInventory(filterItem); + selectedAttributes = new ArrayList<>(); + whitelistMode = WhitelistMode.values()[filterItem.getOrCreateTag() + .getInt("WhitelistMode")]; + ListTag attributes = filterItem.getOrCreateTag() + .getList("MatchedAttributes", Tag.TAG_COMPOUND); + attributes.forEach(inbt -> { + CompoundTag compound = (CompoundTag) inbt; + selectedAttributes.add(Pair.of(ItemAttribute.fromNBT(compound), compound.getBoolean("Inverted"))); + }); + } + + @Override + protected void saveData(ItemStack filterItem) { + filterItem.getOrCreateTag() + .putInt("WhitelistMode", whitelistMode.ordinal()); + ListTag attributes = new ListTag(); + selectedAttributes.forEach(at -> { + if (at == null) + return; + CompoundTag compoundNBT = new CompoundTag(); + at.getFirst() + .serializeNBT(compoundNBT); + compoundNBT.putBoolean("Inverted", at.getSecond()); + attributes.add(compoundNBT); + }); + filterItem.getOrCreateTag() + .put("MatchedAttributes", attributes); + + if (attributes.isEmpty() && whitelistMode == WhitelistMode.WHITELIST_DISJ) + filterItem.setTag(null); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/AttributeFilterScreen.java b/src/main/java/com/simibubi/create/content/logistics/filter/AttributeFilterScreen.java similarity index 89% rename from src/main/java/com/simibubi/create/content/logistics/item/filter/AttributeFilterScreen.java rename to src/main/java/com/simibubi/create/content/logistics/filter/AttributeFilterScreen.java index 924b38941..5617879a3 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/filter/AttributeFilterScreen.java +++ b/src/main/java/com/simibubi/create/content/logistics/filter/AttributeFilterScreen.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.item.filter; +package com.simibubi.create.content.logistics.filter; import java.util.ArrayList; import java.util.Arrays; @@ -6,15 +6,15 @@ import java.util.List; import java.util.stream.Collectors; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.content.logistics.item.filter.AttributeFilterContainer.WhitelistMode; -import com.simibubi.create.content.logistics.item.filter.FilterScreenPacket.Option; +import com.simibubi.create.AllPackets; +import com.simibubi.create.content.logistics.filter.AttributeFilterMenu.WhitelistMode; +import com.simibubi.create.content.logistics.filter.FilterScreenPacket.Option; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.gui.widget.IconButton; import com.simibubi.create.foundation.gui.widget.Indicator; import com.simibubi.create.foundation.gui.widget.Label; import com.simibubi.create.foundation.gui.widget.SelectionScrollInput; -import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Pair; @@ -26,7 +26,7 @@ import net.minecraft.network.chat.MutableComponent; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.item.ItemStack; -public class AttributeFilterScreen extends AbstractFilterScreen { +public class AttributeFilterScreen extends AbstractFilterScreen { private static final String PREFIX = "gui.attribute_filter."; @@ -55,8 +55,8 @@ public class AttributeFilterScreen extends AbstractFilterScreen { menu.whitelistMode = WhitelistMode.WHITELIST_DISJ; sendOptionUpdate(Option.WHITELIST); }); whitelistDis.setToolTip(allowDisN); - whitelistCon = new IconButton(x + 65, y + 59, AllIcons.I_WHITELIST_AND); + whitelistCon = new IconButton(x + 65, y + 61, AllIcons.I_WHITELIST_AND); whitelistCon.withCallback(() -> { menu.whitelistMode = WhitelistMode.WHITELIST_CONJ; sendOptionUpdate(Option.WHITELIST2); }); whitelistCon.setToolTip(allowConN); - blacklist = new IconButton(x + 83, y + 59, AllIcons.I_WHITELIST_NOT); + blacklist = new IconButton(x + 83, y + 61, AllIcons.I_WHITELIST_NOT); blacklist.withCallback(() -> { menu.whitelistMode = WhitelistMode.BLACKLIST; sendOptionUpdate(Option.BLACKLIST); }); blacklist.setToolTip(denyN); - whitelistDisIndicator = new Indicator(x + 47, y + 53, Components.immutableEmpty()); - whitelistConIndicator = new Indicator(x + 65, y + 53, Components.immutableEmpty()); - blacklistIndicator = new Indicator(x + 83, y + 53, Components.immutableEmpty()); + whitelistDisIndicator = new Indicator(x + 47, y + 55, Components.immutableEmpty()); + whitelistConIndicator = new Indicator(x + 65, y + 55, Components.immutableEmpty()); + blacklistIndicator = new Indicator(x + 83, y + 55, Components.immutableEmpty()); addRenderableWidgets(blacklist, whitelistCon, whitelistDis, blacklistIndicator, whitelistConIndicator, whitelistDisIndicator); - addRenderableWidget(add = new IconButton(x + 182, y + 21, AllIcons.I_ADD)); - addRenderableWidget(addInverted = new IconButton(x + 200, y + 21, AllIcons.I_ADD_INVERTED_ATTRIBUTE)); + addRenderableWidget(add = new IconButton(x + 182, y + 23, AllIcons.I_ADD)); + addRenderableWidget(addInverted = new IconButton(x + 200, y + 23, AllIcons.I_ADD_INVERTED_ATTRIBUTE)); add.withCallback(() -> { handleAddedAttibute(false); }); @@ -106,9 +106,9 @@ public class AttributeFilterScreen extends AbstractFilterScreen makeSummary = makeSummary(stack); if (makeSummary.isEmpty()) return; - ItemDescription.add(tooltip, Components.literal(" ")); - ItemDescription.add(tooltip, makeSummary); + tooltip.add(Components.literal(" ")); + tooltip.addAll(makeSummary); } } private List makeSummary(ItemStack filter) { List list = new ArrayList<>(); + if (!filter.hasTag()) + return list; if (type == FilterType.REGULAR) { ItemStackHandler filterItems = getFilterItems(filter); boolean blacklist = filter.getOrCreateTag() .getBoolean("Blacklist"); - list.add((blacklist ? Lang.translateDirect("gui.filter.deny_list") : Lang.translateDirect("gui.filter.allow_list")).withStyle(ChatFormatting.GOLD)); + list.add((blacklist ? Lang.translateDirect("gui.filter.deny_list") + : Lang.translateDirect("gui.filter.allow_list")).withStyle(ChatFormatting.GOLD)); int count = 0; for (int i = 0; i < filterItems.getSlots(); i++) { if (count > 3) { - list.add(Components.literal("- ...").withStyle(ChatFormatting.DARK_GRAY)); + list.add(Components.literal("- ...") + .withStyle(ChatFormatting.DARK_GRAY)); break; } ItemStack filterStack = filterItems.getStackInSlot(i); if (filterStack.isEmpty()) continue; - list.add(Components.literal("- ").append(filterStack.getHoverName()).withStyle(ChatFormatting.GRAY)); + list.add(Components.literal("- ") + .append(filterStack.getHoverName()) + .withStyle(ChatFormatting.GRAY)); count++; } @@ -122,12 +127,16 @@ public class FilterItem extends Item implements MenuProvider { for (Tag inbt : attributes) { CompoundTag compound = (CompoundTag) inbt; ItemAttribute attribute = ItemAttribute.fromNBT(compound); + if (attribute == null) + continue; boolean inverted = compound.getBoolean("Inverted"); if (count > 3) { - list.add(Components.literal("- ...").withStyle(ChatFormatting.DARK_GRAY)); + list.add(Components.literal("- ...") + .withStyle(ChatFormatting.DARK_GRAY)); break; } - list.add(Components.literal("- ").append(attribute.format(inverted))); + list.add(Components.literal("- ") + .append(attribute.format(inverted))); count++; } @@ -156,9 +165,9 @@ public class FilterItem extends Item implements MenuProvider { public AbstractContainerMenu createMenu(int id, Inventory inv, Player player) { ItemStack heldItem = player.getMainHandItem(); if (type == FilterType.REGULAR) - return FilterContainer.create(id, inv, heldItem); + return FilterMenu.create(id, inv, heldItem); if (type == FilterType.ATTRIBUTE) - return AttributeFilterContainer.create(id, inv, heldItem); + return AttributeFilterMenu.create(id, inv, heldItem); return null; } @@ -171,6 +180,8 @@ public class FilterItem extends Item implements MenuProvider { ItemStackHandler newInv = new ItemStackHandler(18); if (AllItems.FILTER.get() != stack.getItem()) throw new IllegalArgumentException("Cannot get filter items from non-filter: " + stack); + if (!stack.hasTag()) + return newInv; CompoundTag invNBT = stack.getOrCreateTagElement("Items"); if (!invNBT.isEmpty()) newInv.deserializeNBT(invNBT); @@ -185,36 +196,53 @@ public class FilterItem extends Item implements MenuProvider { return test(world, stack, filter, true); } - private static boolean test(Level world, ItemStack stack, ItemStack filter, boolean matchNBT) { + public static boolean test(Level world, ItemStack stack, ItemStack filter, boolean matchNBT) { if (filter.isEmpty()) return true; if (!(filter.getItem() instanceof FilterItem)) - return (matchNBT ? ItemHandlerHelper.canItemStacksStack(filter, stack) - : ItemStack.isSame(filter, stack)); + return testDirect(filter, stack, matchNBT); + + boolean defaults = !filter.hasTag(); + + if (defaults) { + return testDirect(filter, stack, matchNBT); + } if (AllItems.FILTER.get() == filter.getItem()) { ItemStackHandler filterItems = getFilterItems(filter); - boolean respectNBT = filter.getOrCreateTag() - .getBoolean("RespectNBT"); - boolean blacklist = filter.getOrCreateTag() - .getBoolean("Blacklist"); + boolean respectNBT = defaults ? false + : filter.getTag() + .getBoolean("RespectNBT"); + boolean blacklist = defaults ? false + : filter.getTag() + .getBoolean("Blacklist"); + boolean isEmpty = true; for (int slot = 0; slot < filterItems.getSlots(); slot++) { ItemStack stackInSlot = filterItems.getStackInSlot(slot); if (stackInSlot.isEmpty()) continue; + isEmpty = false; boolean matches = test(world, stack, stackInSlot, respectNBT); if (matches) return !blacklist; } + if (isEmpty) { + return testDirect(filter, stack, matchNBT); + } return blacklist; } if (AllItems.ATTRIBUTE_FILTER.get() == filter.getItem()) { - WhitelistMode whitelistMode = WhitelistMode.values()[filter.getOrCreateTag() - .getInt("WhitelistMode")]; - ListTag attributes = filter.getOrCreateTag() - .getList("MatchedAttributes", Tag.TAG_COMPOUND); + ListTag attributes = defaults ? new ListTag() + : filter.getTag() + .getList("MatchedAttributes", Tag.TAG_COMPOUND); + if (attributes.isEmpty()) { + return testDirect(filter, stack, matchNBT); + } + WhitelistMode whitelistMode = WhitelistMode.values()[defaults ? 0 + : filter.getTag() + .getInt("WhitelistMode")]; for (Tag inbt : attributes) { CompoundTag compound = (CompoundTag) inbt; ItemAttribute attribute = ItemAttribute.fromNBT(compound); @@ -256,16 +284,16 @@ public class FilterItem extends Item implements MenuProvider { return false; } - private static boolean test(Level world, FluidStack stack, ItemStack filter, boolean matchNBT) { + public static boolean test(Level world, FluidStack stack, ItemStack filter, boolean matchNBT) { if (filter.isEmpty()) return true; if (stack.isEmpty()) return false; if (!(filter.getItem() instanceof FilterItem)) { - if (!EmptyingByBasin.canItemBeEmptied(world, filter)) + if (!GenericItemEmptying.canItemBeEmptied(world, filter)) return false; - FluidStack fluidInFilter = EmptyingByBasin.emptyItem(world, filter, true) + FluidStack fluidInFilter = GenericItemEmptying.emptyItem(world, filter, true) .getFirst(); if (fluidInFilter == null) return false; @@ -276,12 +304,16 @@ public class FilterItem extends Item implements MenuProvider { return fluidEqual; } + boolean defaults = !filter.hasTag(); + if (AllItems.FILTER.get() == filter.getItem()) { ItemStackHandler filterItems = getFilterItems(filter); - boolean respectNBT = filter.getOrCreateTag() - .getBoolean("RespectNBT"); - boolean blacklist = filter.getOrCreateTag() - .getBoolean("Blacklist"); + boolean respectNBT = defaults ? false + : filter.getTag() + .getBoolean("RespectNBT"); + boolean blacklist = defaults ? false + : filter.getTag() + .getBoolean("Blacklist"); for (int slot = 0; slot < filterItems.getSlots(); slot++) { ItemStack stackInSlot = filterItems.getStackInSlot(slot); if (stackInSlot.isEmpty()) @@ -295,4 +327,12 @@ public class FilterItem extends Item implements MenuProvider { return false; } + private static boolean testDirect(ItemStack filter, ItemStack stack, boolean matchNBT) { + if (matchNBT) { + return ItemHandlerHelper.canItemStacksStack(filter, stack); + } else { + return ItemStack.isSame(filter, stack); + } + } + } diff --git a/src/main/java/com/simibubi/create/content/logistics/filter/FilterMenu.java b/src/main/java/com/simibubi/create/content/logistics/filter/FilterMenu.java new file mode 100644 index 000000000..29864709f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/filter/FilterMenu.java @@ -0,0 +1,78 @@ +package com.simibubi.create.content.logistics.filter; + +import com.simibubi.create.AllMenuTypes; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.inventory.MenuType; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.items.ItemStackHandler; +import net.minecraftforge.items.SlotItemHandler; + +public class FilterMenu extends AbstractFilterMenu { + + boolean respectNBT; + boolean blacklist; + + public FilterMenu(MenuType type, int id, Inventory inv, FriendlyByteBuf extraData) { + super(type, id, inv, extraData); + } + + public FilterMenu(MenuType type, int id, Inventory inv, ItemStack stack) { + super(type, id, inv, stack); + } + + public static FilterMenu create(int id, Inventory inv, ItemStack stack) { + return new FilterMenu(AllMenuTypes.FILTER.get(), id, inv, stack); + } + + @Override + protected int getPlayerInventoryXOffset() { + return 38; + } + + @Override + protected int getPlayerInventoryYOffset() { + return 121; + } + + @Override + protected void addFilterSlots() { + int x = 23; + int y = 22; + for (int row = 0; row < 2; ++row) + for (int col = 0; col < 9; ++col) + this.addSlot(new SlotItemHandler(ghostInventory, col + row * 9, x + col * 18, y + row * 18)); + } + + @Override + protected ItemStackHandler createGhostInventory() { + return FilterItem.getFilterItems(contentHolder); + } + + @Override + protected void initAndReadInventory(ItemStack filterItem) { + super.initAndReadInventory(filterItem); + CompoundTag tag = filterItem.getOrCreateTag(); + respectNBT = tag.getBoolean("RespectNBT"); + blacklist = tag.getBoolean("Blacklist"); + } + + @Override + protected void saveData(ItemStack filterItem) { + super.saveData(filterItem); + CompoundTag tag = filterItem.getOrCreateTag(); + tag.putBoolean("RespectNBT", respectNBT); + tag.putBoolean("Blacklist", blacklist); + + if (respectNBT || blacklist) + return; + for (int i = 0; i < ghostInventory.getSlots(); i++) + if (!ghostInventory.getStackInSlot(i) + .isEmpty()) + return; + filterItem.setTag(null); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/FilterScreen.java b/src/main/java/com/simibubi/create/content/logistics/filter/FilterScreen.java similarity index 80% rename from src/main/java/com/simibubi/create/content/logistics/item/filter/FilterScreen.java rename to src/main/java/com/simibubi/create/content/logistics/filter/FilterScreen.java index bdb5b0b0e..d2b5adb56 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/filter/FilterScreen.java +++ b/src/main/java/com/simibubi/create/content/logistics/filter/FilterScreen.java @@ -1,9 +1,9 @@ -package com.simibubi.create.content.logistics.item.filter; +package com.simibubi.create.content.logistics.filter; import java.util.Arrays; import java.util.List; -import com.simibubi.create.content.logistics.item.filter.FilterScreenPacket.Option; +import com.simibubi.create.content.logistics.filter.FilterScreenPacket.Option; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.gui.widget.IconButton; @@ -15,7 +15,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.world.entity.player.Inventory; -public class FilterScreen extends AbstractFilterScreen { +public class FilterScreen extends AbstractFilterScreen { private static final String PREFIX = "gui.filter."; @@ -34,8 +34,8 @@ public class FilterScreen extends AbstractFilterScreen { private Indicator whitelistIndicator, blacklistIndicator; private Indicator respectNBTIndicator, ignoreNBTIndicator; - public FilterScreen(FilterContainer container, Inventory inv, Component title) { - super(container, inv, title, AllGuiTextures.FILTER); + public FilterScreen(FilterMenu menu, Inventory inv, Component title) { + super(menu, inv, title, AllGuiTextures.FILTER); } @Override @@ -46,36 +46,36 @@ public class FilterScreen extends AbstractFilterScreen { int x = leftPos; int y = topPos; - blacklist = new IconButton(x + 18, y + 73, AllIcons.I_BLACKLIST); + blacklist = new IconButton(x + 18, y + 75, AllIcons.I_BLACKLIST); blacklist.withCallback(() -> { menu.blacklist = true; sendOptionUpdate(Option.BLACKLIST); }); blacklist.setToolTip(denyN); - whitelist = new IconButton(x + 36, y + 73, AllIcons.I_WHITELIST); + whitelist = new IconButton(x + 36, y + 75, AllIcons.I_WHITELIST); whitelist.withCallback(() -> { menu.blacklist = false; sendOptionUpdate(Option.WHITELIST); }); whitelist.setToolTip(allowN); - blacklistIndicator = new Indicator(x + 18, y + 67, Components.immutableEmpty()); - whitelistIndicator = new Indicator(x + 36, y + 67, Components.immutableEmpty()); + blacklistIndicator = new Indicator(x + 18, y + 69, Components.immutableEmpty()); + whitelistIndicator = new Indicator(x + 36, y + 69, Components.immutableEmpty()); addRenderableWidgets(blacklist, whitelist, blacklistIndicator, whitelistIndicator); - respectNBT = new IconButton(x + 60, y + 73, AllIcons.I_RESPECT_NBT); + respectNBT = new IconButton(x + 60, y + 75, AllIcons.I_RESPECT_NBT); respectNBT.withCallback(() -> { menu.respectNBT = true; sendOptionUpdate(Option.RESPECT_DATA); }); respectNBT.setToolTip(respectDataN); - ignoreNBT = new IconButton(x + 78, y + 73, AllIcons.I_IGNORE_NBT); + ignoreNBT = new IconButton(x + 78, y + 75, AllIcons.I_IGNORE_NBT); ignoreNBT.withCallback(() -> { menu.respectNBT = false; sendOptionUpdate(Option.IGNORE_DATA); }); ignoreNBT.setToolTip(ignoreDataN); - respectNBTIndicator = new Indicator(x + 60, y + 67, Components.immutableEmpty()); - ignoreNBTIndicator = new Indicator(x + 78, y + 67, Components.immutableEmpty()); + respectNBTIndicator = new Indicator(x + 60, y + 69, Components.immutableEmpty()); + ignoreNBTIndicator = new Indicator(x + 78, y + 69, Components.immutableEmpty()); addRenderableWidgets(respectNBT, ignoreNBT, respectNBTIndicator, ignoreNBTIndicator); handleIndicators(); diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/FilterScreenPacket.java b/src/main/java/com/simibubi/create/content/logistics/filter/FilterScreenPacket.java similarity index 75% rename from src/main/java/com/simibubi/create/content/logistics/item/filter/FilterScreenPacket.java rename to src/main/java/com/simibubi/create/content/logistics/filter/FilterScreenPacket.java index 8b1b5440c..2896d8abc 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/filter/FilterScreenPacket.java +++ b/src/main/java/com/simibubi/create/content/logistics/filter/FilterScreenPacket.java @@ -1,8 +1,6 @@ -package com.simibubi.create.content.logistics.item.filter; +package com.simibubi.create.content.logistics.filter; -import java.util.function.Supplier; - -import com.simibubi.create.content.logistics.item.filter.AttributeFilterContainer.WhitelistMode; +import com.simibubi.create.content.logistics.filter.AttributeFilterMenu.WhitelistMode; import com.simibubi.create.foundation.networking.SimplePacketBase; import net.minecraft.nbt.CompoundTag; @@ -40,14 +38,14 @@ public class FilterScreenPacket extends SimplePacketBase { } @Override - public void handle(Supplier context) { - context.get().enqueueWork(() -> { - ServerPlayer player = context.get().getSender(); + public boolean handle(Context context) { + context.enqueueWork(() -> { + ServerPlayer player = context.getSender(); if (player == null) return; - if (player.containerMenu instanceof FilterContainer) { - FilterContainer c = (FilterContainer) player.containerMenu; + if (player.containerMenu instanceof FilterMenu) { + FilterMenu c = (FilterMenu) player.containerMenu; if (option == Option.WHITELIST) c.blacklist = false; if (option == Option.BLACKLIST) @@ -62,8 +60,8 @@ public class FilterScreenPacket extends SimplePacketBase { net.minecraft.world.item.ItemStack.of(data.getCompound("Item"))); } - if (player.containerMenu instanceof AttributeFilterContainer) { - AttributeFilterContainer c = (AttributeFilterContainer) player.containerMenu; + if (player.containerMenu instanceof AttributeFilterMenu) { + AttributeFilterMenu c = (AttributeFilterMenu) player.containerMenu; if (option == Option.WHITELIST) c.whitelistMode = WhitelistMode.WHITELIST_DISJ; if (option == Option.WHITELIST2) @@ -77,7 +75,7 @@ public class FilterScreenPacket extends SimplePacketBase { } }); - context.get().setPacketHandled(true); + return true; } } diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/ItemAttribute.java b/src/main/java/com/simibubi/create/content/logistics/filter/ItemAttribute.java similarity index 87% rename from src/main/java/com/simibubi/create/content/logistics/item/filter/ItemAttribute.java rename to src/main/java/com/simibubi/create/content/logistics/filter/ItemAttribute.java index e46660686..67d38c959 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/filter/ItemAttribute.java +++ b/src/main/java/com/simibubi/create/content/logistics/filter/ItemAttribute.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.item.filter; +package com.simibubi.create.content.logistics.filter; import java.util.ArrayList; import java.util.Arrays; @@ -10,20 +10,21 @@ import java.util.function.Predicate; import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; +import org.jetbrains.annotations.Nullable; import com.simibubi.create.AllRecipeTypes; -import com.simibubi.create.content.contraptions.processing.InWorldProcessing; -import com.simibubi.create.content.logistics.item.filter.attribute.BookAuthorAttribute; -import com.simibubi.create.content.logistics.item.filter.attribute.BookCopyAttribute; -import com.simibubi.create.content.logistics.item.filter.attribute.ColorAttribute; -import com.simibubi.create.content.logistics.item.filter.attribute.EnchantAttribute; -import com.simibubi.create.content.logistics.item.filter.attribute.FluidContentsAttribute; -import com.simibubi.create.content.logistics.item.filter.attribute.ItemNameAttribute; -import com.simibubi.create.content.logistics.item.filter.attribute.ShulkerFillLevelAttribute; -import com.simibubi.create.content.logistics.item.filter.attribute.astralsorcery.AstralSorceryAmuletAttribute; -import com.simibubi.create.content.logistics.item.filter.attribute.astralsorcery.AstralSorceryAttunementAttribute; -import com.simibubi.create.content.logistics.item.filter.attribute.astralsorcery.AstralSorceryCrystalAttribute; -import com.simibubi.create.content.logistics.item.filter.attribute.astralsorcery.AstralSorceryPerkGemAttribute; +import com.simibubi.create.content.kinetics.fan.FanProcessing; +import com.simibubi.create.content.logistics.filter.attribute.BookAuthorAttribute; +import com.simibubi.create.content.logistics.filter.attribute.BookCopyAttribute; +import com.simibubi.create.content.logistics.filter.attribute.ColorAttribute; +import com.simibubi.create.content.logistics.filter.attribute.EnchantAttribute; +import com.simibubi.create.content.logistics.filter.attribute.FluidContentsAttribute; +import com.simibubi.create.content.logistics.filter.attribute.ItemNameAttribute; +import com.simibubi.create.content.logistics.filter.attribute.ShulkerFillLevelAttribute; +import com.simibubi.create.content.logistics.filter.attribute.astralsorcery.AstralSorceryAmuletAttribute; +import com.simibubi.create.content.logistics.filter.attribute.astralsorcery.AstralSorceryAttunementAttribute; +import com.simibubi.create.content.logistics.filter.attribute.astralsorcery.AstralSorceryCrystalAttribute; +import com.simibubi.create.content.logistics.filter.attribute.astralsorcery.AstralSorceryPerkGemAttribute; import com.simibubi.create.foundation.utility.Lang; import net.minecraft.nbt.CompoundTag; @@ -76,6 +77,7 @@ public interface ItemAttribute { return attributeType; } + @Nullable static ItemAttribute fromNBT(CompoundTag nbt) { for (ItemAttribute itemAttribute : types) if (itemAttribute.canRead(nbt)) @@ -141,8 +143,8 @@ public interface ItemAttribute { EQUIPABLE(s -> LivingEntity.getEquipmentSlotForItem(s) .getType() != EquipmentSlot.Type.HAND), FURNACE_FUEL(AbstractFurnaceBlockEntity::isFuel), - WASHABLE(InWorldProcessing::isWashable), - HAUNTABLE(InWorldProcessing::isHauntable), + WASHABLE(FanProcessing::isWashable), + HAUNTABLE(FanProcessing::isHauntable), CRUSHABLE((s, w) -> testRecipe(s, w, AllRecipeTypes.CRUSHING.getType()) || testRecipe(s, w, AllRecipeTypes.MILLING.getType())), SMELTABLE((s, w) -> testRecipe(s, w, RecipeType.SMELTING)), diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/BookAuthorAttribute.java b/src/main/java/com/simibubi/create/content/logistics/filter/attribute/BookAuthorAttribute.java similarity index 90% rename from src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/BookAuthorAttribute.java rename to src/main/java/com/simibubi/create/content/logistics/filter/attribute/BookAuthorAttribute.java index 9e7d8c026..c0eaf419f 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/BookAuthorAttribute.java +++ b/src/main/java/com/simibubi/create/content/logistics/filter/attribute/BookAuthorAttribute.java @@ -1,9 +1,9 @@ -package com.simibubi.create.content.logistics.item.filter.attribute; +package com.simibubi.create.content.logistics.filter.attribute; import java.util.ArrayList; import java.util.List; -import com.simibubi.create.content.logistics.item.filter.ItemAttribute; +import com.simibubi.create.content.logistics.filter.ItemAttribute; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.ItemStack; diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/BookCopyAttribute.java b/src/main/java/com/simibubi/create/content/logistics/filter/attribute/BookCopyAttribute.java similarity index 92% rename from src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/BookCopyAttribute.java rename to src/main/java/com/simibubi/create/content/logistics/filter/attribute/BookCopyAttribute.java index 88a3c7c87..04a60b8b3 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/BookCopyAttribute.java +++ b/src/main/java/com/simibubi/create/content/logistics/filter/attribute/BookCopyAttribute.java @@ -1,9 +1,9 @@ -package com.simibubi.create.content.logistics.item.filter.attribute; +package com.simibubi.create.content.logistics.filter.attribute; import java.util.ArrayList; import java.util.List; -import com.simibubi.create.content.logistics.item.filter.ItemAttribute; +import com.simibubi.create.content.logistics.filter.ItemAttribute; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.ItemStack; diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/ColorAttribute.java b/src/main/java/com/simibubi/create/content/logistics/filter/attribute/ColorAttribute.java similarity index 95% rename from src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/ColorAttribute.java rename to src/main/java/com/simibubi/create/content/logistics/filter/attribute/ColorAttribute.java index d41a6da25..59fc5ec70 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/ColorAttribute.java +++ b/src/main/java/com/simibubi/create/content/logistics/filter/attribute/ColorAttribute.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.item.filter.attribute; +package com.simibubi.create.content.logistics.filter.attribute; import java.util.Arrays; import java.util.Collection; @@ -8,7 +8,7 @@ import java.util.List; import java.util.Set; import java.util.stream.Collectors; -import com.simibubi.create.content.logistics.item.filter.ItemAttribute; +import com.simibubi.create.content.logistics.filter.ItemAttribute; import com.simibubi.create.foundation.utility.RegisteredObjects; import net.minecraft.client.resources.language.I18n; diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/EnchantAttribute.java b/src/main/java/com/simibubi/create/content/logistics/filter/attribute/EnchantAttribute.java similarity index 93% rename from src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/EnchantAttribute.java rename to src/main/java/com/simibubi/create/content/logistics/filter/attribute/EnchantAttribute.java index f64614243..fb61fe07f 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/EnchantAttribute.java +++ b/src/main/java/com/simibubi/create/content/logistics/filter/attribute/EnchantAttribute.java @@ -1,11 +1,11 @@ -package com.simibubi.create.content.logistics.item.filter.attribute; +package com.simibubi.create.content.logistics.filter.attribute; import java.util.List; import java.util.stream.Collectors; import javax.annotation.Nullable; -import com.simibubi.create.content.logistics.item.filter.ItemAttribute; +import com.simibubi.create.content.logistics.filter.ItemAttribute; import com.simibubi.create.foundation.utility.Components; import net.minecraft.nbt.CompoundTag; diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/FluidContentsAttribute.java b/src/main/java/com/simibubi/create/content/logistics/filter/attribute/FluidContentsAttribute.java similarity index 93% rename from src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/FluidContentsAttribute.java rename to src/main/java/com/simibubi/create/content/logistics/filter/attribute/FluidContentsAttribute.java index e78a75642..45c2a8402 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/FluidContentsAttribute.java +++ b/src/main/java/com/simibubi/create/content/logistics/filter/attribute/FluidContentsAttribute.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.item.filter.attribute; +package com.simibubi.create.content.logistics.filter.attribute; import java.util.ArrayList; import java.util.List; @@ -6,7 +6,7 @@ import java.util.stream.Collectors; import javax.annotation.Nullable; -import com.simibubi.create.content.logistics.item.filter.ItemAttribute; +import com.simibubi.create.content.logistics.filter.ItemAttribute; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/ItemNameAttribute.java b/src/main/java/com/simibubi/create/content/logistics/filter/attribute/ItemNameAttribute.java similarity index 92% rename from src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/ItemNameAttribute.java rename to src/main/java/com/simibubi/create/content/logistics/filter/attribute/ItemNameAttribute.java index ab3ff572b..83bab8d96 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/ItemNameAttribute.java +++ b/src/main/java/com/simibubi/create/content/logistics/filter/attribute/ItemNameAttribute.java @@ -1,10 +1,10 @@ -package com.simibubi.create.content.logistics.item.filter.attribute; +package com.simibubi.create.content.logistics.filter.attribute; import java.util.ArrayList; import java.util.List; import com.google.gson.JsonParseException; -import com.simibubi.create.content.logistics.item.filter.ItemAttribute; +import com.simibubi.create.content.logistics.filter.ItemAttribute; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/ShulkerFillLevelAttribute.java b/src/main/java/com/simibubi/create/content/logistics/filter/attribute/ShulkerFillLevelAttribute.java similarity index 95% rename from src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/ShulkerFillLevelAttribute.java rename to src/main/java/com/simibubi/create/content/logistics/filter/attribute/ShulkerFillLevelAttribute.java index 86fca30e0..9f0f20b06 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/ShulkerFillLevelAttribute.java +++ b/src/main/java/com/simibubi/create/content/logistics/filter/attribute/ShulkerFillLevelAttribute.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.item.filter.attribute; +package com.simibubi.create.content.logistics.filter.attribute; import java.util.Arrays; import java.util.List; @@ -7,7 +7,7 @@ import java.util.stream.Collectors; import javax.annotation.Nullable; -import com.simibubi.create.content.logistics.item.filter.ItemAttribute; +import com.simibubi.create.content.logistics.filter.ItemAttribute; import com.simibubi.create.foundation.utility.Lang; import net.minecraft.core.NonNullList; diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/astralsorcery/AstralSorceryAmuletAttribute.java b/src/main/java/com/simibubi/create/content/logistics/filter/attribute/astralsorcery/AstralSorceryAmuletAttribute.java similarity index 94% rename from src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/astralsorcery/AstralSorceryAmuletAttribute.java rename to src/main/java/com/simibubi/create/content/logistics/filter/attribute/astralsorcery/AstralSorceryAmuletAttribute.java index 76f3b351f..0bca33be9 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/astralsorcery/AstralSorceryAmuletAttribute.java +++ b/src/main/java/com/simibubi/create/content/logistics/filter/attribute/astralsorcery/AstralSorceryAmuletAttribute.java @@ -1,9 +1,9 @@ -package com.simibubi.create.content.logistics.item.filter.attribute.astralsorcery; +package com.simibubi.create.content.logistics.filter.attribute.astralsorcery; import java.util.ArrayList; import java.util.List; -import com.simibubi.create.content.logistics.item.filter.ItemAttribute; +import com.simibubi.create.content.logistics.filter.ItemAttribute; import com.simibubi.create.foundation.utility.Components; import net.minecraft.nbt.CompoundTag; diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/astralsorcery/AstralSorceryAttunementAttribute.java b/src/main/java/com/simibubi/create/content/logistics/filter/attribute/astralsorcery/AstralSorceryAttunementAttribute.java similarity index 94% rename from src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/astralsorcery/AstralSorceryAttunementAttribute.java rename to src/main/java/com/simibubi/create/content/logistics/filter/attribute/astralsorcery/AstralSorceryAttunementAttribute.java index be706047b..139eefe69 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/astralsorcery/AstralSorceryAttunementAttribute.java +++ b/src/main/java/com/simibubi/create/content/logistics/filter/attribute/astralsorcery/AstralSorceryAttunementAttribute.java @@ -1,9 +1,9 @@ -package com.simibubi.create.content.logistics.item.filter.attribute.astralsorcery; +package com.simibubi.create.content.logistics.filter.attribute.astralsorcery; import java.util.ArrayList; import java.util.List; -import com.simibubi.create.content.logistics.item.filter.ItemAttribute; +import com.simibubi.create.content.logistics.filter.ItemAttribute; import com.simibubi.create.foundation.utility.Components; import net.minecraft.nbt.CompoundTag; diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/astralsorcery/AstralSorceryCrystalAttribute.java b/src/main/java/com/simibubi/create/content/logistics/filter/attribute/astralsorcery/AstralSorceryCrystalAttribute.java similarity index 93% rename from src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/astralsorcery/AstralSorceryCrystalAttribute.java rename to src/main/java/com/simibubi/create/content/logistics/filter/attribute/astralsorcery/AstralSorceryCrystalAttribute.java index d33a7e6c5..d55d33771 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/astralsorcery/AstralSorceryCrystalAttribute.java +++ b/src/main/java/com/simibubi/create/content/logistics/filter/attribute/astralsorcery/AstralSorceryCrystalAttribute.java @@ -1,9 +1,9 @@ -package com.simibubi.create.content.logistics.item.filter.attribute.astralsorcery; +package com.simibubi.create.content.logistics.filter.attribute.astralsorcery; import java.util.ArrayList; import java.util.List; -import com.simibubi.create.content.logistics.item.filter.ItemAttribute; +import com.simibubi.create.content.logistics.filter.ItemAttribute; import com.simibubi.create.foundation.utility.Components; import net.minecraft.nbt.CompoundTag; diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/astralsorcery/AstralSorceryPerkGemAttribute.java b/src/main/java/com/simibubi/create/content/logistics/filter/attribute/astralsorcery/AstralSorceryPerkGemAttribute.java similarity index 93% rename from src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/astralsorcery/AstralSorceryPerkGemAttribute.java rename to src/main/java/com/simibubi/create/content/logistics/filter/attribute/astralsorcery/AstralSorceryPerkGemAttribute.java index 2e8e476fd..3e567c396 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/astralsorcery/AstralSorceryPerkGemAttribute.java +++ b/src/main/java/com/simibubi/create/content/logistics/filter/attribute/astralsorcery/AstralSorceryPerkGemAttribute.java @@ -1,9 +1,9 @@ -package com.simibubi.create.content.logistics.item.filter.attribute.astralsorcery; +package com.simibubi.create.content.logistics.filter.attribute.astralsorcery; import java.util.ArrayList; import java.util.List; -import com.simibubi.create.content.logistics.item.filter.ItemAttribute; +import com.simibubi.create.content.logistics.filter.ItemAttribute; import com.simibubi.create.foundation.utility.Components; import net.minecraft.nbt.CompoundTag; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/flap/FlapData.java b/src/main/java/com/simibubi/create/content/logistics/flwdata/FlapData.java similarity index 97% rename from src/main/java/com/simibubi/create/content/logistics/block/flap/FlapData.java rename to src/main/java/com/simibubi/create/content/logistics/flwdata/FlapData.java index d95e4c28b..453c109a7 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/flap/FlapData.java +++ b/src/main/java/com/simibubi/create/content/logistics/flwdata/FlapData.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.block.flap; +package com.simibubi.create.content.logistics.flwdata; import org.joml.Vector3f; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/flap/FlapType.java b/src/main/java/com/simibubi/create/content/logistics/flwdata/FlapType.java similarity index 96% rename from src/main/java/com/simibubi/create/content/logistics/block/flap/FlapType.java rename to src/main/java/com/simibubi/create/content/logistics/flwdata/FlapType.java index 1745d78db..42adae76e 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/flap/FlapType.java +++ b/src/main/java/com/simibubi/create/content/logistics/flwdata/FlapType.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.block.flap; +package com.simibubi.create.content.logistics.flwdata; import com.jozufozu.flywheel.api.struct.Batched; import com.jozufozu.flywheel.api.struct.Instanced; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/flap/UnsafeFlapWriter.java b/src/main/java/com/simibubi/create/content/logistics/flwdata/UnsafeFlapWriter.java similarity index 95% rename from src/main/java/com/simibubi/create/content/logistics/block/flap/UnsafeFlapWriter.java rename to src/main/java/com/simibubi/create/content/logistics/flwdata/UnsafeFlapWriter.java index 345fde063..4ca7961d5 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/flap/UnsafeFlapWriter.java +++ b/src/main/java/com/simibubi/create/content/logistics/flwdata/UnsafeFlapWriter.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.block.flap; +package com.simibubi.create.content.logistics.flwdata; import org.lwjgl.system.MemoryUtil; diff --git a/src/main/java/com/simibubi/create/content/logistics/flwdata/package-info.java b/src/main/java/com/simibubi/create/content/logistics/flwdata/package-info.java new file mode 100644 index 000000000..5f4c5ce95 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/flwdata/package-info.java @@ -0,0 +1,6 @@ +@ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault +package com.simibubi.create.content.logistics.flwdata; + +import javax.annotation.ParametersAreNonnullByDefault; + +import net.minecraft.MethodsReturnNonnullByDefault; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/funnel/AbstractDirectionalFunnelBlock.java b/src/main/java/com/simibubi/create/content/logistics/funnel/AbstractDirectionalFunnelBlock.java similarity index 95% rename from src/main/java/com/simibubi/create/content/logistics/block/funnel/AbstractDirectionalFunnelBlock.java rename to src/main/java/com/simibubi/create/content/logistics/funnel/AbstractDirectionalFunnelBlock.java index 9fabd9a11..2d7627ed8 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/funnel/AbstractDirectionalFunnelBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/funnel/AbstractDirectionalFunnelBlock.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.block.funnel; +package com.simibubi.create.content.logistics.funnel; import net.minecraft.core.Direction; import net.minecraft.world.level.block.Block; diff --git a/src/main/java/com/simibubi/create/content/logistics/funnel/AbstractFunnelBlock.java b/src/main/java/com/simibubi/create/content/logistics/funnel/AbstractFunnelBlock.java new file mode 100644 index 000000000..f24c09370 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/funnel/AbstractFunnelBlock.java @@ -0,0 +1,162 @@ +package com.simibubi.create.content.logistics.funnel; + +import java.util.function.Consumer; + +import javax.annotation.Nullable; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.block.ProperWaterloggedBlock; +import com.simibubi.create.foundation.block.render.ReducedDestroyEffects; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.inventory.InvManipulationBehaviour; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.item.ItemStack; +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.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition.Builder; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.level.pathfinder.PathComputationType; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.client.extensions.common.IClientBlockExtensions; + +public abstract class AbstractFunnelBlock extends Block + implements IBE, IWrenchable, ProperWaterloggedBlock { + + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; + + protected AbstractFunnelBlock(Properties p_i48377_1_) { + super(p_i48377_1_); + registerDefaultState(defaultBlockState().setValue(POWERED, false) + .setValue(WATERLOGGED, false)); + } + + @OnlyIn(Dist.CLIENT) + public void initializeClient(Consumer consumer) { + consumer.accept(new ReducedDestroyEffects()); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext context) { + return withWater(defaultBlockState().setValue(POWERED, context.getLevel() + .hasNeighborSignal(context.getClickedPos())), context); + } + + @Override + public FluidState getFluidState(BlockState pState) { + return fluidState(pState); + } + + @Override + public BlockState updateShape(BlockState pState, Direction pDirection, BlockState pNeighborState, + LevelAccessor pLevel, BlockPos pCurrentPos, BlockPos pNeighborPos) { + updateWater(pLevel, pState, pCurrentPos); + return pState; + } + + @Override + public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) { + return false; + } + + @Override + protected void createBlockStateDefinition(Builder builder) { + super.createBlockStateDefinition(builder.add(POWERED, WATERLOGGED)); + } + + @Override + public void neighborChanged(BlockState state, Level worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, + boolean isMoving) { + if (worldIn.isClientSide) + return; + InvManipulationBehaviour behaviour = BlockEntityBehaviour.get(worldIn, pos, InvManipulationBehaviour.TYPE); + if (behaviour != null) + behaviour.onNeighborChanged(fromPos); + if (!worldIn.getBlockTicks() + .willTickThisTick(pos, this)) + worldIn.scheduleTick(pos, this, 0); + } + + @Override + public void tick(BlockState state, ServerLevel worldIn, BlockPos pos, RandomSource r) { + boolean previouslyPowered = state.getValue(POWERED); + if (previouslyPowered != worldIn.hasNeighborSignal(pos)) + worldIn.setBlock(pos, state.cycle(POWERED), 2); + } + + public static ItemStack tryInsert(Level worldIn, BlockPos pos, ItemStack toInsert, boolean simulate) { + FilteringBehaviour filter = BlockEntityBehaviour.get(worldIn, pos, FilteringBehaviour.TYPE); + InvManipulationBehaviour inserter = BlockEntityBehaviour.get(worldIn, pos, InvManipulationBehaviour.TYPE); + if (inserter == null) + return toInsert; + if (filter != null && !filter.test(toInsert)) + return toInsert; + if (simulate) + inserter.simulate(); + ItemStack insert = inserter.insert(toInsert); + + if (!simulate && insert.getCount() != toInsert.getCount()) { + BlockEntity blockEntity = worldIn.getBlockEntity(pos); + if (blockEntity instanceof FunnelBlockEntity) { + FunnelBlockEntity funnelBlockEntity = (FunnelBlockEntity) blockEntity; + funnelBlockEntity.onTransfer(toInsert); + if (funnelBlockEntity.hasFlap()) + funnelBlockEntity.flap(true); + } + } + return insert; + } + + @Override + public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { + Block block = world.getBlockState(pos.relative(getFunnelFacing(state).getOpposite())) + .getBlock(); + return !(block instanceof AbstractFunnelBlock); + } + + @Nullable + public static boolean isFunnel(BlockState state) { + return state.getBlock() instanceof AbstractFunnelBlock; + } + + @Nullable + public static Direction getFunnelFacing(BlockState state) { + if (!(state.getBlock() instanceof AbstractFunnelBlock)) + return null; + return ((AbstractFunnelBlock) state.getBlock()).getFacing(state); + } + + protected abstract Direction getFacing(BlockState state); + + @Override + public void onRemove(BlockState state, Level world, BlockPos pos, BlockState newState, boolean isMoving) { + if (state.getBlock() != newState.getBlock() && !isFunnel(newState) || !newState.hasBlockEntity()) + IBE.onRemove(state, world, pos, newState); + } + + @Override + public Class getBlockEntityClass() { + return FunnelBlockEntity.class; + } + + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.FUNNEL.get(); + }; + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/funnel/AbstractHorizontalFunnelBlock.java b/src/main/java/com/simibubi/create/content/logistics/funnel/AbstractHorizontalFunnelBlock.java similarity index 95% rename from src/main/java/com/simibubi/create/content/logistics/block/funnel/AbstractHorizontalFunnelBlock.java rename to src/main/java/com/simibubi/create/content/logistics/funnel/AbstractHorizontalFunnelBlock.java index 7e1b03073..368d6dfd4 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/funnel/AbstractHorizontalFunnelBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/funnel/AbstractHorizontalFunnelBlock.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.block.funnel; +package com.simibubi.create.content.logistics.funnel; import net.minecraft.core.Direction; import net.minecraft.world.level.block.Block; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/funnel/AndesiteFunnelBlock.java b/src/main/java/com/simibubi/create/content/logistics/funnel/AndesiteFunnelBlock.java similarity index 91% rename from src/main/java/com/simibubi/create/content/logistics/block/funnel/AndesiteFunnelBlock.java rename to src/main/java/com/simibubi/create/content/logistics/funnel/AndesiteFunnelBlock.java index 26792cf23..239fe3cad 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/funnel/AndesiteFunnelBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/funnel/AndesiteFunnelBlock.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.block.funnel; +package com.simibubi.create.content.logistics.funnel; import com.simibubi.create.AllBlocks; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/funnel/BeltFunnelBlock.java b/src/main/java/com/simibubi/create/content/logistics/funnel/BeltFunnelBlock.java similarity index 90% rename from src/main/java/com/simibubi/create/content/logistics/block/funnel/BeltFunnelBlock.java rename to src/main/java/com/simibubi/create/content/logistics/funnel/BeltFunnelBlock.java index 37d2bf5b7..bdf48f661 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/funnel/BeltFunnelBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/funnel/BeltFunnelBlock.java @@ -1,14 +1,15 @@ -package com.simibubi.create.content.logistics.block.funnel; +package com.simibubi.create.content.logistics.funnel; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; -import com.simibubi.create.content.contraptions.relays.belt.BeltBlock; -import com.simibubi.create.content.contraptions.relays.belt.BeltSlope; -import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement; -import com.simibubi.create.content.schematics.ItemRequirement; +import com.simibubi.create.content.kinetics.belt.BeltBlock; +import com.simibubi.create.content.kinetics.belt.BeltSlope; +import com.simibubi.create.content.kinetics.belt.behaviour.DirectBeltInputBehaviour; +import com.simibubi.create.content.schematics.requirement.ISpecialBlockItemRequirement; +import com.simibubi.create.content.schematics.requirement.ItemRequirement; import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour; +import com.simibubi.create.foundation.block.ProperWaterloggedBlock; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.VoxelShaper; import com.tterrag.registrate.util.entry.BlockEntry; @@ -132,8 +133,9 @@ public class BeltFunnelBlock extends AbstractHorizontalFunnelBlock implements IS @Override public BlockState updateShape(BlockState state, Direction direction, BlockState neighbour, LevelAccessor world, BlockPos pos, BlockPos p_196271_6_) { + updateWater(world, state, pos); if (!isOnValidBelt(state, world, pos)) { - BlockState parentState = parent.getDefaultState(); + BlockState parentState = ProperWaterloggedBlock.withWater(world, parent.getDefaultState(), pos); if (state.getOptionalValue(POWERED) .orElse(false)) parentState = parentState.setValue(POWERED, true); @@ -161,7 +163,7 @@ public class BeltFunnelBlock extends AbstractHorizontalFunnelBlock implements IS if ((stateBelow.getBlock() instanceof BeltBlock)) return BeltBlock.canTransportObjects(stateBelow); DirectBeltInputBehaviour directBeltInputBehaviour = - TileEntityBehaviour.get(world, pos.below(), DirectBeltInputBehaviour.TYPE); + BlockEntityBehaviour.get(world, pos.below(), DirectBeltInputBehaviour.TYPE); if (directBeltInputBehaviour == null) return false; return directBeltInputBehaviour.canSupportBeltFunnels(); @@ -207,8 +209,8 @@ public class BeltFunnelBlock extends AbstractHorizontalFunnelBlock implements IS } @Override - public ItemRequirement getRequiredItems(BlockState state, BlockEntity te) { - return ItemRequirement.of(parent.getDefaultState(), te); + public ItemRequirement getRequiredItems(BlockState state, BlockEntity be) { + return ItemRequirement.of(parent.getDefaultState(), be); } } diff --git a/src/main/java/com/simibubi/create/content/logistics/funnel/BeltFunnelGenerator.java b/src/main/java/com/simibubi/create/content/logistics/funnel/BeltFunnelGenerator.java new file mode 100644 index 000000000..3f3468d53 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/funnel/BeltFunnelGenerator.java @@ -0,0 +1,56 @@ +package com.simibubi.create.content.logistics.funnel; + +import com.simibubi.create.Create; +import com.simibubi.create.content.logistics.funnel.BeltFunnelBlock.Shape; +import com.simibubi.create.foundation.data.SpecialBlockStateGen; +import com.tterrag.registrate.providers.DataGenContext; +import com.tterrag.registrate.providers.RegistrateBlockstateProvider; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraftforge.client.model.generators.ModelFile; + +public class BeltFunnelGenerator extends SpecialBlockStateGen { + + private String type; + private ResourceLocation materialBlockTexture; + + public BeltFunnelGenerator(String type) { + this.type = type; + this.materialBlockTexture = Create.asResource("block/" + type + "_block"); + } + + @Override + protected int getXRotation(BlockState state) { + return 0; + } + + @Override + protected int getYRotation(BlockState state) { + return horizontalAngle(state.getValue(BeltFunnelBlock.HORIZONTAL_FACING)) + 180; + } + + @Override + public ModelFile getModel(DataGenContext ctx, RegistrateBlockstateProvider prov, + BlockState state) { + String prefix = "block/funnel/"; + Shape shape = state.getValue(BeltFunnelBlock.SHAPE); + String shapeName = shape.getSerializedName(); + boolean powered = state.getOptionalValue(BlockStateProperties.POWERED) + .orElse(false); + String poweredSuffix = powered ? "_powered" : "_unpowered"; + String shapeSuffix = shape == Shape.PULLING ? "_pull" : shape == Shape.PUSHING ? "_push" : "_neutral"; + String name = ctx.getName() + "_" + shapeName + poweredSuffix; + + return prov.models() + .withExistingParent(name, prov.modLoc("block/belt_funnel/block_" + shapeName)) + .texture("particle", materialBlockTexture) + .texture("block", materialBlockTexture) + .texture("direction", prov.modLoc(prefix + type + "_funnel" + shapeSuffix)) + .texture("redstone", prov.modLoc(prefix + type + "_funnel" + poweredSuffix)) + .texture("base", prov.modLoc(prefix + type + "_funnel")); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/funnel/BrassFunnelBlock.java b/src/main/java/com/simibubi/create/content/logistics/funnel/BrassFunnelBlock.java similarity index 91% rename from src/main/java/com/simibubi/create/content/logistics/block/funnel/BrassFunnelBlock.java rename to src/main/java/com/simibubi/create/content/logistics/funnel/BrassFunnelBlock.java index 969f141dd..a9e273fbd 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/funnel/BrassFunnelBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/funnel/BrassFunnelBlock.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.block.funnel; +package com.simibubi.create.content.logistics.funnel; import com.simibubi.create.AllBlocks; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelBlock.java b/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelBlock.java similarity index 95% rename from src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelBlock.java rename to src/main/java/com/simibubi/create/content/logistics/funnel/FunnelBlock.java index 9c7fe7430..d617c9e42 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelBlock.java @@ -1,9 +1,10 @@ -package com.simibubi.create.content.logistics.block.funnel; +package com.simibubi.create.content.logistics.funnel; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; import com.simibubi.create.AllShapes; import com.simibubi.create.foundation.advancement.AdvancementBehaviour; +import com.simibubi.create.foundation.block.ProperWaterloggedBlock; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.core.BlockPos; @@ -89,7 +90,7 @@ public abstract class FunnelBlock extends AbstractDirectionalFunnelBlock { if (hit.getDirection() == getFunnelFacing(state) && !shouldntInsertItem) { if (!worldIn.isClientSide) - withTileEntityDo(worldIn, pos, te -> { + withBlockEntityDo(worldIn, pos, be -> { ItemStack toInsert = heldItem.copy(); ItemStack remainder = tryInsert(worldIn, pos, toInsert, false); if (!ItemStack.matches(remainder, toInsert)) @@ -163,10 +164,12 @@ public abstract class FunnelBlock extends AbstractDirectionalFunnelBlock { @Override public BlockState updateShape(BlockState state, Direction direction, BlockState p_196271_3_, LevelAccessor world, BlockPos pos, BlockPos p_196271_6_) { + updateWater(world, state, pos); if (getFacing(state).getAxis() .isVertical() || direction != Direction.DOWN) return state; - BlockState equivalentFunnel = getEquivalentBeltFunnel(null, null, state); + BlockState equivalentFunnel = + ProperWaterloggedBlock.withWater(world, getEquivalentBeltFunnel(null, null, state), pos); if (BeltFunnelBlock.isOnValidBelt(equivalentFunnel, world, pos)) return equivalentFunnel.setValue(BeltFunnelBlock.SHAPE, BeltFunnelBlock.getShapeForPosition(world, pos, getFacing(state), state.getValue(EXTRACTING))); diff --git a/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelBlockEntity.java b/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelBlockEntity.java new file mode 100644 index 000000000..281168261 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelBlockEntity.java @@ -0,0 +1,356 @@ +package com.simibubi.create.content.logistics.funnel; + +import java.lang.ref.WeakReference; +import java.util.List; + +import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPackets; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.content.equipment.goggles.IHaveHoveringInformation; +import com.simibubi.create.content.kinetics.belt.BeltBlockEntity; +import com.simibubi.create.content.kinetics.belt.BeltHelper; +import com.simibubi.create.content.kinetics.belt.behaviour.DirectBeltInputBehaviour; +import com.simibubi.create.content.kinetics.belt.transport.TransportedItemStack; +import com.simibubi.create.content.logistics.funnel.BeltFunnelBlock.Shape; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.inventory.InvManipulationBehaviour; +import com.simibubi.create.foundation.item.ItemHelper.ExtractionCountMode; +import com.simibubi.create.foundation.utility.BlockFace; +import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; + +public class FunnelBlockEntity extends SmartBlockEntity implements IHaveHoveringInformation { + + private FilteringBehaviour filtering; + private InvManipulationBehaviour invManipulation; + private int extractionCooldown; + + private WeakReference lastObserved; // In-world Extractors only + + LerpedFloat flap; + + static enum Mode { + INVALID, PAUSED, COLLECT, PUSHING_TO_BELT, TAKING_FROM_BELT, EXTRACT + } + + public FunnelBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + extractionCooldown = 0; + flap = createChasingFlap(); + } + + public Mode determineCurrentMode() { + BlockState state = getBlockState(); + if (!FunnelBlock.isFunnel(state)) + return Mode.INVALID; + if (state.getOptionalValue(BlockStateProperties.POWERED) + .orElse(false)) + return Mode.PAUSED; + if (state.getBlock() instanceof BeltFunnelBlock) { + Shape shape = state.getValue(BeltFunnelBlock.SHAPE); + if (shape == Shape.PULLING) + return Mode.TAKING_FROM_BELT; + if (shape == Shape.PUSHING) + return Mode.PUSHING_TO_BELT; + + BeltBlockEntity belt = BeltHelper.getSegmentBE(level, worldPosition.below()); + if (belt != null) + return belt.getMovementFacing() == state.getValue(BeltFunnelBlock.HORIZONTAL_FACING) + ? Mode.PUSHING_TO_BELT + : Mode.TAKING_FROM_BELT; + return Mode.INVALID; + } + if (state.getBlock() instanceof FunnelBlock) + return state.getValue(FunnelBlock.EXTRACTING) ? Mode.EXTRACT : Mode.COLLECT; + + return Mode.INVALID; + } + + @Override + public void tick() { + super.tick(); + flap.tickChaser(); + Mode mode = determineCurrentMode(); + if (level.isClientSide) + return; + + // Redstone resets the extraction cooldown + if (mode == Mode.PAUSED) + extractionCooldown = 0; + if (mode == Mode.TAKING_FROM_BELT) + return; + + if (extractionCooldown > 0) { + extractionCooldown--; + return; + } + + if (mode == Mode.PUSHING_TO_BELT) + activateExtractingBeltFunnel(); + if (mode == Mode.EXTRACT) + activateExtractor(); + } + + private void activateExtractor() { + BlockState blockState = getBlockState(); + Direction facing = AbstractFunnelBlock.getFunnelFacing(blockState); + + if (facing == null) + return; + + boolean trackingEntityPresent = true; + AABB area = getEntityOverflowScanningArea(); + + // Check if last item is still blocking the extractor + if (lastObserved == null) { + trackingEntityPresent = false; + } else { + ItemEntity lastEntity = lastObserved.get(); + if (lastEntity == null || !lastEntity.isAlive() || !lastEntity.getBoundingBox() + .intersects(area)) { + trackingEntityPresent = false; + lastObserved = null; + } + } + + if (trackingEntityPresent) + return; + + // Find other entities blocking the extract (only if necessary) + int amountToExtract = getAmountToExtract(); + ExtractionCountMode mode = getModeToExtract(); + ItemStack stack = invManipulation.simulate() + .extract(mode, amountToExtract); + if (stack.isEmpty()) + return; + for (ItemEntity itemEntity : level.getEntitiesOfClass(ItemEntity.class, area)) { + lastObserved = new WeakReference<>(itemEntity); + return; + } + + // Extract + stack = invManipulation.extract(mode, amountToExtract); + if (stack.isEmpty()) + return; + + flap(false); + onTransfer(stack); + + Vec3 outputPos = VecHelper.getCenterOf(worldPosition); + boolean vertical = facing.getAxis() + .isVertical(); + boolean up = facing == Direction.UP; + + outputPos = outputPos.add(Vec3.atLowerCornerOf(facing.getNormal()) + .scale(vertical ? up ? .15f : .5f : .25f)); + if (!vertical) + outputPos = outputPos.subtract(0, .45f, 0); + + Vec3 motion = Vec3.ZERO; + if (up) + motion = new Vec3(0, 4 / 16f, 0); + + ItemEntity item = new ItemEntity(level, outputPos.x, outputPos.y, outputPos.z, stack.copy()); + item.setDefaultPickUpDelay(); + item.setDeltaMovement(motion); + level.addFreshEntity(item); + lastObserved = new WeakReference<>(item); + + startCooldown(); + } + + static final AABB coreBB = new AABB(VecHelper.CENTER_OF_ORIGIN, VecHelper.CENTER_OF_ORIGIN).inflate(.75f); + + private AABB getEntityOverflowScanningArea() { + Direction facing = AbstractFunnelBlock.getFunnelFacing(getBlockState()); + AABB bb = coreBB.move(worldPosition); + if (facing == null || facing == Direction.UP) + return bb; + return bb.expandTowards(0, -1, 0); + } + + private void activateExtractingBeltFunnel() { + BlockState blockState = getBlockState(); + Direction facing = blockState.getValue(BeltFunnelBlock.HORIZONTAL_FACING); + DirectBeltInputBehaviour inputBehaviour = + BlockEntityBehaviour.get(level, worldPosition.below(), DirectBeltInputBehaviour.TYPE); + + if (inputBehaviour == null) + return; + if (!inputBehaviour.canInsertFromSide(facing)) + return; + + int amountToExtract = getAmountToExtract(); + ExtractionCountMode mode = getModeToExtract(); + ItemStack stack = + invManipulation.extract(mode, amountToExtract, s -> inputBehaviour.handleInsertion(s, facing, true) + .isEmpty()); + if (stack.isEmpty()) + return; + flap(false); + onTransfer(stack); + inputBehaviour.handleInsertion(stack, facing, false); + startCooldown(); + } + + public int getAmountToExtract() { + if (!supportsAmountOnFilter()) + return 64; + int amountToExtract = invManipulation.getAmountFromFilter(); + if (!filtering.isActive()) + amountToExtract = 1; + return amountToExtract; + } + + public ExtractionCountMode getModeToExtract() { + if (!supportsAmountOnFilter() || !filtering.isActive()) + return ExtractionCountMode.UPTO; + return invManipulation.getModeFromFilter(); + } + + private int startCooldown() { + return extractionCooldown = AllConfigs.server().logistics.defaultExtractionTimer.get(); + } + + @Override + public void addBehaviours(List behaviours) { + invManipulation = + new InvManipulationBehaviour(this, (w, p, s) -> new BlockFace(p, AbstractFunnelBlock.getFunnelFacing(s) + .getOpposite())); + behaviours.add(invManipulation); + + filtering = new FilteringBehaviour(this, new FunnelFilterSlotPositioning()); + filtering.showCountWhen(this::supportsAmountOnFilter); + filtering.onlyActiveWhen(this::supportsFiltering); + behaviours.add(filtering); + + behaviours.add(new DirectBeltInputBehaviour(this).onlyInsertWhen(this::supportsDirectBeltInput) + .setInsertionHandler(this::handleDirectBeltInput)); + registerAwardables(behaviours, AllAdvancements.FUNNEL); + } + + private boolean supportsAmountOnFilter() { + BlockState blockState = getBlockState(); + boolean beltFunnelsupportsAmount = false; + if (blockState.getBlock() instanceof BeltFunnelBlock) { + Shape shape = blockState.getValue(BeltFunnelBlock.SHAPE); + if (shape == Shape.PUSHING) + beltFunnelsupportsAmount = true; + else + beltFunnelsupportsAmount = BeltHelper.getSegmentBE(level, worldPosition.below()) != null; + } + boolean extractor = blockState.getBlock() instanceof FunnelBlock && blockState.getValue(FunnelBlock.EXTRACTING); + return beltFunnelsupportsAmount || extractor; + } + + private boolean supportsDirectBeltInput(Direction side) { + BlockState blockState = getBlockState(); + if (blockState == null) + return false; + if (!(blockState.getBlock() instanceof FunnelBlock)) + return false; + if (blockState.getValue(FunnelBlock.EXTRACTING)) + return false; + return FunnelBlock.getFunnelFacing(blockState) == Direction.UP; + } + + private boolean supportsFiltering() { + BlockState blockState = getBlockState(); + return AllBlocks.BRASS_BELT_FUNNEL.has(blockState) || AllBlocks.BRASS_FUNNEL.has(blockState); + } + + private ItemStack handleDirectBeltInput(TransportedItemStack stack, Direction side, boolean simulate) { + ItemStack inserted = stack.stack; + if (!filtering.test(inserted)) + return inserted; + if (determineCurrentMode() == Mode.PAUSED) + return inserted; + if (simulate) + invManipulation.simulate(); + if (!simulate) + onTransfer(inserted); + return invManipulation.insert(inserted); + } + + public void flap(boolean inward) { + if (!level.isClientSide) { + AllPackets.getChannel() + .send(packetTarget(), new FunnelFlapPacket(this, inward)); + } else { + flap.setValue(inward ? 1 : -1); + AllSoundEvents.FUNNEL_FLAP.playAt(level, worldPosition, 1, 1, true); + } + } + + public boolean hasFlap() { + BlockState blockState = getBlockState(); + if (!AbstractFunnelBlock.getFunnelFacing(blockState) + .getAxis() + .isHorizontal()) + return false; + return true; + } + + public float getFlapOffset() { + BlockState blockState = getBlockState(); + if (!(blockState.getBlock() instanceof BeltFunnelBlock)) + return -1 / 16f; + switch (blockState.getValue(BeltFunnelBlock.SHAPE)) { + default: + case RETRACTED: + return 0; + case EXTENDED: + return 8 / 16f; + case PULLING: + case PUSHING: + return -2 / 16f; + } + } + + @Override + protected void write(CompoundTag compound, boolean clientPacket) { + super.write(compound, clientPacket); + compound.putInt("TransferCooldown", extractionCooldown); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + super.read(compound, clientPacket); + extractionCooldown = compound.getInt("TransferCooldown"); + + if (clientPacket) + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(this)); + } + + public void onTransfer(ItemStack stack) { + AllBlocks.SMART_OBSERVER.get() + .onFunnelTransfer(level, worldPosition, stack); + award(AllAdvancements.FUNNEL); + } + + private LerpedFloat createChasingFlap() { + return LerpedFloat.linear() + .startWithValue(.25f) + .chase(0, .05f, Chaser.EXP); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelFilterSlotPositioning.java b/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelFilterSlotPositioning.java similarity index 83% rename from src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelFilterSlotPositioning.java rename to src/main/java/com/simibubi/create/content/logistics/funnel/FunnelFilterSlotPositioning.java index 2188665cb..8de1dd63d 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelFilterSlotPositioning.java +++ b/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelFilterSlotPositioning.java @@ -1,9 +1,9 @@ -package com.simibubi.create.content.logistics.block.funnel; +package com.simibubi.create.content.logistics.funnel; import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.content.logistics.block.funnel.BeltFunnelBlock.Shape; -import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform; +import com.simibubi.create.content.logistics.funnel.BeltFunnelBlock.Shape; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.VecHelper; @@ -15,7 +15,7 @@ import net.minecraft.world.phys.Vec3; public class FunnelFilterSlotPositioning extends ValueBoxTransform.Sided { @Override - protected Vec3 getLocalOffset(BlockState state) { + public Vec3 getLocalOffset(BlockState state) { Direction side = getSide(); float horizontalAngle = AngleHelper.horizontalAngle(side); Direction funnelFacing = FunnelBlock.getFunnelFacing(state); @@ -28,7 +28,7 @@ public class FunnelFilterSlotPositioning extends ValueBoxTransform.Sided { return VecHelper.rotateCentered(VecHelper.voxelSpace(8, 15.5f, 13), stateAngle, Axis.Y); case PULLING: case PUSHING: - return VecHelper.rotateCentered(VecHelper.voxelSpace(8, 12.1, 8.7f), horizontalAngle, Axis.Y); + return VecHelper.rotateCentered(VecHelper.voxelSpace(8, 12.0f, 8.675f), horizontalAngle, Axis.Y); default: case RETRACTED: return VecHelper.rotateCentered(VecHelper.voxelSpace(8, 13, 7.5f), horizontalAngle, Axis.Y); @@ -41,11 +41,11 @@ public class FunnelFilterSlotPositioning extends ValueBoxTransform.Sided { return VecHelper.rotateCentered(southLocation, horizontalAngle, Axis.Y); } - return VecHelper.rotateCentered(VecHelper.voxelSpace(8, 12.1, 8.7f), horizontalAngle, Axis.Y); + return VecHelper.rotateCentered(VecHelper.voxelSpace(8, 12.2, 8.55f), horizontalAngle, Axis.Y); } @Override - protected void rotate(BlockState state, PoseStack ms) { + public void rotate(BlockState state, PoseStack ms) { Direction facing = FunnelBlock.getFunnelFacing(state); if (facing.getAxis() diff --git a/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelFlapPacket.java b/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelFlapPacket.java new file mode 100644 index 000000000..b403a527d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelFlapPacket.java @@ -0,0 +1,31 @@ +package com.simibubi.create.content.logistics.funnel; + +import com.simibubi.create.foundation.networking.BlockEntityDataPacket; + +import net.minecraft.network.FriendlyByteBuf; + +public class FunnelFlapPacket extends BlockEntityDataPacket { + + private final boolean inwards; + + public FunnelFlapPacket(FriendlyByteBuf buffer) { + super(buffer); + + inwards = buffer.readBoolean(); + } + + public FunnelFlapPacket(FunnelBlockEntity blockEntity, boolean inwards) { + super(blockEntity.getBlockPos()); + this.inwards = inwards; + } + + @Override + protected void writeData(FriendlyByteBuf buffer) { + buffer.writeBoolean(inwards); + } + + @Override + protected void handlePacket(FunnelBlockEntity blockEntity) { + blockEntity.flap(inwards); + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelGenerator.java b/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelGenerator.java new file mode 100644 index 000000000..67d130ff6 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelGenerator.java @@ -0,0 +1,81 @@ +package com.simibubi.create.content.logistics.funnel; + +import com.simibubi.create.Create; +import com.simibubi.create.foundation.data.SpecialBlockStateGen; +import com.tterrag.registrate.providers.DataGenContext; +import com.tterrag.registrate.providers.RegistrateBlockstateProvider; +import com.tterrag.registrate.providers.RegistrateItemModelProvider; +import com.tterrag.registrate.util.nullness.NonNullBiConsumer; + +import net.minecraft.core.Direction; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.client.model.generators.BlockModelBuilder; +import net.minecraftforge.client.model.generators.ModelFile; + +public class FunnelGenerator extends SpecialBlockStateGen { + + private String type; + private ResourceLocation blockTexture; + private boolean hasFilter; + + public FunnelGenerator(String type, boolean hasFilter) { + this.type = type; + this.hasFilter = hasFilter; + this.blockTexture = Create.asResource("block/" + type + "_block"); + } + + @Override + protected int getXRotation(BlockState state) { + return state.getValue(FunnelBlock.FACING) == Direction.DOWN ? 180 : 0; + } + + @Override + protected int getYRotation(BlockState state) { + return horizontalAngle(state.getValue(FunnelBlock.FACING)) + 180; + } + + @Override + public ModelFile getModel(DataGenContext c, RegistrateBlockstateProvider p, + BlockState s) { + String prefix = "block/funnel/"; + String powered = s.getValue(FunnelBlock.POWERED) ? "_powered" : "_unpowered"; + String closed = s.getValue(FunnelBlock.POWERED) ? "_closed" : "_open"; + String extracting = s.getValue(FunnelBlock.EXTRACTING) ? "_push" : "_pull"; + Direction facing = s.getValue(FunnelBlock.FACING); + boolean horizontal = facing.getAxis() + .isHorizontal(); + String parent = horizontal ? "horizontal" : hasFilter ? "vertical" : "vertical_filterless"; + + BlockModelBuilder model = p.models() + .withExistingParent("block/" + type + "_funnel_" + parent + extracting + powered, + p.modLoc(prefix + "block_" + parent)) + .texture("particle", blockTexture) + .texture("base", p.modLoc(prefix + type + "_funnel")) + .texture("redstone", p.modLoc(prefix + type + "_funnel" + powered)) + .texture("direction", p.modLoc(prefix + type + "_funnel" + extracting)); + + if (horizontal) + return model.texture("block", blockTexture); + + return model.texture("frame", p.modLoc(prefix + type + "_funnel_frame")) + .texture("open", p.modLoc(prefix + "funnel" + closed)); + } + + public static NonNullBiConsumer, RegistrateItemModelProvider> itemModel( + String type) { + String prefix = "block/funnel/"; + ResourceLocation blockTexture = Create.asResource("block/" + type + "_block"); + return (c, p) -> { + p.withExistingParent("item/" + type + "_funnel", p.modLoc("block/funnel/item")) + .texture("particle", blockTexture) + .texture("block", blockTexture) + .texture("base", p.modLoc(prefix + type + "_funnel")) + .texture("direction", p.modLoc(prefix + type + "_funnel_neutral")) + .texture("redstone", p.modLoc(prefix + type + "_funnel_unpowered")); + }; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelInstance.java b/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelInstance.java new file mode 100644 index 000000000..c386dc75d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelInstance.java @@ -0,0 +1,87 @@ +package com.simibubi.create.content.logistics.funnel; + +import java.util.ArrayList; + +import com.jozufozu.flywheel.api.InstanceData; +import com.jozufozu.flywheel.api.Instancer; +import com.jozufozu.flywheel.api.MaterialManager; +import com.jozufozu.flywheel.api.instance.DynamicInstance; +import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance; +import com.jozufozu.flywheel.core.PartialModel; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.logistics.flwdata.FlapData; +import com.simibubi.create.foundation.render.AllMaterialSpecs; +import com.simibubi.create.foundation.utility.AnimationTickHolder; + +import net.minecraft.core.Direction; +import net.minecraft.world.level.LightLayer; + +public class FunnelInstance extends BlockEntityInstance implements DynamicInstance { + + private final ArrayList flaps; + + public FunnelInstance(MaterialManager materialManager, FunnelBlockEntity blockEntity) { + super(materialManager, blockEntity); + + flaps = new ArrayList<>(4); + + if (!blockEntity.hasFlap()) return; + + PartialModel flapPartial = (blockState.getBlock() instanceof FunnelBlock ? AllPartialModels.FUNNEL_FLAP + : AllPartialModels.BELT_FUNNEL_FLAP); + Instancer model = materialManager.defaultSolid() + .material(AllMaterialSpecs.FLAPS) + .getModel(flapPartial, blockState); + + int blockLight = world.getBrightness(LightLayer.BLOCK, pos); + int skyLight = world.getBrightness(LightLayer.SKY, pos); + + Direction direction = FunnelBlock.getFunnelFacing(blockState); + + float flapness = blockEntity.flap.getValue(AnimationTickHolder.getPartialTicks()); + float horizontalAngle = direction.getOpposite().toYRot(); + + for (int segment = 0; segment <= 3; segment++) { + float intensity = segment == 3 ? 1.5f : segment + 1; + float segmentOffset = -3.05f / 16f * segment + 0.075f / 16f; + + FlapData key = model.createInstance(); + + key.setPosition(getInstancePosition()) + .setSegmentOffset(segmentOffset, 0, -blockEntity.getFlapOffset()) + .setBlockLight(blockLight) + .setSkyLight(skyLight) + .setHorizontalAngle(horizontalAngle) + .setFlapness(flapness) + .setFlapScale(-1) + .setPivotVoxelSpace(0, 10, 9.5f) + .setIntensity(intensity); + + flaps.add(key); + } + } + + @Override + public void beginFrame() { + if (flaps == null) return; + + float flapness = blockEntity.flap.getValue(AnimationTickHolder.getPartialTicks()); + + for (FlapData flap : flaps) { + flap.setFlapness(flapness); + } + } + + @Override + public void updateLight() { + if (flaps != null) + relight(pos, flaps.stream()); + } + + @Override + public void remove() { + if (flaps == null) return; + + flaps.forEach(InstanceData::delete); + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelItem.java b/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelItem.java similarity index 96% rename from src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelItem.java rename to src/main/java/com/simibubi/create/content/logistics/funnel/FunnelItem.java index 7376cff5d..1e5eecbe3 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelItem.java +++ b/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelItem.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.block.funnel; +package com.simibubi.create.content.logistics.funnel; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelMovementBehaviour.java b/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelMovementBehaviour.java similarity index 80% rename from src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelMovementBehaviour.java rename to src/main/java/com/simibubi/create/content/logistics/funnel/FunnelMovementBehaviour.java index 5928c0403..9178f3684 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelMovementBehaviour.java @@ -1,11 +1,10 @@ -package com.simibubi.create.content.logistics.block.funnel; +package com.simibubi.create.content.logistics.funnel; import java.util.List; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; -import com.simibubi.create.content.logistics.item.filter.FilterItem; -import com.simibubi.create.foundation.config.AllConfigs; +import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.logistics.filter.FilterItem; import com.simibubi.create.foundation.item.ItemHelper; import net.minecraft.core.BlockPos; @@ -73,12 +72,14 @@ public class FunnelMovementBehaviour implements MovementBehaviour { return; ItemStack filter = getFilter(context); - int filterAmount = context.tileData.getInt("FilterAmount"); + int filterAmount = context.blockEntityData.getInt("FilterAmount"); + boolean upTo = context.blockEntityData.getBoolean("UpTo"); if (filterAmount <= 0) - filterAmount = hasFilter ? AllConfigs.SERVER.logistics.defaultExtractionLimit.get() : 1; + filterAmount = hasFilter ? 64 : 1; ItemStack extract = ItemHelper.extract(context.contraption.getSharedInventory(), - s -> FilterItem.test(world, s, filter), ItemHelper.ExtractionCountMode.UPTO, filterAmount, false); + s -> FilterItem.test(world, s, filter), + upTo ? ItemHelper.ExtractionCountMode.UPTO : ItemHelper.ExtractionCountMode.EXACTLY, filterAmount, false); if (extract.isEmpty()) return; @@ -119,12 +120,12 @@ public class FunnelMovementBehaviour implements MovementBehaviour { } @Override - public boolean renderAsNormalTileEntity() { + public boolean renderAsNormalBlockEntity() { return true; } private ItemStack getFilter(MovementContext context) { - return hasFilter ? ItemStack.of(context.tileData.getCompound("Filter")) : ItemStack.EMPTY; + return hasFilter ? ItemStack.of(context.blockEntityData.getCompound("Filter")) : ItemStack.EMPTY; } } diff --git a/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelRenderer.java b/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelRenderer.java new file mode 100644 index 000000000..65105f1d4 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelRenderer.java @@ -0,0 +1,76 @@ +package com.simibubi.create.content.logistics.funnel; + +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.core.PartialModel; +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.foundation.blockEntity.renderer.SmartBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.util.Mth; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class FunnelRenderer extends SmartBlockEntityRenderer { + + public FunnelRenderer(BlockEntityRendererProvider.Context context) { + super(context); + } + + @Override + protected void renderSafe(FunnelBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + super.renderSafe(be, partialTicks, ms, buffer, light, overlay); + + if (!be.hasFlap() || Backend.canUseInstancing(be.getLevel())) + return; + + BlockState blockState = be.getBlockState(); + VertexConsumer vb = buffer.getBuffer(RenderType.solid()); + PartialModel partialModel = (blockState.getBlock() instanceof FunnelBlock ? AllPartialModels.FUNNEL_FLAP + : AllPartialModels.BELT_FUNNEL_FLAP); + SuperByteBuffer flapBuffer = CachedBufferer.partial(partialModel, blockState); + Vec3 pivot = VecHelper.voxelSpace(0, 10, 9.5f); + TransformStack msr = TransformStack.cast(ms); + + float horizontalAngle = AngleHelper.horizontalAngle(FunnelBlock.getFunnelFacing(blockState) + .getOpposite()); + float f = be.flap.getValue(partialTicks); + + ms.pushPose(); + msr.centre() + .rotateY(horizontalAngle) + .unCentre(); + ms.translate(0.075f / 16f, 0, -be.getFlapOffset()); + + for (int segment = 0; segment <= 3; segment++) { + ms.pushPose(); + + float intensity = segment == 3 ? 1.5f : segment + 1; + float abs = Math.abs(f); + float flapAngle = Mth.sin((float) ((1 - abs) * Math.PI * intensity)) * 30 * -f; + if (f > 0) + flapAngle *= .5f; + + msr.translate(pivot) + .rotateX(flapAngle) + .translateBack(pivot); + + flapBuffer.light(light) + .renderInto(ms, vb); + + ms.popPose(); + ms.translate(-3.05f / 16f, 0, 0); + } + ms.popPose(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/LecternControllerBlock.java b/src/main/java/com/simibubi/create/content/logistics/item/LecternControllerBlock.java deleted file mode 100644 index 7df57cf9d..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/item/LecternControllerBlock.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.simibubi.create.content.logistics.item; - -import java.util.ArrayList; - -import com.simibubi.create.AllItems; -import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement; -import com.simibubi.create.content.schematics.ItemRequirement; -import com.simibubi.create.foundation.block.ITE; - -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.item.ItemStack; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.LecternBlock; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.world.phys.HitResult; - -public class LecternControllerBlock extends LecternBlock - implements ITE, ISpecialBlockItemRequirement { - - public LecternControllerBlock(Properties properties) { - super(properties); - registerDefaultState(defaultBlockState().setValue(HAS_BOOK, true)); - } - - @Override - public Class getTileEntityClass() { - return LecternControllerTileEntity.class; - } - - @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.LECTERN_CONTROLLER.get(); - } - - @Override - public BlockEntity newBlockEntity(BlockPos p_153573_, BlockState p_153574_) { - return ITE.super.newBlockEntity(p_153573_, p_153574_); - } - - @Override - public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, - BlockHitResult hit) { - if (!player.isShiftKeyDown() && LecternControllerTileEntity.playerInRange(player, world, pos)) { - if (!world.isClientSide) - withTileEntityDo(world, pos, te -> te.tryStartUsing(player)); - return InteractionResult.SUCCESS; - } - - if (player.isShiftKeyDown()) { - if (!world.isClientSide) - replaceWithLectern(state, world, pos); - return InteractionResult.SUCCESS; - } - - return InteractionResult.PASS; - } - - @Override - public void onRemove(BlockState state, Level world, BlockPos pos, BlockState newState, boolean isMoving) { - if (!state.is(newState.getBlock())) { - if (!world.isClientSide) - withTileEntityDo(world, pos, te -> te.dropController(state)); - - super.onRemove(state, world, pos, newState, isMoving); - } - } - - @Override - public int getAnalogOutputSignal(BlockState state, Level world, BlockPos pos) { - return 15; - } - - public void replaceLectern(BlockState lecternState, Level world, BlockPos pos, ItemStack controller) { - world.setBlockAndUpdate(pos, defaultBlockState().setValue(FACING, lecternState.getValue(FACING)) - .setValue(POWERED, lecternState.getValue(POWERED))); - withTileEntityDo(world, pos, te -> te.setController(controller)); - } - - public void replaceWithLectern(BlockState state, Level world, BlockPos pos) { - AllSoundEvents.CONTROLLER_TAKE.playOnServer(world, pos); - world.setBlockAndUpdate(pos, Blocks.LECTERN.defaultBlockState() - .setValue(FACING, state.getValue(FACING)) - .setValue(POWERED, state.getValue(POWERED))); - } - - @Override - public ItemStack getCloneItemStack(BlockState state, HitResult target, BlockGetter world, BlockPos pos, Player player) { - return Blocks.LECTERN.getCloneItemStack(state, target, world, pos, player); - } - - @Override - public ItemRequirement getRequiredItems(BlockState state, BlockEntity te) { - ArrayList requiredItems = new ArrayList<>(); - requiredItems.add(new ItemStack(Blocks.LECTERN)); - requiredItems.add(new ItemStack(AllItems.LINKED_CONTROLLER.get())); - return new ItemRequirement(ItemRequirement.ItemUseType.CONSUME, requiredItems); - } -} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/LecternControllerRenderer.java b/src/main/java/com/simibubi/create/content/logistics/item/LecternControllerRenderer.java deleted file mode 100644 index d56a6ac3d..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/item/LecternControllerRenderer.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.simibubi.create.content.logistics.item; - -import com.jozufozu.flywheel.util.transform.TransformStack; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllItems; -import com.simibubi.create.foundation.item.render.PartialItemModelRenderer; -import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; -import com.simibubi.create.foundation.utility.AngleHelper; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.block.model.ItemTransforms.TransformType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.Direction; -import net.minecraft.world.item.ItemStack; - -public class LecternControllerRenderer extends SafeTileEntityRenderer { - - public LecternControllerRenderer(BlockEntityRendererProvider.Context context) { - } - - @Override - protected void renderSafe(LecternControllerTileEntity te, float partialTicks, PoseStack ms, - MultiBufferSource buffer, int light, int overlay) { - - ItemStack stack = AllItems.LINKED_CONTROLLER.asStack(); - TransformType transformType = TransformType.NONE; - LinkedControllerModel mainModel = (LinkedControllerModel) Minecraft.getInstance() - .getItemRenderer() - .getModel(stack, te.getLevel(), null, 0); - PartialItemModelRenderer renderer = PartialItemModelRenderer.of(stack, transformType, ms, buffer, overlay); - boolean active = te.hasUser(); - boolean renderDepression = te.isUsedBy(Minecraft.getInstance().player); - - Direction facing = te.getBlockState().getValue(LecternControllerBlock.FACING); - TransformStack msr = TransformStack.cast(ms); - - ms.pushPose(); - msr.translate(0.5, 1.45, 0.5); - msr.rotateY(AngleHelper.horizontalAngle(facing) - 90); - msr.translate(0.28, 0, 0); - msr.rotateZ(-22.0); - LinkedControllerItemRenderer.renderInLectern(stack, mainModel, renderer, transformType, ms, light, active, renderDepression); - ms.popPose(); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/LecternControllerTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/item/LecternControllerTileEntity.java deleted file mode 100644 index d67868a23..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/item/LecternControllerTileEntity.java +++ /dev/null @@ -1,179 +0,0 @@ -package com.simibubi.create.content.logistics.item; - -import java.util.List; -import java.util.UUID; - -import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; - -import net.minecraft.client.Minecraft; -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.InteractionHand; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.item.ItemEntity; -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.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.common.ForgeMod; -import net.minecraftforge.fml.DistExecutor; - -public class LecternControllerTileEntity extends SmartTileEntity { - - private ItemStack controller; - private UUID user; - private UUID prevUser; // used only on client - private boolean deactivatedThisTick; // used only on server - - public LecternControllerTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - @Override - public void addBehaviours(List behaviours) { } - - @Override - protected void write(CompoundTag compound, boolean clientPacket) { - super.write(compound, clientPacket); - compound.put("Controller", controller.save(new CompoundTag())); - if (user != null) - compound.putUUID("User", user); - } - - @Override - public void writeSafe(CompoundTag compound) { - super.writeSafe(compound); - compound.put("Controller", controller.save(new CompoundTag())); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - super.read(compound, clientPacket); - controller = ItemStack.of(compound.getCompound("Controller")); - user = compound.hasUUID("User") ? compound.getUUID("User") : null; - } - - public ItemStack getController() { - return controller; - } - - public boolean hasUser() { return user != null; } - - public boolean isUsedBy(Player player) { - return hasUser() && user.equals(player.getUUID()); - } - - public void tryStartUsing(Player player) { - if (!deactivatedThisTick && !hasUser() && !playerIsUsingLectern(player) && playerInRange(player, level, worldPosition)) - startUsing(player); - } - - public void tryStopUsing(Player player) { - if (isUsedBy(player)) - stopUsing(player); - } - - private void startUsing(Player player) { - user = player.getUUID(); - player.getPersistentData().putBoolean("IsUsingLecternController", true); - sendData(); - } - - private void stopUsing(Player player) { - user = null; - if (player != null) - player.getPersistentData().remove("IsUsingLecternController"); - deactivatedThisTick = true; - sendData(); - } - - public static boolean playerIsUsingLectern(Player player) { - return player.getPersistentData().contains("IsUsingLecternController"); - } - - @Override - public void tick() { - super.tick(); - - if (level.isClientSide) { - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> this::tryToggleActive); - prevUser = user; - } - - if (!level.isClientSide) { - deactivatedThisTick = false; - - if (!(level instanceof ServerLevel)) - return; - if (user == null) - return; - - Entity entity = ((ServerLevel) level).getEntity(user); - if (!(entity instanceof Player)) { - stopUsing(null); - return; - } - - Player player = (Player) entity; - if (!playerInRange(player, level, worldPosition) || !playerIsUsingLectern(player)) - stopUsing(player); - } - } - - @OnlyIn(Dist.CLIENT) - private void tryToggleActive() { - if (user == null && Minecraft.getInstance().player.getUUID().equals(prevUser)) { - LinkedControllerClientHandler.deactivateInLectern(); - } else if (prevUser == null && Minecraft.getInstance().player.getUUID().equals(user)) { - LinkedControllerClientHandler.activateInLectern(worldPosition); - } - } - - public void setController(ItemStack newController) { - controller = newController; - if (newController != null) { - AllSoundEvents.CONTROLLER_PUT.playOnServer(level, worldPosition); - } - } - - public void swapControllers(ItemStack stack, Player player, InteractionHand hand, BlockState state) { - ItemStack newController = stack.copy(); - stack.setCount(0); - if (player.getItemInHand(hand).isEmpty()) { - player.setItemInHand(hand, controller); - } else { - dropController(state); - } - setController(newController); - } - - public void dropController(BlockState state) { - Entity playerEntity = ((ServerLevel) level).getEntity(user); - if (playerEntity instanceof Player) - stopUsing((Player) playerEntity); - - Direction dir = state.getValue(LecternControllerBlock.FACING); - double x = worldPosition.getX() + 0.5 + 0.25*dir.getStepX(); - double y = worldPosition.getY() + 1; - double z = worldPosition.getZ() + 0.5 + 0.25*dir.getStepZ(); - ItemEntity itementity = new ItemEntity(level, x, y, z, controller.copy()); - itementity.setDefaultPickUpDelay(); - level.addFreshEntity(itementity); - controller = null; - } - - public static boolean playerInRange(Player player, Level world, BlockPos pos) { - //double modifier = world.isRemote ? 0 : 1.0; - double reach = 0.4*player.getAttributeValue(ForgeMod.REACH_DISTANCE.get());// + modifier; - return player.distanceToSqr(Vec3.atCenterOf(pos)) < reach*reach; - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerContainer.java b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerContainer.java deleted file mode 100644 index ab08fd0a6..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerContainer.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.simibubi.create.content.logistics.item; - -import com.simibubi.create.AllContainerTypes; -import com.simibubi.create.foundation.gui.container.GhostItemContainer; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.ClickType; -import net.minecraft.world.inventory.MenuType; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.items.ItemStackHandler; -import net.minecraftforge.items.SlotItemHandler; - -public class LinkedControllerContainer extends GhostItemContainer { - - public LinkedControllerContainer(MenuType type, int id, Inventory inv, FriendlyByteBuf extraData) { - super(type, id, inv, extraData); - } - - public LinkedControllerContainer(MenuType type, int id, Inventory inv, ItemStack filterItem) { - super(type, id, inv, filterItem); - } - - public static LinkedControllerContainer create(int id, Inventory inv, ItemStack filterItem) { - return new LinkedControllerContainer(AllContainerTypes.LINKED_CONTROLLER.get(), id, inv, filterItem); - } - - @Override - protected ItemStack createOnClient(FriendlyByteBuf extraData) { - return extraData.readItem(); - } - - @Override - protected ItemStackHandler createGhostInventory() { - return LinkedControllerItem.getFrequencyItems(contentHolder); - } - - @Override - protected void addSlots() { - addPlayerSlots(8, 131); - - int x = 12; - int y = 34; - int slot = 0; - - for (int column = 0; column < 6; column++) { - for (int row = 0; row < 2; ++row) - addSlot(new SlotItemHandler(ghostInventory, slot++, x, y + row * 18)); - x += 24; - if (column == 3) - x += 11; - } - } - - @Override - protected void saveData(ItemStack contentHolder) { - contentHolder.getOrCreateTag() - .put("Items", ghostInventory.serializeNBT()); - } - - @Override - protected boolean allowRepeats() { - return true; - } - - @Override - public void clicked(int slotId, int dragType, ClickType clickTypeIn, Player player) { - if (slotId == playerInventory.selected && clickTypeIn != ClickType.THROW) - return; - super.clicked(slotId, dragType, clickTypeIn, player); - } - - @Override - public boolean stillValid(Player playerIn) { - return playerInventory.getSelected() == contentHolder; - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerModel.java b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerModel.java deleted file mode 100644 index 7b3784d6e..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerModel.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.simibubi.create.content.logistics.item; - -import com.simibubi.create.foundation.item.render.CreateCustomRenderedItemModel; - -import net.minecraft.client.resources.model.BakedModel; - -public class LinkedControllerModel extends CreateCustomRenderedItemModel { - - public LinkedControllerModel(BakedModel template) { - super(template, "linked_controller"); - addPartials("powered", "button"); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/AbstractFilterContainer.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/AbstractFilterContainer.java deleted file mode 100644 index 614e61d8b..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/item/filter/AbstractFilterContainer.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.simibubi.create.content.logistics.item.filter; - -import com.simibubi.create.foundation.gui.container.GhostItemContainer; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.ClickType; -import net.minecraft.world.inventory.MenuType; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -public abstract class AbstractFilterContainer extends GhostItemContainer { - - protected AbstractFilterContainer(MenuType type, int id, Inventory inv, FriendlyByteBuf extraData) { - super(type, id, inv, extraData); - } - - protected AbstractFilterContainer(MenuType type, int id, Inventory inv, ItemStack contentHolder) { - super(type, id, inv, contentHolder); - } - - @Override - public void clicked(int slotId, int dragType, ClickType clickTypeIn, Player player) { - if (slotId == playerInventory.selected && clickTypeIn != ClickType.THROW) - return; - super.clicked(slotId, dragType, clickTypeIn, player); - } - - @Override - protected boolean allowRepeats() { - return false; - } - - @Override - @OnlyIn(Dist.CLIENT) - protected ItemStack createOnClient(FriendlyByteBuf extraData) { - return extraData.readItem(); - } - - protected abstract int getPlayerInventoryXOffset(); - - protected abstract int getPlayerInventoryYOffset(); - - protected abstract void addFilterSlots(); - - @Override - protected void addSlots() { - addPlayerSlots(getPlayerInventoryXOffset(), getPlayerInventoryYOffset()); - addFilterSlots(); - } - - @Override - protected void saveData(ItemStack contentHolder) { - contentHolder.getOrCreateTag() - .put("Items", ghostInventory.serializeNBT()); - } - - @Override - public boolean stillValid(Player player) { - return playerInventory.getSelected() == contentHolder; - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/AbstractFilterScreen.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/AbstractFilterScreen.java deleted file mode 100644 index f06e71732..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/item/filter/AbstractFilterScreen.java +++ /dev/null @@ -1,159 +0,0 @@ -package com.simibubi.create.content.logistics.item.filter; - -import static com.simibubi.create.foundation.gui.AllGuiTextures.PLAYER_INVENTORY; -import static net.minecraft.ChatFormatting.GRAY; - -import java.util.Collections; -import java.util.List; - -import com.google.common.collect.ImmutableList; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.content.logistics.item.filter.FilterScreenPacket.Option; -import com.simibubi.create.foundation.gui.AllGuiTextures; -import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.gui.container.AbstractSimiContainerScreen; -import com.simibubi.create.foundation.gui.element.GuiGameElement; -import com.simibubi.create.foundation.gui.widget.IconButton; -import com.simibubi.create.foundation.gui.widget.Indicator; -import com.simibubi.create.foundation.gui.widget.Indicator.State; -import com.simibubi.create.foundation.item.ItemDescription.Palette; -import com.simibubi.create.foundation.item.TooltipHelper; -import com.simibubi.create.foundation.networking.AllPackets; - -import net.minecraft.client.renderer.Rect2i; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.entity.player.Inventory; - -public abstract class AbstractFilterScreen extends AbstractSimiContainerScreen { - - protected AllGuiTextures background; - private List extraAreas = Collections.emptyList(); - - private IconButton resetButton; - private IconButton confirmButton; - - protected AbstractFilterScreen(F container, Inventory inv, Component title, AllGuiTextures background) { - super(container, inv, title); - this.background = background; - } - - @Override - protected void init() { - setWindowSize(Math.max(background.width, PLAYER_INVENTORY.width), background.height + 4 + PLAYER_INVENTORY.height); - super.init(); - - int x = leftPos; - int y = topPos; - - resetButton = new IconButton(x + background.width - 62, y + background.height - 24, AllIcons.I_TRASH); - resetButton.withCallback(() -> { - menu.clearContents(); - contentsCleared(); - menu.sendClearPacket(); - }); - confirmButton = new IconButton(x + background.width - 33, y + background.height - 24, AllIcons.I_CONFIRM); - confirmButton.withCallback(() -> { - minecraft.player.closeContainer(); - }); - - addRenderableWidget(resetButton); - addRenderableWidget(confirmButton); - - extraAreas = ImmutableList.of( - new Rect2i(x + background.width, y + background.height - 40, 80, 48) - ); - } - - @Override - protected void renderBg(PoseStack ms, float partialTicks, int mouseX, int mouseY) { - int invX = getLeftOfCentered(PLAYER_INVENTORY.width); - int invY = topPos + background.height + 4; - renderPlayerInventory(ms, invX, invY); - - int x = leftPos; - int y = topPos; - - background.render(ms, x, y, this); - drawCenteredString(ms, font, title, x + (background.width - 8) / 2, y + 3, 0xFFFFFF); - - GuiGameElement.of(menu.contentHolder) - .at(x + background.width, y + background.height - 56, -200) - .scale(5) - .render(ms); - } - - @Override - protected void containerTick() { - if (!menu.player.getMainHandItem() - .equals(menu.contentHolder, false)) - menu.player.closeContainer(); - - super.containerTick(); - - handleTooltips(); - handleIndicators(); - } - - protected void handleTooltips() { - List tooltipButtons = getTooltipButtons(); - - for (IconButton button : tooltipButtons) { - if (!button.getToolTip() - .isEmpty()) { - button.setToolTip(button.getToolTip() - .get(0)); - button.getToolTip() - .add(TooltipHelper.holdShift(Palette.Yellow, hasShiftDown())); - } - } - - if (hasShiftDown()) { - List tooltipDescriptions = getTooltipDescriptions(); - for (int i = 0; i < tooltipButtons.size(); i++) - fillToolTip(tooltipButtons.get(i), tooltipDescriptions.get(i)); - } - } - - public void handleIndicators() { - for (IconButton button : getTooltipButtons()) - button.active = isButtonEnabled(button); - for (Indicator indicator : getIndicators()) - indicator.state = isIndicatorOn(indicator) ? State.ON : State.OFF; - } - - protected abstract boolean isButtonEnabled(IconButton button); - - protected abstract boolean isIndicatorOn(Indicator indicator); - - protected List getTooltipButtons() { - return Collections.emptyList(); - } - - protected List getTooltipDescriptions() { - return Collections.emptyList(); - } - - protected List getIndicators() { - return Collections.emptyList(); - } - - private void fillToolTip(IconButton button, Component tooltip) { - if (!button.isHoveredOrFocused()) - return; - List tip = button.getToolTip(); - tip.addAll(TooltipHelper.cutTextComponent(tooltip, GRAY, GRAY)); - } - - protected void contentsCleared() {} - - protected void sendOptionUpdate(Option option) { - AllPackets.channel.sendToServer(new FilterScreenPacket(option)); - } - - @Override - public List getExtraAreas() { - return extraAreas; - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/AttributeFilterContainer.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/AttributeFilterContainer.java deleted file mode 100644 index eed646d68..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/item/filter/AttributeFilterContainer.java +++ /dev/null @@ -1,161 +0,0 @@ -package com.simibubi.create.content.logistics.item.filter; - -import java.util.ArrayList; -import java.util.List; - -import com.simibubi.create.AllContainerTypes; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Pair; - -import net.minecraft.ChatFormatting; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.Tag; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.entity.player.Player; -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.minecraft.world.item.Items; -import net.minecraftforge.items.ItemStackHandler; -import net.minecraftforge.items.SlotItemHandler; - -public class AttributeFilterContainer extends AbstractFilterContainer { - - public enum WhitelistMode { - WHITELIST_DISJ, WHITELIST_CONJ, BLACKLIST; - } - - WhitelistMode whitelistMode; - List> selectedAttributes; - - public AttributeFilterContainer(MenuType type, int id, Inventory inv, FriendlyByteBuf extraData) { - super(type, id, inv, extraData); - } - - public AttributeFilterContainer(MenuType type, int id, Inventory inv, ItemStack stack) { - super(type, id, inv, stack); - } - - public static AttributeFilterContainer create(int id, Inventory inv, ItemStack stack) { - return new AttributeFilterContainer(AllContainerTypes.ATTRIBUTE_FILTER.get(), id, inv, stack); - } - - public void appendSelectedAttribute(ItemAttribute itemAttribute, boolean inverted) { - selectedAttributes.add(Pair.of(itemAttribute, inverted)); - } - - @Override - protected void init(Inventory inv, ItemStack contentHolder) { - super.init(inv, contentHolder); - ItemStack stack = new ItemStack(Items.NAME_TAG); - stack.setHoverName( - Components.literal("Selected Tags").withStyle(ChatFormatting.RESET, ChatFormatting.BLUE)); - ghostInventory.setStackInSlot(1, stack); - } - - @Override - protected int getPlayerInventoryXOffset() { - return 51; - } - - @Override - protected int getPlayerInventoryYOffset() { - return 105; - } - - @Override - protected void addFilterSlots() { - this.addSlot(new SlotItemHandler(ghostInventory, 0, 16, 22)); - this.addSlot(new SlotItemHandler(ghostInventory, 1, 22, 57) { - @Override - public boolean mayPickup(Player playerIn) { - return false; - } - }); - } - - @Override - protected ItemStackHandler createGhostInventory() { - return new ItemStackHandler(2); - } - - @Override - public void clearContents() { - selectedAttributes.clear(); - } - - @Override - public void clicked(int slotId, int dragType, ClickType clickTypeIn, Player player) { - if (slotId == 37) - return; - super.clicked(slotId, dragType, clickTypeIn, player); - } - - @Override - public boolean canDragTo(Slot slotIn) { - if (slotIn.index == 37) - return false; - return super.canDragTo(slotIn); - } - - @Override - public boolean canTakeItemForPickAll(ItemStack stack, Slot slotIn) { - if (slotIn.index == 37) - return false; - return super.canTakeItemForPickAll(stack, slotIn); - } - - @Override - public ItemStack quickMoveStack(Player playerIn, int index) { - if (index == 37) - return ItemStack.EMPTY; - if (index == 36) { - ghostInventory.setStackInSlot(37, ItemStack.EMPTY); - return ItemStack.EMPTY; - } - if (index < 36) { - ItemStack stackToInsert = playerInventory.getItem(index); - ItemStack copy = stackToInsert.copy(); - copy.setCount(1); - ghostInventory.setStackInSlot(0, copy); - } - return ItemStack.EMPTY; - } - - @Override - protected void initAndReadInventory(ItemStack filterItem) { - super.initAndReadInventory(filterItem); - selectedAttributes = new ArrayList<>(); - whitelistMode = WhitelistMode.values()[filterItem.getOrCreateTag() - .getInt("WhitelistMode")]; - ListTag attributes = filterItem.getOrCreateTag() - .getList("MatchedAttributes", Tag.TAG_COMPOUND); - attributes.forEach(inbt -> { - CompoundTag compound = (CompoundTag) inbt; - selectedAttributes.add(Pair.of(ItemAttribute.fromNBT(compound), compound.getBoolean("Inverted"))); - }); - } - - @Override - protected void saveData(ItemStack filterItem) { - super.saveData(filterItem); - filterItem.getOrCreateTag() - .putInt("WhitelistMode", whitelistMode.ordinal()); - ListTag attributes = new ListTag(); - selectedAttributes.forEach(at -> { - if (at == null) - return; - CompoundTag compoundNBT = new CompoundTag(); - at.getFirst() - .serializeNBT(compoundNBT); - compoundNBT.putBoolean("Inverted", at.getSecond()); - attributes.add(compoundNBT); - }); - filterItem.getOrCreateTag() - .put("MatchedAttributes", attributes); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/FilterContainer.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/FilterContainer.java deleted file mode 100644 index 10b66edd2..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/item/filter/FilterContainer.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.simibubi.create.content.logistics.item.filter; - -import com.simibubi.create.AllContainerTypes; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.inventory.MenuType; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.items.ItemStackHandler; -import net.minecraftforge.items.SlotItemHandler; - -public class FilterContainer extends AbstractFilterContainer { - - boolean respectNBT; - boolean blacklist; - - public FilterContainer(MenuType type, int id, Inventory inv, FriendlyByteBuf extraData) { - super(type, id, inv, extraData); - } - - public FilterContainer(MenuType type, int id, Inventory inv, ItemStack stack) { - super(type, id, inv, stack); - } - - public static FilterContainer create(int id, Inventory inv, ItemStack stack) { - return new FilterContainer(AllContainerTypes.FILTER.get(), id, inv, stack); - } - - @Override - protected int getPlayerInventoryXOffset() { - return 38; - } - - @Override - protected int getPlayerInventoryYOffset() { - return 119; - } - - @Override - protected void addFilterSlots() { - int x = 23; - int y = 20; - for (int row = 0; row < 2; ++row) - for (int col = 0; col < 9; ++col) - this.addSlot(new SlotItemHandler(ghostInventory, col + row * 9, x + col * 18, y + row * 18)); - } - - @Override - protected ItemStackHandler createGhostInventory() { - return FilterItem.getFilterItems(contentHolder); - } - - @Override - protected void initAndReadInventory(ItemStack filterItem) { - super.initAndReadInventory(filterItem); - CompoundTag tag = filterItem.getOrCreateTag(); - respectNBT = tag.getBoolean("RespectNBT"); - blacklist = tag.getBoolean("Blacklist"); - } - - @Override - protected void saveData(ItemStack filterItem) { - super.saveData(filterItem); - CompoundTag tag = filterItem.getOrCreateTag(); - tag.putBoolean("RespectNBT", respectNBT); - tag.putBoolean("Blacklist", blacklist); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/packet/ConfigureStockswitchPacket.java b/src/main/java/com/simibubi/create/content/logistics/packet/ConfigureStockswitchPacket.java deleted file mode 100644 index 39f4474f2..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/packet/ConfigureStockswitchPacket.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.simibubi.create.content.logistics.packet; - -import com.simibubi.create.content.logistics.block.redstone.StockpileSwitchTileEntity; -import com.simibubi.create.foundation.networking.TileEntityConfigurationPacket; - -import net.minecraft.core.BlockPos; -import net.minecraft.network.FriendlyByteBuf; - -public class ConfigureStockswitchPacket extends TileEntityConfigurationPacket { - - private float offBelow; - private float onAbove; - private boolean invert; - - public ConfigureStockswitchPacket(BlockPos pos, float offBelow, float onAbove, boolean invert) { - super(pos); - this.offBelow = offBelow; - this.onAbove = onAbove; - this.invert = invert; - } - - public ConfigureStockswitchPacket(FriendlyByteBuf buffer) { - super(buffer); - } - - @Override - protected void readSettings(FriendlyByteBuf buffer) { - offBelow = buffer.readFloat(); - onAbove = buffer.readFloat(); - invert = buffer.readBoolean(); - } - - @Override - protected void writeSettings(FriendlyByteBuf buffer) { - buffer.writeFloat(offBelow); - buffer.writeFloat(onAbove); - buffer.writeBoolean(invert); - } - - @Override - protected void applySettings(StockpileSwitchTileEntity te) { - te.offWhenBelow = offBelow; - te.onWhenAbove = onAbove; - te.setInverted(invert); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/packet/FunnelFlapPacket.java b/src/main/java/com/simibubi/create/content/logistics/packet/FunnelFlapPacket.java deleted file mode 100644 index a7eaf3bdc..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/packet/FunnelFlapPacket.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.simibubi.create.content.logistics.packet; - -import com.simibubi.create.content.logistics.block.funnel.FunnelTileEntity; -import com.simibubi.create.foundation.networking.TileEntityDataPacket; - -import net.minecraft.network.FriendlyByteBuf; - -public class FunnelFlapPacket extends TileEntityDataPacket { - - private final boolean inwards; - - public FunnelFlapPacket(FriendlyByteBuf buffer) { - super(buffer); - - inwards = buffer.readBoolean(); - } - - public FunnelFlapPacket(FunnelTileEntity tile, boolean inwards) { - super(tile.getBlockPos()); - this.inwards = inwards; - } - - @Override - protected void writeData(FriendlyByteBuf buffer) { - buffer.writeBoolean(inwards); - } - - @Override - protected void handlePacket(FunnelTileEntity tile) { - tile.flap(inwards); - } -} diff --git a/src/main/java/com/simibubi/create/content/logistics/packet/TunnelFlapPacket.java b/src/main/java/com/simibubi/create/content/logistics/packet/TunnelFlapPacket.java deleted file mode 100644 index ffbf776a0..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/packet/TunnelFlapPacket.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.simibubi.create.content.logistics.packet; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.commons.lang3.tuple.Pair; - -import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelTileEntity; -import com.simibubi.create.foundation.networking.TileEntityDataPacket; - -import net.minecraft.core.Direction; -import net.minecraft.network.FriendlyByteBuf; - -public class TunnelFlapPacket extends TileEntityDataPacket { - - private List> flaps; - - public TunnelFlapPacket(FriendlyByteBuf buffer) { - super(buffer); - - byte size = buffer.readByte(); - - this.flaps = new ArrayList<>(size); - - for (int i = 0; i < size; i++) { - Direction direction = Direction.from3DDataValue(buffer.readByte()); - boolean inwards = buffer.readBoolean(); - - flaps.add(Pair.of(direction, inwards)); - } - } - - public TunnelFlapPacket(BeltTunnelTileEntity tile, List> flaps) { - super(tile.getBlockPos()); - - this.flaps = new ArrayList<>(flaps); - } - - @Override - protected void writeData(FriendlyByteBuf buffer) { - buffer.writeByte(flaps.size()); - - for (Pair flap : flaps) { - buffer.writeByte(flap.getLeft().get3DDataValue()); - buffer.writeBoolean(flap.getRight()); - } - } - - @Override - protected void handlePacket(BeltTunnelTileEntity tile) { - for (Pair flap : flaps) { - tile.flap(flap.getLeft(), flap.getRight()); - } - } -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/BogeyTileEntityRenderer.java b/src/main/java/com/simibubi/create/content/logistics/trains/BogeyTileEntityRenderer.java deleted file mode 100644 index 94a08b145..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/BogeyTileEntityRenderer.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.simibubi.create.content.logistics.trains; - -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.content.logistics.trains.track.StandardBogeyTileEntity; -import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; - -public class BogeyTileEntityRenderer extends SafeTileEntityRenderer { - - public BogeyTileEntityRenderer(BlockEntityRendererProvider.Context context) {} - - @Override - protected void renderSafe(T te, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light, - int overlay) { - BlockState blockState = te.getBlockState(); - float angle = 0; - if (te instanceof StandardBogeyTileEntity sbte) - angle = sbte.getVirtualAngle(partialTicks); - if (blockState.getBlock()instanceof IBogeyBlock bogey) - bogey.render(blockState, angle, ms, partialTicks, buffer, light, overlay); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/GraphLocation.java b/src/main/java/com/simibubi/create/content/logistics/trains/GraphLocation.java deleted file mode 100644 index e64513743..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/GraphLocation.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.simibubi.create.content.logistics.trains; - -import com.simibubi.create.foundation.utility.Couple; - -public class GraphLocation { - - public TrackGraph graph; - public Couple edge; - public double position; - -} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/IBogeyBlock.java b/src/main/java/com/simibubi/create/content/logistics/trains/IBogeyBlock.java deleted file mode 100644 index dea2966aa..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/IBogeyBlock.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.simibubi.create.content.logistics.trains; - -import static net.minecraft.world.level.block.state.properties.BlockStateProperties.WATERLOGGED; - -import java.util.ArrayList; -import java.util.EnumSet; -import java.util.List; - -import javax.annotation.Nullable; - -import com.jozufozu.flywheel.api.MaterialManager; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; -import com.simibubi.create.content.logistics.trains.entity.BogeyInstance; -import com.simibubi.create.content.logistics.trains.entity.CarriageBogey; -import com.simibubi.create.foundation.utility.RegisteredObjects; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.registries.ForgeRegistries; - -public interface IBogeyBlock extends IWrenchable { - - static final List BOGEYS = new ArrayList<>(); - - public static void register(ResourceLocation block) { - BOGEYS.add(block); - } - - public EnumSet getStickySurfaces(BlockGetter world, BlockPos pos, BlockState state); - - public double getWheelPointSpacing(); - - public double getWheelRadius(); - - public boolean allowsSingleBogeyCarriage(); - - public Vec3 getConnectorAnchorOffset(); - - @OnlyIn(Dist.CLIENT) - public void render(@Nullable BlockState state, float wheelAngle, PoseStack ms, float partialTicks, - MultiBufferSource buffers, int light, int overlay); - - @OnlyIn(Dist.CLIENT) - public BogeyInstance createInstance(MaterialManager materialManager, CarriageBogey bogey); - - public default Direction getBogeyUpDirection() { - return Direction.UP; - } - - public boolean isTrackAxisAlongFirstCoordinate(BlockState state); - - @Nullable - public BlockState getMatchingBogey(Direction upDirection, boolean axisAlongFirst); - - @Override - default BlockState getRotatedBlockState(BlockState state, Direction targetedFace) { - Block block = state.getBlock(); - int indexOf = BOGEYS.indexOf(RegisteredObjects.getKeyOrThrow(block)); - if (indexOf == -1) - return state; - - int index = (indexOf + 1) % BOGEYS.size(); - Direction bogeyUpDirection = getBogeyUpDirection(); - boolean trackAxisAlongFirstCoordinate = isTrackAxisAlongFirstCoordinate(state); - - while (index != indexOf) { - ResourceLocation id = BOGEYS.get(index); - Block newBlock = ForgeRegistries.BLOCKS.getValue(id); - if (newBlock instanceof IBogeyBlock bogey) { - BlockState matchingBogey = bogey.getMatchingBogey(bogeyUpDirection, trackAxisAlongFirstCoordinate); - if (matchingBogey != null) - return matchingBogey.hasProperty(WATERLOGGED) - ? matchingBogey.setValue(WATERLOGGED, state.getValue(WATERLOGGED)) - : matchingBogey; - } - index = (index + 1) % BOGEYS.size(); - } - - return state; - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/ITrackBlock.java b/src/main/java/com/simibubi/create/content/logistics/trains/ITrackBlock.java deleted file mode 100644 index 33946c2a5..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/ITrackBlock.java +++ /dev/null @@ -1,155 +0,0 @@ -package com.simibubi.create.content.logistics.trains; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.function.BiFunction; -import java.util.function.Function; - -import javax.annotation.Nullable; - -import com.jozufozu.flywheel.core.PartialModel; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.content.logistics.trains.TrackNodeLocation.DiscoveredLocation; -import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBehaviour.RenderedTrackOverlayType; -import com.simibubi.create.content.logistics.trains.track.BezierTrackPointLocation; -import com.simibubi.create.content.logistics.trains.track.TrackBlock; -import com.simibubi.create.content.logistics.trains.track.TrackShape; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Pair; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.AxisDirection; -import net.minecraft.resources.ResourceKey; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -public interface ITrackBlock { - - public Vec3 getUpNormal(BlockGetter world, BlockPos pos, BlockState state); - - public List getTrackAxes(BlockGetter world, BlockPos pos, BlockState state); - - public Vec3 getCurveStart(BlockGetter world, BlockPos pos, BlockState state, Vec3 axis); - - public BlockState getBogeyAnchor(BlockGetter world, BlockPos pos, BlockState state); // should be on bogey side - - public boolean trackEquals(BlockState state1, BlockState state2); - - public default BlockState overlay(BlockGetter world, BlockPos pos, BlockState existing, BlockState placed) { - return existing; - } - - public default double getElevationAtCenter(BlockGetter world, BlockPos pos, BlockState state) { - return isSlope(world, pos, state) ? .5 : 0; - } - - public static Collection walkConnectedTracks(BlockGetter worldIn, TrackNodeLocation location, - boolean linear) { - BlockGetter world = location != null && worldIn instanceof ServerLevel sl ? sl.getServer() - .getLevel(location.dimension) : worldIn; - List list = new ArrayList<>(); - for (BlockPos blockPos : location.allAdjacent()) { - BlockState blockState = world.getBlockState(blockPos); - if (blockState.getBlock()instanceof ITrackBlock track) - list.addAll(track.getConnected(world, blockPos, blockState, linear, location)); - } - return list; - } - - public default Collection getConnected(BlockGetter worldIn, BlockPos pos, BlockState state, - boolean linear, @Nullable TrackNodeLocation connectedTo) { - BlockGetter world = connectedTo != null && worldIn instanceof ServerLevel sl ? sl.getServer() - .getLevel(connectedTo.dimension) : worldIn; - Vec3 center = Vec3.atBottomCenterOf(pos) - .add(0, getElevationAtCenter(world, pos, state), 0); - List list = new ArrayList<>(); - TrackShape shape = state.getValue(TrackBlock.SHAPE); - getTrackAxes(world, pos, state).forEach(axis -> { - addToListIfConnected(connectedTo, list, (d, b) -> axis.scale(b ? d : -d) - .add(center), b -> shape.getNormal(), b -> world instanceof Level l ? l.dimension() : Level.OVERWORLD, - axis, null); - }); - - return list; - } - - public static void addToListIfConnected(@Nullable TrackNodeLocation fromEnd, Collection list, - BiFunction offsetFactory, Function normalFactory, - Function> dimensionFactory, Vec3 axis, BezierConnection viaTurn) { - - DiscoveredLocation firstLocation = - new DiscoveredLocation(dimensionFactory.apply(true), offsetFactory.apply(0.5d, true)).viaTurn(viaTurn) - .withNormal(normalFactory.apply(true)) - .withDirection(axis); - DiscoveredLocation secondLocation = - new DiscoveredLocation(dimensionFactory.apply(false), offsetFactory.apply(0.5d, false)).viaTurn(viaTurn) - .withNormal(normalFactory.apply(false)) - .withDirection(axis); - - if (!firstLocation.dimension.equals(secondLocation.dimension)) { - firstLocation.forceNode(); - secondLocation.forceNode(); - } - - boolean skipFirst = false; - boolean skipSecond = false; - - if (fromEnd != null) { - boolean equalsFirst = firstLocation.equals(fromEnd); - boolean equalsSecond = secondLocation.equals(fromEnd); - - // not reachable from this end - if (!equalsFirst && !equalsSecond) - return; - - if (equalsFirst) - skipFirst = true; - if (equalsSecond) - skipSecond = true; - } - - if (!skipFirst) - list.add(firstLocation); - if (!skipSecond) - list.add(secondLocation); - } - - @OnlyIn(Dist.CLIENT) - public PartialModel prepareTrackOverlay(BlockGetter world, BlockPos pos, BlockState state, - BezierTrackPointLocation bezierPoint, AxisDirection direction, PoseStack transform, - RenderedTrackOverlayType type); - - @OnlyIn(Dist.CLIENT) - public PartialModel prepareAssemblyOverlay(BlockGetter world, BlockPos pos, BlockState state, Direction direction, - PoseStack ms); - - public default boolean isSlope(BlockGetter world, BlockPos pos, BlockState state) { - return getTrackAxes(world, pos, state).get(0).y != 0; - } - - public default Pair getNearestTrackAxis(BlockGetter world, BlockPos pos, BlockState state, - Vec3 lookVec) { - Vec3 best = null; - double bestDiff = Double.MAX_VALUE; - for (Vec3 vec3 : getTrackAxes(world, pos, state)) { - for (int opposite : Iterate.positiveAndNegative) { - double distanceTo = vec3.normalize() - .distanceTo(lookVec.scale(opposite)); - if (distanceTo > bestDiff) - continue; - bestDiff = distanceTo; - best = vec3; - } - } - return Pair.of(best, lookVec.dot(best.multiply(1, 0, 1) - .normalize()) < 0 ? AxisDirection.POSITIVE : AxisDirection.NEGATIVE); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/TrackEdge.java b/src/main/java/com/simibubi/create/content/logistics/trains/TrackEdge.java deleted file mode 100644 index d5e3affe0..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/TrackEdge.java +++ /dev/null @@ -1,195 +0,0 @@ -package com.simibubi.create.content.logistics.trains; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; - -import com.google.common.collect.ImmutableList; -import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgeData; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction.Axis; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.util.Mth; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.Vec3; - -public class TrackEdge { - - public TrackNode node1; - public TrackNode node2; - BezierConnection turn; - EdgeData edgeData; - boolean interDimensional; - - public TrackEdge(TrackNode node1, TrackNode node2, BezierConnection turn) { - this.interDimensional = !node1.location.dimension.equals(node2.location.dimension); - this.edgeData = new EdgeData(this); - this.node1 = node1; - this.node2 = node2; - this.turn = turn; - } - - public boolean isTurn() { - return turn != null; - } - - public boolean isInterDimensional() { - return interDimensional; - } - - public EdgeData getEdgeData() { - return edgeData; - } - - public BezierConnection getTurn() { - return turn; - } - - public Vec3 getDirection(boolean fromFirst) { - return getPosition(fromFirst ? 0.25f : 1).subtract(getPosition(fromFirst ? 0 : 0.75f)) - .normalize(); - } - - public Vec3 getDirectionAt(double t) { - double length = getLength(); - double step = .5f / length; - t /= length; - Vec3 ahead = getPosition(Math.min(1, t + step)); - Vec3 behind = getPosition(Math.max(0, t - step)); - return ahead.subtract(behind) - .normalize(); - } - - public boolean canTravelTo(TrackEdge other) { - if (isInterDimensional() || other.isInterDimensional()) - return true; - Vec3 newDirection = other.getDirection(true); - return getDirection(false).dot(newDirection) > 7 / 8f; - } - - public double getLength() { - return isInterDimensional() ? 0 - : isTurn() ? turn.getLength() - : node1.location.getLocation() - .distanceTo(node2.location.getLocation()); - } - - public double incrementT(double currentT, double distance) { - boolean tooFar = Math.abs(distance) > 5; - double length = getLength(); - distance = distance / (length == 0 ? 1 : length); - return !tooFar && isTurn() ? turn.incrementT(currentT, distance) : currentT + distance; - } - - public Vec3 getPosition(double t) { - return isTurn() ? turn.getPosition(Mth.clamp(t, 0, 1)) - : VecHelper.lerp((float) t, node1.location.getLocation(), node2.location.getLocation()); - } - - public Collection getIntersection(TrackNode node1, TrackNode node2, TrackEdge other, TrackNode other1, - TrackNode other2) { - Vec3 v1 = node1.location.getLocation(); - Vec3 v2 = node2.location.getLocation(); - Vec3 w1 = other1.location.getLocation(); - Vec3 w2 = other2.location.getLocation(); - - if (isInterDimensional() || other.isInterDimensional()) - return Collections.emptyList(); - if (v1.y != v2.y || v1.y != w1.y || v1.y != w2.y) - return Collections.emptyList(); - - if (!isTurn()) { - if (!other.isTurn()) - return ImmutableList.of(VecHelper.intersectRanged(v1, w1, v2, w2, Axis.Y)); - return other.getIntersection(other1, other2, this, node1, node2) - .stream() - .map(a -> new double[] { a[1], a[0] }) - .toList(); - } - - AABB bb = turn.getBounds(); - - if (!other.isTurn()) { - if (!bb.intersects(w1, w2)) - return Collections.emptyList(); - - Vec3 seg1 = v1; - Vec3 seg2 = null; - double t = 0; - - Collection intersections = new ArrayList<>(); - for (int i = 0; i < turn.getSegmentCount(); i++) { - double tOffset = t; - t += .5; - seg2 = getPosition(t / getLength()); - double[] intersection = VecHelper.intersectRanged(seg1, w1, seg2, w2, Axis.Y); - seg1 = seg2; - if (intersection == null) - continue; - intersection[0] += tOffset; - intersections.add(intersection); - } - - return intersections; - } - - if (!bb.intersects(other.turn.getBounds())) - return Collections.emptyList(); - - Vec3 seg1 = v1; - Vec3 seg2 = null; - double t = 0; - - Collection intersections = new ArrayList<>(); - for (int i = 0; i < turn.getSegmentCount(); i++) { - double tOffset = t; - t += .5; - seg2 = getPosition(t / getLength()); - - Vec3 otherSeg1 = w1; - Vec3 otherSeg2 = null; - double u = 0; - - for (int j = 0; j < other.turn.getSegmentCount(); j++) { - double uOffset = u; - u += .5; - otherSeg2 = other.getPosition(u / other.getLength()); - - double[] intersection = VecHelper.intersectRanged(seg1, otherSeg1, seg2, otherSeg2, Axis.Y); - otherSeg1 = otherSeg2; - - if (intersection == null) - continue; - - intersection[0] += tOffset; - intersection[1] += uOffset; - intersections.add(intersection); - } - - seg1 = seg2; - } - - return intersections; - } - - public Vec3 getNormal(TrackNode node1, TrackNode node2, double t) { - return isTurn() ? turn.getNormal(Mth.clamp(t, 0, 1)) : node1.getNormal(); - } - - public CompoundTag write(DimensionPalette dimensions) { - CompoundTag baseCompound = isTurn() ? turn.write(BlockPos.ZERO) : new CompoundTag(); - baseCompound.put("Signals", edgeData.write(dimensions)); - return baseCompound; - } - - public static TrackEdge read(TrackNode node1, TrackNode node2, CompoundTag tag, TrackGraph graph, - DimensionPalette dimensions) { - TrackEdge trackEdge = - new TrackEdge(node1, node2, tag.contains("Positions") ? new BezierConnection(tag, BlockPos.ZERO) : null); - trackEdge.edgeData = EdgeData.read(tag.getCompound("Signals"), trackEdge, graph, dimensions); - return trackEdge; - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphHelper.java b/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphHelper.java deleted file mode 100644 index 8400d1501..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphHelper.java +++ /dev/null @@ -1,175 +0,0 @@ -package com.simibubi.create.content.logistics.trains; - -import java.util.Collection; -import java.util.Map; -import java.util.Map.Entry; - -import javax.annotation.Nullable; - -import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.TrackNodeLocation.DiscoveredLocation; -import com.simibubi.create.content.logistics.trains.track.BezierTrackPointLocation; -import com.simibubi.create.content.logistics.trains.track.TrackTileEntity; -import com.simibubi.create.foundation.utility.Couple; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction.AxisDirection; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; - -public class TrackGraphHelper { - - @Nullable - public static GraphLocation getGraphLocationAt(Level level, BlockPos pos, AxisDirection targetDirection, - Vec3 targetAxis) { - BlockState trackBlockState = level.getBlockState(pos); - if (!(trackBlockState.getBlock()instanceof ITrackBlock track)) - return null; - - Vec3 axis = targetAxis.scale(targetDirection.getStep()); - double length = axis.length(); - TrackGraph graph = null; - - // Case 1: Centre of block lies on a node - - TrackNodeLocation location = new TrackNodeLocation(Vec3.atBottomCenterOf(pos) - .add(0, track.getElevationAtCenter(level, pos, trackBlockState), 0)).in(level); - graph = Create.RAILWAYS.sided(level) - .getGraph(level, location); - if (graph != null) { - TrackNode node = graph.locateNode(location); - if (node != null) { - Map connectionsFrom = graph.getConnectionsFrom(node); - for (Entry entry : connectionsFrom.entrySet()) { - TrackNode backNode = entry.getKey(); - Vec3 direction = entry.getValue() - .getDirection(true); - if (direction.scale(length) - .distanceToSqr(axis.scale(-1)) > 1 / 4096f) - continue; - - GraphLocation graphLocation = new GraphLocation(); - graphLocation.edge = Couple.create(node.getLocation(), backNode.getLocation()); - graphLocation.position = 0; - graphLocation.graph = graph; - return graphLocation; - } - } - } - - // Case 2: Center of block is between two nodes - - Collection ends = track.getConnected(level, pos, trackBlockState, true, null); - Vec3 start = Vec3.atBottomCenterOf(pos) - .add(0, track.getElevationAtCenter(level, pos, trackBlockState), 0); - - TrackNode frontNode = null; - TrackNode backNode = null; - double position = 0; - - for (DiscoveredLocation current : ends) { - Vec3 offset = current.getLocation() - .subtract(start) - .normalize() - .scale(length); - - boolean forward = offset.distanceToSqr(axis.scale(-1)) < 1 / 4096f; - boolean backwards = offset.distanceToSqr(axis) < 1 / 4096f; - - if (!forward && !backwards) - continue; - - DiscoveredLocation previous = null; - double distance = 0; - for (int i = 0; i < 100 && distance < 32; i++) { - DiscoveredLocation loc = current; - if (graph == null) - graph = Create.RAILWAYS.sided(level) - .getGraph(level, loc); - - if (graph == null || graph.locateNode(loc) == null) { - Collection list = ITrackBlock.walkConnectedTracks(level, loc, true); - for (DiscoveredLocation discoveredLocation : list) { - if (discoveredLocation == previous) - continue; - Vec3 diff = discoveredLocation.getLocation() - .subtract(loc.getLocation()); - if ((forward ? axis.scale(-1) : axis).distanceToSqr(diff.normalize() - .scale(length)) > 1 / 4096f) - continue; - - previous = current; - current = discoveredLocation; - distance += diff.length(); - break; - } - continue; - } - - TrackNode node = graph.locateNode(loc); - if (forward) - frontNode = node; - if (backwards) { - backNode = node; - position = distance + axis.length() / 2; - } - break; - } - } - - if (frontNode == null || backNode == null) - return null; - - GraphLocation graphLocation = new GraphLocation(); - graphLocation.edge = Couple.create(backNode.getLocation(), frontNode.getLocation()); - graphLocation.position = position; - graphLocation.graph = graph; - return graphLocation; - } - - @Nullable - public static GraphLocation getBezierGraphLocationAt(Level level, BlockPos pos, AxisDirection targetDirection, - BezierTrackPointLocation targetBezier) { - BlockState state = level.getBlockState(pos); - - if (!(state.getBlock()instanceof ITrackBlock track)) - return null; - if (!(level.getBlockEntity(pos)instanceof TrackTileEntity trackTE)) - return null; - BezierConnection bc = trackTE.getConnections() - .get(targetBezier.curveTarget()); - if (bc == null || !bc.isPrimary()) - return null; - - TrackNodeLocation targetLoc = new TrackNodeLocation(bc.starts.getSecond()).in(level); - for (DiscoveredLocation location : track.getConnected(level, pos, state, true, null)) { - TrackGraph graph = Create.RAILWAYS.sided(level) - .getGraph(level, location); - if (graph == null) - continue; - TrackNode targetNode = graph.locateNode(targetLoc); - if (targetNode == null) - continue; - TrackNode node = graph.locateNode(location); - TrackEdge edge = graph.getConnectionsFrom(node) - .get(targetNode); - if (edge == null) - continue; - - GraphLocation graphLocation = new GraphLocation(); - graphLocation.graph = graph; - graphLocation.edge = Couple.create(location, targetLoc); - graphLocation.position = (targetBezier.segment() + 1) / 2f; - if (targetDirection == AxisDirection.POSITIVE) { - graphLocation.edge = graphLocation.edge.swap(); - graphLocation.position = edge.getLength() - graphLocation.position; - } - - return graphLocation; - } - - return null; - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphPacket.java b/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphPacket.java deleted file mode 100644 index 888474405..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphPacket.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.simibubi.create.content.logistics.trains; - -import java.util.UUID; -import java.util.function.Supplier; - -import com.simibubi.create.CreateClient; -import com.simibubi.create.foundation.networking.SimplePacketBase; - -import net.minecraftforge.network.NetworkEvent.Context; - -public abstract class TrackGraphPacket extends SimplePacketBase { - - public UUID graphId; - public int netId; - public boolean packetDeletesGraph; - - @Override - public void handle(Supplier context) { - context.get() - .enqueueWork(() -> handle(CreateClient.RAILWAYS, CreateClient.RAILWAYS.getOrCreateGraph(graphId, netId))); - context.get() - .setPacketHandled(true); - } - - protected abstract void handle(GlobalRailwayManager manager, TrackGraph graph); - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphRequestPacket.java b/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphRequestPacket.java deleted file mode 100644 index eb179ba41..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphRequestPacket.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.simibubi.create.content.logistics.trains; - -import java.util.function.Supplier; - -import com.simibubi.create.Create; -import com.simibubi.create.foundation.networking.SimplePacketBase; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraftforge.network.NetworkEvent.Context; - -public class TrackGraphRequestPacket extends SimplePacketBase { - - private int netId; - - public TrackGraphRequestPacket(int netId) { - this.netId = netId; - } - - public TrackGraphRequestPacket(FriendlyByteBuf buffer) { - netId = buffer.readInt(); - } - - @Override - public void write(FriendlyByteBuf buffer) { - buffer.writeInt(netId); - } - - @Override - public void handle(Supplier context) { - context.get() - .enqueueWork(() -> { - for (TrackGraph trackGraph : Create.RAILWAYS.trackNetworks.values()) { - if (trackGraph.netId == netId) { - Create.RAILWAYS.sync.sendFullGraphTo(trackGraph, context.get() - .getSender()); - break; - } - } - }); - context.get() - .setPacketHandled(true); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphRollCallPacket.java b/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphRollCallPacket.java deleted file mode 100644 index fe4f3b0f8..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphRollCallPacket.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.simibubi.create.content.logistics.trains; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.function.Supplier; - -import com.simibubi.create.Create; -import com.simibubi.create.foundation.networking.AllPackets; -import com.simibubi.create.foundation.networking.SimplePacketBase; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraftforge.network.NetworkEvent.Context; - -public class TrackGraphRollCallPacket extends SimplePacketBase { - - int[] ints; - - public TrackGraphRollCallPacket() { - GlobalRailwayManager manager = Create.RAILWAYS; - ints = new int[manager.trackNetworks.size() * 2]; - int i = 0; - for (TrackGraph trackGraph : manager.trackNetworks.values()) { - ints[i] = trackGraph.netId; - ints[i + 1] = trackGraph.getChecksum(); - i += 2; - } - } - - public TrackGraphRollCallPacket(FriendlyByteBuf buffer) { - ints = new int[buffer.readVarInt()]; - for (int i = 0; i < ints.length; i++) - ints[i] = buffer.readInt(); - } - - @Override - public void write(FriendlyByteBuf buffer) { - buffer.writeVarInt(ints.length); - for (int i : ints) - buffer.writeInt(i); - } - - @Override - public void handle(Supplier context) { - context.get() - .enqueueWork(() -> { - - GlobalRailwayManager manager = Create.RAILWAYS.sided(null); - Set unusedIds = new HashSet<>(manager.trackNetworks.keySet()); - List failedIds = new ArrayList<>(); - Map idByNetId = new HashMap<>(); - manager.trackNetworks.forEach((uuid, g) -> idByNetId.put(g.netId, uuid)); - - for (int i = 0; i < ints.length; i += 2) { - UUID uuid = idByNetId.get(ints[i]); - if (uuid == null) { - failedIds.add(ints[i]); - continue; - } - unusedIds.remove(uuid); - TrackGraph trackGraph = manager.trackNetworks.get(uuid); - if (trackGraph.getChecksum() == ints[i + 1]) - continue; - Create.LOGGER.warn("Track network: " + uuid.toString() - .substring(0, 6) + " failed its checksum; Requesting refresh"); - failedIds.add(ints[i]); - } - - for (Integer failed : failedIds) - AllPackets.channel.sendToServer(new TrackGraphRequestPacket(failed)); - for (UUID unused : unusedIds) - manager.trackNetworks.remove(unused); - - }); - context.get() - .setPacketHandled(true); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/TrackNodeLocation.java b/src/main/java/com/simibubi/create/content/logistics/trains/TrackNodeLocation.java deleted file mode 100644 index 509eedd23..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/TrackNodeLocation.java +++ /dev/null @@ -1,175 +0,0 @@ -package com.simibubi.create.content.logistics.trains; - -import java.util.Collection; -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; - -import com.simibubi.create.foundation.utility.Iterate; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Vec3i; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtUtils; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.resources.ResourceKey; -import net.minecraft.world.level.Level; -import net.minecraft.world.phys.Vec3; - -public class TrackNodeLocation extends Vec3i { - - public ResourceKey dimension; - - public TrackNodeLocation(Vec3 vec) { - this(vec.x, vec.y, vec.z); - } - - public TrackNodeLocation(double p_121865_, double p_121866_, double p_121867_) { - super(Math.round(p_121865_ * 2), Math.floor(p_121866_ * 2), Math.round(p_121867_ * 2)); - } - - public TrackNodeLocation in(Level level) { - return in(level.dimension()); - } - - public TrackNodeLocation in(ResourceKey dimension) { - this.dimension = dimension; - return this; - } - - private static TrackNodeLocation fromPackedPos(BlockPos bufferPos) { - return new TrackNodeLocation(bufferPos); - } - - private TrackNodeLocation(BlockPos readBlockPos) { - super(readBlockPos.getX(), readBlockPos.getY(), readBlockPos.getZ()); - } - - public Vec3 getLocation() { - return new Vec3(getX() / 2.0, getY() / 2.0, getZ() / 2.0); - } - - public ResourceKey getDimension() { - return dimension; - } - - @Override - public boolean equals(Object pOther) { - return equalsIgnoreDim(pOther) && pOther instanceof TrackNodeLocation tnl - && Objects.equals(tnl.dimension, dimension); - } - - public boolean equalsIgnoreDim(Object pOther) { - return super.equals(pOther); - } - - @Override - public int hashCode() { - return (this.getY() + (this.getZ() * 31 + dimension.hashCode()) * 31) * 31 + this.getX(); - } - - public CompoundTag write(DimensionPalette dimensions) { - CompoundTag c = NbtUtils.writeBlockPos(new BlockPos(this)); - if (dimensions != null) - c.putInt("D", dimensions.encode(dimension)); - return c; - } - - public static TrackNodeLocation read(CompoundTag tag, DimensionPalette dimensions) { - TrackNodeLocation location = fromPackedPos(NbtUtils.readBlockPos(tag)); - if (dimensions != null) - location.dimension = dimensions.decode(tag.getInt("D")); - return location; - } - - public void send(FriendlyByteBuf buffer, DimensionPalette dimensions) { - buffer.writeVarInt(this.getX()); - buffer.writeShort(this.getY()); - buffer.writeVarInt(this.getZ()); - buffer.writeVarInt(dimensions.encode(dimension)); - } - - public static TrackNodeLocation receive(FriendlyByteBuf buffer, DimensionPalette dimensions) { - TrackNodeLocation location = fromPackedPos(new BlockPos( - buffer.readVarInt(), - buffer.readShort(), - buffer.readVarInt() - )); - location.dimension = dimensions.decode(buffer.readVarInt()); - return location; - } - - public Collection allAdjacent() { - Set set = new HashSet<>(); - Vec3 vec3 = getLocation(); - double step = 1 / 8f; - for (int x : Iterate.positiveAndNegative) - for (int y : Iterate.positiveAndNegative) - for (int z : Iterate.positiveAndNegative) - set.add(new BlockPos(vec3.add(x * step, y * step, z * step))); - return set; - } - - public static class DiscoveredLocation extends TrackNodeLocation { - - BezierConnection turn = null; - boolean forceNode = false; - Vec3 direction; - Vec3 normal; - - public DiscoveredLocation(Level level, double p_121865_, double p_121866_, double p_121867_) { - super(p_121865_, p_121866_, p_121867_); - in(level); - } - - public DiscoveredLocation(ResourceKey dimension, Vec3 vec) { - super(vec); - in(dimension); - } - - public DiscoveredLocation(Level level, Vec3 vec) { - this(level.dimension(), vec); - } - - public DiscoveredLocation viaTurn(BezierConnection turn) { - this.turn = turn; - if (turn != null) - forceNode(); - return this; - } - - public DiscoveredLocation forceNode() { - forceNode = true; - return this; - } - - public DiscoveredLocation withNormal(Vec3 normal) { - this.normal = normal; - return this; - } - - public DiscoveredLocation withDirection(Vec3 direction) { - this.direction = direction == null ? null : direction.normalize(); - return this; - } - - public boolean connectedViaTurn() { - return turn != null; - } - - public BezierConnection getTurn() { - return turn; - } - - public boolean shouldForceNode() { - return forceNode; - } - - public boolean notInLineWith(Vec3 direction) { - return this.direction != null - && Math.max(direction.dot(this.direction), direction.dot(this.direction.scale(-1))) < 7 / 8f; - } - - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/BogeyInstance.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/BogeyInstance.java deleted file mode 100644 index 9a8a6c9c1..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/BogeyInstance.java +++ /dev/null @@ -1,235 +0,0 @@ -package com.simibubi.create.content.logistics.trains.entity; - -import com.jozufozu.flywheel.api.Material; -import com.jozufozu.flywheel.api.MaterialManager; -import com.jozufozu.flywheel.core.Materials; -import com.jozufozu.flywheel.core.materials.model.ModelData; -import com.jozufozu.flywheel.util.AnimationTickHolder; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.relays.elementary.ShaftBlock; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.Iterate; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.BlockAndTintGetter; -import net.minecraft.world.level.LightLayer; -import net.minecraft.world.phys.Vec3; - -public sealed class BogeyInstance { - - public final CarriageBogey bogey; - private final ModelData[] shafts; - - protected BogeyInstance(CarriageBogey bogey, MaterialManager materialManager) { - this.bogey = bogey; - - shafts = new ModelData[2]; - - materialManager.defaultSolid() - .material(Materials.TRANSFORMED) - .getModel(AllBlocks.SHAFT.getDefaultState() - .setValue(ShaftBlock.AXIS, Direction.Axis.Z)) - .createInstances(shafts); - - } - - public void remove() { - for (ModelData shaft : shafts) - shaft.delete(); - } - - public void hiddenFrame() { - beginFrame(0, null); - } - - public void beginFrame(float wheelAngle, PoseStack ms) { - if (ms == null) { - for (int i : Iterate.zeroAndOne) - shafts[i].setEmptyTransform(); - return; - } - - for (int i : Iterate.zeroAndOne) - shafts[i].setTransform(ms) - .translate(-.5f, .25f, i * -1) - .centre() - .rotateZ(wheelAngle) - .unCentre(); - } - - public void updateLight(BlockAndTintGetter world, CarriageContraptionEntity entity) { - var lightPos = new BlockPos(getLightPos(entity)); - - updateLight(world.getBrightness(LightLayer.BLOCK, lightPos), world.getBrightness(LightLayer.SKY, lightPos)); - } - - private Vec3 getLightPos(CarriageContraptionEntity entity) { - if (bogey.getAnchorPosition() != null) { - return bogey.getAnchorPosition(); - } else { - return entity.getLightProbePosition(AnimationTickHolder.getPartialTicks()); - } - } - - public void updateLight(int blockLight, int skyLight) { - for (ModelData shaft : shafts) { - shaft.setBlockLight(blockLight) - .setSkyLight(skyLight); - } - } - - public static final class Frame extends BogeyInstance { - - private final ModelData frame; - private final ModelData[] wheels; - - public Frame(CarriageBogey bogey, MaterialManager materialManager) { - super(bogey, materialManager); - - frame = materialManager.defaultSolid() - .material(Materials.TRANSFORMED) - .getModel(AllBlockPartials.BOGEY_FRAME) - .createInstance(); - - wheels = new ModelData[2]; - - materialManager.defaultSolid() - .material(Materials.TRANSFORMED) - .getModel(AllBlockPartials.SMALL_BOGEY_WHEELS) - .createInstances(wheels); - } - - @Override - public void beginFrame(float wheelAngle, PoseStack ms) { - super.beginFrame(wheelAngle, ms); - - if (ms == null) { - frame.setEmptyTransform(); - for (int side : Iterate.positiveAndNegative) - wheels[(side + 1) / 2].setEmptyTransform(); - return; - } - - frame.setTransform(ms); - - for (int side : Iterate.positiveAndNegative) { - wheels[(side + 1) / 2].setTransform(ms) - .translate(0, 12 / 16f, side) - .rotateX(wheelAngle); - } - } - - @Override - public void updateLight(int blockLight, int skyLight) { - super.updateLight(blockLight, skyLight); - frame.setBlockLight(blockLight) - .setSkyLight(skyLight); - for (ModelData wheel : wheels) - wheel.setBlockLight(blockLight) - .setSkyLight(skyLight); - } - - @Override - public void remove() { - super.remove(); - frame.delete(); - for (ModelData wheel : wheels) - wheel.delete(); - } - } - - public static final class Drive extends BogeyInstance { - - private final ModelData[] secondShaft; - private final ModelData drive; - private final ModelData piston; - private final ModelData wheels; - private final ModelData pin; - - public Drive(CarriageBogey bogey, MaterialManager materialManager) { - super(bogey, materialManager); - Material mat = materialManager.defaultSolid() - .material(Materials.TRANSFORMED); - - secondShaft = new ModelData[2]; - - mat.getModel(AllBlocks.SHAFT.getDefaultState() - .setValue(ShaftBlock.AXIS, Direction.Axis.X)) - .createInstances(secondShaft); - - drive = mat.getModel(AllBlockPartials.BOGEY_DRIVE) - .createInstance(); - piston = mat.getModel(AllBlockPartials.BOGEY_PISTON) - .createInstance(); - wheels = mat.getModel(AllBlockPartials.LARGE_BOGEY_WHEELS) - .createInstance(); - pin = mat.getModel(AllBlockPartials.BOGEY_PIN) - .createInstance(); - } - - @Override - public void beginFrame(float wheelAngle, PoseStack ms) { - super.beginFrame(wheelAngle, ms); - - if (ms == null) { - for (int i : Iterate.zeroAndOne) - secondShaft[i].setEmptyTransform(); - drive.setEmptyTransform(); - piston.setEmptyTransform(); - wheels.setEmptyTransform(); - pin.setEmptyTransform(); - return; - } - - for (int i : Iterate.zeroAndOne) - secondShaft[i].setTransform(ms) - .translate(-.5f, .25f, .5f + i * -2) - .centre() - .rotateX(wheelAngle) - .unCentre(); - - drive.setTransform(ms); - piston.setTransform(ms) - .translate(0, 0, 1 / 4f * Math.sin(AngleHelper.rad(wheelAngle))); - - wheels.setTransform(ms) - .translate(0, 1, 0) - .rotateX(wheelAngle); - pin.setTransform(ms) - .translate(0, 1, 0) - .rotateX(wheelAngle) - .translate(0, 1 / 4f, 0) - .rotateX(-wheelAngle); - } - - @Override - public void updateLight(int blockLight, int skyLight) { - super.updateLight(blockLight, skyLight); - for (ModelData shaft : secondShaft) - shaft.setBlockLight(blockLight) - .setSkyLight(skyLight); - drive.setBlockLight(blockLight) - .setSkyLight(skyLight); - piston.setBlockLight(blockLight) - .setSkyLight(skyLight); - wheels.setBlockLight(blockLight) - .setSkyLight(skyLight); - pin.setBlockLight(blockLight) - .setSkyLight(skyLight); - } - - @Override - public void remove() { - super.remove(); - for (ModelData shaft : secondShaft) - shaft.delete(); - drive.delete(); - piston.delete(); - wheels.delete(); - pin.delete(); - } - } -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageBogey.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageBogey.java deleted file mode 100644 index c9e2d7220..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageBogey.java +++ /dev/null @@ -1,172 +0,0 @@ -package com.simibubi.create.content.logistics.trains.entity; - -import javax.annotation.Nullable; - -import com.jozufozu.flywheel.api.MaterialManager; -import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.DimensionPalette; -import com.simibubi.create.content.logistics.trains.IBogeyBlock; -import com.simibubi.create.content.logistics.trains.TrackGraph; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.RegisteredObjects; -import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; - -import net.minecraft.core.Direction.Axis; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.Tag; -import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.util.Mth; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.registries.ForgeRegistries; - -public class CarriageBogey { - - public Carriage carriage; - - boolean isLeading; - - IBogeyBlock type; - Couple points; - - LerpedFloat wheelAngle; - LerpedFloat yaw; - LerpedFloat pitch; - - public Couple couplingAnchors; - - int derailAngle; - - public CarriageBogey(IBogeyBlock type, TravellingPoint point, TravellingPoint point2) { - this.type = type; - points = Couple.create(point, point2); - wheelAngle = LerpedFloat.angular(); - yaw = LerpedFloat.angular(); - pitch = LerpedFloat.angular(); - derailAngle = Create.RANDOM.nextInt(60) - 30; - couplingAnchors = Couple.create(null, null); - } - - public ResourceKey getDimension() { - TravellingPoint leading = leading(); - TravellingPoint trailing = trailing(); - if (leading.edge == null || trailing.edge == null) - return null; - if (leading.edge.isInterDimensional() || trailing.edge.isInterDimensional()) - return null; - ResourceKey dimension1 = leading.node1.getLocation().dimension; - ResourceKey dimension2 = trailing.node1.getLocation().dimension; - if (dimension1.equals(dimension2)) - return dimension1; - return null; - } - - public void updateAngles(CarriageContraptionEntity entity, double distanceMoved) { - double angleDiff = 360 * distanceMoved / (Math.PI * 2 * type.getWheelRadius()); - - float xRot = 0; - float yRot = 0; - - if (leading().edge == null || carriage.train.derailed) { - yRot = -90 + entity.yaw - derailAngle; - } else if (!entity.level.dimension() - .equals(getDimension())) { - yRot = -90 + entity.yaw; - xRot = 0; - } else { - Vec3 positionVec = leading().getPosition(); - Vec3 coupledVec = trailing().getPosition(); - double diffX = positionVec.x - coupledVec.x; - double diffY = positionVec.y - coupledVec.y; - double diffZ = positionVec.z - coupledVec.z; - yRot = AngleHelper.deg(Mth.atan2(diffZ, diffX)) + 90; - xRot = AngleHelper.deg(Math.atan2(diffY, Math.sqrt(diffX * diffX + diffZ * diffZ))); - } - - double newWheelAngle = (wheelAngle.getValue() - angleDiff) % 360; - - for (boolean twice : Iterate.trueAndFalse) { - if (twice && !entity.firstPositionUpdate) - continue; - wheelAngle.setValue(newWheelAngle); - pitch.setValue(xRot); - yaw.setValue(-yRot); - } - } - - public TravellingPoint leading() { - return points.getFirst(); - } - - public TravellingPoint trailing() { - return points.getSecond(); - } - - public double getStress() { - if (getDimension() == null) - return 0; - if (carriage.train.derailed) - return 0; - return type.getWheelPointSpacing() - leading().getPosition() - .distanceTo(trailing().getPosition()); - } - - @Nullable - public Vec3 getAnchorPosition() { - if (leading().edge == null) - return null; - return points.getFirst() - .getPosition() - .add(points.getSecond() - .getPosition()) - .scale(.5); - } - - public void updateCouplingAnchor(Vec3 entityPos, float entityXRot, float entityYRot, int bogeySpacing, - float partialTicks, boolean leading) { - Vec3 thisOffset = type.getConnectorAnchorOffset(); - thisOffset = thisOffset.multiply(1, 1, leading ? -1 : 1); - - thisOffset = VecHelper.rotate(thisOffset, pitch.getValue(partialTicks), Axis.X); - thisOffset = VecHelper.rotate(thisOffset, yaw.getValue(partialTicks), Axis.Y); - thisOffset = VecHelper.rotate(thisOffset, -entityYRot - 90, Axis.Y); - thisOffset = VecHelper.rotate(thisOffset, entityXRot, Axis.X); - thisOffset = VecHelper.rotate(thisOffset, -180, Axis.Y); - thisOffset = thisOffset.add(0, 0, leading ? 0 : -bogeySpacing); - thisOffset = VecHelper.rotate(thisOffset, 180, Axis.Y); - thisOffset = VecHelper.rotate(thisOffset, -entityXRot, Axis.X); - thisOffset = VecHelper.rotate(thisOffset, entityYRot + 90, Axis.Y); - - couplingAnchors.set(leading, entityPos.add(thisOffset)); - } - - public CompoundTag write(DimensionPalette dimensions) { - CompoundTag tag = new CompoundTag(); - tag.putString("Type", RegisteredObjects.getKeyOrThrow((Block) type) - .toString()); - tag.put("Points", points.serializeEach(tp -> tp.write(dimensions))); - return tag; - } - - public static CarriageBogey read(CompoundTag tag, TrackGraph graph, DimensionPalette dimensions) { - ResourceLocation location = new ResourceLocation(tag.getString("Type")); - IBogeyBlock type = (IBogeyBlock) ForgeRegistries.BLOCKS.getValue(location); - Couple points = Couple.deserializeEach(tag.getList("Points", Tag.TAG_COMPOUND), - c -> TravellingPoint.read(c, graph, dimensions)); - CarriageBogey carriageBogey = new CarriageBogey(type, points.getFirst(), points.getSecond()); - return carriageBogey; - } - - public BogeyInstance createInstance(MaterialManager materialManager) { - return type.createInstance(materialManager, this); - } - - void setLeading() { - isLeading = true; - } -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageCouplingRenderer.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageCouplingRenderer.java deleted file mode 100644 index f67a86798..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageCouplingRenderer.java +++ /dev/null @@ -1,131 +0,0 @@ -package com.simibubi.create.content.logistics.trains.entity; - -import java.util.Collection; -import java.util.List; - -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.CreateClient; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.AnimationTickHolder; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.LightTexture; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.core.BlockPos; -import net.minecraft.util.Mth; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LightLayer; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; - -public class CarriageCouplingRenderer { - - public static void renderAll(PoseStack ms, MultiBufferSource buffer) { - Collection trains = CreateClient.RAILWAYS.trains.values(); - VertexConsumer vb = buffer.getBuffer(RenderType.solid()); - BlockState air = Blocks.AIR.defaultBlockState(); - float partialTicks = AnimationTickHolder.getPartialTicks(); - Entity cameraEntity = Minecraft.getInstance().cameraEntity; - if (cameraEntity == null) - return; - - Vec3 camera = cameraEntity.getPosition(partialTicks); - Level level = cameraEntity.level; - - for (Train train : trains) { - List carriages = train.carriages; - for (int i = 0; i < carriages.size() - 1; i++) { - Carriage carriage = carriages.get(i); - CarriageContraptionEntity entity = carriage.getDimensional(level).entity.get(); - Carriage carriage2 = carriages.get(i + 1); - CarriageContraptionEntity entity2 = carriage.getDimensional(level).entity.get(); - - if (entity == null || entity2 == null) - continue; - - CarriageBogey bogey1 = carriage.trailingBogey(); - CarriageBogey bogey2 = carriage2.leadingBogey(); - Vec3 anchor = bogey1.couplingAnchors.getSecond(); - Vec3 anchor2 = bogey2.couplingAnchors.getFirst(); - - if (anchor == null || anchor2 == null) - continue; - if (!anchor.closerThan(camera, 64)) - continue; - - int lightCoords = getPackedLightCoords(entity, partialTicks); - int lightCoords2 = getPackedLightCoords(entity2, partialTicks); - - double diffX = anchor2.x - anchor.x; - double diffY = anchor2.y - anchor.y; - double diffZ = anchor2.z - anchor.z; - float yRot = AngleHelper.deg(Mth.atan2(diffZ, diffX)) + 90; - float xRot = AngleHelper.deg(Math.atan2(diffY, Math.sqrt(diffX * diffX + diffZ * diffZ))); - - Vec3 position = entity.getPosition(partialTicks); - Vec3 position2 = entity2.getPosition(partialTicks); - - ms.pushPose(); - ms.pushPose(); - ms.translate(anchor.x, anchor.y, anchor.z); - CachedBufferer.partial(AllBlockPartials.TRAIN_COUPLING_HEAD, air) - .rotateY(-yRot) - .rotateX(xRot) - .light(lightCoords) - .renderInto(ms, vb); - - float margin = 3 / 16f; - double couplingDistance = train.carriageSpacing.get(i) - 2 * margin - - bogey1.type.getConnectorAnchorOffset().z - bogey2.type.getConnectorAnchorOffset().z; - int couplingSegments = (int) Math.round(couplingDistance * 4); - double stretch = ((anchor2.distanceTo(anchor) - 2 * margin) * 4) / couplingSegments; - for (int j = 0; j < couplingSegments; j++) { - CachedBufferer.partial(AllBlockPartials.TRAIN_COUPLING_CABLE, air) - .rotateY(-yRot + 180) - .rotateX(-xRot) - .translate(0, 0, margin + 2 / 16f) - .scale(1, 1, (float) stretch) - .translate(0, 0, j / 4f) - .light(lightCoords) - .renderInto(ms, vb); - } - - ms.popPose(); - - ms.pushPose(); - ms.translate(-position.x, -position.y, -position.z); - ms.translate(position2.x, position2.y, position2.z); - ms.translate(anchor2.x, anchor2.y, anchor2.z); - CachedBufferer.partial(AllBlockPartials.TRAIN_COUPLING_HEAD, air) - .rotateY(-yRot + 180) - .rotateX(-xRot) - .light(lightCoords2) - .renderInto(ms, vb); - ms.popPose(); - ms.popPose(); - - } - } - - } - - public static int getPackedLightCoords(Entity pEntity, float pPartialTicks) { - BlockPos blockpos = new BlockPos(pEntity.getLightProbePosition(pPartialTicks)); - return LightTexture.pack(getBlockLightLevel(pEntity, blockpos), getSkyLightLevel(pEntity, blockpos)); - } - - protected static int getSkyLightLevel(Entity pEntity, BlockPos pPos) { - return pEntity.level.getBrightness(LightLayer.SKY, pPos); - } - - protected static int getBlockLightLevel(Entity pEntity, BlockPos pPos) { - return pEntity.isOnFire() ? 15 : pEntity.level.getBrightness(LightLayer.BLOCK, pPos); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainPacket.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainPacket.java deleted file mode 100644 index 479b2699e..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainPacket.java +++ /dev/null @@ -1,115 +0,0 @@ -package com.simibubi.create.content.logistics.trains.entity; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.function.Supplier; - -import com.simibubi.create.CreateClient; -import com.simibubi.create.content.logistics.trains.IBogeyBlock; -import com.simibubi.create.foundation.networking.SimplePacketBase; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.RegisteredObjects; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.chat.Component; -import net.minecraft.world.level.block.Block; -import net.minecraftforge.network.NetworkEvent.Context; -import net.minecraftforge.registries.ForgeRegistries; - -public class TrainPacket extends SimplePacketBase { - - UUID trainId; - Train train; - boolean add; - - public TrainPacket(Train train, boolean add) { - this.train = train; - this.add = add; - } - - public TrainPacket(FriendlyByteBuf buffer) { - add = buffer.readBoolean(); - trainId = buffer.readUUID(); - - if (!add) - return; - - UUID owner = buffer.readUUID(); - List carriages = new ArrayList<>(); - List carriageSpacing = new ArrayList<>(); - - int size = buffer.readVarInt(); - for (int i = 0; i < size; i++) { - Couple bogies = Couple.create(null, null); - for (boolean first : Iterate.trueAndFalse) { - if (!first && !buffer.readBoolean()) - continue; - IBogeyBlock type = (IBogeyBlock) ForgeRegistries.BLOCKS.getValue(buffer.readResourceLocation()); - bogies.set(first, new CarriageBogey(type, new TravellingPoint(), new TravellingPoint())); - } - int spacing = buffer.readVarInt(); - carriages.add(new Carriage(bogies.getFirst(), bogies.getSecond(), spacing)); - } - - size = buffer.readVarInt(); - for (int i = 0; i < size; i++) - carriageSpacing.add(buffer.readVarInt()); - - boolean doubleEnded = buffer.readBoolean(); - train = new Train(trainId, owner, null, carriages, carriageSpacing, doubleEnded); - - train.name = Component.Serializer.fromJson(buffer.readUtf()); - train.icon = TrainIconType.byId(buffer.readResourceLocation()); - } - - @Override - public void write(FriendlyByteBuf buffer) { - buffer.writeBoolean(add); - buffer.writeUUID(train.id); - - if (!add) - return; - - buffer.writeUUID(train.owner); - - buffer.writeVarInt(train.carriages.size()); - for (Carriage carriage : train.carriages) { - for (boolean first : Iterate.trueAndFalse) { - if (!first) { - boolean onTwoBogeys = carriage.isOnTwoBogeys(); - buffer.writeBoolean(onTwoBogeys); - if (!onTwoBogeys) - continue; - } - CarriageBogey bogey = carriage.bogeys.get(first); - buffer.writeResourceLocation(RegisteredObjects.getKeyOrThrow((Block) bogey.type)); - } - buffer.writeVarInt(carriage.bogeySpacing); - } - - buffer.writeVarInt(train.carriageSpacing.size()); - train.carriageSpacing.forEach(buffer::writeVarInt); - - buffer.writeBoolean(train.doubleEnded); - buffer.writeUtf(Component.Serializer.toJson(train.name)); - buffer.writeResourceLocation(train.icon.id); - } - - @Override - public void handle(Supplier context) { - context.get() - .enqueueWork(() -> { - Map trains = CreateClient.RAILWAYS.trains; - if (add) - trains.put(train.id, train); - else - trains.remove(trainId); - }); - context.get() - .setPacketHandled(true); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainPromptPacket.java b/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainPromptPacket.java deleted file mode 100644 index 695a75392..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainPromptPacket.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.simibubi.create.content.logistics.trains.entity; - -import java.util.function.Supplier; - -import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.TrainHUD; -import com.simibubi.create.foundation.networking.SimplePacketBase; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.chat.Component; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.fml.DistExecutor; -import net.minecraftforge.network.NetworkEvent.Context; - -public class TrainPromptPacket extends SimplePacketBase { - - private Component text; - private boolean shadow; - - public TrainPromptPacket(Component text, boolean shadow) { - this.text = text; - this.shadow = shadow; - } - - public TrainPromptPacket(FriendlyByteBuf buffer) { - text = buffer.readComponent(); - shadow = buffer.readBoolean(); - } - - @Override - public void write(FriendlyByteBuf buffer) { - buffer.writeComponent(text); - buffer.writeBoolean(shadow); - } - - @Override - public void handle(Supplier context) { - context.get() - .enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> this::apply)); - context.get() - .setPacketHandled(true); - } - - @OnlyIn(Dist.CLIENT) - public void apply() { - TrainHUD.currentPrompt = text; - TrainHUD.currentPromptShadow = shadow; - TrainHUD.promptKeepAlive = 30; - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/display/FlapDisplayTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/display/FlapDisplayTileEntity.java deleted file mode 100644 index abb9887eb..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/display/FlapDisplayTileEntity.java +++ /dev/null @@ -1,333 +0,0 @@ -package com.simibubi.create.content.logistics.trains.management.display; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import com.google.gson.JsonElement; -import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.DyeHelper; -import com.simibubi.create.foundation.utility.DynamicComponent; -import com.simibubi.create.foundation.utility.NBTHelper; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Vec3i; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.util.Mth; -import net.minecraft.world.item.DyeColor; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.AABB; - -public class FlapDisplayTileEntity extends KineticTileEntity { - - public List lines; - public boolean isController; - public boolean isRunning; - public int xSize, ySize; - public DyeColor[] colour; - public boolean[] glowingLines; - public boolean[] manualLines; - - public FlapDisplayTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - setLazyTickRate(10); - isController = false; - xSize = 1; - ySize = 1; - colour = new DyeColor[2]; - manualLines = new boolean[2]; - glowingLines = new boolean[2]; - } - - @Override - public void initialize() { - super.initialize(); - } - - @Override - public void lazyTick() { - super.lazyTick(); - updateControllerStatus(); - } - - public void updateControllerStatus() { - if (level.isClientSide) - return; - - BlockState blockState = getBlockState(); - if (!(blockState.getBlock() instanceof FlapDisplayBlock)) - return; - - Direction leftDirection = blockState.getValue(FlapDisplayBlock.HORIZONTAL_FACING) - .getClockWise(); - boolean shouldBeController = !blockState.getValue(FlapDisplayBlock.UP) - && level.getBlockState(worldPosition.relative(leftDirection)) != blockState; - - int newXSize = 1; - int newYSize = 1; - - if (shouldBeController) { - for (int xOffset = 1; xOffset < 32; xOffset++) { - if (level.getBlockState(worldPosition.relative(leftDirection.getOpposite(), xOffset)) != blockState) - break; - newXSize++; - } - for (int yOffset = 0; yOffset < 32; yOffset++) { - if (!level.getBlockState(worldPosition.relative(Direction.DOWN, yOffset)) - .getOptionalValue(FlapDisplayBlock.DOWN) - .orElse(false)) - break; - newYSize++; - } - } - - if (isController == shouldBeController && newXSize == xSize && newYSize == ySize) - return; - - isController = shouldBeController; - xSize = newXSize; - ySize = newYSize; - colour = Arrays.copyOf(colour, ySize * 2); - glowingLines = Arrays.copyOf(glowingLines, ySize * 2); - manualLines = new boolean[ySize * 2]; - lines = null; - sendData(); - } - - @Override - public void tick() { - super.tick(); - isRunning = super.isSpeedRequirementFulfilled(); - if ((!level.isClientSide || !isRunning) && !isVirtual()) - return; - int activeFlaps = 0; - for (FlapDisplayLayout line : lines) - for (FlapDisplaySection section : line.getSections()) - activeFlaps += section.tick(); - if (activeFlaps == 0) - return; - - float volume = Mth.clamp(activeFlaps / 20f, 0.25f, 1.5f); - float bgVolume = Mth.clamp(activeFlaps / 40f, 0.25f, 1f); - BlockPos middle = worldPosition.relative(getDirection().getClockWise(), xSize / 2) - .relative(Direction.DOWN, ySize / 2); - AllSoundEvents.SCROLL_VALUE.playAt(level, middle, volume, 0.56f, false); - level.playLocalSound(middle.getX(), middle.getY(), middle.getZ(), SoundEvents.CALCITE_HIT, SoundSource.BLOCKS, - .35f * bgVolume, 1.95f, false); - } - - @Override - protected boolean isNoisy() { - return false; - } - - @Override - public boolean isSpeedRequirementFulfilled() { - return isRunning; - } - - public void applyTextManually(int lineIndex, String rawComponentText) { - List lines = getLines(); - if (lineIndex >= lines.size()) - return; - - FlapDisplayLayout layout = lines.get(lineIndex); - if (!layout.isLayout("Default")) - layout.loadDefault(getMaxCharCount()); - List sections = layout.getSections(); - - FlapDisplaySection flapDisplaySection = sections.get(0); - if (rawComponentText == null) { - manualLines[lineIndex] = false; - flapDisplaySection.setText(Components.immutableEmpty()); - notifyUpdate(); - return; - } - - JsonElement json = DynamicComponent.getJsonFromString(rawComponentText); - if (json == null) - return; - - manualLines[lineIndex] = true; - Component text = isVirtual() ? Component.Serializer.fromJson(rawComponentText) - : DynamicComponent.parseCustomText(level, worldPosition, json); - flapDisplaySection.setText(text); - if (isVirtual()) - flapDisplaySection.refresh(true); - else - notifyUpdate(); - } - - public void setColour(int lineIndex, DyeColor color) { - colour[lineIndex] = color == DyeColor.WHITE ? null : color; - notifyUpdate(); - } - - public void setGlowing(int lineIndex) { - glowingLines[lineIndex] = true; - notifyUpdate(); - } - - public List getLines() { - if (lines == null) - initDefaultSections(); - return lines; - } - - public void initDefaultSections() { - lines = new ArrayList<>(); - for (int i = 0; i < ySize * 2; i++) - lines.add(new FlapDisplayLayout(getMaxCharCount())); - } - - public int getMaxCharCount() { - return getMaxCharCount(0); - } - - public int getMaxCharCount(int gaps) { - return (int) ((xSize * 16f - 2f - 4f * gaps) / 3.5f); - } - - @Override - protected void write(CompoundTag tag, boolean clientPacket) { - super.write(tag, clientPacket); - - tag.putBoolean("Controller", isController); - tag.putInt("XSize", xSize); - tag.putInt("YSize", ySize); - - for (int j = 0; j < manualLines.length; j++) - if (manualLines[j]) - NBTHelper.putMarker(tag, "CustomLine" + j); - - for (int j = 0; j < glowingLines.length; j++) - if (glowingLines[j]) - NBTHelper.putMarker(tag, "GlowingLine" + j); - - for (int j = 0; j < colour.length; j++) - if (colour[j] != null) - NBTHelper.writeEnum(tag, "Dye" + j, colour[j]); - - List lines = getLines(); - for (int i = 0; i < lines.size(); i++) - tag.put("Display" + i, lines.get(i) - .write()); - } - - @Override - protected void read(CompoundTag tag, boolean clientPacket) { - super.read(tag, clientPacket); - boolean wasActive = isController; - int prevX = xSize; - int prevY = ySize; - - isController = tag.getBoolean("Controller"); - xSize = tag.getInt("XSize"); - ySize = tag.getInt("YSize"); - - manualLines = new boolean[ySize * 2]; - for (int i = 0; i < ySize * 2; i++) - manualLines[i] = tag.contains("CustomLine" + i); - - glowingLines = new boolean[ySize * 2]; - for (int i = 0; i < ySize * 2; i++) - glowingLines[i] = tag.contains("GlowingLine" + i); - - colour = new DyeColor[ySize * 2]; - for (int i = 0; i < ySize * 2; i++) - colour[i] = tag.contains("Dye" + i) ? NBTHelper.readEnum(tag, "Dye" + i, DyeColor.class) : null; - - if (clientPacket && wasActive != isController || prevX != xSize || prevY != ySize) { - invalidateRenderBoundingBox(); - lines = null; - } - - List lines = getLines(); - for (int i = 0; i < lines.size(); i++) - lines.get(i) - .read(tag.getCompound("Display" + i)); - } - - public int getLineIndexAt(double yCoord) { - return (int) Mth.clamp(Math.floor(2 * (worldPosition.getY() - yCoord + 1)), 0, ySize * 2); - } - - public FlapDisplayTileEntity getController() { - if (isController) - return this; - - BlockState blockState = getBlockState(); - if (!(blockState.getBlock() instanceof FlapDisplayBlock)) - return null; - - MutableBlockPos pos = getBlockPos().mutable(); - Direction side = blockState.getValue(FlapDisplayBlock.HORIZONTAL_FACING) - .getClockWise(); - - for (int i = 0; i < 64; i++) { - BlockState other = level.getBlockState(pos); - - if (other.getOptionalValue(FlapDisplayBlock.UP) - .orElse(false)) { - pos.move(Direction.UP); - continue; - } - - if (!level.getBlockState(pos.relative(side)) - .getOptionalValue(FlapDisplayBlock.UP) - .orElse(true)) { - pos.move(side); - continue; - } - - BlockEntity found = level.getBlockEntity(pos); - if (found instanceof FlapDisplayTileEntity flap && flap.isController) - return flap; - - break; - } - - return null; - } - - @Override - protected AABB createRenderBoundingBox() { - AABB aabb = new AABB(worldPosition); - if (!isController) - return aabb; - Vec3i normal = getDirection().getClockWise() - .getNormal(); - return aabb.expandTowards(normal.getX() * xSize, -ySize, normal.getZ() * xSize); - } - - public Direction getDirection() { - return getBlockState().getOptionalValue(FlapDisplayBlock.HORIZONTAL_FACING) - .orElse(Direction.SOUTH) - .getOpposite(); - } - - @Override - public void addBehaviours(List behaviours) {} - - public int getLineColor(int line) { - DyeColor color = colour[line]; - return color == null ? 0xFF_D3C6BA - : DyeHelper.DYE_TABLE.get(color) - .getFirst() | 0xFF_000000; - } - - public boolean isLineGlowing(int line) { - return glowingLines[line]; - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/EdgePointType.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/EdgePointType.java deleted file mode 100644 index 306ad68ba..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/EdgePointType.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.simibubi.create.content.logistics.trains.management.edgePoint; - -import java.util.HashMap; -import java.util.Map; -import java.util.function.Supplier; - -import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.DimensionPalette; -import com.simibubi.create.content.logistics.trains.management.edgePoint.observer.TrackObserver; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalBoundary; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.TrackEdgePoint; -import com.simibubi.create.content.logistics.trains.management.edgePoint.station.GlobalStation; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.resources.ResourceLocation; - -public class EdgePointType { - - public static final Map> TYPES = new HashMap<>(); - private ResourceLocation id; - private Supplier factory; - - public static final EdgePointType SIGNAL = - register(Create.asResource("signal"), SignalBoundary::new); - public static final EdgePointType STATION = - register(Create.asResource("station"), GlobalStation::new); - public static final EdgePointType OBSERVER = - register(Create.asResource("observer"), TrackObserver::new); - - public static EdgePointType register(ResourceLocation id, Supplier factory) { - EdgePointType type = new EdgePointType<>(id, factory); - TYPES.put(id, type); - return type; - } - - public EdgePointType(ResourceLocation id, Supplier factory) { - this.id = id; - this.factory = factory; - } - - public T create() { - T t = factory.get(); - t.setType(this); - return t; - } - - public ResourceLocation getId() { - return id; - } - - public static TrackEdgePoint read(FriendlyByteBuf buffer, DimensionPalette dimensions) { - ResourceLocation type = buffer.readResourceLocation(); - EdgePointType edgePointType = TYPES.get(type); - TrackEdgePoint point = edgePointType.create(); - point.read(buffer, dimensions); - return point; - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/observer/TrackObserver.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/observer/TrackObserver.java deleted file mode 100644 index 62ad747bb..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/observer/TrackObserver.java +++ /dev/null @@ -1,111 +0,0 @@ -package com.simibubi.create.content.logistics.trains.management.edgePoint.observer; - -import java.util.UUID; - -import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.DimensionPalette; -import com.simibubi.create.content.logistics.trains.TrackEdge; -import com.simibubi.create.content.logistics.trains.TrackGraph; -import com.simibubi.create.content.logistics.trains.entity.Train; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalPropagator; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SingleTileEdgePoint; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.BlockEntity; - -public class TrackObserver extends SingleTileEdgePoint { - - private int activated; - private ItemStack filter; - private UUID currentTrain; - - public TrackObserver() { - activated = 0; - filter = ItemStack.EMPTY; - currentTrain = null; - } - - @Override - public void tileAdded(BlockEntity tile, boolean front) { - super.tileAdded(tile, front); - FilteringBehaviour filteringBehaviour = TileEntityBehaviour.get(tile, FilteringBehaviour.TYPE); - if (filteringBehaviour != null) - setFilterAndNotify(tile.getLevel(), filteringBehaviour.getFilter()); - } - - @Override - public void tick(TrackGraph graph, boolean preTrains) { - super.tick(graph, preTrains); - if (isActivated()) - activated--; - if (!isActivated()) - currentTrain = null; - } - - public void setFilterAndNotify(Level level, ItemStack filter) { - this.filter = filter; - notifyTrains(level); - } - - private void notifyTrains(Level level) { - TrackGraph graph = Create.RAILWAYS.sided(level) - .getGraph(level, edgeLocation.getFirst()); - if (graph == null) - return; - TrackEdge edge = graph.getConnection(edgeLocation.map(graph::locateNode)); - if (edge == null) - return; - SignalPropagator.notifyTrains(graph, edge); - } - - public ItemStack getFilter() { - return filter; - } - - public UUID getCurrentTrain() { - return currentTrain; - } - - public boolean isActivated() { - return activated > 0; - } - - public void keepAlive(Train train) { - activated = 8; - currentTrain = train.id; - } - - @Override - public void read(CompoundTag nbt, boolean migration, DimensionPalette dimensions) { - super.read(nbt, migration, dimensions); - activated = nbt.getInt("Activated"); - filter = ItemStack.of(nbt.getCompound("Filter")); - if (nbt.contains("TrainId")) - currentTrain = nbt.getUUID("TrainId"); - } - - @Override - public void read(FriendlyByteBuf buffer, DimensionPalette dimensions) { - super.read(buffer, dimensions); - } - - @Override - public void write(CompoundTag nbt, DimensionPalette dimensions) { - super.write(nbt, dimensions); - nbt.putInt("Activated", activated); - nbt.put("Filter", filter.serializeNBT()); - if (currentTrain != null) - nbt.putUUID("TrainId", currentTrain); - } - - @Override - public void write(FriendlyByteBuf buffer, DimensionPalette dimensions) { - super.write(buffer, dimensions); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/observer/TrackObserverBlock.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/observer/TrackObserverBlock.java deleted file mode 100644 index 0fa1f184e..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/observer/TrackObserverBlock.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.simibubi.create.content.logistics.trains.management.edgePoint.observer; - -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; -import com.simibubi.create.foundation.block.ITE; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -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.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition.Builder; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.block.state.properties.BooleanProperty; - -public class TrackObserverBlock extends Block implements ITE, IWrenchable { - - public static final BooleanProperty POWERED = BlockStateProperties.POWERED; - - public TrackObserverBlock(Properties p_49795_) { - super(p_49795_); - registerDefaultState(defaultBlockState().setValue(POWERED, false)); - } - - @Override - protected void createBlockStateDefinition(Builder pBuilder) { - super.createBlockStateDefinition(pBuilder.add(POWERED)); - } - - @Override - public boolean isSignalSource(BlockState state) { - return true; - } - - @Override - public int getSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { - return blockState.getValue(POWERED) ? 15 : 0; - } - - @Override - public boolean canConnectRedstone(BlockState state, BlockGetter world, BlockPos pos, Direction side) { - return true; - } - - @Override - public Class getTileEntityClass() { - return TrackObserverTileEntity.class; - } - - @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.TRACK_OBSERVER.get(); - } - - @Override - public void onRemove(BlockState state, Level worldIn, BlockPos pos, BlockState newState, boolean isMoving) { - ITE.onRemove(state, worldIn, pos, newState); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/observer/TrackObserverRenderer.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/observer/TrackObserverRenderer.java deleted file mode 100644 index c9f4655f3..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/observer/TrackObserverRenderer.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.simibubi.create.content.logistics.trains.management.edgePoint.observer; - -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.content.logistics.trains.ITrackBlock; -import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBehaviour; -import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBehaviour.RenderedTrackOverlayType; -import com.simibubi.create.foundation.tileEntity.renderer.SmartTileEntityRenderer; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider.Context; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; - -public class TrackObserverRenderer extends SmartTileEntityRenderer { - - public TrackObserverRenderer(Context context) { - super(context); - } - - @Override - protected void renderSafe(TrackObserverTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - super.renderSafe(te, partialTicks, ms, buffer, light, overlay); - BlockPos pos = te.getBlockPos(); - - TrackTargetingBehaviour target = te.edgePoint; - BlockPos targetPosition = target.getGlobalPosition(); - Level level = te.getLevel(); - BlockState trackState = level.getBlockState(targetPosition); - Block block = trackState.getBlock(); - - if (!(block instanceof ITrackBlock)) - return; - - ms.pushPose(); - ms.translate(-pos.getX(), -pos.getY(), -pos.getZ()); - RenderedTrackOverlayType type = RenderedTrackOverlayType.OBSERVER; - TrackTargetingBehaviour.render(level, targetPosition, target.getTargetDirection(), target.getTargetBezier(), ms, - buffer, light, overlay, type, 1); - ms.popPose(); - - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/observer/TrackObserverTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/observer/TrackObserverTileEntity.java deleted file mode 100644 index 7b19574f4..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/observer/TrackObserverTileEntity.java +++ /dev/null @@ -1,115 +0,0 @@ -package com.simibubi.create.content.logistics.trains.management.edgePoint.observer; - -import java.util.List; - -import javax.annotation.Nullable; - -import com.jozufozu.flywheel.util.transform.TransformStack; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.content.contraptions.components.structureMovement.ITransformableTE; -import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform; -import com.simibubi.create.content.logistics.block.display.DisplayLinkBlock; -import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType; -import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBehaviour; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform; -import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.Vec3; - -public class TrackObserverTileEntity extends SmartTileEntity implements ITransformableTE { - - public TrackTargetingBehaviour edgePoint; - - private FilteringBehaviour filtering; - - public TrackObserverTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - @Override - public void addBehaviours(List behaviours) { - behaviours.add(edgePoint = new TrackTargetingBehaviour<>(this, EdgePointType.OBSERVER)); - behaviours.add(filtering = createFilter().withCallback(this::onFilterChanged)); - } - - private void onFilterChanged(ItemStack newFilter) { - if (level.isClientSide()) - return; - TrackObserver observer = getObserver(); - if (observer != null) - observer.setFilterAndNotify(level, newFilter); - } - - @Override - public void tick() { - super.tick(); - - if (level.isClientSide()) - return; - - boolean shouldBePowered = false; - TrackObserver observer = getObserver(); - if (observer != null) - shouldBePowered = observer.isActivated(); - if (isBlockPowered() == shouldBePowered) - return; - - BlockState blockState = getBlockState(); - if (blockState.hasProperty(TrackObserverBlock.POWERED)) - level.setBlock(worldPosition, blockState.setValue(TrackObserverBlock.POWERED, shouldBePowered), 3); - DisplayLinkBlock.notifyGatherers(level, worldPosition); - } - - @Nullable - public TrackObserver getObserver() { - return edgePoint.getEdgePoint(); - } - - public ItemStack getFilter() { - return filtering.getFilter(); - } - - public boolean isBlockPowered() { - return getBlockState().getOptionalValue(TrackObserverBlock.POWERED) - .orElse(false); - } - - @Override - protected AABB createRenderBoundingBox() { - return new AABB(worldPosition, edgePoint.getGlobalPosition()).inflate(2); - } - - @Override - public void transform(StructureTransform transform) { - edgePoint.transform(transform); - } - - public FilteringBehaviour createFilter() { - return new FilteringBehaviour(this, new ValueBoxTransform() { - - @Override - protected void rotate(BlockState state, PoseStack ms) { - TransformStack.cast(ms) - .rotateX(90); - } - - @Override - protected Vec3 getLocalOffset(BlockState state) { - return new Vec3(0.5, 15 / 16d, 0.5); - } - - protected float getScale() { - return super.getScale() * 1.5f; - }; - - }); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/signal/SignalEdgeGroupPacket.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/signal/SignalEdgeGroupPacket.java deleted file mode 100644 index 8918a6e77..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/signal/SignalEdgeGroupPacket.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.simibubi.create.content.logistics.trains.management.edgePoint.signal; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.function.Supplier; - -import com.google.common.collect.ImmutableList; -import com.simibubi.create.CreateClient; -import com.simibubi.create.foundation.networking.SimplePacketBase; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraftforge.network.NetworkEvent.Context; - -public class SignalEdgeGroupPacket extends SimplePacketBase { - - List ids; - List colors; - boolean add; - - public SignalEdgeGroupPacket(UUID id, EdgeGroupColor color) { - this(ImmutableList.of(id), ImmutableList.of(color), true); - } - - public SignalEdgeGroupPacket(List ids, List colors, boolean add) { - this.ids = ids; - this.colors = colors; - this.add = add; - } - - public SignalEdgeGroupPacket(FriendlyByteBuf buffer) { - ids = new ArrayList<>(); - colors = new ArrayList<>(); - add = buffer.readBoolean(); - int size = buffer.readVarInt(); - for (int i = 0; i < size; i++) - ids.add(buffer.readUUID()); - size = buffer.readVarInt(); - for (int i = 0; i < size; i++) - colors.add(EdgeGroupColor.values()[buffer.readVarInt()]); - } - - @Override - public void write(FriendlyByteBuf buffer) { - buffer.writeBoolean(add); - buffer.writeVarInt(ids.size()); - ids.forEach(buffer::writeUUID); - buffer.writeVarInt(colors.size()); - colors.forEach(c -> buffer.writeVarInt(c.ordinal())); - } - - @Override - public void handle(Supplier context) { - context.get() - .enqueueWork(() -> { - Map signalEdgeGroups = CreateClient.RAILWAYS.signalEdgeGroups; - int i = 0; - for (UUID id : ids) { - if (!add) { - signalEdgeGroups.remove(id); - continue; - } - - SignalEdgeGroup group = new SignalEdgeGroup(id); - signalEdgeGroups.put(id, group); - if (colors.size() > i) - group.color = colors.get(i); - i++; - } - }); - context.get() - .setPacketHandled(true); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/signal/SignalRenderer.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/signal/SignalRenderer.java deleted file mode 100644 index 0be8feda6..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/signal/SignalRenderer.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.simibubi.create.content.logistics.trains.management.edgePoint.signal; - -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.logistics.trains.ITrackBlock; -import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBehaviour; -import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBehaviour.RenderedTrackOverlayType; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalTileEntity.OverlayState; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalTileEntity.SignalState; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; - -public class SignalRenderer extends SafeTileEntityRenderer { - - public SignalRenderer(BlockEntityRendererProvider.Context context) {} - - @Override - protected void renderSafe(SignalTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - BlockState blockState = te.getBlockState(); - SignalState signalState = te.getState(); - OverlayState overlayState = te.getOverlay(); - - float renderTime = AnimationTickHolder.getRenderTime(te.getLevel()); - if (signalState.isRedLight(renderTime)) - CachedBufferer.partial(AllBlockPartials.SIGNAL_ON, blockState) - .renderInto(ms, buffer.getBuffer(RenderType.solid())); - else - CachedBufferer.partial(AllBlockPartials.SIGNAL_OFF, blockState) - .light(light) - .renderInto(ms, buffer.getBuffer(RenderType.solid())); - - BlockPos pos = te.getBlockPos(); - TrackTargetingBehaviour target = te.edgePoint; - BlockPos targetPosition = target.getGlobalPosition(); - Level level = te.getLevel(); - BlockState trackState = level.getBlockState(targetPosition); - Block block = trackState.getBlock(); - - if (!(block instanceof ITrackBlock)) - return; - if (overlayState == OverlayState.SKIP) - return; - - ms.pushPose(); - ms.translate(-pos.getX(), -pos.getY(), -pos.getZ()); - RenderedTrackOverlayType type = - overlayState == OverlayState.DUAL ? RenderedTrackOverlayType.DUAL_SIGNAL : RenderedTrackOverlayType.SIGNAL; - TrackTargetingBehaviour.render(level, targetPosition, target.getTargetDirection(), target.getTargetBezier(), ms, - buffer, light, overlay, type, 1); - ms.popPose(); - - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/signal/SignalTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/signal/SignalTileEntity.java deleted file mode 100644 index 68bccc274..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/signal/SignalTileEntity.java +++ /dev/null @@ -1,167 +0,0 @@ -package com.simibubi.create.content.logistics.trains.management.edgePoint.signal; - -import java.util.List; - -import javax.annotation.Nullable; - -import com.simibubi.create.content.contraptions.components.structureMovement.ITransformableTE; -import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform; -import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType; -import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBehaviour; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalBlock.SignalType; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.utility.NBTHelper; - -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.AABB; - -public class SignalTileEntity extends SmartTileEntity implements ITransformableTE { - - public static enum OverlayState { - RENDER, SKIP, DUAL - } - - public static enum SignalState { - RED, YELLOW, GREEN, INVALID; - - public boolean isRedLight(float renderTime) { - return this == RED || this == INVALID && renderTime % 40 < 3; - } - - public boolean isYellowLight(float renderTime) { - return this == YELLOW; - } - - public boolean isGreenLight(float renderTime) { - return this == GREEN; - } - } - - public TrackTargetingBehaviour edgePoint; - - private SignalState state; - private OverlayState overlay; - private int switchToRedAfterTrainEntered; - private boolean lastReportedPower; - - public SignalTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - this.state = SignalState.INVALID; - this.overlay = OverlayState.SKIP; - this.lastReportedPower = false; - } - - @Override - protected void write(CompoundTag tag, boolean clientPacket) { - super.write(tag, clientPacket); - NBTHelper.writeEnum(tag, "State", state); - NBTHelper.writeEnum(tag, "Overlay", overlay); - tag.putBoolean("Power", lastReportedPower); - } - - @Override - protected void read(CompoundTag tag, boolean clientPacket) { - super.read(tag, clientPacket); - state = NBTHelper.readEnum(tag, "State", SignalState.class); - overlay = NBTHelper.readEnum(tag, "Overlay", OverlayState.class); - lastReportedPower = tag.getBoolean("Power"); - invalidateRenderBoundingBox(); - } - - @Nullable - public SignalBoundary getSignal() { - return edgePoint.getEdgePoint(); - } - - public boolean isPowered() { - return state == SignalState.RED; - } - - @Override - public void addBehaviours(List behaviours) { - edgePoint = new TrackTargetingBehaviour<>(this, EdgePointType.SIGNAL); - behaviours.add(edgePoint); - } - - @Override - public void tick() { - super.tick(); - if (level.isClientSide) - return; - - SignalBoundary boundary = getSignal(); - if (boundary == null) { - enterState(SignalState.INVALID); - setOverlay(OverlayState.RENDER); - return; - } - - BlockState blockState = getBlockState(); - - blockState.getOptionalValue(SignalBlock.POWERED).ifPresent(powered -> { - if (lastReportedPower == powered) - return; - lastReportedPower = powered; - boundary.updateTilePower(this); - notifyUpdate(); - }); - - blockState.getOptionalValue(SignalBlock.TYPE) - .ifPresent(stateType -> { - SignalType targetType = boundary.getTypeFor(worldPosition); - if (stateType != targetType) { - level.setBlock(worldPosition, blockState.setValue(SignalBlock.TYPE, targetType), 3); - refreshBlockState(); - } - }); - - enterState(boundary.getStateFor(worldPosition)); - setOverlay(boundary.getOverlayFor(worldPosition)); - } - - public boolean getReportedPower() { - return lastReportedPower; - } - - public SignalState getState() { - return state; - } - - public OverlayState getOverlay() { - return overlay; - } - - public void setOverlay(OverlayState state) { - if (this.overlay == state) - return; - this.overlay = state; - notifyUpdate(); - } - - public void enterState(SignalState state) { - if (switchToRedAfterTrainEntered > 0) - switchToRedAfterTrainEntered--; - if (this.state == state) - return; - if (state == SignalState.RED && switchToRedAfterTrainEntered > 0) - return; - this.state = state; - switchToRedAfterTrainEntered = state == SignalState.GREEN || state == SignalState.YELLOW ? 15 : 0; - notifyUpdate(); - } - - @Override - protected AABB createRenderBoundingBox() { - return new AABB(worldPosition, edgePoint.getGlobalPosition()).inflate(2); - } - - @Override - public void transform(StructureTransform transform) { - edgePoint.transform(transform); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/signal/SingleTileEdgePoint.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/signal/SingleTileEdgePoint.java deleted file mode 100644 index f18b78390..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/signal/SingleTileEdgePoint.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.simibubi.create.content.logistics.trains.management.edgePoint.signal; - -import com.simibubi.create.content.logistics.trains.DimensionPalette; - -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtUtils; -import net.minecraft.resources.ResourceKey; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.block.entity.BlockEntity; - -public abstract class SingleTileEdgePoint extends TrackEdgePoint { - - public ResourceKey tileDimension; - public BlockPos tilePos; - - public BlockPos getTilePos() { - return tilePos; - } - - public ResourceKey getTileDimension() { - return tileDimension; - } - - @Override - public void tileAdded(BlockEntity tile, boolean front) { - this.tilePos = tile.getBlockPos(); - this.tileDimension = tile.getLevel() - .dimension(); - } - - @Override - public void tileRemoved(BlockPos tilePos, boolean front) { - removeFromAllGraphs(); - } - - @Override - public void invalidate(LevelAccessor level) { - invalidateAt(level, tilePos); - } - - @Override - public boolean canMerge() { - return false; - } - - @Override - public void read(CompoundTag nbt, boolean migration, DimensionPalette dimensions) { - super.read(nbt, migration, dimensions); - if (migration) - return; - tilePos = NbtUtils.readBlockPos(nbt.getCompound("TilePos")); - tileDimension = dimensions.decode(nbt.contains("TileDimension") ? nbt.getInt("TileDimension") : -1); - } - - @Override - public void write(CompoundTag nbt, DimensionPalette dimensions) { - super.write(nbt, dimensions); - nbt.put("TilePos", NbtUtils.writeBlockPos(tilePos)); - nbt.putInt("TileDimension", dimensions.encode(tileDimension)); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/signal/TrackEdgePoint.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/signal/TrackEdgePoint.java deleted file mode 100644 index acfaa54eb..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/signal/TrackEdgePoint.java +++ /dev/null @@ -1,126 +0,0 @@ -package com.simibubi.create.content.logistics.trains.management.edgePoint.signal; - -import java.util.UUID; - -import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.DimensionPalette; -import com.simibubi.create.content.logistics.trains.TrackEdge; -import com.simibubi.create.content.logistics.trains.TrackGraph; -import com.simibubi.create.content.logistics.trains.TrackNode; -import com.simibubi.create.content.logistics.trains.TrackNodeLocation; -import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType; -import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBehaviour; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.utility.Couple; - -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.Tag; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.block.entity.BlockEntity; - -public abstract class TrackEdgePoint { - - public UUID id; - public Couple edgeLocation; - public double position; - private EdgePointType type; - - public void setId(UUID id) { - this.id = id; - } - - public UUID getId() { - return id; - } - - public void setType(EdgePointType type) { - this.type = type; - } - - public EdgePointType getType() { - return type; - } - - public abstract boolean canMerge(); - - public boolean canCoexistWith(EdgePointType otherType, boolean front) { - return false; - } - - public abstract void invalidate(LevelAccessor level); - - protected void invalidateAt(LevelAccessor level, BlockPos tilePos) { - TrackTargetingBehaviour behaviour = TileEntityBehaviour.get(level, tilePos, TrackTargetingBehaviour.TYPE); - if (behaviour == null) - return; - CompoundTag migrationData = new CompoundTag(); - DimensionPalette dimensions = new DimensionPalette(); - write(migrationData, dimensions); - dimensions.write(migrationData); - behaviour.invalidateEdgePoint(migrationData); - } - - public abstract void tileAdded(BlockEntity tile, boolean front); - - public abstract void tileRemoved(BlockPos tilePos, boolean front); - - public void onRemoved(TrackGraph graph) {} - - public void setLocation(Couple nodes, double position) { - this.edgeLocation = nodes; - this.position = position; - } - - public double getLocationOn(TrackEdge edge) { - return isPrimary(edge.node1) ? edge.getLength() - position : position; - } - - public boolean canNavigateVia(TrackNode side) { - return true; - } - - public boolean isPrimary(TrackNode node1) { - return edgeLocation.getSecond() - .equals(node1.getLocation()); - } - - public void read(CompoundTag nbt, boolean migration, DimensionPalette dimensions) { - if (migration) - return; - - id = nbt.getUUID("Id"); - position = nbt.getDouble("Position"); - edgeLocation = Couple.deserializeEach(nbt.getList("Edge", Tag.TAG_COMPOUND), - tag -> TrackNodeLocation.read(tag, dimensions)); - } - - public void read(FriendlyByteBuf buffer, DimensionPalette dimensions) { - id = buffer.readUUID(); - edgeLocation = Couple.create(() -> TrackNodeLocation.receive(buffer, dimensions)); - position = buffer.readDouble(); - } - - public void write(CompoundTag nbt, DimensionPalette dimensions) { - nbt.putUUID("Id", id); - nbt.putDouble("Position", position); - nbt.put("Edge", edgeLocation.serializeEach(loc -> loc.write(dimensions))); - } - - public void write(FriendlyByteBuf buffer, DimensionPalette dimensions) { - buffer.writeResourceLocation(type.getId()); - buffer.writeUUID(id); - edgeLocation.forEach(loc -> loc.send(buffer, dimensions)); - buffer.writeDouble(position); - } - - public void tick(TrackGraph graph, boolean preTrains) {} - - protected void removeFromAllGraphs() { - for (TrackGraph trackGraph : Create.RAILWAYS.trackNetworks.values()) - if (trackGraph.removePoint(getType(), id) != null) - return; - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/AbstractStationScreen.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/AbstractStationScreen.java deleted file mode 100644 index ed32075ae..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/AbstractStationScreen.java +++ /dev/null @@ -1,112 +0,0 @@ -package com.simibubi.create.content.logistics.trains.management.edgePoint.station; - -import java.lang.ref.WeakReference; -import java.util.List; - -import com.jozufozu.flywheel.core.PartialModel; -import com.jozufozu.flywheel.util.transform.TransformStack; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.CreateClient; -import com.simibubi.create.content.logistics.trains.entity.Carriage; -import com.simibubi.create.content.logistics.trains.entity.Train; -import com.simibubi.create.content.logistics.trains.entity.TrainIconType; -import com.simibubi.create.foundation.gui.AbstractSimiScreen; -import com.simibubi.create.foundation.gui.AllGuiTextures; -import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.gui.element.GuiGameElement; -import com.simibubi.create.foundation.gui.widget.IconButton; - -import net.minecraft.world.level.block.state.properties.BlockStateProperties; - -public abstract class AbstractStationScreen extends AbstractSimiScreen { - - protected AllGuiTextures background; - protected StationTileEntity te; - protected GlobalStation station; - - protected WeakReference displayedTrain; - - private IconButton confirmButton; - - public AbstractStationScreen(StationTileEntity te, GlobalStation station) { - super(te.getBlockState() - .getBlock() - .getName()); - this.te = te; - this.station = station; - displayedTrain = new WeakReference<>(null); - } - - @Override - protected void init() { - setWindowSize(background.width, background.height); - super.init(); - clearWidgets(); - - int x = guiLeft; - int y = guiTop; - - confirmButton = new IconButton(x + background.width - 33, y + background.height - 24, AllIcons.I_CONFIRM); - confirmButton.withCallback(this::onClose); - addRenderableWidget(confirmButton); - } - - public int getTrainIconWidth(Train train) { - TrainIconType icon = train.icon; - List carriages = train.carriages; - - int w = icon.getIconWidth(TrainIconType.ENGINE); - if (carriages.size() == 1) - return w; - - for (int i = 1; i < carriages.size(); i++) { - if (i == carriages.size() - 1 && train.doubleEnded) { - w += icon.getIconWidth(TrainIconType.FLIPPED_ENGINE) + 1; - break; - } - Carriage carriage = carriages.get(i); - w += icon.getIconWidth(carriage.bogeySpacing) + 1; - } - - return w; - } - - @Override - protected void renderWindow(PoseStack ms, int mouseX, int mouseY, float partialTicks) { - int x = guiLeft; - int y = guiTop; - - background.render(ms, x, y, this); - - ms.pushPose(); - TransformStack msr = TransformStack.cast(ms); - msr.pushPose() - .translate(x + background.width + 4, y + background.height + 4, 100) - .scale(40) - .rotateX(-22) - .rotateY(63); - GuiGameElement.of(te.getBlockState() - .setValue(BlockStateProperties.WATERLOGGED, false)) - .render(ms); - - if (te.resolveFlagAngle()) { - msr.translate(1 / 16f, -19 / 16f, -12 / 16f); - StationRenderer.transformFlag(msr, te, partialTicks, 180, false); - GuiGameElement.of(getFlag(partialTicks)) - .render(ms); - } - - ms.popPose(); - } - - protected abstract PartialModel getFlag(float partialTicks); - - protected Train getImminent() { - return te.imminentTrain == null ? null : CreateClient.RAILWAYS.trains.get(te.imminentTrain); - } - - protected boolean trainPresent() { - return te.trainPresent; - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/AssemblyScreen.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/AssemblyScreen.java deleted file mode 100644 index c59a781a2..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/AssemblyScreen.java +++ /dev/null @@ -1,170 +0,0 @@ -package com.simibubi.create.content.logistics.trains.management.edgePoint.station; - -import java.lang.ref.WeakReference; -import java.util.List; - -import com.jozufozu.flywheel.core.PartialModel; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException; -import com.simibubi.create.content.logistics.trains.entity.Carriage; -import com.simibubi.create.content.logistics.trains.entity.Train; -import com.simibubi.create.content.logistics.trains.entity.TrainIconType; -import com.simibubi.create.foundation.gui.AllGuiTextures; -import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.gui.widget.IconButton; -import com.simibubi.create.foundation.gui.widget.ScrollInput; -import com.simibubi.create.foundation.networking.AllPackets; -import com.simibubi.create.foundation.utility.Lang; - -import net.minecraft.client.gui.components.Renderable; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.resources.ResourceLocation; - -public class AssemblyScreen extends AbstractStationScreen { - - private IconButton quitAssembly; - private IconButton toggleAssemblyButton; - private List iconTypes; - private ScrollInput iconTypeScroll; - - public AssemblyScreen(StationTileEntity te, GlobalStation station) { - super(te, station); - background = AllGuiTextures.STATION_ASSEMBLING; - } - - @Override - protected void init() { - super.init(); - int x = guiLeft; - int y = guiTop; - int by = y + background.height - 24; - - Renderable widget = renderables.get(0); - if (widget instanceof IconButton ib) { - ib.setIcon(AllIcons.I_PRIORITY_VERY_LOW); - ib.setToolTip(Lang.translateDirect("station.close")); - } - - iconTypes = TrainIconType.REGISTRY.keySet() - .stream() - .toList(); - iconTypeScroll = new ScrollInput(x + 4, y + 17, 184, 14).titled(Lang.translateDirect("station.icon_type")); - iconTypeScroll.withRange(0, iconTypes.size()); - iconTypeScroll.withStepFunction(ctx -> -iconTypeScroll.standardStep() - .apply(ctx)); - iconTypeScroll.calling(s -> { - Train train = displayedTrain.get(); - if (train != null) - train.icon = TrainIconType.byId(iconTypes.get(s)); - }); - iconTypeScroll.active = iconTypeScroll.visible = false; - addRenderableWidget(iconTypeScroll); - - toggleAssemblyButton = new WideIconButton(x + 94, by, AllGuiTextures.I_ASSEMBLE_TRAIN); - toggleAssemblyButton.active = false; - toggleAssemblyButton.setToolTip(Lang.translateDirect("station.assemble_train")); - toggleAssemblyButton.withCallback(() -> { - AllPackets.channel.sendToServer(StationEditPacket.tryAssemble(te.getBlockPos())); - }); - - quitAssembly = new IconButton(x + 73, by, AllIcons.I_DISABLE); - quitAssembly.active = true; - quitAssembly.setToolTip(Lang.translateDirect("station.cancel")); - quitAssembly.withCallback(() -> { - AllPackets.channel.sendToServer(StationEditPacket.configure(te.getBlockPos(), false, station.name)); - minecraft.setScreen(new StationScreen(te, station)); - }); - - addRenderableWidget(toggleAssemblyButton); - addRenderableWidget(quitAssembly); - - tickTrainDisplay(); - } - - @Override - public void tick() { - super.tick(); - tickTrainDisplay(); - Train train = displayedTrain.get(); - toggleAssemblyButton.active = te.bogeyCount > 0 || train != null; - - if (train != null) { - AllPackets.channel.sendToServer(StationEditPacket.configure(te.getBlockPos(), false, station.name)); - minecraft.setScreen(new StationScreen(te, station)); - for (Carriage carriage : train.carriages) - carriage.updateConductors(); - } - } - - private void tickTrainDisplay() { - if (getImminent() == null) { - displayedTrain = new WeakReference<>(null); - quitAssembly.active = true; - iconTypeScroll.active = iconTypeScroll.visible = false; - toggleAssemblyButton.setToolTip(Lang.translateDirect("station.assemble_train")); - toggleAssemblyButton.setIcon(AllGuiTextures.I_ASSEMBLE_TRAIN); - toggleAssemblyButton.withCallback(() -> { - AllPackets.channel.sendToServer(StationEditPacket.tryAssemble(te.getBlockPos())); - }); - } else { - AllPackets.channel.sendToServer(StationEditPacket.configure(te.getBlockPos(), false, station.name)); - minecraft.setScreen(new StationScreen(te, station)); - } - } - - @Override - protected void renderWindow(PoseStack ms, int mouseX, int mouseY, float partialTicks) { - super.renderWindow(ms, mouseX, mouseY, partialTicks); - int x = guiLeft; - int y = guiTop; - - MutableComponent header = Lang.translateDirect("station.assembly_title"); - font.draw(ms, header, x + background.width / 2 - font.width(header) / 2, y + 4, 0x0E2233); - - AssemblyException lastAssemblyException = te.lastException; - if (lastAssemblyException != null) { - MutableComponent text = Lang.translateDirect("station.failed"); - font.draw(ms, text, x + 97 - font.width(text) / 2, y + 47, 0x775B5B); - int offset = 0; - if (te.failedCarriageIndex != -1) { - font.draw(ms, Lang.translateDirect("station.carriage_number", te.failedCarriageIndex), x + 30, y + 67, - 0x7A7A7A); - offset += 10; - } - font.drawWordWrap(lastAssemblyException.component, x + 30, y + 67 + offset, 134, 0x775B5B); - offset += font.split(lastAssemblyException.component, 134) - .size() * 9 + 5; - font.drawWordWrap(Lang.translateDirect("station.retry"), x + 30, y + 67 + offset, 134, 0x7A7A7A); - return; - } - - int bogeyCount = te.bogeyCount; - - MutableComponent text = Lang.translateDirect( - bogeyCount == 0 ? "station.no_bogeys" : bogeyCount == 1 ? "station.one_bogey" : "station.more_bogeys", - bogeyCount); - font.draw(ms, text, x + 97 - font.width(text) / 2, y + 47, 0x7A7A7A); - - font.drawWordWrap(Lang.translateDirect("station.how_to"), x + 28, y + 62, 134, 0x7A7A7A); - font.drawWordWrap(Lang.translateDirect("station.how_to_1"), x + 28, y + 94, 134, 0x7A7A7A); - font.drawWordWrap(Lang.translateDirect("station.how_to_2"), x + 28, y + 117, 138, 0x7A7A7A); - } - - @Override - public void removed() { - super.removed(); - Train train = displayedTrain.get(); - if (train != null) { - ResourceLocation iconId = iconTypes.get(iconTypeScroll.getState()); - train.icon = TrainIconType.byId(iconId); - AllPackets.channel.sendToServer(new TrainEditPacket(train.id, "", iconId)); - } - } - - @Override - protected PartialModel getFlag(float partialTicks) { - return AllBlockPartials.STATION_ASSEMBLE; - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationEditPacket.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationEditPacket.java deleted file mode 100644 index e1ec084c7..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationEditPacket.java +++ /dev/null @@ -1,211 +0,0 @@ -package com.simibubi.create.content.logistics.trains.management.edgePoint.station; - -import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.GraphLocation; -import com.simibubi.create.content.logistics.trains.entity.Train; -import com.simibubi.create.foundation.networking.TileEntityConfigurationPacket; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.core.BlockPos; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; - -public class StationEditPacket extends TileEntityConfigurationPacket { - - boolean dropSchedule; - boolean assemblyMode; - Boolean tryAssemble; - String name; - - public static StationEditPacket dropSchedule(BlockPos pos) { - StationEditPacket packet = new StationEditPacket(pos); - packet.dropSchedule = true; - return packet; - } - - public static StationEditPacket tryAssemble(BlockPos pos) { - StationEditPacket packet = new StationEditPacket(pos); - packet.tryAssemble = true; - return packet; - } - - public static StationEditPacket tryDisassemble(BlockPos pos) { - StationEditPacket packet = new StationEditPacket(pos); - packet.tryAssemble = false; - return packet; - } - - public static StationEditPacket configure(BlockPos pos, boolean assemble, String name) { - StationEditPacket packet = new StationEditPacket(pos); - packet.assemblyMode = assemble; - packet.tryAssemble = null; - packet.name = name; - return packet; - } - - public StationEditPacket(FriendlyByteBuf buffer) { - super(buffer); - } - - public StationEditPacket(BlockPos pos) { - super(pos); - } - - @Override - protected void writeSettings(FriendlyByteBuf buffer) { - buffer.writeBoolean(dropSchedule); - if (dropSchedule) - return; - buffer.writeBoolean(tryAssemble != null); - if (tryAssemble != null) { - buffer.writeBoolean(tryAssemble); - return; - } - buffer.writeBoolean(assemblyMode); - buffer.writeUtf(name); - } - - @Override - protected void readSettings(FriendlyByteBuf buffer) { - if (buffer.readBoolean()) { - dropSchedule = true; - return; - } - name = ""; - if (buffer.readBoolean()) { - tryAssemble = buffer.readBoolean(); - return; - } - assemblyMode = buffer.readBoolean(); - name = buffer.readUtf(256); - } - - @Override - protected void applySettings(ServerPlayer player, StationTileEntity te) { - Level level = te.getLevel(); - BlockPos blockPos = te.getBlockPos(); - BlockState blockState = level.getBlockState(blockPos); - - if (dropSchedule) { - scheduleDropRequested(player, te); - return; - } - - if (!name.isBlank()) { - GlobalStation station = te.getStation(); - GraphLocation graphLocation = te.edgePoint.determineGraphLocation(); - if (station != null && graphLocation != null) { - station.name = name; - Create.RAILWAYS.sync.pointAdded(graphLocation.graph, station); - Create.RAILWAYS.markTracksDirty(); - } - } - - if (!(blockState.getBlock() instanceof StationBlock)) - return; - - Boolean isAssemblyMode = blockState.getValue(StationBlock.ASSEMBLING); - boolean assemblyComplete = false; - - if (tryAssemble != null) { - if (!isAssemblyMode) - return; - if (tryAssemble) { - te.assemble(player.getUUID()); - assemblyComplete = te.getStation() != null && te.getStation() - .getPresentTrain() != null; - } else { - if (disassembleAndEnterMode(player, te)) - te.refreshAssemblyInfo(); - } - if (!assemblyComplete) - return; - } - if (isAssemblyMode == assemblyMode) - return; - - BlockState newState = blockState.cycle(StationBlock.ASSEMBLING); - Boolean nowAssembling = newState.getValue(StationBlock.ASSEMBLING); - - if (nowAssembling) { - if (!disassembleAndEnterMode(player, te)) - return; - } else { - te.cancelAssembly(); - } - - level.setBlock(blockPos, newState, 3); - te.refreshBlockState(); - - if (nowAssembling) - te.refreshAssemblyInfo(); - - GlobalStation station = te.getStation(); - GraphLocation graphLocation = te.edgePoint.determineGraphLocation(); - if (station != null && graphLocation != null) { - station.assembling = nowAssembling; - Create.RAILWAYS.sync.pointAdded(graphLocation.graph, station); - Create.RAILWAYS.markTracksDirty(); - - if (nowAssembling) - for (Train train : Create.RAILWAYS.sided(level).trains.values()) { - if (train.navigation.destination != station) - continue; - GlobalStation preferredDestination = train.runtime.startCurrentInstruction(); - if (preferredDestination != null) - train.navigation.startNavigation(preferredDestination, Double.MAX_VALUE, false); - else - train.navigation.startNavigation(station, Double.MAX_VALUE, false); - } - } - } - - private void scheduleDropRequested(ServerPlayer sender, StationTileEntity te) { - GlobalStation station = te.getStation(); - if (station == null) - return; - Train train = station.getPresentTrain(); - if (train == null) - return; - ItemStack schedule = train.runtime.returnSchedule(); - dropSchedule(sender, te, schedule); - } - - private boolean disassembleAndEnterMode(ServerPlayer sender, StationTileEntity te) { - GlobalStation station = te.getStation(); - if (station != null) { - Train train = station.getPresentTrain(); - BlockPos trackPosition = te.edgePoint.getGlobalPosition(); - ItemStack schedule = train == null ? ItemStack.EMPTY : train.runtime.returnSchedule(); - if (train != null && !train.disassemble(te.getAssemblyDirection(), trackPosition.above())) - return false; - dropSchedule(sender, te, schedule); - } - return te.tryEnterAssemblyMode(); - } - - private void dropSchedule(ServerPlayer sender, StationTileEntity te, ItemStack schedule) { - if (schedule.isEmpty()) - return; - if (sender.getMainHandItem() - .isEmpty()) { - sender.getInventory() - .placeItemBackInInventory(schedule); - return; - } - Vec3 v = VecHelper.getCenterOf(te.getBlockPos()); - ItemEntity itemEntity = new ItemEntity(te.getLevel(), v.x, v.y, v.z, schedule); - itemEntity.setDeltaMovement(Vec3.ZERO); - te.getLevel() - .addFreshEntity(itemEntity); - } - - @Override - protected void applySettings(StationTileEntity te) {} - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationMapData.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationMapData.java deleted file mode 100644 index a440b8135..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationMapData.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.simibubi.create.content.logistics.trains.management.edgePoint.station; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.LevelAccessor; - -public interface StationMapData { - - boolean toggleStation(LevelAccessor level, BlockPos pos, StationTileEntity stationTileEntity); - - void addStationMarker(StationMarker marker); - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationRenderer.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationRenderer.java deleted file mode 100644 index e71fdf1ed..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationRenderer.java +++ /dev/null @@ -1,152 +0,0 @@ -package com.simibubi.create.content.logistics.trains.management.edgePoint.station; - -import com.jozufozu.flywheel.core.PartialModel; -import com.jozufozu.flywheel.util.transform.Transform; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.logistics.block.depot.DepotRenderer; -import com.simibubi.create.content.logistics.trains.ITrackBlock; -import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBehaviour; -import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBehaviour.RenderedTrackOverlayType; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; - -import net.minecraft.client.renderer.LevelRenderer; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Direction; -import net.minecraft.util.Mth; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; - -public class StationRenderer extends SafeTileEntityRenderer { - - public StationRenderer(BlockEntityRendererProvider.Context context) {} - - @Override - protected void renderSafe(StationTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, - int light, int overlay) { - - BlockPos pos = te.getBlockPos(); - TrackTargetingBehaviour target = te.edgePoint; - BlockPos targetPosition = target.getGlobalPosition(); - Level level = te.getLevel(); - - DepotRenderer.renderItemsOf(te, partialTicks, ms, buffer, light, overlay, te.depotBehaviour); - - BlockState trackState = level.getBlockState(targetPosition); - Block block = trackState.getBlock(); - if (!(block instanceof ITrackBlock)) - return; - - GlobalStation station = te.getStation(); - boolean isAssembling = te.getBlockState() - .getValue(StationBlock.ASSEMBLING); - - if (!isAssembling || (station == null || station.getPresentTrain() != null) && !te.isVirtual()) { - renderFlag( - te.flag.getValue(partialTicks) > 0.75f ? AllBlockPartials.STATION_ON : AllBlockPartials.STATION_OFF, te, - partialTicks, ms, buffer, light, overlay); - ms.pushPose(); - ms.translate(-pos.getX(), -pos.getY(), -pos.getZ()); - TrackTargetingBehaviour.render(level, targetPosition, target.getTargetDirection(), target.getTargetBezier(), - ms, buffer, light, overlay, RenderedTrackOverlayType.STATION, 1); - ms.popPose(); - return; - } - - renderFlag(AllBlockPartials.STATION_ASSEMBLE, te, partialTicks, ms, buffer, light, overlay); - - ITrackBlock track = (ITrackBlock) block; - Direction direction = te.assemblyDirection; - - if (te.isVirtual() && te.bogeyLocations == null) - te.refreshAssemblyInfo(); - - if (direction == null || te.assemblyLength == 0 || te.bogeyLocations == null) - return; - - ms.pushPose(); - BlockPos offset = targetPosition.subtract(pos); - ms.translate(offset.getX(), offset.getY(), offset.getZ()); - - MutableBlockPos currentPos = targetPosition.mutable(); - - PartialModel assemblyOverlay = track.prepareAssemblyOverlay(level, targetPosition, trackState, direction, ms); - int colorWhenValid = 0x96B5FF; - int colorWhenCarriage = 0xCAFF96; - VertexConsumer vb = buffer.getBuffer(RenderType.cutoutMipped()); - - currentPos.move(direction, 1); - ms.translate(0, 0, 1); - - for (int i = 0; i < te.assemblyLength; i++) { - int valid = te.isValidBogeyOffset(i) ? colorWhenValid : -1; - - for (int j : te.bogeyLocations) - if (i == j) { - valid = colorWhenCarriage; - break; - } - - if (valid != -1) { - int lightColor = LevelRenderer.getLightColor(level, currentPos); - SuperByteBuffer sbb = CachedBufferer.partial(assemblyOverlay, trackState); - sbb.color(valid); - sbb.light(lightColor); - sbb.renderInto(ms, vb); - } - ms.translate(0, 0, 1); - currentPos.move(direction); - } - - ms.popPose(); - } - - public static void renderFlag(PartialModel flag, StationTileEntity te, float partialTicks, PoseStack ms, - MultiBufferSource buffer, int light, int overlay) { - if (!te.resolveFlagAngle()) - return; - SuperByteBuffer flagBB = CachedBufferer.partial(flag, te.getBlockState()); - transformFlag(flagBB, te, partialTicks, te.flagYRot, te.flagFlipped); - flagBB.translate(0.5f / 16, 0, 0) - .rotateY(te.flagFlipped ? 0 : 180) - .translate(-0.5f / 16, 0, 0) - .light(light) - .renderInto(ms, buffer.getBuffer(RenderType.cutoutMipped())); - } - - public static void transformFlag(Transform flag, StationTileEntity te, float partialTicks, int yRot, - boolean flipped) { - float value = te.flag.getValue(partialTicks); - float progress = (float) (Math.pow(Math.min(value * 5, 1), 2)); - if (te.flag.getChaseTarget() > 0 && !te.flag.settled() && progress == 1) { - float wiggleProgress = (value - .2f) / .8f; - progress += (Math.sin(wiggleProgress * (2 * Mth.PI) * 4) / 8f) / Math.max(1, 8f * wiggleProgress); - } - - float nudge = 1 / 512f; - flag.centre() - .rotateY(yRot) - .translate(nudge, 9.5f / 16f, flipped ? 14f / 16f - nudge : 2f / 16f + nudge) - .unCentre() - .rotateX((flipped ? 1 : -1) * (progress * 90 + 270)); - } - - @Override - public boolean shouldRenderOffScreen(StationTileEntity pBlockEntity) { - return true; - } - - @Override - public int getViewDistance() { - return 96 * 2; - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationTileEntity.java deleted file mode 100644 index 9fdb9a96b..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationTileEntity.java +++ /dev/null @@ -1,768 +0,0 @@ -package com.simibubi.create.content.logistics.trains.management.edgePoint.station; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Objects; -import java.util.UUID; - -import javax.annotation.Nullable; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllItems; -import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.Create; -import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException; -import com.simibubi.create.content.contraptions.components.structureMovement.ITransformableTE; -import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform; -import com.simibubi.create.content.logistics.block.depot.DepotBehaviour; -import com.simibubi.create.content.logistics.block.display.DisplayLinkBlock; -import com.simibubi.create.content.logistics.trains.IBogeyBlock; -import com.simibubi.create.content.logistics.trains.ITrackBlock; -import com.simibubi.create.content.logistics.trains.TrackEdge; -import com.simibubi.create.content.logistics.trains.TrackGraph; -import com.simibubi.create.content.logistics.trains.TrackNode; -import com.simibubi.create.content.logistics.trains.TrackNodeLocation; -import com.simibubi.create.content.logistics.trains.TrackNodeLocation.DiscoveredLocation; -import com.simibubi.create.content.logistics.trains.entity.Carriage; -import com.simibubi.create.content.logistics.trains.entity.CarriageBogey; -import com.simibubi.create.content.logistics.trains.entity.CarriageContraption; -import com.simibubi.create.content.logistics.trains.entity.Train; -import com.simibubi.create.content.logistics.trains.entity.TrainPacket; -import com.simibubi.create.content.logistics.trains.entity.TravellingPoint; -import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType; -import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBehaviour; -import com.simibubi.create.content.logistics.trains.management.schedule.Schedule; -import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleItem; -import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.block.ProperWaterloggedBlock; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.networking.AllPackets; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.WorldAttached; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; -import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.BlockPos.MutableBlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.core.Direction.AxisDirection; -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.sounds.SoundSource; -import net.minecraft.util.Mth; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.structure.BoundingBox; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.network.PacketDistributor; - -public class StationTileEntity extends SmartTileEntity implements ITransformableTE { - - public TrackTargetingBehaviour edgePoint; - public LerpedFloat flag; - - protected int failedCarriageIndex; - protected AssemblyException lastException; - protected DepotBehaviour depotBehaviour; - - // for display - UUID imminentTrain; - boolean trainPresent; - boolean trainBackwards; - boolean trainCanDisassemble; - boolean trainHasSchedule; - boolean trainHasAutoSchedule; - - int flagYRot = -1; - boolean flagFlipped; - - public Component lastDisassembledTrainName; - - public StationTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - setLazyTickRate(20); - lastException = null; - failedCarriageIndex = -1; - flag = LerpedFloat.linear() - .startWithValue(0); - } - - @Override - public void addBehaviours(List behaviours) { - behaviours.add(edgePoint = new TrackTargetingBehaviour<>(this, EdgePointType.STATION)); - behaviours.add(depotBehaviour = new DepotBehaviour(this).onlyAccepts(AllItems.SCHEDULE::isIn) - .withCallback(s -> applyAutoSchedule())); - depotBehaviour.addSubBehaviours(behaviours); - registerAwardables(behaviours, AllAdvancements.CONTRAPTION_ACTORS, AllAdvancements.TRAIN, - AllAdvancements.LONG_TRAIN, AllAdvancements.CONDUCTOR); - } - - @Override - protected void read(CompoundTag tag, boolean clientPacket) { - lastException = AssemblyException.read(tag); - failedCarriageIndex = tag.getInt("FailedCarriageIndex"); - super.read(tag, clientPacket); - invalidateRenderBoundingBox(); - - if (tag.contains("ForceFlag")) - trainPresent = tag.getBoolean("ForceFlag"); - if (tag.contains("PrevTrainName")) - lastDisassembledTrainName = Component.Serializer.fromJson(tag.getString("PrevTrainName")); - - if (!clientPacket) - return; - if (!tag.contains("ImminentTrain")) { - imminentTrain = null; - trainPresent = false; - trainCanDisassemble = false; - trainBackwards = false; - return; - } - - imminentTrain = tag.getUUID("ImminentTrain"); - trainPresent = tag.contains("TrainPresent"); - trainCanDisassemble = tag.contains("TrainCanDisassemble"); - trainBackwards = tag.contains("TrainBackwards"); - trainHasSchedule = tag.contains("TrainHasSchedule"); - trainHasAutoSchedule = tag.contains("TrainHasAutoSchedule"); - } - - @Override - protected void write(CompoundTag tag, boolean clientPacket) { - AssemblyException.write(tag, lastException); - tag.putInt("FailedCarriageIndex", failedCarriageIndex); - - if (lastDisassembledTrainName != null) - tag.putString("PrevTrainName", Component.Serializer.toJson(lastDisassembledTrainName)); - - super.write(tag, clientPacket); - - if (!clientPacket) - return; - if (imminentTrain == null) - return; - - tag.putUUID("ImminentTrain", imminentTrain); - - if (trainPresent) - NBTHelper.putMarker(tag, "TrainPresent"); - if (trainCanDisassemble) - NBTHelper.putMarker(tag, "TrainCanDisassemble"); - if (trainBackwards) - NBTHelper.putMarker(tag, "TrainBackwards"); - if (trainHasSchedule) - NBTHelper.putMarker(tag, "TrainHasSchedule"); - if (trainHasAutoSchedule) - NBTHelper.putMarker(tag, "TrainHasAutoSchedule"); - } - - @Nullable - public GlobalStation getStation() { - return edgePoint.getEdgePoint(); - } - - // Train Assembly - - public static WorldAttached> assemblyAreas = new WorldAttached<>(w -> new HashMap<>()); - - Direction assemblyDirection; - int assemblyLength; - int[] bogeyLocations; - IBogeyBlock[] bogeyTypes; - int bogeyCount; - - @Override - public void lazyTick() { - if (isAssembling() && !level.isClientSide) - refreshAssemblyInfo(); - super.lazyTick(); - } - - @Override - public void tick() { - if (isAssembling() && level.isClientSide) - refreshAssemblyInfo(); - super.tick(); - - if (level.isClientSide) { - float currentTarget = flag.getChaseTarget(); - if (currentTarget == 0 || flag.settled()) { - int target = trainPresent || isAssembling() ? 1 : 0; - if (target != currentTarget) { - flag.chase(target, 0.1f, Chaser.LINEAR); - if (target == 1) - AllSoundEvents.CONTRAPTION_ASSEMBLE.playAt(level, worldPosition, 1, 2, true); - } - } - boolean settled = flag.getValue() > .15f; - flag.tickChaser(); - if (currentTarget == 0 && settled != flag.getValue() > .15f) - AllSoundEvents.CONTRAPTION_DISASSEMBLE.playAt(level, worldPosition, 0.75f, 1.5f, true); - return; - } - - GlobalStation station = getStation(); - if (station == null) - return; - - Train imminentTrain = station.getImminentTrain(); - boolean trainPresent = imminentTrain != null && imminentTrain.getCurrentStation() == station; - boolean canDisassemble = trainPresent && imminentTrain.canDisassemble(); - UUID imminentID = imminentTrain != null ? imminentTrain.id : null; - boolean trainHasSchedule = trainPresent && imminentTrain.runtime.getSchedule() != null; - boolean trainHasAutoSchedule = trainHasSchedule && imminentTrain.runtime.isAutoSchedule; - boolean newlyArrived = this.trainPresent != trainPresent; - - if (trainPresent && imminentTrain.runtime.displayLinkUpdateRequested) { - DisplayLinkBlock.notifyGatherers(level, worldPosition); - imminentTrain.runtime.displayLinkUpdateRequested = false; - } - - if (newlyArrived) - applyAutoSchedule(); - - if (newlyArrived || this.trainCanDisassemble != canDisassemble - || !Objects.equals(imminentID, this.imminentTrain) || this.trainHasSchedule != trainHasSchedule - || this.trainHasAutoSchedule != trainHasAutoSchedule) { - - this.imminentTrain = imminentID; - this.trainPresent = trainPresent; - this.trainCanDisassemble = canDisassemble; - this.trainBackwards = imminentTrain != null && imminentTrain.currentlyBackwards; - this.trainHasSchedule = trainHasSchedule; - this.trainHasAutoSchedule = trainHasAutoSchedule; - - notifyUpdate(); - } - } - - public boolean trackClicked(Player player, InteractionHand hand, ITrackBlock track, BlockState state, - BlockPos pos) { - refreshAssemblyInfo(); - BoundingBox bb = assemblyAreas.get(level) - .get(worldPosition); - if (bb == null || !bb.isInside(pos)) - return false; - - BlockPos up = new BlockPos(track.getUpNormal(level, pos, state)); - int bogeyOffset = pos.distManhattan(edgePoint.getGlobalPosition()) - 1; - if (!isValidBogeyOffset(bogeyOffset)) { - for (int i = -1; i <= 1; i++) { - BlockPos bogeyPos = pos.relative(assemblyDirection, i) - .offset(up); - BlockState blockState = level.getBlockState(bogeyPos); - if (blockState.getBlock() instanceof IBogeyBlock bogey) { - level.setBlock(bogeyPos, bogey.getRotatedBlockState(blockState, Direction.DOWN), 3); - bogey.playRotateSound(level, bogeyPos); - return true; - } - } - - return false; - } - - ItemStack handItem = player.getItemInHand(hand); - if (!player.isCreative() && !AllBlocks.RAILWAY_CASING.isIn(handItem)) { - player.displayClientMessage(Lang.translateDirect("train_assembly.requires_casing"), true); - return false; - } - - BlockPos targetPos = pos.offset(up); - if (level.getBlockState(targetPos) - .getDestroySpeed(level, targetPos) == -1) { - return false; - } - - level.destroyBlock(targetPos, true); - - BlockState bogeyAnchor = ProperWaterloggedBlock.withWater(level, track.getBogeyAnchor(level, pos, state), pos); - level.setBlock(targetPos, bogeyAnchor, 3); - player.displayClientMessage(Lang.translateDirect("train_assembly.bogey_created"), true); - SoundType soundtype = bogeyAnchor.getBlock() - .getSoundType(state, level, pos, player); - level.playSound(null, pos, soundtype.getPlaceSound(), SoundSource.BLOCKS, (soundtype.getVolume() + 1.0F) / 2.0F, - soundtype.getPitch() * 0.8F); - - if (!player.isCreative()) { - ItemStack itemInHand = player.getItemInHand(hand); - itemInHand.shrink(1); - if (itemInHand.isEmpty()) - player.setItemInHand(hand, ItemStack.EMPTY); - } - - return true; - } - - public boolean isAssembling() { - BlockState state = getBlockState(); - return state.hasProperty(StationBlock.ASSEMBLING) && state.getValue(StationBlock.ASSEMBLING); - } - - public boolean tryEnterAssemblyMode() { - if (!edgePoint.hasValidTrack()) - return false; - - BlockPos targetPosition = edgePoint.getGlobalPosition(); - BlockState trackState = edgePoint.getTrackBlockState(); - ITrackBlock track = edgePoint.getTrack(); - Vec3 trackAxis = track.getTrackAxes(level, targetPosition, trackState) - .get(0); - - boolean axisFound = false; - for (Axis axis : Iterate.axes) { - if (trackAxis.get(axis) == 0) - continue; - if (axisFound) - return false; - axisFound = true; - } - - return true; - } - - public void refreshAssemblyInfo() { - if (!edgePoint.hasValidTrack()) - return; - - if (!isVirtual()) { - GlobalStation station = getStation(); - if (station == null || station.getPresentTrain() != null) - return; - } - - int prevLength = assemblyLength; - BlockPos targetPosition = edgePoint.getGlobalPosition(); - BlockState trackState = edgePoint.getTrackBlockState(); - ITrackBlock track = edgePoint.getTrack(); - getAssemblyDirection(); - - MutableBlockPos currentPos = targetPosition.mutable(); - currentPos.move(assemblyDirection); - - BlockPos bogeyOffset = new BlockPos(track.getUpNormal(level, targetPosition, trackState)); - - int MAX_LENGTH = AllConfigs.SERVER.trains.maxAssemblyLength.get(); - int MAX_BOGEY_COUNT = AllConfigs.SERVER.trains.maxBogeyCount.get(); - - int bogeyIndex = 0; - int maxBogeyCount = MAX_BOGEY_COUNT; - if (bogeyLocations == null) - bogeyLocations = new int[maxBogeyCount]; - if (bogeyTypes == null) - bogeyTypes = new IBogeyBlock[maxBogeyCount]; - Arrays.fill(bogeyLocations, -1); - Arrays.fill(bogeyTypes, null); - - for (int i = 0; i < MAX_LENGTH; i++) { - if (i == MAX_LENGTH - 1) { - assemblyLength = i; - break; - } - if (!track.trackEquals(trackState, level.getBlockState(currentPos))) { - assemblyLength = Math.max(0, i - 1); - break; - } - - BlockState potentialBogeyState = level.getBlockState(bogeyOffset.offset(currentPos)); - if (potentialBogeyState.getBlock() instanceof IBogeyBlock bogey && bogeyIndex < bogeyLocations.length) { - bogeyTypes[bogeyIndex] = bogey; - bogeyLocations[bogeyIndex] = i; - bogeyIndex++; - } - - currentPos.move(assemblyDirection); - } - - bogeyCount = bogeyIndex; - - if (level.isClientSide) - return; - if (prevLength == assemblyLength) - return; - if (isVirtual()) - return; - - Map map = assemblyAreas.get(level); - BlockPos startPosition = targetPosition.relative(assemblyDirection); - BlockPos trackEnd = startPosition.relative(assemblyDirection, assemblyLength - 1); - map.put(worldPosition, BoundingBox.fromCorners(startPosition, trackEnd)); - } - - public boolean isValidBogeyOffset(int i) { - if ((i < 3 || bogeyCount == 0) && i != 0) - return false; - for (int j : bogeyLocations) { - if (j == -1) - break; - if (i >= j - 2 && i <= j + 2) - return false; - } - return true; - } - - public Direction getAssemblyDirection() { - if (assemblyDirection != null) - return assemblyDirection; - if (!edgePoint.hasValidTrack()) - return null; - BlockPos targetPosition = edgePoint.getGlobalPosition(); - BlockState trackState = edgePoint.getTrackBlockState(); - ITrackBlock track = edgePoint.getTrack(); - AxisDirection axisDirection = edgePoint.getTargetDirection(); - Vec3 axis = track.getTrackAxes(level, targetPosition, trackState) - .get(0) - .normalize() - .scale(axisDirection.getStep()); - return assemblyDirection = Direction.getNearest(axis.x, axis.y, axis.z); - } - - @Override - public void remove() { - assemblyAreas.get(level) - .remove(worldPosition); - super.remove(); - } - - public void assemble(UUID playerUUID) { - refreshAssemblyInfo(); - - if (bogeyLocations == null) - return; - - if (bogeyLocations[0] != 0) { - exception(new AssemblyException(Lang.translateDirect("train_assembly.frontmost_bogey_at_station")), -1); - return; - } - - if (!edgePoint.hasValidTrack()) - return; - - BlockPos trackPosition = edgePoint.getGlobalPosition(); - BlockState trackState = edgePoint.getTrackBlockState(); - ITrackBlock track = edgePoint.getTrack(); - BlockPos bogeyOffset = new BlockPos(track.getUpNormal(level, trackPosition, trackState)); - - TrackNodeLocation location = null; - Vec3 centre = Vec3.atBottomCenterOf(trackPosition) - .add(0, track.getElevationAtCenter(level, trackPosition, trackState), 0); - Collection ends = track.getConnected(level, trackPosition, trackState, true, null); - Vec3 targetOffset = Vec3.atLowerCornerOf(assemblyDirection.getNormal()); - for (DiscoveredLocation end : ends) - if (Mth.equal(0, targetOffset.distanceToSqr(end.getLocation() - .subtract(centre) - .normalize()))) - location = end; - if (location == null) - return; - - List pointOffsets = new ArrayList<>(); - int iPrevious = -100; - for (int i = 0; i < bogeyLocations.length; i++) { - int loc = bogeyLocations[i]; - if (loc == -1) - break; - - if (loc - iPrevious < 3) { - exception(new AssemblyException(Lang.translateDirect("train_assembly.bogeys_too_close", i, i + 1)), -1); - return; - } - - double bogeySize = bogeyTypes[i].getWheelPointSpacing(); - pointOffsets.add(Double.valueOf(loc + .5 - bogeySize / 2)); - pointOffsets.add(Double.valueOf(loc + .5 + bogeySize / 2)); - iPrevious = loc; - } - - List points = new ArrayList<>(); - Vec3 directionVec = Vec3.atLowerCornerOf(assemblyDirection.getNormal()); - TrackGraph graph = null; - TrackNode secondNode = null; - - for (int j = 0; j < assemblyLength * 2 + 40; j++) { - double i = j / 2d; - if (points.size() == pointOffsets.size()) - break; - - TrackNodeLocation currentLocation = location; - location = new TrackNodeLocation(location.getLocation() - .add(directionVec.scale(.5))).in(location.dimension); - - if (graph == null) - graph = Create.RAILWAYS.getGraph(level, currentLocation); - if (graph == null) - continue; - TrackNode node = graph.locateNode(currentLocation); - if (node == null) - continue; - - for (int pointIndex = points.size(); pointIndex < pointOffsets.size(); pointIndex++) { - double offset = pointOffsets.get(pointIndex); - if (offset > i) - break; - double positionOnEdge = i - offset; - - Map connectionsFromNode = graph.getConnectionsFrom(node); - - if (secondNode == null) - for (Entry entry : connectionsFromNode.entrySet()) { - TrackEdge edge = entry.getValue(); - TrackNode otherNode = entry.getKey(); - if (edge.isTurn()) - continue; - Vec3 edgeDirection = edge.getDirection(true); - if (Mth.equal(edgeDirection.normalize() - .dot(directionVec), -1d)) - secondNode = otherNode; - } - - if (secondNode == null) { - Create.LOGGER.warn("Cannot assemble: No valid starting node found"); - return; - } - - TrackEdge edge = connectionsFromNode.get(secondNode); - - if (edge == null) { - Create.LOGGER.warn("Cannot assemble: Missing graph edge"); - return; - } - - points.add(new TravellingPoint(node, secondNode, edge, positionOnEdge)); - } - - secondNode = node; - } - - if (points.size() != pointOffsets.size()) { - Create.LOGGER.warn("Cannot assemble: Not all Points created"); - return; - } - - if (points.size() == 0) { - exception(new AssemblyException(Lang.translateDirect("train_assembly.no_bogeys")), -1); - return; - } - - List contraptions = new ArrayList<>(); - List carriages = new ArrayList<>(); - List spacing = new ArrayList<>(); - boolean atLeastOneForwardControls = false; - - for (int bogeyIndex = 0; bogeyIndex < bogeyCount; bogeyIndex++) { - int pointIndex = bogeyIndex * 2; - if (bogeyIndex > 0) - spacing.add(bogeyLocations[bogeyIndex] - bogeyLocations[bogeyIndex - 1]); - CarriageContraption contraption = new CarriageContraption(assemblyDirection); - BlockPos bogeyPosOffset = trackPosition.offset(bogeyOffset); - - try { - int offset = bogeyLocations[bogeyIndex] + 1; - boolean success = contraption.assemble(level, bogeyPosOffset.relative(assemblyDirection, offset)); - atLeastOneForwardControls |= contraption.hasForwardControls(); - contraption.setSoundQueueOffset(offset); - if (!success) { - exception(new AssemblyException(Lang.translateDirect("train_assembly.nothing_attached", bogeyIndex + 1)), - -1); - return; - } - } catch (AssemblyException e) { - exception(e, contraptions.size() + 1); - return; - } - - IBogeyBlock typeOfFirstBogey = bogeyTypes[bogeyIndex]; - CarriageBogey firstBogey = - new CarriageBogey(typeOfFirstBogey, points.get(pointIndex), points.get(pointIndex + 1)); - CarriageBogey secondBogey = null; - BlockPos secondBogeyPos = contraption.getSecondBogeyPos(); - int bogeySpacing = 0; - - if (secondBogeyPos != null) { - if (bogeyIndex == bogeyCount - 1 || !secondBogeyPos - .equals(bogeyPosOffset.relative(assemblyDirection, bogeyLocations[bogeyIndex + 1] + 1))) { - exception(new AssemblyException(Lang.translateDirect("train_assembly.not_connected_in_order")), - contraptions.size() + 1); - return; - } - - bogeySpacing = bogeyLocations[bogeyIndex + 1] - bogeyLocations[bogeyIndex]; - secondBogey = new CarriageBogey(bogeyTypes[bogeyIndex + 1], points.get(pointIndex + 2), - points.get(pointIndex + 3)); - bogeyIndex++; - - } else if (!typeOfFirstBogey.allowsSingleBogeyCarriage()) { - exception(new AssemblyException(Lang.translateDirect("train_assembly.single_bogey_carriage")), - contraptions.size() + 1); - return; - } - - contraptions.add(contraption); - carriages.add(new Carriage(firstBogey, secondBogey, bogeySpacing)); - } - - if (!atLeastOneForwardControls) { - exception(new AssemblyException(Lang.translateDirect("train_assembly.no_controls")), -1); - return; - } - - for (CarriageContraption contraption : contraptions) { - contraption.removeBlocksFromWorld(level, BlockPos.ZERO); - contraption.expandBoundsAroundAxis(Axis.Y); - } - - Train train = new Train(UUID.randomUUID(), playerUUID, graph, carriages, spacing, contraptions.stream() - .anyMatch(CarriageContraption::hasBackwardControls)); - - if (lastDisassembledTrainName != null) { - train.name = lastDisassembledTrainName; - lastDisassembledTrainName = null; - } - - for (int i = 0; i < contraptions.size(); i++) { - CarriageContraption contraption = contraptions.get(i); - Carriage carriage = carriages.get(i); - carriage.setContraption(level, contraption); - if (contraption.containsBlockBreakers()) - award(AllAdvancements.CONTRAPTION_ACTORS); - } - - GlobalStation station = getStation(); - if (station != null) { - train.setCurrentStation(station); - station.reserveFor(train); - } - - train.collectInitiallyOccupiedSignalBlocks(); - Create.RAILWAYS.addTrain(train); - AllPackets.channel.send(PacketDistributor.ALL.noArg(), new TrainPacket(train, true)); - clearException(); - - award(AllAdvancements.TRAIN); - if (contraptions.size() >= 6) - award(AllAdvancements.LONG_TRAIN); - } - - public void cancelAssembly() { - assemblyLength = 0; - assemblyAreas.get(level) - .remove(worldPosition); - clearException(); - } - - private void clearException() { - exception(null, -1); - } - - private void exception(AssemblyException exception, int carriage) { - failedCarriageIndex = carriage; - lastException = exception; - sendData(); - } - - @Override - @OnlyIn(Dist.CLIENT) - public AABB getRenderBoundingBox() { - if (isAssembling()) - return INFINITE_EXTENT_AABB; - return super.getRenderBoundingBox(); - } - - @Override - protected AABB createRenderBoundingBox() { - return new AABB(worldPosition, edgePoint.getGlobalPosition()).inflate(2); - } - - public ItemStack getAutoSchedule() { - return depotBehaviour.getHeldItemStack(); - } - - @Override - public LazyOptional getCapability(Capability cap, Direction side) { - if (isItemHandlerCap(cap)) - return depotBehaviour.getItemCapability(cap, side); - return super.getCapability(cap, side); - } - - private void applyAutoSchedule() { - ItemStack stack = getAutoSchedule(); - if (!AllItems.SCHEDULE.isIn(stack)) - return; - Schedule schedule = ScheduleItem.getSchedule(stack); - if (schedule == null || schedule.entries.isEmpty()) - return; - GlobalStation station = getStation(); - if (station == null) - return; - Train imminentTrain = station.getImminentTrain(); - if (imminentTrain == null || imminentTrain.getCurrentStation() != station) - return; - - award(AllAdvancements.CONDUCTOR); - imminentTrain.runtime.setSchedule(schedule, true); - AllSoundEvents.CONFIRM.playOnServer(level, worldPosition, 1, 1); - - if (!(level instanceof ServerLevel server)) - return; - - Vec3 v = Vec3.atBottomCenterOf(worldPosition.above()); - server.sendParticles(ParticleTypes.HAPPY_VILLAGER, v.x, v.y, v.z, 8, 0.35, 0.05, 0.35, 1); - server.sendParticles(ParticleTypes.END_ROD, v.x, v.y + .25f, v.z, 10, 0.05, 1, 0.05, 0.005f); - } - - public boolean resolveFlagAngle() { - if (flagYRot != -1) - return true; - - BlockState target = edgePoint.getTrackBlockState(); - if (!(target.getBlock() instanceof ITrackBlock def)) - return false; - - Vec3 axis = null; - BlockPos trackPos = edgePoint.getGlobalPosition(); - for (Vec3 vec3 : def.getTrackAxes(level, trackPos, target)) - axis = vec3.scale(edgePoint.getTargetDirection() - .getStep()); - if (axis == null) - return false; - - Direction nearest = Direction.getNearest(axis.x, 0, axis.z); - flagYRot = (int) (-nearest.toYRot() - 90); - - Vec3 diff = Vec3.atLowerCornerOf(trackPos.subtract(worldPosition)) - .multiply(1, 0, 1); - if (diff.lengthSqr() == 0) - return true; - - flagFlipped = diff.dot(Vec3.atLowerCornerOf(nearest.getClockWise() - .getNormal())) > 0; - - return true; - } - - @Override - public void transform(StructureTransform transform) { - edgePoint.transform(transform); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/TrainEditPacket.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/TrainEditPacket.java deleted file mode 100644 index f89993b53..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/TrainEditPacket.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.simibubi.create.content.logistics.trains.management.edgePoint.station; - -import java.util.UUID; -import java.util.function.Supplier; - -import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.entity.Train; -import com.simibubi.create.content.logistics.trains.entity.TrainIconType; -import com.simibubi.create.foundation.networking.AllPackets; -import com.simibubi.create.foundation.networking.SimplePacketBase; -import com.simibubi.create.foundation.utility.Components; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.level.Level; -import net.minecraftforge.network.NetworkEvent.Context; -import net.minecraftforge.network.PacketDistributor; - -public class TrainEditPacket extends SimplePacketBase { - - private String name; - private UUID id; - private ResourceLocation iconType; - - public TrainEditPacket(UUID id, String name, ResourceLocation iconType) { - this.name = name; - this.id = id; - this.iconType = iconType; - } - - public TrainEditPacket(FriendlyByteBuf buffer) { - id = buffer.readUUID(); - name = buffer.readUtf(256); - iconType = buffer.readResourceLocation(); - } - - @Override - public void write(FriendlyByteBuf buffer) { - buffer.writeUUID(id); - buffer.writeUtf(name); - buffer.writeResourceLocation(iconType); - } - - @Override - public void handle(Supplier context) { - Context ctx = context.get(); - ctx.enqueueWork(() -> { - ServerPlayer sender = ctx.getSender(); - Level level = sender == null ? null : sender.level; - Train train = Create.RAILWAYS.sided(level).trains.get(id); - if (train == null) - return; - if (!name.isBlank()) - train.name = Components.literal(name); - train.icon = TrainIconType.byId(iconType); - if (sender != null) - AllPackets.channel.send(PacketDistributor.ALL.noArg(), new TrainEditReturnPacket(id, name, iconType)); - }); - ctx.setPacketHandled(true); - } - - public static class TrainEditReturnPacket extends TrainEditPacket { - - public TrainEditReturnPacket(FriendlyByteBuf buffer) { - super(buffer); - } - - public TrainEditReturnPacket(UUID id, String name, ResourceLocation iconType) { - super(id, name, iconType); - } - - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/Schedule.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/Schedule.java deleted file mode 100644 index f27ea2f9c..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/Schedule.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.simibubi.create.content.logistics.trains.management.schedule; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Supplier; - -import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.management.schedule.condition.FluidThresholdCondition; -import com.simibubi.create.content.logistics.trains.management.schedule.condition.IdleCargoCondition; -import com.simibubi.create.content.logistics.trains.management.schedule.condition.ItemThresholdCondition; -import com.simibubi.create.content.logistics.trains.management.schedule.condition.PlayerPassengerCondition; -import com.simibubi.create.content.logistics.trains.management.schedule.condition.RedstoneLinkCondition; -import com.simibubi.create.content.logistics.trains.management.schedule.condition.ScheduleWaitCondition; -import com.simibubi.create.content.logistics.trains.management.schedule.condition.ScheduledDelay; -import com.simibubi.create.content.logistics.trains.management.schedule.condition.StationPoweredCondition; -import com.simibubi.create.content.logistics.trains.management.schedule.condition.StationUnloadedCondition; -import com.simibubi.create.content.logistics.trains.management.schedule.condition.TimeOfDayCondition; -import com.simibubi.create.content.logistics.trains.management.schedule.destination.ChangeThrottleInstruction; -import com.simibubi.create.content.logistics.trains.management.schedule.destination.ChangeTitleInstruction; -import com.simibubi.create.content.logistics.trains.management.schedule.destination.DestinationInstruction; -import com.simibubi.create.content.logistics.trains.management.schedule.destination.ScheduleInstruction; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.Pair; - -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; - -public class Schedule { - - public static List>> INSTRUCTION_TYPES = - new ArrayList<>(); - public static List>> CONDITION_TYPES = - new ArrayList<>(); - - static { - registerInstruction("destination", DestinationInstruction::new); - registerInstruction("rename", ChangeTitleInstruction::new); - registerInstruction("throttle", ChangeThrottleInstruction::new); - registerCondition("delay", ScheduledDelay::new); - registerCondition("time_of_day", TimeOfDayCondition::new); - registerCondition("fluid_threshold", FluidThresholdCondition::new); - registerCondition("item_threshold", ItemThresholdCondition::new); - registerCondition("redstone_link", RedstoneLinkCondition::new); - registerCondition("player_count", PlayerPassengerCondition::new); - registerCondition("idle", IdleCargoCondition::new); - registerCondition("unloaded", StationUnloadedCondition::new); - registerCondition("powered", StationPoweredCondition::new); - } - - private static void registerInstruction(String name, Supplier factory) { - INSTRUCTION_TYPES.add(Pair.of(Create.asResource(name), factory)); - } - - private static void registerCondition(String name, Supplier factory) { - CONDITION_TYPES.add(Pair.of(Create.asResource(name), factory)); - } - - public static List getTypeOptions(List> list) { - String langSection = list.equals(INSTRUCTION_TYPES) ? "instruction." : "condition."; - return list.stream() - .map(Pair::getFirst) - .map(rl -> rl.getNamespace() + ".schedule." + langSection + rl.getPath()) - .map(Components::translatable) - .toList(); - } - - public List entries; - public boolean cyclic; - public int savedProgress; - - public Schedule() { - entries = new ArrayList<>(); - cyclic = true; - savedProgress = 0; - } - - public CompoundTag write() { - CompoundTag tag = new CompoundTag(); - ListTag list = NBTHelper.writeCompoundList(entries, ScheduleEntry::write); - tag.put("Entries", list); - tag.putBoolean("Cyclic", cyclic); - if (savedProgress > 0) - tag.putInt("Progress", savedProgress); - return tag; - } - - public static Schedule fromTag(CompoundTag tag) { - Schedule schedule = new Schedule(); - schedule.entries = NBTHelper.readCompoundList(tag.getList("Entries", Tag.TAG_COMPOUND), ScheduleEntry::fromTag); - schedule.cyclic = tag.getBoolean("Cyclic"); - if (tag.contains("Progress")) - schedule.savedProgress = tag.getInt("Progress"); - return schedule; - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleContainer.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleContainer.java deleted file mode 100644 index 15f456bbb..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleContainer.java +++ /dev/null @@ -1,107 +0,0 @@ -package com.simibubi.create.content.logistics.trains.management.schedule; - -import com.simibubi.create.foundation.gui.container.GhostItemContainer; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.Container; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.entity.player.Player; -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.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.ItemStackHandler; -import net.minecraftforge.items.SlotItemHandler; - -public class ScheduleContainer extends GhostItemContainer { - - public boolean slotsActive = true; - public int targetSlotsActive = 1; - - static final int slots = 2; - - public ScheduleContainer(MenuType type, int id, Inventory inv, FriendlyByteBuf extraData) { - super(type, id, inv, extraData); - } - - public ScheduleContainer(MenuType type, int id, Inventory inv, ItemStack contentHolder) { - super(type, id, inv, contentHolder); - } - - @Override - protected ItemStackHandler createGhostInventory() { - return new ItemStackHandler(slots); - } - - @Override - public void clicked(int slotId, int dragType, ClickType clickTypeIn, Player player) { - if (slotId != playerInventory.selected || clickTypeIn == ClickType.THROW) - super.clicked(slotId, dragType, clickTypeIn, player); - } - - @Override - protected boolean allowRepeats() { - return true; - } - - @Override - protected ItemStack createOnClient(FriendlyByteBuf extraData) { - return extraData.readItem(); - } - - @Override - protected void addSlots() { - addPlayerSlots(46, 140); - for (int i = 0; i < slots; i++) - addSlot(new InactiveItemHandlerSlot(ghostInventory, i, i, 54 + 20 * i, 88)); - } - - @Override - protected void addPlayerSlots(int x, int y) { - for (int hotbarSlot = 0; hotbarSlot < 9; ++hotbarSlot) - this.addSlot(new InactiveSlot(playerInventory, hotbarSlot, x + hotbarSlot * 18, y + 58)); - for (int row = 0; row < 3; ++row) - for (int col = 0; col < 9; ++col) - this.addSlot(new InactiveSlot(playerInventory, col + row * 9 + 9, x + col * 18, y + row * 18)); - } - - @Override - protected void saveData(ItemStack contentHolder) {} - - @Override - public boolean stillValid(Player player) { - return playerInventory.getSelected() == contentHolder; - } - - class InactiveSlot extends Slot { - - public InactiveSlot(Container pContainer, int pIndex, int pX, int pY) { - super(pContainer, pIndex, pX, pY); - } - - @Override - public boolean isActive() { - return slotsActive; - } - - } - - class InactiveItemHandlerSlot extends SlotItemHandler { - - private int targetIndex; - - public InactiveItemHandlerSlot(IItemHandler itemHandler, int targetIndex, int index, int xPosition, - int yPosition) { - super(itemHandler, index, xPosition, yPosition); - this.targetIndex = targetIndex; - } - - @Override - public boolean isActive() { - return slotsActive && targetIndex < targetSlotsActive; - } - - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleEditPacket.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleEditPacket.java deleted file mode 100644 index c609feeca..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleEditPacket.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.simibubi.create.content.logistics.trains.management.schedule; - -import java.util.function.Supplier; - -import com.simibubi.create.AllItems; -import com.simibubi.create.foundation.networking.SimplePacketBase; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.network.NetworkEvent.Context; - -public class ScheduleEditPacket extends SimplePacketBase { - - private Schedule schedule; - - public ScheduleEditPacket(Schedule schedule) { - this.schedule = schedule; - } - - public ScheduleEditPacket(FriendlyByteBuf buffer) { - schedule = Schedule.fromTag(buffer.readNbt()); - } - - @Override - public void write(FriendlyByteBuf buffer) { - buffer.writeNbt(schedule.write()); - } - - @Override - public void handle(Supplier context) { - context.get() - .enqueueWork(() -> { - ServerPlayer sender = context.get() - .getSender(); - ItemStack mainHandItem = sender.getMainHandItem(); - if (!AllItems.SCHEDULE.isIn(mainHandItem)) - return; - - CompoundTag tag = mainHandItem.getOrCreateTag(); - if (schedule.entries.isEmpty()) { - tag.remove("Schedule"); - if (tag.isEmpty()) - mainHandItem.setTag(null); - } else - tag.put("Schedule", schedule.write()); - - sender.getCooldowns() - .addCooldown(mainHandItem.getItem(), 5); - }); - context.get() - .setPacketHandled(true); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/ScheduleWaitCondition.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/ScheduleWaitCondition.java deleted file mode 100644 index a8e307d6a..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/ScheduleWaitCondition.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.simibubi.create.content.logistics.trains.management.schedule.condition; - -import java.util.function.Supplier; - -import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.entity.Train; -import com.simibubi.create.content.logistics.trains.management.schedule.Schedule; -import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleDataEntry; -import com.simibubi.create.foundation.utility.Pair; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.Level; - -public abstract class ScheduleWaitCondition extends ScheduleDataEntry { - - public abstract boolean tickCompletion(Level level, Train train, CompoundTag context); - - protected void requestStatusToUpdate(CompoundTag context) { - context.putInt("StatusVersion", context.getInt("StatusVersion") + 1); - } - - public final CompoundTag write() { - CompoundTag tag = new CompoundTag(); - tag.putString("Id", getId().toString()); - tag.put("Data", data.copy()); - writeAdditional(tag); - return tag; - } - - public static ScheduleWaitCondition fromTag(CompoundTag tag) { - ResourceLocation location = new ResourceLocation(tag.getString("Id")); - Supplier supplier = null; - for (Pair> pair : Schedule.CONDITION_TYPES) - if (pair.getFirst() - .equals(location)) - supplier = pair.getSecond(); - - if (supplier == null) { - Create.LOGGER.warn("Could not parse waiting condition type: " + location); - return null; - } - - ScheduleWaitCondition condition = supplier.get(); - condition.data = tag.getCompound("Data"); - condition.readAdditional(tag); - return condition; - } - - public abstract MutableComponent getWaitingStatus(Level level, Train train, CompoundTag tag); - -} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/destination/ScheduleInstruction.java b/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/destination/ScheduleInstruction.java deleted file mode 100644 index cc3554094..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/destination/ScheduleInstruction.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.simibubi.create.content.logistics.trains.management.schedule.destination; - -import java.util.function.Supplier; - -import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.management.schedule.Schedule; -import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleDataEntry; -import com.simibubi.create.foundation.utility.Pair; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.resources.ResourceLocation; - -public abstract class ScheduleInstruction extends ScheduleDataEntry { - - public abstract boolean supportsConditions(); - - public final CompoundTag write() { - CompoundTag tag = new CompoundTag(); - tag.putString("Id", getId().toString()); - tag.put("Data", data.copy()); - writeAdditional(tag); - return tag; - } - - public static ScheduleInstruction fromTag(CompoundTag tag) { - ResourceLocation location = new ResourceLocation(tag.getString("Id")); - Supplier supplier = null; - for (Pair> pair : Schedule.INSTRUCTION_TYPES) - if (pair.getFirst() - .equals(location)) - supplier = pair.getSecond(); - - if (supplier == null) { - Create.LOGGER.warn("Could not parse schedule instruction type: " + location); - return new DestinationInstruction(); - } - - ScheduleInstruction scheduleDestination = supplier.get(); - scheduleDestination.data = tag.getCompound("Data"); - scheduleDestination.readAdditional(tag); - return scheduleDestination; - } - -} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/track/BezierTrackPointLocation.java b/src/main/java/com/simibubi/create/content/logistics/trains/track/BezierTrackPointLocation.java deleted file mode 100644 index c087ed6a1..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/track/BezierTrackPointLocation.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.simibubi.create.content.logistics.trains.track; - -import net.minecraft.core.BlockPos; - -public record BezierTrackPointLocation(BlockPos curveTarget, int segment) { -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/track/CurvedTrackDestroyPacket.java b/src/main/java/com/simibubi/create/content/logistics/trains/track/CurvedTrackDestroyPacket.java deleted file mode 100644 index 23d2ffc4e..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/track/CurvedTrackDestroyPacket.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.simibubi.create.content.logistics.trains.track; - -import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.BezierConnection; -import com.simibubi.create.content.logistics.trains.TrackPropagator; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.networking.TileEntityConfigurationPacket; - -import net.minecraft.core.BlockPos; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.sounds.SoundSource; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.block.state.BlockState; - -public class CurvedTrackDestroyPacket extends TileEntityConfigurationPacket { - - private BlockPos targetPos; - private BlockPos soundSource; - private boolean wrench; - - public CurvedTrackDestroyPacket(BlockPos pos, BlockPos targetPos, BlockPos soundSource, boolean wrench) { - super(pos); - this.targetPos = targetPos; - this.soundSource = soundSource; - this.wrench = wrench; - } - - public CurvedTrackDestroyPacket(FriendlyByteBuf buffer) { - super(buffer); - } - - @Override - protected void writeSettings(FriendlyByteBuf buffer) { - buffer.writeBlockPos(targetPos); - buffer.writeBlockPos(soundSource); - buffer.writeBoolean(wrench); - } - - @Override - protected void readSettings(FriendlyByteBuf buffer) { - targetPos = buffer.readBlockPos(); - soundSource = buffer.readBlockPos(); - wrench = buffer.readBoolean(); - } - - @Override - protected void applySettings(ServerPlayer player, TrackTileEntity te) { - int verifyDistance = AllConfigs.SERVER.trains.maxTrackPlacementLength.get() * 4; - if (!te.getBlockPos() - .closerThan(player.blockPosition(), verifyDistance)) { - Create.LOGGER.warn(player.getScoreboardName() + " too far away from destroyed Curve track"); - return; - } - - Level level = te.getLevel(); - BezierConnection bezierConnection = te.getConnections() - .get(targetPos); - - te.removeConnection(targetPos); - if (level.getBlockEntity(targetPos)instanceof TrackTileEntity other) - other.removeConnection(pos); - - BlockState blockState = te.getBlockState(); - TrackPropagator.onRailRemoved(level, pos, blockState); - - if (wrench) { - AllSoundEvents.WRENCH_REMOVE.playOnServer(player.level, soundSource, 1, - Create.RANDOM.nextFloat() * .5f + .5f); - if (!player.isCreative() && bezierConnection != null) - bezierConnection.addItemsToPlayer(player); - } else if (!player.isCreative() && bezierConnection != null) - bezierConnection.spawnItems(level); - - bezierConnection.spawnDestroyParticles(level); - SoundType soundtype = blockState.getSoundType(level, pos, player); - if (soundtype == null) - return; - - level.playSound(null, soundSource, soundtype.getBreakSound(), SoundSource.BLOCKS, - (soundtype.getVolume() + 1.0F) / 2.0F, soundtype.getPitch() * 0.8F); - } - - @Override - protected int maxRange() { - return 64; - } - - @Override - protected void applySettings(TrackTileEntity te) {} - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/track/FakeTrackTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/trains/track/FakeTrackTileEntity.java deleted file mode 100644 index 8d38b57cf..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/track/FakeTrackTileEntity.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.simibubi.create.content.logistics.trains.track; - -import com.simibubi.create.foundation.tileEntity.SyncedTileEntity; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; - -public class FakeTrackTileEntity extends SyncedTileEntity { - - int keepAlive; - - public FakeTrackTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - keepAlive(); - } - - public void randomTick() { - keepAlive--; - if (keepAlive > 0) - return; - level.removeBlock(worldPosition, false); - } - - public void keepAlive() { - keepAlive = 3; - } - - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/track/PlaceExtendedCurvePacket.java b/src/main/java/com/simibubi/create/content/logistics/trains/track/PlaceExtendedCurvePacket.java deleted file mode 100644 index 4d1859325..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/track/PlaceExtendedCurvePacket.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.simibubi.create.content.logistics.trains.track; - -import java.util.function.Supplier; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.foundation.networking.SimplePacketBase; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.network.NetworkEvent.Context; - -public class PlaceExtendedCurvePacket extends SimplePacketBase { - - boolean mainHand; - boolean ctrlDown; - - public PlaceExtendedCurvePacket(boolean mainHand, boolean ctrlDown) { - this.mainHand = mainHand; - this.ctrlDown = ctrlDown; - } - - public PlaceExtendedCurvePacket(FriendlyByteBuf buffer) { - mainHand = buffer.readBoolean(); - ctrlDown = buffer.readBoolean(); - } - - @Override - public void write(FriendlyByteBuf buffer) { - buffer.writeBoolean(mainHand); - buffer.writeBoolean(ctrlDown); - } - - @Override - public void handle(Supplier context) { - Context ctx = context.get(); - ctx.enqueueWork(() -> { - ServerPlayer sender = ctx.getSender(); - ItemStack stack = sender.getItemInHand(mainHand ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND); - if (!AllBlocks.TRACK.isIn(stack) || !stack.hasTag()) - return; - CompoundTag tag = stack.getTag(); - tag.putBoolean("ExtendCurve", true); - stack.setTag(tag); - }); - ctx.setPacketHandled(true); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/track/StandardBogeyBlock.java b/src/main/java/com/simibubi/create/content/logistics/trains/track/StandardBogeyBlock.java deleted file mode 100644 index 76ab2335f..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/track/StandardBogeyBlock.java +++ /dev/null @@ -1,241 +0,0 @@ -package com.simibubi.create.content.logistics.trains.track; - -import java.util.EnumSet; - -import com.jozufozu.flywheel.api.MaterialManager; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import com.mojang.math.Axis; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.relays.elementary.ShaftBlock; -import com.simibubi.create.content.logistics.trains.IBogeyBlock; -import com.simibubi.create.content.logistics.trains.entity.BogeyInstance; -import com.simibubi.create.content.logistics.trains.entity.CarriageBogey; -import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement; -import com.simibubi.create.content.schematics.ItemRequirement; -import com.simibubi.create.content.schematics.ItemRequirement.ItemUseType; -import com.simibubi.create.foundation.block.ITE; -import com.simibubi.create.foundation.block.ProperWaterloggedBlock; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.Iterate; - -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.Rotation; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition.Builder; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.block.state.properties.EnumProperty; -import net.minecraft.world.level.material.FluidState; -import net.minecraft.world.phys.HitResult; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -public class StandardBogeyBlock extends Block - implements IBogeyBlock, ITE, ProperWaterloggedBlock, ISpecialBlockItemRequirement { - - public static final EnumProperty AXIS = BlockStateProperties.HORIZONTAL_AXIS; - private final boolean large; - - public StandardBogeyBlock(Properties p_i48440_1_, boolean large) { - super(p_i48440_1_); - this.large = large; - registerDefaultState(defaultBlockState().setValue(WATERLOGGED, false)); - } - - @Override - protected void createBlockStateDefinition(Builder builder) { - builder.add(AXIS, WATERLOGGED); - super.createBlockStateDefinition(builder); - } - - static final EnumSet STICKY_X = EnumSet.of(Direction.EAST, Direction.WEST); - static final EnumSet STICKY_Z = EnumSet.of(Direction.SOUTH, Direction.NORTH); - - @Override - public EnumSet getStickySurfaces(BlockGetter world, BlockPos pos, BlockState state) { - return state.getValue(BlockStateProperties.HORIZONTAL_AXIS) == Direction.Axis.X ? STICKY_X : STICKY_Z; - } - - @Override - public BlockState updateShape(BlockState pState, Direction pDirection, BlockState pNeighborState, - LevelAccessor pLevel, BlockPos pCurrentPos, BlockPos pNeighborPos) { - updateWater(pLevel, pState, pCurrentPos); - return pState; - } - - @Override - public FluidState getFluidState(BlockState pState) { - return fluidState(pState); - } - - @Override - public double getWheelPointSpacing() { - return 2; - } - - @Override - public double getWheelRadius() { - return (large ? 12.5 : 6.5) / 16d; - } - - @Override - public Vec3 getConnectorAnchorOffset() { - return new Vec3(0, 7 / 32f, 1); - } - - @Override - public boolean allowsSingleBogeyCarriage() { - return true; - } - - @Override - public BlockState getMatchingBogey(Direction upDirection, boolean axisAlongFirst) { - if (upDirection != Direction.UP) - return null; - return defaultBlockState().setValue(AXIS, axisAlongFirst ? Direction.Axis.X : Direction.Axis.Z); - } - - @Override - public boolean isTrackAxisAlongFirstCoordinate(BlockState state) { - return state.getValue(AXIS) == Direction.Axis.X; - } - - @Override - @OnlyIn(Dist.CLIENT) - public void render(BlockState state, float wheelAngle, PoseStack ms, float partialTicks, MultiBufferSource buffers, - int light, int overlay) { - if (state != null) { - ms.translate(.5f, .5f, .5f); - if (state.getValue(AXIS) == Direction.Axis.X) - ms.mulPose(Axis.YP.rotationDegrees(90)); - } - - ms.translate(0, -1.5 - 1 / 128f, 0); - - VertexConsumer vb = buffers.getBuffer(RenderType.cutoutMipped()); - BlockState air = Blocks.AIR.defaultBlockState(); - - for (int i : Iterate.zeroAndOne) - CachedBufferer.block(AllBlocks.SHAFT.getDefaultState() - .setValue(ShaftBlock.AXIS, Direction.Axis.Z)) - .translate(-.5f, .25f, i * -1) - .centre() - .rotateZ(wheelAngle) - .unCentre() - .light(light) - .renderInto(ms, vb); - - if (large) { - renderLargeBogey(wheelAngle, ms, light, vb, air); - } else { - renderBogey(wheelAngle, ms, light, vb, air); - } - } - - private void renderBogey(float wheelAngle, PoseStack ms, int light, VertexConsumer vb, BlockState air) { - CachedBufferer.partial(AllBlockPartials.BOGEY_FRAME, air) - .scale(1 - 1 / 512f) - .light(light) - .renderInto(ms, vb); - - for (int side : Iterate.positiveAndNegative) { - ms.pushPose(); - CachedBufferer.partial(AllBlockPartials.SMALL_BOGEY_WHEELS, air) - .translate(0, 12 / 16f, side) - .rotateX(wheelAngle) - .light(light) - .renderInto(ms, vb); - ms.popPose(); - } - } - - private void renderLargeBogey(float wheelAngle, PoseStack ms, int light, VertexConsumer vb, BlockState air) { - for (int i : Iterate.zeroAndOne) - CachedBufferer.block(AllBlocks.SHAFT.getDefaultState() - .setValue(ShaftBlock.AXIS, Direction.Axis.X)) - .translate(-.5f, .25f, .5f + i * -2) - .centre() - .rotateX(wheelAngle) - .unCentre() - .light(light) - .renderInto(ms, vb); - - CachedBufferer.partial(AllBlockPartials.BOGEY_DRIVE, air) - .scale(1 - 1 / 512f) - .light(light) - .renderInto(ms, vb); - CachedBufferer.partial(AllBlockPartials.BOGEY_PISTON, air) - .translate(0, 0, 1 / 4f * Math.sin(AngleHelper.rad(wheelAngle))) - .light(light) - .renderInto(ms, vb); - - ms.pushPose(); - CachedBufferer.partial(AllBlockPartials.LARGE_BOGEY_WHEELS, air) - .translate(0, 1, 0) - .rotateX(wheelAngle) - .light(light) - .renderInto(ms, vb); - CachedBufferer.partial(AllBlockPartials.BOGEY_PIN, air) - .translate(0, 1, 0) - .rotateX(wheelAngle) - .translate(0, 1 / 4f, 0) - .rotateX(-wheelAngle) - .light(light) - .renderInto(ms, vb); - ms.popPose(); - } - - @Override - public BogeyInstance createInstance(MaterialManager materialManager, CarriageBogey bogey) { - if (large) { - return new BogeyInstance.Drive(bogey, materialManager); - } else { - return new BogeyInstance.Frame(bogey, materialManager); - } - } - - @Override - public BlockState rotate(BlockState pState, Rotation pRotation) { - return switch (pRotation) { - case COUNTERCLOCKWISE_90, CLOCKWISE_90 -> pState.cycle(AXIS); - default -> pState; - }; - } - - @Override - public ItemStack getCloneItemStack(BlockState state, HitResult target, BlockGetter level, BlockPos pos, - Player player) { - return AllBlocks.RAILWAY_CASING.asStack(); - } - - @Override - public Class getTileEntityClass() { - return StandardBogeyTileEntity.class; - } - - @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.BOGEY.get(); - } - - @Override - public ItemRequirement getRequiredItems(BlockState state, BlockEntity te) { - return new ItemRequirement(ItemUseType.CONSUME, AllBlocks.RAILWAY_CASING.asStack()); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/track/StandardBogeyTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/trains/track/StandardBogeyTileEntity.java deleted file mode 100644 index 9a4c8a621..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/track/StandardBogeyTileEntity.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.simibubi.create.content.logistics.trains.track; - -import com.simibubi.create.content.logistics.trains.IBogeyBlock; -import com.simibubi.create.foundation.tileEntity.CachedRenderBBTileEntity; -import com.simibubi.create.foundation.utility.animation.LerpedFloat; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.AABB; - -public class StandardBogeyTileEntity extends CachedRenderBBTileEntity { - - public StandardBogeyTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - } - - @Override - protected AABB createRenderBoundingBox() { - return super.createRenderBoundingBox().inflate(2); - } - - // Ponder - - LerpedFloat virtualAnimation = LerpedFloat.angular(); - - public float getVirtualAngle(float partialTicks) { - return virtualAnimation.getValue(partialTicks); - } - - public void animate(float distanceMoved) { - BlockState blockState = getBlockState(); - if (!(blockState.getBlock() instanceof IBogeyBlock type)) - return; - double angleDiff = 360 * distanceMoved / (Math.PI * 2 * type.getWheelRadius()); - double newWheelAngle = (virtualAnimation.getValue() - angleDiff) % 360; - virtualAnimation.setValue(newWheelAngle); - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackTileEntity.java deleted file mode 100644 index 56bbe53c9..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackTileEntity.java +++ /dev/null @@ -1,396 +0,0 @@ -package com.simibubi.create.content.logistics.trains.track; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; -import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.components.structureMovement.ITransformableTE; -import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform; -import com.simibubi.create.content.logistics.trains.BezierConnection; -import com.simibubi.create.content.logistics.trains.ITrackBlock; -import com.simibubi.create.content.logistics.trains.TrackNodeLocation; -import com.simibubi.create.foundation.block.ProperWaterloggedBlock; -import com.simibubi.create.foundation.networking.AllPackets; -import com.simibubi.create.foundation.tileEntity.IMergeableTE; -import com.simibubi.create.foundation.tileEntity.RemoveTileEntityPacket; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.utility.Pair; -import com.simibubi.create.foundation.utility.VecHelper; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction.Axis; -import net.minecraft.core.registries.Registries; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.NbtUtils; -import net.minecraft.nbt.Tag; -import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.util.Mth; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.FluidState; -import net.minecraft.world.level.material.Fluids; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.fml.DistExecutor; - -public class TrackTileEntity extends SmartTileEntity implements ITransformableTE, IMergeableTE { - - Map connections; - boolean cancelDrops; - - public Pair, BlockPos> boundLocation; - - public TrackTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - connections = new HashMap<>(); - setLazyTickRate(100); - } - - public Map getConnections() { - return connections; - } - - @Override - public void initialize() { - super.initialize(); - if (!level.isClientSide && hasInteractableConnections()) - registerToCurveInteraction(); - } - - @Override - public void lazyTick() { - for (BezierConnection connection : connections.values()) - if (connection.isPrimary()) - manageFakeTracksAlong(connection, false); - } - - public void validateConnections() { - Set invalid = new HashSet<>(); - - for (Entry entry : connections.entrySet()) { - BlockPos key = entry.getKey(); - BezierConnection bc = entry.getValue(); - - if (!key.equals(bc.getKey()) || !worldPosition.equals(bc.tePositions.getFirst())) { - invalid.add(key); - continue; - } - - BlockState blockState = level.getBlockState(key); - if (blockState.getBlock()instanceof ITrackBlock trackBlock && !blockState.getValue(TrackBlock.HAS_TE)) - for (Vec3 v : trackBlock.getTrackAxes(level, key, blockState)) { - Vec3 bcEndAxis = bc.axes.getSecond(); - if (v.distanceTo(bcEndAxis) < 1 / 1024f || v.distanceTo(bcEndAxis.scale(-1)) < 1 / 1024f) - level.setBlock(key, blockState.setValue(TrackBlock.HAS_TE, true), 3); - } - - BlockEntity blockEntity = level.getBlockEntity(key); - if (!(blockEntity instanceof TrackTileEntity trackTE) || blockEntity.isRemoved()) { - invalid.add(key); - continue; - } - - if (!trackTE.connections.containsKey(worldPosition)) - trackTE.addConnection(bc.secondary()); - } - - for (BlockPos blockPos : invalid) - removeConnection(blockPos); - } - - public void addConnection(BezierConnection connection) { - connections.put(connection.getKey(), connection); - level.scheduleTick(worldPosition, getBlockState().getBlock(), 1); - notifyUpdate(); - - if (connection.isPrimary()) - manageFakeTracksAlong(connection, false); - } - - public void removeConnection(BlockPos target) { - BezierConnection removed = connections.remove(target); - notifyUpdate(); - - if (removed != null) - manageFakeTracksAlong(removed, true); - - if (!connections.isEmpty() || getBlockState().getOptionalValue(TrackBlock.SHAPE) - .orElse(TrackShape.NONE) - .isPortal()) - return; - - BlockState blockState = level.getBlockState(worldPosition); - if (blockState.hasProperty(TrackBlock.HAS_TE)) - level.setBlockAndUpdate(worldPosition, blockState.setValue(TrackBlock.HAS_TE, false)); - AllPackets.channel.send(packetTarget(), new RemoveTileEntityPacket(worldPosition)); - } - - public void removeInboundConnections() { - for (BezierConnection bezierConnection : connections.values()) { - BlockEntity blockEntity = level.getBlockEntity(bezierConnection.getKey()); - if (!(blockEntity instanceof TrackTileEntity)) - return; - TrackTileEntity other = (TrackTileEntity) blockEntity; - other.removeConnection(bezierConnection.tePositions.getFirst()); - - if (!cancelDrops) - bezierConnection.spawnItems(level); - bezierConnection.spawnDestroyParticles(level); - } - AllPackets.channel.send(packetTarget(), new RemoveTileEntityPacket(worldPosition)); - } - - public void bind(ResourceKey boundDimension, BlockPos boundLocation) { - this.boundLocation = Pair.of(boundDimension, boundLocation); - setChanged(); - } - - @Override - public void writeSafe(CompoundTag tag) { - super.writeSafe(tag); - writeTurns(tag); - } - - @Override - protected void write(CompoundTag tag, boolean clientPacket) { - super.write(tag, clientPacket); - writeTurns(tag); - if (boundLocation == null) - return; - tag.put("BoundLocation", NbtUtils.writeBlockPos(boundLocation.getSecond())); - tag.putString("BoundDimension", boundLocation.getFirst() - .location() - .toString()); - } - - private void writeTurns(CompoundTag tag) { - ListTag listTag = new ListTag(); - for (BezierConnection bezierConnection : connections.values()) - listTag.add(bezierConnection.write(worldPosition)); - tag.put("Connections", listTag); - } - - @Override - protected void read(CompoundTag tag, boolean clientPacket) { - super.read(tag, clientPacket); - connections.clear(); - for (Tag t : tag.getList("Connections", Tag.TAG_COMPOUND)) { - if (!(t instanceof CompoundTag)) - return; - BezierConnection connection = new BezierConnection((CompoundTag) t, worldPosition); - connections.put(connection.getKey(), connection); - } - - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(this)); - - if (hasInteractableConnections()) - registerToCurveInteraction(); - else - removeFromCurveInteraction(); - - if (tag.contains("BoundLocation")) - boundLocation = Pair.of( - ResourceKey.create(Registries.DIMENSION, new ResourceLocation(tag.getString("BoundDimension"))), - NbtUtils.readBlockPos(tag.getCompound("BoundLocation"))); - } - - @Override - @OnlyIn(Dist.CLIENT) - public AABB getRenderBoundingBox() { - return INFINITE_EXTENT_AABB; - } - - @Override - public void addBehaviours(List behaviours) {} - - @Override - public void accept(BlockEntity other) { - if (other instanceof TrackTileEntity track) - connections.putAll(track.connections); - validateConnections(); - level.scheduleTick(worldPosition, getBlockState().getBlock(), 1); - } - - public boolean hasInteractableConnections() { - for (BezierConnection connection : connections.values()) - if (connection.isPrimary()) - return true; - return false; - } - - @Override - public void transform(StructureTransform transform) { - if (transform.rotationAxis != Axis.Y) - return; - - Map transformedConnections = new HashMap<>(); - for (Entry entry : connections.entrySet()) { - BezierConnection newConnection = entry.getValue(); - newConnection.normals.replace(transform::applyWithoutOffsetUncentered); - newConnection.axes.replace(transform::applyWithoutOffsetUncentered); - - BlockPos diff = newConnection.tePositions.getSecond() - .subtract(newConnection.tePositions.getFirst()); - newConnection.tePositions.setSecond(new BlockPos(Vec3.atCenterOf(newConnection.tePositions.getFirst()) - .add(transform.applyWithoutOffsetUncentered(Vec3.atLowerCornerOf(diff))))); - - Vec3 teVec = Vec3.atLowerCornerOf(worldPosition); - Vec3 teCenterVec = teVec.add(0.5, 0.5, 0.5); - Vec3 start = newConnection.starts.getFirst(); - Vec3 startToTE = start.subtract(teCenterVec); - Vec3 endToStart = newConnection.starts.getSecond() - .subtract(start); - startToTE = transform.applyWithoutOffsetUncentered(startToTE) - .add(teCenterVec); - endToStart = transform.applyWithoutOffsetUncentered(endToStart) - .add(startToTE); - - newConnection.starts.setFirst(new TrackNodeLocation(startToTE).getLocation()); - newConnection.starts.setSecond(new TrackNodeLocation(endToStart).getLocation()); - - BlockPos newTarget = newConnection.getKey(); - transformedConnections.put(newTarget, newConnection); - } - - connections = transformedConnections; - } - - @Override - public void invalidate() { - super.invalidate(); - if (level.isClientSide) - removeFromCurveInteraction(); - } - - @Override - public void remove() { - super.remove(); - - for (BezierConnection connection : connections.values()) - manageFakeTracksAlong(connection, true); - - if (boundLocation != null && level instanceof ServerLevel) { - ServerLevel otherLevel = level.getServer() - .getLevel(boundLocation.getFirst()); - if (otherLevel == null) - return; - if (AllBlocks.TRACK.has(otherLevel.getBlockState(boundLocation.getSecond()))) - otherLevel.destroyBlock(boundLocation.getSecond(), false); - } - } - - private void registerToCurveInteraction() { - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> this::registerToCurveInteractionUnsafe); - } - - private void removeFromCurveInteraction() { - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> this::removeFromCurveInteractionUnsafe); - } - - @OnlyIn(Dist.CLIENT) - private void registerToCurveInteractionUnsafe() { - TrackBlockOutline.TRACKS_WITH_TURNS.get(level) - .put(worldPosition, this); - } - - @OnlyIn(Dist.CLIENT) - private void removeFromCurveInteractionUnsafe() { - TrackBlockOutline.TRACKS_WITH_TURNS.get(level) - .remove(worldPosition); - } - - public void manageFakeTracksAlong(BezierConnection bc, boolean remove) { - Map, Double> yLevels = new HashMap<>(); - BlockPos tePosition = bc.tePositions.getFirst(); - Vec3 end1 = bc.starts.getFirst() - .subtract(Vec3.atLowerCornerOf(tePosition)) - .add(0, 3 / 16f, 0); - Vec3 end2 = bc.starts.getSecond() - .subtract(Vec3.atLowerCornerOf(tePosition)) - .add(0, 3 / 16f, 0); - Vec3 axis1 = bc.axes.getFirst(); - Vec3 axis2 = bc.axes.getSecond(); - - double handleLength = bc.getHandleLength(); - - Vec3 finish1 = axis1.scale(handleLength) - .add(end1); - Vec3 finish2 = axis2.scale(handleLength) - .add(end2); - - Vec3 faceNormal1 = bc.normals.getFirst(); - Vec3 faceNormal2 = bc.normals.getSecond(); - - int segCount = bc.getSegmentCount(); - float[] lut = bc.getStepLUT(); - - for (int i = 0; i < segCount; i++) { - float t = i == segCount ? 1 : i * lut[i] / segCount; - t += 0.5f / segCount; - - Vec3 result = VecHelper.bezier(end1, end2, finish1, finish2, t); - Vec3 derivative = VecHelper.bezierDerivative(end1, end2, finish1, finish2, t) - .normalize(); - Vec3 faceNormal = - faceNormal1.equals(faceNormal2) ? faceNormal1 : VecHelper.slerp(t, faceNormal1, faceNormal2); - Vec3 normal = faceNormal.cross(derivative) - .normalize(); - Vec3 below = result.add(faceNormal.scale(-.25f)); - Vec3 rail1 = below.add(normal.scale(.05f)); - Vec3 rail2 = below.subtract(normal.scale(.05f)); - Vec3 railMiddle = rail1.add(rail2) - .scale(.5); - - for (Vec3 vec : new Vec3[] { railMiddle }) { - BlockPos pos = new BlockPos(vec); - Pair key = Pair.of(pos.getX(), pos.getZ()); - if (!yLevels.containsKey(key) || yLevels.get(key) > vec.y) - yLevels.put(key, vec.y); - } - } - - for (Entry, Double> entry : yLevels.entrySet()) { - double yValue = entry.getValue(); - int floor = Mth.floor(yValue); - BlockPos targetPos = new BlockPos(entry.getKey() - .getFirst(), floor, - entry.getKey() - .getSecond()); - targetPos = targetPos.offset(tePosition) - .above(1); - - BlockState stateAtPos = level.getBlockState(targetPos); - boolean present = AllBlocks.FAKE_TRACK.has(stateAtPos); - - if (remove) { - if (present) - level.removeBlock(targetPos, false); - continue; - } - - FluidState fluidState = stateAtPos.getFluidState(); - if (!fluidState.isEmpty() && !fluidState.isSourceOfType(Fluids.WATER)) - continue; - - if (!present && stateAtPos.getMaterial() - .isReplaceable()) - level.setBlock(targetPos, - ProperWaterloggedBlock.withWater(level, AllBlocks.FAKE_TRACK.getDefaultState(), targetPos), 3); - FakeTrackBlock.keepAlive(level, targetPos); - } - } - -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelBlock.java b/src/main/java/com/simibubi/create/content/logistics/tunnel/BeltTunnelBlock.java similarity index 85% rename from src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelBlock.java rename to src/main/java/com/simibubi/create/content/logistics/tunnel/BeltTunnelBlock.java index 0d5ea76a4..4c572e848 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/tunnel/BeltTunnelBlock.java @@ -1,14 +1,14 @@ -package com.simibubi.create.content.logistics.block.belts.tunnel; +package com.simibubi.create.content.logistics.tunnel; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.relays.belt.BeltBlock; -import com.simibubi.create.content.contraptions.relays.belt.BeltSlope; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; -import com.simibubi.create.content.logistics.block.funnel.BeltFunnelBlock; -import com.simibubi.create.foundation.block.ITE; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.content.kinetics.belt.BeltBlock; +import com.simibubi.create.content.kinetics.belt.BeltSlope; +import com.simibubi.create.content.kinetics.belt.behaviour.DirectBeltInputBehaviour; +import com.simibubi.create.content.logistics.funnel.BeltFunnelBlock; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld; @@ -36,7 +36,7 @@ import net.minecraft.world.level.block.state.properties.Property; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; -public class BeltTunnelBlock extends Block implements ITE, IWrenchable { +public class BeltTunnelBlock extends Block implements IBE, IWrenchable { public static final Property SHAPE = EnumProperty.create("shape", Shape.class); public static final Property HORIZONTAL_AXIS = BlockStateProperties.HORIZONTAL_AXIS; @@ -100,7 +100,7 @@ public class BeltTunnelBlock extends Block implements ITE, @Override public void onPlace(BlockState state, Level world, BlockPos pos, BlockState p_220082_4_, boolean p_220082_5_) { if (!(world instanceof WrappedWorld) && !world.isClientSide()) - withTileEntityDo(world, pos, BeltTunnelTileEntity::updateTunnelConnections); + withBlockEntityDo(world, pos, BeltTunnelBlockEntity::updateTunnelConnections); } @Override @@ -110,7 +110,7 @@ public class BeltTunnelBlock extends Block implements ITE, .isVertical()) return state; if (!(worldIn instanceof WrappedWorld) && !worldIn.isClientSide()) - withTileEntityDo(worldIn, currentPos, BeltTunnelTileEntity::updateTunnelConnections); + withBlockEntityDo(worldIn, currentPos, BeltTunnelBlockEntity::updateTunnelConnections); BlockState tunnelState = getTunnelState(worldIn, currentPos); if (tunnelState.getValue(HORIZONTAL_AXIS) == state.getValue(HORIZONTAL_AXIS)) { if (hasWindow(tunnelState) == hasWindow(state)) @@ -125,9 +125,9 @@ public class BeltTunnelBlock extends Block implements ITE, BlockState newTunnel = getTunnelState(world, pos); if (tunnel != newTunnel && !world.isClientSide()) { world.setBlock(pos, newTunnel, 3); - BlockEntity te = world.getBlockEntity(pos); - if (te != null && (te instanceof BeltTunnelTileEntity)) - ((BeltTunnelTileEntity) te).updateTunnelConnections(); + BlockEntity be = world.getBlockEntity(pos); + if (be != null && (be instanceof BeltTunnelBlockEntity)) + ((BeltTunnelBlockEntity) be).updateTunnelConnections(); } } @@ -185,7 +185,7 @@ public class BeltTunnelBlock extends Block implements ITE, return blockState.getValue(BeltBlock.HORIZONTAL_FACING) .getAxis() == side.getAxis(); DirectBeltInputBehaviour behaviour = - TileEntityBehaviour.get(world, pos.relative(side), DirectBeltInputBehaviour.TYPE); + BlockEntityBehaviour.get(world, pos.relative(side), DirectBeltInputBehaviour.TYPE); return behaviour != null && behaviour.canInsertFromSide(side); } @@ -232,13 +232,13 @@ public class BeltTunnelBlock extends Block implements ITE, } @Override - public Class getTileEntityClass() { - return BeltTunnelTileEntity.class; + public Class getBlockEntityClass() { + return BeltTunnelBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.ANDESITE_TUNNEL.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.ANDESITE_TUNNEL.get(); } } diff --git a/src/main/java/com/simibubi/create/content/logistics/tunnel/BeltTunnelBlockEntity.java b/src/main/java/com/simibubi/create/content/logistics/tunnel/BeltTunnelBlockEntity.java new file mode 100644 index 000000000..86ab58df7 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/tunnel/BeltTunnelBlockEntity.java @@ -0,0 +1,211 @@ +package com.simibubi.create.content.logistics.tunnel; + +import java.util.EnumMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.lang3.tuple.Pair; + +import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPackets; +import com.simibubi.create.content.logistics.funnel.BeltFunnelBlock; +import com.simibubi.create.content.logistics.tunnel.BeltTunnelBlock.Shape; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.IntTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.Tag; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; + +public class BeltTunnelBlockEntity extends SmartBlockEntity { + + public Map flaps; + public Set sides; + + protected LazyOptional cap = LazyOptional.empty(); + protected List> flapsToSend; + + public BeltTunnelBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + flaps = new EnumMap<>(Direction.class); + sides = new HashSet<>(); + flapsToSend = new LinkedList<>(); + } + + @Override + public void invalidate() { + super.invalidate(); + cap.invalidate(); + } + + protected void writeFlapsAndSides(CompoundTag compound) { + ListTag flapsNBT = new ListTag(); + for (Direction direction : flaps.keySet()) + flapsNBT.add(IntTag.valueOf(direction.get3DDataValue())); + compound.put("Flaps", flapsNBT); + + ListTag sidesNBT = new ListTag(); + for (Direction direction : sides) + sidesNBT.add(IntTag.valueOf(direction.get3DDataValue())); + compound.put("Sides", sidesNBT); + } + + @Override + public void writeSafe(CompoundTag tag) { + writeFlapsAndSides(tag); + super.writeSafe(tag); + } + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + writeFlapsAndSides(compound); + super.write(compound, clientPacket); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + Set newFlaps = new HashSet<>(6); + ListTag flapsNBT = compound.getList("Flaps", Tag.TAG_INT); + for (Tag inbt : flapsNBT) + if (inbt instanceof IntTag) + newFlaps.add(Direction.from3DDataValue(((IntTag) inbt).getAsInt())); + + sides.clear(); + ListTag sidesNBT = compound.getList("Sides", Tag.TAG_INT); + for (Tag inbt : sidesNBT) + if (inbt instanceof IntTag) + sides.add(Direction.from3DDataValue(((IntTag) inbt).getAsInt())); + + for (Direction d : Iterate.directions) + if (!newFlaps.contains(d)) + flaps.remove(d); + else if (!flaps.containsKey(d)) + flaps.put(d, createChasingFlap()); + + // Backwards compat + if (!compound.contains("Sides") && compound.contains("Flaps")) + sides.addAll(flaps.keySet()); + super.read(compound, clientPacket); + if (clientPacket) + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(this)); + } + + private LerpedFloat createChasingFlap() { + return LerpedFloat.linear() + .startWithValue(.25f) + .chase(0, .05f, Chaser.EXP); + } + + public void updateTunnelConnections() { + flaps.clear(); + sides.clear(); + BlockState tunnelState = getBlockState(); + for (Direction direction : Iterate.horizontalDirections) { + if (direction.getAxis() != tunnelState.getValue(BlockStateProperties.HORIZONTAL_AXIS)) { + boolean positive = + direction.getAxisDirection() == AxisDirection.POSITIVE ^ direction.getAxis() == Axis.Z; + Shape shape = tunnelState.getValue(BeltTunnelBlock.SHAPE); + if (BeltTunnelBlock.isStraight(tunnelState)) + continue; + if (positive && shape == Shape.T_LEFT) + continue; + if (!positive && shape == Shape.T_RIGHT) + continue; + } + + sides.add(direction); + + // Flap might be occluded + BlockState nextState = level.getBlockState(worldPosition.relative(direction)); + if (nextState.getBlock() instanceof BeltTunnelBlock) + continue; + if (nextState.getBlock() instanceof BeltFunnelBlock) + if (nextState.getValue(BeltFunnelBlock.SHAPE) == BeltFunnelBlock.Shape.EXTENDED + && nextState.getValue(BeltFunnelBlock.HORIZONTAL_FACING) == direction.getOpposite()) + continue; + + flaps.put(direction, createChasingFlap()); + } + sendData(); + } + + public void flap(Direction side, boolean inward) { + if (level.isClientSide) { + if (flaps.containsKey(side)) + flaps.get(side) + .setValue(inward ^ side.getAxis() == Axis.Z ? -1 : 1); + return; + } + + flapsToSend.add(Pair.of(side, inward)); + } + + @Override + public void initialize() { + super.initialize(); + updateTunnelConnections(); + } + + @Override + public void tick() { + super.tick(); + if (!level.isClientSide) { + if (!flapsToSend.isEmpty()) + sendFlaps(); + return; + } + flaps.forEach((d, value) -> value.tickChaser()); + } + + private void sendFlaps() { + AllPackets.getChannel().send(packetTarget(), new TunnelFlapPacket(this, flapsToSend)); + + flapsToSend.clear(); + } + + @Override + public void addBehaviours(List behaviours) {} + + @Override + public LazyOptional getCapability(Capability capability, Direction side) { + if (capability != CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) + return super.getCapability(capability, side); + + if (!this.cap.isPresent()) { + if (AllBlocks.BELT.has(level.getBlockState(worldPosition.below()))) { + BlockEntity teBelow = level.getBlockEntity(worldPosition.below()); + if (teBelow != null) { + T capBelow = teBelow.getCapability(capability, Direction.UP) + .orElse(null); + if (capBelow != null) { + cap = LazyOptional.of(() -> capBelow) + .cast(); + } + } + } + } + return this.cap.cast(); + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelInstance.java b/src/main/java/com/simibubi/create/content/logistics/tunnel/BeltTunnelInstance.java similarity index 82% rename from src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelInstance.java rename to src/main/java/com/simibubi/create/content/logistics/tunnel/BeltTunnelInstance.java index 67d5d7c00..ccbd7d4a0 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelInstance.java +++ b/src/main/java/com/simibubi/create/content/logistics/tunnel/BeltTunnelInstance.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.block.belts.tunnel; +package com.simibubi.create.content.logistics.tunnel; import java.util.ArrayList; import java.util.Collection; @@ -10,8 +10,8 @@ import com.jozufozu.flywheel.api.Instancer; import com.jozufozu.flywheel.api.MaterialManager; import com.jozufozu.flywheel.api.instance.DynamicInstance; import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.logistics.block.flap.FlapData; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.logistics.flwdata.FlapData; import com.simibubi.create.foundation.render.AllMaterialSpecs; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.animation.LerpedFloat; @@ -19,23 +19,23 @@ import com.simibubi.create.foundation.utility.animation.LerpedFloat; import net.minecraft.core.Direction; import net.minecraft.world.level.LightLayer; -public class BeltTunnelInstance extends BlockEntityInstance implements DynamicInstance { +public class BeltTunnelInstance extends BlockEntityInstance implements DynamicInstance { private final Map> tunnelFlaps; - public BeltTunnelInstance(MaterialManager modelManager, BeltTunnelTileEntity tile) { - super(modelManager, tile); + public BeltTunnelInstance(MaterialManager materialManager, BeltTunnelBlockEntity blockEntity) { + super(materialManager, blockEntity); tunnelFlaps = new EnumMap<>(Direction.class); - Instancer model = modelManager.defaultSolid() + Instancer model = materialManager.defaultSolid() .material(AllMaterialSpecs.FLAPS) - .getModel(AllBlockPartials.BELT_TUNNEL_FLAP, blockState); + .getModel(AllPartialModels.BELT_TUNNEL_FLAP, blockState); int blockLight = world.getBrightness(LightLayer.BLOCK, pos); int skyLight = world.getBrightness(LightLayer.SKY, pos); - tile.flaps.forEach((direction, flapValue) -> { + blockEntity.flaps.forEach((direction, flapValue) -> { float flapness = flapValue.getValue(AnimationTickHolder.getPartialTicks()); @@ -47,7 +47,7 @@ public class BeltTunnelInstance extends BlockEntityInstance { + + public BeltTunnelRenderer(BlockEntityRendererProvider.Context context) { + super(context); + } + + @Override + protected void renderSafe(BeltTunnelBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + super.renderSafe(be, partialTicks, ms, buffer, light, overlay); + + if (Backend.canUseInstancing(be.getLevel())) + return; + + SuperByteBuffer flapBuffer = CachedBufferer.partial(AllPartialModels.BELT_TUNNEL_FLAP, be.getBlockState()); + VertexConsumer vb = buffer.getBuffer(RenderType.solid()); + Vec3 pivot = VecHelper.voxelSpace(0, 10, 1f); + TransformStack msr = TransformStack.cast(ms); + + for (Direction direction : Iterate.directions) { + if (!be.flaps.containsKey(direction)) + continue; + + float horizontalAngle = AngleHelper.horizontalAngle(direction.getOpposite()); + float f = be.flaps.get(direction) + .getValue(partialTicks); + + ms.pushPose(); + msr.centre() + .rotateY(horizontalAngle) + .unCentre(); + + ms.translate(0.075f / 16f, 0, 0); + + for (int segment = 0; segment <= 3; segment++) { + ms.pushPose(); + float intensity = segment == 3 ? 1.5f : segment + 1; + float abs = Math.abs(f); + float flapAngle = Mth.sin((float) ((1 - abs) * Math.PI * intensity)) * 30 * f + * (direction.getAxis() == Axis.X ? 1 : -1); + if (f > 0) + flapAngle *= .5f; + + msr.translate(pivot) + .rotateX(flapAngle) + .translateBack(pivot); + flapBuffer.light(light) + .renderInto(ms, vb); + + ms.popPose(); + ms.translate(-3.05f / 16f, 0, 0); + } + ms.popPose(); + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelShapes.java b/src/main/java/com/simibubi/create/content/logistics/tunnel/BeltTunnelShapes.java similarity index 96% rename from src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelShapes.java rename to src/main/java/com/simibubi/create/content/logistics/tunnel/BeltTunnelShapes.java index f7e359aec..b1dc2f5d8 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelShapes.java +++ b/src/main/java/com/simibubi/create/content/logistics/tunnel/BeltTunnelShapes.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.block.belts.tunnel; +package com.simibubi.create.content.logistics.tunnel; import static net.minecraft.world.level.block.Block.box; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BrassTunnelBlock.java b/src/main/java/com/simibubi/create/content/logistics/tunnel/BrassTunnelBlock.java similarity index 80% rename from src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BrassTunnelBlock.java rename to src/main/java/com/simibubi/create/content/logistics/tunnel/BrassTunnelBlock.java index 7c9629055..5812add24 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BrassTunnelBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/tunnel/BrassTunnelBlock.java @@ -1,9 +1,9 @@ -package com.simibubi.create.content.logistics.block.belts.tunnel; +package com.simibubi.create.content.logistics.tunnel; import java.util.List; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.foundation.block.IBE; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -29,10 +29,10 @@ public class BrassTunnelBlock extends BeltTunnelBlock { @Override public InteractionResult use(BlockState p_225533_1_, Level world, BlockPos pos, Player player, InteractionHand p_225533_5_, BlockHitResult p_225533_6_) { - return onTileEntityUse(world, pos, te -> { - if (!(te instanceof BrassTunnelTileEntity)) + return onBlockEntityUse(world, pos, be -> { + if (!(be instanceof BrassTunnelBlockEntity)) return InteractionResult.PASS; - BrassTunnelTileEntity bte = (BrassTunnelTileEntity) te; + BrassTunnelBlockEntity bte = (BrassTunnelBlockEntity) be; List stacksOfGroup = bte.grabAllStacksOfGroup(world.isClientSide); if (stacksOfGroup.isEmpty()) return InteractionResult.PASS; @@ -47,8 +47,8 @@ public class BrassTunnelBlock extends BeltTunnelBlock { } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.BRASS_TUNNEL.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.BRASS_TUNNEL.get(); } @Override @@ -59,7 +59,7 @@ public class BrassTunnelBlock extends BeltTunnelBlock { @Override public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { - ITE.onRemove(state, level, pos, newState); + IBE.onRemove(state, level, pos, newState); } } diff --git a/src/main/java/com/simibubi/create/content/logistics/tunnel/BrassTunnelBlockEntity.java b/src/main/java/com/simibubi/create/content/logistics/tunnel/BrassTunnelBlockEntity.java new file mode 100644 index 000000000..b2f248fea --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/tunnel/BrassTunnelBlockEntity.java @@ -0,0 +1,805 @@ +package com.simibubi.create.content.logistics.tunnel; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Random; +import java.util.Set; + +import javax.annotation.Nullable; + +import org.apache.commons.lang3.tuple.Pair; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.equipment.goggles.IHaveGoggleInformation; +import com.simibubi.create.content.kinetics.belt.BeltBlockEntity; +import com.simibubi.create.content.kinetics.belt.BeltHelper; +import com.simibubi.create.content.kinetics.belt.behaviour.DirectBeltInputBehaviour; +import com.simibubi.create.content.logistics.funnel.BeltFunnelBlock; +import com.simibubi.create.content.logistics.funnel.BeltFunnelBlock.Shape; +import com.simibubi.create.content.logistics.funnel.FunnelBlock; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.SidedFilteringBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.INamedIconOptions; +import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollOptionBehaviour; +import com.simibubi.create.foundation.gui.AllIcons; +import com.simibubi.create.foundation.utility.BlockHelper; +import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.Couple; +import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.NBTHelper; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.minecraft.ChatFormatting; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemHandlerHelper; + +public class BrassTunnelBlockEntity extends BeltTunnelBlockEntity implements IHaveGoggleInformation { + + SidedFilteringBehaviour filtering; + + boolean connectedLeft; + boolean connectedRight; + + ItemStack stackToDistribute; + Direction stackEnteredFrom; + + float distributionProgress; + int distributionDistanceLeft; + int distributionDistanceRight; + int previousOutputIndex; + + // + Couple>> distributionTargets; + + private boolean syncedOutputActive; + private Set syncSet; + + protected ScrollOptionBehaviour selectionMode; + private LazyOptional beltCapability; + private LazyOptional tunnelCapability; + + public BrassTunnelBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + distributionTargets = Couple.create(ArrayList::new); + syncSet = new HashSet<>(); + stackToDistribute = ItemStack.EMPTY; + stackEnteredFrom = null; + beltCapability = LazyOptional.empty(); + tunnelCapability = LazyOptional.of(() -> new BrassTunnelItemHandler(this)); + previousOutputIndex = 0; + syncedOutputActive = false; + } + + @Override + public void addBehaviours(List behaviours) { + super.addBehaviours(behaviours); + behaviours.add(selectionMode = new ScrollOptionBehaviour<>(SelectionMode.class, + Lang.translateDirect("logistics.when_multiple_outputs_available"), this, new BrassTunnelModeSlot())); + + selectionMode.onlyActiveWhen(this::hasDistributionBehaviour); + + // Propagate settings across connected tunnels + selectionMode.withCallback(setting -> { + for (boolean side : Iterate.trueAndFalse) { + if (!isConnected(side)) + continue; + BrassTunnelBlockEntity adjacent = getAdjacent(side); + if (adjacent != null) + adjacent.selectionMode.setValue(setting); + } + }); + } + + @Override + public void tick() { + super.tick(); + BeltBlockEntity beltBelow = BeltHelper.getSegmentBE(level, worldPosition.below()); + + if (distributionProgress > 0) + distributionProgress--; + if (beltBelow == null || beltBelow.getSpeed() == 0) + return; + if (stackToDistribute.isEmpty() && !syncedOutputActive) + return; + if (level.isClientSide && !isVirtual()) + return; + + if (distributionProgress == -1) { + distributionTargets.forEach(List::clear); + distributionDistanceLeft = 0; + distributionDistanceRight = 0; + + syncSet.clear(); + List> validOutputs = gatherValidOutputs(); + if (selectionMode.get() == SelectionMode.SYNCHRONIZE) { + boolean allEmpty = true; + boolean allFull = true; + for (BrassTunnelBlockEntity be : syncSet) { + boolean hasStack = !be.stackToDistribute.isEmpty(); + allEmpty &= !hasStack; + allFull &= hasStack; + } + final boolean notifySyncedOut = !allEmpty; + if (allFull || allEmpty) + syncSet.forEach(be -> be.syncedOutputActive = notifySyncedOut); + } + + if (validOutputs == null) + return; + if (stackToDistribute.isEmpty()) + return; + + for (Pair pair : validOutputs) { + BrassTunnelBlockEntity tunnel = pair.getKey(); + Direction output = pair.getValue(); + if (insertIntoTunnel(tunnel, output, stackToDistribute, true) == null) + continue; + distributionTargets.get(!tunnel.flapFilterEmpty(output)) + .add(Pair.of(tunnel.worldPosition, output)); + int distance = tunnel.worldPosition.getX() + tunnel.worldPosition.getZ() - worldPosition.getX() + - worldPosition.getZ(); + if (distance < 0) + distributionDistanceLeft = Math.max(distributionDistanceLeft, -distance); + else + distributionDistanceRight = Math.max(distributionDistanceRight, distance); + } + + if (distributionTargets.getFirst() + .isEmpty() + && distributionTargets.getSecond() + .isEmpty()) + return; + + if (selectionMode.get() != SelectionMode.SYNCHRONIZE || syncedOutputActive) { + distributionProgress = AllConfigs.server().logistics.brassTunnelTimer.get(); + sendData(); + } + return; + } + + if (distributionProgress != 0) + return; + + distributionTargets.forEach(list -> { + if (stackToDistribute.isEmpty()) + return; + List> validTargets = new ArrayList<>(); + for (Pair pair : list) { + BlockPos tunnelPos = pair.getKey(); + Direction output = pair.getValue(); + if (tunnelPos.equals(worldPosition) && output == stackEnteredFrom) + continue; + BlockEntity be = level.getBlockEntity(tunnelPos); + if (!(be instanceof BrassTunnelBlockEntity)) + continue; + validTargets.add(Pair.of((BrassTunnelBlockEntity) be, output)); + } + distribute(validTargets); + distributionProgress = -1; + }); + } + + private static Random rand = new Random(); + private static Map, ItemStack> distributed = new IdentityHashMap<>(); + private static Set> full = new HashSet<>(); + + private void distribute(List> validTargets) { + int amountTargets = validTargets.size(); + if (amountTargets == 0) + return; + + distributed.clear(); + full.clear(); + + int indexStart = previousOutputIndex % amountTargets; + SelectionMode mode = selectionMode.get(); + boolean force = mode == SelectionMode.FORCED_ROUND_ROBIN || mode == SelectionMode.FORCED_SPLIT; + boolean split = mode == SelectionMode.FORCED_SPLIT || mode == SelectionMode.SPLIT; + boolean robin = mode == SelectionMode.FORCED_ROUND_ROBIN || mode == SelectionMode.ROUND_ROBIN; + + if (mode == SelectionMode.RANDOMIZE) + indexStart = rand.nextInt(amountTargets); + if (mode == SelectionMode.PREFER_NEAREST || mode == SelectionMode.SYNCHRONIZE) + indexStart = 0; + + ItemStack toDistribute = stackToDistribute.copy(); + for (boolean distributeAgain : Iterate.trueAndFalse) { + ItemStack toDistributeThisCycle = null; + int remainingOutputs = amountTargets; + int leftovers = 0; + + for (boolean simulate : Iterate.trueAndFalse) { + if (remainingOutputs == 0) + break; + + leftovers = 0; + int index = indexStart; + int stackSize = toDistribute.getCount(); + int splitStackSize = stackSize / remainingOutputs; + int splitRemainder = stackSize % remainingOutputs; + int visited = 0; + + toDistributeThisCycle = toDistribute.copy(); + if (!(force || split) && simulate) + continue; + + while (visited < amountTargets) { + Pair pair = validTargets.get(index); + BrassTunnelBlockEntity tunnel = pair.getKey(); + Direction side = pair.getValue(); + index = (index + 1) % amountTargets; + visited++; + + if (full.contains(pair)) { + if (split && simulate) + remainingOutputs--; + continue; + } + + int count = split ? splitStackSize + (splitRemainder > 0 ? 1 : 0) : stackSize; + ItemStack toOutput = ItemHandlerHelper.copyStackWithSize(toDistributeThisCycle, count); + + // Grow by 1 to determine if target is full even after a successful transfer + boolean testWithIncreasedCount = distributed.containsKey(pair); + int increasedCount = testWithIncreasedCount ? distributed.get(pair) + .getCount() : 0; + if (testWithIncreasedCount) + toOutput.grow(increasedCount); + + ItemStack remainder = insertIntoTunnel(tunnel, side, toOutput, true); + + if (remainder == null || remainder.getCount() == (testWithIncreasedCount ? count + 1 : count)) { + if (force) + return; + if (split && simulate) + remainingOutputs--; + if (!simulate) + full.add(pair); + if (robin) + break; + continue; + } else if (!remainder.isEmpty() && !simulate) { + full.add(pair); + } + + if (!simulate) { + toOutput.shrink(remainder.getCount()); + distributed.put(pair, toOutput); + } + + leftovers += remainder.getCount(); + toDistributeThisCycle.shrink(count); + if (toDistributeThisCycle.isEmpty()) + break; + splitRemainder--; + if (!split) + break; + } + } + + toDistribute.setCount(toDistributeThisCycle.getCount() + leftovers); + if (leftovers == 0 && distributeAgain) + break; + if (!split) + break; + } + + int failedTransferrals = 0; + for (Entry, ItemStack> entry : distributed.entrySet()) { + Pair pair = entry.getKey(); + failedTransferrals += insertIntoTunnel(pair.getKey(), pair.getValue(), entry.getValue(), false).getCount(); + } + + toDistribute.grow(failedTransferrals); + stackToDistribute = ItemHandlerHelper.copyStackWithSize(stackToDistribute, toDistribute.getCount()); + if (stackToDistribute.isEmpty()) + stackEnteredFrom = null; + previousOutputIndex++; + previousOutputIndex %= amountTargets; + notifyUpdate(); + } + + public void setStackToDistribute(ItemStack stack, @Nullable Direction enteredFrom) { + stackToDistribute = stack; + stackEnteredFrom = enteredFrom; + distributionProgress = -1; + sendData(); + setChanged(); + } + + public ItemStack getStackToDistribute() { + return stackToDistribute; + } + + public List grabAllStacksOfGroup(boolean simulate) { + List list = new ArrayList<>(); + + ItemStack own = getStackToDistribute(); + if (!own.isEmpty()) { + list.add(own); + if (!simulate) + setStackToDistribute(ItemStack.EMPTY, null); + } + + for (boolean left : Iterate.trueAndFalse) { + BrassTunnelBlockEntity adjacent = this; + while (adjacent != null) { + if (!level.isLoaded(adjacent.getBlockPos())) + return null; + adjacent = adjacent.getAdjacent(left); + if (adjacent == null) + continue; + ItemStack other = adjacent.getStackToDistribute(); + if (other.isEmpty()) + continue; + list.add(other); + if (!simulate) + adjacent.setStackToDistribute(ItemStack.EMPTY, null); + } + } + + return list; + } + + @Nullable + protected ItemStack insertIntoTunnel(BrassTunnelBlockEntity tunnel, Direction side, ItemStack stack, + boolean simulate) { + if (stack.isEmpty()) + return stack; + if (!tunnel.testFlapFilter(side, stack)) + return null; + + BeltBlockEntity below = BeltHelper.getSegmentBE(level, tunnel.worldPosition.below()); + if (below == null) + return null; + BlockPos offset = tunnel.getBlockPos() + .below() + .relative(side); + DirectBeltInputBehaviour sideOutput = BlockEntityBehaviour.get(level, offset, DirectBeltInputBehaviour.TYPE); + if (sideOutput != null) { + if (!sideOutput.canInsertFromSide(side)) + return null; + ItemStack result = sideOutput.handleInsertion(stack, side, simulate); + if (result.isEmpty() && !simulate) + tunnel.flap(side, false); + return result; + } + + Direction movementFacing = below.getMovementFacing(); + if (side == movementFacing) + if (!BlockHelper.hasBlockSolidSide(level.getBlockState(offset), level, offset, side.getOpposite())) { + BeltBlockEntity controllerBE = below.getControllerBE(); + if (controllerBE == null) + return null; + + if (!simulate) { + tunnel.flap(side, true); + ItemStack ejected = stack; + float beltMovementSpeed = below.getDirectionAwareBeltMovementSpeed(); + float movementSpeed = Math.max(Math.abs(beltMovementSpeed), 1 / 8f); + int additionalOffset = beltMovementSpeed > 0 ? 1 : 0; + Vec3 outPos = BeltHelper.getVectorForOffset(controllerBE, below.index + additionalOffset); + Vec3 outMotion = Vec3.atLowerCornerOf(side.getNormal()) + .scale(movementSpeed) + .add(0, 1 / 8f, 0); + outPos.add(outMotion.normalize()); + ItemEntity entity = new ItemEntity(level, outPos.x, outPos.y + 6 / 16f, outPos.z, ejected); + entity.setDeltaMovement(outMotion); + entity.setDefaultPickUpDelay(); + entity.hurtMarked = true; + level.addFreshEntity(entity); + } + + return ItemStack.EMPTY; + } + + return null; + } + + public boolean testFlapFilter(Direction side, ItemStack stack) { + if (filtering == null) + return false; + if (filtering.get(side) == null) { + FilteringBehaviour adjacentFilter = + BlockEntityBehaviour.get(level, worldPosition.relative(side), FilteringBehaviour.TYPE); + if (adjacentFilter == null) + return true; + return adjacentFilter.test(stack); + } + return filtering.test(side, stack); + } + + public boolean flapFilterEmpty(Direction side) { + if (filtering == null) + return false; + if (filtering.get(side) == null) { + FilteringBehaviour adjacentFilter = + BlockEntityBehaviour.get(level, worldPosition.relative(side), FilteringBehaviour.TYPE); + if (adjacentFilter == null) + return true; + return adjacentFilter.getFilter() + .isEmpty(); + } + return filtering.getFilter(side) + .isEmpty(); + } + + @Override + public void initialize() { + if (filtering == null) { + filtering = createSidedFilter(); + attachBehaviourLate(filtering); + } + super.initialize(); + } + + public boolean canInsert(Direction side, ItemStack stack) { + if (filtering != null && !filtering.test(side, stack)) + return false; + if (!hasDistributionBehaviour()) + return true; + if (!stackToDistribute.isEmpty()) + return false; + return true; + } + + public boolean hasDistributionBehaviour() { + if (flaps.isEmpty()) + return false; + if (connectedLeft || connectedRight) + return true; + BlockState blockState = getBlockState(); + if (!AllBlocks.BRASS_TUNNEL.has(blockState)) + return false; + Axis axis = blockState.getValue(BrassTunnelBlock.HORIZONTAL_AXIS); + for (Direction direction : flaps.keySet()) + if (direction.getAxis() != axis) + return true; + return false; + } + + private List> gatherValidOutputs() { + List> validOutputs = new ArrayList<>(); + boolean synchronize = selectionMode.get() == SelectionMode.SYNCHRONIZE; + addValidOutputsOf(this, validOutputs); + + for (boolean left : Iterate.trueAndFalse) { + BrassTunnelBlockEntity adjacent = this; + while (adjacent != null) { + if (!level.isLoaded(adjacent.getBlockPos())) + return null; + adjacent = adjacent.getAdjacent(left); + if (adjacent == null) + continue; + addValidOutputsOf(adjacent, validOutputs); + } + } + + if (!syncedOutputActive && synchronize) + return null; + return validOutputs; + } + + private void addValidOutputsOf(BrassTunnelBlockEntity tunnelBE, + List> validOutputs) { + syncSet.add(tunnelBE); + BeltBlockEntity below = BeltHelper.getSegmentBE(level, tunnelBE.worldPosition.below()); + if (below == null) + return; + Direction movementFacing = below.getMovementFacing(); + BlockState blockState = getBlockState(); + if (!AllBlocks.BRASS_TUNNEL.has(blockState)) + return; + + boolean prioritizeSides = tunnelBE == this; + + for (boolean sidePass : Iterate.trueAndFalse) { + if (!prioritizeSides && sidePass) + continue; + for (Direction direction : Iterate.horizontalDirections) { + if (direction == movementFacing && below.getSpeed() == 0) + continue; + if (prioritizeSides && sidePass == (direction.getAxis() == movementFacing.getAxis())) + continue; + if (direction == movementFacing.getOpposite()) + continue; + if (!tunnelBE.sides.contains(direction)) + continue; + + BlockPos offset = tunnelBE.worldPosition.below() + .relative(direction); + + BlockState potentialFunnel = level.getBlockState(offset.above()); + if (potentialFunnel.getBlock() instanceof BeltFunnelBlock + && potentialFunnel.getValue(BeltFunnelBlock.SHAPE) == Shape.PULLING + && FunnelBlock.getFunnelFacing(potentialFunnel) == direction) + continue; + + DirectBeltInputBehaviour inputBehaviour = + BlockEntityBehaviour.get(level, offset, DirectBeltInputBehaviour.TYPE); + if (inputBehaviour == null) { + if (direction == movementFacing) + if (!BlockHelper.hasBlockSolidSide(level.getBlockState(offset), level, offset, + direction.getOpposite())) + validOutputs.add(Pair.of(tunnelBE, direction)); + continue; + } + if (inputBehaviour.canInsertFromSide(direction)) + validOutputs.add(Pair.of(tunnelBE, direction)); + continue; + } + } + } + + @Override + public void addBehavioursDeferred(List behaviours) { + super.addBehavioursDeferred(behaviours); + filtering = createSidedFilter(); + behaviours.add(filtering); + } + + protected SidedFilteringBehaviour createSidedFilter() { + return new SidedFilteringBehaviour(this, new BrassTunnelFilterSlot(), this::makeFilter, + this::isValidFaceForFilter); + } + + private FilteringBehaviour makeFilter(Direction side, FilteringBehaviour filter) { + return filter; + } + + private boolean isValidFaceForFilter(Direction side) { + return sides.contains(side); + } + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + compound.putBoolean("SyncedOutput", syncedOutputActive); + compound.putBoolean("ConnectedLeft", connectedLeft); + compound.putBoolean("ConnectedRight", connectedRight); + + compound.put("StackToDistribute", stackToDistribute.serializeNBT()); + if (stackEnteredFrom != null) + NBTHelper.writeEnum(compound, "StackEnteredFrom", stackEnteredFrom); + + compound.putFloat("DistributionProgress", distributionProgress); + compound.putInt("PreviousIndex", previousOutputIndex); + compound.putInt("DistanceLeft", distributionDistanceLeft); + compound.putInt("DistanceRight", distributionDistanceRight); + + for (boolean filtered : Iterate.trueAndFalse) { + compound.put(filtered ? "FilteredTargets" : "Targets", + NBTHelper.writeCompoundList(distributionTargets.get(filtered), pair -> { + CompoundTag nbt = new CompoundTag(); + nbt.put("Pos", NbtUtils.writeBlockPos(pair.getKey())); + nbt.putInt("Face", pair.getValue() + .get3DDataValue()); + return nbt; + })); + } + + super.write(compound, clientPacket); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + boolean wasConnectedLeft = connectedLeft; + boolean wasConnectedRight = connectedRight; + + syncedOutputActive = compound.getBoolean("SyncedOutput"); + connectedLeft = compound.getBoolean("ConnectedLeft"); + connectedRight = compound.getBoolean("ConnectedRight"); + + stackToDistribute = ItemStack.of(compound.getCompound("StackToDistribute")); + stackEnteredFrom = + compound.contains("StackEnteredFrom") ? NBTHelper.readEnum(compound, "StackEnteredFrom", Direction.class) + : null; + + distributionProgress = compound.getFloat("DistributionProgress"); + previousOutputIndex = compound.getInt("PreviousIndex"); + distributionDistanceLeft = compound.getInt("DistanceLeft"); + distributionDistanceRight = compound.getInt("DistanceRight"); + + for (boolean filtered : Iterate.trueAndFalse) { + distributionTargets.set(filtered, NBTHelper + .readCompoundList(compound.getList(filtered ? "FilteredTargets" : "Targets", Tag.TAG_COMPOUND), nbt -> { + BlockPos pos = NbtUtils.readBlockPos(nbt.getCompound("Pos")); + Direction face = Direction.from3DDataValue(nbt.getInt("Face")); + return Pair.of(pos, face); + })); + } + + super.read(compound, clientPacket); + + if (!clientPacket) + return; + if (wasConnectedLeft != connectedLeft || wasConnectedRight != connectedRight) { + requestModelDataUpdate(); + if (hasLevel()) + level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 16); + } + filtering.updateFilterPresence(); + } + + public boolean isConnected(boolean leftSide) { + return leftSide ? connectedLeft : connectedRight; + } + + @Override + public void updateTunnelConnections() { + super.updateTunnelConnections(); + boolean connectivityChanged = false; + boolean nowConnectedLeft = determineIfConnected(true); + boolean nowConnectedRight = determineIfConnected(false); + + if (connectedLeft != nowConnectedLeft) { + connectedLeft = nowConnectedLeft; + connectivityChanged = true; + BrassTunnelBlockEntity adjacent = getAdjacent(true); + if (adjacent != null && !level.isClientSide) { + adjacent.updateTunnelConnections(); + adjacent.selectionMode.setValue(selectionMode.getValue()); + } + } + + if (connectedRight != nowConnectedRight) { + connectedRight = nowConnectedRight; + connectivityChanged = true; + BrassTunnelBlockEntity adjacent = getAdjacent(false); + if (adjacent != null && !level.isClientSide) { + adjacent.updateTunnelConnections(); + adjacent.selectionMode.setValue(selectionMode.getValue()); + } + } + + if (filtering != null) + filtering.updateFilterPresence(); + if (connectivityChanged) + sendData(); + } + + protected boolean determineIfConnected(boolean leftSide) { + if (flaps.isEmpty()) + return false; + BrassTunnelBlockEntity adjacentTunnelBE = getAdjacent(leftSide); + return adjacentTunnelBE != null && !adjacentTunnelBE.flaps.isEmpty(); + } + + @Nullable + protected BrassTunnelBlockEntity getAdjacent(boolean leftSide) { + if (!hasLevel()) + return null; + + BlockState blockState = getBlockState(); + if (!AllBlocks.BRASS_TUNNEL.has(blockState)) + return null; + + Axis axis = blockState.getValue(BrassTunnelBlock.HORIZONTAL_AXIS); + Direction baseDirection = Direction.get(AxisDirection.POSITIVE, axis); + Direction direction = leftSide ? baseDirection.getCounterClockWise() : baseDirection.getClockWise(); + BlockPos adjacentPos = worldPosition.relative(direction); + BlockState adjacentBlockState = level.getBlockState(adjacentPos); + + if (!AllBlocks.BRASS_TUNNEL.has(adjacentBlockState)) + return null; + if (adjacentBlockState.getValue(BrassTunnelBlock.HORIZONTAL_AXIS) != axis) + return null; + BlockEntity adjacentBE = level.getBlockEntity(adjacentPos); + if (adjacentBE.isRemoved()) + return null; + if (!(adjacentBE instanceof BrassTunnelBlockEntity)) + return null; + return (BrassTunnelBlockEntity) adjacentBE; + } + + @Override + public void invalidate() { + super.invalidate(); + tunnelCapability.invalidate(); + } + + @Override + public void destroy() { + super.destroy(); + Block.popResource(level, worldPosition, stackToDistribute); + stackEnteredFrom = null; + } + + @Override + public LazyOptional getCapability(Capability capability, Direction side) { + if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) + return tunnelCapability.cast(); + return super.getCapability(capability, side); + } + + public LazyOptional getBeltCapability() { + if (!beltCapability.isPresent()) { + BlockEntity blockEntity = level.getBlockEntity(worldPosition.below()); + if (blockEntity != null) + beltCapability = blockEntity.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY); + } + return beltCapability; + } + + public enum SelectionMode implements INamedIconOptions { + SPLIT(AllIcons.I_TUNNEL_SPLIT), + FORCED_SPLIT(AllIcons.I_TUNNEL_FORCED_SPLIT), + ROUND_ROBIN(AllIcons.I_TUNNEL_ROUND_ROBIN), + FORCED_ROUND_ROBIN(AllIcons.I_TUNNEL_FORCED_ROUND_ROBIN), + PREFER_NEAREST(AllIcons.I_TUNNEL_PREFER_NEAREST), + RANDOMIZE(AllIcons.I_TUNNEL_RANDOMIZE), + SYNCHRONIZE(AllIcons.I_TUNNEL_SYNCHRONIZE), + + ; + + private final String translationKey; + private final AllIcons icon; + + SelectionMode(AllIcons icon) { + this.icon = icon; + this.translationKey = "tunnel.selection_mode." + Lang.asId(name()); + } + + @Override + public AllIcons getIcon() { + return icon; + } + + @Override + public String getTranslationKey() { + return translationKey; + } + } + + public boolean canTakeItems() { + return stackToDistribute.isEmpty() && !syncedOutputActive; + } + + @Override + public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { + List allStacks = grabAllStacksOfGroup(true); + if (allStacks.isEmpty()) + return false; + + tooltip.add(componentSpacing.plainCopy() + .append(Lang.translateDirect("tooltip.brass_tunnel.contains")) + .withStyle(ChatFormatting.WHITE)); + for (ItemStack item : allStacks) { + tooltip.add(componentSpacing.plainCopy() + .append(Lang.translateDirect("tooltip.brass_tunnel.contains_entry", + Components.translatable(item.getDescriptionId()) + .getString(), + item.getCount())) + .withStyle(ChatFormatting.GRAY)); + } + tooltip.add(componentSpacing.plainCopy() + .append(Lang.translateDirect("tooltip.brass_tunnel.retrieve")) + .withStyle(ChatFormatting.DARK_GRAY)); + + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/tunnel/BrassTunnelCTBehaviour.java b/src/main/java/com/simibubi/create/content/logistics/tunnel/BrassTunnelCTBehaviour.java new file mode 100644 index 000000000..7004a7c86 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/tunnel/BrassTunnelCTBehaviour.java @@ -0,0 +1,50 @@ +package com.simibubi.create.content.logistics.tunnel; + +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.AllSpriteShifts; +import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry; +import com.simibubi.create.foundation.block.connected.CTType; +import com.simibubi.create.foundation.block.connected.ConnectedTextureBehaviour; + +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.state.BlockState; + +public class BrassTunnelCTBehaviour extends ConnectedTextureBehaviour.Base { + + @Override + public @Nullable CTType getDataType(BlockAndTintGetter world, BlockPos pos, BlockState state, Direction direction) { + if (!(world.getBlockEntity(pos) instanceof BrassTunnelBlockEntity tunnelBE) + || !tunnelBE.hasDistributionBehaviour()) + return null; + return super.getDataType(world, pos, state, direction); + } + + @Override + public CTSpriteShiftEntry getShift(BlockState state, Direction direction, @Nullable TextureAtlasSprite sprite) { + return direction == Direction.UP ? AllSpriteShifts.BRASS_TUNNEL_TOP : null; + } + + @Override + protected boolean reverseUVs(BlockState state, Direction face) { + return true; + } + + @Override + public boolean connectsTo(BlockState state, BlockState other, BlockAndTintGetter reader, BlockPos pos, + BlockPos otherPos, Direction face) { + int yDiff = otherPos.getY() - pos.getY(); + int zDiff = otherPos.getZ() - pos.getZ(); + if (yDiff != 0) + return false; + + if (!(reader.getBlockEntity(pos) instanceof BrassTunnelBlockEntity tunnelBE)) + return false; + boolean leftSide = zDiff > 0; + return tunnelBE.isConnected(leftSide); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/tunnel/BrassTunnelFilterSlot.java b/src/main/java/com/simibubi/create/content/logistics/tunnel/BrassTunnelFilterSlot.java new file mode 100644 index 000000000..1c32b74d8 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/tunnel/BrassTunnelFilterSlot.java @@ -0,0 +1,15 @@ +package com.simibubi.create.content.logistics.tunnel; + +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.world.phys.Vec3; + +public class BrassTunnelFilterSlot extends ValueBoxTransform.Sided { + + @Override + protected Vec3 getSouthLocation() { + return VecHelper.voxelSpace(8, 13, 15.5f); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/tunnel/BrassTunnelItemHandler.java b/src/main/java/com/simibubi/create/content/logistics/tunnel/BrassTunnelItemHandler.java new file mode 100644 index 000000000..430755c50 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/tunnel/BrassTunnelItemHandler.java @@ -0,0 +1,59 @@ +package com.simibubi.create.content.logistics.tunnel; + +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.items.IItemHandler; + +public class BrassTunnelItemHandler implements IItemHandler { + + private BrassTunnelBlockEntity blockEntity; + + public BrassTunnelItemHandler(BrassTunnelBlockEntity be) { + this.blockEntity = be; + } + + @Override + public int getSlots() { + return 1; + } + + @Override + public ItemStack getStackInSlot(int slot) { + return blockEntity.stackToDistribute; + } + + @Override + public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) { + if (!blockEntity.hasDistributionBehaviour()) { + LazyOptional beltCapability = blockEntity.getBeltCapability(); + if (!beltCapability.isPresent()) + return stack; + return beltCapability.orElse(null).insertItem(slot, stack, simulate); + } + + if (!blockEntity.canTakeItems()) + return stack; + if (!simulate) + blockEntity.setStackToDistribute(stack, null); + return ItemStack.EMPTY; + } + + @Override + public ItemStack extractItem(int slot, int amount, boolean simulate) { + LazyOptional beltCapability = blockEntity.getBeltCapability(); + if (!beltCapability.isPresent()) + return ItemStack.EMPTY; + return beltCapability.orElse(null).extractItem(slot, amount, simulate); + } + + @Override + public int getSlotLimit(int slot) { + return blockEntity.stackToDistribute.isEmpty() ? 64 : blockEntity.stackToDistribute.getMaxStackSize(); + } + + @Override + public boolean isItemValid(int slot, ItemStack stack) { + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/tunnel/BrassTunnelModeSlot.java b/src/main/java/com/simibubi/create/content/logistics/tunnel/BrassTunnelModeSlot.java new file mode 100644 index 000000000..0b07a36c5 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/tunnel/BrassTunnelModeSlot.java @@ -0,0 +1,18 @@ +package com.simibubi.create.content.logistics.tunnel; + +import com.simibubi.create.foundation.blockEntity.behaviour.CenteredSideValueBoxTransform; + +import net.minecraft.core.Direction; + +public class BrassTunnelModeSlot extends CenteredSideValueBoxTransform { + + public BrassTunnelModeSlot() { + super((state, d) -> d == Direction.UP); + } + + @Override + public int getOverrideColor() { + return 0x592424; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/tunnel/TunnelFlapPacket.java b/src/main/java/com/simibubi/create/content/logistics/tunnel/TunnelFlapPacket.java new file mode 100644 index 000000000..1cfe8db70 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/tunnel/TunnelFlapPacket.java @@ -0,0 +1,54 @@ +package com.simibubi.create.content.logistics.tunnel; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang3.tuple.Pair; + +import com.simibubi.create.foundation.networking.BlockEntityDataPacket; + +import net.minecraft.core.Direction; +import net.minecraft.network.FriendlyByteBuf; + +public class TunnelFlapPacket extends BlockEntityDataPacket { + + private List> flaps; + + public TunnelFlapPacket(FriendlyByteBuf buffer) { + super(buffer); + + byte size = buffer.readByte(); + + this.flaps = new ArrayList<>(size); + + for (int i = 0; i < size; i++) { + Direction direction = Direction.from3DDataValue(buffer.readByte()); + boolean inwards = buffer.readBoolean(); + + flaps.add(Pair.of(direction, inwards)); + } + } + + public TunnelFlapPacket(BeltTunnelBlockEntity blockEntity, List> flaps) { + super(blockEntity.getBlockPos()); + + this.flaps = new ArrayList<>(flaps); + } + + @Override + protected void writeData(FriendlyByteBuf buffer) { + buffer.writeByte(flaps.size()); + + for (Pair flap : flaps) { + buffer.writeByte(flap.getLeft().get3DDataValue()); + buffer.writeBoolean(flap.getRight()); + } + } + + @Override + protected void handlePacket(BeltTunnelBlockEntity blockEntity) { + for (Pair flap : flaps) { + blockEntity.flap(flap.getLeft(), flap.getRight()); + } + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/vault/ItemVaultBlock.java b/src/main/java/com/simibubi/create/content/logistics/vault/ItemVaultBlock.java similarity index 84% rename from src/main/java/com/simibubi/create/content/logistics/block/vault/ItemVaultBlock.java rename to src/main/java/com/simibubi/create/content/logistics/vault/ItemVaultBlock.java index f7cdb74ea..134d6f0e0 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/vault/ItemVaultBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/vault/ItemVaultBlock.java @@ -1,12 +1,12 @@ -package com.simibubi.create.content.logistics.block.vault; +package com.simibubi.create.content.logistics.vault; import javax.annotation.Nullable; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllTileEntities; import com.simibubi.create.api.connectivity.ConnectivityHandler; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.item.ItemHelper; import net.minecraft.core.BlockPos; @@ -34,7 +34,7 @@ import net.minecraft.world.level.block.state.properties.Property; import net.minecraftforge.common.util.ForgeSoundType; import net.minecraftforge.items.CapabilityItemHandler; -public class ItemVaultBlock extends Block implements IWrenchable, ITE { +public class ItemVaultBlock extends Block implements IWrenchable, IBE { public static final Property HORIZONTAL_AXIS = BlockStateProperties.HORIZONTAL_AXIS; public static final BooleanProperty LARGE = BooleanProperty.create("large"); @@ -74,7 +74,7 @@ public class ItemVaultBlock extends Block implements IWrenchable, ITE vte.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)) .map(lo -> lo.map(ItemHelper::calcRedstoneFromInventory) .orElse(0)) @@ -167,12 +167,12 @@ public class ItemVaultBlock extends Block implements IWrenchable, ITE getTileEntityType() { - return AllTileEntities.ITEM_VAULT.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.ITEM_VAULT.get(); } @Override - public Class getTileEntityClass() { - return ItemVaultTileEntity.class; + public Class getBlockEntityClass() { + return ItemVaultBlockEntity.class; } } diff --git a/src/main/java/com/simibubi/create/content/logistics/vault/ItemVaultBlockEntity.java b/src/main/java/com/simibubi/create/content/logistics/vault/ItemVaultBlockEntity.java new file mode 100644 index 000000000..9127bc91d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/vault/ItemVaultBlockEntity.java @@ -0,0 +1,312 @@ +package com.simibubi.create.content.logistics.vault; + +import java.util.List; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.api.connectivity.ConnectivityHandler; +import com.simibubi.create.foundation.blockEntity.IMultiBlockEntityContainer; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.ItemStackHandler; +import net.minecraftforge.items.wrapper.CombinedInvWrapper; + +public class ItemVaultBlockEntity extends SmartBlockEntity implements IMultiBlockEntityContainer.Inventory { + + protected LazyOptional itemCapability; + + protected ItemStackHandler inventory; + protected BlockPos controller; + protected BlockPos lastKnownPos; + protected boolean updateConnectivity; + protected int radius; + protected int length; + protected Axis axis; + + public ItemVaultBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + + inventory = new ItemStackHandler(AllConfigs.server().logistics.vaultCapacity.get()) { + @Override + protected void onContentsChanged(int slot) { + super.onContentsChanged(slot); + updateComparators(); + } + }; + + itemCapability = LazyOptional.empty(); + radius = 1; + length = 1; + } + + @Override + public void addBehaviours(List behaviours) {} + + protected void updateConnectivity() { + updateConnectivity = false; + if (level.isClientSide()) + return; + if (!isController()) + return; + ConnectivityHandler.formMulti(this); + } + + protected void updateComparators() { + ItemVaultBlockEntity controllerBE = getControllerBE(); + if (controllerBE == null) + return; + + level.blockEntityChanged(controllerBE.worldPosition); + + BlockPos pos = controllerBE.getBlockPos(); + for (int y = 0; y < controllerBE.radius; y++) { + for (int z = 0; z < (controllerBE.axis == Axis.X ? controllerBE.radius : controllerBE.length); z++) { + for (int x = 0; x < (controllerBE.axis == Axis.Z ? controllerBE.radius : controllerBE.length); x++) { + level.updateNeighbourForOutputSignal(pos.offset(x, y, z), getBlockState().getBlock()); + } + } + } + } + + @Override + public void tick() { + super.tick(); + + if (lastKnownPos == null) + lastKnownPos = getBlockPos(); + else if (!lastKnownPos.equals(worldPosition) && worldPosition != null) { + onPositionChanged(); + return; + } + + if (updateConnectivity) + updateConnectivity(); + } + + @Override + public BlockPos getLastKnownPos() { + return lastKnownPos; + } + + @Override + public boolean isController() { + return controller == null || worldPosition.getX() == controller.getX() + && worldPosition.getY() == controller.getY() && worldPosition.getZ() == controller.getZ(); + } + + private void onPositionChanged() { + removeController(true); + lastKnownPos = worldPosition; + } + + @SuppressWarnings("unchecked") + @Override + public ItemVaultBlockEntity getControllerBE() { + if (isController()) + return this; + BlockEntity blockEntity = level.getBlockEntity(controller); + if (blockEntity instanceof ItemVaultBlockEntity) + return (ItemVaultBlockEntity) blockEntity; + return null; + } + + public void removeController(boolean keepContents) { + if (level.isClientSide()) + return; + updateConnectivity = true; + controller = null; + radius = 1; + length = 1; + + BlockState state = getBlockState(); + if (ItemVaultBlock.isVault(state)) { + state = state.setValue(ItemVaultBlock.LARGE, false); + getLevel().setBlock(worldPosition, state, 22); + } + + itemCapability.invalidate(); + setChanged(); + sendData(); + } + + @Override + public void setController(BlockPos controller) { + if (level.isClientSide && !isVirtual()) + return; + if (controller.equals(this.controller)) + return; + this.controller = controller; + itemCapability.invalidate(); + setChanged(); + sendData(); + } + + @Override + public BlockPos getController() { + return isController() ? worldPosition : controller; + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + super.read(compound, clientPacket); + + BlockPos controllerBefore = controller; + int prevSize = radius; + int prevLength = length; + + updateConnectivity = compound.contains("Uninitialized"); + controller = null; + lastKnownPos = null; + + if (compound.contains("LastKnownPos")) + lastKnownPos = NbtUtils.readBlockPos(compound.getCompound("LastKnownPos")); + if (compound.contains("Controller")) + controller = NbtUtils.readBlockPos(compound.getCompound("Controller")); + + if (isController()) { + radius = compound.getInt("Size"); + length = compound.getInt("Length"); + } + + if (!clientPacket) { + inventory.deserializeNBT(compound.getCompound("Inventory")); + return; + } + + boolean changeOfController = + controllerBefore == null ? controller != null : !controllerBefore.equals(controller); + if (hasLevel() && (changeOfController || prevSize != radius || prevLength != length)) + level.setBlocksDirty(getBlockPos(), Blocks.AIR.defaultBlockState(), getBlockState()); + } + + @Override + protected void write(CompoundTag compound, boolean clientPacket) { + if (updateConnectivity) + compound.putBoolean("Uninitialized", true); + if (lastKnownPos != null) + compound.put("LastKnownPos", NbtUtils.writeBlockPos(lastKnownPos)); + if (!isController()) + compound.put("Controller", NbtUtils.writeBlockPos(controller)); + if (isController()) { + compound.putInt("Size", radius); + compound.putInt("Length", length); + } + + super.write(compound, clientPacket); + + if (!clientPacket) { + compound.putString("StorageType", "CombinedInv"); + compound.put("Inventory", inventory.serializeNBT()); + } + } + + public ItemStackHandler getInventoryOfBlock() { + return inventory; + } + + public void applyInventoryToBlock(ItemStackHandler handler) { + for (int i = 0; i < inventory.getSlots(); i++) + inventory.setStackInSlot(i, i < handler.getSlots() ? handler.getStackInSlot(i) : ItemStack.EMPTY); + } + + @Override + public LazyOptional getCapability(Capability cap, Direction side) { + if (isItemHandlerCap(cap)) { + initCapability(); + return itemCapability.cast(); + } + return super.getCapability(cap, side); + } + + private void initCapability() { + if (itemCapability.isPresent()) + return; + if (!isController()) { + ItemVaultBlockEntity controllerBE = getControllerBE(); + if (controllerBE == null) + return; + controllerBE.initCapability(); + itemCapability = controllerBE.itemCapability; + return; + } + + boolean alongZ = ItemVaultBlock.getVaultBlockAxis(getBlockState()) == Axis.Z; + IItemHandlerModifiable[] invs = new IItemHandlerModifiable[length * radius * radius]; + for (int yOffset = 0; yOffset < length; yOffset++) { + for (int xOffset = 0; xOffset < radius; xOffset++) { + for (int zOffset = 0; zOffset < radius; zOffset++) { + BlockPos vaultPos = alongZ ? worldPosition.offset(xOffset, zOffset, yOffset) + : worldPosition.offset(yOffset, xOffset, zOffset); + ItemVaultBlockEntity vaultAt = + ConnectivityHandler.partAt(AllBlockEntityTypes.ITEM_VAULT.get(), level, vaultPos); + invs[yOffset * radius * radius + xOffset * radius + zOffset] = + vaultAt != null ? vaultAt.inventory : new ItemStackHandler(); + } + } + } + + CombinedInvWrapper combinedInvWrapper = new CombinedInvWrapper(invs); + itemCapability = LazyOptional.of(() -> combinedInvWrapper); + } + + public static int getMaxLength(int radius) { + return radius * 3; + } + + @Override + public void preventConnectivityUpdate() { updateConnectivity = false; } + + @Override + public void notifyMultiUpdated() { + BlockState state = this.getBlockState(); + if (ItemVaultBlock.isVault(state)) { // safety + level.setBlock(getBlockPos(), state.setValue(ItemVaultBlock.LARGE, radius > 2), 6); + } + itemCapability.invalidate(); + setChanged(); + } + + @Override + public Direction.Axis getMainConnectionAxis() { return getMainAxisOf(this); } + + @Override + public int getMaxLength(Direction.Axis longAxis, int width) { + if (longAxis == Direction.Axis.Y) return getMaxWidth(); + return getMaxLength(width); + } + + @Override + public int getMaxWidth() { + return 3; + } + + @Override + public int getHeight() { return length; } + + @Override + public int getWidth() { return radius; } + + @Override + public void setHeight(int height) { this.length = height; } + + @Override + public void setWidth(int width) { this.radius = width; } + + @Override + public boolean hasInventory() { return true; } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/vault/ItemVaultCTBehaviour.java b/src/main/java/com/simibubi/create/content/logistics/vault/ItemVaultCTBehaviour.java similarity index 98% rename from src/main/java/com/simibubi/create/content/logistics/block/vault/ItemVaultCTBehaviour.java rename to src/main/java/com/simibubi/create/content/logistics/vault/ItemVaultCTBehaviour.java index 808876277..d46b26616 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/vault/ItemVaultCTBehaviour.java +++ b/src/main/java/com/simibubi/create/content/logistics/vault/ItemVaultCTBehaviour.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.block.vault; +package com.simibubi.create.content.logistics.vault; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/vault/ItemVaultItem.java b/src/main/java/com/simibubi/create/content/logistics/vault/ItemVaultItem.java similarity index 89% rename from src/main/java/com/simibubi/create/content/logistics/block/vault/ItemVaultItem.java rename to src/main/java/com/simibubi/create/content/logistics/vault/ItemVaultItem.java index fdd76e9bd..4c29eaa5f 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/vault/ItemVaultItem.java +++ b/src/main/java/com/simibubi/create/content/logistics/vault/ItemVaultItem.java @@ -1,6 +1,6 @@ -package com.simibubi.create.content.logistics.block.vault; +package com.simibubi.create.content.logistics.vault; -import com.simibubi.create.AllTileEntities; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.api.connectivity.ConnectivityHandler; import com.simibubi.create.foundation.utility.VecHelper; @@ -65,14 +65,14 @@ public class ItemVaultItem extends BlockItem { if (!ItemVaultBlock.isVault(placedOnState)) return; - ItemVaultTileEntity tankAt = ConnectivityHandler.partAt(AllTileEntities.ITEM_VAULT.get(), world, placedOnPos); + ItemVaultBlockEntity tankAt = ConnectivityHandler.partAt(AllBlockEntityTypes.ITEM_VAULT.get(), world, placedOnPos); if (tankAt == null) return; - ItemVaultTileEntity controllerTE = tankAt.getControllerTE(); - if (controllerTE == null) + ItemVaultBlockEntity controllerBE = tankAt.getControllerBE(); + if (controllerBE == null) return; - int width = controllerTE.radius; + int width = controllerBE.radius; if (width == 1) return; @@ -84,10 +84,10 @@ public class ItemVaultItem extends BlockItem { return; Direction vaultFacing = Direction.fromAxisAndDirection(vaultBlockAxis, AxisDirection.POSITIVE); - BlockPos startPos = face == vaultFacing.getOpposite() ? controllerTE.getBlockPos() + BlockPos startPos = face == vaultFacing.getOpposite() ? controllerBE.getBlockPos() .relative(vaultFacing.getOpposite()) - : controllerTE.getBlockPos() - .relative(vaultFacing, controllerTE.length); + : controllerBE.getBlockPos() + .relative(vaultFacing, controllerBE.length); if (VecHelper.getCoordinate(startPos, vaultBlockAxis) != VecHelper.getCoordinate(pos, vaultBlockAxis)) return; diff --git a/src/main/java/com/simibubi/create/content/materials/ExperienceBlock.java b/src/main/java/com/simibubi/create/content/materials/ExperienceBlock.java new file mode 100644 index 000000000..442deccce --- /dev/null +++ b/src/main/java/com/simibubi/create/content/materials/ExperienceBlock.java @@ -0,0 +1,29 @@ +package com.simibubi.create.content.materials; + +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class ExperienceBlock extends Block { + + public ExperienceBlock(Properties pProperties) { + super(pProperties); + } + + @Override + public void animateTick(BlockState pState, Level pLevel, BlockPos pPos, RandomSource pRand) { + if (pRand.nextInt(5) != 0) + return; + Vec3 vec3 = VecHelper.clampComponentWise(VecHelper.offsetRandomly(Vec3.ZERO, pRand, .75f), .55f) + .add(VecHelper.getCenterOf(pPos)); + pLevel.addParticle(ParticleTypes.END_ROD, vec3.x, vec3.y, vec3.z, pRand.nextGaussian() * 0.005D, + pRand.nextGaussian() * 0.005D, pRand.nextGaussian() * 0.005D); + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/ExperienceNuggetItem.java b/src/main/java/com/simibubi/create/content/materials/ExperienceNuggetItem.java similarity index 97% rename from src/main/java/com/simibubi/create/content/curiosities/ExperienceNuggetItem.java rename to src/main/java/com/simibubi/create/content/materials/ExperienceNuggetItem.java index 4407cbd7b..3ac078117 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/ExperienceNuggetItem.java +++ b/src/main/java/com/simibubi/create/content/materials/ExperienceNuggetItem.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities; +package com.simibubi.create.content.materials; import com.simibubi.create.foundation.utility.VecHelper; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/AssemblyOperatorBlockItem.java b/src/main/java/com/simibubi/create/content/processing/AssemblyOperatorBlockItem.java similarity index 90% rename from src/main/java/com/simibubi/create/content/contraptions/components/AssemblyOperatorBlockItem.java rename to src/main/java/com/simibubi/create/content/processing/AssemblyOperatorBlockItem.java index c7e4d65db..0538cb5f6 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/AssemblyOperatorBlockItem.java +++ b/src/main/java/com/simibubi/create/content/processing/AssemblyOperatorBlockItem.java @@ -1,8 +1,8 @@ -package com.simibubi.create.content.contraptions.components; +package com.simibubi.create.content.processing; import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.relays.belt.BeltBlock; -import com.simibubi.create.content.contraptions.relays.belt.BeltSlope; +import com.simibubi.create.content.kinetics.belt.BeltBlock; +import com.simibubi.create.content.kinetics.belt.BeltSlope; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/AssemblyOperatorUseContext.java b/src/main/java/com/simibubi/create/content/processing/AssemblyOperatorUseContext.java similarity index 91% rename from src/main/java/com/simibubi/create/content/contraptions/components/AssemblyOperatorUseContext.java rename to src/main/java/com/simibubi/create/content/processing/AssemblyOperatorUseContext.java index 38a66bb7b..6115a9274 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/AssemblyOperatorUseContext.java +++ b/src/main/java/com/simibubi/create/content/processing/AssemblyOperatorUseContext.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components; +package com.simibubi.create.content.processing; import javax.annotation.Nullable; diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/BasinBlock.java b/src/main/java/com/simibubi/create/content/processing/basin/BasinBlock.java similarity index 75% rename from src/main/java/com/simibubi/create/content/contraptions/processing/BasinBlock.java rename to src/main/java/com/simibubi/create/content/processing/basin/BasinBlock.java index cbae94b8f..941cd5a99 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/BasinBlock.java +++ b/src/main/java/com/simibubi/create/content/processing/basin/BasinBlock.java @@ -1,18 +1,19 @@ -package com.simibubi.create.content.contraptions.processing; +package com.simibubi.create.content.processing.basin; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; import com.simibubi.create.Create; -import com.simibubi.create.content.contraptions.fluids.actors.GenericItemFilling; -import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; -import com.simibubi.create.content.logistics.block.funnel.FunnelBlock; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.content.fluids.transfer.GenericItemEmptying; +import com.simibubi.create.content.fluids.transfer.GenericItemFilling; +import com.simibubi.create.content.kinetics.belt.BeltBlockEntity; +import com.simibubi.create.content.kinetics.belt.behaviour.DirectBeltInputBehaviour; +import com.simibubi.create.content.logistics.funnel.FunnelBlock; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.fluid.FluidHelper; import com.simibubi.create.foundation.item.ItemHelper; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -48,7 +49,7 @@ import net.minecraftforge.items.IItemHandlerModifiable; import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.items.ItemStackHandler; -public class BasinBlock extends Block implements ITE, IWrenchable { +public class BasinBlock extends Block implements IBE, IWrenchable { public static final DirectionProperty FACING = BlockStateProperties.FACING_HOPPER; @@ -64,8 +65,8 @@ public class BasinBlock extends Block implements ITE, IWrenchab @Override public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) { - BlockEntity tileEntity = world.getBlockEntity(pos.above()); - if (tileEntity instanceof BasinOperatingTileEntity) + BlockEntity blockEntity = world.getBlockEntity(pos.above()); + if (blockEntity instanceof BasinOperatingBlockEntity) return false; return true; } @@ -73,7 +74,7 @@ public class BasinBlock extends Block implements ITE, IWrenchab @Override public InteractionResult onWrenched(BlockState state, UseOnContext context) { if (!context.getLevel().isClientSide) - withTileEntityDo(context.getLevel(), context.getClickedPos(), + withBlockEntityDo(context.getLevel(), context.getClickedPos(), bte -> bte.onWrenched(context.getClickedFace())); return InteractionResult.SUCCESS; } @@ -83,19 +84,19 @@ public class BasinBlock extends Block implements ITE, IWrenchab BlockHitResult hit) { ItemStack heldItem = player.getItemInHand(handIn); - return onTileEntityUse(worldIn, pos, te -> { + return onBlockEntityUse(worldIn, pos, be -> { if (!heldItem.isEmpty()) { - if (FluidHelper.tryEmptyItemIntoTE(worldIn, player, handIn, heldItem, te)) + if (FluidHelper.tryEmptyItemIntoBE(worldIn, player, handIn, heldItem, be)) return InteractionResult.SUCCESS; - if (FluidHelper.tryFillItemFromTE(worldIn, player, handIn, heldItem, te)) + if (FluidHelper.tryFillItemFromBE(worldIn, player, handIn, heldItem, be)) return InteractionResult.SUCCESS; - if (EmptyingByBasin.canItemBeEmptied(worldIn, heldItem) + if (GenericItemEmptying.canItemBeEmptied(worldIn, heldItem) || GenericItemFilling.canItemBeFilled(worldIn, heldItem)) return InteractionResult.SUCCESS; if (heldItem.getItem() .equals(Items.SPONGE) - && !te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) + && !be.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) .map(iFluidHandler -> iFluidHandler.drain(Integer.MAX_VALUE, IFluidHandler.FluidAction.EXECUTE)) .orElse(FluidStack.EMPTY) .isEmpty()) { @@ -104,7 +105,7 @@ public class BasinBlock extends Block implements ITE, IWrenchab return InteractionResult.PASS; } - IItemHandlerModifiable inv = te.itemCapability.orElse(new ItemStackHandler(1)); + IItemHandlerModifiable inv = be.itemCapability.orElse(new ItemStackHandler(1)); boolean success = false; for (int slot = 0; slot < inv.getSlots(); slot++) { ItemStack stackInSlot = inv.getStackInSlot(slot); @@ -118,7 +119,7 @@ public class BasinBlock extends Block implements ITE, IWrenchab if (success) worldIn.playSound(null, pos, SoundEvents.ITEM_PICKUP, SoundSource.PLAYERS, .2f, 1f + Create.RANDOM.nextFloat()); - te.onEmptied(); + be.onEmptied(); return InteractionResult.SUCCESS; }); } @@ -133,13 +134,13 @@ public class BasinBlock extends Block implements ITE, IWrenchab if (!entityIn.isAlive()) return; ItemEntity itemEntity = (ItemEntity) entityIn; - withTileEntityDo(worldIn, entityIn.blockPosition(), te -> { + withBlockEntityDo(worldIn, entityIn.blockPosition(), be -> { // Tossed items bypass the quarter-stack limit - te.inputInventory.withMaxStackSize(64); - ItemStack insertItem = ItemHandlerHelper.insertItem(te.inputInventory, itemEntity.getItem() + be.inputInventory.withMaxStackSize(64); + ItemStack insertItem = ItemHandlerHelper.insertItem(be.inputInventory, itemEntity.getItem() .copy(), false); - te.inputInventory.withMaxStackSize(16); + be.inputInventory.withMaxStackSize(16); if (insertItem.isEmpty()) { itemEntity.discard(); @@ -169,7 +170,7 @@ public class BasinBlock extends Block implements ITE, IWrenchab @Override public void onRemove(BlockState state, Level worldIn, BlockPos pos, BlockState newState, boolean isMoving) { - ITE.onRemove(state, worldIn, pos, newState); + IBE.onRemove(state, worldIn, pos, newState); } @Override @@ -179,19 +180,19 @@ public class BasinBlock extends Block implements ITE, IWrenchab @Override public int getAnalogOutputSignal(BlockState blockState, Level worldIn, BlockPos pos) { - return getTileEntityOptional(worldIn, pos).map(BasinTileEntity::getInputInventory) + return getBlockEntityOptional(worldIn, pos).map(BasinBlockEntity::getInputInventory) .map(ItemHelper::calcRedstoneFromInventory) .orElse(0); } @Override - public Class getTileEntityClass() { - return BasinTileEntity.class; + public Class getBlockEntityClass() { + return BasinBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.BASIN.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.BASIN.get(); } public static boolean canOutputTo(BlockGetter world, BlockPos basinPos, Direction direction) { @@ -206,15 +207,15 @@ public class BasinBlock extends Block implements ITE, IWrenchab .isEmpty()) { return false; } else { - BlockEntity tileEntity = world.getBlockEntity(output); - if (tileEntity instanceof BeltTileEntity) { - BeltTileEntity belt = (BeltTileEntity) tileEntity; + BlockEntity blockEntity = world.getBlockEntity(output); + if (blockEntity instanceof BeltBlockEntity) { + BeltBlockEntity belt = (BeltBlockEntity) blockEntity; return belt.getSpeed() == 0 || belt.getMovementFacing() != direction.getOpposite(); } } DirectBeltInputBehaviour directBeltInputBehaviour = - TileEntityBehaviour.get(world, output, DirectBeltInputBehaviour.TYPE); + BlockEntityBehaviour.get(world, output, DirectBeltInputBehaviour.TYPE); if (directBeltInputBehaviour != null) return directBeltInputBehaviour.canInsertFromSide(direction); return false; diff --git a/src/main/java/com/simibubi/create/content/processing/basin/BasinBlockEntity.java b/src/main/java/com/simibubi/create/content/processing/basin/BasinBlockEntity.java new file mode 100644 index 000000000..a8aa3c9a2 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/processing/basin/BasinBlockEntity.java @@ -0,0 +1,796 @@ +package com.simibubi.create.content.processing.basin; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Optional; + +import javax.annotation.Nonnull; + +import com.google.common.collect.ImmutableList; +import com.simibubi.create.AllParticleTypes; +import com.simibubi.create.AllTags; +import com.simibubi.create.content.equipment.goggles.IHaveGoggleInformation; +import com.simibubi.create.content.fluids.FluidFX; +import com.simibubi.create.content.fluids.particle.FluidParticleData; +import com.simibubi.create.content.kinetics.belt.behaviour.DirectBeltInputBehaviour; +import com.simibubi.create.content.kinetics.mixer.MechanicalMixerBlockEntity; +import com.simibubi.create.content.processing.burner.BlazeBurnerBlock; +import com.simibubi.create.content.processing.burner.BlazeBurnerBlock.HeatLevel; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.fluid.SmartFluidTankBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.fluid.SmartFluidTankBehaviour.TankSegment; +import com.simibubi.create.foundation.blockEntity.behaviour.inventory.InvManipulationBehaviour; +import com.simibubi.create.foundation.fluid.CombinedTankWrapper; +import com.simibubi.create.foundation.item.ItemHelper; +import com.simibubi.create.foundation.item.SmartInventory; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.Couple; +import com.simibubi.create.foundation.utility.IntAttached; +import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.LangBuilder; +import com.simibubi.create.foundation.utility.NBTHelper; +import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; + +import net.minecraft.ChatFormatting; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.particles.ParticleOptions; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.StringTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.Component; +import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction; +import net.minecraftforge.fluids.capability.templates.FluidTank; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.ItemHandlerHelper; +import net.minecraftforge.items.ItemStackHandler; +import net.minecraftforge.items.wrapper.CombinedInvWrapper; + +public class BasinBlockEntity extends SmartBlockEntity implements IHaveGoggleInformation { + + private boolean areFluidsMoving; + LerpedFloat ingredientRotationSpeed; + LerpedFloat ingredientRotation; + + public BasinInventory inputInventory; + public SmartFluidTankBehaviour inputTank; + protected SmartInventory outputInventory; + protected SmartFluidTankBehaviour outputTank; + private FilteringBehaviour filtering; + private boolean contentsChanged; + + private Couple invs; + private Couple tanks; + + protected LazyOptional itemCapability; + protected LazyOptional fluidCapability; + + List disabledSpoutputs; + Direction preferredSpoutput; + protected List spoutputBuffer; + protected List spoutputFluidBuffer; + int recipeBackupCheck; + + public static final int OUTPUT_ANIMATION_TIME = 10; + List> visualizedOutputItems; + List> visualizedOutputFluids; + + public BasinBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + inputInventory = new BasinInventory(9, this); + inputInventory.whenContentsChanged($ -> contentsChanged = true); + outputInventory = new BasinInventory(9, this).forbidInsertion() + .withMaxStackSize(64); + areFluidsMoving = false; + itemCapability = LazyOptional.of(() -> new CombinedInvWrapper(inputInventory, outputInventory)); + contentsChanged = true; + ingredientRotation = LerpedFloat.angular() + .startWithValue(0); + ingredientRotationSpeed = LerpedFloat.linear() + .startWithValue(0); + + invs = Couple.create(inputInventory, outputInventory); + tanks = Couple.create(inputTank, outputTank); + visualizedOutputItems = Collections.synchronizedList(new ArrayList<>()); + visualizedOutputFluids = Collections.synchronizedList(new ArrayList<>()); + disabledSpoutputs = new ArrayList<>(); + preferredSpoutput = null; + spoutputBuffer = new ArrayList<>(); + spoutputFluidBuffer = new ArrayList<>(); + recipeBackupCheck = 20; + } + + @Override + public void addBehaviours(List behaviours) { + behaviours.add(new DirectBeltInputBehaviour(this)); + filtering = new FilteringBehaviour(this, new BasinValueBox()).withCallback(newFilter -> contentsChanged = true) + .forRecipes(); + behaviours.add(filtering); + + inputTank = new SmartFluidTankBehaviour(SmartFluidTankBehaviour.INPUT, this, 2, 1000, true) + .whenFluidUpdates(() -> contentsChanged = true); + outputTank = new SmartFluidTankBehaviour(SmartFluidTankBehaviour.OUTPUT, this, 2, 1000, true) + .whenFluidUpdates(() -> contentsChanged = true) + .forbidInsertion(); + behaviours.add(inputTank); + behaviours.add(outputTank); + + fluidCapability = LazyOptional.of(() -> { + LazyOptional inputCap = inputTank.getCapability(); + LazyOptional outputCap = outputTank.getCapability(); + return new CombinedTankWrapper(outputCap.orElse(null), inputCap.orElse(null)); + }); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + super.read(compound, clientPacket); + inputInventory.deserializeNBT(compound.getCompound("InputItems")); + outputInventory.deserializeNBT(compound.getCompound("OutputItems")); + + preferredSpoutput = null; + if (compound.contains("PreferredSpoutput")) + preferredSpoutput = NBTHelper.readEnum(compound, "PreferredSpoutput", Direction.class); + disabledSpoutputs.clear(); + ListTag disabledList = compound.getList("DisabledSpoutput", Tag.TAG_STRING); + disabledList.forEach(d -> disabledSpoutputs.add(Direction.valueOf(((StringTag) d).getAsString()))); + spoutputBuffer = NBTHelper.readItemList(compound.getList("Overflow", Tag.TAG_COMPOUND)); + spoutputFluidBuffer = NBTHelper.readCompoundList(compound.getList("FluidOverflow", Tag.TAG_COMPOUND), + FluidStack::loadFluidStackFromNBT); + + if (!clientPacket) + return; + + NBTHelper.iterateCompoundList(compound.getList("VisualizedItems", Tag.TAG_COMPOUND), + c -> visualizedOutputItems.add(IntAttached.with(OUTPUT_ANIMATION_TIME, ItemStack.of(c)))); + NBTHelper.iterateCompoundList(compound.getList("VisualizedFluids", Tag.TAG_COMPOUND), + c -> visualizedOutputFluids + .add(IntAttached.with(OUTPUT_ANIMATION_TIME, FluidStack.loadFluidStackFromNBT(c)))); + } + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + super.write(compound, clientPacket); + compound.put("InputItems", inputInventory.serializeNBT()); + compound.put("OutputItems", outputInventory.serializeNBT()); + + if (preferredSpoutput != null) + NBTHelper.writeEnum(compound, "PreferredSpoutput", preferredSpoutput); + ListTag disabledList = new ListTag(); + disabledSpoutputs.forEach(d -> disabledList.add(StringTag.valueOf(d.name()))); + compound.put("DisabledSpoutput", disabledList); + compound.put("Overflow", NBTHelper.writeItemList(spoutputBuffer)); + compound.put("FluidOverflow", + NBTHelper.writeCompoundList(spoutputFluidBuffer, fs -> fs.writeToNBT(new CompoundTag()))); + + if (!clientPacket) + return; + + compound.put("VisualizedItems", NBTHelper.writeCompoundList(visualizedOutputItems, ia -> ia.getValue() + .serializeNBT())); + compound.put("VisualizedFluids", NBTHelper.writeCompoundList(visualizedOutputFluids, ia -> ia.getValue() + .writeToNBT(new CompoundTag()))); + visualizedOutputItems.clear(); + visualizedOutputFluids.clear(); + } + + @Override + public void destroy() { + super.destroy(); + ItemHelper.dropContents(level, worldPosition, inputInventory); + ItemHelper.dropContents(level, worldPosition, outputInventory); + spoutputBuffer.forEach(is -> Block.popResource(level, worldPosition, is)); + } + + @Override + public void remove() { + super.remove(); + onEmptied(); + } + + public void onEmptied() { + getOperator().ifPresent(be -> be.basinRemoved = true); + } + + @Override + public void invalidate() { + super.invalidate(); + itemCapability.invalidate(); + fluidCapability.invalidate(); + } + + @Nonnull + @Override + public LazyOptional getCapability(@Nonnull Capability cap, Direction side) { + if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) + return itemCapability.cast(); + if (cap == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) + return fluidCapability.cast(); + return super.getCapability(cap, side); + } + + @Override + public void notifyUpdate() { + super.notifyUpdate(); + } + + @Override + public void lazyTick() { + super.lazyTick(); + + if (!level.isClientSide) { + updateSpoutput(); + if (recipeBackupCheck-- > 0) + return; + recipeBackupCheck = 20; + if (isEmpty()) + return; + notifyChangeOfContents(); + return; + } + + BlockEntity blockEntity = level.getBlockEntity(worldPosition.above(2)); + if (!(blockEntity instanceof MechanicalMixerBlockEntity)) { + setAreFluidsMoving(false); + return; + } + + MechanicalMixerBlockEntity mixer = (MechanicalMixerBlockEntity) blockEntity; + setAreFluidsMoving(mixer.running && mixer.runningTicks <= 20); + } + + public boolean isEmpty() { + return inputInventory.isEmpty() && outputInventory.isEmpty() && inputTank.isEmpty() && outputTank.isEmpty(); + } + + public void onWrenched(Direction face) { + BlockState blockState = getBlockState(); + Direction currentFacing = blockState.getValue(BasinBlock.FACING); + + disabledSpoutputs.remove(face); + if (currentFacing == face) { + if (preferredSpoutput == face) + preferredSpoutput = null; + disabledSpoutputs.add(face); + } else + preferredSpoutput = face; + + updateSpoutput(); + } + + private void updateSpoutput() { + BlockState blockState = getBlockState(); + Direction currentFacing = blockState.getValue(BasinBlock.FACING); + Direction newFacing = Direction.DOWN; + for (Direction test : Iterate.horizontalDirections) { + boolean canOutputTo = BasinBlock.canOutputTo(level, worldPosition, test); + if (canOutputTo && !disabledSpoutputs.contains(test)) + newFacing = test; + } + + if (preferredSpoutput != null && BasinBlock.canOutputTo(level, worldPosition, preferredSpoutput) + && preferredSpoutput != Direction.UP) + newFacing = preferredSpoutput; + + if (newFacing == currentFacing) + return; + + level.setBlockAndUpdate(worldPosition, blockState.setValue(BasinBlock.FACING, newFacing)); + + if (newFacing.getAxis() + .isVertical()) + return; + + for (int slot = 0; slot < outputInventory.getSlots(); slot++) { + ItemStack extractItem = outputInventory.extractItem(slot, 64, true); + if (extractItem.isEmpty()) + continue; + if (acceptOutputs(ImmutableList.of(extractItem), Collections.emptyList(), true)) + acceptOutputs(ImmutableList.of(outputInventory.extractItem(slot, 64, false)), Collections.emptyList(), + false); + } + + IFluidHandler handler = outputTank.getCapability() + .orElse(null); + for (int slot = 0; slot < handler.getTanks(); slot++) { + FluidStack fs = handler.getFluidInTank(slot) + .copy(); + if (fs.isEmpty()) + continue; + if (acceptOutputs(Collections.emptyList(), ImmutableList.of(fs), true)) { + handler.drain(fs, FluidAction.EXECUTE); + acceptOutputs(Collections.emptyList(), ImmutableList.of(fs), false); + } + } + + notifyChangeOfContents(); + notifyUpdate(); + } + + @Override + public void tick() { + super.tick(); + if (level.isClientSide) { + createFluidParticles(); + tickVisualizedOutputs(); + ingredientRotationSpeed.tickChaser(); + ingredientRotation.setValue(ingredientRotation.getValue() + ingredientRotationSpeed.getValue()); + } + + if ((!spoutputBuffer.isEmpty() || !spoutputFluidBuffer.isEmpty()) && !level.isClientSide) + tryClearingSpoutputOverflow(); + if (!contentsChanged) + return; + + contentsChanged = false; + getOperator().ifPresent(be -> be.basinChecker.scheduleUpdate()); + + for (Direction offset : Iterate.horizontalDirections) { + BlockPos toUpdate = worldPosition.above() + .relative(offset); + BlockState stateToUpdate = level.getBlockState(toUpdate); + if (stateToUpdate.getBlock() instanceof BasinBlock + && stateToUpdate.getValue(BasinBlock.FACING) == offset.getOpposite()) { + BlockEntity be = level.getBlockEntity(toUpdate); + if (be instanceof BasinBlockEntity) + ((BasinBlockEntity) be).contentsChanged = true; + } + } + } + + private void tryClearingSpoutputOverflow() { + BlockState blockState = getBlockState(); + if (!(blockState.getBlock() instanceof BasinBlock)) + return; + Direction direction = blockState.getValue(BasinBlock.FACING); + BlockEntity be = level.getBlockEntity(worldPosition.below() + .relative(direction)); + + FilteringBehaviour filter = null; + InvManipulationBehaviour inserter = null; + if (be != null) { + filter = BlockEntityBehaviour.get(level, be.getBlockPos(), FilteringBehaviour.TYPE); + inserter = BlockEntityBehaviour.get(level, be.getBlockPos(), InvManipulationBehaviour.TYPE); + } + + IItemHandler targetInv = be == null ? null + : be.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, direction.getOpposite()) + .orElse(inserter == null ? null : inserter.getInventory()); + + IFluidHandler targetTank = be == null ? null + : be.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, direction.getOpposite()) + .orElse(null); + + boolean update = false; + + for (Iterator iterator = spoutputBuffer.iterator(); iterator.hasNext();) { + ItemStack itemStack = iterator.next(); + + if (direction == Direction.DOWN) { + Block.popResource(level, worldPosition, itemStack); + iterator.remove(); + update = true; + continue; + } + + if (targetInv == null) + break; + if (!ItemHandlerHelper.insertItemStacked(targetInv, itemStack, true) + .isEmpty()) + continue; + if (filter != null && !filter.test(itemStack)) + continue; + + update = true; + ItemHandlerHelper.insertItemStacked(targetInv, itemStack.copy(), false); + iterator.remove(); + visualizedOutputItems.add(IntAttached.withZero(itemStack)); + } + + for (Iterator iterator = spoutputFluidBuffer.iterator(); iterator.hasNext();) { + FluidStack fluidStack = iterator.next(); + + if (direction == Direction.DOWN) { + iterator.remove(); + update = true; + continue; + } + + if (targetTank == null) + break; + + for (boolean simulate : Iterate.trueAndFalse) { + FluidAction action = simulate ? FluidAction.SIMULATE : FluidAction.EXECUTE; + int fill = targetTank instanceof SmartFluidTankBehaviour.InternalFluidHandler + ? ((SmartFluidTankBehaviour.InternalFluidHandler) targetTank).forceFill(fluidStack.copy(), action) + : targetTank.fill(fluidStack.copy(), action); + if (fill != fluidStack.getAmount()) + break; + if (simulate) + continue; + + update = true; + iterator.remove(); + visualizedOutputFluids.add(IntAttached.withZero(fluidStack)); + } + } + + if (update) { + notifyChangeOfContents(); + sendData(); + } + } + + public float getTotalFluidUnits(float partialTicks) { + int renderedFluids = 0; + float totalUnits = 0; + + for (SmartFluidTankBehaviour behaviour : getTanks()) { + if (behaviour == null) + continue; + for (TankSegment tankSegment : behaviour.getTanks()) { + if (tankSegment.getRenderedFluid() + .isEmpty()) + continue; + float units = tankSegment.getTotalUnits(partialTicks); + if (units < 1) + continue; + totalUnits += units; + renderedFluids++; + } + } + + if (renderedFluids == 0) + return 0; + if (totalUnits < 1) + return 0; + return totalUnits; + } + + private Optional getOperator() { + if (level == null) + return Optional.empty(); + BlockEntity be = level.getBlockEntity(worldPosition.above(2)); + if (be instanceof BasinOperatingBlockEntity) + return Optional.of((BasinOperatingBlockEntity) be); + return Optional.empty(); + } + + public FilteringBehaviour getFilter() { + return filtering; + } + + public void notifyChangeOfContents() { + contentsChanged = true; + } + + public SmartInventory getInputInventory() { + return inputInventory; + } + + public SmartInventory getOutputInventory() { + return outputInventory; + } + + public boolean canContinueProcessing() { + return spoutputBuffer.isEmpty() && spoutputFluidBuffer.isEmpty(); + } + + public boolean acceptOutputs(List outputItems, List outputFluids, boolean simulate) { + outputInventory.allowInsertion(); + outputTank.allowInsertion(); + boolean acceptOutputsInner = acceptOutputsInner(outputItems, outputFluids, simulate); + outputInventory.forbidInsertion(); + outputTank.forbidInsertion(); + return acceptOutputsInner; + } + + private boolean acceptOutputsInner(List outputItems, List outputFluids, boolean simulate) { + BlockState blockState = getBlockState(); + if (!(blockState.getBlock() instanceof BasinBlock)) + return false; + + Direction direction = blockState.getValue(BasinBlock.FACING); + if (direction != Direction.DOWN) { + + BlockEntity be = level.getBlockEntity(worldPosition.below() + .relative(direction)); + + InvManipulationBehaviour inserter = + be == null ? null : BlockEntityBehaviour.get(level, be.getBlockPos(), InvManipulationBehaviour.TYPE); + IItemHandler targetInv = be == null ? null + : be.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, direction.getOpposite()) + .orElse(inserter == null ? null : inserter.getInventory()); + IFluidHandler targetTank = be == null ? null + : be.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, direction.getOpposite()) + .orElse(null); + boolean externalTankNotPresent = targetTank == null; + + if (!outputItems.isEmpty() && targetInv == null) + return false; + if (!outputFluids.isEmpty() && externalTankNotPresent) { + // Special case - fluid outputs but output only accepts items + targetTank = outputTank.getCapability() + .orElse(null); + if (targetTank == null) + return false; + if (!acceptFluidOutputsIntoBasin(outputFluids, simulate, targetTank)) + return false; + } + + if (simulate) + return true; + for (ItemStack itemStack : outputItems) { + if (itemStack.hasCraftingRemainingItem() && itemStack.getCraftingRemainingItem() + .sameItem(itemStack)) + continue; + spoutputBuffer.add(itemStack.copy()); + } + if (!externalTankNotPresent) + for (FluidStack fluidStack : outputFluids) + spoutputFluidBuffer.add(fluidStack.copy()); + return true; + } + + IItemHandler targetInv = outputInventory; + IFluidHandler targetTank = outputTank.getCapability() + .orElse(null); + + if (targetInv == null && !outputItems.isEmpty()) + return false; + if (!acceptItemOutputsIntoBasin(outputItems, simulate, targetInv)) + return false; + if (outputFluids.isEmpty()) + return true; + if (targetTank == null) + return false; + if (!acceptFluidOutputsIntoBasin(outputFluids, simulate, targetTank)) + return false; + + return true; + } + + private boolean acceptFluidOutputsIntoBasin(List outputFluids, boolean simulate, + IFluidHandler targetTank) { + for (FluidStack fluidStack : outputFluids) { + FluidAction action = simulate ? FluidAction.SIMULATE : FluidAction.EXECUTE; + int fill = targetTank instanceof SmartFluidTankBehaviour.InternalFluidHandler + ? ((SmartFluidTankBehaviour.InternalFluidHandler) targetTank).forceFill(fluidStack.copy(), action) + : targetTank.fill(fluidStack.copy(), action); + if (fill != fluidStack.getAmount()) + return false; + } + return true; + } + + private boolean acceptItemOutputsIntoBasin(List outputItems, boolean simulate, IItemHandler targetInv) { + for (ItemStack itemStack : outputItems) { + // Catalyst items are never consumed + if (itemStack.hasCraftingRemainingItem() && itemStack.getCraftingRemainingItem() + .sameItem(itemStack)) + continue; + if (!ItemHandlerHelper.insertItemStacked(targetInv, itemStack.copy(), simulate) + .isEmpty()) + return false; + } + return true; + } + + public void readOnlyItems(CompoundTag compound) { + inputInventory.deserializeNBT(compound.getCompound("InputItems")); + outputInventory.deserializeNBT(compound.getCompound("OutputItems")); + } + + public static HeatLevel getHeatLevelOf(BlockState state) { + if (state.hasProperty(BlazeBurnerBlock.HEAT_LEVEL)) + return state.getValue(BlazeBurnerBlock.HEAT_LEVEL); + return AllTags.AllBlockTags.PASSIVE_BOILER_HEATERS.matches(state) ? HeatLevel.SMOULDERING : HeatLevel.NONE; + } + + public Couple getTanks() { + return tanks; + } + + public Couple getInvs() { + return invs; + } + + // client things + + private void tickVisualizedOutputs() { + visualizedOutputFluids.forEach(IntAttached::decrement); + visualizedOutputItems.forEach(IntAttached::decrement); + visualizedOutputFluids.removeIf(IntAttached::isOrBelowZero); + visualizedOutputItems.removeIf(IntAttached::isOrBelowZero); + } + + private void createFluidParticles() { + RandomSource r = level.random; + + if (!visualizedOutputFluids.isEmpty()) + createOutputFluidParticles(r); + + if (!areFluidsMoving && r.nextFloat() > 1 / 8f) + return; + + int segments = 0; + for (SmartFluidTankBehaviour behaviour : getTanks()) { + if (behaviour == null) + continue; + for (TankSegment tankSegment : behaviour.getTanks()) + if (!tankSegment.isEmpty(0)) + segments++; + } + if (segments < 2) + return; + + float totalUnits = getTotalFluidUnits(0); + if (totalUnits == 0) + return; + float fluidLevel = Mth.clamp(totalUnits / 2000, 0, 1); + float rim = 2 / 16f; + float space = 12 / 16f; + float surface = worldPosition.getY() + rim + space * fluidLevel + 1 / 32f; + + if (areFluidsMoving) { + createMovingFluidParticles(surface, segments); + return; + } + + for (SmartFluidTankBehaviour behaviour : getTanks()) { + if (behaviour == null) + continue; + for (TankSegment tankSegment : behaviour.getTanks()) { + if (tankSegment.isEmpty(0)) + continue; + float x = worldPosition.getX() + rim + space * r.nextFloat(); + float z = worldPosition.getZ() + rim + space * r.nextFloat(); + level.addAlwaysVisibleParticle( + new FluidParticleData(AllParticleTypes.BASIN_FLUID.get(), tankSegment.getRenderedFluid()), x, + surface, z, 0, 0, 0); + } + } + } + + private void createOutputFluidParticles(RandomSource r) { + BlockState blockState = getBlockState(); + if (!(blockState.getBlock() instanceof BasinBlock)) + return; + Direction direction = blockState.getValue(BasinBlock.FACING); + if (direction == Direction.DOWN) + return; + Vec3 directionVec = Vec3.atLowerCornerOf(direction.getNormal()); + Vec3 outVec = VecHelper.getCenterOf(worldPosition) + .add(directionVec.scale(.65) + .subtract(0, 1 / 4f, 0)); + Vec3 outMotion = directionVec.scale(1 / 16f) + .add(0, -1 / 16f, 0); + + for (int i = 0; i < 2; i++) { + visualizedOutputFluids.forEach(ia -> { + FluidStack fluidStack = ia.getValue(); + ParticleOptions fluidParticle = FluidFX.getFluidParticle(fluidStack); + Vec3 m = VecHelper.offsetRandomly(outMotion, r, 1 / 16f); + level.addAlwaysVisibleParticle(fluidParticle, outVec.x, outVec.y, outVec.z, m.x, m.y, m.z); + }); + } + } + + private void createMovingFluidParticles(float surface, int segments) { + Vec3 pointer = new Vec3(1, 0, 0).scale(1 / 16f); + float interval = 360f / segments; + Vec3 centerOf = VecHelper.getCenterOf(worldPosition); + float intervalOffset = (AnimationTickHolder.getTicks() * 18) % 360; + + int currentSegment = 0; + for (SmartFluidTankBehaviour behaviour : getTanks()) { + if (behaviour == null) + continue; + for (TankSegment tankSegment : behaviour.getTanks()) { + if (tankSegment.isEmpty(0)) + continue; + float angle = interval * (1 + currentSegment) + intervalOffset; + Vec3 vec = centerOf.add(VecHelper.rotate(pointer, angle, Axis.Y)); + level.addAlwaysVisibleParticle( + new FluidParticleData(AllParticleTypes.BASIN_FLUID.get(), tankSegment.getRenderedFluid()), vec.x(), + surface, vec.z(), 1, 0, 0); + currentSegment++; + } + } + } + + public boolean areFluidsMoving() { + return areFluidsMoving; + } + + public boolean setAreFluidsMoving(boolean areFluidsMoving) { + this.areFluidsMoving = areFluidsMoving; + ingredientRotationSpeed.chase(areFluidsMoving ? 20 : 0, .1f, Chaser.EXP); + return areFluidsMoving; + } + + @Override + public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { + Lang.translate("gui.goggles.basin_contents") + .forGoggles(tooltip); + + IItemHandlerModifiable items = itemCapability.orElse(new ItemStackHandler()); + IFluidHandler fluids = fluidCapability.orElse(new FluidTank(0)); + boolean isEmpty = true; + + for (int i = 0; i < items.getSlots(); i++) { + ItemStack stackInSlot = items.getStackInSlot(i); + if (stackInSlot.isEmpty()) + continue; + Lang.text("") + .add(Components.translatable(stackInSlot.getDescriptionId()) + .withStyle(ChatFormatting.GRAY)) + .add(Lang.text(" x" + stackInSlot.getCount()) + .style(ChatFormatting.GREEN)) + .forGoggles(tooltip, 1); + isEmpty = false; + } + + LangBuilder mb = Lang.translate("generic.unit.millibuckets"); + for (int i = 0; i < fluids.getTanks(); i++) { + FluidStack fluidStack = fluids.getFluidInTank(i); + if (fluidStack.isEmpty()) + continue; + Lang.text("") + .add(Lang.fluidName(fluidStack) + .add(Lang.text(" ")) + .style(ChatFormatting.GRAY) + .add(Lang.number(fluidStack.getAmount()) + .add(mb) + .style(ChatFormatting.BLUE))) + .forGoggles(tooltip, 1); + isEmpty = false; + } + + if (isEmpty) + tooltip.remove(0); + + return true; + } + + class BasinValueBox extends ValueBoxTransform.Sided { + + @Override + protected Vec3 getSouthLocation() { + return VecHelper.voxelSpace(8, 12, 16.05); + } + + @Override + protected boolean isSideActive(BlockState state, Direction direction) { + return direction.getAxis() + .isHorizontal(); + } + + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/BasinGenerator.java b/src/main/java/com/simibubi/create/content/processing/basin/BasinGenerator.java similarity index 94% rename from src/main/java/com/simibubi/create/content/contraptions/processing/BasinGenerator.java rename to src/main/java/com/simibubi/create/content/processing/basin/BasinGenerator.java index 84704801e..1683a5eba 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/BasinGenerator.java +++ b/src/main/java/com/simibubi/create/content/processing/basin/BasinGenerator.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.processing; +package com.simibubi.create.content.processing.basin; import com.simibubi.create.foundation.data.AssetLookup; import com.simibubi.create.foundation.data.SpecialBlockStateGen; diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/BasinInventory.java b/src/main/java/com/simibubi/create/content/processing/basin/BasinInventory.java similarity index 76% rename from src/main/java/com/simibubi/create/content/contraptions/processing/BasinInventory.java rename to src/main/java/com/simibubi/create/content/processing/basin/BasinInventory.java index c0e3bed77..0c88d4d0d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/BasinInventory.java +++ b/src/main/java/com/simibubi/create/content/processing/basin/BasinInventory.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.processing; +package com.simibubi.create.content.processing.basin; import com.simibubi.create.foundation.item.SmartInventory; @@ -7,11 +7,11 @@ import net.minecraftforge.items.ItemHandlerHelper; public class BasinInventory extends SmartInventory { - private BasinTileEntity te; + private BasinBlockEntity blockEntity; - public BasinInventory(int slots, BasinTileEntity te) { - super(slots, te, 16, true); - this.te = te; + public BasinInventory(int slots, BasinBlockEntity be) { + super(slots, be, 16, true); + this.blockEntity = be; } @Override @@ -27,7 +27,7 @@ public class BasinInventory extends SmartInventory { public ItemStack extractItem(int slot, int amount, boolean simulate) { ItemStack extractItem = super.extractItem(slot, amount, simulate); if (!simulate && !extractItem.isEmpty()) - te.notifyChangeOfContents(); + blockEntity.notifyChangeOfContents(); return extractItem; } diff --git a/src/main/java/com/simibubi/create/content/processing/basin/BasinMovementBehaviour.java b/src/main/java/com/simibubi/create/content/processing/basin/BasinMovementBehaviour.java new file mode 100644 index 000000000..646c3783d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/processing/basin/BasinMovementBehaviour.java @@ -0,0 +1,60 @@ +package com.simibubi.create.content.processing.basin; + +import java.util.HashMap; +import java.util.Map; + +import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; + +import net.minecraft.core.Direction; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.items.ItemStackHandler; + +public class BasinMovementBehaviour implements MovementBehaviour { + public Map getOrReadInventory(MovementContext context) { + Map map = new HashMap<>(); + map.put("InputItems", new ItemStackHandler(9)); + map.put("OutputItems", new ItemStackHandler(8)); + map.forEach((s, h) -> h.deserializeNBT(context.blockEntityData.getCompound(s))); + return map; + } + + @Override + public boolean renderAsNormalBlockEntity() { + return true; + } + + @Override + public void tick(MovementContext context) { + MovementBehaviour.super.tick(context); + if (context.temporaryData == null || (boolean) context.temporaryData) { + Vec3 facingVec = context.rotation.apply(Vec3.atLowerCornerOf(Direction.UP.getNormal())); + facingVec.normalize(); + if (Direction.getNearest(facingVec.x, facingVec.y, facingVec.z) == Direction.DOWN) + dump(context, facingVec); + } + } + + private void dump(MovementContext context, Vec3 facingVec) { + getOrReadInventory(context).forEach((key, itemStackHandler) -> { + for (int i = 0; i < itemStackHandler.getSlots(); i++) { + if (itemStackHandler.getStackInSlot(i) + .isEmpty()) + continue; + ItemEntity itemEntity = new ItemEntity(context.world, context.position.x, context.position.y, + context.position.z, itemStackHandler.getStackInSlot(i)); + itemEntity.setDeltaMovement(facingVec.scale(.05)); + context.world.addFreshEntity(itemEntity); + itemStackHandler.setStackInSlot(i, ItemStack.EMPTY); + } + context.blockEntityData.put(key, itemStackHandler.serializeNBT()); + }); + BlockEntity blockEntity = context.contraption.presentBlockEntities.get(context.localPos); + if (blockEntity instanceof BasinBlockEntity) + ((BasinBlockEntity) blockEntity).readOnlyItems(context.blockEntityData); + context.temporaryData = false; // did already dump, so can't any more + } +} diff --git a/src/main/java/com/simibubi/create/content/processing/basin/BasinOperatingBlockEntity.java b/src/main/java/com/simibubi/create/content/processing/basin/BasinOperatingBlockEntity.java new file mode 100644 index 000000000..d17993851 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/processing/basin/BasinOperatingBlockEntity.java @@ -0,0 +1,155 @@ +package com.simibubi.create.content.processing.basin; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.foundation.advancement.CreateAdvancement; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.simple.DeferralBehaviour; +import com.simibubi.create.foundation.recipe.RecipeFinder; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.Container; +import net.minecraft.world.item.crafting.Recipe; +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 BasinOperatingBlockEntity extends KineticBlockEntity { + + public DeferralBehaviour basinChecker; + public boolean basinRemoved; + protected Recipe currentRecipe; + + public BasinOperatingBlockEntity(BlockEntityType typeIn, BlockPos pos, BlockState state) { + super(typeIn, pos, state); + } + + @Override + public void addBehaviours(List behaviours) { + super.addBehaviours(behaviours); + basinChecker = new DeferralBehaviour(this, this::updateBasin); + behaviours.add(basinChecker); + } + + @Override + public void onSpeedChanged(float prevSpeed) { + super.onSpeedChanged(prevSpeed); + if (getSpeed() == 0) + basinRemoved = true; + basinRemoved = false; + basinChecker.scheduleUpdate(); + } + + @Override + public void tick() { + if (basinRemoved) { + basinRemoved = false; + onBasinRemoved(); + sendData(); + return; + } + + super.tick(); + } + + protected boolean updateBasin() { + if (!isSpeedRequirementFulfilled()) + return true; + if (getSpeed() == 0) + return true; + if (isRunning()) + return true; + if (level == null || level.isClientSide) + return true; + Optional basin = getBasin(); + if (!basin.filter(BasinBlockEntity::canContinueProcessing) + .isPresent()) + return true; + + List> recipes = getMatchingRecipes(); + if (recipes.isEmpty()) + return true; + currentRecipe = recipes.get(0); + startProcessingBasin(); + sendData(); + return true; + } + + protected abstract boolean isRunning(); + + public void startProcessingBasin() {} + + public boolean continueWithPreviousRecipe() { + return true; + } + + protected boolean matchBasinRecipe(Recipe recipe) { + if (recipe == null) + return false; + Optional basin = getBasin(); + if (!basin.isPresent()) + return false; + return BasinRecipe.match(basin.get(), recipe); + } + + protected void applyBasinRecipe() { + if (currentRecipe == null) + return; + + Optional optionalBasin = getBasin(); + if (!optionalBasin.isPresent()) + return; + BasinBlockEntity basin = optionalBasin.get(); + boolean wasEmpty = basin.canContinueProcessing(); + if (!BasinRecipe.apply(basin, currentRecipe)) + return; + getProcessedRecipeTrigger().ifPresent(this::award); + basin.inputTank.sendDataImmediately(); + + // Continue mixing + if (wasEmpty && matchBasinRecipe(currentRecipe)) { + continueWithPreviousRecipe(); + sendData(); + } + + basin.notifyChangeOfContents(); + } + + protected List> getMatchingRecipes() { + if (getBasin().map(BasinBlockEntity::isEmpty) + .orElse(true)) + return new ArrayList<>(); + + List> list = RecipeFinder.get(getRecipeCacheKey(), level, this::matchStaticFilters); + return list.stream() + .filter(this::matchBasinRecipe) + .sorted((r1, r2) -> r2.getIngredients() + .size() + - r1.getIngredients() + .size()) + .collect(Collectors.toList()); + } + + protected abstract void onBasinRemoved(); + + protected Optional getBasin() { + if (level == null) + return Optional.empty(); + BlockEntity basinBE = level.getBlockEntity(worldPosition.below(2)); + if (!(basinBE instanceof BasinBlockEntity)) + return Optional.empty(); + return Optional.of((BasinBlockEntity) basinBE); + } + + protected Optional getProcessedRecipeTrigger() { + return Optional.empty(); + } + + protected abstract boolean matchStaticFilters(Recipe recipe); + + protected abstract Object getRecipeCacheKey(); +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/BasinRecipe.java b/src/main/java/com/simibubi/create/content/processing/basin/BasinRecipe.java similarity index 82% rename from src/main/java/com/simibubi/create/content/contraptions/processing/BasinRecipe.java rename to src/main/java/com/simibubi/create/content/processing/basin/BasinRecipe.java index a810af08d..ddcf9ecaa 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/BasinRecipe.java +++ b/src/main/java/com/simibubi/create/content/processing/basin/BasinRecipe.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.processing; +package com.simibubi.create.content.processing.basin; import java.util.ArrayList; import java.util.Collections; @@ -8,16 +8,18 @@ import java.util.List; import javax.annotation.Nonnull; import com.simibubi.create.AllRecipeTypes; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder.ProcessingRecipeParams; -import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.HeatLevel; +import com.simibubi.create.content.processing.burner.BlazeBurnerBlock.HeatLevel; +import com.simibubi.create.content.processing.recipe.ProcessingRecipe; +import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder; +import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder.ProcessingRecipeParams; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.fluid.SmartFluidTankBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.fluid.SmartFluidTankBehaviour.TankSegment; import com.simibubi.create.foundation.fluid.FluidIngredient; import com.simibubi.create.foundation.item.SmartInventory; -import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour.TankSegment; +import com.simibubi.create.foundation.recipe.DummyCraftingContainer; +import com.simibubi.create.foundation.recipe.IRecipeTypeInfo; import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.recipe.DummyCraftingContainer; -import com.simibubi.create.foundation.utility.recipe.IRecipeTypeInfo; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.CraftingRecipe; @@ -32,7 +34,7 @@ import net.minecraftforge.items.IItemHandler; public class BasinRecipe extends ProcessingRecipe { - public static boolean match(BasinTileEntity basin, Recipe recipe) { + public static boolean match(BasinBlockEntity basin, Recipe recipe) { FilteringBehaviour filter = basin.getFilter(); if (filter == null) return false; @@ -54,11 +56,11 @@ public class BasinRecipe extends ProcessingRecipe { return apply(basin, recipe, true); } - public static boolean apply(BasinTileEntity basin, Recipe recipe) { + public static boolean apply(BasinBlockEntity basin, Recipe recipe) { return apply(basin, recipe, false); } - private static boolean apply(BasinTileEntity basin, Recipe recipe, boolean test) { + private static boolean apply(BasinBlockEntity basin, Recipe recipe, boolean test) { boolean isBasinRecipe = recipe instanceof BasinRecipe; IItemHandler availableItems = basin.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) .orElse(null); @@ -68,7 +70,7 @@ public class BasinRecipe extends ProcessingRecipe { if (availableItems == null || availableFluids == null) return false; - HeatLevel heat = BasinTileEntity.getHeatLevelOf(basin.getLevel() + HeatLevel heat = BasinBlockEntity.getHeatLevelOf(basin.getLevel() .getBlockState(basin.getBlockPos() .below(1))); if (isBasinRecipe && !((BasinRecipe) recipe).getRequiredHeat() @@ -100,15 +102,8 @@ public class BasinRecipe extends ProcessingRecipe { ItemStack extracted = availableItems.extractItem(slot, 1, true); if (!ingredient.test(extracted)) continue; - // Catalyst items are never consumed - if (extracted.hasCraftingRemainingItem() && extracted.getCraftingRemainingItem() - .sameItem(extracted)) - continue Ingredients; if (!simulate) availableItems.extractItem(slot, 1, false); - else if (extracted.hasCraftingRemainingItem()) - recipeOutputItems.add(extracted.getCraftingRemainingItem() - .copy()); extractedItemsFromSlot[slot]++; continue Ingredients; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/BasinRenderer.java b/src/main/java/com/simibubi/create/content/processing/basin/BasinRenderer.java similarity index 89% rename from src/main/java/com/simibubi/create/content/contraptions/processing/BasinRenderer.java rename to src/main/java/com/simibubi/create/content/processing/basin/BasinRenderer.java index 05f4c8d2d..4a42ecab6 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/BasinRenderer.java +++ b/src/main/java/com/simibubi/create/content/processing/basin/BasinRenderer.java @@ -1,11 +1,11 @@ -package com.simibubi.create.content.contraptions.processing; +package com.simibubi.create.content.processing.basin; import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.foundation.blockEntity.behaviour.fluid.SmartFluidTankBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.fluid.SmartFluidTankBehaviour.TankSegment; +import com.simibubi.create.foundation.blockEntity.renderer.SmartBlockEntityRenderer; import com.simibubi.create.foundation.fluid.FluidRenderer; -import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour.TankSegment; -import com.simibubi.create.foundation.tileEntity.renderer.SmartTileEntityRenderer; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.IntAttached; @@ -27,14 +27,14 @@ import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.items.IItemHandlerModifiable; import net.minecraftforge.items.ItemStackHandler; -public class BasinRenderer extends SmartTileEntityRenderer { +public class BasinRenderer extends SmartBlockEntityRenderer { public BasinRenderer(BlockEntityRendererProvider.Context context) { super(context); } @Override - protected void renderSafe(BasinTileEntity basin, float partialTicks, PoseStack ms, MultiBufferSource buffer, + protected void renderSafe(BasinBlockEntity basin, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light, int overlay) { super.renderSafe(basin, partialTicks, ms, buffer, light, overlay); @@ -115,7 +115,7 @@ public class BasinRenderer extends SmartTileEntityRenderer { .getBlock() instanceof BasinBlock; for (IntAttached intAttached : basin.visualizedOutputItems) { - float progress = 1 - (intAttached.getFirst() - partialTicks) / BasinTileEntity.OUTPUT_ANIMATION_TIME; + float progress = 1 - (intAttached.getFirst() - partialTicks) / BasinBlockEntity.OUTPUT_ANIMATION_TIME; if (!outToBasin && progress > .35f) continue; @@ -138,7 +138,7 @@ public class BasinRenderer extends SmartTileEntityRenderer { .renderStatic(stack, TransformType.GROUND, light, overlay, ms, buffer, 0); } - protected float renderFluids(BasinTileEntity basin, float partialTicks, PoseStack ms, MultiBufferSource buffer, + protected float renderFluids(BasinBlockEntity basin, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light, int overlay) { SmartFluidTankBehaviour inputFluids = basin.getBehaviour(SmartFluidTankBehaviour.INPUT); SmartFluidTankBehaviour outputFluids = basin.getBehaviour(SmartFluidTankBehaviour.OUTPUT); diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerBlock.java b/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerBlock.java similarity index 89% rename from src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerBlock.java rename to src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerBlock.java index dc076742c..94383c534 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerBlock.java +++ b/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerBlock.java @@ -1,17 +1,17 @@ -package com.simibubi.create.content.contraptions.processing.burner; +package com.simibubi.create.content.processing.burner; import java.util.Random; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.processing.BasinTileEntity; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.content.processing.basin.BasinBlockEntity; +import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.utility.Lang; import net.minecraft.MethodsReturnNonnullByDefault; @@ -55,7 +55,7 @@ import net.minecraftforge.common.util.FakePlayer; @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault -public class BlazeBurnerBlock extends HorizontalDirectionalBlock implements ITE, IWrenchable { +public class BlazeBurnerBlock extends HorizontalDirectionalBlock implements IBE, IWrenchable { public static final EnumProperty HEAT_LEVEL = EnumProperty.create("blaze", HeatLevel.class); @@ -74,21 +74,21 @@ public class BlazeBurnerBlock extends HorizontalDirectionalBlock implements ITE< public void onPlace(BlockState state, Level world, BlockPos pos, BlockState p_220082_4_, boolean p_220082_5_) { if (world.isClientSide) return; - BlockEntity tileEntity = world.getBlockEntity(pos.above()); - if (!(tileEntity instanceof BasinTileEntity)) + BlockEntity blockEntity = world.getBlockEntity(pos.above()); + if (!(blockEntity instanceof BasinBlockEntity)) return; - BasinTileEntity basin = (BasinTileEntity) tileEntity; + BasinBlockEntity basin = (BasinBlockEntity) blockEntity; basin.notifyChangeOfContents(); } @Override - public Class getTileEntityClass() { - return BlazeBurnerTileEntity.class; + public Class getBlockEntityClass() { + return BlazeBurnerBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.HEATER.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.HEATER.get(); } @Nullable @@ -96,7 +96,7 @@ public class BlazeBurnerBlock extends HorizontalDirectionalBlock implements ITE< public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { if (state.getValue(HEAT_LEVEL) == HeatLevel.NONE) return null; - return ITE.super.newBlockEntity(pos, state); + return IBE.super.newBlockEntity(pos, state); } @Override @@ -106,7 +106,7 @@ public class BlazeBurnerBlock extends HorizontalDirectionalBlock implements ITE< HeatLevel heat = state.getValue(HEAT_LEVEL); if (AllItems.GOGGLES.isIn(heldItem) && heat != HeatLevel.NONE) - return onTileEntityUse(world, pos, bbte -> { + return onBlockEntityUse(world, pos, bbte -> { if (bbte.goggles) return InteractionResult.PASS; bbte.goggles = true; @@ -115,7 +115,7 @@ public class BlazeBurnerBlock extends HorizontalDirectionalBlock implements ITE< }); if (heldItem.isEmpty() && heat != HeatLevel.NONE) - return onTileEntityUse(world, pos, bbte -> { + return onBlockEntityUse(world, pos, bbte -> { if (!bbte.goggles) return InteractionResult.PASS; bbte.goggles = false; @@ -159,17 +159,17 @@ public class BlazeBurnerBlock extends HorizontalDirectionalBlock implements ITE< if (!state.hasBlockEntity()) return InteractionResultHolder.fail(ItemStack.EMPTY); - BlockEntity te = world.getBlockEntity(pos); - if (!(te instanceof BlazeBurnerTileEntity)) + BlockEntity be = world.getBlockEntity(pos); + if (!(be instanceof BlazeBurnerBlockEntity)) return InteractionResultHolder.fail(ItemStack.EMPTY); - BlazeBurnerTileEntity burnerTE = (BlazeBurnerTileEntity) te; + BlazeBurnerBlockEntity burnerBE = (BlazeBurnerBlockEntity) be; - if (burnerTE.isCreativeFuel(stack)) { + if (burnerBE.isCreativeFuel(stack)) { if (!simulate) - burnerTE.applyCreativeFuel(); + burnerBE.applyCreativeFuel(); return InteractionResultHolder.success(ItemStack.EMPTY); } - if (!burnerTE.tryUpdateFuel(stack, forceOverflow, simulate)) + if (!burnerBE.tryUpdateFuel(stack, forceOverflow, simulate)) return InteractionResultHolder.fail(ItemStack.EMPTY); if (!doNotConsume) { diff --git a/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerBlockEntity.java b/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerBlockEntity.java new file mode 100644 index 000000000..64873b435 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerBlockEntity.java @@ -0,0 +1,354 @@ +package com.simibubi.create.content.processing.burner; + +import java.util.List; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllItems; +import com.simibubi.create.AllTags.AllItemTags; +import com.simibubi.create.content.fluids.tank.FluidTankBlock; +import com.simibubi.create.content.processing.burner.BlazeBurnerBlock.HeatLevel; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.common.ForgeHooks; + +public class BlazeBurnerBlockEntity extends SmartBlockEntity { + + public static final int MAX_HEAT_CAPACITY = 10000; + public static final int INSERTION_THRESHOLD = 500; + + protected FuelType activeFuel; + protected int remainingBurnTime; + protected LerpedFloat headAnimation; + protected LerpedFloat headAngle; + protected boolean isCreative; + protected boolean goggles; + protected boolean hat; + + public BlazeBurnerBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + activeFuel = FuelType.NONE; + remainingBurnTime = 0; + headAnimation = LerpedFloat.linear(); + headAngle = LerpedFloat.angular(); + isCreative = false; + goggles = false; + + headAngle.startWithValue((AngleHelper.horizontalAngle(state.getOptionalValue(BlazeBurnerBlock.FACING) + .orElse(Direction.SOUTH)) + 180) % 360); + } + + public FuelType getActiveFuel() { + return activeFuel; + } + + public int getRemainingBurnTime() { + return remainingBurnTime; + } + + public boolean isCreative() { + return isCreative; + } + + @Override + public void tick() { + super.tick(); + + if (level.isClientSide) { + tickAnimation(); + if (!isVirtual()) + spawnParticles(getHeatLevelFromBlock(), 1); + return; + } + + if (isCreative) + return; + + if (remainingBurnTime > 0) + remainingBurnTime--; + + if (activeFuel == FuelType.NORMAL) + updateBlockState(); + if (remainingBurnTime > 0) + return; + + if (activeFuel == FuelType.SPECIAL) { + activeFuel = FuelType.NORMAL; + remainingBurnTime = MAX_HEAT_CAPACITY / 2; + } else + activeFuel = FuelType.NONE; + + updateBlockState(); + } + + @OnlyIn(Dist.CLIENT) + private void tickAnimation() { + boolean active = getHeatLevelFromBlock().isAtLeast(HeatLevel.FADING) && isValidBlockAbove(); + + if (!active) { + float target = 0; + LocalPlayer player = Minecraft.getInstance().player; + if (player != null && !player.isInvisible()) { + double x; + double z; + if (isVirtual()) { + x = -4; + z = -10; + } else { + x = player.getX(); + z = player.getZ(); + } + double dx = x - (getBlockPos().getX() + 0.5); + double dz = z - (getBlockPos().getZ() + 0.5); + target = AngleHelper.deg(-Mth.atan2(dz, dx)) - 90; + } + target = headAngle.getValue() + AngleHelper.getShortestAngleDiff(headAngle.getValue(), target); + headAngle.chase(target, .25f, Chaser.exp(5)); + headAngle.tickChaser(); + } else { + headAngle.chase((AngleHelper.horizontalAngle(getBlockState().getOptionalValue(BlazeBurnerBlock.FACING) + .orElse(Direction.SOUTH)) + 180) % 360, .125f, Chaser.EXP); + headAngle.tickChaser(); + } + + headAnimation.chase(active ? 1 : 0, .25f, Chaser.exp(.25f)); + headAnimation.tickChaser(); + } + + @Override + public void addBehaviours(List behaviours) {} + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + if (!isCreative) { + compound.putInt("fuelLevel", activeFuel.ordinal()); + compound.putInt("burnTimeRemaining", remainingBurnTime); + } else + compound.putBoolean("isCreative", true); + if (goggles) + compound.putBoolean("Goggles", true); + if (hat) + compound.putBoolean("TrainHat", true); + super.write(compound, clientPacket); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + activeFuel = FuelType.values()[compound.getInt("fuelLevel")]; + remainingBurnTime = compound.getInt("burnTimeRemaining"); + isCreative = compound.getBoolean("isCreative"); + goggles = compound.contains("Goggles"); + hat = compound.contains("TrainHat"); + super.read(compound, clientPacket); + } + + public BlazeBurnerBlock.HeatLevel getHeatLevelFromBlock() { + return BlazeBurnerBlock.getHeatLevelOf(getBlockState()); + } + + public void updateBlockState() { + setBlockHeat(getHeatLevel()); + } + + protected void setBlockHeat(HeatLevel heat) { + HeatLevel inBlockState = getHeatLevelFromBlock(); + if (inBlockState == heat) + return; + level.setBlockAndUpdate(worldPosition, getBlockState().setValue(BlazeBurnerBlock.HEAT_LEVEL, heat)); + notifyUpdate(); + } + + /** + * @return true if the heater updated its burn time and an item should be + * consumed + */ + protected boolean tryUpdateFuel(ItemStack itemStack, boolean forceOverflow, boolean simulate) { + if (isCreative) + return false; + + FuelType newFuel = FuelType.NONE; + int newBurnTime; + + if (AllItemTags.BLAZE_BURNER_FUEL_SPECIAL.matches(itemStack)) { + newBurnTime = 3200; + newFuel = FuelType.SPECIAL; + } else { + newBurnTime = ForgeHooks.getBurnTime(itemStack, null); + if (newBurnTime > 0) { + newFuel = FuelType.NORMAL; + } else if (AllItemTags.BLAZE_BURNER_FUEL_REGULAR.matches(itemStack)) { + newBurnTime = 1600; // Same as coal + newFuel = FuelType.NORMAL; + } + } + + if (newFuel == FuelType.NONE) + return false; + if (newFuel.ordinal() < activeFuel.ordinal()) + return false; + + if (newFuel == activeFuel) { + if (remainingBurnTime <= INSERTION_THRESHOLD) { + newBurnTime += remainingBurnTime; + } else if (forceOverflow && newFuel == FuelType.NORMAL) { + if (remainingBurnTime < MAX_HEAT_CAPACITY) { + newBurnTime = Math.min(remainingBurnTime + newBurnTime, MAX_HEAT_CAPACITY); + } else { + newBurnTime = remainingBurnTime; + } + } else { + return false; + } + } + + if (simulate) + return true; + + activeFuel = newFuel; + remainingBurnTime = newBurnTime; + + if (level.isClientSide) { + spawnParticleBurst(activeFuel == FuelType.SPECIAL); + return true; + } + + HeatLevel prev = getHeatLevelFromBlock(); + playSound(); + updateBlockState(); + + if (prev != getHeatLevelFromBlock()) + level.playSound(null, worldPosition, SoundEvents.BLAZE_AMBIENT, SoundSource.BLOCKS, + .125f + level.random.nextFloat() * .125f, 1.15f - level.random.nextFloat() * .25f); + + return true; + } + + protected void applyCreativeFuel() { + activeFuel = FuelType.NONE; + remainingBurnTime = 0; + isCreative = true; + + HeatLevel next = getHeatLevelFromBlock().nextActiveLevel(); + + if (level.isClientSide) { + spawnParticleBurst(next.isAtLeast(HeatLevel.SEETHING)); + return; + } + + playSound(); + if (next == HeatLevel.FADING) + next = next.nextActiveLevel(); + setBlockHeat(next); + } + + public boolean isCreativeFuel(ItemStack stack) { + return AllItems.CREATIVE_BLAZE_CAKE.isIn(stack); + } + + public boolean isValidBlockAbove() { + if (isVirtual()) + return false; + BlockState blockState = level.getBlockState(worldPosition.above()); + return AllBlocks.BASIN.has(blockState) || blockState.getBlock() instanceof FluidTankBlock; + } + + protected void playSound() { + level.playSound(null, worldPosition, SoundEvents.BLAZE_SHOOT, SoundSource.BLOCKS, + .125f + level.random.nextFloat() * .125f, .75f - level.random.nextFloat() * .25f); + } + + protected HeatLevel getHeatLevel() { + HeatLevel level = HeatLevel.SMOULDERING; + switch (activeFuel) { + case SPECIAL: + level = HeatLevel.SEETHING; + break; + case NORMAL: + boolean lowPercent = (double) remainingBurnTime / MAX_HEAT_CAPACITY < 0.0125; + level = lowPercent ? HeatLevel.FADING : HeatLevel.KINDLED; + break; + default: + case NONE: + break; + } + return level; + } + + protected void spawnParticles(HeatLevel heatLevel, double burstMult) { + if (level == null) + return; + if (heatLevel == BlazeBurnerBlock.HeatLevel.NONE) + return; + + RandomSource r = level.getRandom(); + + Vec3 c = VecHelper.getCenterOf(worldPosition); + Vec3 v = c.add(VecHelper.offsetRandomly(Vec3.ZERO, r, .125f) + .multiply(1, 0, 1)); + + if (r.nextInt(4) != 0) + return; + + boolean empty = level.getBlockState(worldPosition.above()) + .getCollisionShape(level, worldPosition.above()) + .isEmpty(); + + if (empty || r.nextInt(8) == 0) + level.addParticle(ParticleTypes.LARGE_SMOKE, v.x, v.y, v.z, 0, 0, 0); + + double yMotion = empty ? .0625f : r.nextDouble() * .0125f; + Vec3 v2 = c.add(VecHelper.offsetRandomly(Vec3.ZERO, r, .5f) + .multiply(1, .25f, 1) + .normalize() + .scale((empty ? .25f : .5) + r.nextDouble() * .125f)) + .add(0, .5, 0); + + if (heatLevel.isAtLeast(HeatLevel.SEETHING)) { + level.addParticle(ParticleTypes.SOUL_FIRE_FLAME, v2.x, v2.y, v2.z, 0, yMotion, 0); + } else if (heatLevel.isAtLeast(HeatLevel.FADING)) { + level.addParticle(ParticleTypes.FLAME, v2.x, v2.y, v2.z, 0, yMotion, 0); + } + return; + } + + public void spawnParticleBurst(boolean soulFlame) { + Vec3 c = VecHelper.getCenterOf(worldPosition); + RandomSource r = level.random; + for (int i = 0; i < 20; i++) { + Vec3 offset = VecHelper.offsetRandomly(Vec3.ZERO, r, .5f) + .multiply(1, .25f, 1) + .normalize(); + Vec3 v = c.add(offset.scale(.5 + r.nextDouble() * .125f)) + .add(0, .125, 0); + Vec3 m = offset.scale(1 / 32f); + + level.addParticle(soulFlame ? ParticleTypes.SOUL_FIRE_FLAME : ParticleTypes.FLAME, v.x, v.y, v.z, m.x, m.y, + m.z); + } + } + + public enum FuelType { + NONE, NORMAL, SPECIAL + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerBlockItem.java b/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerBlockItem.java similarity index 95% rename from src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerBlockItem.java rename to src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerBlockItem.java index 4314202fb..04b088c79 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerBlockItem.java +++ b/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerBlockItem.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.processing.burner; +package com.simibubi.create.content.processing.burner; import java.util.ArrayList; import java.util.List; @@ -73,13 +73,13 @@ public class BlazeBurnerBlockItem extends BlockItem { Level world = context.getLevel(); BlockPos pos = context.getClickedPos(); - BlockEntity te = world.getBlockEntity(pos); + BlockEntity be = world.getBlockEntity(pos); Player player = context.getPlayer(); - if (!(te instanceof SpawnerBlockEntity)) + if (!(be instanceof SpawnerBlockEntity)) return super.useOn(context); - BaseSpawner spawner = ((SpawnerBlockEntity) te).getSpawner(); + BaseSpawner spawner = ((SpawnerBlockEntity) be).getSpawner(); List possibleSpawns = spawner.spawnPotentials.unwrap() .stream() diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerHandler.java b/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerHandler.java similarity index 88% rename from src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerHandler.java rename to src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerHandler.java index cae8d2cc5..6d63f2890 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerHandler.java +++ b/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerHandler.java @@ -1,8 +1,8 @@ -package com.simibubi.create.content.contraptions.processing.burner; +package com.simibubi.create.content.processing.burner; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerTileEntity.FuelType; +import com.simibubi.create.content.processing.burner.BlazeBurnerBlockEntity.FuelType; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -44,9 +44,9 @@ public class BlazeBurnerHandler { .getType() != HitResult.Type.BLOCK) return; - BlockEntity tile = projectile.level.getBlockEntity(new BlockPos(event.getRayTraceResult() + BlockEntity blockEntity = projectile.level.getBlockEntity(new BlockPos(event.getRayTraceResult() .getLocation())); - if (!(tile instanceof BlazeBurnerTileEntity)) { + if (!(blockEntity instanceof BlazeBurnerBlockEntity)) { return; } @@ -58,12 +58,12 @@ public class BlazeBurnerHandler { if (world.isClientSide) return; - BlazeBurnerTileEntity heater = (BlazeBurnerTileEntity) tile; + BlazeBurnerBlockEntity heater = (BlazeBurnerBlockEntity) blockEntity; if (!heater.isCreative()) { if (heater.activeFuel != FuelType.SPECIAL) { heater.activeFuel = FuelType.NORMAL; heater.remainingBurnTime = - Mth.clamp(heater.remainingBurnTime + 80, 0, BlazeBurnerTileEntity.MAX_HEAT_CAPACITY); + Mth.clamp(heater.remainingBurnTime + 80, 0, BlazeBurnerBlockEntity.MAX_HEAT_CAPACITY); heater.updateBlockState(); heater.notifyUpdate(); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerInteractionBehaviour.java b/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerInteractionBehaviour.java similarity index 81% rename from src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerInteractionBehaviour.java rename to src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerInteractionBehaviour.java index 2756310ad..72462cd3f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerInteractionBehaviour.java +++ b/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerInteractionBehaviour.java @@ -1,16 +1,16 @@ -package com.simibubi.create.content.contraptions.processing.burner; +package com.simibubi.create.content.processing.burner; import com.simibubi.create.AllItems; import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; -import com.simibubi.create.content.contraptions.components.structureMovement.MovingInteractionBehaviour; -import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.HeatLevel; -import com.simibubi.create.content.logistics.trains.entity.CarriageContraption; -import com.simibubi.create.content.logistics.trains.entity.CarriageContraptionEntity; -import com.simibubi.create.content.logistics.trains.entity.Train; -import com.simibubi.create.content.logistics.trains.management.schedule.Schedule; -import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleItem; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.contraptions.behaviour.MovingInteractionBehaviour; +import com.simibubi.create.content.processing.burner.BlazeBurnerBlock.HeatLevel; +import com.simibubi.create.content.trains.entity.CarriageContraption; +import com.simibubi.create.content.trains.entity.CarriageContraptionEntity; +import com.simibubi.create.content.trains.entity.Train; +import com.simibubi.create.content.trains.schedule.Schedule; +import com.simibubi.create.content.trains.schedule.ScheduleItem; import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Lang; diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerMovementBehaviour.java b/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerMovementBehaviour.java similarity index 84% rename from src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerMovementBehaviour.java rename to src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerMovementBehaviour.java index e4c6ca040..2904d3004 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerMovementBehaviour.java @@ -1,13 +1,13 @@ -package com.simibubi.create.content.contraptions.processing.burner; +package com.simibubi.create.content.processing.burner; import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; -import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; -import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.HeatLevel; -import com.simibubi.create.content.logistics.trains.entity.CarriageContraption; -import com.simibubi.create.content.logistics.trains.entity.CarriageContraptionEntity; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.contraptions.render.ContraptionMatrices; +import com.simibubi.create.content.processing.burner.BlazeBurnerBlock.HeatLevel; +import com.simibubi.create.content.trains.entity.CarriageContraption; +import com.simibubi.create.content.trains.entity.CarriageContraptionEntity; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.VecHelper; @@ -23,6 +23,7 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.util.Mth; import net.minecraft.util.RandomSource; import net.minecraft.world.entity.Entity; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.phys.Vec3; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -30,9 +31,14 @@ import net.minecraftforge.api.distmarker.OnlyIn; public class BlazeBurnerMovementBehaviour implements MovementBehaviour { @Override - public boolean renderAsNormalTileEntity() { + public boolean renderAsNormalBlockEntity() { return false; } + + @Override + public ItemStack canBeDisabledVia(MovementContext context) { + return null; + } @Override public void tick(MovementContext context) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerRenderer.java b/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerRenderer.java similarity index 76% rename from src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerRenderer.java rename to src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerRenderer.java index 8ee5ef9bb..976db1a60 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerRenderer.java +++ b/src/main/java/com/simibubi/create/content/processing/burner/BlazeBurnerRenderer.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.processing.burner; +package com.simibubi.create.content.processing.burner; import javax.annotation.Nullable; @@ -6,15 +6,15 @@ import com.jozufozu.flywheel.core.PartialModel; import com.jozufozu.flywheel.core.virtual.VirtualRenderWorld; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; -import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.AllPartialModels; import com.simibubi.create.AllSpriteShifts; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; -import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.HeatLevel; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.contraptions.render.ContraptionMatrices; +import com.simibubi.create.content.processing.burner.BlazeBurnerBlock.HeatLevel; import com.simibubi.create.foundation.block.render.SpriteShiftEntry; +import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; import com.simibubi.create.foundation.render.CachedBufferer; import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.animation.LerpedFloat; @@ -28,25 +28,25 @@ import net.minecraft.util.Mth; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; -public class BlazeBurnerRenderer extends SafeTileEntityRenderer { +public class BlazeBurnerRenderer extends SafeBlockEntityRenderer { public BlazeBurnerRenderer(BlockEntityRendererProvider.Context context) {} @Override - protected void renderSafe(BlazeBurnerTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource bufferSource, + protected void renderSafe(BlazeBurnerBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource bufferSource, int light, int overlay) { - HeatLevel heatLevel = te.getHeatLevelFromBlock(); + HeatLevel heatLevel = be.getHeatLevelFromBlock(); if (heatLevel == HeatLevel.NONE) return; - Level level = te.getLevel(); - BlockState blockState = te.getBlockState(); - float animation = te.headAnimation.getValue(partialTicks) * .175f; - float horizontalAngle = AngleHelper.rad(te.headAngle.getValue(partialTicks)); + Level level = be.getLevel(); + BlockState blockState = be.getBlockState(); + float animation = be.headAnimation.getValue(partialTicks) * .175f; + float horizontalAngle = AngleHelper.rad(be.headAngle.getValue(partialTicks)); boolean canDrawFlame = heatLevel.isAtLeast(HeatLevel.FADING); - boolean drawGoggles = te.goggles; - boolean drawHat = te.hat; - int hashCode = te.hashCode(); + boolean drawGoggles = be.goggles; + boolean drawHat = be.hat; + int hashCode = be.hashCode(); renderShared(ms, null, bufferSource, level, blockState, heatLevel, animation, horizontalAngle, @@ -66,8 +66,8 @@ public class BlazeBurnerRenderer extends SafeTileEntityRenderer { protected List> sequence; protected int loops; protected ProcessingOutput transitionalItem; - protected List resultPool; + + public final List resultPool; public SequencedAssemblyRecipe(ResourceLocation recipeId, SequencedAssemblyRecipeSerializer serializer) { this.id = recipeId; @@ -213,36 +215,38 @@ public class SequencedAssemblyRecipe implements Recipe { public boolean isSpecial() { return true; } - + @Override public RecipeType getType() { return AllRecipeTypes.SEQUENCED_ASSEMBLY.getType(); } @OnlyIn(Dist.CLIENT) - public static void addToTooltip(List toolTip, ItemStack stack) { + public static void addToTooltip(ItemTooltipEvent event) { + ItemStack stack = event.getItemStack(); if (!stack.hasTag() || !stack.getTag() .contains("SequencedAssembly")) return; CompoundTag compound = stack.getTag() .getCompound("SequencedAssembly"); ResourceLocation resourceLocation = new ResourceLocation(compound.getString("id")); - Optional> recipe = Minecraft.getInstance().level.getRecipeManager() + Optional> optionalRecipe = Minecraft.getInstance().level.getRecipeManager() .byKey(resourceLocation); - if (!recipe.isPresent()) + if (!optionalRecipe.isPresent()) return; - Recipe iRecipe = recipe.get(); - if (!(iRecipe instanceof SequencedAssemblyRecipe)) + Recipe recipe = optionalRecipe.get(); + if (!(recipe instanceof SequencedAssemblyRecipe)) return; - SequencedAssemblyRecipe sequencedAssemblyRecipe = (SequencedAssemblyRecipe) iRecipe; + SequencedAssemblyRecipe sequencedAssemblyRecipe = (SequencedAssemblyRecipe) recipe; int length = sequencedAssemblyRecipe.sequence.size(); int step = sequencedAssemblyRecipe.getStep(stack); int total = length * sequencedAssemblyRecipe.loops; - toolTip.add(Components.immutableEmpty()); - toolTip.add(Lang.translateDirect("recipe.sequenced_assembly") + List tooltip = event.getToolTip(); + tooltip.add(Components.immutableEmpty()); + tooltip.add(Lang.translateDirect("recipe.sequenced_assembly") .withStyle(ChatFormatting.GRAY)); - toolTip.add(Lang.translateDirect("recipe.assembly.progress", step, total) + tooltip.add(Lang.translateDirect("recipe.assembly.progress", step, total) .withStyle(ChatFormatting.DARK_GRAY)); int remaining = total - step; @@ -253,10 +257,10 @@ public class SequencedAssemblyRecipe implements Recipe { Component textComponent = sequencedRecipe.getAsAssemblyRecipe() .getDescriptionForAssembly(); if (i == 0) - toolTip.add(Lang.translateDirect("recipe.assembly.next", textComponent) + tooltip.add(Lang.translateDirect("recipe.assembly.next", textComponent) .withStyle(ChatFormatting.AQUA)); else - toolTip.add(Components.literal("-> ").append(textComponent) + tooltip.add(Components.literal("-> ").append(textComponent) .withStyle(ChatFormatting.DARK_AQUA)); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/itemAssembly/SequencedAssemblyRecipeBuilder.java b/src/main/java/com/simibubi/create/content/processing/sequenced/SequencedAssemblyRecipeBuilder.java similarity index 90% rename from src/main/java/com/simibubi/create/content/contraptions/itemAssembly/SequencedAssemblyRecipeBuilder.java rename to src/main/java/com/simibubi/create/content/processing/sequenced/SequencedAssemblyRecipeBuilder.java index 18924d88a..6e9745de5 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/itemAssembly/SequencedAssemblyRecipeBuilder.java +++ b/src/main/java/com/simibubi/create/content/processing/sequenced/SequencedAssemblyRecipeBuilder.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.itemAssembly; +package com.simibubi.create.content.processing.sequenced; import java.util.ArrayList; import java.util.List; @@ -8,10 +8,10 @@ import java.util.function.UnaryOperator; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.simibubi.create.AllRecipeTypes; -import com.simibubi.create.content.contraptions.processing.ProcessingOutput; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipe; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder.ProcessingRecipeFactory; +import com.simibubi.create.content.processing.recipe.ProcessingOutput; +import com.simibubi.create.content.processing.recipe.ProcessingRecipe; +import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder; +import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder.ProcessingRecipeFactory; import net.minecraft.data.recipes.FinishedRecipe; import net.minecraft.resources.ResourceLocation; diff --git a/src/main/java/com/simibubi/create/content/contraptions/itemAssembly/SequencedAssemblyRecipeSerializer.java b/src/main/java/com/simibubi/create/content/processing/sequenced/SequencedAssemblyRecipeSerializer.java similarity index 96% rename from src/main/java/com/simibubi/create/content/contraptions/itemAssembly/SequencedAssemblyRecipeSerializer.java rename to src/main/java/com/simibubi/create/content/processing/sequenced/SequencedAssemblyRecipeSerializer.java index 7a7622002..ab786275e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/itemAssembly/SequencedAssemblyRecipeSerializer.java +++ b/src/main/java/com/simibubi/create/content/processing/sequenced/SequencedAssemblyRecipeSerializer.java @@ -1,9 +1,9 @@ -package com.simibubi.create.content.contraptions.itemAssembly; +package com.simibubi.create.content.processing.sequenced; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import com.simibubi.create.content.contraptions.processing.ProcessingOutput; +import com.simibubi.create.content.processing.recipe.ProcessingOutput; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; diff --git a/src/main/java/com/simibubi/create/content/contraptions/itemAssembly/SequencedRecipe.java b/src/main/java/com/simibubi/create/content/processing/sequenced/SequencedRecipe.java similarity index 93% rename from src/main/java/com/simibubi/create/content/contraptions/itemAssembly/SequencedRecipe.java rename to src/main/java/com/simibubi/create/content/processing/sequenced/SequencedRecipe.java index c16d0d07e..76c5f3426 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/itemAssembly/SequencedRecipe.java +++ b/src/main/java/com/simibubi/create/content/processing/sequenced/SequencedRecipe.java @@ -1,10 +1,10 @@ -package com.simibubi.create.content.contraptions.itemAssembly; +package com.simibubi.create.content.processing.sequenced; import com.google.common.collect.ImmutableList; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipe; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipeSerializer; +import com.simibubi.create.content.processing.recipe.ProcessingRecipe; +import com.simibubi.create.content.processing.recipe.ProcessingRecipeSerializer; import com.simibubi.create.foundation.utility.RegisteredObjects; import net.minecraft.network.FriendlyByteBuf; diff --git a/src/main/java/com/simibubi/create/content/redstone/DirectedDirectionalBlock.java b/src/main/java/com/simibubi/create/content/redstone/DirectedDirectionalBlock.java new file mode 100644 index 000000000..5fb2d1c05 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/DirectedDirectionalBlock.java @@ -0,0 +1,98 @@ +package com.simibubi.create.content.redstone; + +import javax.annotation.Nullable; + +import com.simibubi.create.content.contraptions.ITransformableBlock; +import com.simibubi.create.content.contraptions.StructureTransform; +import com.simibubi.create.content.equipment.wrench.IWrenchable; + +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.HorizontalDirectionalBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition.Builder; +import net.minecraft.world.level.block.state.properties.AttachFace; +import net.minecraft.world.level.block.state.properties.EnumProperty; + +public class DirectedDirectionalBlock extends HorizontalDirectionalBlock implements IWrenchable, ITransformableBlock { + + public static final EnumProperty TARGET = EnumProperty.create("target", AttachFace.class); + + public DirectedDirectionalBlock(Properties pProperties) { + super(pProperties); + registerDefaultState(defaultBlockState().setValue(TARGET, AttachFace.WALL)); + } + + @Override + protected void createBlockStateDefinition(Builder pBuilder) { + super.createBlockStateDefinition(pBuilder.add(TARGET, FACING)); + } + + @Nullable + public BlockState getStateForPlacement(BlockPlaceContext pContext) { + for (Direction direction : pContext.getNearestLookingDirections()) { + BlockState blockstate; + if (direction.getAxis() == Direction.Axis.Y) { + blockstate = this.defaultBlockState() + .setValue(TARGET, direction == Direction.UP ? AttachFace.CEILING : AttachFace.FLOOR) + .setValue(FACING, pContext.getHorizontalDirection()); + } else { + blockstate = this.defaultBlockState() + .setValue(TARGET, AttachFace.WALL) + .setValue(FACING, direction.getOpposite()); + } + + return blockstate; + } + + return null; + } + + public static Direction getTargetDirection(BlockState pState) { + switch ((AttachFace) pState.getValue(TARGET)) { + case CEILING: + return Direction.UP; + case FLOOR: + return Direction.DOWN; + default: + return pState.getValue(FACING); + } + } + + @Override + public BlockState getRotatedBlockState(BlockState originalState, Direction targetedFace) { + if (targetedFace.getAxis() == Axis.Y) + return IWrenchable.super.getRotatedBlockState(originalState, targetedFace); + + Direction targetDirection = getTargetDirection(originalState); + Direction newFacing = targetDirection.getClockWise(targetedFace.getAxis()); + if (targetedFace.getAxisDirection() == AxisDirection.NEGATIVE) + newFacing = newFacing.getOpposite(); + + if (newFacing.getAxis() == Axis.Y) + return originalState.setValue(TARGET, newFacing == Direction.UP ? AttachFace.CEILING : AttachFace.FLOOR); + return originalState.setValue(TARGET, AttachFace.WALL) + .setValue(FACING, newFacing); + } + + @Override + @SuppressWarnings("deprecation") + public BlockState transform(BlockState state, StructureTransform transform) { + if (transform.mirror != null) + state = mirror(state, transform.mirror); + if (transform.rotationAxis == Direction.Axis.Y) + return rotate(state, transform.rotation); + + Direction targetDirection = getTargetDirection(state); + Direction newFacing = transform.rotateFacing(targetDirection); + + if (newFacing.getAxis() == Axis.Y) + return state.setValue(TARGET, newFacing == Direction.UP ? AttachFace.CEILING : AttachFace.FLOOR); + return state.setValue(TARGET, AttachFace.WALL) + .setValue(FACING, newFacing); + } + +} diff --git a/src/main/java/com/simibubi/create/content/redstone/FilteredDetectorFilterSlot.java b/src/main/java/com/simibubi/create/content/redstone/FilteredDetectorFilterSlot.java new file mode 100644 index 000000000..04c7ebf3c --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/FilteredDetectorFilterSlot.java @@ -0,0 +1,59 @@ +package com.simibubi.create.content.redstone; + +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class FilteredDetectorFilterSlot extends ValueBoxTransform.Sided { + + private boolean hasSlotAtBottom; + + public FilteredDetectorFilterSlot(boolean hasSlotAtBottom) { + this.hasSlotAtBottom = hasSlotAtBottom; + } + + @Override + protected boolean isSideActive(BlockState state, Direction direction) { + Direction targetDirection = DirectedDirectionalBlock.getTargetDirection(state); + if (direction == targetDirection) + return false; + if (targetDirection.getOpposite() == direction) + return true; + + if (targetDirection.getAxis() != Axis.Y) + return direction == Direction.UP || direction == Direction.DOWN && hasSlotAtBottom; + if (targetDirection == Direction.UP) + direction = direction.getOpposite(); + if (!hasSlotAtBottom) + return direction == state.getValue(DirectedDirectionalBlock.FACING); + + return direction.getAxis() == state.getValue(DirectedDirectionalBlock.FACING) + .getClockWise() + .getAxis(); + } + + @Override + public void rotate(BlockState state, PoseStack ms) { + super.rotate(state, ms); + Direction facing = state.getValue(DirectedDirectionalBlock.FACING); + if (facing.getAxis() == Axis.Y) + return; + if (getSide() != Direction.UP) + return; + TransformStack.cast(ms) + .rotateZ(-AngleHelper.horizontalAngle(facing) + 180); + } + + @Override + protected Vec3 getSouthLocation() { + return VecHelper.voxelSpace(8f, 8f, 15.5f); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/RoseQuartzLampBlock.java b/src/main/java/com/simibubi/create/content/redstone/RoseQuartzLampBlock.java similarity index 96% rename from src/main/java/com/simibubi/create/content/logistics/block/redstone/RoseQuartzLampBlock.java rename to src/main/java/com/simibubi/create/content/redstone/RoseQuartzLampBlock.java index 879a2a844..c5b70b24f 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/RoseQuartzLampBlock.java +++ b/src/main/java/com/simibubi/create/content/redstone/RoseQuartzLampBlock.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.block.redstone; +package com.simibubi.create.content.redstone; import java.util.HashSet; import java.util.LinkedList; @@ -6,8 +6,8 @@ import java.util.List; import java.util.Set; import java.util.function.BiConsumer; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; -import com.simibubi.create.content.logistics.block.diodes.BrassDiodeBlock; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.content.redstone.diodes.BrassDiodeBlock; import com.simibubi.create.foundation.utility.Iterate; import net.minecraft.core.BlockPos; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/AnalogLeverBlock.java b/src/main/java/com/simibubi/create/content/redstone/analogLever/AnalogLeverBlock.java similarity index 84% rename from src/main/java/com/simibubi/create/content/logistics/block/redstone/AnalogLeverBlock.java rename to src/main/java/com/simibubi/create/content/redstone/analogLever/AnalogLeverBlock.java index 9d83cec5d..e693e8c92 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/AnalogLeverBlock.java +++ b/src/main/java/com/simibubi/create/content/redstone/analogLever/AnalogLeverBlock.java @@ -1,9 +1,10 @@ -package com.simibubi.create.content.logistics.block.redstone; +package com.simibubi.create.content.redstone.analogLever; + import org.joml.Vector3f; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.foundation.block.IBE; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -30,7 +31,7 @@ import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -public class AnalogLeverBlock extends FaceAttachedHorizontalDirectionalBlock implements ITE { +public class AnalogLeverBlock extends FaceAttachedHorizontalDirectionalBlock implements IBE { public AnalogLeverBlock(Properties p_i48402_1_) { super(p_i48402_1_); @@ -44,10 +45,10 @@ public class AnalogLeverBlock extends FaceAttachedHorizontalDirectionalBlock imp return InteractionResult.SUCCESS; } - return onTileEntityUse(worldIn, pos, te -> { + return onBlockEntityUse(worldIn, pos, be -> { boolean sneak = player.isShiftKeyDown(); - te.changeState(sneak); - float f = .25f + ((te.state + 5) / 15f) * .5f; + be.changeState(sneak); + float f = .25f + ((be.state + 5) / 15f) * .5f; worldIn.playSound(null, pos, SoundEvents.LEVER_CLICK, SoundSource.BLOCKS, 0.2F, f); return InteractionResult.SUCCESS; }); @@ -55,7 +56,7 @@ public class AnalogLeverBlock extends FaceAttachedHorizontalDirectionalBlock imp @Override public int getSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { - return getTileEntityOptional(blockAccess, pos).map(al -> al.state) + return getBlockEntityOptional(blockAccess, pos).map(al -> al.state) .orElse(0); } @@ -72,8 +73,8 @@ public class AnalogLeverBlock extends FaceAttachedHorizontalDirectionalBlock imp @Override @OnlyIn(Dist.CLIENT) public void animateTick(BlockState stateIn, Level worldIn, BlockPos pos, RandomSource rand) { - withTileEntityDo(worldIn, pos, te -> { - if (te.state != 0 && rand.nextFloat() < 0.25F) + withBlockEntityDo(worldIn, pos, be -> { + if (be.state != 0 && rand.nextFloat() < 0.25F) addParticles(stateIn, worldIn, pos, 0.5F); }); } @@ -82,8 +83,8 @@ public class AnalogLeverBlock extends FaceAttachedHorizontalDirectionalBlock imp public void onRemove(BlockState state, Level worldIn, BlockPos pos, BlockState newState, boolean isMoving) { if (isMoving || state.getBlock() == newState.getBlock()) return; - withTileEntityDo(worldIn, pos, te -> { - if (te.state != 0) + withBlockEntityDo(worldIn, pos, be -> { + if (be.state != 0) updateNeighbors(state, worldIn, pos); worldIn.removeBlockEntity(pos); }); @@ -120,13 +121,13 @@ public class AnalogLeverBlock extends FaceAttachedHorizontalDirectionalBlock imp } @Override - public Class getTileEntityClass() { - return AnalogLeverTileEntity.class; + public Class getBlockEntityClass() { + return AnalogLeverBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.ANALOG_LEVER.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.ANALOG_LEVER.get(); } @Override diff --git a/src/main/java/com/simibubi/create/content/redstone/analogLever/AnalogLeverBlockEntity.java b/src/main/java/com/simibubi/create/content/redstone/analogLever/AnalogLeverBlockEntity.java new file mode 100644 index 000000000..3902009ff --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/analogLever/AnalogLeverBlockEntity.java @@ -0,0 +1,90 @@ +package com.simibubi.create.content.redstone.analogLever; + +import java.util.List; + +import com.simibubi.create.content.equipment.goggles.IHaveGoggleInformation; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.util.Mth; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; + +public class AnalogLeverBlockEntity extends SmartBlockEntity implements IHaveGoggleInformation { + + int state = 0; + int lastChange; + LerpedFloat clientState; + + public AnalogLeverBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + clientState = LerpedFloat.linear(); + } + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + compound.putInt("State", state); + compound.putInt("ChangeTimer", lastChange); + super.write(compound, clientPacket); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + state = compound.getInt("State"); + lastChange = compound.getInt("ChangeTimer"); + clientState.chase(state, 0.2f, Chaser.EXP); + super.read(compound, clientPacket); + } + + @Override + public void tick() { + super.tick(); + if (lastChange > 0) { + lastChange--; + if (lastChange == 0) + updateOutput(); + } + if (level.isClientSide) + clientState.tickChaser(); + } + + @Override + public void initialize() { + super.initialize(); + + } + + private void updateOutput() { + AnalogLeverBlock.updateNeighbors(getBlockState(), level, worldPosition); + } + + @Override + public void addBehaviours(List behaviours) { + } + + public void changeState(boolean back) { + int prevState = state; + state += back ? -1 : 1; + state = Mth.clamp(state, 0, 15); + if (prevState != state) + lastChange = 15; + sendData(); + } + + @Override + public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { + tooltip.add(componentSpacing.plainCopy().append(Lang.translateDirect("tooltip.analogStrength", this.state))); + + return true; + } + + public int getState() { + return state; + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/AnalogLeverInstance.java b/src/main/java/com/simibubi/create/content/redstone/analogLever/AnalogLeverInstance.java similarity index 83% rename from src/main/java/com/simibubi/create/content/logistics/block/redstone/AnalogLeverInstance.java rename to src/main/java/com/simibubi/create/content/redstone/analogLever/AnalogLeverInstance.java index 86a77af8b..0f5145e15 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/AnalogLeverInstance.java +++ b/src/main/java/com/simibubi/create/content/redstone/analogLever/AnalogLeverInstance.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.block.redstone; +package com.simibubi.create.content.redstone.analogLever; import com.jozufozu.flywheel.api.Material; import com.jozufozu.flywheel.api.MaterialManager; @@ -7,7 +7,7 @@ import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance; import com.jozufozu.flywheel.core.materials.model.ModelData; import com.jozufozu.flywheel.util.transform.Rotate; import com.jozufozu.flywheel.util.transform.Translate; -import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.AllPartialModels; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.Color; @@ -15,7 +15,7 @@ import com.simibubi.create.foundation.utility.Color; import net.minecraft.core.Direction; import net.minecraft.world.level.block.state.properties.AttachFace; -public class AnalogLeverInstance extends BlockEntityInstance implements DynamicInstance { +public class AnalogLeverInstance extends BlockEntityInstance implements DynamicInstance { protected final ModelData handle; protected final ModelData indicator; @@ -23,14 +23,14 @@ public class AnalogLeverInstance extends BlockEntityInstance mat = getTransformMaterial(); - handle = mat.getModel(AllBlockPartials.ANALOG_LEVER_HANDLE, blockState) + handle = mat.getModel(AllPartialModels.ANALOG_LEVER_HANDLE, blockState) .createInstance(); - indicator = mat.getModel(AllBlockPartials.ANALOG_LEVER_INDICATOR, blockState) + indicator = mat.getModel(AllPartialModels.ANALOG_LEVER_INDICATOR, blockState) .createInstance(); transform(indicator); diff --git a/src/main/java/com/simibubi/create/content/redstone/analogLever/AnalogLeverRenderer.java b/src/main/java/com/simibubi/create/content/redstone/analogLever/AnalogLeverRenderer.java new file mode 100644 index 000000000..89a6150c1 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/analogLever/AnalogLeverRenderer.java @@ -0,0 +1,62 @@ +package com.simibubi.create.content.redstone.analogLever; + +import com.jozufozu.flywheel.backend.Backend; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.Color; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.AttachFace; + +public class AnalogLeverRenderer extends SafeBlockEntityRenderer { + + public AnalogLeverRenderer(BlockEntityRendererProvider.Context context) { + } + + @Override + protected void renderSafe(AnalogLeverBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + + if (Backend.canUseInstancing(be.getLevel())) return; + + BlockState leverState = be.getBlockState(); + float state = be.clientState.getValue(partialTicks); + + VertexConsumer vb = buffer.getBuffer(RenderType.solid()); + + // Handle + SuperByteBuffer handle = CachedBufferer.partial(AllPartialModels.ANALOG_LEVER_HANDLE, leverState); + float angle = (float) ((state / 15) * 90 / 180 * Math.PI); + transform(handle, leverState).translate(1 / 2f, 1 / 16f, 1 / 2f) + .rotate(Direction.EAST, angle) + .translate(-1 / 2f, -1 / 16f, -1 / 2f); + handle.light(light) + .renderInto(ms, vb); + + // Indicator + int color = Color.mixColors(0x2C0300, 0xCD0000, state / 15f); + SuperByteBuffer indicator = transform(CachedBufferer.partial(AllPartialModels.ANALOG_LEVER_INDICATOR, leverState), leverState); + indicator.light(light) + .color(color) + .renderInto(ms, vb); + } + + private SuperByteBuffer transform(SuperByteBuffer buffer, BlockState leverState) { + AttachFace face = leverState.getValue(AnalogLeverBlock.FACE); + float rX = face == AttachFace.FLOOR ? 0 : face == AttachFace.WALL ? 90 : 180; + float rY = AngleHelper.horizontalAngle(leverState.getValue(AnalogLeverBlock.FACING)); + buffer.rotateCentered(Direction.UP, (float) (rY / 180 * Math.PI)); + buffer.rotateCentered(Direction.EAST, (float) (rX / 180 * Math.PI)); + return buffer; + } + +} diff --git a/src/main/java/com/simibubi/create/content/redstone/contact/ContactMovementBehaviour.java b/src/main/java/com/simibubi/create/content/redstone/contact/ContactMovementBehaviour.java new file mode 100644 index 000000000..e4f4bef7b --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/contact/ContactMovementBehaviour.java @@ -0,0 +1,80 @@ +package com.simibubi.create.content.redstone.contact; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.contraptions.elevator.ElevatorContraption; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.ticks.TickPriority; + +public class ContactMovementBehaviour implements MovementBehaviour { + + @Override + public Vec3 getActiveAreaOffset(MovementContext context) { + return Vec3.atLowerCornerOf(context.state.getValue(RedstoneContactBlock.FACING) + .getNormal()) + .scale(.65f); + } + + @Override + public void visitNewPosition(MovementContext context, BlockPos pos) { + BlockState block = context.state; + Level world = context.world; + + if (world.isClientSide) + return; + if (context.firstMovement) + return; + + deactivateLastVisitedContact(context); + BlockState visitedState = world.getBlockState(pos); + if (!AllBlocks.REDSTONE_CONTACT.has(visitedState) && !AllBlocks.ELEVATOR_CONTACT.has(visitedState)) + return; + + Vec3 contact = Vec3.atLowerCornerOf(block.getValue(RedstoneContactBlock.FACING) + .getNormal()); + contact = context.rotation.apply(contact); + Direction direction = Direction.getNearest(contact.x, contact.y, contact.z); + + if (visitedState.getValue(RedstoneContactBlock.FACING) != direction.getOpposite()) + return; + + if (AllBlocks.REDSTONE_CONTACT.has(visitedState)) + world.setBlockAndUpdate(pos, visitedState.setValue(RedstoneContactBlock.POWERED, true)); + if (AllBlocks.ELEVATOR_CONTACT.has(visitedState) && context.contraption instanceof ElevatorContraption ec) + ec.broadcastFloorData(world, pos); + + context.data.put("lastContact", NbtUtils.writeBlockPos(pos)); + return; + } + + @Override + public void stopMoving(MovementContext context) { + deactivateLastVisitedContact(context); + } + + @Override + public void cancelStall(MovementContext context) { + MovementBehaviour.super.cancelStall(context); + deactivateLastVisitedContact(context); + } + + public void deactivateLastVisitedContact(MovementContext context) { + if (!context.data.contains("lastContact")) + return; + + BlockPos last = NbtUtils.readBlockPos(context.data.getCompound("lastContact")); + context.data.remove("lastContact"); + BlockState blockState = context.world.getBlockState(last); + + if (AllBlocks.REDSTONE_CONTACT.has(blockState)) + context.world.scheduleTick(last, AllBlocks.REDSTONE_CONTACT.get(), 1, TickPriority.NORMAL); + } + +} diff --git a/src/main/java/com/simibubi/create/content/redstone/contact/RedstoneContactBlock.java b/src/main/java/com/simibubi/create/content/redstone/contact/RedstoneContactBlock.java new file mode 100644 index 000000000..40bde7345 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/contact/RedstoneContactBlock.java @@ -0,0 +1,142 @@ +package com.simibubi.create.content.redstone.contact; + +import javax.annotation.Nullable; +import javax.annotation.ParametersAreNonnullByDefault; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.contraptions.elevator.ElevatorColumn; +import com.simibubi.create.content.contraptions.elevator.ElevatorColumn.ColumnCoords; +import com.simibubi.create.foundation.block.WrenchableDirectionalBlock; +import com.simibubi.create.foundation.utility.BlockHelper; + +import net.minecraft.MethodsReturnNonnullByDefault; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.item.context.UseOnContext; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition.Builder; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.BooleanProperty; + +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +public class RedstoneContactBlock extends WrenchableDirectionalBlock { + + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; + + public RedstoneContactBlock(Properties properties) { + super(properties); + registerDefaultState(defaultBlockState().setValue(POWERED, false) + .setValue(FACING, Direction.UP)); + } + + @Override + protected void createBlockStateDefinition(Builder builder) { + builder.add(POWERED); + super.createBlockStateDefinition(builder); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext context) { + BlockState state = defaultBlockState().setValue(FACING, context.getNearestLookingDirection() + .getOpposite()); + Direction placeDirection = context.getClickedFace() + .getOpposite(); + + if ((context.getPlayer() != null && context.getPlayer() + .isShiftKeyDown()) || hasValidContact(context.getLevel(), context.getClickedPos(), placeDirection)) + state = state.setValue(FACING, placeDirection); + if (hasValidContact(context.getLevel(), context.getClickedPos(), state.getValue(FACING))) + state = state.setValue(POWERED, true); + + return state; + } + + @Override + public InteractionResult onWrenched(BlockState state, UseOnContext context) { + InteractionResult onWrenched = super.onWrenched(state, context); + if (onWrenched != InteractionResult.SUCCESS) + return onWrenched; + + Level level = context.getLevel(); + if (level.isClientSide()) + return onWrenched; + + BlockPos pos = context.getClickedPos(); + state = level.getBlockState(pos); + Direction facing = state.getValue(RedstoneContactBlock.FACING); + if (facing.getAxis() == Axis.Y) + return onWrenched; + if (ElevatorColumn.get(level, new ColumnCoords(pos.getX(), pos.getZ(), facing)) == null) + return onWrenched; + + level.setBlockAndUpdate(pos, BlockHelper.copyProperties(state, AllBlocks.ELEVATOR_CONTACT.getDefaultState())); + + return onWrenched; + } + + @Override + public BlockState updateShape(BlockState stateIn, Direction facing, BlockState facingState, LevelAccessor worldIn, + BlockPos currentPos, BlockPos facingPos) { + if (facing != stateIn.getValue(FACING)) + return stateIn; + boolean hasValidContact = hasValidContact(worldIn, currentPos, facing); + if (stateIn.getValue(POWERED) != hasValidContact) + return stateIn.setValue(POWERED, hasValidContact); + return stateIn; + } + + @SuppressWarnings("deprecation") + @Override + public void onRemove(BlockState state, Level worldIn, BlockPos pos, BlockState newState, boolean isMoving) { + if (state.getBlock() == this && newState.getBlock() == this) + if (state == newState.cycle(POWERED)) + worldIn.updateNeighborsAt(pos, this); + super.onRemove(state, worldIn, pos, newState, isMoving); + } + + @Override + public void tick(BlockState state, ServerLevel worldIn, BlockPos pos, RandomSource random) { + boolean hasValidContact = hasValidContact(worldIn, pos, state.getValue(FACING)); + if (state.getValue(POWERED) != hasValidContact) + worldIn.setBlockAndUpdate(pos, state.setValue(POWERED, hasValidContact)); + } + + public static boolean hasValidContact(LevelAccessor world, BlockPos pos, Direction direction) { + BlockState blockState = world.getBlockState(pos.relative(direction)); + return (AllBlocks.REDSTONE_CONTACT.has(blockState) || AllBlocks.ELEVATOR_CONTACT.has(blockState)) + && blockState.getValue(FACING) == direction.getOpposite(); + } + + @Override + public boolean shouldCheckWeakPower(BlockState state, LevelReader level, BlockPos pos, Direction side) { + return false; + } + + @Override + public boolean isSignalSource(BlockState state) { + return state.getValue(POWERED); + } + + @Override + public boolean canConnectRedstone(BlockState state, BlockGetter world, BlockPos pos, @Nullable Direction side) { + return side != null && state.getValue(FACING) != side.getOpposite(); + } + + @Override + public int getSignal(BlockState state, BlockGetter blockAccess, BlockPos pos, Direction side) { + return state.getValue(POWERED) && side != state.getValue(FACING) + .getOpposite() ? 15 : 0; + } + +} diff --git a/src/main/java/com/simibubi/create/content/redstone/contact/RedstoneContactItem.java b/src/main/java/com/simibubi/create/content/redstone/contact/RedstoneContactItem.java new file mode 100644 index 000000000..7969b3995 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/contact/RedstoneContactItem.java @@ -0,0 +1,43 @@ +package com.simibubi.create.content.redstone.contact; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.contraptions.elevator.ElevatorColumn; +import com.simibubi.create.content.contraptions.elevator.ElevatorColumn.ColumnCoords; +import com.simibubi.create.foundation.utility.BlockHelper; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; + +public class RedstoneContactItem extends BlockItem { + + public RedstoneContactItem(Block pBlock, Properties pProperties) { + super(pBlock, pProperties); + } + + @Override + protected BlockState getPlacementState(BlockPlaceContext ctx) { + Level world = ctx.getLevel(); + BlockPos pos = ctx.getClickedPos(); + BlockState state = super.getPlacementState(ctx); + + if (state == null) + return state; + if (!(state.getBlock() instanceof RedstoneContactBlock)) + return state; + Direction facing = state.getValue(RedstoneContactBlock.FACING); + if (facing.getAxis() == Axis.Y) + return state; + + if (ElevatorColumn.get(world, new ColumnCoords(pos.getX(), pos.getZ(), facing)) == null) + return state; + + return BlockHelper.copyProperties(state, AllBlocks.ELEVATOR_CONTACT.getDefaultState()); + } + +} diff --git a/src/main/java/com/simibubi/create/content/redstone/diodes/AbstractDiodeBlock.java b/src/main/java/com/simibubi/create/content/redstone/diodes/AbstractDiodeBlock.java new file mode 100644 index 000000000..2c16bb1d9 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/diodes/AbstractDiodeBlock.java @@ -0,0 +1,18 @@ +package com.simibubi.create.content.redstone.diodes; + +import com.simibubi.create.content.equipment.wrench.IWrenchable; + +import net.minecraft.world.level.block.DiodeBlock; +import net.minecraft.world.level.block.state.BlockState; + +public abstract class AbstractDiodeBlock extends DiodeBlock implements IWrenchable { + + public AbstractDiodeBlock(Properties builder) { + super(builder); + } + + @Override + public boolean isSignalSource(BlockState state) { + return true; + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/diodes/AbstractDiodeGenerator.java b/src/main/java/com/simibubi/create/content/redstone/diodes/AbstractDiodeGenerator.java similarity index 97% rename from src/main/java/com/simibubi/create/content/logistics/block/diodes/AbstractDiodeGenerator.java rename to src/main/java/com/simibubi/create/content/redstone/diodes/AbstractDiodeGenerator.java index 89a74d08f..e5abcfb3c 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/diodes/AbstractDiodeGenerator.java +++ b/src/main/java/com/simibubi/create/content/redstone/diodes/AbstractDiodeGenerator.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.block.diodes; +package com.simibubi.create.content.redstone.diodes; import java.util.Vector; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/diodes/BrassDiodeBlock.java b/src/main/java/com/simibubi/create/content/redstone/diodes/BrassDiodeBlock.java similarity index 80% rename from src/main/java/com/simibubi/create/content/logistics/block/diodes/BrassDiodeBlock.java rename to src/main/java/com/simibubi/create/content/redstone/diodes/BrassDiodeBlock.java index be5b927d8..c80c6a4a9 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/diodes/BrassDiodeBlock.java +++ b/src/main/java/com/simibubi/create/content/redstone/diodes/BrassDiodeBlock.java @@ -1,9 +1,9 @@ -package com.simibubi.create.content.logistics.block.diodes; +package com.simibubi.create.content.redstone.diodes; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.foundation.block.IBE; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -21,7 +21,7 @@ import net.minecraft.world.level.block.state.StateDefinition.Builder; import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraft.world.phys.BlockHitResult; -public class BrassDiodeBlock extends AbstractDiodeBlock implements ITE { +public class BrassDiodeBlock extends AbstractDiodeBlock implements IBE { public static final BooleanProperty POWERING = BooleanProperty.create("powering"); public static final BooleanProperty INVERTED = BooleanProperty.create("inverted"); @@ -36,6 +36,11 @@ public class BrassDiodeBlock extends AbstractDiodeBlock implements ITE getTileEntityClass() { - return BrassDiodeTileEntity.class; + public Class getBlockEntityClass() { + return BrassDiodeBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllBlocks.PULSE_EXTENDER.is(this) ? AllTileEntities.PULSE_EXTENDER.get() - : AllTileEntities.PULSE_REPEATER.get(); + public BlockEntityType getBlockEntityType() { + return AllBlocks.PULSE_EXTENDER.is(this) ? AllBlockEntityTypes.PULSE_EXTENDER.get() + : AllBlockEntityTypes.PULSE_REPEATER.get(); } } diff --git a/src/main/java/com/simibubi/create/content/redstone/diodes/BrassDiodeBlockEntity.java b/src/main/java/com/simibubi/create/content/redstone/diodes/BrassDiodeBlockEntity.java new file mode 100644 index 000000000..9de08f8d5 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/diodes/BrassDiodeBlockEntity.java @@ -0,0 +1,111 @@ +package com.simibubi.create.content.redstone.diodes; + +import static com.simibubi.create.content.redstone.diodes.BrassDiodeBlock.POWERING; + +import java.util.List; + +import com.simibubi.create.content.equipment.clipboard.ClipboardCloneable; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollValueBehaviour; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.block.DiodeBlock; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; + +public abstract class BrassDiodeBlockEntity extends SmartBlockEntity implements ClipboardCloneable { + + protected int state; + ScrollValueBehaviour maxState; + + public BrassDiodeBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + public void addBehaviours(List behaviours) { + maxState = new BrassDiodeScrollValueBehaviour(Lang.translateDirect("logistics.redstone_interval"), this, + new BrassDiodeScrollSlot()).between(2, 60 * 20 * 60); + maxState.withFormatter(this::format); + maxState.withCallback(this::onMaxDelayChanged); + maxState.setValue(2); + behaviours.add(maxState); + } + + public float getProgress() { + int max = Math.max(2, maxState.getValue()); + return Mth.clamp(state, 0, max) / (float) max; + } + + public boolean isIdle() { + return state == 0; + } + + @Override + public void tick() { + super.tick(); + boolean powered = getBlockState().getValue(DiodeBlock.POWERED); + boolean powering = getBlockState().getValue(POWERING); + boolean atMax = state >= maxState.getValue(); + boolean atMin = state <= 0; + updateState(powered, powering, atMax, atMin); + } + + protected abstract void updateState(boolean powered, boolean powering, boolean atMax, boolean atMin); + + private void onMaxDelayChanged(int newMax) { + state = Mth.clamp(state, 0, newMax); + sendData(); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + state = compound.getInt("State"); + super.read(compound, clientPacket); + } + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + compound.putInt("State", state); + super.write(compound, clientPacket); + } + + private String format(int value) { + if (value < 60) + return value + "t"; + if (value < 20 * 60) + return (value / 20) + "s"; + return (value / 20 / 60) + "m"; + } + + @Override + public String getClipboardKey() { + return "Block"; + } + + @Override + public boolean readFromClipboard(CompoundTag tag, Player player, Direction side, boolean simulate) { + if (!tag.contains("Inverted")) + return false; + if (simulate) + return true; + BlockState blockState = getBlockState(); + if (blockState.getValue(BrassDiodeBlock.INVERTED) != tag.getBoolean("Inverted")) + level.setBlockAndUpdate(worldPosition, blockState.cycle(BrassDiodeBlock.INVERTED)); + return true; + } + + @Override + public boolean writeToClipboard(CompoundTag tag, Direction side) { + tag.putBoolean("Inverted", getBlockState().getOptionalValue(BrassDiodeBlock.INVERTED) + .orElse(false)); + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/diodes/BrassDiodeGenerator.java b/src/main/java/com/simibubi/create/content/redstone/diodes/BrassDiodeGenerator.java similarity index 95% rename from src/main/java/com/simibubi/create/content/logistics/block/diodes/BrassDiodeGenerator.java rename to src/main/java/com/simibubi/create/content/redstone/diodes/BrassDiodeGenerator.java index a1ee76859..dc3055f4c 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/diodes/BrassDiodeGenerator.java +++ b/src/main/java/com/simibubi/create/content/redstone/diodes/BrassDiodeGenerator.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.block.diodes; +package com.simibubi.create.content.redstone.diodes; import java.util.Vector; diff --git a/src/main/java/com/simibubi/create/content/redstone/diodes/BrassDiodeInstance.java b/src/main/java/com/simibubi/create/content/redstone/diodes/BrassDiodeInstance.java new file mode 100644 index 000000000..0c51e6b76 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/diodes/BrassDiodeInstance.java @@ -0,0 +1,53 @@ +package com.simibubi.create.content.redstone.diodes; + +import com.jozufozu.flywheel.api.MaterialManager; +import com.jozufozu.flywheel.api.instance.TickableInstance; +import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance; +import com.jozufozu.flywheel.core.Materials; +import com.jozufozu.flywheel.core.materials.model.ModelData; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.foundation.utility.Color; + +public class BrassDiodeInstance extends BlockEntityInstance implements TickableInstance { + + protected final ModelData indicator; + + protected int previousState; + + public BrassDiodeInstance(MaterialManager materialManager, BrassDiodeBlockEntity blockEntity) { + super(materialManager, blockEntity); + + indicator = materialManager.defaultSolid() + .material(Materials.TRANSFORMED) + .getModel(AllPartialModels.FLEXPEATER_INDICATOR, blockState).createInstance(); + + indicator.loadIdentity() + .translate(getInstancePosition()) + .setColor(getColor()); + + previousState = blockEntity.state; + } + + @Override + public void tick() { + if (previousState == blockEntity.state) return; + + indicator.setColor(getColor()); + + previousState = blockEntity.state; + } + + @Override + public void updateLight() { + relight(pos, indicator); + } + + @Override + public void remove() { + indicator.delete(); + } + + protected int getColor() { + return Color.mixColors(0x2c0300, 0xcd0000, blockEntity.getProgress()); + } +} diff --git a/src/main/java/com/simibubi/create/content/redstone/diodes/BrassDiodeRenderer.java b/src/main/java/com/simibubi/create/content/redstone/diodes/BrassDiodeRenderer.java new file mode 100644 index 000000000..3cf4a8d0f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/diodes/BrassDiodeRenderer.java @@ -0,0 +1,27 @@ +package com.simibubi.create.content.redstone.diodes; + +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.foundation.blockEntity.renderer.ColoredOverlayBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.Color; + +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; + +public class BrassDiodeRenderer extends ColoredOverlayBlockEntityRenderer { + + public BrassDiodeRenderer(BlockEntityRendererProvider.Context context) { + super(context); + } + + @Override + protected int getColor(BrassDiodeBlockEntity be, float partialTicks) { + return Color.mixColors(0x2C0300, 0xCD0000, be.getProgress()); + } + + @Override + protected SuperByteBuffer getOverlayBuffer(BrassDiodeBlockEntity be) { + return CachedBufferer.partial(AllPartialModels.FLEXPEATER_INDICATOR, be.getBlockState()); + } + +} diff --git a/src/main/java/com/simibubi/create/content/redstone/diodes/BrassDiodeScrollSlot.java b/src/main/java/com/simibubi/create/content/redstone/diodes/BrassDiodeScrollSlot.java new file mode 100644 index 000000000..c492cae70 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/diodes/BrassDiodeScrollSlot.java @@ -0,0 +1,33 @@ +package com.simibubi.create.content.redstone.diodes; + +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.phys.Vec3; + +public class BrassDiodeScrollSlot extends ValueBoxTransform { + + @Override + public Vec3 getLocalOffset(BlockState state) { + return VecHelper.voxelSpace(8, 2.6f, 8); + } + + @Override + public void rotate(BlockState state, PoseStack ms) { + float yRot = AngleHelper.horizontalAngle(state.getValue(BlockStateProperties.HORIZONTAL_FACING)) + 180; + TransformStack.cast(ms) + .rotateY(yRot) + .rotateX(90); + } + + @Override + public int getOverrideColor() { + return 0x592424; + } + +} diff --git a/src/main/java/com/simibubi/create/content/redstone/diodes/BrassDiodeScrollValueBehaviour.java b/src/main/java/com/simibubi/create/content/redstone/diodes/BrassDiodeScrollValueBehaviour.java new file mode 100644 index 000000000..51bcd78b4 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/diodes/BrassDiodeScrollValueBehaviour.java @@ -0,0 +1,82 @@ +package com.simibubi.create.content.redstone.diodes; + +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsBoard; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsFormatter; +import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollValueBehaviour; +import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.core.Direction; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; + +public class BrassDiodeScrollValueBehaviour extends ScrollValueBehaviour { + + public BrassDiodeScrollValueBehaviour(Component label, SmartBlockEntity be, ValueBoxTransform slot) { + super(label, be, slot); + } + + @Override + public ValueSettingsBoard createBoard(Player player, BlockHitResult hitResult) { + return new ValueSettingsBoard(label, 60, 10, + Lang.translatedOptions("generic.unit", "ticks", "seconds", "minutes"), + new ValueSettingsFormatter(this::formatSettings)); + } + + @Override + public void onShortInteract(Player player, InteractionHand hand, Direction side) { + BlockState blockState = blockEntity.getBlockState(); + if (blockState.getBlock()instanceof BrassDiodeBlock bdb) + bdb.toggle(getWorld(), getPos(), blockState, player, hand); + } + + @Override + public void setValueSettings(Player player, ValueSettings valueSetting, boolean ctrlHeld) { + int value = valueSetting.value(); + int multiplier = switch (valueSetting.row()) { + case 0 -> 1; + case 1 -> 20; + default -> 60 * 20; + }; + if (!valueSetting.equals(getValueSettings())) + playFeedbackSound(this); + setValue(Math.max(2, Math.max(1, value) * multiplier)); + } + + @Override + public ValueSettings getValueSettings() { + int row = 0; + int value = this.value; + + if (value > 60 * 20) { + value = value / (60 * 20); + row = 2; + } else if (value > 60) { + value = value / 20; + row = 1; + } + + return new ValueSettings(row, value); + } + + public MutableComponent formatSettings(ValueSettings settings) { + int value = Math.max(1, settings.value()); + return Components.literal(switch (settings.row()) { + case 0 -> Math.max(2, value) + "t"; + case 1 -> "0:" + (value < 10 ? "0" : "") + value; + default -> value + ":00"; + }); + } + + @Override + public String getClipboardKey() { + return "Timings"; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/diodes/PoweredLatchBlock.java b/src/main/java/com/simibubi/create/content/redstone/diodes/PoweredLatchBlock.java similarity index 98% rename from src/main/java/com/simibubi/create/content/logistics/block/diodes/PoweredLatchBlock.java rename to src/main/java/com/simibubi/create/content/redstone/diodes/PoweredLatchBlock.java index 56858b057..15f1d24fa 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/diodes/PoweredLatchBlock.java +++ b/src/main/java/com/simibubi/create/content/redstone/diodes/PoweredLatchBlock.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.block.diodes; +package com.simibubi.create.content.redstone.diodes; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/diodes/PoweredLatchGenerator.java b/src/main/java/com/simibubi/create/content/redstone/diodes/PoweredLatchGenerator.java similarity index 94% rename from src/main/java/com/simibubi/create/content/logistics/block/diodes/PoweredLatchGenerator.java rename to src/main/java/com/simibubi/create/content/redstone/diodes/PoweredLatchGenerator.java index 290df7517..5928f3649 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/diodes/PoweredLatchGenerator.java +++ b/src/main/java/com/simibubi/create/content/redstone/diodes/PoweredLatchGenerator.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.block.diodes; +package com.simibubi.create.content.redstone.diodes; import java.util.Vector; diff --git a/src/main/java/com/simibubi/create/content/redstone/diodes/PulseExtenderBlockEntity.java b/src/main/java/com/simibubi/create/content/redstone/diodes/PulseExtenderBlockEntity.java new file mode 100644 index 000000000..23dc3cf74 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/diodes/PulseExtenderBlockEntity.java @@ -0,0 +1,36 @@ +package com.simibubi.create.content.redstone.diodes; + +import static com.simibubi.create.content.redstone.diodes.BrassDiodeBlock.POWERING; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; + +public class PulseExtenderBlockEntity extends BrassDiodeBlockEntity { + + public PulseExtenderBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + protected void updateState(boolean powered, boolean powering, boolean atMax, boolean atMin) { + if (atMin && !powered) + return; + if (atMin || powered) { + level.setBlockAndUpdate(worldPosition, getBlockState().setValue(POWERING, true)); + state = maxState.getValue(); + return; + } + + if (state == 1) { + if (powering && !level.isClientSide) + level.setBlockAndUpdate(worldPosition, getBlockState().setValue(POWERING, false)); + if (!powered) + state = 0; + return; + } + + if (!powered) + state--; + } +} diff --git a/src/main/java/com/simibubi/create/content/redstone/diodes/PulseRepeaterBlockEntity.java b/src/main/java/com/simibubi/create/content/redstone/diodes/PulseRepeaterBlockEntity.java new file mode 100644 index 000000000..76e9dc004 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/diodes/PulseRepeaterBlockEntity.java @@ -0,0 +1,35 @@ +package com.simibubi.create.content.redstone.diodes; + +import static com.simibubi.create.content.redstone.diodes.BrassDiodeBlock.POWERING; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; + +public class PulseRepeaterBlockEntity extends BrassDiodeBlockEntity { + + public PulseRepeaterBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + protected void updateState(boolean powered, boolean powering, boolean atMax, boolean atMin) { + if (atMin && !powered) + return; + if (state > maxState.getValue() + 1) { + if (!powered && !powering) + state = 0; + return; + } + + state++; + if (level.isClientSide) + return; + + if (state == maxState.getValue() - 1 && !powering) + level.setBlockAndUpdate(worldPosition, getBlockState().cycle(POWERING)); + if (state == maxState.getValue() + 1 && powering) + level.setBlockAndUpdate(worldPosition, getBlockState().cycle(POWERING)); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/diodes/ToggleLatchBlock.java b/src/main/java/com/simibubi/create/content/redstone/diodes/ToggleLatchBlock.java similarity index 98% rename from src/main/java/com/simibubi/create/content/logistics/block/diodes/ToggleLatchBlock.java rename to src/main/java/com/simibubi/create/content/redstone/diodes/ToggleLatchBlock.java index 47c86403a..24eefae6c 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/diodes/ToggleLatchBlock.java +++ b/src/main/java/com/simibubi/create/content/redstone/diodes/ToggleLatchBlock.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.block.diodes; +package com.simibubi.create.content.redstone.diodes; import com.simibubi.create.AllItems; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/diodes/ToggleLatchGenerator.java b/src/main/java/com/simibubi/create/content/redstone/diodes/ToggleLatchGenerator.java similarity index 95% rename from src/main/java/com/simibubi/create/content/logistics/block/diodes/ToggleLatchGenerator.java rename to src/main/java/com/simibubi/create/content/redstone/diodes/ToggleLatchGenerator.java index 9e09e32fd..c98d3a51a 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/diodes/ToggleLatchGenerator.java +++ b/src/main/java/com/simibubi/create/content/redstone/diodes/ToggleLatchGenerator.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.block.diodes; +package com.simibubi.create.content.redstone.diodes; import java.util.Vector; diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/AllDisplayBehaviours.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/AllDisplayBehaviours.java new file mode 100644 index 000000000..43963ea65 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/AllDisplayBehaviours.java @@ -0,0 +1,246 @@ +package com.simibubi.create.content.redstone.displayLink; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.annotation.Nullable; + +import com.simibubi.create.Create; +import com.simibubi.create.compat.Mods; +import com.simibubi.create.content.redstone.displayLink.source.ComputerDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.DeathCounterDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.DisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.EnchantPowerDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.RedstonePowerDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.ScoreboardDisplaySource; +import com.simibubi.create.content.redstone.displayLink.target.DisplayTarget; +import com.simibubi.create.content.redstone.displayLink.target.LecternDisplayTarget; +import com.simibubi.create.content.redstone.displayLink.target.SignDisplayTarget; +import com.simibubi.create.foundation.utility.AttachedRegistry; +import com.simibubi.create.foundation.utility.RegisteredObjects; +import com.tterrag.registrate.util.nullness.NonNullConsumer; + +import net.minecraft.core.BlockPos; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.entity.SignBlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.registries.ForgeRegistries; + +public class AllDisplayBehaviours { + public static final Map GATHERER_BEHAVIOURS = new HashMap<>(); + + private static final AttachedRegistry> SOURCES_BY_BLOCK = new AttachedRegistry<>(ForgeRegistries.BLOCKS); + private static final AttachedRegistry, List> SOURCES_BY_BLOCK_ENTITY = new AttachedRegistry<>(ForgeRegistries.BLOCK_ENTITY_TYPES); + + private static final AttachedRegistry TARGETS_BY_BLOCK = new AttachedRegistry<>(ForgeRegistries.BLOCKS); + private static final AttachedRegistry, DisplayTarget> TARGETS_BY_BLOCK_ENTITY = new AttachedRegistry<>(ForgeRegistries.BLOCK_ENTITY_TYPES); + + public static DisplayBehaviour register(ResourceLocation id, DisplayBehaviour behaviour) { + behaviour.id = id; + GATHERER_BEHAVIOURS.put(id, behaviour); + return behaviour; + } + + public static void assignBlock(DisplayBehaviour behaviour, ResourceLocation block) { + if (behaviour instanceof DisplaySource source) { + List sources = SOURCES_BY_BLOCK.get(block); + if (sources == null) { + sources = new ArrayList<>(); + SOURCES_BY_BLOCK.register(block, sources); + } + sources.add(source); + } + if (behaviour instanceof DisplayTarget target) { + TARGETS_BY_BLOCK.register(block, target); + } + } + + public static void assignBlockEntity(DisplayBehaviour behaviour, ResourceLocation beType) { + if (behaviour instanceof DisplaySource source) { + List sources = SOURCES_BY_BLOCK_ENTITY.get(beType); + if (sources == null) { + sources = new ArrayList<>(); + SOURCES_BY_BLOCK_ENTITY.register(beType, sources); + } + sources.add(source); + } + if (behaviour instanceof DisplayTarget target) { + TARGETS_BY_BLOCK_ENTITY.register(beType, target); + } + } + + public static void assignBlock(DisplayBehaviour behaviour, Block block) { + if (behaviour instanceof DisplaySource source) { + List sources = SOURCES_BY_BLOCK.get(block); + if (sources == null) { + sources = new ArrayList<>(); + SOURCES_BY_BLOCK.register(block, sources); + } + sources.add(source); + } + if (behaviour instanceof DisplayTarget target) { + TARGETS_BY_BLOCK.register(block, target); + } + } + + public static void assignBlockEntity(DisplayBehaviour behaviour, BlockEntityType beType) { + if (behaviour instanceof DisplaySource source) { + List sources = SOURCES_BY_BLOCK_ENTITY.get(beType); + if (sources == null) { + sources = new ArrayList<>(); + SOURCES_BY_BLOCK_ENTITY.register(beType, sources); + } + sources.add(source); + } + if (behaviour instanceof DisplayTarget target) { + TARGETS_BY_BLOCK_ENTITY.register(beType, target); + } + } + + public static NonNullConsumer assignDataBehaviour(DisplayBehaviour behaviour, + String... suffix) { + return b -> { + ResourceLocation registryName = RegisteredObjects.getKeyOrThrow(b); + String idSuffix = behaviour instanceof DisplaySource ? "_source" : "_target"; + if (suffix.length > 0) + idSuffix += "_" + suffix[0]; + assignBlock(register(new ResourceLocation(registryName.getNamespace(), registryName.getPath() + idSuffix), + behaviour), registryName); + }; + } + + public static > NonNullConsumer assignDataBehaviourBE( + DisplayBehaviour behaviour, String... suffix) { + return b -> { + ResourceLocation registryName = RegisteredObjects.getKeyOrThrow(b); + String idSuffix = behaviour instanceof DisplaySource ? "_source" : "_target"; + if (suffix.length > 0) + idSuffix += "_" + suffix[0]; + assignBlockEntity( + register(new ResourceLocation(registryName.getNamespace(), registryName.getPath() + idSuffix), + behaviour), + registryName); + }; + } + + // + + @Nullable + public static DisplaySource getSource(ResourceLocation resourceLocation) { + DisplayBehaviour available = GATHERER_BEHAVIOURS.getOrDefault(resourceLocation, null); + if (available instanceof DisplaySource source) + return source; + return null; + } + + @Nullable + public static DisplayTarget getTarget(ResourceLocation resourceLocation) { + DisplayBehaviour available = GATHERER_BEHAVIOURS.getOrDefault(resourceLocation, null); + if (available instanceof DisplayTarget target) + return target; + return null; + } + + // + + public static List sourcesOf(Block block) { + List sources = SOURCES_BY_BLOCK.get(block); + if (sources == null) { + return Collections.emptyList(); + } + return sources; + } + + public static List sourcesOf(BlockState state) { + return sourcesOf(state.getBlock()); + } + + public static List sourcesOf(BlockEntityType blockEntityType) { + List sources = SOURCES_BY_BLOCK_ENTITY.get(blockEntityType); + if (sources == null) { + return Collections.emptyList(); + } + return sources; + } + + public static List sourcesOf(BlockEntity blockEntity) { + return sourcesOf(blockEntity.getType()); + } + + @Nullable + public static DisplayTarget targetOf(Block block) { + return TARGETS_BY_BLOCK.get(block); + } + + @Nullable + public static DisplayTarget targetOf(BlockState state) { + return targetOf(state.getBlock()); + } + + @Nullable + public static DisplayTarget targetOf(BlockEntityType blockEntityType) { + return TARGETS_BY_BLOCK_ENTITY.get(blockEntityType); + } + + @Nullable + public static DisplayTarget targetOf(BlockEntity blockEntity) { + return targetOf(blockEntity.getType()); + } + + public static List sourcesOf(LevelAccessor level, BlockPos pos) { + BlockState blockState = level.getBlockState(pos); + BlockEntity blockEntity = level.getBlockEntity(pos); + + List sourcesOfBlock = sourcesOf(blockState); + List sourcesOfBlockEntity = blockEntity == null ? Collections.emptyList() : sourcesOf(blockEntity); + + if (sourcesOfBlockEntity.isEmpty()) + return sourcesOfBlock; + return sourcesOfBlockEntity; + } + + @Nullable + public static DisplayTarget targetOf(LevelAccessor level, BlockPos pos) { + BlockState blockState = level.getBlockState(pos); + BlockEntity blockEntity = level.getBlockEntity(pos); + + DisplayTarget targetOfBlock = targetOf(blockState); + DisplayTarget targetOfBlockEntity = blockEntity == null ? null : targetOf(blockEntity); + + // Commonly added by mods, but with a non-vanilla blockentitytype + if (targetOfBlockEntity == null && blockEntity instanceof SignBlockEntity) + targetOfBlockEntity = targetOf(BlockEntityType.SIGN); + + if (targetOfBlockEntity == null) + return targetOfBlock; + return targetOfBlockEntity; + } + + // + + public static void registerDefaults() { + assignBlockEntity(register(Create.asResource("sign_display_target"), new SignDisplayTarget()), BlockEntityType.SIGN); + assignBlockEntity(register(Create.asResource("lectern_display_target"), new LecternDisplayTarget()), BlockEntityType.LECTERN); + assignBlock(register(Create.asResource("death_count_display_source"), new DeathCounterDisplaySource()), Blocks.RESPAWN_ANCHOR); + assignBlockEntity(register(Create.asResource("scoreboard_display_source"), new ScoreboardDisplaySource()), BlockEntityType.COMMAND_BLOCK); + assignBlockEntity(register(Create.asResource("enchant_power_display_source"), new EnchantPowerDisplaySource()), BlockEntityType.ENCHANTING_TABLE); + assignBlock(register(Create.asResource("redstone_power_display_source"), new RedstonePowerDisplaySource()), Blocks.TARGET); + + Mods.COMPUTERCRAFT.executeIfInstalled(() -> () -> { + DisplayBehaviour computerDisplaySource = register(Create.asResource("computer_display_source"), new ComputerDisplaySource()); + + assignBlockEntity(computerDisplaySource, new ResourceLocation(Mods.COMPUTERCRAFT.asId(), "wired_modem_full")); + assignBlockEntity(computerDisplaySource, new ResourceLocation(Mods.COMPUTERCRAFT.asId(), "computer_normal")); + assignBlockEntity(computerDisplaySource, new ResourceLocation(Mods.COMPUTERCRAFT.asId(), "computer_advanced")); + assignBlockEntity(computerDisplaySource, new ResourceLocation(Mods.COMPUTERCRAFT.asId(), "computer_command")); + }); + } +} diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayBehaviour.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayBehaviour.java new file mode 100644 index 000000000..7c067394d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayBehaviour.java @@ -0,0 +1,9 @@ +package com.simibubi.create.content.redstone.displayLink; + +import net.minecraft.resources.ResourceLocation; + +public abstract class DisplayBehaviour { + + public ResourceLocation id; + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/DisplayLinkBlock.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkBlock.java similarity index 80% rename from src/main/java/com/simibubi/create/content/logistics/block/display/DisplayLinkBlock.java rename to src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkBlock.java index 85ae770fc..0601fe82f 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/DisplayLinkBlock.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkBlock.java @@ -1,15 +1,15 @@ -package com.simibubi.create.content.logistics.block.display; +package com.simibubi.create.content.redstone.displayLink; import java.util.function.BiConsumer; import java.util.function.Consumer; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.logistics.block.display.source.DisplaySource; -import com.simibubi.create.content.logistics.block.display.source.RedstonePowerDisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.DisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.RedstonePowerDisplaySource; import com.simibubi.create.foundation.advancement.AdvancementBehaviour; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.block.WrenchableDirectionalBlock; import com.simibubi.create.foundation.gui.ScreenOpener; import com.simibubi.create.foundation.utility.Iterate; @@ -42,7 +42,7 @@ import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.fml.DistExecutor; -public class DisplayLinkBlock extends WrenchableDirectionalBlock implements ITE { +public class DisplayLinkBlock extends WrenchableDirectionalBlock implements IBE { public static final BooleanProperty POWERED = BlockStateProperties.POWERED; @@ -65,12 +65,12 @@ public class DisplayLinkBlock extends WrenchableDirectionalBlock implements ITE< } public static void notifyGatherers(LevelAccessor level, BlockPos pos) { - forEachAttachedGatherer(level, pos, DisplayLinkTileEntity::updateGatheredData); + forEachAttachedGatherer(level, pos, DisplayLinkBlockEntity::updateGatheredData); } @SuppressWarnings("unchecked") public static void sendToGatherers(LevelAccessor level, BlockPos pos, - BiConsumer callback, Class type) { + BiConsumer callback, Class type) { forEachAttachedGatherer(level, pos, dgte -> { if (type.isInstance(dgte.activeSource)) callback.accept(dgte, (T) dgte.activeSource); @@ -78,7 +78,7 @@ public class DisplayLinkBlock extends WrenchableDirectionalBlock implements ITE< } private static void forEachAttachedGatherer(LevelAccessor level, BlockPos pos, - Consumer callback) { + Consumer callback) { for (Direction d : Iterate.directions) { BlockPos offsetPos = pos.relative(d); BlockState blockState = level.getBlockState(offsetPos); @@ -86,14 +86,14 @@ public class DisplayLinkBlock extends WrenchableDirectionalBlock implements ITE< continue; BlockEntity blockEntity = level.getBlockEntity(offsetPos); - if (!(blockEntity instanceof DisplayLinkTileEntity dgte)) + if (!(blockEntity instanceof DisplayLinkBlockEntity dlbe)) continue; - if (dgte.activeSource == null) + if (dlbe.activeSource == null) continue; - if (dgte.getDirection() != d.getOpposite()) + if (dlbe.getDirection() != d.getOpposite()) continue; - callback.accept(dgte); + callback.accept(dlbe); } } @@ -112,7 +112,7 @@ public class DisplayLinkBlock extends WrenchableDirectionalBlock implements ITE< if (previouslyPowered != powered) { worldIn.setBlock(pos, state.cycle(POWERED), 2); if (!powered) - withTileEntityDo(worldIn, pos, DisplayLinkTileEntity::onNoLongerPowered); + withBlockEntityDo(worldIn, pos, DisplayLinkBlockEntity::onNoLongerPowered); } } @@ -142,19 +142,19 @@ public class DisplayLinkBlock extends WrenchableDirectionalBlock implements ITE< if (pPlayer.isSteppingCarefully()) return InteractionResult.PASS; DistExecutor.unsafeRunWhenOn(Dist.CLIENT, - () -> () -> withTileEntityDo(pLevel, pPos, te -> this.displayScreen(te, pPlayer))); + () -> () -> withBlockEntityDo(pLevel, pPos, be -> this.displayScreen(be, pPlayer))); return InteractionResult.SUCCESS; } @OnlyIn(value = Dist.CLIENT) - protected void displayScreen(DisplayLinkTileEntity te, Player player) { + protected void displayScreen(DisplayLinkBlockEntity be, Player player) { if (!(player instanceof LocalPlayer)) return; - if (te.targetOffset.equals(BlockPos.ZERO)) { + if (be.targetOffset.equals(BlockPos.ZERO)) { player.displayClientMessage(Lang.translateDirect("display_link.invalid"), true); return; } - ScreenOpener.open(new DisplayLinkScreen(te)); + ScreenOpener.open(new DisplayLinkScreen(be)); } @Override @@ -168,13 +168,13 @@ public class DisplayLinkBlock extends WrenchableDirectionalBlock implements ITE< } @Override - public Class getTileEntityClass() { - return DisplayLinkTileEntity.class; + public Class getBlockEntityClass() { + return DisplayLinkBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.DISPLAY_LINK.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.DISPLAY_LINK.get(); } } diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkBlockEntity.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkBlockEntity.java new file mode 100644 index 000000000..26771c942 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkBlockEntity.java @@ -0,0 +1,226 @@ +package com.simibubi.create.content.redstone.displayLink; + +import java.util.List; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.compat.computercraft.AbstractComputerBehaviour; +import com.simibubi.create.compat.computercraft.ComputerCraftProxy; +import com.simibubi.create.content.redstone.displayLink.source.DisplaySource; +import com.simibubi.create.content.redstone.displayLink.target.DisplayTarget; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.NBTHelper; +import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; + +public class DisplayLinkBlockEntity extends SmartBlockEntity { + + protected BlockPos targetOffset; + + public DisplaySource activeSource; + private CompoundTag sourceConfig; + + public DisplayTarget activeTarget; + public int targetLine; + + public LerpedFloat glow; + private boolean sendPulse; + + public int refreshTicks; + public AbstractComputerBehaviour computerBehaviour; + + public DisplayLinkBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + targetOffset = BlockPos.ZERO; + sourceConfig = new CompoundTag(); + targetLine = 0; + glow = LerpedFloat.linear() + .startWithValue(0); + glow.chase(0, 0.5f, Chaser.EXP); + } + + @Override + public void addBehaviours(List behaviours) { + behaviours.add(computerBehaviour = ComputerCraftProxy.behaviour(this)); + registerAwardables(behaviours, AllAdvancements.DISPLAY_LINK, AllAdvancements.DISPLAY_BOARD); + } + + @Override + public void tick() { + super.tick(); + + if (isVirtual()) { + glow.tickChaser(); + return; + } + + if (activeSource == null) + return; + if (level.isClientSide) { + glow.tickChaser(); + return; + } + + refreshTicks++; + if (refreshTicks < activeSource.getPassiveRefreshTicks() || !activeSource.shouldPassiveReset()) + return; + tickSource(); + } + + public void tickSource() { + refreshTicks = 0; + if (getBlockState().getOptionalValue(DisplayLinkBlock.POWERED) + .orElse(true)) + return; + if (!level.isClientSide) + updateGatheredData(); + } + + public void onNoLongerPowered() { + if (activeSource == null) + return; + refreshTicks = 0; + activeSource.onSignalReset(new DisplayLinkContext(level, this)); + updateGatheredData(); + } + + public void updateGatheredData() { + BlockPos sourcePosition = getSourcePosition(); + BlockPos targetPosition = getTargetPosition(); + + if (!level.isLoaded(targetPosition) || !level.isLoaded(sourcePosition)) + return; + + DisplayTarget target = AllDisplayBehaviours.targetOf(level, targetPosition); + List sources = AllDisplayBehaviours.sourcesOf(level, sourcePosition); + boolean notify = false; + + if (activeTarget != target) { + activeTarget = target; + notify = true; + } + + if (activeSource != null && !sources.contains(activeSource)) { + activeSource = null; + sourceConfig = new CompoundTag(); + notify = true; + } + + if (notify) + notifyUpdate(); + if (activeSource == null || activeTarget == null) + return; + + DisplayLinkContext context = new DisplayLinkContext(level, this); + activeSource.transferData(context, activeTarget, targetLine); + sendPulse = true; + sendData(); + + award(AllAdvancements.DISPLAY_LINK); + } + + @Override + public void writeSafe(CompoundTag tag) { + super.writeSafe(tag); + writeGatheredData(tag); + } + + @Override + protected void write(CompoundTag tag, boolean clientPacket) { + super.write(tag, clientPacket); + writeGatheredData(tag); + if (clientPacket && activeTarget != null) + tag.putString("TargetType", activeTarget.id.toString()); + if (clientPacket && sendPulse) { + sendPulse = false; + NBTHelper.putMarker(tag, "Pulse"); + } + } + + private void writeGatheredData(CompoundTag tag) { + tag.put("TargetOffset", NbtUtils.writeBlockPos(targetOffset)); + tag.putInt("TargetLine", targetLine); + + if (activeSource != null) { + CompoundTag data = sourceConfig.copy(); + data.putString("Id", activeSource.id.toString()); + tag.put("Source", data); + } + } + + @Override + protected void read(CompoundTag tag, boolean clientPacket) { + super.read(tag, clientPacket); + targetOffset = NbtUtils.readBlockPos(tag.getCompound("TargetOffset")); + targetLine = tag.getInt("TargetLine"); + + if (clientPacket && tag.contains("TargetType")) + activeTarget = AllDisplayBehaviours.getTarget(new ResourceLocation(tag.getString("TargetType"))); + if (clientPacket && tag.contains("Pulse")) + glow.setValue(2); + + if (!tag.contains("Source")) + return; + + CompoundTag data = tag.getCompound("Source"); + activeSource = AllDisplayBehaviours.getSource(new ResourceLocation(data.getString("Id"))); + sourceConfig = new CompoundTag(); + if (activeSource != null) + sourceConfig = data.copy(); + } + + @NotNull + @Override + public LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction side) { + if (computerBehaviour.isPeripheralCap(cap)) + return computerBehaviour.getPeripheralCapability(); + + return super.getCapability(cap, side); + } + + @Override + public void invalidateCaps() { + super.invalidateCaps(); + computerBehaviour.removePeripheral(); + } + + public void target(BlockPos targetPosition) { + this.targetOffset = targetPosition.subtract(worldPosition); + } + + public BlockPos getSourcePosition() { + return worldPosition.relative(getDirection()); + } + + public CompoundTag getSourceConfig() { + return sourceConfig; + } + + public void setSourceConfig(CompoundTag sourceConfig) { + this.sourceConfig = sourceConfig; + } + + public Direction getDirection() { + return getBlockState().getOptionalValue(DisplayLinkBlock.FACING) + .orElse(Direction.UP) + .getOpposite(); + } + + public BlockPos getTargetPosition() { + return worldPosition.offset(targetOffset); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/DisplayLinkBlockItem.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkBlockItem.java similarity index 94% rename from src/main/java/com/simibubi/create/content/logistics/block/display/DisplayLinkBlockItem.java rename to src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkBlockItem.java index 9ba8cd707..e1a7857e0 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/DisplayLinkBlockItem.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkBlockItem.java @@ -1,10 +1,10 @@ -package com.simibubi.create.content.logistics.block.display; +package com.simibubi.create.content.redstone.displayLink; import com.simibubi.create.AllBlocks; import com.simibubi.create.CreateClient; -import com.simibubi.create.content.logistics.block.display.target.DisplayTarget; -import com.simibubi.create.foundation.config.AllConfigs; +import com.simibubi.create.content.redstone.displayLink.target.DisplayTarget; import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; @@ -82,7 +82,7 @@ public class DisplayLinkBlockItem extends BlockItem { BlockPos placedPos = pos.relative(pContext.getClickedFace(), state.getMaterial() .isReplaceable() ? 0 : 1); - if (!selectedPos.closerThan(placedPos, AllConfigs.SERVER.logistics.displayLinkRange.get())) { + if (!selectedPos.closerThan(placedPos, AllConfigs.server().logistics.displayLinkRange.get())) { player.displayClientMessage(Lang.translateDirect("display_link.too_far") .withStyle(ChatFormatting.RED), true); return InteractionResult.FAIL; diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkConfigurationPacket.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkConfigurationPacket.java new file mode 100644 index 000000000..70fbba6a6 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkConfigurationPacket.java @@ -0,0 +1,66 @@ +package com.simibubi.create.content.redstone.displayLink; + +import com.simibubi.create.content.redstone.displayLink.source.DisplaySource; +import com.simibubi.create.foundation.networking.BlockEntityConfigurationPacket; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; + +public class DisplayLinkConfigurationPacket extends BlockEntityConfigurationPacket { + + private CompoundTag configData; + private int targetLine; + + public DisplayLinkConfigurationPacket(BlockPos pos, CompoundTag configData, int targetLine) { + super(pos); + this.configData = configData; + this.targetLine = targetLine; + } + + public DisplayLinkConfigurationPacket(FriendlyByteBuf buffer) { + super(buffer); + } + + @Override + protected void writeSettings(FriendlyByteBuf buffer) { + buffer.writeNbt(configData); + buffer.writeInt(targetLine); + } + + @Override + protected void readSettings(FriendlyByteBuf buffer) { + configData = buffer.readNbt(); + targetLine = buffer.readInt(); + } + + @Override + protected void applySettings(DisplayLinkBlockEntity be) { + be.targetLine = targetLine; + + if (!configData.contains("Id")) { + be.notifyUpdate(); + return; + } + + ResourceLocation id = new ResourceLocation(configData.getString("Id")); + DisplaySource source = AllDisplayBehaviours.getSource(id); + if (source == null) { + be.notifyUpdate(); + return; + } + + if (be.activeSource == null || be.activeSource != source) { + be.activeSource = source; + be.setSourceConfig(configData.copy()); + } else { + be.getSourceConfig() + .merge(configData); + } + + be.updateGatheredData(); + be.notifyUpdate(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkContext.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkContext.java new file mode 100644 index 000000000..0bbebc50d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkContext.java @@ -0,0 +1,48 @@ +package com.simibubi.create.content.redstone.displayLink; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; + +public class DisplayLinkContext { + + private Level level; + private DisplayLinkBlockEntity blockEntity; + + public Object flapDisplayContext; + + public DisplayLinkContext(Level level, DisplayLinkBlockEntity blockEntity) { + this.level = level; + this.blockEntity = blockEntity; + } + + public Level level() { + return level; + } + + public DisplayLinkBlockEntity blockEntity() { + return blockEntity; + } + + public BlockEntity getSourceBlockEntity() { + return level.getBlockEntity(getSourcePos()); + } + + public BlockPos getSourcePos() { + return blockEntity.getSourcePosition(); + } + + public BlockEntity getTargetBlockEntity() { + return level.getBlockEntity(getTargetPos()); + } + + public BlockPos getTargetPos() { + return blockEntity.getTargetPosition(); + } + + public CompoundTag sourceConfig() { + return blockEntity.getSourceConfig(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkRenderer.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkRenderer.java new file mode 100644 index 000000000..c53bb68e8 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkRenderer.java @@ -0,0 +1,65 @@ +package com.simibubi.create.content.redstone.displayLink; + +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.RenderTypes; +import com.simibubi.create.foundation.utility.AngleHelper; + +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; +import net.minecraft.world.level.block.state.BlockState; + +public class DisplayLinkRenderer extends SafeBlockEntityRenderer { + + public DisplayLinkRenderer(BlockEntityRendererProvider.Context context) {} + + @Override + protected void renderSafe(DisplayLinkBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + float glow = be.glow.getValue(partialTicks); + if (glow < .125f) + return; + + glow = (float) (1 - (2 * Math.pow(glow - .75f, 2))); + glow = Mth.clamp(glow, -1, 1); + + int color = (int) (200 * glow); + + BlockState blockState = be.getBlockState(); + TransformStack msr = TransformStack.cast(ms); + + Direction face = blockState.getOptionalValue(DisplayLinkBlock.FACING) + .orElse(Direction.UP); + + if (face.getAxis() + .isHorizontal()) + face = face.getOpposite(); + + ms.pushPose(); + + msr.centre() + .rotateY(AngleHelper.horizontalAngle(face)) + .rotateX(-AngleHelper.verticalAngle(face) - 90) + .unCentre(); + + CachedBufferer.partial(AllPartialModels.DISPLAY_LINK_TUBE, blockState) + .light(LightTexture.FULL_BRIGHT) + .renderInto(ms, buffer.getBuffer(RenderType.translucent())); + + CachedBufferer.partial(AllPartialModels.DISPLAY_LINK_GLOW, blockState) + .light(LightTexture.FULL_BRIGHT) + .color(color, color, color, 255) + .disableDiffuse() + .renderInto(ms, buffer.getBuffer(RenderTypes.getAdditive())); + + ms.popPose(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/DisplayLinkScreen.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkScreen.java similarity index 81% rename from src/main/java/com/simibubi/create/content/logistics/block/display/DisplayLinkScreen.java rename to src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkScreen.java index 443d7f7b5..e0742597e 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/DisplayLinkScreen.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/DisplayLinkScreen.java @@ -1,14 +1,15 @@ -package com.simibubi.create.content.logistics.block.display; +package com.simibubi.create.content.redstone.displayLink; import java.util.Collections; import java.util.List; import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.content.logistics.block.display.source.DisplaySource; -import com.simibubi.create.content.logistics.block.display.source.SingleLineDisplaySource; -import com.simibubi.create.content.logistics.block.display.target.DisplayTarget; -import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats; +import com.simibubi.create.AllPackets; +import com.simibubi.create.content.redstone.displayLink.source.DisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.SingleLineDisplaySource; +import com.simibubi.create.content.redstone.displayLink.target.DisplayTarget; +import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; import com.simibubi.create.foundation.gui.AbstractSimiScreen; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; @@ -22,12 +23,11 @@ import com.simibubi.create.foundation.gui.widget.IconButton; import com.simibubi.create.foundation.gui.widget.Label; import com.simibubi.create.foundation.gui.widget.ScrollInput; import com.simibubi.create.foundation.gui.widget.SelectionScrollInput; -import com.simibubi.create.foundation.networking.AllPackets; -import com.simibubi.create.foundation.ponder.PonderTag; import com.simibubi.create.foundation.ponder.ui.PonderTagScreen; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.infrastructure.ponder.AllPonderTags; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.components.events.GuiEventListener; @@ -47,7 +47,7 @@ public class DisplayLinkScreen extends AbstractSimiScreen { private static final ItemStack FALLBACK = new ItemStack(Items.BARRIER); private AllGuiTextures background; - private DisplayLinkTileEntity te; + private DisplayLinkBlockEntity blockEntity; private IconButton confirmButton; BlockState sourceState; @@ -64,9 +64,9 @@ public class DisplayLinkScreen extends AbstractSimiScreen { Couple configWidgets; - public DisplayLinkScreen(DisplayLinkTileEntity te) { + public DisplayLinkScreen(DisplayLinkBlockEntity be) { this.background = AllGuiTextures.DATA_GATHERER; - this.te = te; + this.blockEntity = be; sources = Collections.emptyList(); configWidgets = Couple.create(ModularGuiLine::new); target = null; @@ -92,9 +92,9 @@ public class DisplayLinkScreen extends AbstractSimiScreen { @Override public void tick() { super.tick(); - if (sourceState != null && sourceState.getBlock() != minecraft.level.getBlockState(te.getSourcePosition()) + if (sourceState != null && sourceState.getBlock() != minecraft.level.getBlockState(blockEntity.getSourcePosition()) .getBlock() - || targetState != null && targetState.getBlock() != minecraft.level.getBlockState(te.getTargetPosition()) + || targetState != null && targetState.getBlock() != minecraft.level.getBlockState(blockEntity.getTargetPosition()) .getBlock()) initGathererOptions(); } @@ -102,8 +102,8 @@ public class DisplayLinkScreen extends AbstractSimiScreen { @SuppressWarnings("deprecation") private void initGathererOptions() { ClientLevel level = minecraft.level; - sourceState = level.getBlockState(te.getSourcePosition()); - targetState = level.getBlockState(te.getTargetPosition()); + sourceState = level.getBlockState(blockEntity.getSourcePosition()); + targetState = level.getBlockState(blockEntity.getTargetPosition()); ItemStack asItem; int x = guiLeft; @@ -112,13 +112,13 @@ public class DisplayLinkScreen extends AbstractSimiScreen { Block sourceBlock = sourceState.getBlock(); Block targetBlock = targetState.getBlock(); - asItem = sourceBlock.getCloneItemStack(level, te.getSourcePosition(), sourceState); + asItem = sourceBlock.getCloneItemStack(level, blockEntity.getSourcePosition(), sourceState); ItemStack sourceIcon = asItem == null || asItem.isEmpty() ? FALLBACK : asItem; - asItem = targetBlock.getCloneItemStack(level, te.getTargetPosition(), targetState); + asItem = targetBlock.getCloneItemStack(level, blockEntity.getTargetPosition(), targetState); ItemStack targetIcon = asItem == null || asItem.isEmpty() ? FALLBACK : asItem; - sources = AllDisplayBehaviours.sourcesOf(level, te.getSourcePosition()); - target = AllDisplayBehaviours.targetOf(level, te.getTargetPosition()); + sources = AllDisplayBehaviours.sourcesOf(level, blockEntity.getSourcePosition()); + target = AllDisplayBehaviours.targetOf(level, blockEntity.getTargetPosition()); removeWidget(targetLineSelector); removeWidget(targetLineLabel); @@ -133,9 +133,9 @@ public class DisplayLinkScreen extends AbstractSimiScreen { sourceTypeSelector = null; if (target != null) { - DisplayTargetStats stats = target.provideStats(new DisplayLinkContext(level, te)); + DisplayTargetStats stats = target.provideStats(new DisplayLinkContext(level, blockEntity)); int rows = stats.maxRows(); - int startIndex = Math.min(te.targetLine, rows); + int startIndex = Math.min(blockEntity.targetLine, rows); targetLineLabel = new Label(x + 65, y + 109, Components.immutableEmpty()).withShadow(); targetLineLabel.text = target.getLineOptionText(startIndex); @@ -155,7 +155,7 @@ public class DisplayLinkScreen extends AbstractSimiScreen { sourceWidget = new ElementWidget(x + 37, y + 26) .showingElement(GuiGameElement.of(sourceIcon)) .withCallback((mX, mY) -> { - ScreenOpener.open(new PonderTagScreen(PonderTag.DISPLAY_SOURCES)); + ScreenOpener.open(new PonderTagScreen(AllPonderTags.DISPLAY_SOURCES)); }); sourceWidget.getToolTip().addAll(List.of( @@ -172,7 +172,7 @@ public class DisplayLinkScreen extends AbstractSimiScreen { targetWidget = new ElementWidget(x + 37, y + 105) .showingElement(GuiGameElement.of(targetIcon)) .withCallback((mX, mY) -> { - ScreenOpener.open(new PonderTagScreen(PonderTag.DISPLAY_TARGETS)); + ScreenOpener.open(new PonderTagScreen(AllPonderTags.DISPLAY_TARGETS)); }); targetWidget.getToolTip().addAll(List.of( @@ -187,7 +187,7 @@ public class DisplayLinkScreen extends AbstractSimiScreen { addRenderableWidget(targetWidget); if (!sources.isEmpty()) { - int startIndex = Math.max(sources.indexOf(te.activeSource), 0); + int startIndex = Math.max(sources.indexOf(blockEntity.activeSource), 0); sourceTypeLabel = new Label(x + 65, y + 30, Components.immutableEmpty()).withShadow(); sourceTypeLabel.text = sources.get(startIndex) @@ -214,7 +214,7 @@ public class DisplayLinkScreen extends AbstractSimiScreen { private void initGathererSourceSubOptions(int i) { DisplaySource source = sources.get(i); - source.populateData(new DisplayLinkContext(te.getLevel(), te)); + source.populateData(new DisplayLinkContext(blockEntity.getLevel(), blockEntity)); if (targetLineSelector != null) targetLineSelector @@ -226,11 +226,11 @@ public class DisplayLinkScreen extends AbstractSimiScreen { s.clear(); }); - DisplayLinkContext context = new DisplayLinkContext(minecraft.level, te); + DisplayLinkContext context = new DisplayLinkContext(minecraft.level, blockEntity); configWidgets.forEachWithContext((s, first) -> source.initConfigurationWidgets(context, new ModularGuiLineBuilder(font, s, guiLeft + 60, guiTop + (first ? 51 : 72)), first)); configWidgets - .forEach(s -> s.loadValues(te.getSourceConfig(), this::addRenderableWidget, this::addRenderableOnly)); + .forEach(s -> s.loadValues(blockEntity.getSourceConfig(), this::addRenderableWidget, this::addRenderableOnly)); } @Override @@ -244,7 +244,7 @@ public class DisplayLinkScreen extends AbstractSimiScreen { configWidgets.forEach(s -> s.saveValues(sourceData)); } - AllPackets.channel.sendToServer(new DisplayLinkConfigurationPacket(te.getBlockPos(), sourceData, + AllPackets.getChannel().sendToServer(new DisplayLinkConfigurationPacket(blockEntity.getBlockPos(), sourceData, targetLineSelector == null ? 0 : targetLineSelector.getState())); } @@ -255,7 +255,7 @@ public class DisplayLinkScreen extends AbstractSimiScreen { background.render(ms, x, y, this); MutableComponent header = Lang.translateDirect("display_link.title"); - font.draw(ms, header, x + background.width / 2 - font.width(header) / 2, y + 4, 0x442000); + font.draw(ms, header, x + background.width / 2 - font.width(header) / 2, y + 4, 0x592424); if (sources.isEmpty()) font.drawShadow(ms, Lang.translateDirect("display_link.no_source"), x + 65, y + 30, 0xD3D3D3); @@ -278,7 +278,7 @@ public class DisplayLinkScreen extends AbstractSimiScreen { .scale(40) .rotateX(-22) .rotateY(63); - GuiGameElement.of(te.getBlockState() + GuiGameElement.of(blockEntity.getBlockState() .setValue(DisplayLinkBlock.FACING, Direction.UP)) .render(ms); ms.popPose(); diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/AccumulatedItemCountDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/AccumulatedItemCountDisplaySource.java new file mode 100644 index 000000000..8ebd8f3fd --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/AccumulatedItemCountDisplaySource.java @@ -0,0 +1,53 @@ +package com.simibubi.create.content.redstone.displayLink.source; + +import com.simibubi.create.content.redstone.displayLink.DisplayLinkBlock; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkBlockEntity; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; +import com.simibubi.create.foundation.utility.Components; + +import net.minecraft.network.chat.MutableComponent; + +public class AccumulatedItemCountDisplaySource extends NumericSingleLineDisplaySource { + + @Override + protected MutableComponent provideLine(DisplayLinkContext context, DisplayTargetStats stats) { + return Components.literal(String.valueOf(context.sourceConfig() + .getInt("Collected"))); + } + + public void itemReceived(DisplayLinkBlockEntity be, int amount) { + if (be.getBlockState() + .getOptionalValue(DisplayLinkBlock.POWERED) + .orElse(true)) + return; + + int collected = be.getSourceConfig() + .getInt("Collected"); + be.getSourceConfig() + .putInt("Collected", collected + amount); + be.updateGatheredData(); + } + + @Override + protected String getTranslationKey() { + return "accumulate_items"; + } + + @Override + public int getPassiveRefreshTicks() { + return 200; + } + + @Override + public void onSignalReset(DisplayLinkContext context) { + context.sourceConfig() + .remove("Collected"); + } + + @Override + protected boolean allowsLabeling(DisplayLinkContext context) { + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/BoilerDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/BoilerDisplaySource.java similarity index 81% rename from src/main/java/com/simibubi/create/content/logistics/block/display/source/BoilerDisplaySource.java rename to src/main/java/com/simibubi/create/content/redstone/displayLink/source/BoilerDisplaySource.java index d50164f66..8ea2a88ab 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/BoilerDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/BoilerDisplaySource.java @@ -1,16 +1,16 @@ -package com.simibubi.create.content.logistics.block.display.source; +package com.simibubi.create.content.redstone.displayLink.source; import java.util.List; import java.util.Optional; import java.util.stream.Stream; -import com.simibubi.create.content.contraptions.fluids.tank.BoilerData; -import com.simibubi.create.content.contraptions.fluids.tank.FluidTankTileEntity; -import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; -import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats; -import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayLayout; -import com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection; -import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayTileEntity; +import com.simibubi.create.content.fluids.tank.BoilerData; +import com.simibubi.create.content.fluids.tank.FluidTankBlockEntity; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; +import com.simibubi.create.content.trains.display.FlapDisplayBlockEntity; +import com.simibubi.create.content.trains.display.FlapDisplayLayout; +import com.simibubi.create.content.trains.display.FlapDisplaySection; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Lang; @@ -41,7 +41,7 @@ public class BoilerDisplaySource extends DisplaySource { else if (stats.maxRows() < 4) return notEnoughSpaceDouble; - boolean isBook = context.getTargetTE() instanceof LecternBlockEntity; + boolean isBook = context.getTargetBlockEntity() instanceof LecternBlockEntity; if (isBook) { Stream componentList = getComponents(context, false).map(components -> { @@ -84,7 +84,7 @@ public class BoilerDisplaySource extends DisplaySource { } @Override - public void loadFlapDisplayLayout(DisplayLinkContext context, FlapDisplayTileEntity flapDisplay, + public void loadFlapDisplayLayout(DisplayLinkContext context, FlapDisplayBlockEntity flapDisplay, FlapDisplayLayout layout, int lineIndex) { if (lineIndex == 0 || context.flapDisplayContext instanceof Boolean b && !b) { if (layout.isLayout("Default")) @@ -107,17 +107,17 @@ public class BoilerDisplaySource extends DisplaySource { } private Stream> getComponents(DisplayLinkContext context, boolean forFlapDisplay) { - BlockEntity sourceTE = context.getSourceTE(); - if (!(sourceTE instanceof FluidTankTileEntity tankTile)) + BlockEntity sourceBE = context.getSourceBlockEntity(); + if (!(sourceBE instanceof FluidTankBlockEntity tankBlockEntity)) return Stream.of(EMPTY); - tankTile = tankTile.getControllerTE(); - if (tankTile == null) + tankBlockEntity = tankBlockEntity.getControllerBE(); + if (tankBlockEntity == null) return Stream.of(EMPTY); - BoilerData boiler = tankTile.boiler; + BoilerData boiler = tankBlockEntity.boiler; - int totalTankSize = tankTile.getTotalTankSize(); + int totalTankSize = tankBlockEntity.getTotalTankSize(); boiler.calcMinMaxForSize(totalTankSize); @@ -134,9 +134,9 @@ public class BoilerDisplaySource extends DisplaySource { } return Stream.of(List.of(Lang.translateDirect(label, boiler.getHeatLevelTextComponent())), - List.of(size, boiler.getSizeComponent(!forFlapDisplay, forFlapDisplay, ChatFormatting.BLACK)), - List.of(water, boiler.getWaterComponent(!forFlapDisplay, forFlapDisplay, ChatFormatting.BLACK)), - List.of(heat, boiler.getHeatComponent(!forFlapDisplay, forFlapDisplay, ChatFormatting.BLACK))); + List.of(size, boiler.getSizeComponent(!forFlapDisplay, forFlapDisplay, ChatFormatting.RESET)), + List.of(water, boiler.getWaterComponent(!forFlapDisplay, forFlapDisplay, ChatFormatting.RESET)), + List.of(heat, boiler.getHeatComponent(!forFlapDisplay, forFlapDisplay, ChatFormatting.RESET))); } private int labelWidth() { diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ComputerDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ComputerDisplaySource.java new file mode 100644 index 000000000..1d99ae70b --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ComputerDisplaySource.java @@ -0,0 +1,33 @@ +package com.simibubi.create.content.redstone.displayLink.source; + +import java.util.ArrayList; +import java.util.List; + +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; +import com.simibubi.create.foundation.utility.Components; + +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.MutableComponent; + +public class ComputerDisplaySource extends DisplaySource { + + @Override + public List provideText(DisplayLinkContext context, DisplayTargetStats stats) { + List components = new ArrayList<>(); + ListTag tag = context.sourceConfig().getList("ComputerSourceList", Tag.TAG_STRING); + + for (int i = 0; i < tag.size(); i++) { + components.add(Components.literal(tag.getString(i))); + } + + return components; + } + + @Override + public boolean shouldPassiveReset() { + return false; + } + +} diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/CurrentFloorDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/CurrentFloorDisplaySource.java new file mode 100644 index 000000000..b61a5856a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/CurrentFloorDisplaySource.java @@ -0,0 +1,29 @@ +package com.simibubi.create.content.redstone.displayLink.source; + +import com.simibubi.create.content.contraptions.elevator.ElevatorContactBlockEntity; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; +import com.simibubi.create.foundation.utility.Components; + +import net.minecraft.network.chat.MutableComponent; + +public class CurrentFloorDisplaySource extends SingleLineDisplaySource { + + @Override + protected MutableComponent provideLine(DisplayLinkContext context, DisplayTargetStats stats) { + if (!(context.getSourceBlockEntity() instanceof ElevatorContactBlockEntity ecbe)) + return EMPTY_LINE; + return Components.literal(ecbe.lastReportedCurrentFloor); + } + + @Override + protected String getTranslationKey() { + return "current_floor"; + } + + @Override + protected boolean allowsLabeling(DisplayLinkContext context) { + return false; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/DeathCounterDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/DeathCounterDisplaySource.java similarity index 91% rename from src/main/java/com/simibubi/create/content/logistics/block/display/source/DeathCounterDisplaySource.java rename to src/main/java/com/simibubi/create/content/redstone/displayLink/source/DeathCounterDisplaySource.java index d248da249..f051926fb 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/DeathCounterDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/DeathCounterDisplaySource.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.block.display.source; +package com.simibubi.create.content.redstone.displayLink.source; import com.simibubi.create.foundation.utility.Lang; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/DisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/DisplaySource.java similarity index 75% rename from src/main/java/com/simibubi/create/content/logistics/block/display/source/DisplaySource.java rename to src/main/java/com/simibubi/create/content/redstone/displayLink/source/DisplaySource.java index 5b9877273..b5db5c057 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/DisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/DisplaySource.java @@ -1,16 +1,16 @@ -package com.simibubi.create.content.logistics.block.display.source; +package com.simibubi.create.content.redstone.displayLink.source; import java.util.Arrays; import java.util.List; import com.google.common.collect.ImmutableList; -import com.simibubi.create.content.logistics.block.display.DisplayBehaviour; -import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; -import com.simibubi.create.content.logistics.block.display.target.DisplayBoardTarget; -import com.simibubi.create.content.logistics.block.display.target.DisplayTarget; -import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats; -import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayLayout; -import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayTileEntity; +import com.simibubi.create.content.redstone.displayLink.DisplayBehaviour; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import com.simibubi.create.content.redstone.displayLink.target.DisplayBoardTarget; +import com.simibubi.create.content.redstone.displayLink.target.DisplayTarget; +import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; +import com.simibubi.create.content.trains.display.FlapDisplayBlockEntity; +import com.simibubi.create.content.trains.display.FlapDisplayLayout; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; import com.simibubi.create.foundation.utility.Components; @@ -49,6 +49,10 @@ public abstract class DisplaySource extends DisplayBehaviour { return 100; }; + public boolean shouldPassiveReset() { + return true; + } + protected String getTranslationKey() { return id.getPath(); } @@ -57,11 +61,11 @@ public abstract class DisplaySource extends DisplayBehaviour { return Components.translatable(id.getNamespace() + ".display_source." + getTranslationKey()); } - public void loadFlapDisplayLayout(DisplayLinkContext context, FlapDisplayTileEntity flapDisplay, FlapDisplayLayout layout, int lineIndex) { + public void loadFlapDisplayLayout(DisplayLinkContext context, FlapDisplayBlockEntity flapDisplay, FlapDisplayLayout layout, int lineIndex) { loadFlapDisplayLayout(context, flapDisplay, layout); } - public void loadFlapDisplayLayout(DisplayLinkContext context, FlapDisplayTileEntity flapDisplay, + public void loadFlapDisplayLayout(DisplayLinkContext context, FlapDisplayBlockEntity flapDisplay, FlapDisplayLayout layout) { if (!layout.isLayout("Default")) layout.loadDefault(flapDisplay.getMaxCharCount()); diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/EnchantPowerDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/EnchantPowerDisplaySource.java similarity index 83% rename from src/main/java/com/simibubi/create/content/logistics/block/display/source/EnchantPowerDisplaySource.java rename to src/main/java/com/simibubi/create/content/redstone/displayLink/source/EnchantPowerDisplaySource.java index fddb3f9d5..4de9bc362 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/EnchantPowerDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/EnchantPowerDisplaySource.java @@ -1,7 +1,7 @@ -package com.simibubi.create.content.logistics.block.display.source; +package com.simibubi.create.content.redstone.displayLink.source; -import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; -import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; import com.simibubi.create.foundation.utility.Components; import net.minecraft.core.BlockPos; @@ -21,7 +21,7 @@ public class EnchantPowerDisplaySource extends NumericSingleLineDisplaySource { @Override protected MutableComponent provideLine(DisplayLinkContext context, DisplayTargetStats stats) { - if (!(context.getSourceTE() instanceof EnchantmentTableBlockEntity enchantmentTile)) + if (!(context.getSourceBlockEntity() instanceof EnchantmentTableBlockEntity)) return ZERO.copy(); BlockPos pos = context.getSourcePos(); diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/EntityNameDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/EntityNameDisplaySource.java new file mode 100644 index 000000000..8dd981462 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/EntityNameDisplaySource.java @@ -0,0 +1,39 @@ +package com.simibubi.create.content.redstone.displayLink.source; + +import java.util.List; + +import com.simibubi.create.content.contraptions.actors.seat.SeatEntity; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; + +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.AABB; + +public class EntityNameDisplaySource extends SingleLineDisplaySource { + @Override + protected MutableComponent provideLine(DisplayLinkContext context, DisplayTargetStats stats) { + List seats = context.level().getEntitiesOfClass(SeatEntity.class, new AABB(context.getSourcePos())); + + if (seats.isEmpty()) + return EMPTY_LINE; + + SeatEntity seatEntity = seats.get(0); + List passengers = seatEntity.getPassengers(); + + if (passengers.isEmpty()) + return EMPTY_LINE; + + return passengers.get(0).getDisplayName().copy(); + } + + @Override + protected String getTranslationKey() { + return "entity_name"; + } + + @Override + protected boolean allowsLabeling(DisplayLinkContext context) { + return true; + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/FillLevelDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/FillLevelDisplaySource.java similarity index 77% rename from src/main/java/com/simibubi/create/content/logistics/block/display/source/FillLevelDisplaySource.java rename to src/main/java/com/simibubi/create/content/redstone/displayLink/source/FillLevelDisplaySource.java index dc6807ded..c62551edd 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/FillLevelDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/FillLevelDisplaySource.java @@ -1,7 +1,7 @@ -package com.simibubi.create.content.logistics.block.display.source; +package com.simibubi.create.content.redstone.displayLink.source; -import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; -import com.simibubi.create.content.logistics.block.redstone.StockpileSwitchTileEntity; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import com.simibubi.create.content.redstone.thresholdSwitch.ThresholdSwitchBlockEntity; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; import com.simibubi.create.foundation.utility.Lang; @@ -13,10 +13,10 @@ public class FillLevelDisplaySource extends PercentOrProgressBarDisplaySource { @Override protected Float getProgress(DisplayLinkContext context) { - BlockEntity te = context.getSourceTE(); - if (!(te instanceof StockpileSwitchTileEntity sste)) + BlockEntity be = context.getSourceBlockEntity(); + if (!(be instanceof ThresholdSwitchBlockEntity tsbe)) return null; - return sste.currentLevel; + return tsbe.currentLevel; } @Override diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/FluidAmountDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/FluidAmountDisplaySource.java new file mode 100644 index 000000000..dbed634dc --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/FluidAmountDisplaySource.java @@ -0,0 +1,53 @@ +package com.simibubi.create.content.redstone.displayLink.source; + +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; +import com.simibubi.create.content.redstone.smartObserver.SmartObserverBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.inventory.TankManipulationBehaviour; +import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.FluidFormatter; + +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.IFluidHandler; + +public class FluidAmountDisplaySource extends SingleLineDisplaySource { + + @Override + protected MutableComponent provideLine(DisplayLinkContext context, DisplayTargetStats stats) { + BlockEntity sourceBE = context.getSourceBlockEntity(); + if (!(sourceBE instanceof SmartObserverBlockEntity cobe)) + return EMPTY_LINE; + + TankManipulationBehaviour tankManipulationBehaviour = cobe.getBehaviour(TankManipulationBehaviour.OBSERVE); + FilteringBehaviour filteringBehaviour = cobe.getBehaviour(FilteringBehaviour.TYPE); + IFluidHandler handler = tankManipulationBehaviour.getInventory(); + + if (handler == null) + return EMPTY_LINE; + + long collected = 0; + for (int i = 0; i < handler.getTanks(); i++) { + FluidStack stack = handler.getFluidInTank(i); + if (stack.isEmpty()) + continue; + if (!filteringBehaviour.test(stack)) + continue; + collected += stack.getAmount(); + } + + return Components.literal(FluidFormatter.asString(collected, false)); + } + + @Override + protected String getTranslationKey() { + return "fluid_amount"; + } + + @Override + protected boolean allowsLabeling(DisplayLinkContext context) { + return true; + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/FluidListDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/FluidListDisplaySource.java similarity index 77% rename from src/main/java/com/simibubi/create/content/logistics/block/display/source/FluidListDisplaySource.java rename to src/main/java/com/simibubi/create/content/redstone/displayLink/source/FluidListDisplaySource.java index fa8b725c8..159640f9e 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/FluidListDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/FluidListDisplaySource.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.block.display.source; +package com.simibubi.create.content.redstone.displayLink.source; import java.util.Comparator; import java.util.HashMap; @@ -8,13 +8,13 @@ import java.util.stream.Stream; import org.apache.commons.lang3.mutable.MutableInt; -import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; -import com.simibubi.create.content.logistics.block.redstone.ContentObserverTileEntity; -import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayLayout; -import com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection; -import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayTileEntity; -import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.inventory.TankManipulationBehaviour; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import com.simibubi.create.content.redstone.smartObserver.SmartObserverBlockEntity; +import com.simibubi.create.content.trains.display.FlapDisplayBlockEntity; +import com.simibubi.create.content.trains.display.FlapDisplayLayout; +import com.simibubi.create.content.trains.display.FlapDisplaySection; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.inventory.TankManipulationBehaviour; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.FluidFormatter; @@ -31,12 +31,12 @@ public class FluidListDisplaySource extends ValueListDisplaySource { @Override protected Stream> provideEntries(DisplayLinkContext context, int maxRows) { - BlockEntity sourceTE = context.getSourceTE(); - if (!(sourceTE instanceof ContentObserverTileEntity cote)) + BlockEntity sourceBE = context.getSourceBlockEntity(); + if (!(sourceBE instanceof SmartObserverBlockEntity cobe)) return Stream.empty(); - TankManipulationBehaviour tankManipulationBehaviour = cote.getBehaviour(TankManipulationBehaviour.OBSERVE); - FilteringBehaviour filteringBehaviour = cote.getBehaviour(FilteringBehaviour.TYPE); + TankManipulationBehaviour tankManipulationBehaviour = cobe.getBehaviour(TankManipulationBehaviour.OBSERVE); + FilteringBehaviour filteringBehaviour = cobe.getBehaviour(FilteringBehaviour.TYPE); IFluidHandler handler = tankManipulationBehaviour.getInventory(); if (handler == null) @@ -78,7 +78,7 @@ public class FluidListDisplaySource extends ValueListDisplaySource { } @Override - public void loadFlapDisplayLayout(DisplayLinkContext context, FlapDisplayTileEntity flapDisplay, FlapDisplayLayout layout) { + public void loadFlapDisplayLayout(DisplayLinkContext context, FlapDisplayBlockEntity flapDisplay, FlapDisplayLayout layout) { Integer max = ((MutableInt) context.flapDisplayContext).getValue(); boolean shorten = shortenNumbers(context); int length = FluidFormatter.asString(max, shorten).length(); diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ItemCountDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ItemCountDisplaySource.java new file mode 100644 index 000000000..752718a62 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ItemCountDisplaySource.java @@ -0,0 +1,53 @@ +package com.simibubi.create.content.redstone.displayLink.source; + +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; +import com.simibubi.create.content.redstone.smartObserver.SmartObserverBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.inventory.InvManipulationBehaviour; +import com.simibubi.create.foundation.utility.Components; + +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraftforge.items.IItemHandler; + +public class ItemCountDisplaySource extends NumericSingleLineDisplaySource { + + @Override + protected MutableComponent provideLine(DisplayLinkContext context, DisplayTargetStats stats) { + BlockEntity sourceBE = context.getSourceBlockEntity(); + if (!(sourceBE instanceof SmartObserverBlockEntity cobe)) + return ZERO.copy(); + + InvManipulationBehaviour invManipulationBehaviour = cobe.getBehaviour(InvManipulationBehaviour.TYPE); + FilteringBehaviour filteringBehaviour = cobe.getBehaviour(FilteringBehaviour.TYPE); + IItemHandler handler = invManipulationBehaviour.getInventory(); + + if (handler == null) + return ZERO.copy(); + + int collected = 0; + for (int i = 0; i < handler.getSlots(); i++) { + ItemStack stack = handler.extractItem(i, handler.getSlotLimit(i), true); + if (stack.isEmpty()) + continue; + if (!filteringBehaviour.test(stack)) + continue; + collected += stack.getCount(); + } + + return Components.literal(String.valueOf(collected)); + } + + @Override + protected String getTranslationKey() { + return "count_items"; + } + + @Override + protected boolean allowsLabeling(DisplayLinkContext context) { + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ItemListDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ItemListDisplaySource.java new file mode 100644 index 000000000..2869bbe99 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ItemListDisplaySource.java @@ -0,0 +1,44 @@ +package com.simibubi.create.content.redstone.displayLink.source; + +import java.util.stream.Stream; + +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import com.simibubi.create.content.redstone.smartObserver.SmartObserverBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.inventory.InvManipulationBehaviour; +import com.simibubi.create.foundation.item.CountedItemStackList; +import com.simibubi.create.foundation.utility.IntAttached; + +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraftforge.items.IItemHandler; + +public class ItemListDisplaySource extends ValueListDisplaySource { + + @Override + protected Stream> provideEntries(DisplayLinkContext context, int maxRows) { + BlockEntity sourceBE = context.getSourceBlockEntity(); + if (!(sourceBE instanceof SmartObserverBlockEntity cobe)) + return Stream.empty(); + + InvManipulationBehaviour invManipulationBehaviour = cobe.getBehaviour(InvManipulationBehaviour.TYPE); + FilteringBehaviour filteringBehaviour = cobe.getBehaviour(FilteringBehaviour.TYPE); + IItemHandler handler = invManipulationBehaviour.getInventory(); + + if (handler == null) + return Stream.empty(); + + return new CountedItemStackList(handler, filteringBehaviour).getTopNames(maxRows); + } + + @Override + protected String getTranslationKey() { + return "list_items"; + } + + @Override + protected boolean valueFirst() { + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ItemNameDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ItemNameDisplaySource.java new file mode 100644 index 000000000..5c7aef3c8 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ItemNameDisplaySource.java @@ -0,0 +1,65 @@ +package com.simibubi.create.content.redstone.displayLink.source; + +import org.apache.commons.lang3.mutable.MutableObject; + +import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour; +import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour.TransportedResult; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkBlockEntity; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; + +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.world.item.ItemStack; + +public class ItemNameDisplaySource extends SingleLineDisplaySource { + + @Override + protected MutableComponent provideLine(DisplayLinkContext context, DisplayTargetStats stats) { + DisplayLinkBlockEntity gatherer = context.blockEntity(); + Direction direction = gatherer.getDirection(); + MutableBlockPos pos = gatherer.getSourcePosition() + .mutable(); + + MutableComponent combined = EMPTY_LINE.copy(); + + for (int i = 0; i < 32; i++) { + TransportedItemStackHandlerBehaviour behaviour = + BlockEntityBehaviour.get(context.level(), pos, TransportedItemStackHandlerBehaviour.TYPE); + pos.move(direction); + + if (behaviour == null) + break; + + MutableObject stackHolder = new MutableObject<>(); + behaviour.handleCenteredProcessingOnAllItems(.25f, tis -> { + stackHolder.setValue(tis.stack); + return TransportedResult.doNothing(); + }); + + ItemStack stack = stackHolder.getValue(); + if (stack != null && !stack.isEmpty()) + combined = combined.append(stack.getHoverName()); + } + + return combined; + } + + @Override + protected String getTranslationKey() { + return "combine_item_names"; + } + + @Override + protected boolean allowsLabeling(DisplayLinkContext context) { + return true; + } + + @Override + protected String getFlapDisplayLayoutName(DisplayLinkContext context) { + return "Number"; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/ItemThroughputDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ItemThroughputDisplaySource.java similarity index 82% rename from src/main/java/com/simibubi/create/content/logistics/block/display/source/ItemThroughputDisplaySource.java rename to src/main/java/com/simibubi/create/content/redstone/displayLink/source/ItemThroughputDisplaySource.java index 72f9300af..38ff12f6c 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/ItemThroughputDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ItemThroughputDisplaySource.java @@ -1,9 +1,9 @@ -package com.simibubi.create.content.logistics.block.display.source; +package com.simibubi.create.content.redstone.displayLink.source; -import com.simibubi.create.content.logistics.block.display.DisplayLinkBlock; -import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; -import com.simibubi.create.content.logistics.block.display.DisplayLinkTileEntity; -import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkBlock; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkBlockEntity; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; import com.simibubi.create.foundation.utility.Lang; @@ -30,7 +30,7 @@ public class ItemThroughputDisplaySource extends AccumulatedItemCountDisplaySour if (rate > 0) { long previousTime = conf.getLong("LastReceived"); - long gameTime = context.te() + long gameTime = context.blockEntity() .getLevel() .getGameTime(); int diff = (int) (gameTime - previousTime); @@ -47,14 +47,14 @@ public class ItemThroughputDisplaySource extends AccumulatedItemCountDisplaySour .component(); } - public void itemReceived(DisplayLinkTileEntity te, int amount) { - if (te.getBlockState() + public void itemReceived(DisplayLinkBlockEntity be, int amount) { + if (be.getBlockState() .getOptionalValue(DisplayLinkBlock.POWERED) .orElse(true)) return; - CompoundTag conf = te.getSourceConfig(); - long gameTime = te.getLevel() + CompoundTag conf = be.getSourceConfig(); + long gameTime = be.getLevel() .getGameTime(); if (!conf.contains("LastReceived")) { @@ -95,7 +95,7 @@ public class ItemThroughputDisplaySource extends AccumulatedItemCountDisplaySour conf.putLong("LastReceived", gameTime); conf.putInt("Index", poolIndex + 1); conf.put("PrevRates", rates); - te.updateGatheredData(); + be.updateGatheredData(); } @Override diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/KineticSpeedDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/KineticSpeedDisplaySource.java new file mode 100644 index 000000000..6db6f2491 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/KineticSpeedDisplaySource.java @@ -0,0 +1,52 @@ +package com.simibubi.create.content.redstone.displayLink.source; + +import com.simibubi.create.content.kinetics.gauge.SpeedGaugeBlockEntity; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; +import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.network.chat.MutableComponent; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public class KineticSpeedDisplaySource extends NumericSingleLineDisplaySource { + + @Override + protected MutableComponent provideLine(DisplayLinkContext context, DisplayTargetStats stats) { + if (!(context.getSourceBlockEntity() instanceof SpeedGaugeBlockEntity speedGauge)) + return ZERO.copy(); + + boolean absoluteValue = context.sourceConfig() + .getInt("Directional") == 0; + float speed = absoluteValue ? Math.abs(speedGauge.getSpeed()) : speedGauge.getSpeed(); + return Lang.number(speed) + .space() + .translate("generic.unit.rpm") + .component(); + } + + @Override + protected String getTranslationKey() { + return "kinetic_speed"; + } + + @Override + @OnlyIn(Dist.CLIENT) + public void initConfigurationWidgets(DisplayLinkContext context, ModularGuiLineBuilder builder, + boolean isFirstLine) { + super.initConfigurationWidgets(context, builder, isFirstLine); + if (isFirstLine) + return; + + builder.addSelectionScrollInput(0, 95, (selectionScrollInput, label) -> { + selectionScrollInput + .forOptions(Lang.translatedOptions("display_source.kinetic_speed", "absolute", "directional")); + }, "Directional"); + } + + @Override + protected boolean allowsLabeling(DisplayLinkContext context) { + return true; + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/KineticStressDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/KineticStressDisplaySource.java similarity index 78% rename from src/main/java/com/simibubi/create/content/logistics/block/display/source/KineticStressDisplaySource.java rename to src/main/java/com/simibubi/create/content/redstone/displayLink/source/KineticStressDisplaySource.java index 1a1a06185..343a2b283 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/KineticStressDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/KineticStressDisplaySource.java @@ -1,8 +1,8 @@ -package com.simibubi.create.content.logistics.block.display.source; +package com.simibubi.create.content.redstone.displayLink.source; -import com.simibubi.create.content.contraptions.relays.gauge.StressGaugeTileEntity; -import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; -import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayTileEntity; +import com.simibubi.create.content.kinetics.gauge.StressGaugeBlockEntity; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import com.simibubi.create.content.trains.display.FlapDisplayBlockEntity; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.LangBuilder; @@ -19,7 +19,7 @@ public class KineticStressDisplaySource extends PercentOrProgressBarDisplaySourc if (mode == 1) return super.formatNumeric(context, currentLevel); LangBuilder builder = Lang.number(currentLevel); - if (context.getTargetTE() instanceof FlapDisplayTileEntity) + if (context.getTargetBlockEntity() instanceof FlapDisplayBlockEntity) builder.space(); return builder.translate("generic.unit.stress") .component(); @@ -32,11 +32,11 @@ public class KineticStressDisplaySource extends PercentOrProgressBarDisplaySourc @Override protected Float getProgress(DisplayLinkContext context) { - if (!(context.getSourceTE()instanceof StressGaugeTileEntity gaugeTile)) + if (!(context.getSourceBlockEntity()instanceof StressGaugeBlockEntity stressGauge)) return null; - float capacity = gaugeTile.getNetworkCapacity(); - float stress = gaugeTile.getNetworkStress(); + float capacity = stressGauge.getNetworkCapacity(); + float stress = stressGauge.getNetworkStress(); if (capacity == 0) return 0f; diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/NixieTubeDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/NixieTubeDisplaySource.java new file mode 100644 index 000000000..3d08cd1f9 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/NixieTubeDisplaySource.java @@ -0,0 +1,60 @@ +package com.simibubi.create.content.redstone.displayLink.source; + +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; +import com.simibubi.create.content.redstone.displayLink.target.NixieTubeDisplayTarget; +import com.simibubi.create.content.redstone.nixieTube.NixieTubeBlockEntity; +import com.simibubi.create.content.trains.display.FlapDisplaySection; + +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.world.level.block.entity.BlockEntity; + +public class NixieTubeDisplaySource extends SingleLineDisplaySource { + + @Override + protected String getTranslationKey() { + return "nixie_tube"; + } + + @Override + protected MutableComponent provideLine(DisplayLinkContext context, DisplayTargetStats stats) { + BlockEntity sourceBE = context.getSourceBlockEntity(); + if (!(sourceBE instanceof NixieTubeBlockEntity nbe)) + return EMPTY_LINE; + + MutableComponent text = nbe.getFullText(); + + try { + String line = text.getString(); + Integer.valueOf(line); + context.flapDisplayContext = Boolean.TRUE; + } catch (NumberFormatException e) { + } + + return text; + } + + @Override + protected boolean allowsLabeling(DisplayLinkContext context) { + return !(context.blockEntity().activeTarget instanceof NixieTubeDisplayTarget); + } + + @Override + protected String getFlapDisplayLayoutName(DisplayLinkContext context) { + if (isNumeric(context)) + return "Number"; + return super.getFlapDisplayLayoutName(context); + } + + @Override + protected FlapDisplaySection createSectionForValue(DisplayLinkContext context, int size) { + if (isNumeric(context)) + return new FlapDisplaySection(size * FlapDisplaySection.MONOSPACE, "numeric", false, false); + return super.createSectionForValue(context, size); + } + + protected boolean isNumeric(DisplayLinkContext context) { + return context.flapDisplayContext == Boolean.TRUE; + } + +} diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/NumericSingleLineDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/NumericSingleLineDisplaySource.java new file mode 100644 index 000000000..ffb702116 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/NumericSingleLineDisplaySource.java @@ -0,0 +1,23 @@ +package com.simibubi.create.content.redstone.displayLink.source; + +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import com.simibubi.create.content.trains.display.FlapDisplaySection; +import com.simibubi.create.foundation.utility.Components; + +import net.minecraft.network.chat.Component; + +public abstract class NumericSingleLineDisplaySource extends SingleLineDisplaySource { + + protected static final Component ZERO = Components.literal("0"); + + @Override + protected String getFlapDisplayLayoutName(DisplayLinkContext context) { + return "Number"; + } + + @Override + protected FlapDisplaySection createSectionForValue(DisplayLinkContext context, int size) { + return new FlapDisplaySection(size * FlapDisplaySection.MONOSPACE, "numeric", false, false); + } + +} diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ObservedTrainNameSource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ObservedTrainNameSource.java new file mode 100644 index 000000000..2503d00d6 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ObservedTrainNameSource.java @@ -0,0 +1,47 @@ +package com.simibubi.create.content.redstone.displayLink.source; + +import java.util.UUID; + +import com.simibubi.create.Create; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; +import com.simibubi.create.content.trains.entity.Train; +import com.simibubi.create.content.trains.observer.TrackObserver; +import com.simibubi.create.content.trains.observer.TrackObserverBlockEntity; + +import net.minecraft.network.chat.MutableComponent; + +public class ObservedTrainNameSource extends SingleLineDisplaySource { + + @Override + protected MutableComponent provideLine(DisplayLinkContext context, DisplayTargetStats stats) { + if (!(context.getSourceBlockEntity() instanceof TrackObserverBlockEntity observerBE)) + return EMPTY_LINE; + TrackObserver observer = observerBE.getObserver(); + if (observer == null) + return EMPTY_LINE; + UUID currentTrain = observer.getCurrentTrain(); + if (currentTrain == null) + return EMPTY_LINE; + Train train = Create.RAILWAYS.trains.get(currentTrain); + if (train == null) + return EMPTY_LINE; + return train.name.copy(); + } + + @Override + public int getPassiveRefreshTicks() { + return 400; + } + + @Override + protected String getTranslationKey() { + return "observed_train_name"; + } + + @Override + protected boolean allowsLabeling(DisplayLinkContext context) { + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/PercentOrProgressBarDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/PercentOrProgressBarDisplaySource.java similarity index 76% rename from src/main/java/com/simibubi/create/content/logistics/block/display/source/PercentOrProgressBarDisplaySource.java rename to src/main/java/com/simibubi/create/content/redstone/displayLink/source/PercentOrProgressBarDisplaySource.java index 5d1da0b7b..b4985985b 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/PercentOrProgressBarDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/PercentOrProgressBarDisplaySource.java @@ -1,13 +1,13 @@ -package com.simibubi.create.content.logistics.block.display.source; +package com.simibubi.create.content.redstone.displayLink.source; -import static com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection.WIDE_MONOSPACE; +import static com.simibubi.create.content.trains.display.FlapDisplaySection.WIDE_MONOSPACE; import javax.annotation.Nullable; -import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; -import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats; -import com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection; -import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayTileEntity; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; +import com.simibubi.create.content.trains.display.FlapDisplayBlockEntity; +import com.simibubi.create.content.trains.display.FlapDisplaySection; import com.simibubi.create.foundation.utility.Components; import net.minecraft.network.chat.MutableComponent; @@ -30,9 +30,9 @@ public abstract class PercentOrProgressBarDisplaySource extends NumericSingleLin int labelSize = label.isEmpty() ? 0 : label.length() + 1; int length = Math.min(stats.maxColumns() - labelSize, 128); - if (context.getTargetTE() instanceof SignBlockEntity) + if (context.getTargetBlockEntity() instanceof SignBlockEntity) length = (int) (length * 6f / 9f); - if (context.getTargetTE() instanceof FlapDisplayTileEntity) + if (context.getTargetBlockEntity() instanceof FlapDisplayBlockEntity) length = sizeForWideChars(length); int filledLength = (int) (currentLevel * length); diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/RedstonePowerDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/RedstonePowerDisplaySource.java similarity index 92% rename from src/main/java/com/simibubi/create/content/logistics/block/display/source/RedstonePowerDisplaySource.java rename to src/main/java/com/simibubi/create/content/redstone/displayLink/source/RedstonePowerDisplaySource.java index 68ff0e51e..45ebde9fb 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/RedstonePowerDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/RedstonePowerDisplaySource.java @@ -1,6 +1,6 @@ -package com.simibubi.create.content.logistics.block.display.source; +package com.simibubi.create.content.redstone.displayLink.source; -import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Lang; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/ScoreboardDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ScoreboardDisplaySource.java similarity index 92% rename from src/main/java/com/simibubi/create/content/logistics/block/display/source/ScoreboardDisplaySource.java rename to src/main/java/com/simibubi/create/content/redstone/displayLink/source/ScoreboardDisplaySource.java index 94947ac35..1081078ae 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/ScoreboardDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ScoreboardDisplaySource.java @@ -1,9 +1,9 @@ -package com.simibubi.create.content.logistics.block.display.source; +package com.simibubi.create.content.redstone.displayLink.source; import java.util.stream.Stream; import com.google.common.collect.ImmutableList; -import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.IntAttached; @@ -19,7 +19,7 @@ public class ScoreboardDisplaySource extends ValueListDisplaySource { @Override protected Stream> provideEntries(DisplayLinkContext context, int maxRows) { - Level level = context.te() + Level level = context.blockEntity() .getLevel(); if (!(level instanceof ServerLevel sLevel)) return Stream.empty(); diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/SingleLineDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/SingleLineDisplaySource.java similarity index 87% rename from src/main/java/com/simibubi/create/content/logistics/block/display/source/SingleLineDisplaySource.java rename to src/main/java/com/simibubi/create/content/redstone/displayLink/source/SingleLineDisplaySource.java index aaa2a2942..a07064dc5 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/SingleLineDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/SingleLineDisplaySource.java @@ -1,13 +1,13 @@ -package com.simibubi.create.content.logistics.block.display.source; +package com.simibubi.create.content.redstone.displayLink.source; import java.util.List; import com.google.common.collect.ImmutableList; -import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; -import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats; -import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayLayout; -import com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection; -import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayTileEntity; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; +import com.simibubi.create.content.trains.display.FlapDisplayBlockEntity; +import com.simibubi.create.content.trains.display.FlapDisplayLayout; +import com.simibubi.create.content.trains.display.FlapDisplaySection; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Lang; @@ -71,7 +71,7 @@ public abstract class SingleLineDisplaySource extends DisplaySource { } @Override - public void loadFlapDisplayLayout(DisplayLinkContext context, FlapDisplayTileEntity flapDisplay, + public void loadFlapDisplayLayout(DisplayLinkContext context, FlapDisplayBlockEntity flapDisplay, FlapDisplayLayout layout) { String layoutKey = getFlapDisplayLayoutName(context); diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/StatTrackingDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/StatTrackingDisplaySource.java similarity index 91% rename from src/main/java/com/simibubi/create/content/logistics/block/display/source/StatTrackingDisplaySource.java rename to src/main/java/com/simibubi/create/content/redstone/displayLink/source/StatTrackingDisplaySource.java index 9d6b9f3f5..14391ef1b 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/StatTrackingDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/StatTrackingDisplaySource.java @@ -1,8 +1,8 @@ -package com.simibubi.create.content.logistics.block.display.source; +package com.simibubi.create.content.redstone.displayLink.source; import java.util.stream.Stream; -import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; import com.simibubi.create.foundation.utility.IntAttached; @@ -22,7 +22,7 @@ public abstract class StatTrackingDisplaySource extends ScoreboardDisplaySource @Override protected Stream> provideEntries(DisplayLinkContext context, int maxRows) { - Level level = context.te() + Level level = context.blockEntity() .getLevel(); if (!(level instanceof ServerLevel sLevel)) return Stream.empty(); diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/StationSummaryDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/StationSummaryDisplaySource.java similarity index 85% rename from src/main/java/com/simibubi/create/content/logistics/block/display/source/StationSummaryDisplaySource.java rename to src/main/java/com/simibubi/create/content/redstone/displayLink/source/StationSummaryDisplaySource.java index 5eba86c04..f56ddfffd 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/StationSummaryDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/StationSummaryDisplaySource.java @@ -1,19 +1,19 @@ -package com.simibubi.create.content.logistics.block.display.source; +package com.simibubi.create.content.redstone.displayLink.source; -import static com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection.MONOSPACE; +import static com.simibubi.create.content.trains.display.FlapDisplaySection.MONOSPACE; import java.util.ArrayList; import java.util.List; import com.google.common.collect.ImmutableList; -import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; -import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats; -import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayLayout; -import com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection; -import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayTileEntity; -import com.simibubi.create.content.logistics.trains.management.display.GlobalTrainDisplayData; -import com.simibubi.create.content.logistics.trains.management.edgePoint.station.GlobalStation; -import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationTileEntity; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; +import com.simibubi.create.content.trains.display.FlapDisplayBlockEntity; +import com.simibubi.create.content.trains.display.FlapDisplayLayout; +import com.simibubi.create.content.trains.display.FlapDisplaySection; +import com.simibubi.create.content.trains.display.GlobalTrainDisplayData; +import com.simibubi.create.content.trains.station.GlobalStation; +import com.simibubi.create.content.trains.station.StationBlockEntity; import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; import com.simibubi.create.foundation.utility.Components; @@ -91,7 +91,7 @@ public class StationSummaryDisplaySource extends DisplaySource { }); if (list.size() > 0) - context.te() + context.blockEntity() .award(AllAdvancements.DISPLAY_BOARD); int toPad = stats.maxRows() - list.size(); @@ -102,7 +102,7 @@ public class StationSummaryDisplaySource extends DisplaySource { } @Override - public void loadFlapDisplayLayout(DisplayLinkContext context, FlapDisplayTileEntity flapDisplay, + public void loadFlapDisplayLayout(DisplayLinkContext context, FlapDisplayBlockEntity flapDisplay, FlapDisplayLayout layout) { CompoundTag conf = context.sourceConfig(); int columnWidth = conf.getInt("NameColumn"); @@ -172,9 +172,9 @@ public class StationSummaryDisplaySource extends DisplaySource { if (conf.contains("Filter")) return; - if (!(context.getSourceTE() instanceof StationTileEntity stationTe)) + if (!(context.getSourceBlockEntity() instanceof StationBlockEntity stationBe)) return; - GlobalStation station = stationTe.getStation(); + GlobalStation station = stationBe.getStation(); if (station == null) return; conf.putString("Filter", station.name); diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/StopWatchDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/StopWatchDisplaySource.java new file mode 100644 index 000000000..5b47472a9 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/StopWatchDisplaySource.java @@ -0,0 +1,74 @@ +package com.simibubi.create.content.redstone.displayLink.source; + +import com.simibubi.create.content.kinetics.clock.CuckooClockBlockEntity; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; +import com.simibubi.create.content.trains.display.FlapDisplaySection; +import com.simibubi.create.foundation.utility.Components; + +import net.minecraft.network.chat.MutableComponent; + +public class StopWatchDisplaySource extends SingleLineDisplaySource { + + @Override + protected MutableComponent provideLine(DisplayLinkContext context, DisplayTargetStats stats) { + if (!(context.getSourceBlockEntity() instanceof CuckooClockBlockEntity ccbe)) + return TimeOfDayDisplaySource.EMPTY_TIME; + if (ccbe.getSpeed() == 0) + return TimeOfDayDisplaySource.EMPTY_TIME; + + if (!context.sourceConfig() + .contains("StartTime")) + onSignalReset(context); + + long started = context.sourceConfig() + .getLong("StartTime"); + long current = context.blockEntity() + .getLevel() + .getGameTime(); + + int diff = (int) (current - started); + int hours = (diff / 60 / 60 / 20); + int minutes = (diff / 60 / 20) % 60; + int seconds = (diff / 20) % 60; + + MutableComponent component = Components.literal((hours == 0 ? "" : (hours < 10 ? " " : "") + hours + ":") + + (minutes < 10 ? hours == 0 ? " " : "0" : "") + minutes + ":" + (seconds < 10 ? "0" : "") + seconds); + + return component; + } + + @Override + public void onSignalReset(DisplayLinkContext context) { + context.sourceConfig() + .putLong("StartTime", context.blockEntity() + .getLevel() + .getGameTime()); + } + + @Override + public int getPassiveRefreshTicks() { + return 20; + } + + @Override + protected boolean allowsLabeling(DisplayLinkContext context) { + return true; + } + + @Override + protected String getFlapDisplayLayoutName(DisplayLinkContext context) { + return "Instant"; + } + + @Override + protected FlapDisplaySection createSectionForValue(DisplayLinkContext context, int size) { + return new FlapDisplaySection(size * FlapDisplaySection.MONOSPACE, "instant", false, false); + } + + @Override + protected String getTranslationKey() { + return "stop_watch"; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/TimeOfDayDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/TimeOfDayDisplaySource.java similarity index 83% rename from src/main/java/com/simibubi/create/content/logistics/block/display/source/TimeOfDayDisplaySource.java rename to src/main/java/com/simibubi/create/content/redstone/displayLink/source/TimeOfDayDisplaySource.java index 2564f67ee..ec95ba5c8 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/TimeOfDayDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/TimeOfDayDisplaySource.java @@ -1,10 +1,10 @@ -package com.simibubi.create.content.logistics.block.display.source; +package com.simibubi.create.content.redstone.displayLink.source; import com.simibubi.create.Create; -import com.simibubi.create.content.contraptions.components.clock.CuckooClockTileEntity; -import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; -import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats; -import com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection; +import com.simibubi.create.content.kinetics.clock.CuckooClockBlockEntity; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; +import com.simibubi.create.content.trains.display.FlapDisplaySection; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Lang; @@ -22,9 +22,9 @@ public class TimeOfDayDisplaySource extends SingleLineDisplaySource { protected MutableComponent provideLine(DisplayLinkContext context, DisplayTargetStats stats) { if (!(context.level()instanceof ServerLevel sLevel)) return EMPTY_TIME; - if (!(context.getSourceTE() instanceof CuckooClockTileEntity ccte)) + if (!(context.getSourceBlockEntity() instanceof CuckooClockBlockEntity ccbe)) return EMPTY_TIME; - if (ccte.getSpeed() == 0) + if (ccbe.getSpeed() == 0) return EMPTY_TIME; boolean c12 = context.sourceConfig() diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/TrainStatusDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/TrainStatusDisplaySource.java new file mode 100644 index 000000000..b2656a125 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/TrainStatusDisplaySource.java @@ -0,0 +1,51 @@ +package com.simibubi.create.content.redstone.displayLink.source; + +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; +import com.simibubi.create.content.trains.entity.Train; +import com.simibubi.create.content.trains.schedule.Schedule; +import com.simibubi.create.content.trains.schedule.ScheduleRuntime; +import com.simibubi.create.content.trains.schedule.ScheduleRuntime.State; +import com.simibubi.create.content.trains.station.GlobalStation; +import com.simibubi.create.content.trains.station.StationBlockEntity; + +import net.minecraft.network.chat.MutableComponent; + +public class TrainStatusDisplaySource extends SingleLineDisplaySource { + + @Override + protected MutableComponent provideLine(DisplayLinkContext context, DisplayTargetStats stats) { + if (!(context.getSourceBlockEntity() instanceof StationBlockEntity observerBE)) + return EMPTY_LINE; + GlobalStation observer = observerBE.getStation(); + if (observer == null) + return EMPTY_LINE; + Train currentTrain = observer.getPresentTrain(); + if (currentTrain == null) + return EMPTY_LINE; + + ScheduleRuntime runtime = currentTrain.runtime; + Schedule schedule = runtime.getSchedule(); + if (schedule == null) + return EMPTY_LINE; + if (runtime.paused) + return EMPTY_LINE; + if (runtime.state != State.POST_TRANSIT) + return EMPTY_LINE; + if (runtime.currentEntry == schedule.entries.size() - 1 && !schedule.cyclic) + return EMPTY_LINE; + + return runtime.getWaitingStatus(context.level()); + } + + @Override + protected boolean allowsLabeling(DisplayLinkContext context) { + return false; + } + + @Override + protected String getTranslationKey() { + return "train_status"; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/source/ValueListDisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ValueListDisplaySource.java similarity index 88% rename from src/main/java/com/simibubi/create/content/logistics/block/display/source/ValueListDisplaySource.java rename to src/main/java/com/simibubi/create/content/redstone/displayLink/source/ValueListDisplaySource.java index b33c98caa..057171755 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/source/ValueListDisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/ValueListDisplaySource.java @@ -1,6 +1,6 @@ -package com.simibubi.create.content.logistics.block.display.source; +package com.simibubi.create.content.redstone.displayLink.source; -import static com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection.MONOSPACE; +import static com.simibubi.create.content.trains.display.FlapDisplaySection.MONOSPACE; import java.util.ArrayList; import java.util.Arrays; @@ -9,11 +9,11 @@ import java.util.stream.Stream; import org.apache.commons.lang3.mutable.MutableInt; -import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; -import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats; -import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayLayout; -import com.simibubi.create.content.logistics.trains.management.display.FlapDisplaySection; -import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayTileEntity; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import com.simibubi.create.content.redstone.displayLink.target.DisplayTargetStats; +import com.simibubi.create.content.trains.display.FlapDisplayBlockEntity; +import com.simibubi.create.content.trains.display.FlapDisplayLayout; +import com.simibubi.create.content.trains.display.FlapDisplaySection; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Couple; @@ -33,7 +33,7 @@ public abstract class ValueListDisplaySource extends DisplaySource { @Override public List provideText(DisplayLinkContext context, DisplayTargetStats stats) { - boolean isBook = context.getTargetTE() instanceof LecternBlockEntity; + boolean isBook = context.getTargetBlockEntity() instanceof LecternBlockEntity; List list = provideEntries(context, stats.maxRows() * (isBook ? ENTRIES_PER_PAGE : 1)) .map(e -> createComponentsFromEntry(context, e)) @@ -104,7 +104,7 @@ public abstract class ValueListDisplaySource extends DisplaySource { } @Override - public void loadFlapDisplayLayout(DisplayLinkContext context, FlapDisplayTileEntity flapDisplay, + public void loadFlapDisplayLayout(DisplayLinkContext context, FlapDisplayBlockEntity flapDisplay, FlapDisplayLayout layout) { boolean valueFirst = valueFirst(); diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/target/DisplayBoardTarget.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/target/DisplayBoardTarget.java new file mode 100644 index 000000000..ba2ae4053 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/target/DisplayBoardTarget.java @@ -0,0 +1,109 @@ +package com.simibubi.create.content.redstone.displayLink.target; + +import java.util.List; + +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import com.simibubi.create.content.redstone.displayLink.source.DisplaySource; +import com.simibubi.create.content.redstone.displayLink.source.SingleLineDisplaySource; +import com.simibubi.create.content.trains.display.FlapDisplayBlockEntity; +import com.simibubi.create.content.trains.display.FlapDisplayLayout; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Vec3i; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.phys.AABB; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public class DisplayBoardTarget extends DisplayTarget { + + @Override + public void acceptText(int line, List text, DisplayLinkContext context) {} + + public void acceptFlapText(int line, List> text, DisplayLinkContext context) { + FlapDisplayBlockEntity controller = getController(context); + if (controller == null) + return; + if (!controller.isSpeedRequirementFulfilled()) + return; + + DisplaySource source = context.blockEntity().activeSource; + List lines = controller.getLines(); + for (int i = 0; i + line < lines.size(); i++) { + + if (i == 0) + reserve(i + line, controller, context); + if (i > 0 && isReserved(i + line, controller, context)) + break; + + FlapDisplayLayout layout = lines.get(i + line); + + if (i >= text.size()) { + if (source instanceof SingleLineDisplaySource) + break; + controller.applyTextManually(i + line, null); + continue; + } + + source.loadFlapDisplayLayout(context, controller, layout, i); + + for (int sectionIndex = 0; sectionIndex < layout.getSections() + .size(); sectionIndex++) { + List textLine = text.get(i); + if (textLine.size() <= sectionIndex) + break; + layout.getSections() + .get(sectionIndex) + .setText(textLine.get(sectionIndex)); + } + } + + controller.sendData(); + } + + @Override + public boolean isReserved(int line, BlockEntity target, DisplayLinkContext context) { + return super.isReserved(line, target, context) + || target instanceof FlapDisplayBlockEntity fdte && fdte.manualLines.length > line && fdte.manualLines[line]; + } + + @Override + public DisplayTargetStats provideStats(DisplayLinkContext context) { + FlapDisplayBlockEntity controller = getController(context); + if (controller == null) + return new DisplayTargetStats(1, 1, this); + return new DisplayTargetStats(controller.ySize * 2, controller.getMaxCharCount(), this); + } + + private FlapDisplayBlockEntity getController(DisplayLinkContext context) { + BlockEntity teIn = context.getTargetBlockEntity(); + if (!(teIn instanceof FlapDisplayBlockEntity be)) + return null; + return be.getController(); + } + + @Override + @OnlyIn(Dist.CLIENT) + public AABB getMultiblockBounds(LevelAccessor level, BlockPos pos) { + AABB baseShape = super.getMultiblockBounds(level, pos); + BlockEntity be = level.getBlockEntity(pos); + + if (!(be instanceof FlapDisplayBlockEntity fdbe)) + return baseShape; + + FlapDisplayBlockEntity controller = fdbe.getController(); + if (controller == null) + return baseShape; + + Vec3i normal = controller.getDirection() + .getClockWise() + .getNormal(); + return baseShape.move(controller.getBlockPos() + .subtract(pos)) + .expandTowards(normal.getX() * (controller.xSize - 1), 1 - controller.ySize, + normal.getZ() * (controller.xSize - 1)); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/target/DisplayTarget.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/target/DisplayTarget.java similarity index 85% rename from src/main/java/com/simibubi/create/content/logistics/block/display/target/DisplayTarget.java rename to src/main/java/com/simibubi/create/content/redstone/displayLink/target/DisplayTarget.java index 819f5e32c..ee6163d8a 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/target/DisplayTarget.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/target/DisplayTarget.java @@ -1,10 +1,10 @@ -package com.simibubi.create.content.logistics.block.display.target; +package com.simibubi.create.content.redstone.displayLink.target; import java.util.List; import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.logistics.block.display.DisplayBehaviour; -import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; +import com.simibubi.create.content.redstone.displayLink.DisplayBehaviour; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; import com.simibubi.create.foundation.utility.Lang; import net.minecraft.core.BlockPos; @@ -41,7 +41,7 @@ public abstract class DisplayTarget extends DisplayBehaviour { CompoundTag tag = target.getPersistentData(); CompoundTag compound = tag.getCompound("DisplayLink"); - compound.putLong("Line" + line, context.te() + compound.putLong("Line" + line, context.blockEntity() .getBlockPos() .asLong()); tag.put("DisplayLink", compound); @@ -57,7 +57,7 @@ public abstract class DisplayTarget extends DisplayBehaviour { long l = compound.getLong("Line" + line); BlockPos reserved = BlockPos.of(l); - if (!reserved.equals(context.te() + if (!reserved.equals(context.blockEntity() .getBlockPos()) && AllBlocks.DISPLAY_LINK.has(target.getLevel() .getBlockState(reserved))) return true; diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/target/DisplayTargetStats.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/target/DisplayTargetStats.java new file mode 100644 index 000000000..13dff9550 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/target/DisplayTargetStats.java @@ -0,0 +1,5 @@ +package com.simibubi.create.content.redstone.displayLink.target; + +public record DisplayTargetStats(int maxRows, int maxColumns, DisplayTarget type) { + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/target/LecternDisplayTarget.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/target/LecternDisplayTarget.java similarity index 90% rename from src/main/java/com/simibubi/create/content/logistics/block/display/target/LecternDisplayTarget.java rename to src/main/java/com/simibubi/create/content/redstone/displayLink/target/LecternDisplayTarget.java index 9e97bdbee..fdc087b4f 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/target/LecternDisplayTarget.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/target/LecternDisplayTarget.java @@ -1,8 +1,8 @@ -package com.simibubi.create.content.logistics.block.display.target; +package com.simibubi.create.content.redstone.displayLink.target; import java.util.List; -import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; import com.simibubi.create.foundation.utility.Lang; import net.minecraft.nbt.CompoundTag; @@ -20,8 +20,8 @@ public class LecternDisplayTarget extends DisplayTarget { @Override public void acceptText(int line, List text, DisplayLinkContext context) { - BlockEntity te = context.getTargetTE(); - if (!(te instanceof LecternBlockEntity lectern)) + BlockEntity be = context.getTargetBlockEntity(); + if (!(be instanceof LecternBlockEntity lectern)) return; ItemStack book = lectern.getBook(); if (book.isEmpty()) diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/target/NixieTubeDisplayTarget.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/target/NixieTubeDisplayTarget.java similarity index 83% rename from src/main/java/com/simibubi/create/content/logistics/block/display/target/NixieTubeDisplayTarget.java rename to src/main/java/com/simibubi/create/content/redstone/displayLink/target/NixieTubeDisplayTarget.java index 2a0857682..13415b9be 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/target/NixieTubeDisplayTarget.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/target/NixieTubeDisplayTarget.java @@ -1,11 +1,11 @@ -package com.simibubi.create.content.logistics.block.display.target; +package com.simibubi.create.content.redstone.displayLink.target; import org.apache.commons.lang3.mutable.MutableInt; import org.apache.commons.lang3.mutable.MutableObject; -import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; -import com.simibubi.create.content.logistics.block.redstone.NixieTubeBlock; -import com.simibubi.create.content.logistics.block.redstone.NixieTubeTileEntity; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; +import com.simibubi.create.content.redstone.nixieTube.NixieTubeBlock; +import com.simibubi.create.content.redstone.nixieTube.NixieTubeBlockEntity; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; @@ -25,7 +25,7 @@ public class NixieTubeDisplayTarget extends SingleLineDisplayTarget { NixieTubeBlock.walkNixies(context.level(), context.getTargetPos(), (currentPos, rowPosition) -> { BlockEntity blockEntity = context.level() .getBlockEntity(currentPos); - if (blockEntity instanceof NixieTubeTileEntity nixie) + if (blockEntity instanceof NixieTubeBlockEntity nixie) nixie.displayCustomText(tagElement, rowPosition); }); } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/target/SignDisplayTarget.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/target/SignDisplayTarget.java similarity index 79% rename from src/main/java/com/simibubi/create/content/logistics/block/display/target/SignDisplayTarget.java rename to src/main/java/com/simibubi/create/content/redstone/displayLink/target/SignDisplayTarget.java index 031f4fe0f..77efd5436 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/target/SignDisplayTarget.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/target/SignDisplayTarget.java @@ -1,8 +1,8 @@ -package com.simibubi.create.content.logistics.block.display.target; +package com.simibubi.create.content.redstone.displayLink.target; import java.util.List; -import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; import net.minecraft.network.chat.MutableComponent; import net.minecraft.world.level.block.entity.BlockEntity; @@ -12,8 +12,8 @@ public class SignDisplayTarget extends DisplayTarget { @Override public void acceptText(int line, List text, DisplayLinkContext context) { - BlockEntity te = context.getTargetTE(); - if (!(te instanceof SignBlockEntity sign)) + BlockEntity be = context.getTargetBlockEntity(); + if (!(be instanceof SignBlockEntity sign)) return; boolean changed = false; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/display/target/SingleLineDisplayTarget.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/target/SingleLineDisplayTarget.java similarity index 84% rename from src/main/java/com/simibubi/create/content/logistics/block/display/target/SingleLineDisplayTarget.java rename to src/main/java/com/simibubi/create/content/redstone/displayLink/target/SingleLineDisplayTarget.java index 0858e5a92..e1a59719f 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/display/target/SingleLineDisplayTarget.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/target/SingleLineDisplayTarget.java @@ -1,8 +1,8 @@ -package com.simibubi.create.content.logistics.block.display.target; +package com.simibubi.create.content.redstone.displayLink.target; import java.util.List; -import com.simibubi.create.content.logistics.block.display.DisplayLinkContext; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkContext; import com.simibubi.create.foundation.utility.Lang; import net.minecraft.network.chat.Component; diff --git a/src/main/java/com/simibubi/create/content/redstone/link/IRedstoneLinkable.java b/src/main/java/com/simibubi/create/content/redstone/link/IRedstoneLinkable.java new file mode 100644 index 000000000..4d44880cb --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/link/IRedstoneLinkable.java @@ -0,0 +1,22 @@ +package com.simibubi.create.content.redstone.link; + +import com.simibubi.create.content.redstone.link.RedstoneLinkNetworkHandler.Frequency; +import com.simibubi.create.foundation.utility.Couple; + +import net.minecraft.core.BlockPos; + +public interface IRedstoneLinkable { + + public int getTransmittedStrength(); + + public void setReceivedStrength(int power); + + public boolean isListening(); + + public boolean isAlive(); + + public Couple getNetworkKey(); + + public BlockPos getLocation(); + +} diff --git a/src/main/java/com/simibubi/create/content/redstone/link/LinkBehaviour.java b/src/main/java/com/simibubi/create/content/redstone/link/LinkBehaviour.java new file mode 100644 index 000000000..982d4d544 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/link/LinkBehaviour.java @@ -0,0 +1,253 @@ +package com.simibubi.create.content.redstone.link; + +import java.util.function.Function; +import java.util.function.IntConsumer; +import java.util.function.IntSupplier; + +import org.apache.commons.lang3.tuple.Pair; + +import com.simibubi.create.Create; +import com.simibubi.create.content.equipment.clipboard.ClipboardCloneable; +import com.simibubi.create.content.redstone.link.RedstoneLinkNetworkHandler.Frequency; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; +import com.simibubi.create.foundation.utility.Couple; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +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.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class LinkBehaviour extends BlockEntityBehaviour implements IRedstoneLinkable, ClipboardCloneable { + + public static final BehaviourType TYPE = new BehaviourType<>(); + + enum Mode { + TRANSMIT, RECEIVE + } + + Frequency frequencyFirst; + Frequency frequencyLast; + ValueBoxTransform firstSlot; + ValueBoxTransform secondSlot; + Vec3 textShift; + + public boolean newPosition; + private Mode mode; + private IntSupplier transmission; + private IntConsumer signalCallback; + + protected LinkBehaviour(SmartBlockEntity be, Pair slots) { + super(be); + frequencyFirst = Frequency.EMPTY; + frequencyLast = Frequency.EMPTY; + firstSlot = slots.getLeft(); + secondSlot = slots.getRight(); + textShift = Vec3.ZERO; + newPosition = true; + } + + public static LinkBehaviour receiver(SmartBlockEntity be, Pair slots, + IntConsumer signalCallback) { + LinkBehaviour behaviour = new LinkBehaviour(be, slots); + behaviour.signalCallback = signalCallback; + behaviour.mode = Mode.RECEIVE; + return behaviour; + } + + public static LinkBehaviour transmitter(SmartBlockEntity be, Pair slots, + IntSupplier transmission) { + LinkBehaviour behaviour = new LinkBehaviour(be, slots); + behaviour.transmission = transmission; + behaviour.mode = Mode.TRANSMIT; + return behaviour; + } + + public LinkBehaviour moveText(Vec3 shift) { + textShift = shift; + return this; + } + + public void copyItemsFrom(LinkBehaviour behaviour) { + if (behaviour == null) + return; + frequencyFirst = behaviour.frequencyFirst; + frequencyLast = behaviour.frequencyLast; + } + + @Override + public boolean isListening() { + return mode == Mode.RECEIVE; + } + + @Override + public int getTransmittedStrength() { + return mode == Mode.TRANSMIT ? transmission.getAsInt() : 0; + } + + @Override + public void setReceivedStrength(int networkPower) { + if (!newPosition) + return; + signalCallback.accept(networkPower); + } + + public void notifySignalChange() { + Create.REDSTONE_LINK_NETWORK_HANDLER.updateNetworkOf(getWorld(), this); + } + + @Override + public void initialize() { + super.initialize(); + if (getWorld().isClientSide) + return; + getHandler().addToNetwork(getWorld(), this); + newPosition = true; + } + + @Override + public Couple getNetworkKey() { + return Couple.create(frequencyFirst, frequencyLast); + } + + @Override + public void unload() { + super.unload(); + if (getWorld().isClientSide) + return; + getHandler().removeFromNetwork(getWorld(), this); + } + + @Override + public boolean isSafeNBT() { + return true; + } + + @Override + public void write(CompoundTag nbt, boolean clientPacket) { + super.write(nbt, clientPacket); + nbt.put("FrequencyFirst", frequencyFirst.getStack() + .save(new CompoundTag())); + nbt.put("FrequencyLast", frequencyLast.getStack() + .save(new CompoundTag())); + nbt.putLong("LastKnownPosition", blockEntity.getBlockPos() + .asLong()); + } + + @Override + public void read(CompoundTag nbt, boolean clientPacket) { + long positionInTag = blockEntity.getBlockPos() + .asLong(); + long positionKey = nbt.getLong("LastKnownPosition"); + newPosition = positionInTag != positionKey; + + super.read(nbt, clientPacket); + frequencyFirst = Frequency.of(ItemStack.of(nbt.getCompound("FrequencyFirst"))); + frequencyLast = Frequency.of(ItemStack.of(nbt.getCompound("FrequencyLast"))); + } + + public void setFrequency(boolean first, ItemStack stack) { + stack = stack.copy(); + stack.setCount(1); + ItemStack toCompare = first ? frequencyFirst.getStack() : frequencyLast.getStack(); + boolean changed = !ItemStack.isSame(stack, toCompare) || !ItemStack.tagMatches(stack, toCompare); + + if (changed) + getHandler().removeFromNetwork(getWorld(), this); + + if (first) + frequencyFirst = Frequency.of(stack); + else + frequencyLast = Frequency.of(stack); + + if (!changed) + return; + + blockEntity.sendData(); + getHandler().addToNetwork(getWorld(), this); + } + + @Override + public BehaviourType getType() { + return TYPE; + } + + private RedstoneLinkNetworkHandler getHandler() { + return Create.REDSTONE_LINK_NETWORK_HANDLER; + } + + public static class SlotPositioning { + Function> offsets; + Function rotation; + float scale; + + public SlotPositioning(Function> offsetsForState, + Function rotationForState) { + offsets = offsetsForState; + rotation = rotationForState; + scale = 1; + } + + public SlotPositioning scale(float scale) { + this.scale = scale; + return this; + } + + } + + public boolean testHit(Boolean first, Vec3 hit) { + BlockState state = blockEntity.getBlockState(); + Vec3 localHit = hit.subtract(Vec3.atLowerCornerOf(blockEntity.getBlockPos())); + return (first ? firstSlot : secondSlot).testHit(state, localHit); + } + + @Override + public boolean isAlive() { + Level level = getWorld(); + BlockPos pos = getPos(); + if (blockEntity.isChunkUnloaded()) + return false; + if (blockEntity.isRemoved()) + return false; + if (!level.isLoaded(pos)) + return false; + return level.getBlockEntity(pos) == blockEntity; + } + + @Override + public BlockPos getLocation() { + return getPos(); + } + + @Override + public String getClipboardKey() { + return "Frequencies"; + } + + @Override + public boolean writeToClipboard(CompoundTag tag, Direction side) { + tag.put("First", frequencyFirst.getStack() + .save(new CompoundTag())); + tag.put("Last", frequencyLast.getStack() + .save(new CompoundTag())); + return true; + } + + @Override + public boolean readFromClipboard(CompoundTag tag, Player player, Direction side, boolean simulate) { + if (!tag.contains("First") || !tag.contains("Last")) + return false; + if (simulate) + return true; + setFrequency(true, ItemStack.of(tag.getCompound("First"))); + setFrequency(false, ItemStack.of(tag.getCompound("Last"))); + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/redstone/link/LinkHandler.java b/src/main/java/com/simibubi/create/content/redstone/link/LinkHandler.java new file mode 100644 index 000000000..ab4489dad --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/link/LinkHandler.java @@ -0,0 +1,77 @@ +package com.simibubi.create.content.redstone.link; + +import java.util.Arrays; + +import com.simibubi.create.AllItems; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.RaycastHelper; + +import net.minecraft.core.BlockPos; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +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.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.common.util.FakePlayer; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.LogicalSide; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; + +@EventBusSubscriber +public class LinkHandler { + + @SubscribeEvent + public static void onBlockActivated(PlayerInteractEvent.RightClickBlock event) { + Level world = event.getLevel(); + BlockPos pos = event.getPos(); + Player player = event.getEntity(); + InteractionHand hand = event.getHand(); + + if (player.isShiftKeyDown() || player.isSpectator()) + return; + + LinkBehaviour behaviour = BlockEntityBehaviour.get(world, pos, LinkBehaviour.TYPE); + if (behaviour == null) + return; + + ItemStack heldItem = player.getItemInHand(hand); + BlockHitResult ray = RaycastHelper.rayTraceRange(world, player, 10); + if (ray == null) + return; + if (AllItems.LINKED_CONTROLLER.isIn(heldItem)) + return; + if (AllItems.WRENCH.isIn(heldItem)) + return; + + boolean fakePlayer = player instanceof FakePlayer; + boolean fakePlayerChoice = false; + + if (fakePlayer) { + BlockState blockState = world.getBlockState(pos); + Vec3 localHit = ray.getLocation() + .subtract(Vec3.atLowerCornerOf(pos)) + .add(Vec3.atLowerCornerOf(ray.getDirection() + .getNormal()) + .scale(.25f)); + fakePlayerChoice = localHit.distanceToSqr(behaviour.firstSlot.getLocalOffset(blockState)) > localHit + .distanceToSqr(behaviour.secondSlot.getLocalOffset(blockState)); + } + + for (boolean first : Arrays.asList(false, true)) { + if (behaviour.testHit(first, ray.getLocation()) || fakePlayer && fakePlayerChoice == first) { + if (event.getSide() != LogicalSide.CLIENT) + behaviour.setFrequency(first, heldItem); + event.setCanceled(true); + event.setCancellationResult(InteractionResult.SUCCESS); + world.playSound(null, pos, SoundEvents.ITEM_FRAME_ADD_ITEM, SoundSource.BLOCKS, .25f, .1f); + } + } + } + +} diff --git a/src/main/java/com/simibubi/create/content/redstone/link/LinkRenderer.java b/src/main/java/com/simibubi/create/content/redstone/link/LinkRenderer.java new file mode 100644 index 000000000..fe9dd8b56 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/link/LinkRenderer.java @@ -0,0 +1,108 @@ +package com.simibubi.create.content.redstone.link; + +import java.util.ArrayList; +import java.util.List; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.datafixers.util.Pair; +import com.simibubi.create.CreateClient; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBox; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxRenderer; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; +import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.Vec3; + +public class LinkRenderer { + + public static void tick() { + Minecraft mc = Minecraft.getInstance(); + HitResult target = mc.hitResult; + if (target == null || !(target instanceof BlockHitResult)) + return; + + BlockHitResult result = (BlockHitResult) target; + ClientLevel world = mc.level; + BlockPos pos = result.getBlockPos(); + + LinkBehaviour behaviour = BlockEntityBehaviour.get(world, pos, LinkBehaviour.TYPE); + if (behaviour == null) + return; + + Component freq1 = Lang.translateDirect("logistics.firstFrequency"); + Component freq2 = Lang.translateDirect("logistics.secondFrequency"); + + for (boolean first : Iterate.trueAndFalse) { + AABB bb = new AABB(Vec3.ZERO, Vec3.ZERO).inflate(.25f); + Component label = first ? freq1 : freq2; + boolean hit = behaviour.testHit(first, target.getLocation()); + ValueBoxTransform transform = first ? behaviour.firstSlot : behaviour.secondSlot; + + ValueBox box = new ValueBox(label, bb, pos).passive(!hit); + boolean empty = behaviour.getNetworkKey() + .get(first) + .getStack() + .isEmpty(); + + if (!empty) + box.wideOutline(); + + CreateClient.OUTLINER.showValueBox(Pair.of(Boolean.valueOf(first), pos), box.transform(transform)) + .highlightFace(result.getDirection()); + + if (!hit) + continue; + + List tip = new ArrayList<>(); + tip.add(label.copy()); + tip.add( + Lang.translateDirect(empty ? "logistics.filter.click_to_set" : "logistics.filter.click_to_replace")); + CreateClient.VALUE_SETTINGS_HANDLER.showHoverTip(tip); + } + } + + public static void renderOnBlockEntity(SmartBlockEntity be, float partialTicks, PoseStack ms, + MultiBufferSource buffer, int light, int overlay) { + + if (be == null || be.isRemoved()) + return; + + Entity cameraEntity = Minecraft.getInstance().cameraEntity; + float max = AllConfigs.client().filterItemRenderDistance.getF(); + if (!be.isVirtual() && cameraEntity != null && cameraEntity.position() + .distanceToSqr(VecHelper.getCenterOf(be.getBlockPos())) > (max * max)) + return; + + LinkBehaviour behaviour = be.getBehaviour(LinkBehaviour.TYPE); + if (behaviour == null) + return; + + for (boolean first : Iterate.trueAndFalse) { + ValueBoxTransform transform = first ? behaviour.firstSlot : behaviour.secondSlot; + ItemStack stack = first ? behaviour.frequencyFirst.getStack() : behaviour.frequencyLast.getStack(); + + ms.pushPose(); + transform.transform(be.getBlockState(), ms); + ValueBoxRenderer.renderItemIntoValueBox(stack, ms, buffer, light, overlay); + ms.popPose(); + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/RedstoneLinkBlock.java b/src/main/java/com/simibubi/create/content/redstone/link/RedstoneLinkBlock.java similarity index 89% rename from src/main/java/com/simibubi/create/content/logistics/block/redstone/RedstoneLinkBlock.java rename to src/main/java/com/simibubi/create/content/redstone/link/RedstoneLinkBlock.java index c05385471..170168159 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/RedstoneLinkBlock.java +++ b/src/main/java/com/simibubi/create/content/redstone/link/RedstoneLinkBlock.java @@ -1,8 +1,8 @@ -package com.simibubi.create.content.logistics.block.redstone; +package com.simibubi.create.content.redstone.link; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.block.WrenchableDirectionalBlock; import com.simibubi.create.foundation.utility.Iterate; @@ -29,7 +29,7 @@ import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; -public class RedstoneLinkBlock extends WrenchableDirectionalBlock implements ITE { +public class RedstoneLinkBlock extends WrenchableDirectionalBlock implements IBE { public static final BooleanProperty POWERED = BlockStateProperties.POWERED; public static final BooleanProperty RECEIVER = BooleanProperty.create("receiver"); @@ -84,7 +84,7 @@ public class RedstoneLinkBlock extends WrenchableDirectionalBlock implements ITE worldIn.setBlock(pos, state.cycle(POWERED), 2); int transmit = power; - withTileEntityDo(worldIn, pos, te -> te.transmit(transmit)); + withBlockEntityDo(worldIn, pos, be -> be.transmit(transmit)); } private int getPower(Level worldIn, BlockPos pos) { @@ -112,7 +112,7 @@ public class RedstoneLinkBlock extends WrenchableDirectionalBlock implements ITE public int getSignal(BlockState state, BlockGetter blockAccess, BlockPos pos, Direction side) { if (!state.getValue(RECEIVER)) return 0; - return getTileEntityOptional(blockAccess, pos).map(RedstoneLinkTileEntity::getReceivedSignal) + return getBlockEntityOptional(blockAccess, pos).map(RedstoneLinkBlockEntity::getReceivedSignal) .orElse(0); } @@ -134,12 +134,12 @@ public class RedstoneLinkBlock extends WrenchableDirectionalBlock implements ITE if (worldIn.isClientSide) return InteractionResult.SUCCESS; - return onTileEntityUse(worldIn, pos, te -> { + return onBlockEntityUse(worldIn, pos, be -> { Boolean wasReceiver = state.getValue(RECEIVER); boolean blockPowered = worldIn.hasNeighborSignal(pos); worldIn.setBlock(pos, state.cycle(RECEIVER) .setValue(POWERED, blockPowered), 3); - te.transmit(wasReceiver ? 0 : getPower(worldIn, pos)); + be.transmit(wasReceiver ? 0 : getPower(worldIn, pos)); return InteractionResult.SUCCESS; }); } @@ -188,13 +188,13 @@ public class RedstoneLinkBlock extends WrenchableDirectionalBlock implements ITE } @Override - public Class getTileEntityClass() { - return RedstoneLinkTileEntity.class; + public Class getBlockEntityClass() { + return RedstoneLinkBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.REDSTONE_LINK.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.REDSTONE_LINK.get(); } } diff --git a/src/main/java/com/simibubi/create/content/redstone/link/RedstoneLinkBlockEntity.java b/src/main/java/com/simibubi/create/content/redstone/link/RedstoneLinkBlockEntity.java new file mode 100644 index 000000000..7b5b706d2 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/link/RedstoneLinkBlockEntity.java @@ -0,0 +1,129 @@ +package com.simibubi.create.content.redstone.link; + +import java.util.List; + +import org.apache.commons.lang3.tuple.Pair; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; + +public class RedstoneLinkBlockEntity extends SmartBlockEntity { + + private boolean receivedSignalChanged; + private int receivedSignal; + private int transmittedSignal; + private LinkBehaviour link; + private boolean transmitter; + + public RedstoneLinkBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + public void addBehaviours(List behaviours) {} + + @Override + public void addBehavioursDeferred(List behaviours) { + createLink(); + behaviours.add(link); + } + + protected void createLink() { + Pair slots = + ValueBoxTransform.Dual.makeSlots(RedstoneLinkFrequencySlot::new); + link = transmitter ? LinkBehaviour.transmitter(this, slots, this::getSignal) + : LinkBehaviour.receiver(this, slots, this::setSignal); + } + + public int getSignal() { + return transmittedSignal; + } + + public void setSignal(int power) { + if (receivedSignal != power) + receivedSignalChanged = true; + receivedSignal = power; + } + + public void transmit(int strength) { + transmittedSignal = strength; + if (link != null) + link.notifySignalChange(); + } + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + compound.putBoolean("Transmitter", transmitter); + compound.putInt("Receive", getReceivedSignal()); + compound.putBoolean("ReceivedChanged", receivedSignalChanged); + compound.putInt("Transmit", transmittedSignal); + super.write(compound, clientPacket); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + transmitter = compound.getBoolean("Transmitter"); + super.read(compound, clientPacket); + + receivedSignal = compound.getInt("Receive"); + receivedSignalChanged = compound.getBoolean("ReceivedChanged"); + if (level == null || level.isClientSide || !link.newPosition) + transmittedSignal = compound.getInt("Transmit"); + } + + @Override + public void tick() { + super.tick(); + + if (isTransmitterBlock() != transmitter) { + transmitter = isTransmitterBlock(); + LinkBehaviour prevlink = link; + removeBehaviour(LinkBehaviour.TYPE); + createLink(); + link.copyItemsFrom(prevlink); + attachBehaviourLate(link); + } + + if (transmitter) + return; + if (level.isClientSide) + return; + + BlockState blockState = getBlockState(); + if (!AllBlocks.REDSTONE_LINK.has(blockState)) + return; + + if ((getReceivedSignal() > 0) != blockState.getValue(RedstoneLinkBlock.POWERED)) { + receivedSignalChanged = true; + level.setBlockAndUpdate(worldPosition, blockState.cycle(RedstoneLinkBlock.POWERED)); + } + + if (receivedSignalChanged) { + Direction attachedFace = blockState.getValue(RedstoneLinkBlock.FACING) + .getOpposite(); + BlockPos attachedPos = worldPosition.relative(attachedFace); + level.blockUpdated(worldPosition, level.getBlockState(worldPosition) + .getBlock()); + level.blockUpdated(attachedPos, level.getBlockState(attachedPos) + .getBlock()); + receivedSignalChanged = false; + } + } + + protected Boolean isTransmitterBlock() { + return !getBlockState().getValue(RedstoneLinkBlock.RECEIVER); + } + + public int getReceivedSignal() { + return receivedSignal; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/RedstoneLinkFrequencySlot.java b/src/main/java/com/simibubi/create/content/redstone/link/RedstoneLinkFrequencySlot.java similarity index 78% rename from src/main/java/com/simibubi/create/content/logistics/block/redstone/RedstoneLinkFrequencySlot.java rename to src/main/java/com/simibubi/create/content/redstone/link/RedstoneLinkFrequencySlot.java index e3a9526e5..715e7780a 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/RedstoneLinkFrequencySlot.java +++ b/src/main/java/com/simibubi/create/content/redstone/link/RedstoneLinkFrequencySlot.java @@ -1,8 +1,8 @@ -package com.simibubi.create.content.logistics.block.redstone; +package com.simibubi.create.content.redstone.link; import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.VecHelper; @@ -21,13 +21,13 @@ public class RedstoneLinkFrequencySlot extends ValueBoxTransform.Dual { Vec3 vertical = VecHelper.voxelSpace(10f, 2.5f, 5.5f); @Override - protected Vec3 getLocalOffset(BlockState state) { + public Vec3 getLocalOffset(BlockState state) { Direction facing = state.getValue(RedstoneLinkBlock.FACING); - Vec3 location = vertical; + Vec3 location = VecHelper.voxelSpace(8f, 3.01f, 5.5f); if (facing.getAxis() .isHorizontal()) { - location = horizontal; + location = VecHelper.voxelSpace(8f, 5.5f, 3.01f); if (isFirst()) location = location.add(0, 5 / 16f, 0); return rotateHorizontally(state, location); @@ -40,7 +40,7 @@ public class RedstoneLinkFrequencySlot extends ValueBoxTransform.Dual { } @Override - protected void rotate(BlockState state, PoseStack ms) { + public void rotate(BlockState state, PoseStack ms) { Direction facing = state.getValue(RedstoneLinkBlock.FACING); float yRot = facing.getAxis() .isVertical() ? 0 : AngleHelper.horizontalAngle(facing) + 180; @@ -51,8 +51,8 @@ public class RedstoneLinkFrequencySlot extends ValueBoxTransform.Dual { } @Override - protected float getScale() { - return .5f; + public float getScale() { + return .4975f; } } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/RedstoneLinkGenerator.java b/src/main/java/com/simibubi/create/content/redstone/link/RedstoneLinkGenerator.java similarity index 95% rename from src/main/java/com/simibubi/create/content/logistics/block/redstone/RedstoneLinkGenerator.java rename to src/main/java/com/simibubi/create/content/redstone/link/RedstoneLinkGenerator.java index 769138d43..24ca6ae8f 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/RedstoneLinkGenerator.java +++ b/src/main/java/com/simibubi/create/content/redstone/link/RedstoneLinkGenerator.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.block.redstone; +package com.simibubi.create.content.redstone.link; import com.simibubi.create.foundation.data.SpecialBlockStateGen; import com.tterrag.registrate.providers.DataGenContext; diff --git a/src/main/java/com/simibubi/create/content/logistics/RedstoneLinkNetworkHandler.java b/src/main/java/com/simibubi/create/content/redstone/link/RedstoneLinkNetworkHandler.java similarity index 94% rename from src/main/java/com/simibubi/create/content/logistics/RedstoneLinkNetworkHandler.java rename to src/main/java/com/simibubi/create/content/redstone/link/RedstoneLinkNetworkHandler.java index 687bc8845..5faa0f30e 100644 --- a/src/main/java/com/simibubi/create/content/logistics/RedstoneLinkNetworkHandler.java +++ b/src/main/java/com/simibubi/create/content/redstone/link/RedstoneLinkNetworkHandler.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics; +package com.simibubi.create.content.redstone.link; import java.util.HashMap; import java.util.IdentityHashMap; @@ -9,10 +9,9 @@ import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import com.simibubi.create.Create; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.tileEntity.behaviour.linked.LinkBehaviour; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.WorldHelper; +import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.Item; @@ -138,7 +137,7 @@ public class RedstoneLinkNetworkHandler { if (from == to) return true; return from.getLocation() - .closerThan(to.getLocation(), AllConfigs.SERVER.logistics.linkRange.get()); + .closerThan(to.getLocation(), AllConfigs.server().logistics.linkRange.get()); } public Map, Set> networksIn(LevelAccessor world) { diff --git a/src/main/java/com/simibubi/create/content/redstone/link/controller/LecternControllerBlock.java b/src/main/java/com/simibubi/create/content/redstone/link/controller/LecternControllerBlock.java new file mode 100644 index 000000000..a2b793a58 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/link/controller/LecternControllerBlock.java @@ -0,0 +1,108 @@ +package com.simibubi.create.content.redstone.link.controller; + +import java.util.ArrayList; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllItems; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.content.schematics.requirement.ISpecialBlockItemRequirement; +import com.simibubi.create.content.schematics.requirement.ItemRequirement; +import com.simibubi.create.foundation.block.IBE; + +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.item.ItemStack; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.LecternBlock; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.HitResult; + +public class LecternControllerBlock extends LecternBlock + implements IBE, ISpecialBlockItemRequirement { + + public LecternControllerBlock(Properties properties) { + super(properties); + registerDefaultState(defaultBlockState().setValue(HAS_BOOK, true)); + } + + @Override + public Class getBlockEntityClass() { + return LecternControllerBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.LECTERN_CONTROLLER.get(); + } + + @Override + public BlockEntity newBlockEntity(BlockPos p_153573_, BlockState p_153574_) { + return IBE.super.newBlockEntity(p_153573_, p_153574_); + } + + @Override + public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, + BlockHitResult hit) { + if (!player.isShiftKeyDown() && LecternControllerBlockEntity.playerInRange(player, world, pos)) { + if (!world.isClientSide) + withBlockEntityDo(world, pos, be -> be.tryStartUsing(player)); + return InteractionResult.SUCCESS; + } + + if (player.isShiftKeyDown()) { + if (!world.isClientSide) + replaceWithLectern(state, world, pos); + return InteractionResult.SUCCESS; + } + + return InteractionResult.PASS; + } + + @Override + public void onRemove(BlockState state, Level world, BlockPos pos, BlockState newState, boolean isMoving) { + if (!state.is(newState.getBlock())) { + if (!world.isClientSide) + withBlockEntityDo(world, pos, be -> be.dropController(state)); + + super.onRemove(state, world, pos, newState, isMoving); + } + } + + @Override + public int getAnalogOutputSignal(BlockState state, Level world, BlockPos pos) { + return 15; + } + + public void replaceLectern(BlockState lecternState, Level world, BlockPos pos, ItemStack controller) { + world.setBlockAndUpdate(pos, defaultBlockState().setValue(FACING, lecternState.getValue(FACING)) + .setValue(POWERED, lecternState.getValue(POWERED))); + withBlockEntityDo(world, pos, be -> be.setController(controller)); + } + + public void replaceWithLectern(BlockState state, Level world, BlockPos pos) { + AllSoundEvents.CONTROLLER_TAKE.playOnServer(world, pos); + world.setBlockAndUpdate(pos, Blocks.LECTERN.defaultBlockState() + .setValue(FACING, state.getValue(FACING)) + .setValue(POWERED, state.getValue(POWERED))); + } + + @Override + public ItemStack getCloneItemStack(BlockState state, HitResult target, BlockGetter world, BlockPos pos, Player player) { + return Blocks.LECTERN.getCloneItemStack(state, target, world, pos, player); + } + + @Override + public ItemRequirement getRequiredItems(BlockState state, BlockEntity be) { + ArrayList requiredItems = new ArrayList<>(); + requiredItems.add(new ItemStack(Blocks.LECTERN)); + requiredItems.add(new ItemStack(AllItems.LINKED_CONTROLLER.get())); + return new ItemRequirement(ItemRequirement.ItemUseType.CONSUME, requiredItems); + } +} diff --git a/src/main/java/com/simibubi/create/content/redstone/link/controller/LecternControllerBlockEntity.java b/src/main/java/com/simibubi/create/content/redstone/link/controller/LecternControllerBlockEntity.java new file mode 100644 index 000000000..1c0cd29ba --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/link/controller/LecternControllerBlockEntity.java @@ -0,0 +1,179 @@ +package com.simibubi.create.content.redstone.link.controller; + +import java.util.List; +import java.util.UUID; + +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; + +import net.minecraft.client.Minecraft; +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.InteractionHand; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.item.ItemEntity; +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.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.common.ForgeMod; +import net.minecraftforge.fml.DistExecutor; + +public class LecternControllerBlockEntity extends SmartBlockEntity { + + private ItemStack controller; + private UUID user; + private UUID prevUser; // used only on client + private boolean deactivatedThisTick; // used only on server + + public LecternControllerBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + public void addBehaviours(List behaviours) { } + + @Override + protected void write(CompoundTag compound, boolean clientPacket) { + super.write(compound, clientPacket); + compound.put("Controller", controller.save(new CompoundTag())); + if (user != null) + compound.putUUID("User", user); + } + + @Override + public void writeSafe(CompoundTag compound) { + super.writeSafe(compound); + compound.put("Controller", controller.save(new CompoundTag())); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + super.read(compound, clientPacket); + controller = ItemStack.of(compound.getCompound("Controller")); + user = compound.hasUUID("User") ? compound.getUUID("User") : null; + } + + public ItemStack getController() { + return controller; + } + + public boolean hasUser() { return user != null; } + + public boolean isUsedBy(Player player) { + return hasUser() && user.equals(player.getUUID()); + } + + public void tryStartUsing(Player player) { + if (!deactivatedThisTick && !hasUser() && !playerIsUsingLectern(player) && playerInRange(player, level, worldPosition)) + startUsing(player); + } + + public void tryStopUsing(Player player) { + if (isUsedBy(player)) + stopUsing(player); + } + + private void startUsing(Player player) { + user = player.getUUID(); + player.getPersistentData().putBoolean("IsUsingLecternController", true); + sendData(); + } + + private void stopUsing(Player player) { + user = null; + if (player != null) + player.getPersistentData().remove("IsUsingLecternController"); + deactivatedThisTick = true; + sendData(); + } + + public static boolean playerIsUsingLectern(Player player) { + return player.getPersistentData().contains("IsUsingLecternController"); + } + + @Override + public void tick() { + super.tick(); + + if (level.isClientSide) { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> this::tryToggleActive); + prevUser = user; + } + + if (!level.isClientSide) { + deactivatedThisTick = false; + + if (!(level instanceof ServerLevel)) + return; + if (user == null) + return; + + Entity entity = ((ServerLevel) level).getEntity(user); + if (!(entity instanceof Player)) { + stopUsing(null); + return; + } + + Player player = (Player) entity; + if (!playerInRange(player, level, worldPosition) || !playerIsUsingLectern(player)) + stopUsing(player); + } + } + + @OnlyIn(Dist.CLIENT) + private void tryToggleActive() { + if (user == null && Minecraft.getInstance().player.getUUID().equals(prevUser)) { + LinkedControllerClientHandler.deactivateInLectern(); + } else if (prevUser == null && Minecraft.getInstance().player.getUUID().equals(user)) { + LinkedControllerClientHandler.activateInLectern(worldPosition); + } + } + + public void setController(ItemStack newController) { + controller = newController; + if (newController != null) { + AllSoundEvents.CONTROLLER_PUT.playOnServer(level, worldPosition); + } + } + + public void swapControllers(ItemStack stack, Player player, InteractionHand hand, BlockState state) { + ItemStack newController = stack.copy(); + stack.setCount(0); + if (player.getItemInHand(hand).isEmpty()) { + player.setItemInHand(hand, controller); + } else { + dropController(state); + } + setController(newController); + } + + public void dropController(BlockState state) { + Entity playerEntity = ((ServerLevel) level).getEntity(user); + if (playerEntity instanceof Player) + stopUsing((Player) playerEntity); + + Direction dir = state.getValue(LecternControllerBlock.FACING); + double x = worldPosition.getX() + 0.5 + 0.25*dir.getStepX(); + double y = worldPosition.getY() + 1; + double z = worldPosition.getZ() + 0.5 + 0.25*dir.getStepZ(); + ItemEntity itementity = new ItemEntity(level, x, y, z, controller.copy()); + itementity.setDefaultPickUpDelay(); + level.addFreshEntity(itementity); + controller = null; + } + + public static boolean playerInRange(Player player, Level world, BlockPos pos) { + //double modifier = world.isRemote ? 0 : 1.0; + double reach = 0.4*player.getAttributeValue(ForgeMod.REACH_DISTANCE.get());// + modifier; + return player.distanceToSqr(Vec3.atCenterOf(pos)) < reach*reach; + } + +} diff --git a/src/main/java/com/simibubi/create/content/redstone/link/controller/LecternControllerRenderer.java b/src/main/java/com/simibubi/create/content/redstone/link/controller/LecternControllerRenderer.java new file mode 100644 index 000000000..355f26380 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/link/controller/LecternControllerRenderer.java @@ -0,0 +1,48 @@ +package com.simibubi.create.content.redstone.link.controller; + +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllItems; +import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; +import com.simibubi.create.foundation.item.render.CustomRenderedItemModel; +import com.simibubi.create.foundation.item.render.PartialItemModelRenderer; +import com.simibubi.create.foundation.utility.AngleHelper; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.block.model.ItemTransforms.TransformType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.core.Direction; +import net.minecraft.world.item.ItemStack; + +public class LecternControllerRenderer extends SafeBlockEntityRenderer { + + public LecternControllerRenderer(BlockEntityRendererProvider.Context context) { + } + + @Override + protected void renderSafe(LecternControllerBlockEntity be, float partialTicks, PoseStack ms, + MultiBufferSource buffer, int light, int overlay) { + + ItemStack stack = AllItems.LINKED_CONTROLLER.asStack(); + TransformType transformType = TransformType.NONE; + CustomRenderedItemModel mainModel = (CustomRenderedItemModel) Minecraft.getInstance() + .getItemRenderer() + .getModel(stack, be.getLevel(), null, 0); + PartialItemModelRenderer renderer = PartialItemModelRenderer.of(stack, transformType, ms, buffer, overlay); + boolean active = be.hasUser(); + boolean renderDepression = be.isUsedBy(Minecraft.getInstance().player); + + Direction facing = be.getBlockState().getValue(LecternControllerBlock.FACING); + TransformStack msr = TransformStack.cast(ms); + + ms.pushPose(); + msr.translate(0.5, 1.45, 0.5); + msr.rotateY(AngleHelper.horizontalAngle(facing) - 90); + msr.translate(0.28, 0, 0); + msr.rotateZ(-22.0); + LinkedControllerItemRenderer.renderInLectern(stack, mainModel, renderer, transformType, ms, light, active, renderDepression); + ms.popPose(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerBindPacket.java b/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerBindPacket.java similarity index 80% rename from src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerBindPacket.java rename to src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerBindPacket.java index 2af7d8555..5c9e790ff 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerBindPacket.java +++ b/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerBindPacket.java @@ -1,7 +1,7 @@ -package com.simibubi.create.content.logistics.item; +package com.simibubi.create.content.redstone.link.controller; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.linked.LinkBehaviour; +import com.simibubi.create.content.redstone.link.LinkBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import net.minecraft.core.BlockPos; import net.minecraft.network.FriendlyByteBuf; @@ -39,7 +39,7 @@ public class LinkedControllerBindPacket extends LinkedControllerPacketBase { return; ItemStackHandler frequencyItems = LinkedControllerItem.getFrequencyItems(heldItem); - LinkBehaviour linkBehaviour = TileEntityBehaviour.get(player.level, linkLocation, LinkBehaviour.TYPE); + LinkBehaviour linkBehaviour = BlockEntityBehaviour.get(player.level, linkLocation, LinkBehaviour.TYPE); if (linkBehaviour == null) return; @@ -52,6 +52,6 @@ public class LinkedControllerBindPacket extends LinkedControllerPacketBase { } @Override - protected void handleLectern(ServerPlayer player, LecternControllerTileEntity lectern) {} + protected void handleLectern(ServerPlayer player, LecternControllerBlockEntity lectern) {} } diff --git a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerClientHandler.java b/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerClientHandler.java similarity index 84% rename from src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerClientHandler.java rename to src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerClientHandler.java index 03ae43bfa..830905e81 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerClientHandler.java +++ b/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerClientHandler.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.item; +package com.simibubi.create.content.redstone.link.controller; import java.util.ArrayList; import java.util.Collection; @@ -12,12 +12,13 @@ import com.mojang.blaze3d.platform.InputConstants; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; +import com.simibubi.create.AllPackets; import com.simibubi.create.AllSoundEvents; import com.simibubi.create.CreateClient; +import com.simibubi.create.content.redstone.link.LinkBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.item.TooltipHelper; -import com.simibubi.create.foundation.networking.AllPackets; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.linked.LinkBehaviour; +import com.simibubi.create.foundation.item.TooltipHelper.Palette; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.ControlsUtil; import com.simibubi.create.foundation.utility.Lang; @@ -90,11 +91,11 @@ public class LinkedControllerClientHandler { selectedLocation = BlockPos.ZERO; if (inLectern()) - AllPackets.channel.sendToServer(new LinkedControllerStopLecternPacket(lecternPos)); + AllPackets.getChannel().sendToServer(new LinkedControllerStopLecternPacket(lecternPos)); lecternPos = null; if (!currentlyPressed.isEmpty()) - AllPackets.channel.sendToServer(new LinkedControllerInputPacket(currentlyPressed, false)); + AllPackets.getChannel().sendToServer(new LinkedControllerInputPacket(currentlyPressed, false)); currentlyPressed.clear(); LinkedControllerItemRenderer.resetButtons(); @@ -128,8 +129,8 @@ public class LinkedControllerClientHandler { } if (inLectern() && AllBlocks.LECTERN_CONTROLLER.get() - .getTileEntityOptional(mc.level, lecternPos) - .map(te -> !te.isUsedBy(mc.player)) + .getBlockEntityOptional(mc.level, lecternPos) + .map(be -> !be.isUsedBy(mc.player)) .orElse(true)) { deactivateInLectern(); return; @@ -163,13 +164,13 @@ public class LinkedControllerClientHandler { if (MODE == Mode.ACTIVE) { // Released Keys if (!releasedKeys.isEmpty()) { - AllPackets.channel.sendToServer(new LinkedControllerInputPacket(releasedKeys, false, lecternPos)); + AllPackets.getChannel().sendToServer(new LinkedControllerInputPacket(releasedKeys, false, lecternPos)); AllSoundEvents.CONTROLLER_CLICK.playAt(player.level, player.blockPosition(), 1f, .5f, true); } // Newly Pressed Keys if (!newKeys.isEmpty()) { - AllPackets.channel.sendToServer(new LinkedControllerInputPacket(newKeys, true, lecternPos)); + AllPackets.getChannel().sendToServer(new LinkedControllerInputPacket(newKeys, true, lecternPos)); packetCooldown = PACKET_RATE; AllSoundEvents.CONTROLLER_CLICK.playAt(player.level, player.blockPosition(), 1f, .75f, true); } @@ -177,7 +178,7 @@ public class LinkedControllerClientHandler { // Keepalive Pressed Keys if (packetCooldown == 0) { if (!pressedKeys.isEmpty()) { - AllPackets.channel.sendToServer(new LinkedControllerInputPacket(pressedKeys, true, lecternPos)); + AllPackets.getChannel().sendToServer(new LinkedControllerInputPacket(pressedKeys, true, lecternPos)); packetCooldown = PACKET_RATE; } } @@ -193,9 +194,9 @@ public class LinkedControllerClientHandler { .lineWidth(1 / 16f); for (Integer integer : newKeys) { - LinkBehaviour linkBehaviour = TileEntityBehaviour.get(mc.level, selectedLocation, LinkBehaviour.TYPE); + LinkBehaviour linkBehaviour = BlockEntityBehaviour.get(mc.level, selectedLocation, LinkBehaviour.TYPE); if (linkBehaviour != null) { - AllPackets.channel.sendToServer(new LinkedControllerBindPacket(integer, selectedLocation)); + AllPackets.getChannel().sendToServer(new LinkedControllerBindPacket(integer, selectedLocation)); Lang.translate("linked_controller.key_bound", controls.get(integer) .getTranslatedKeyMessage() .getString()) @@ -236,7 +237,7 @@ public class LinkedControllerClientHandler { list.add(Lang.translateDirect("linked_controller.bind_mode") .withStyle(ChatFormatting.GOLD)); list.addAll(TooltipHelper.cutTextComponent(Lang.translateDirect("linked_controller.press_keybind", keys), - ChatFormatting.GRAY, ChatFormatting.GRAY)); + Palette.ALL_GRAY)); int width = 0; int height = list.size() * mc.font.lineHeight; diff --git a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerInputPacket.java b/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerInputPacket.java similarity index 95% rename from src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerInputPacket.java rename to src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerInputPacket.java index 48d8f886d..0eabc73a4 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerInputPacket.java +++ b/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerInputPacket.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.item; +package com.simibubi.create.content.redstone.link.controller; import java.util.ArrayList; import java.util.Collection; @@ -44,7 +44,7 @@ public class LinkedControllerInputPacket extends LinkedControllerPacketBase { } @Override - protected void handleLectern(ServerPlayer player, LecternControllerTileEntity lectern) { + protected void handleLectern(ServerPlayer player, LecternControllerBlockEntity lectern) { if (lectern.isUsedBy(player)) handleItem(player, lectern.getController()); } diff --git a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerItem.java b/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerItem.java similarity index 92% rename from src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerItem.java rename to src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerItem.java index 500c06b1e..8988c489d 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerItem.java +++ b/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerItem.java @@ -1,11 +1,11 @@ -package com.simibubi.create.content.logistics.item; +package com.simibubi.create.content.redstone.link.controller; import java.util.function.Consumer; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; -import com.simibubi.create.content.logistics.RedstoneLinkNetworkHandler; -import com.simibubi.create.content.logistics.RedstoneLinkNetworkHandler.Frequency; +import com.simibubi.create.content.redstone.link.RedstoneLinkNetworkHandler; +import com.simibubi.create.content.redstone.link.RedstoneLinkNetworkHandler.Frequency; import com.simibubi.create.foundation.item.render.SimpleCustomRenderer; import com.simibubi.create.foundation.utility.Couple; @@ -53,8 +53,8 @@ public class LinkedControllerItem extends Item implements MenuProvider { if (player.isShiftKeyDown()) { if (AllBlocks.LECTERN_CONTROLLER.has(hitState)) { if (!world.isClientSide) - AllBlocks.LECTERN_CONTROLLER.get().withTileEntityDo(world, pos, te -> - te.swapControllers(stack, player, ctx.getHand(), hitState)); + AllBlocks.LECTERN_CONTROLLER.get().withBlockEntityDo(world, pos, be -> + be.swapControllers(stack, player, ctx.getHand(), hitState)); return InteractionResult.SUCCESS; } } else { @@ -133,7 +133,7 @@ public class LinkedControllerItem extends Item implements MenuProvider { @Override public AbstractContainerMenu createMenu(int id, Inventory inv, Player player) { ItemStack heldItem = player.getMainHandItem(); - return LinkedControllerContainer.create(id, inv, heldItem); + return LinkedControllerMenu.create(id, inv, heldItem); } @Override diff --git a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerItemRenderer.java b/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerItemRenderer.java similarity index 84% rename from src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerItemRenderer.java rename to src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerItemRenderer.java index adfb33b81..0db4bfbea 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerItemRenderer.java +++ b/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerItemRenderer.java @@ -1,11 +1,14 @@ -package com.simibubi.create.content.logistics.item; +package com.simibubi.create.content.redstone.link.controller; import java.util.Vector; +import com.jozufozu.flywheel.core.PartialModel; import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllItems; -import com.simibubi.create.content.logistics.item.LinkedControllerClientHandler.Mode; +import com.simibubi.create.Create; +import com.simibubi.create.content.redstone.link.controller.LinkedControllerClientHandler.Mode; +import com.simibubi.create.foundation.item.render.CustomRenderedItemModel; import com.simibubi.create.foundation.item.render.CustomRenderedItemModelRenderer; import com.simibubi.create.foundation.item.render.PartialItemModelRenderer; import com.simibubi.create.foundation.utility.AnimationTickHolder; @@ -21,7 +24,10 @@ import net.minecraft.util.Mth; import net.minecraft.world.entity.HumanoidArm; import net.minecraft.world.item.ItemStack; -public class LinkedControllerItemRenderer extends CustomRenderedItemModelRenderer { +public class LinkedControllerItemRenderer extends CustomRenderedItemModelRenderer { + + protected static final PartialModel POWERED = new PartialModel(Create.asResource("item/linked_controller/powered")); + protected static final PartialModel BUTTON = new PartialModel(Create.asResource("item/linked_controller/button")); static LerpedFloat equipProgress; static Vector buttons; @@ -61,25 +67,25 @@ public class LinkedControllerItemRenderer extends CustomRenderedItemModelRendere } @Override - protected void render(ItemStack stack, LinkedControllerModel model, PartialItemModelRenderer renderer, + protected void render(ItemStack stack, CustomRenderedItemModel model, PartialItemModelRenderer renderer, ItemTransforms.TransformType transformType, PoseStack ms, MultiBufferSource buffer, int light, int overlay) { renderNormal(stack, model, renderer, transformType, ms, light); } - protected static void renderNormal(ItemStack stack, LinkedControllerModel model, + protected static void renderNormal(ItemStack stack, CustomRenderedItemModel model, PartialItemModelRenderer renderer, ItemTransforms.TransformType transformType, PoseStack ms, int light) { render(stack, model, renderer, transformType, ms, light, RenderType.NORMAL, false, false); } - public static void renderInLectern(ItemStack stack, LinkedControllerModel model, + public static void renderInLectern(ItemStack stack, CustomRenderedItemModel model, PartialItemModelRenderer renderer, ItemTransforms.TransformType transformType, PoseStack ms, int light, boolean active, boolean renderDepression) { render(stack, model, renderer, transformType, ms, light, RenderType.LECTERN, active, renderDepression); } - protected static void render(ItemStack stack, LinkedControllerModel model, + protected static void render(ItemStack stack, CustomRenderedItemModel model, PartialItemModelRenderer renderer, ItemTransforms.TransformType transformType, PoseStack ms, int light, RenderType renderType, boolean active, boolean renderDepression) { float pt = AnimationTickHolder.getPartialTicks(); @@ -119,14 +125,14 @@ public class LinkedControllerItemRenderer extends CustomRenderedItemModelRendere renderDepression = true; } - renderer.render(active ? model.getPartial("powered") : model.getOriginalModel(), light); + renderer.render(active ? POWERED.get() : model.getOriginalModel(), light); if (!active) { ms.popPose(); return; } - BakedModel button = model.getPartial("button"); + BakedModel button = BUTTON.get(); float s = 1 / 16f; float b = s * -.75f; int index = 0; @@ -168,11 +174,6 @@ public class LinkedControllerItemRenderer extends CustomRenderedItemModelRendere ms.popPose(); } - @Override - public LinkedControllerModel createModel(BakedModel originalModel) { - return new LinkedControllerModel(originalModel); - } - protected enum RenderType { NORMAL, LECTERN; } diff --git a/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerMenu.java b/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerMenu.java new file mode 100644 index 000000000..51bb6f905 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerMenu.java @@ -0,0 +1,79 @@ +package com.simibubi.create.content.redstone.link.controller; + +import com.simibubi.create.AllMenuTypes; +import com.simibubi.create.foundation.gui.menu.GhostItemMenu; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.ClickType; +import net.minecraft.world.inventory.MenuType; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.items.ItemStackHandler; +import net.minecraftforge.items.SlotItemHandler; + +public class LinkedControllerMenu extends GhostItemMenu { + + public LinkedControllerMenu(MenuType type, int id, Inventory inv, FriendlyByteBuf extraData) { + super(type, id, inv, extraData); + } + + public LinkedControllerMenu(MenuType type, int id, Inventory inv, ItemStack filterItem) { + super(type, id, inv, filterItem); + } + + public static LinkedControllerMenu create(int id, Inventory inv, ItemStack filterItem) { + return new LinkedControllerMenu(AllMenuTypes.LINKED_CONTROLLER.get(), id, inv, filterItem); + } + + @Override + protected ItemStack createOnClient(FriendlyByteBuf extraData) { + return extraData.readItem(); + } + + @Override + protected ItemStackHandler createGhostInventory() { + return LinkedControllerItem.getFrequencyItems(contentHolder); + } + + @Override + protected void addSlots() { + addPlayerSlots(8, 131); + + int x = 12; + int y = 34; + int slot = 0; + + for (int column = 0; column < 6; column++) { + for (int row = 0; row < 2; ++row) + addSlot(new SlotItemHandler(ghostInventory, slot++, x, y + row * 18)); + x += 24; + if (column == 3) + x += 11; + } + } + + @Override + protected void saveData(ItemStack contentHolder) { + contentHolder.getOrCreateTag() + .put("Items", ghostInventory.serializeNBT()); + } + + @Override + protected boolean allowRepeats() { + return true; + } + + @Override + public void clicked(int slotId, int dragType, ClickType clickTypeIn, Player player) { + if (slotId == playerInventory.selected && clickTypeIn != ClickType.THROW) + return; + super.clicked(slotId, dragType, clickTypeIn, player); + } + + @Override + public boolean stillValid(Player playerIn) { + return playerInventory.getSelected() == contentHolder; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerPacketBase.java b/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerPacketBase.java similarity index 77% rename from src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerPacketBase.java rename to src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerPacketBase.java index 2f1cb8d94..0b0739777 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerPacketBase.java +++ b/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerPacketBase.java @@ -1,6 +1,4 @@ -package com.simibubi.create.content.logistics.item; - -import java.util.function.Supplier; +package com.simibubi.create.content.redstone.link.controller; import com.simibubi.create.AllItems; import com.simibubi.create.foundation.networking.SimplePacketBase; @@ -41,17 +39,17 @@ public abstract class LinkedControllerPacketBase extends SimplePacketBase { } @Override - public void handle(Supplier context) { - context.get().enqueueWork(() -> { - ServerPlayer player = context.get().getSender(); + public boolean handle(Context context) { + context.enqueueWork(() -> { + ServerPlayer player = context.getSender(); if (player == null) return; if (inLectern()) { - BlockEntity te = player.level.getBlockEntity(lecternPos); - if (!(te instanceof LecternControllerTileEntity)) + BlockEntity be = player.level.getBlockEntity(lecternPos); + if (!(be instanceof LecternControllerBlockEntity)) return; - handleLectern(player, (LecternControllerTileEntity) te); + handleLectern(player, (LecternControllerBlockEntity) be); } else { ItemStack controller = player.getMainHandItem(); if (!AllItems.LINKED_CONTROLLER.isIn(controller)) { @@ -62,11 +60,10 @@ public abstract class LinkedControllerPacketBase extends SimplePacketBase { handleItem(player, controller); } }); - - context.get().setPacketHandled(true); + return true; } protected abstract void handleItem(ServerPlayer player, ItemStack heldItem); - protected abstract void handleLectern(ServerPlayer player, LecternControllerTileEntity lectern); + protected abstract void handleLectern(ServerPlayer player, LecternControllerBlockEntity lectern); } diff --git a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerScreen.java b/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerScreen.java similarity index 91% rename from src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerScreen.java rename to src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerScreen.java index 5436e38af..a923b1df9 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerScreen.java +++ b/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerScreen.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.item; +package com.simibubi.create.content.redstone.link.controller; import static com.simibubi.create.foundation.gui.AllGuiTextures.PLAYER_INVENTORY; @@ -10,8 +10,8 @@ import com.google.common.collect.ImmutableList; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.gui.container.AbstractSimiContainerScreen; import com.simibubi.create.foundation.gui.element.GuiGameElement; +import com.simibubi.create.foundation.gui.menu.AbstractSimiContainerScreen; import com.simibubi.create.foundation.gui.widget.IconButton; import com.simibubi.create.foundation.utility.ControlsUtil; import com.simibubi.create.foundation.utility.Lang; @@ -22,7 +22,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.item.ItemStack; -public class LinkedControllerScreen extends AbstractSimiContainerScreen { +public class LinkedControllerScreen extends AbstractSimiContainerScreen { protected AllGuiTextures background; private List extraAreas = Collections.emptyList(); @@ -30,8 +30,8 @@ public class LinkedControllerScreen extends AbstractSimiContainerScreenat(x + background.width - 4, y + background.height - 56, -200) diff --git a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerServerHandler.java b/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerServerHandler.java similarity index 92% rename from src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerServerHandler.java rename to src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerServerHandler.java index 56962c1c5..727fadc9a 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerServerHandler.java +++ b/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerServerHandler.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.item; +package com.simibubi.create.content.redstone.link.controller; import java.util.ArrayList; import java.util.Collection; @@ -10,10 +10,10 @@ import java.util.Map.Entry; import java.util.UUID; import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.IRedstoneLinkable; -import com.simibubi.create.content.logistics.RedstoneLinkNetworkHandler.Frequency; +import com.simibubi.create.content.redstone.link.IRedstoneLinkable; +import com.simibubi.create.content.redstone.link.LinkBehaviour; +import com.simibubi.create.content.redstone.link.RedstoneLinkNetworkHandler.Frequency; import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.tileEntity.behaviour.linked.LinkBehaviour; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.IntAttached; import com.simibubi.create.foundation.utility.WorldAttached; diff --git a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerStopLecternPacket.java b/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerStopLecternPacket.java similarity index 87% rename from src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerStopLecternPacket.java rename to src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerStopLecternPacket.java index 03cbe9532..1281e0e49 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerStopLecternPacket.java +++ b/src/main/java/com/simibubi/create/content/redstone/link/controller/LinkedControllerStopLecternPacket.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.item; +package com.simibubi.create.content.redstone.link.controller; import net.minecraft.core.BlockPos; import net.minecraft.network.FriendlyByteBuf; @@ -16,7 +16,7 @@ public class LinkedControllerStopLecternPacket extends LinkedControllerPacketBas } @Override - protected void handleLectern(ServerPlayer player, LecternControllerTileEntity lectern) { + protected void handleLectern(ServerPlayer player, LecternControllerBlockEntity lectern) { lectern.tryStopUsing(player); } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/DoubleFaceAttachedBlock.java b/src/main/java/com/simibubi/create/content/redstone/nixieTube/DoubleFaceAttachedBlock.java similarity index 97% rename from src/main/java/com/simibubi/create/content/logistics/block/redstone/DoubleFaceAttachedBlock.java rename to src/main/java/com/simibubi/create/content/redstone/nixieTube/DoubleFaceAttachedBlock.java index 0d7625ff7..adeca87f0 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/DoubleFaceAttachedBlock.java +++ b/src/main/java/com/simibubi/create/content/redstone/nixieTube/DoubleFaceAttachedBlock.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.block.redstone; +package com.simibubi.create.content.redstone.nixieTube; import javax.annotation.Nullable; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/NixieTubeBlock.java b/src/main/java/com/simibubi/create/content/redstone/nixieTube/NixieTubeBlock.java similarity index 85% rename from src/main/java/com/simibubi/create/content/logistics/block/redstone/NixieTubeBlock.java rename to src/main/java/com/simibubi/create/content/redstone/nixieTube/NixieTubeBlock.java index bfcc0f74c..aedc16041 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/NixieTubeBlock.java +++ b/src/main/java/com/simibubi/create/content/redstone/nixieTube/NixieTubeBlock.java @@ -1,23 +1,26 @@ -package com.simibubi.create.content.logistics.block.redstone; +package com.simibubi.create.content.redstone.nixieTube; import static net.minecraft.world.level.block.state.properties.BlockStateProperties.WATERLOGGED; +import java.util.List; import java.util.function.BiConsumer; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; -import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement; -import com.simibubi.create.content.schematics.ItemRequirement; -import com.simibubi.create.content.schematics.ItemRequirement.ItemUseType; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.content.equipment.clipboard.ClipboardEntry; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.content.schematics.requirement.ISpecialBlockItemRequirement; +import com.simibubi.create.content.schematics.requirement.ItemRequirement; +import com.simibubi.create.content.schematics.requirement.ItemRequirement.ItemUseType; +import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.utility.Iterate; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; import net.minecraft.util.RandomSource; import net.minecraft.world.InteractionHand; @@ -45,7 +48,7 @@ import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; public class NixieTubeBlock extends DoubleFaceAttachedBlock - implements ITE, IWrenchable, SimpleWaterloggedBlock, ISpecialBlockItemRequirement { + implements IBE, IWrenchable, SimpleWaterloggedBlock, ISpecialBlockItemRequirement { protected final DyeColor color; @@ -64,7 +67,7 @@ public class NixieTubeBlock extends DoubleFaceAttachedBlock return InteractionResult.PASS; ItemStack heldItem = player.getItemInHand(hand); - NixieTubeTileEntity nixie = getTileEntity(world, pos); + NixieTubeBlockEntity nixie = getBlockEntity(world, pos); if (nixie == null) return InteractionResult.PASS; @@ -76,20 +79,31 @@ public class NixieTubeBlock extends DoubleFaceAttachedBlock return InteractionResult.SUCCESS; } - boolean display = heldItem.getItem() == Items.NAME_TAG && heldItem.hasCustomHoverName(); + boolean display = + heldItem.getItem() == Items.NAME_TAG && heldItem.hasCustomHoverName() || AllBlocks.CLIPBOARD.isIn(heldItem); DyeColor dye = DyeColor.getColor(heldItem); if (!display && dye == null) return InteractionResult.PASS; - if (world.isClientSide) - return InteractionResult.SUCCESS; CompoundTag tag = heldItem.getTagElement("display"); String tagElement = tag != null && tag.contains("Name", Tag.TAG_STRING) ? tag.getString("Name") : null; + if (AllBlocks.CLIPBOARD.isIn(heldItem)) { + List entries = ClipboardEntry.getLastViewedEntries(heldItem); + for (int i = 0; i < entries.size();) { + tagElement = Component.Serializer.toJson(entries.get(i).text); + break; + } + } + + if (world.isClientSide) + return InteractionResult.SUCCESS; + + String tagUsed = tagElement; walkNixies(world, pos, (currentPos, rowPosition) -> { if (display) - withTileEntityDo(world, currentPos, te -> te.displayCustomText(tagElement, rowPosition)); + withBlockEntityDo(world, currentPos, be -> be.displayCustomText(tagUsed, rowPosition)); if (dye != null) world.setBlockAndUpdate(currentPos, withColor(state, dye)); }); @@ -151,7 +165,7 @@ public class NixieTubeBlock extends DoubleFaceAttachedBlock } @Override - public ItemRequirement getRequiredItems(BlockState state, BlockEntity te) { + public ItemRequirement getRequiredItems(BlockState state, BlockEntity be) { return new ItemRequirement(ItemUseType.CONSUME, AllBlocks.ORANGE_NIXIE_TUBE.get() .asItem()); } @@ -231,9 +245,9 @@ public class NixieTubeBlock extends DoubleFaceAttachedBlock private void updateDisplayedRedstoneValue(BlockState state, Level worldIn, BlockPos pos) { if (worldIn.isClientSide) return; - withTileEntityDo(worldIn, pos, te -> { - if (te.reactsToRedstone()) - te.updateRedstoneStrength(getPower(worldIn, pos)); + withBlockEntityDo(worldIn, pos, be -> { + if (be.reactsToRedstone()) + be.updateRedstoneStrength(getPower(worldIn, pos)); }); } @@ -263,13 +277,13 @@ public class NixieTubeBlock extends DoubleFaceAttachedBlock } @Override - public Class getTileEntityClass() { - return NixieTubeTileEntity.class; + public Class getBlockEntityClass() { + return NixieTubeBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.NIXIE_TUBE.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.NIXIE_TUBE.get(); } public DyeColor getColor() { diff --git a/src/main/java/com/simibubi/create/content/redstone/nixieTube/NixieTubeBlockEntity.java b/src/main/java/com/simibubi/create/content/redstone/nixieTube/NixieTubeBlockEntity.java new file mode 100644 index 000000000..b1c13be2c --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/nixieTube/NixieTubeBlockEntity.java @@ -0,0 +1,174 @@ +package com.simibubi.create.content.redstone.nixieTube; + +import java.lang.ref.WeakReference; +import java.util.List; +import java.util.Optional; + +import com.simibubi.create.content.redstone.displayLink.DisplayLinkBlock; +import com.simibubi.create.content.trains.signal.SignalBlockEntity; +import com.simibubi.create.content.trains.signal.SignalBlockEntity.SignalState; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.Couple; +import com.simibubi.create.foundation.utility.DynamicComponent; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.MutableComponent; +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 class NixieTubeBlockEntity extends SmartBlockEntity { + + private static final Couple EMPTY = Couple.create("", ""); + + private int redstoneStrength; + private Optional customText; + private int nixieIndex; + private Couple displayedStrings; + + private WeakReference cachedSignalTE; + public SignalState signalState; + + public NixieTubeBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + customText = Optional.empty(); + redstoneStrength = 0; + cachedSignalTE = new WeakReference<>(null); + } + + @Override + public void tick() { + super.tick(); + if (!level.isClientSide) + return; + + signalState = null; + SignalBlockEntity signalBlockEntity = cachedSignalTE.get(); + + if (signalBlockEntity == null || signalBlockEntity.isRemoved()) { + Direction facing = NixieTubeBlock.getFacing(getBlockState()); + BlockEntity blockEntity = level.getBlockEntity(worldPosition.relative(facing.getOpposite())); + if (blockEntity instanceof SignalBlockEntity signal) { + signalState = signal.getState(); + cachedSignalTE = new WeakReference<>(signal); + } + return; + } + + signalState = signalBlockEntity.getState(); + } + + @Override + public void initialize() { + if (level.isClientSide) + updateDisplayedStrings(); + } + + // + + public boolean reactsToRedstone() { + return customText.isEmpty(); + } + + public Couple getDisplayedStrings() { + if (displayedStrings == null) + return EMPTY; + return displayedStrings; + } + + public MutableComponent getFullText() { + return customText.map(DynamicComponent::get) + .orElse(Components.literal("" + redstoneStrength)); + } + + public void updateRedstoneStrength(int signalStrength) { + clearCustomText(); + redstoneStrength = signalStrength; + DisplayLinkBlock.notifyGatherers(level, worldPosition); + notifyUpdate(); + } + + public void displayCustomText(String tagElement, int nixiePositionInRow) { + if (tagElement == null) + return; + if (customText.filter(d -> d.sameAs(tagElement)) + .isPresent()) + return; + + DynamicComponent component = customText.orElseGet(DynamicComponent::new); + component.displayCustomText(level, worldPosition, tagElement); + customText = Optional.of(component); + nixieIndex = nixiePositionInRow; + DisplayLinkBlock.notifyGatherers(level, worldPosition); + notifyUpdate(); + } + + public void updateDisplayedStrings() { + if (signalState != null) + return; + customText.map(DynamicComponent::resolve) + .ifPresentOrElse( + fullText -> displayedStrings = + Couple.create(charOrEmpty(fullText, nixieIndex * 2), charOrEmpty(fullText, nixieIndex * 2 + 1)), + () -> displayedStrings = + Couple.create(redstoneStrength < 10 ? "0" : "1", String.valueOf(redstoneStrength % 10))); + } + + public void clearCustomText() { + nixieIndex = 0; + customText = Optional.empty(); + } + + public int getRedstoneStrength() { + return redstoneStrength; + } + + // + + @Override + protected void read(CompoundTag nbt, boolean clientPacket) { + super.read(nbt, clientPacket); + + if (nbt.contains("CustomText")) { + DynamicComponent component = customText.orElseGet(DynamicComponent::new); + component.read(level, worldPosition, nbt); + + if (component.isValid()) { + customText = Optional.of(component); + nixieIndex = nbt.getInt("CustomTextIndex"); + } else { + customText = Optional.empty(); + nixieIndex = 0; + } + } + + if (customText.isEmpty()) + redstoneStrength = nbt.getInt("RedstoneStrength"); + if (clientPacket) + updateDisplayedStrings(); + } + + @Override + protected void write(CompoundTag nbt, boolean clientPacket) { + super.write(nbt, clientPacket); + + if (customText.isPresent()) { + nbt.putInt("CustomTextIndex", nixieIndex); + customText.get() + .write(nbt); + } else + nbt.putInt("RedstoneStrength", redstoneStrength); + } + + private String charOrEmpty(String string, int index) { + return string.length() <= index ? " " : string.substring(index, index + 1); + } + + @Override + public void addBehaviours(List behaviours) {} + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/NixieTubeGenerator.java b/src/main/java/com/simibubi/create/content/redstone/nixieTube/NixieTubeGenerator.java similarity index 86% rename from src/main/java/com/simibubi/create/content/logistics/block/redstone/NixieTubeGenerator.java rename to src/main/java/com/simibubi/create/content/redstone/nixieTube/NixieTubeGenerator.java index c39fde187..63e0277d0 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/NixieTubeGenerator.java +++ b/src/main/java/com/simibubi/create/content/redstone/nixieTube/NixieTubeGenerator.java @@ -1,6 +1,6 @@ -package com.simibubi.create.content.logistics.block.redstone; +package com.simibubi.create.content.redstone.nixieTube; -import com.simibubi.create.content.logistics.block.redstone.DoubleFaceAttachedBlock.DoubleAttachFace; +import com.simibubi.create.content.redstone.nixieTube.DoubleFaceAttachedBlock.DoubleAttachFace; import com.simibubi.create.foundation.data.SpecialBlockStateGen; import com.tterrag.registrate.providers.DataGenContext; import com.tterrag.registrate.providers.RegistrateBlockstateProvider; diff --git a/src/main/java/com/simibubi/create/content/redstone/nixieTube/NixieTubeRenderer.java b/src/main/java/com/simibubi/create/content/redstone/nixieTube/NixieTubeRenderer.java new file mode 100644 index 000000000..e1cf7edfc --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/nixieTube/NixieTubeRenderer.java @@ -0,0 +1,205 @@ +package com.simibubi.create.content.redstone.nixieTube; + +import java.util.Random; + +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.redstone.nixieTube.DoubleFaceAttachedBlock.DoubleAttachFace; +import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.RenderTypes; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.Color; +import com.simibubi.create.foundation.utility.Couple; +import com.simibubi.create.foundation.utility.DyeHelper; +import com.simibubi.create.foundation.utility.Iterate; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.font.glyphs.BakedGlyph; +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.MultiBufferSource.BufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.core.Direction; +import net.minecraft.network.chat.Style; +import net.minecraft.world.item.DyeColor; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class NixieTubeRenderer extends SafeBlockEntityRenderer { + + private static Random r = new Random(); + + public NixieTubeRenderer(BlockEntityRendererProvider.Context context) {} + + @Override + protected void renderSafe(NixieTubeBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + ms.pushPose(); + BlockState blockState = be.getBlockState(); + DoubleAttachFace face = blockState.getValue(NixieTubeBlock.FACE); + float yRot = AngleHelper.horizontalAngle(blockState.getValue(NixieTubeBlock.FACING)) - 90 + + (face == DoubleAttachFace.WALL_REVERSED ? 180 : 0); + float xRot = face == DoubleAttachFace.WALL ? -90 : face == DoubleAttachFace.WALL_REVERSED ? 90 : 0; + + TransformStack msr = TransformStack.cast(ms); + msr.centre() + .rotateY(yRot) + .rotateZ(xRot) + .unCentre(); + + if (be.signalState != null) { + renderAsSignal(be, partialTicks, ms, buffer, light, overlay); + ms.popPose(); + return; + } + + msr.centre(); + + float height = face == DoubleAttachFace.CEILING ? 5 : 3; + float scale = 1 / 20f; + + Couple s = be.getDisplayedStrings(); + DyeColor color = NixieTubeBlock.colorOf(be.getBlockState()); + + ms.pushPose(); + ms.translate(-4 / 16f, 0, 0); + ms.scale(scale, -scale, scale); + drawTube(ms, buffer, s.getFirst(), height, color); + ms.popPose(); + + ms.pushPose(); + ms.translate(4 / 16f, 0, 0); + ms.scale(scale, -scale, scale); + drawTube(ms, buffer, s.getSecond(), height, color); + ms.popPose(); + + ms.popPose(); + } + + public static void drawTube(PoseStack ms, MultiBufferSource buffer, String c, float height, DyeColor color) { + Font fontRenderer = Minecraft.getInstance().font; + float charWidth = fontRenderer.width(c); + float shadowOffset = .5f; + float flicker = r.nextFloat(); + Couple couple = DyeHelper.DYE_TABLE.get(color); + int brightColor = couple.getFirst(); + int darkColor = couple.getSecond(); + int flickeringBrightColor = Color.mixColors(brightColor, darkColor, flicker / 4); + + ms.pushPose(); + ms.translate((charWidth - shadowOffset) / -2f, -height, 0); + drawInWorldString(ms, buffer, c, flickeringBrightColor); + ms.pushPose(); + ms.translate(shadowOffset, shadowOffset, -1 / 16f); + drawInWorldString(ms, buffer, c, darkColor); + ms.popPose(); + ms.popPose(); + + ms.pushPose(); + ms.scale(-1, 1, 1); + ms.translate((charWidth - shadowOffset) / -2f, -height, 0); + drawInWorldString(ms, buffer, c, darkColor); + ms.pushPose(); + ms.translate(-shadowOffset, shadowOffset, -1 / 16f); + drawInWorldString(ms, buffer, c, Color.mixColors(darkColor, 0, .35f)); + ms.popPose(); + ms.popPose(); + } + + public static void drawInWorldString(PoseStack ms, MultiBufferSource buffer, String c, int color) { + Font fontRenderer = Minecraft.getInstance().font; + fontRenderer.drawInBatch(c, 0, 0, color, false, ms.last() + .pose(), buffer, false, 0, LightTexture.FULL_BRIGHT); + if (buffer instanceof BufferSource) { + BakedGlyph texturedglyph = fontRenderer.getFontSet(Style.DEFAULT_FONT) + .whiteGlyph(); + ((BufferSource) buffer).endBatch(texturedglyph.renderType(Font.DisplayMode.NORMAL)); + } + } + + private void renderAsSignal(NixieTubeBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + BlockState blockState = be.getBlockState(); + Direction facing = NixieTubeBlock.getFacing(blockState); + Vec3 observerVec = Minecraft.getInstance().cameraEntity.getEyePosition(partialTicks); + TransformStack msr = TransformStack.cast(ms); + + if (facing == Direction.DOWN) + msr.centre() + .rotateZ(180) + .unCentre(); + + boolean invertTubes = + facing == Direction.DOWN || blockState.getValue(NixieTubeBlock.FACE) == DoubleAttachFace.WALL_REVERSED; + + CachedBufferer.partial(AllPartialModels.SIGNAL_PANEL, blockState) + .light(light) + .renderInto(ms, buffer.getBuffer(RenderType.solid())); + + ms.pushPose(); + ms.translate(1 / 2f, 7.5f / 16f, 1 / 2f); + float renderTime = AnimationTickHolder.getRenderTime(be.getLevel()); + + for (boolean first : Iterate.trueAndFalse) { + Vec3 lampVec = Vec3.atCenterOf(be.getBlockPos()); + Vec3 diff = lampVec.subtract(observerVec); + + if (first && !be.signalState.isRedLight(renderTime)) + continue; + if (!first && !be.signalState.isGreenLight(renderTime) && !be.signalState.isYellowLight(renderTime)) + continue; + + boolean flip = first == invertTubes; + boolean yellow = be.signalState.isYellowLight(renderTime); + + ms.pushPose(); + ms.translate(flip ? 4 / 16f : -4 / 16f, 0, 0); + + if (diff.lengthSqr() < 96 * 96) { + boolean vert = first ^ facing.getAxis() + .isHorizontal(); + float longSide = yellow ? 1 : 4; + float longSideGlow = yellow ? 2 : 5.125f; + + CachedBufferer.partial(AllPartialModels.SIGNAL_WHITE_CUBE, blockState) + .light(0xf000f0) + .disableDiffuse() + .scale(vert ? longSide : 1, vert ? 1 : longSide, 1) + .renderInto(ms, buffer.getBuffer(RenderType.translucent())); + + CachedBufferer + .partial( + first ? AllPartialModels.SIGNAL_RED_GLOW + : yellow ? AllPartialModels.SIGNAL_YELLOW_GLOW : AllPartialModels.SIGNAL_WHITE_GLOW, + blockState) + .light(0xf000f0) + .disableDiffuse() + .scale(vert ? longSideGlow : 2, vert ? 2 : longSideGlow, 2) + .renderInto(ms, buffer.getBuffer(RenderTypes.getAdditive())); + } + + CachedBufferer + .partial(first ? AllPartialModels.SIGNAL_RED + : yellow ? AllPartialModels.SIGNAL_YELLOW : AllPartialModels.SIGNAL_WHITE, blockState) + .light(0xF000F0) + .disableDiffuse() + .scale(1 + 1 / 16f) + .renderInto(ms, buffer.getBuffer(RenderTypes.getAdditive())); + + ms.popPose(); + } + ms.popPose(); + + } + + @Override + public int getViewDistance() { + return 128; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/tracks/ControllerRailBlock.java b/src/main/java/com/simibubi/create/content/redstone/rail/ControllerRailBlock.java similarity index 98% rename from src/main/java/com/simibubi/create/content/contraptions/components/tracks/ControllerRailBlock.java rename to src/main/java/com/simibubi/create/content/redstone/rail/ControllerRailBlock.java index 2c5914c76..7dcb8cf42 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/tracks/ControllerRailBlock.java +++ b/src/main/java/com/simibubi/create/content/redstone/rail/ControllerRailBlock.java @@ -1,10 +1,10 @@ -package com.simibubi.create.content.contraptions.components.tracks; +package com.simibubi.create.content.redstone.rail; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; +import com.simibubi.create.content.equipment.wrench.IWrenchable; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.VecHelper; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/tracks/ControllerRailGenerator.java b/src/main/java/com/simibubi/create/content/redstone/rail/ControllerRailGenerator.java similarity index 96% rename from src/main/java/com/simibubi/create/content/contraptions/components/tracks/ControllerRailGenerator.java rename to src/main/java/com/simibubi/create/content/redstone/rail/ControllerRailGenerator.java index d8510c7bb..a36300544 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/tracks/ControllerRailGenerator.java +++ b/src/main/java/com/simibubi/create/content/redstone/rail/ControllerRailGenerator.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.components.tracks; +package com.simibubi.create.content.redstone.rail; import com.simibubi.create.foundation.data.AssetLookup; import com.simibubi.create.foundation.data.SpecialBlockStateGen; diff --git a/src/main/java/com/simibubi/create/content/redstone/smartObserver/SmartObserverBlock.java b/src/main/java/com/simibubi/create/content/redstone/smartObserver/SmartObserverBlock.java new file mode 100644 index 000000000..69326a35b --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/smartObserver/SmartObserverBlock.java @@ -0,0 +1,163 @@ +package com.simibubi.create.content.redstone.smartObserver; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.fluids.FluidTransportBehaviour; +import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour; +import com.simibubi.create.content.logistics.funnel.FunnelBlockEntity; +import com.simibubi.create.content.redstone.DirectedDirectionalBlock; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.inventory.InvManipulationBehaviour; +import com.simibubi.create.foundation.utility.Iterate; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.BlockPlaceContext; +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.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition.Builder; +import net.minecraft.world.level.block.state.properties.AttachFace; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; + +public class SmartObserverBlock extends DirectedDirectionalBlock implements IBE { + + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; + + public SmartObserverBlock(Properties properties) { + super(properties); + registerDefaultState(defaultBlockState().setValue(POWERED, false)); + } + + @Override + protected void createBlockStateDefinition(Builder builder) { + super.createBlockStateDefinition(builder.add(POWERED)); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext context) { + BlockState state = defaultBlockState(); + Capability itemCap = CapabilityItemHandler.ITEM_HANDLER_CAPABILITY; + Capability fluidCap = CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY; + + Direction preferredFacing = null; + for (Direction face : context.getNearestLookingDirections()) { + BlockPos offsetPos = context.getClickedPos() + .relative(face); + Level world = context.getLevel(); + boolean canDetect = false; + BlockEntity blockEntity = world.getBlockEntity(offsetPos); + + if (BlockEntityBehaviour.get(blockEntity, TransportedItemStackHandlerBehaviour.TYPE) != null) + canDetect = true; + else if (BlockEntityBehaviour.get(blockEntity, FluidTransportBehaviour.TYPE) != null) + canDetect = true; + else if (blockEntity != null && (blockEntity.getCapability(itemCap) + .isPresent() + || blockEntity.getCapability(fluidCap) + .isPresent())) + canDetect = true; + else if (blockEntity instanceof FunnelBlockEntity) + canDetect = true; + + if (canDetect) { + preferredFacing = face; + break; + } + } + + if (preferredFacing == null) { + Direction facing = context.getNearestLookingDirection(); + preferredFacing = context.getPlayer() != null && context.getPlayer() + .isSteppingCarefully() ? facing : facing.getOpposite(); + } + + if (preferredFacing.getAxis() == Axis.Y) { + state = state.setValue(TARGET, preferredFacing == Direction.UP ? AttachFace.CEILING : AttachFace.FLOOR); + preferredFacing = context.getHorizontalDirection(); + } + + return state.setValue(FACING, preferredFacing); + } + + @Override + public boolean isSignalSource(BlockState state) { + return state.getValue(POWERED); + } + + @Override + public int getSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { + return isSignalSource(blockState) && (side == null || side != blockState.getValue(FACING) + .getOpposite()) ? 15 : 0; + } + + @Override + public void tick(BlockState state, ServerLevel worldIn, BlockPos pos, RandomSource random) { + worldIn.setBlock(pos, state.setValue(POWERED, false), 2); + worldIn.updateNeighborsAt(pos, this); + } + + @Override + public boolean canConnectRedstone(BlockState state, BlockGetter world, BlockPos pos, Direction side) { + return side != state.getValue(FACING) + .getOpposite(); + } + + @Override + public void onRemove(BlockState state, Level worldIn, BlockPos pos, BlockState newState, boolean isMoving) { + IBE.onRemove(state, worldIn, pos, newState); + } + + @Override + public void neighborChanged(BlockState state, Level worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, + boolean isMoving) { + InvManipulationBehaviour behaviour = BlockEntityBehaviour.get(worldIn, pos, InvManipulationBehaviour.TYPE); + if (behaviour != null) + behaviour.onNeighborChanged(fromPos); + } + + public void onFunnelTransfer(Level world, BlockPos funnelPos, ItemStack transferred) { + for (Direction direction : Iterate.horizontalDirections) { + BlockPos detectorPos = funnelPos.relative(direction); + BlockState detectorState = world.getBlockState(detectorPos); + if (!AllBlocks.SMART_OBSERVER.has(detectorState)) + continue; + if (detectorState.getValue(FACING) != direction.getOpposite()) + continue; + withBlockEntityDo(world, detectorPos, be -> { + FilteringBehaviour filteringBehaviour = BlockEntityBehaviour.get(be, FilteringBehaviour.TYPE); + if (filteringBehaviour == null) + return; + if (!filteringBehaviour.test(transferred)) + return; + be.activate(4); + }); + } + } + + @Override + public Class getBlockEntityClass() { + return SmartObserverBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.SMART_OBSERVER.get(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/redstone/smartObserver/SmartObserverBlockEntity.java b/src/main/java/com/simibubi/create/content/redstone/smartObserver/SmartObserverBlockEntity.java new file mode 100644 index 000000000..484aeab56 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/smartObserver/SmartObserverBlockEntity.java @@ -0,0 +1,152 @@ +package com.simibubi.create.content.redstone.smartObserver; + +import java.util.List; + +import com.simibubi.create.content.fluids.FluidTransportBehaviour; +import com.simibubi.create.content.fluids.PipeConnection.Flow; +import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour; +import com.simibubi.create.content.kinetics.belt.behaviour.TransportedItemStackHandlerBehaviour.TransportedResult; +import com.simibubi.create.content.redstone.DirectedDirectionalBlock; +import com.simibubi.create.content.redstone.FilteredDetectorFilterSlot; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.inventory.CapManipulationBehaviourBase.InterfaceProvider; +import com.simibubi.create.foundation.blockEntity.behaviour.inventory.InvManipulationBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.inventory.TankManipulationBehaviour; +import com.simibubi.create.foundation.utility.BlockFace; +import com.simibubi.create.foundation.utility.Iterate; + +import net.minecraft.core.BlockPos; +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.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; + +public class SmartObserverBlockEntity extends SmartBlockEntity { + + private static final int DEFAULT_DELAY = 6; + private FilteringBehaviour filtering; + private InvManipulationBehaviour observedInventory; + private TankManipulationBehaviour observedTank; + public int turnOffTicks = 0; + + public SmartObserverBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + setLazyTickRate(20); + } + + @Override + public void addBehaviours(List behaviours) { + behaviours.add(filtering = new FilteringBehaviour(this, new FilteredDetectorFilterSlot(false))); + + InterfaceProvider towardBlockFacing = + (w, p, s) -> new BlockFace(p, DirectedDirectionalBlock.getTargetDirection(s)); + + behaviours.add(observedInventory = new InvManipulationBehaviour(this, towardBlockFacing).bypassSidedness()); + behaviours.add(observedTank = new TankManipulationBehaviour(this, towardBlockFacing).bypassSidedness()); + } + + @Override + public void tick() { + super.tick(); + + if (level.isClientSide()) + return; + + BlockState state = getBlockState(); + if (turnOffTicks > 0) { + turnOffTicks--; + if (turnOffTicks == 0) + level.scheduleTick(worldPosition, state.getBlock(), 1); + } + + if (!isActive()) + return; + + BlockPos targetPos = worldPosition.relative(SmartObserverBlock.getTargetDirection(state)); + Block block = level.getBlockState(targetPos) + .getBlock(); + + if (!filtering.getFilter() + .isEmpty() && block.asItem() != null && filtering.test(new ItemStack(block))) { + activate(3); + return; + } + + // Detect items on belt + TransportedItemStackHandlerBehaviour behaviour = + BlockEntityBehaviour.get(level, targetPos, TransportedItemStackHandlerBehaviour.TYPE); + if (behaviour != null) { + behaviour.handleCenteredProcessingOnAllItems(.45f, stack -> { + if (!filtering.test(stack.stack) || turnOffTicks == 6) + return TransportedResult.doNothing(); + activate(); + return TransportedResult.doNothing(); + }); + return; + } + + // Detect fluids in pipe + FluidTransportBehaviour fluidBehaviour = + BlockEntityBehaviour.get(level, targetPos, FluidTransportBehaviour.TYPE); + if (fluidBehaviour != null) { + for (Direction side : Iterate.directions) { + Flow flow = fluidBehaviour.getFlow(side); + if (flow == null || !flow.inbound || !flow.complete) + continue; + if (!filtering.test(flow.fluid)) + continue; + activate(); + return; + } + return; + } + + if (!observedInventory.simulate() + .extract() + .isEmpty()) { + activate(); + return; + } + + if (!observedTank.simulate() + .extractAny() + .isEmpty()) { + activate(); + return; + } + } + + public void activate() { + activate(DEFAULT_DELAY); + } + + public void activate(int ticks) { + BlockState state = getBlockState(); + turnOffTicks = ticks; + if (state.getValue(SmartObserverBlock.POWERED)) + return; + level.setBlockAndUpdate(worldPosition, state.setValue(SmartObserverBlock.POWERED, true)); + level.updateNeighborsAt(worldPosition, state.getBlock()); + } + + private boolean isActive() { + return true; + } + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + compound.putInt("TurnOff", turnOffTicks); + super.write(compound, clientPacket); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + super.read(compound, clientPacket); + turnOffTicks = compound.getInt("TurnOff"); + } + +} diff --git a/src/main/java/com/simibubi/create/content/redstone/smartObserver/SmartObserverGenerator.java b/src/main/java/com/simibubi/create/content/redstone/smartObserver/SmartObserverGenerator.java new file mode 100644 index 000000000..9f7f73289 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/smartObserver/SmartObserverGenerator.java @@ -0,0 +1,36 @@ +package com.simibubi.create.content.redstone.smartObserver; + +import com.simibubi.create.content.redstone.thresholdSwitch.ThresholdSwitchBlock; +import com.simibubi.create.foundation.data.AssetLookup; +import com.simibubi.create.foundation.data.SpecialBlockStateGen; +import com.tterrag.registrate.providers.DataGenContext; +import com.tterrag.registrate.providers.RegistrateBlockstateProvider; + +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.client.model.generators.ModelFile; + +public class SmartObserverGenerator extends SpecialBlockStateGen { + + @Override + protected int getXRotation(BlockState state) { + return switch (state.getValue(SmartObserverBlock.TARGET)) { + case CEILING -> -90; + case WALL -> 0; + case FLOOR -> 90; + }; + } + + @Override + protected int getYRotation(BlockState state) { + return horizontalAngle(state.getValue(ThresholdSwitchBlock.FACING)) + 180; + } + + @Override + public ModelFile getModel(DataGenContext ctx, RegistrateBlockstateProvider prov, + BlockState state) { + return AssetLookup.forPowered(ctx, prov) + .apply(state); + } + +} diff --git a/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ConfigureThresholdSwitchPacket.java b/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ConfigureThresholdSwitchPacket.java new file mode 100644 index 000000000..235023c7d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ConfigureThresholdSwitchPacket.java @@ -0,0 +1,46 @@ +package com.simibubi.create.content.redstone.thresholdSwitch; + +import com.simibubi.create.foundation.networking.BlockEntityConfigurationPacket; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; + +public class ConfigureThresholdSwitchPacket extends BlockEntityConfigurationPacket { + + private float offBelow; + private float onAbove; + private boolean invert; + + public ConfigureThresholdSwitchPacket(BlockPos pos, float offBelow, float onAbove, boolean invert) { + super(pos); + this.offBelow = offBelow; + this.onAbove = onAbove; + this.invert = invert; + } + + public ConfigureThresholdSwitchPacket(FriendlyByteBuf buffer) { + super(buffer); + } + + @Override + protected void readSettings(FriendlyByteBuf buffer) { + offBelow = buffer.readFloat(); + onAbove = buffer.readFloat(); + invert = buffer.readBoolean(); + } + + @Override + protected void writeSettings(FriendlyByteBuf buffer) { + buffer.writeFloat(offBelow); + buffer.writeFloat(onAbove); + buffer.writeBoolean(invert); + } + + @Override + protected void applySettings(ThresholdSwitchBlockEntity be) { + be.offWhenBelow = offBelow; + be.onWhenAbove = onAbove; + be.setInverted(invert); + } + +} diff --git a/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ThresholdSwitchBlock.java b/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ThresholdSwitchBlock.java new file mode 100644 index 000000000..b88499c03 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ThresholdSwitchBlock.java @@ -0,0 +1,146 @@ +package com.simibubi.create.content.redstone.thresholdSwitch; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllItems; +import com.simibubi.create.content.redstone.DirectedDirectionalBlock; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.gui.ScreenOpener; + +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +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.LevelReader; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition.Builder; +import net.minecraft.world.level.block.state.properties.AttachFace; +import net.minecraft.world.level.block.state.properties.IntegerProperty; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; + +public class ThresholdSwitchBlock extends DirectedDirectionalBlock implements IBE { + + public static final IntegerProperty LEVEL = IntegerProperty.create("level", 0, 5); + + public ThresholdSwitchBlock(Properties p_i48377_1_) { + super(p_i48377_1_); + } + + @Override + public void onPlace(BlockState state, Level worldIn, BlockPos pos, BlockState oldState, boolean isMoving) { + updateObservedInventory(state, worldIn, pos); + } + + private void updateObservedInventory(BlockState state, LevelReader world, BlockPos pos) { + withBlockEntityDo(world, pos, ThresholdSwitchBlockEntity::updateCurrentLevel); + } + + @Override + public boolean canConnectRedstone(BlockState state, BlockGetter world, BlockPos pos, Direction side) { + return side != null && side.getOpposite() != state.getValue(FACING); + } + + @Override + public boolean isSignalSource(BlockState state) { + return true; + } + + @Override + public int getSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { + if (side == blockState.getValue(FACING) + .getOpposite()) + return 0; + return getBlockEntityOptional(blockAccess, pos).filter(ThresholdSwitchBlockEntity::isPowered) + .map($ -> 15) + .orElse(0); + } + + @Override + public void tick(BlockState blockState, ServerLevel world, BlockPos pos, RandomSource random) { + getBlockEntityOptional(world, pos).ifPresent(ThresholdSwitchBlockEntity::updatePowerAfterDelay); + } + + @Override + protected void createBlockStateDefinition(Builder builder) { + super.createBlockStateDefinition(builder.add(LEVEL)); + } + + @Override + public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, + BlockHitResult hit) { + if (player != null && AllItems.WRENCH.isIn(player.getItemInHand(handIn))) + return InteractionResult.PASS; + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, + () -> () -> withBlockEntityDo(worldIn, pos, be -> this.displayScreen(be, player))); + return InteractionResult.SUCCESS; + } + + @OnlyIn(value = Dist.CLIENT) + protected void displayScreen(ThresholdSwitchBlockEntity be, Player player) { + if (player instanceof LocalPlayer) + ScreenOpener.open(new ThresholdSwitchScreen(be)); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext context) { + BlockState state = defaultBlockState(); + Capability itemCap = CapabilityItemHandler.ITEM_HANDLER_CAPABILITY; + Capability fluidCap = CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY; + + Direction preferredFacing = null; + for (Direction face : context.getNearestLookingDirections()) { + BlockEntity be = context.getLevel() + .getBlockEntity(context.getClickedPos() + .relative(face)); + if (be != null && (be.getCapability(itemCap) + .isPresent() + || be.getCapability(fluidCap) + .isPresent())) { + preferredFacing = face; + break; + } + } + + if (preferredFacing == null) { + Direction facing = context.getNearestLookingDirection(); + preferredFacing = context.getPlayer() != null && context.getPlayer() + .isSteppingCarefully() ? facing : facing.getOpposite(); + } + + if (preferredFacing.getAxis() == Axis.Y) { + state = state.setValue(TARGET, preferredFacing == Direction.UP ? AttachFace.CEILING : AttachFace.FLOOR); + preferredFacing = context.getHorizontalDirection(); + } + + return state.setValue(FACING, preferredFacing); + } + + @Override + public Class getBlockEntityClass() { + return ThresholdSwitchBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.THRESHOLD_SWITCH.get(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ThresholdSwitchBlockEntity.java b/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ThresholdSwitchBlockEntity.java new file mode 100644 index 000000000..124e8fbfc --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ThresholdSwitchBlockEntity.java @@ -0,0 +1,238 @@ +package com.simibubi.create.content.redstone.thresholdSwitch; + +import java.util.List; + +import com.simibubi.create.compat.storageDrawers.StorageDrawers; +import com.simibubi.create.content.redstone.DirectedDirectionalBlock; +import com.simibubi.create.content.redstone.FilteredDetectorFilterSlot; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkBlock; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.inventory.CapManipulationBehaviourBase.InterfaceProvider; +import com.simibubi.create.foundation.blockEntity.behaviour.inventory.InvManipulationBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.inventory.TankManipulationBehaviour; +import com.simibubi.create.foundation.utility.BlockFace; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.Mth; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.ticks.TickPriority; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.items.IItemHandler; + +public class ThresholdSwitchBlockEntity extends SmartBlockEntity { + + public float onWhenAbove; + public float offWhenBelow; + public float currentLevel; + private boolean redstoneState; + private boolean inverted; + private boolean poweredAfterDelay; + + private FilteringBehaviour filtering; + private InvManipulationBehaviour observedInventory; + private TankManipulationBehaviour observedTank; + + public ThresholdSwitchBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + onWhenAbove = .75f; + offWhenBelow = .25f; + currentLevel = -1; + redstoneState = false; + inverted = false; + poweredAfterDelay = false; + setLazyTickRate(10); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + onWhenAbove = compound.getFloat("OnAbove"); + offWhenBelow = compound.getFloat("OffBelow"); + currentLevel = compound.getFloat("Current"); + redstoneState = compound.getBoolean("Powered"); + inverted = compound.getBoolean("Inverted"); + poweredAfterDelay = compound.getBoolean("PoweredAfterDelay"); + super.read(compound, clientPacket); + } + + protected void writeCommon(CompoundTag compound) { + compound.putFloat("OnAbove", onWhenAbove); + compound.putFloat("OffBelow", offWhenBelow); + compound.putBoolean("Inverted", inverted); + } + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + writeCommon(compound); + compound.putFloat("Current", currentLevel); + compound.putBoolean("Powered", redstoneState); + compound.putBoolean("PoweredAfterDelay", poweredAfterDelay); + super.write(compound, clientPacket); + } + + @Override + public void writeSafe(CompoundTag compound) { + writeCommon(compound); + super.writeSafe(compound); + } + + public float getStockLevel() { + return currentLevel; + } + + public void updateCurrentLevel() { + boolean changed = false; + float occupied = 0; + float totalSpace = 0; + float prevLevel = currentLevel; + + observedInventory.findNewCapability(); + observedTank.findNewCapability(); + + BlockPos target = worldPosition.relative(ThresholdSwitchBlock.getTargetDirection(getBlockState())); + BlockEntity targetBlockEntity = level.getBlockEntity(target); + + if (targetBlockEntity instanceof ThresholdSwitchObservable observable) { + currentLevel = observable.getPercent() / 100f; + + } else if (StorageDrawers.isDrawer(targetBlockEntity) && observedInventory.hasInventory()) { + currentLevel = StorageDrawers.getTrueFillLevel(observedInventory.getInventory(), filtering); + + } else if (observedInventory.hasInventory() || observedTank.hasInventory()) { + if (observedInventory.hasInventory()) { + // Item inventory + IItemHandler inv = observedInventory.getInventory(); + for (int slot = 0; slot < inv.getSlots(); slot++) { + ItemStack stackInSlot = inv.getStackInSlot(slot); + int space = Math.min(stackInSlot.getMaxStackSize(), inv.getSlotLimit(slot)); + int count = stackInSlot.getCount(); + if (space == 0) + continue; + + totalSpace += 1; + if (filtering.test(stackInSlot)) + occupied += count * (1f / space); + } + } + + if (observedTank.hasInventory()) { + // Fluid inventory + IFluidHandler tank = observedTank.getInventory(); + for (int slot = 0; slot < tank.getTanks(); slot++) { + FluidStack stackInSlot = tank.getFluidInTank(slot); + int space = tank.getTankCapacity(slot); + int count = stackInSlot.getAmount(); + if (space == 0) + continue; + + totalSpace += 1; + if (filtering.test(stackInSlot)) + occupied += count * (1f / space); + } + } + + currentLevel = occupied / totalSpace; + + } else { + // No compatible inventories found + if (currentLevel == -1) + return; + level.setBlock(worldPosition, getBlockState().setValue(ThresholdSwitchBlock.LEVEL, 0), 3); + currentLevel = -1; + redstoneState = false; + sendData(); + scheduleBlockTick(); + return; + } + + currentLevel = Mth.clamp(currentLevel, 0, 1); + changed = currentLevel != prevLevel; + + boolean previouslyPowered = redstoneState; + if (redstoneState && currentLevel <= offWhenBelow) + redstoneState = false; + else if (!redstoneState && currentLevel >= onWhenAbove) + redstoneState = true; + boolean update = previouslyPowered != redstoneState; + + int displayLevel = 0; + if (currentLevel > 0) + displayLevel = (int) (1 + currentLevel * 4); + level.setBlock(worldPosition, getBlockState().setValue(ThresholdSwitchBlock.LEVEL, displayLevel), + update ? 3 : 2); + + if (update) + scheduleBlockTick(); + + if (changed || update) { + DisplayLinkBlock.notifyGatherers(level, worldPosition); + notifyUpdate(); + } + } + + protected void scheduleBlockTick() { + Block block = getBlockState().getBlock(); + if (!level.getBlockTicks() + .willTickThisTick(worldPosition, block)) + level.scheduleTick(worldPosition, block, 2, TickPriority.NORMAL); + } + + @Override + public void lazyTick() { + super.lazyTick(); + if (level.isClientSide) + return; + updateCurrentLevel(); + } + + @Override + public void addBehaviours(List behaviours) { + behaviours.add(filtering = new FilteringBehaviour(this, new FilteredDetectorFilterSlot(true)) + .withCallback($ -> this.updateCurrentLevel())); + + InterfaceProvider towardBlockFacing = + (w, p, s) -> new BlockFace(p, DirectedDirectionalBlock.getTargetDirection(s)); + + behaviours.add(observedInventory = new InvManipulationBehaviour(this, towardBlockFacing).bypassSidedness()); + behaviours.add(observedTank = new TankManipulationBehaviour(this, towardBlockFacing).bypassSidedness()); + } + + public float getLevelForDisplay() { + return currentLevel == -1 ? 0 : currentLevel; + } + + public boolean getState() { + return redstoneState; + } + + public boolean shouldBePowered() { + return inverted != redstoneState; + } + + public void updatePowerAfterDelay() { + poweredAfterDelay = shouldBePowered(); + level.blockUpdated(worldPosition, getBlockState().getBlock()); + } + + public boolean isPowered() { + return poweredAfterDelay; + } + + public boolean isInverted() { + return inverted; + } + + public void setInverted(boolean inverted) { + if (inverted == this.inverted) + return; + this.inverted = inverted; + updatePowerAfterDelay(); + } +} diff --git a/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ThresholdSwitchGenerator.java b/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ThresholdSwitchGenerator.java new file mode 100644 index 000000000..d85e974d6 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ThresholdSwitchGenerator.java @@ -0,0 +1,36 @@ +package com.simibubi.create.content.redstone.thresholdSwitch; + +import com.simibubi.create.Create; +import com.simibubi.create.foundation.data.SpecialBlockStateGen; +import com.simibubi.create.foundation.utility.Lang; +import com.tterrag.registrate.providers.DataGenContext; +import com.tterrag.registrate.providers.RegistrateBlockstateProvider; + +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.client.model.generators.ModelFile; + +public class ThresholdSwitchGenerator extends SpecialBlockStateGen { + + @Override + protected int getXRotation(BlockState state) { + return 0; + } + + @Override + protected int getYRotation(BlockState state) { + return horizontalAngle(state.getValue(ThresholdSwitchBlock.FACING)) + 180; + } + + @Override + public ModelFile getModel(DataGenContext ctx, RegistrateBlockstateProvider prov, + BlockState state) { + int level = state.getValue(ThresholdSwitchBlock.LEVEL); + String path = "threshold_switch/block_" + Lang.asId(state.getValue(ThresholdSwitchBlock.TARGET) + .name()); + return prov.models() + .withExistingParent(path + "_" + level, Create.asResource("block/" + path)) + .texture("level", Create.asResource("block/threshold_switch/level_" + level)); + } + +} diff --git a/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ThresholdSwitchObservable.java b/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ThresholdSwitchObservable.java new file mode 100644 index 000000000..039945c2a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ThresholdSwitchObservable.java @@ -0,0 +1,7 @@ +package com.simibubi.create.content.redstone.thresholdSwitch; + +public interface ThresholdSwitchObservable { + + public float getPercent(); + +} diff --git a/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ThresholdSwitchScreen.java b/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ThresholdSwitchScreen.java new file mode 100644 index 000000000..fc74d4cf0 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/redstone/thresholdSwitch/ThresholdSwitchScreen.java @@ -0,0 +1,169 @@ +package com.simibubi.create.content.redstone.thresholdSwitch; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPackets; +import com.simibubi.create.foundation.gui.AbstractSimiScreen; +import com.simibubi.create.foundation.gui.AllGuiTextures; +import com.simibubi.create.foundation.gui.AllIcons; +import com.simibubi.create.foundation.gui.element.GuiGameElement; +import com.simibubi.create.foundation.gui.widget.IconButton; +import com.simibubi.create.foundation.gui.widget.ScrollInput; +import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; + +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.ItemStack; + +public class ThresholdSwitchScreen extends AbstractSimiScreen { + + private ScrollInput offBelow; + private ScrollInput onAbove; + private IconButton confirmButton; + private IconButton flipSignals; + + private final Component invertSignal = Lang.translateDirect("gui.threshold_switch.invert_signal"); + private final ItemStack renderedItem = new ItemStack(AllBlocks.THRESHOLD_SWITCH.get()); + + private AllGuiTextures background; + private ThresholdSwitchBlockEntity blockEntity; + private int lastModification; + + private LerpedFloat cursor; + private LerpedFloat cursorLane; + + public ThresholdSwitchScreen(ThresholdSwitchBlockEntity be) { + super(Lang.translateDirect("gui.threshold_switch.title")); + background = AllGuiTextures.STOCKSWITCH; + this.blockEntity = be; + lastModification = -1; + } + + @Override + protected void init() { + setWindowSize(background.width, background.height); + setWindowOffset(-20, 0); + super.init(); + + int x = guiLeft; + int y = guiTop; + + cursor = LerpedFloat.linear() + .startWithValue(blockEntity.getLevelForDisplay()); + cursorLane = LerpedFloat.linear() + .startWithValue(blockEntity.getState() ? 1 : 0); + + offBelow = new ScrollInput(x + 36, y + 42, 102, 18).withRange(0, 100) + .titled(Components.empty()) + .calling(state -> { + lastModification = 0; + offBelow.titled(Lang.translateDirect("gui.threshold_switch.move_to_upper_at", state)); + if (onAbove.getState() <= state) { + onAbove.setState(state + 1); + onAbove.onChanged(); + } + }) + .setState((int) (blockEntity.offWhenBelow * 100)); + + onAbove = new ScrollInput(x + 36, y + 20, 102, 18).withRange(1, 101) + .titled(Components.empty()) + .calling(state -> { + lastModification = 0; + onAbove.titled(Lang.translateDirect("gui.threshold_switch.move_to_lower_at", state)); + if (offBelow.getState() >= state) { + offBelow.setState(state - 1); + offBelow.onChanged(); + } + }) + .setState((int) (blockEntity.onWhenAbove * 100)); + + onAbove.onChanged(); + offBelow.onChanged(); + + addRenderableWidget(onAbove); + addRenderableWidget(offBelow); + + confirmButton = new IconButton(x + background.width - 33, y + background.height - 24, AllIcons.I_CONFIRM); + confirmButton.withCallback(() -> { + onClose(); + }); + addRenderableWidget(confirmButton); + + flipSignals = new IconButton(x + background.width - 62, y + background.height - 24, AllIcons.I_FLIP); + flipSignals.withCallback(() -> { + send(!blockEntity.isInverted()); + }); + flipSignals.setToolTip(invertSignal); + addRenderableWidget(flipSignals); + } + + @Override + protected void renderWindow(PoseStack ms, int mouseX, int mouseY, float partialTicks) { + int x = guiLeft; + int y = guiTop; + + background.render(ms, x, y, this); + + AllGuiTextures.STOCKSWITCH_POWERED_LANE.render(ms, x + 37, y + (blockEntity.isInverted() ? 20 : 42), this); + AllGuiTextures.STOCKSWITCH_UNPOWERED_LANE.render(ms, x + 37, y + (blockEntity.isInverted() ? 42 : 20), this); + font.draw(ms, title, x + (background.width - 8) / 2 - font.width(title) / 2, y + 4, 0x592424); + + AllGuiTextures sprite = AllGuiTextures.STOCKSWITCH_INTERVAL; + float lowerBound = offBelow.getState(); + float upperBound = onAbove.getState(); + + sprite.bind(); + blit(ms, (int) (x + upperBound) + 37, y + 20, (int) (sprite.startX + upperBound), sprite.startY, + (int) (sprite.width - upperBound), sprite.height); + blit(ms, x + 37, y + 42, sprite.startX, sprite.startY, (int) (lowerBound), sprite.height); + + AllGuiTextures.STOCKSWITCH_ARROW_UP.render(ms, (int) (x + lowerBound + 36) - 2, y + 37, this); + AllGuiTextures.STOCKSWITCH_ARROW_DOWN.render(ms, (int) (x + upperBound + 36) - 3, y + 19, this); + + if (blockEntity.currentLevel != -1) { + AllGuiTextures cursor = AllGuiTextures.STOCKSWITCH_CURSOR; + ms.pushPose(); + ms.translate(Math.min(99, this.cursor.getValue(partialTicks) * sprite.width), + cursorLane.getValue(partialTicks) * 22, 0); + cursor.render(ms, x + 34, y + 21, this); + ms.popPose(); + } + + GuiGameElement.of(renderedItem).at(x + background.width + 6, y + background.height - 56, -200) + .scale(5) + .render(ms); + } + + @Override + public void tick() { + super.tick(); + + cursor.chase(blockEntity.getLevelForDisplay(), 1 / 4f, Chaser.EXP); + cursor.tickChaser(); + cursorLane.chase(blockEntity.getState() ? 1 : 0, 1 / 4f, Chaser.EXP); + cursorLane.tickChaser(); + + if (lastModification >= 0) + lastModification++; + + if (lastModification >= 20) { + lastModification = -1; + send(blockEntity.isInverted()); + } + } + + @Override + public void removed() { + send(blockEntity.isInverted()); + } + + protected void send(boolean invert) { + AllPackets.getChannel() + .sendToServer(new ConfigureThresholdSwitchPacket(blockEntity.getBlockPos(), offBelow.getState() / 100f, + onAbove.getState() / 100f, invert)); + } + +} diff --git a/src/main/java/com/simibubi/create/content/schematics/ISpecialBlockEntityItemRequirement.java b/src/main/java/com/simibubi/create/content/schematics/ISpecialBlockEntityItemRequirement.java deleted file mode 100644 index bfcb9ef69..000000000 --- a/src/main/java/com/simibubi/create/content/schematics/ISpecialBlockEntityItemRequirement.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.simibubi.create.content.schematics; - -import net.minecraft.world.level.block.state.BlockState; - -public interface ISpecialBlockEntityItemRequirement { - - public ItemRequirement getRequiredItems(BlockState state); - -} diff --git a/src/main/java/com/simibubi/create/content/schematics/ISpecialBlockItemRequirement.java b/src/main/java/com/simibubi/create/content/schematics/ISpecialBlockItemRequirement.java deleted file mode 100644 index 26729dc49..000000000 --- a/src/main/java/com/simibubi/create/content/schematics/ISpecialBlockItemRequirement.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.simibubi.create.content.schematics; - -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; - -public interface ISpecialBlockItemRequirement { - - public ItemRequirement getRequiredItems(BlockState state, BlockEntity te); - -} diff --git a/src/main/java/com/simibubi/create/content/schematics/ISpecialEntityItemRequirement.java b/src/main/java/com/simibubi/create/content/schematics/ISpecialEntityItemRequirement.java deleted file mode 100644 index 7cdf23c5e..000000000 --- a/src/main/java/com/simibubi/create/content/schematics/ISpecialEntityItemRequirement.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.simibubi.create.content.schematics; - -public interface ISpecialEntityItemRequirement { - - public ItemRequirement getRequiredItems(); - -} diff --git a/src/main/java/com/simibubi/create/content/schematics/ItemRequirement.java b/src/main/java/com/simibubi/create/content/schematics/ItemRequirement.java deleted file mode 100644 index 32f4c1563..000000000 --- a/src/main/java/com/simibubi/create/content/schematics/ItemRequirement.java +++ /dev/null @@ -1,178 +0,0 @@ -package com.simibubi.create.content.schematics; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.decoration.ArmorStand; -import net.minecraft.world.entity.decoration.ItemFrame; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.minecraft.world.level.block.AbstractBannerBlock; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.DirtPathBlock; -import net.minecraft.world.level.block.FarmBlock; -import net.minecraft.world.level.block.SeaPickleBlock; -import net.minecraft.world.level.block.SnowLayerBlock; -import net.minecraft.world.level.block.TurtleEggBlock; -import net.minecraft.world.level.block.entity.BannerBlockEntity; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.block.state.properties.SlabType; - -public class ItemRequirement { - public static final ItemRequirement NONE = new ItemRequirement(Collections.emptyList()); - public static final ItemRequirement INVALID = new ItemRequirement(Collections.emptyList()); - - protected List requiredItems; - - public ItemRequirement(List requiredItems) { - this.requiredItems = requiredItems; - } - - public ItemRequirement(StackRequirement stackRequirement) { - this(List.of(stackRequirement)); - } - - public ItemRequirement(ItemUseType usage, ItemStack stack) { - this(new StackRequirement(stack, usage)); - } - - public ItemRequirement(ItemUseType usage, Item item) { - this(usage, new ItemStack(item)); - } - - public ItemRequirement(ItemUseType usage, List requiredItems) { - this(requiredItems.stream().map(req -> new StackRequirement(req, usage)).collect(Collectors.toList())); - } - - public static ItemRequirement of(BlockState state, BlockEntity te) { - Block block = state.getBlock(); - - ItemRequirement requirement; - if (block instanceof ISpecialBlockItemRequirement specialBlock) { - requirement = specialBlock.getRequiredItems(state, te); - } else { - requirement = defaultOf(state, te); - } - - if (te instanceof ISpecialBlockEntityItemRequirement specialBE) - requirement = requirement.union(specialBE.getRequiredItems(state)); - - return requirement; - } - - private static ItemRequirement defaultOf(BlockState state, BlockEntity te) { - Block block = state.getBlock(); - if (block == Blocks.AIR) - return NONE; - - Item item = block.asItem(); - if (item == Items.AIR) - return INVALID; - - // double slab needs two items - if (state.hasProperty(BlockStateProperties.SLAB_TYPE) && state.getValue(BlockStateProperties.SLAB_TYPE) == SlabType.DOUBLE) - return new ItemRequirement(ItemUseType.CONSUME, new ItemStack(item, 2)); - if (block instanceof TurtleEggBlock) - return new ItemRequirement(ItemUseType.CONSUME, new ItemStack(item, state.getValue(TurtleEggBlock.EGGS).intValue())); - if (block instanceof SeaPickleBlock) - return new ItemRequirement(ItemUseType.CONSUME, new ItemStack(item, state.getValue(SeaPickleBlock.PICKLES).intValue())); - if (block instanceof SnowLayerBlock) - return new ItemRequirement(ItemUseType.CONSUME, new ItemStack(item, state.getValue(SnowLayerBlock.LAYERS).intValue())); - if (block instanceof FarmBlock || block instanceof DirtPathBlock) - return new ItemRequirement(ItemUseType.CONSUME, Items.DIRT); - if (block instanceof AbstractBannerBlock && te instanceof BannerBlockEntity bannerBE) - return new ItemRequirement(new StrictNbtStackRequirement(bannerBE.getItem(), ItemUseType.CONSUME)); - - return new ItemRequirement(ItemUseType.CONSUME, item); - } - - public static ItemRequirement of(Entity entity) { - if (entity instanceof ISpecialEntityItemRequirement specialEntity) - return specialEntity.getRequiredItems(); - - if (entity instanceof ItemFrame itemFrame) { - ItemStack frame = new ItemStack(Items.ITEM_FRAME); - ItemStack displayedItem = itemFrame.getItem(); - if (displayedItem.isEmpty()) - return new ItemRequirement(ItemUseType.CONSUME, Items.ITEM_FRAME); - return new ItemRequirement(ItemUseType.CONSUME, Arrays.asList(frame, displayedItem)); - } - - if (entity instanceof ArmorStand armorStand) { - List requirements = new ArrayList<>(); - requirements.add(new ItemStack(Items.ARMOR_STAND)); - armorStand.getAllSlots().forEach(requirements::add); - return new ItemRequirement(ItemUseType.CONSUME, requirements); - } - - ItemStack pickedStack = entity.getPickResult(); - if (pickedStack != null) { - return new ItemRequirement(ItemUseType.CONSUME, pickedStack); - } - - return INVALID; - } - - public boolean isEmpty() { - return NONE == this; - } - - public boolean isInvalid() { - return INVALID == this; - } - - public List getRequiredItems() { - return requiredItems; - } - - public ItemRequirement union(ItemRequirement other) { - if (this.isInvalid() || other.isInvalid()) - return INVALID; - if (this.isEmpty()) - return other; - if (other.isEmpty()) - return this; - - return new ItemRequirement( - Stream.concat(requiredItems.stream(), other.requiredItems.stream()).collect(Collectors.toList()) - ); - } - - public enum ItemUseType { - CONSUME, DAMAGE - } - - public static class StackRequirement { - public final ItemStack stack; - public final ItemUseType usage; - - public StackRequirement(ItemStack stack, ItemUseType usage) { - this.stack = stack; - this.usage = usage; - } - - public boolean matches(ItemStack other) { - return stack.sameItem(other); - } - } - - public static class StrictNbtStackRequirement extends StackRequirement { - public StrictNbtStackRequirement(ItemStack stack, ItemUseType usage) { - super(stack, usage); - } - - @Override - public boolean matches(ItemStack other) { - return ItemStack.isSameItemSameTags(stack, other); - } - } -} diff --git a/src/main/java/com/simibubi/create/content/schematics/MaterialChecklist.java b/src/main/java/com/simibubi/create/content/schematics/MaterialChecklist.java deleted file mode 100644 index d79dc1586..000000000 --- a/src/main/java/com/simibubi/create/content/schematics/MaterialChecklist.java +++ /dev/null @@ -1,170 +0,0 @@ -package com.simibubi.create.content.schematics; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Locale; - -import com.google.common.collect.Sets; -import com.simibubi.create.content.schematics.ItemRequirement.ItemUseType; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Lang; - -import it.unimi.dsi.fastutil.objects.Object2IntArrayMap; -import it.unimi.dsi.fastutil.objects.Object2IntMap; -import net.minecraft.ChatFormatting; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.StringTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.HoverEvent; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.network.chat.Style; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; - -public class MaterialChecklist { - - public static final int MAX_ENTRIES_PER_PAGE = 5; - - public Object2IntMap gathered = new Object2IntArrayMap<>(); - public Object2IntMap required = new Object2IntArrayMap<>(); - public Object2IntMap damageRequired = new Object2IntArrayMap<>(); - public boolean blocksNotLoaded; - - public void warnBlockNotLoaded() { - blocksNotLoaded = true; - } - - public void require(ItemRequirement requirement) { - if (requirement.isEmpty()) - return; - if (requirement.isInvalid()) - return; - - for (ItemRequirement.StackRequirement stack : requirement.requiredItems) { - if (stack.usage == ItemUseType.DAMAGE) - putOrIncrement(damageRequired, stack.stack); - if (stack.usage == ItemUseType.CONSUME) - putOrIncrement(required, stack.stack); - } - } - - private void putOrIncrement(Object2IntMap map, ItemStack stack) { - Item item = stack.getItem(); - if (item == Items.AIR) - return; - if (map.containsKey(item)) - map.put(item, map.getInt(item) + stack.getCount()); - else - map.put(item, stack.getCount()); - } - - public void collect(ItemStack stack) { - Item item = stack.getItem(); - if (required.containsKey(item) || damageRequired.containsKey(item)) - if (gathered.containsKey(item)) - gathered.put(item, gathered.getInt(item) + stack.getCount()); - else - gathered.put(item, stack.getCount()); - } - - public ItemStack createItem() { - ItemStack book = new ItemStack(Items.WRITTEN_BOOK); - - CompoundTag tag = book.getOrCreateTag(); - ListTag pages = new ListTag(); - - int itemsWritten = 0; - MutableComponent textComponent; - - if (blocksNotLoaded) { - textComponent = Components.literal("\n" + ChatFormatting.RED); - textComponent = textComponent.append(Lang.translateDirect("materialChecklist.blocksNotLoaded")); - pages.add(StringTag.valueOf(Component.Serializer.toJson(textComponent))); - } - - List keys = new ArrayList<>(Sets.union(required.keySet(), damageRequired.keySet())); - Collections.sort(keys, (item1, item2) -> { - Locale locale = Locale.ENGLISH; - String name1 = item1.getDescription().getString() - .toLowerCase(locale); - String name2 = item2.getDescription().getString() - .toLowerCase(locale); - return name1.compareTo(name2); - }); - - textComponent = Components.empty(); - List completed = new ArrayList<>(); - for (Item item : keys) { - int amount = getRequiredAmount(item); - if (gathered.containsKey(item)) - amount -= gathered.getInt(item); - - if (amount <= 0) { - completed.add(item); - continue; - } - - if (itemsWritten == MAX_ENTRIES_PER_PAGE) { - itemsWritten = 0; - textComponent.append(Components.literal("\n >>>").withStyle(ChatFormatting.BLUE)); - pages.add(StringTag.valueOf(Component.Serializer.toJson(textComponent))); - textComponent = Components.empty(); - } - - itemsWritten++; - textComponent.append(entry(new ItemStack(item), amount, true)); - } - - for (Item item : completed) { - if (itemsWritten == MAX_ENTRIES_PER_PAGE) { - itemsWritten = 0; - textComponent.append(Components.literal("\n >>>").withStyle(ChatFormatting.DARK_GREEN)); - pages.add(StringTag.valueOf(Component.Serializer.toJson(textComponent))); - textComponent = Components.empty(); - } - - itemsWritten++; - textComponent.append(entry(new ItemStack(item), getRequiredAmount(item), false)); - } - - pages.add(StringTag.valueOf(Component.Serializer.toJson(textComponent))); - - tag.put("pages", pages); - tag.putString("author", "Schematicannon"); - tag.putString("title", ChatFormatting.BLUE + "Material Checklist"); - textComponent = Lang.translateDirect("materialChecklist") - .setStyle(Style.EMPTY.withColor(ChatFormatting.BLUE) - .withItalic(Boolean.FALSE)); - book.getOrCreateTagElement("display") - .putString("Name", Component.Serializer.toJson(textComponent)); - book.setTag(tag); - - return book; - } - - public int getRequiredAmount(Item item) { - int amount = required.getOrDefault(item, 0); - if (damageRequired.containsKey(item)) - amount += Math.ceil(damageRequired.getInt(item) / (float) new ItemStack(item).getMaxDamage()); - return amount; - } - - private Component entry(ItemStack item, int amount, boolean unfinished) { - int stacks = amount / 64; - int remainder = amount % 64; - MutableComponent tc = Components.empty(); - tc.append(Components.translatable(item.getDescriptionId()) - .setStyle(Style.EMPTY - .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_ITEM, new HoverEvent.ItemStackInfo(item))))); - - if (!unfinished) - tc.append(" \u2714"); - tc.withStyle(unfinished ? ChatFormatting.BLUE : ChatFormatting.DARK_GREEN); - return tc.append(Components.literal("\n" + " x" + amount).withStyle(ChatFormatting.BLACK)) - .append(Components.literal(" | " + stacks + "\u25A4 +" + remainder + "\n").withStyle(ChatFormatting.GRAY)); - } - -} diff --git a/src/main/java/com/simibubi/create/content/schematics/item/SchematicAndQuillItem.java b/src/main/java/com/simibubi/create/content/schematics/SchematicAndQuillItem.java similarity index 94% rename from src/main/java/com/simibubi/create/content/schematics/item/SchematicAndQuillItem.java rename to src/main/java/com/simibubi/create/content/schematics/SchematicAndQuillItem.java index fe5160009..f3b9fc908 100644 --- a/src/main/java/com/simibubi/create/content/schematics/item/SchematicAndQuillItem.java +++ b/src/main/java/com/simibubi/create/content/schematics/SchematicAndQuillItem.java @@ -1,9 +1,9 @@ -package com.simibubi.create.content.schematics.item; +package com.simibubi.create.content.schematics; import java.util.Iterator; import com.simibubi.create.AllEntityTypes; -import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueEntity; +import com.simibubi.create.content.contraptions.glue.SuperGlueEntity; import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.RegisteredObjects; diff --git a/src/main/java/com/simibubi/create/content/schematics/SchematicExport.java b/src/main/java/com/simibubi/create/content/schematics/SchematicExport.java new file mode 100644 index 000000000..66bbc923b --- /dev/null +++ b/src/main/java/com/simibubi/create/content/schematics/SchematicExport.java @@ -0,0 +1,73 @@ +package com.simibubi.create.content.schematics; + +import java.io.IOException; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; + +import javax.annotation.Nullable; + +import com.simibubi.create.Create; +import com.simibubi.create.foundation.utility.FilesHelper; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtIo; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.levelgen.structure.BoundingBox; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; +import net.minecraft.world.phys.AABB; +import net.minecraftforge.fml.loading.FMLPaths; + +public class SchematicExport { + public static final Path SCHEMATICS = FMLPaths.GAMEDIR.get().resolve("schematics"); + + /** + * Save a schematic to a file from a world. + * @param dir the directory the schematic will be created in + * @param fileName the ideal name of the schematic, may not be the name of the created file + * @param overwrite whether overwriting an existing schematic is allowed + * @param level the level where the schematic structure is placed + * @param first the first corner of the schematic area + * @param second the second corner of the schematic area + * @return a SchematicExportResult, or null if an error occurred. + */ + @Nullable + public static SchematicExportResult saveSchematic(Path dir, String fileName, boolean overwrite, Level level, BlockPos first, BlockPos second) { + BoundingBox bb = BoundingBox.fromCorners(first, second); + BlockPos origin = new BlockPos(bb.minX(), bb.minY(), bb.minZ()); + BlockPos bounds = new BlockPos(bb.getXSpan(), bb.getYSpan(), bb.getZSpan()); + + StructureTemplate structure = new StructureTemplate(); + structure.fillFromWorld(level, origin, bounds, true, Blocks.AIR); + CompoundTag data = structure.save(new CompoundTag()); + SchematicAndQuillItem.replaceStructureVoidWithAir(data); + SchematicAndQuillItem.clampGlueBoxes(level, new AABB(origin, origin.offset(bounds)), data); + + if (fileName.isEmpty()) + fileName = Lang.translateDirect("schematicAndQuill.fallbackName").getString(); + if (!overwrite) + fileName = FilesHelper.findFirstValidFilename(fileName, dir, "nbt"); + if (!fileName.endsWith(".nbt")) + fileName += ".nbt"; + Path file = dir.resolve(fileName).toAbsolutePath(); + + try { + Files.createDirectories(dir); + boolean overwritten = Files.deleteIfExists(file); + try (OutputStream out = Files.newOutputStream(file, StandardOpenOption.CREATE)) { + NbtIo.writeCompressed(data, out); + } + return new SchematicExportResult(file, dir, fileName, overwritten, origin, bounds); + } catch (IOException e) { + Create.LOGGER.error("An error occurred while saving schematic [" + fileName + "]", e); + return null; + } + } + + public record SchematicExportResult(Path file, Path dir, String fileName, boolean overwritten, BlockPos origin, BlockPos bounds) { + } +} diff --git a/src/main/java/com/simibubi/create/content/schematics/filtering/SchematicInstances.java b/src/main/java/com/simibubi/create/content/schematics/SchematicInstances.java similarity index 83% rename from src/main/java/com/simibubi/create/content/schematics/filtering/SchematicInstances.java rename to src/main/java/com/simibubi/create/content/schematics/SchematicInstances.java index ee6c477ec..9d0fa1157 100644 --- a/src/main/java/com/simibubi/create/content/schematics/filtering/SchematicInstances.java +++ b/src/main/java/com/simibubi/create/content/schematics/SchematicInstances.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.schematics.filtering; +package com.simibubi.create.content.schematics; import java.util.concurrent.TimeUnit; @@ -6,11 +6,11 @@ import javax.annotation.Nullable; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; -import com.simibubi.create.content.schematics.SchematicWorld; -import com.simibubi.create.content.schematics.item.SchematicItem; +import com.simibubi.create.content.contraptions.StructureTransform; import com.simibubi.create.foundation.utility.WorldAttached; import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; import net.minecraft.core.Vec3i; import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; @@ -18,12 +18,13 @@ import net.minecraft.nbt.NbtUtils; 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.entity.BlockEntity; import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; public class SchematicInstances { - public static WorldAttached> loadedSchematics; + public static final WorldAttached> loadedSchematics; static { loadedSchematics = new WorldAttached<>($ -> CacheBuilder.newBuilder() @@ -67,6 +68,11 @@ public class SchematicInstances { StructurePlaceSettings settings = SchematicItem.getSettings(schematic); activeTemplate.placeInWorld(world, anchor, anchor, settings, wrapped.getRandom(), Block.UPDATE_CLIENTS); + StructureTransform transform = new StructureTransform(settings.getRotationPivot(), Direction.Axis.Y, + settings.getRotation(), settings.getMirror()); + for (BlockEntity be : world.getBlockEntities()) + transform.apply(be); + return world; } diff --git a/src/main/java/com/simibubi/create/content/schematics/item/SchematicItem.java b/src/main/java/com/simibubi/create/content/schematics/SchematicItem.java similarity index 96% rename from src/main/java/com/simibubi/create/content/schematics/item/SchematicItem.java rename to src/main/java/com/simibubi/create/content/schematics/SchematicItem.java index 7cb9e745c..7c2a3b4b5 100644 --- a/src/main/java/com/simibubi/create/content/schematics/item/SchematicItem.java +++ b/src/main/java/com/simibubi/create/content/schematics/SchematicItem.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.schematics.item; +package com.simibubi.create.content.schematics; import java.io.BufferedInputStream; import java.io.DataInputStream; @@ -16,9 +16,7 @@ import org.slf4j.Logger; import com.mojang.logging.LogUtils; import com.simibubi.create.AllItems; -import com.simibubi.create.content.schematics.SchematicProcessor; import com.simibubi.create.content.schematics.client.SchematicEditScreen; -import com.simibubi.create.content.schematics.filtering.SchematicInstances; import com.simibubi.create.foundation.gui.ScreenOpener; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Lang; diff --git a/src/main/java/com/simibubi/create/content/schematics/SchematicPrinter.java b/src/main/java/com/simibubi/create/content/schematics/SchematicPrinter.java index ab9b07050..9e633dd64 100644 --- a/src/main/java/com/simibubi/create/content/schematics/SchematicPrinter.java +++ b/src/main/java/com/simibubi/create/content/schematics/SchematicPrinter.java @@ -6,10 +6,11 @@ import java.util.stream.Collectors; import com.simibubi.create.AllBlocks; import com.simibubi.create.Create; -import com.simibubi.create.content.contraptions.components.structureMovement.BlockMovementChecks; -import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform; -import com.simibubi.create.content.schematics.item.SchematicItem; -import com.simibubi.create.foundation.tileEntity.IMergeableTE; +import com.simibubi.create.content.contraptions.BlockMovementChecks; +import com.simibubi.create.content.contraptions.StructureTransform; +import com.simibubi.create.content.schematics.cannon.MaterialChecklist; +import com.simibubi.create.content.schematics.requirement.ItemRequirement; +import com.simibubi.create.foundation.blockEntity.IMergeableBE; import com.simibubi.create.foundation.utility.BBHelper; import com.simibubi.create.foundation.utility.BlockHelper; @@ -114,8 +115,8 @@ public class SchematicPrinter { StructureTransform transform = new StructureTransform(settings.getRotationPivot(), Direction.Axis.Y, settings.getRotation(), settings.getMirror()); - for (BlockEntity te : blockReader.tileEntities.values()) - transform.apply(te); + for (BlockEntity be : blockReader.getBlockEntities()) + transform.apply(be); printingEntityIndex = -1; printStage = PrintStage.BLOCKS; @@ -165,7 +166,7 @@ public class SchematicPrinter { @FunctionalInterface public interface BlockTargetHandler { - void handle(BlockPos target, BlockState blockState, BlockEntity tileEntity); + void handle(BlockPos target, BlockState blockState, BlockEntity blockEntity); } @FunctionalInterface public interface EntityTargetHandler { @@ -182,14 +183,14 @@ public class SchematicPrinter { entityHandler.handle(target, entity); } else { BlockState blockState = BlockHelper.setZeroAge(blockReader.getBlockState(target)); - BlockEntity tileEntity = blockReader.getBlockEntity(target); - blockHandler.handle(target, blockState, tileEntity); + BlockEntity blockEntity = blockReader.getBlockEntity(target); + blockHandler.handle(target, blockState, blockEntity); } } @FunctionalInterface public interface PlacementPredicate { - boolean shouldPlace(BlockPos target, BlockState blockState, BlockEntity tileEntity, + boolean shouldPlace(BlockPos target, BlockState blockState, BlockEntity blockEntity, BlockState toReplace, BlockState toReplaceOther, boolean isNormalCube); } @@ -207,10 +208,10 @@ public class SchematicPrinter { public boolean shouldPlaceBlock(Level world, PlacementPredicate predicate, BlockPos pos) { BlockState state = BlockHelper.setZeroAge(blockReader.getBlockState(pos)); - BlockEntity tileEntity = blockReader.getBlockEntity(pos); + BlockEntity blockEntity = blockReader.getBlockEntity(pos); BlockState toReplace = world.getBlockState(pos); - BlockEntity toReplaceTE = world.getBlockEntity(pos); + BlockEntity toReplaceBE = world.getBlockEntity(pos); BlockState toReplaceOther = null; if (state.hasProperty(BlockStateProperties.BED_PART) && state.hasProperty(BlockStateProperties.HORIZONTAL_FACING) @@ -220,8 +221,8 @@ public class SchematicPrinter { && state.getValue(BlockStateProperties.DOUBLE_BLOCK_HALF) == DoubleBlockHalf.LOWER) toReplaceOther = world.getBlockState(pos.above()); - boolean mergeTEs = tileEntity != null && toReplaceTE instanceof IMergeableTE mergeTE && toReplaceTE.getType() - .equals(tileEntity.getType()); + boolean mergeTEs = blockEntity != null && toReplaceBE instanceof IMergeableBE mergeBE && toReplaceBE.getType() + .equals(blockEntity.getType()); if (!world.isLoaded(pos)) return false; @@ -234,7 +235,7 @@ public class SchematicPrinter { return false; boolean isNormalCube = state.isRedstoneConductor(blockReader, currentPos); - return predicate.shouldPlace(pos, state, tileEntity, toReplace, toReplaceOther, isNormalCube); + return predicate.shouldPlace(pos, state, blockEntity, toReplace, toReplaceOther, isNormalCube); } public ItemRequirement getCurrentRequirement() { @@ -245,8 +246,8 @@ public class SchematicPrinter { BlockPos target = getCurrentTarget(); BlockState blockState = BlockHelper.setZeroAge(blockReader.getBlockState(target)); - BlockEntity tileEntity = blockReader.getBlockEntity(target); - return ItemRequirement.of(blockState, tileEntity); + BlockEntity blockEntity = blockReader.getBlockEntity(target); + return ItemRequirement.of(blockState, blockEntity); } public int markAllBlockRequirements(MaterialChecklist checklist, Level world, PlacementPredicate predicate) { @@ -254,7 +255,7 @@ public class SchematicPrinter { for (BlockPos pos : blockReader.getAllPositions()) { BlockPos relPos = pos.offset(schematicAnchor); BlockState required = blockReader.getBlockState(relPos); - BlockEntity requiredTE = blockReader.getBlockEntity(relPos); + BlockEntity requiredBE = blockReader.getBlockEntity(relPos); if (!world.isLoaded(pos.offset(schematicAnchor))) { checklist.warnBlockNotLoaded(); @@ -262,7 +263,7 @@ public class SchematicPrinter { } if (!shouldPlaceBlock(world, predicate, relPos)) continue; - ItemRequirement requirement = ItemRequirement.of(required, requiredTE); + ItemRequirement requirement = ItemRequirement.of(required, requiredBE); if (requirement.isEmpty()) continue; if (requirement.isInvalid()) diff --git a/src/main/java/com/simibubi/create/content/schematics/SchematicProcessor.java b/src/main/java/com/simibubi/create/content/schematics/SchematicProcessor.java index e5507d8e7..131338652 100644 --- a/src/main/java/com/simibubi/create/content/schematics/SchematicProcessor.java +++ b/src/main/java/com/simibubi/create/content/schematics/SchematicProcessor.java @@ -33,9 +33,9 @@ public class SchematicProcessor extends StructureProcessor { public StructureTemplate.StructureBlockInfo process(LevelReader world, BlockPos pos, BlockPos anotherPos, StructureTemplate.StructureBlockInfo rawInfo, StructureTemplate.StructureBlockInfo info, StructurePlaceSettings settings, @Nullable StructureTemplate template) { if (info.nbt != null && info.state.hasBlockEntity()) { - BlockEntity te = ((EntityBlock) info.state.getBlock()).newBlockEntity(info.pos, info.state); - if (te != null) { - CompoundTag nbt = NBTProcessors.process(te, info.nbt, false); + BlockEntity be = ((EntityBlock) info.state.getBlock()).newBlockEntity(info.pos, info.state); + if (be != null) { + CompoundTag nbt = NBTProcessors.process(be, info.nbt, false); if (nbt != info.nbt) return new StructureTemplate.StructureBlockInfo(info.pos, info.state, nbt); } diff --git a/src/main/java/com/simibubi/create/content/schematics/SchematicWorld.java b/src/main/java/com/simibubi/create/content/schematics/SchematicWorld.java index 512f55d7f..cc57999cb 100644 --- a/src/main/java/com/simibubi/create/content/schematics/SchematicWorld.java +++ b/src/main/java/com/simibubi/create/content/schematics/SchematicWorld.java @@ -11,6 +11,7 @@ import java.util.stream.Stream; import com.simibubi.create.Create; import com.simibubi.create.foundation.utility.BBHelper; +import com.simibubi.create.foundation.utility.NBTProcessors; import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld; import net.minecraft.core.BlockPos; @@ -19,6 +20,7 @@ import net.minecraft.core.Holder; import net.minecraft.core.registries.Registries; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.decoration.ArmorStand; import net.minecraft.world.entity.decoration.ItemFrame; import net.minecraft.world.entity.player.Player; @@ -44,8 +46,8 @@ import net.minecraft.world.ticks.LevelTickAccess; public class SchematicWorld extends WrappedWorld implements ServerLevelAccessor { protected Map blocks; - protected Map tileEntities; - protected List renderedTileEntities; + protected Map blockEntities; + protected List renderedBlockEntities; protected List entities; protected BoundingBox bounds; @@ -60,11 +62,11 @@ public class SchematicWorld extends WrappedWorld implements ServerLevelAccessor super(original); setChunkSource(new SchematicChunkSource(this)); this.blocks = new HashMap<>(); - this.tileEntities = new HashMap<>(); + this.blockEntities = new HashMap<>(); this.bounds = new BoundingBox(BlockPos.ZERO); this.anchor = anchor; this.entities = new ArrayList<>(); - this.renderedTileEntities = new ArrayList<>(); + this.renderedBlockEntities = new ArrayList<>(); } public Set getAllPositions() { @@ -73,14 +75,12 @@ public class SchematicWorld extends WrappedWorld implements ServerLevelAccessor @Override public boolean addFreshEntity(Entity entityIn) { - if (entityIn instanceof ItemFrame) - ((ItemFrame) entityIn).getItem() - .setTag(null); - if (entityIn instanceof ArmorStand) { - ArmorStand armorStandEntity = (ArmorStand) entityIn; - armorStandEntity.getAllSlots() - .forEach(stack -> stack.setTag(null)); - } + if (entityIn instanceof ItemFrame itemFrame) + itemFrame.setItem(NBTProcessors.withUnsafeNBTDiscarded(itemFrame.getItem())); + if (entityIn instanceof ArmorStand armorStand) + for (EquipmentSlot equipmentSlot : EquipmentSlot.values()) + armorStand.setItemSlot(equipmentSlot, + NBTProcessors.withUnsafeNBTDiscarded(armorStand.getItemBySlot(equipmentSlot))); return entities.add(entityIn); } @@ -93,30 +93,30 @@ public class SchematicWorld extends WrappedWorld implements ServerLevelAccessor public BlockEntity getBlockEntity(BlockPos pos) { if (isOutsideBuildHeight(pos)) return null; - if (tileEntities.containsKey(pos)) - return tileEntities.get(pos); + if (blockEntities.containsKey(pos)) + return blockEntities.get(pos); if (!blocks.containsKey(pos.subtract(anchor))) return null; BlockState blockState = getBlockState(pos); if (blockState.hasBlockEntity()) { try { - BlockEntity tileEntity = ((EntityBlock) blockState.getBlock()).newBlockEntity(pos, blockState); - if (tileEntity != null) { - onTEadded(tileEntity, pos); - tileEntities.put(pos, tileEntity); - renderedTileEntities.add(tileEntity); + BlockEntity blockEntity = ((EntityBlock) blockState.getBlock()).newBlockEntity(pos, blockState); + if (blockEntity != null) { + onBEadded(blockEntity, pos); + blockEntities.put(pos, blockEntity); + renderedBlockEntities.add(blockEntity); } - return tileEntity; + return blockEntity; } catch (Exception e) { - Create.LOGGER.debug("Could not create TE of block " + blockState, e); + Create.LOGGER.debug("Could not create BlockEntity of block " + blockState, e); } } return null; } - protected void onTEadded(BlockEntity tileEntity, BlockPos pos) { - tileEntity.setLevel(this); + protected void onBEadded(BlockEntity blockEntity, BlockPos pos) { + blockEntity.setLevel(this); } @Override @@ -124,7 +124,7 @@ public class SchematicWorld extends WrappedWorld implements ServerLevelAccessor BlockPos pos = globalPos.subtract(anchor); if (pos.getY() - bounds.minY() == -1 && !renderMode) - return Blocks.GRASS_BLOCK.defaultBlockState(); + return Blocks.DIRT.defaultBlockState(); if (getBounds().isInside(pos) && blocks.containsKey(pos)) return processBlockStateForPrinting(blocks.get(pos)); return Blocks.AIR.defaultBlockState(); @@ -207,18 +207,18 @@ public class SchematicWorld extends WrappedWorld implements ServerLevelAccessor .subtract(anchor); bounds = BBHelper.encapsulate(bounds, pos); blocks.put(pos, arg1); - if (tileEntities.containsKey(pos)) { - BlockEntity tileEntity = tileEntities.get(pos); - if (!tileEntity.getType() + if (blockEntities.containsKey(pos)) { + BlockEntity blockEntity = blockEntities.get(pos); + if (!blockEntity.getType() .isValid(arg1)) { - tileEntities.remove(pos); - renderedTileEntities.remove(tileEntity); + blockEntities.remove(pos); + renderedBlockEntities.remove(blockEntity); } } - BlockEntity tileEntity = getBlockEntity(pos); - if (tileEntity != null) - tileEntities.put(pos, tileEntity); + BlockEntity blockEntity = getBlockEntity(pos); + if (blockEntity != null) + blockEntities.put(pos, blockEntity); return true; } @@ -229,9 +229,13 @@ public class SchematicWorld extends WrappedWorld implements ServerLevelAccessor public BoundingBox getBounds() { return bounds; } + + public Iterable getBlockEntities() { + return blockEntities.values(); + } - public Iterable getRenderedTileEntities() { - return renderedTileEntities; + public Iterable getRenderedBlockEntities() { + return renderedBlockEntities; } protected BlockState processBlockStateForPrinting(BlockState state) { diff --git a/src/main/java/com/simibubi/create/content/schematics/ServerSchematicLoader.java b/src/main/java/com/simibubi/create/content/schematics/ServerSchematicLoader.java index 801e06238..62266c992 100644 --- a/src/main/java/com/simibubi/create/content/schematics/ServerSchematicLoader.java +++ b/src/main/java/com/simibubi/create/content/schematics/ServerSchematicLoader.java @@ -8,6 +8,7 @@ import java.nio.file.Paths; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; @@ -16,27 +17,22 @@ import java.util.stream.Stream; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; import com.simibubi.create.Create; -import com.simibubi.create.content.schematics.block.SchematicTableTileEntity; -import com.simibubi.create.content.schematics.item.SchematicAndQuillItem; -import com.simibubi.create.content.schematics.item.SchematicItem; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.config.CSchematics; +import com.simibubi.create.content.schematics.SchematicExport.SchematicExportResult; +import com.simibubi.create.content.schematics.table.SchematicTableBlockEntity; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.FilesHelper; import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.infrastructure.config.AllConfigs; +import com.simibubi.create.infrastructure.config.CSchematics; +import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; import net.minecraft.core.registries.Registries; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtIo; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; -import net.minecraft.world.phys.AABB; public class ServerSchematicLoader { @@ -124,7 +120,7 @@ public class ServerSchematicLoader { try { // Validate Referenced Block - SchematicTableTileEntity table = getTable(player.getCommandSenderWorld(), pos); + SchematicTableBlockEntity table = getTable(player.getCommandSenderWorld(), pos); if (table == null) return; @@ -152,7 +148,7 @@ public class ServerSchematicLoader { OutputStream writer = Files.newOutputStream(uploadPath); activeUploads.put(playerSchematicId, new SchematicUploadEntry(writer, size, player.getLevel(), pos)); - // Notify Tile Entity + // Notify Block Entity table.startUpload(schematic); } catch (IOException e) { @@ -164,7 +160,6 @@ public class ServerSchematicLoader { protected boolean validateSchematicSizeOnServer(ServerPlayer player, long size) { Integer maxFileSize = getConfig().maxTotalSchematicSize.get(); if (size > maxFileSize * 1000) { - player.sendSystemMessage(Lang.translateDirect("schematics.uploadTooLarge") .append(Components.literal(" (" + size / 1000 + " KB)."))); player.sendSystemMessage(Lang.translateDirect("schematics.maxAllowedSize") @@ -175,7 +170,7 @@ public class ServerSchematicLoader { } public CSchematics getConfig() { - return AllConfigs.SERVER.schematics; + return AllConfigs.server().schematics; } public void handleWriteRequest(ServerPlayer player, String schematic, byte[] data) { @@ -203,7 +198,7 @@ public class ServerSchematicLoader { entry.stream.write(data); entry.idleTime = 0; - SchematicTableTileEntity table = getTable(entry.world, entry.tablePos); + SchematicTableBlockEntity table = getTable(entry.world, entry.tablePos); if (table == null) return; table.uploadingProgress = (float) ((double) entry.bytesUploaded / entry.totalBytes); @@ -236,16 +231,16 @@ public class ServerSchematicLoader { if (pos == null) return; - SchematicTableTileEntity table = getTable(entry.world, pos); + SchematicTableBlockEntity table = getTable(entry.world, pos); if (table != null) table.finishUpload(); } - public SchematicTableTileEntity getTable(Level world, BlockPos pos) { - BlockEntity te = world.getBlockEntity(pos); - if (!(te instanceof SchematicTableTileEntity)) + public SchematicTableBlockEntity getTable(Level world, BlockPos pos) { + BlockEntity be = world.getBlockEntity(pos); + if (!(be instanceof SchematicTableBlockEntity)) return null; - SchematicTableTileEntity table = (SchematicTableTileEntity) te; + SchematicTableBlockEntity table = (SchematicTableBlockEntity) be; return table; } @@ -268,7 +263,7 @@ public class ServerSchematicLoader { if (AllBlocks.SCHEMATIC_TABLE.get() != blockState.getBlock()) return; - SchematicTableTileEntity table = getTable(world, pos); + SchematicTableBlockEntity table = getTable(world, pos); if (table == null) return; table.finishUpload(); @@ -284,10 +279,9 @@ public class ServerSchematicLoader { public void handleInstantSchematic(ServerPlayer player, String schematic, Level world, BlockPos pos, BlockPos bounds) { - String playerPath = getSchematicPath() + "/" + player.getGameProfile() - .getName(); - String playerSchematicId = player.getGameProfile() - .getName() + "/" + schematic; + String playerName = player.getGameProfile().getName(); + String playerPath = getSchematicPath() + "/" + playerName; + String playerSchematicId = playerName + "/" + schematic; FilesHelper.createFolderIfMissing(playerPath); // Unsupported Format @@ -310,43 +304,45 @@ public class ServerSchematicLoader { if (!AllItems.SCHEMATIC_AND_QUILL.isIn(player.getMainHandItem())) return; + // if there's too many schematics, delete oldest + Path playerSchematics = Paths.get(playerPath); + + if (!tryDeleteOldestSchematic(playerSchematics)) + return; + + SchematicExportResult result = SchematicExport.saveSchematic( + playerSchematics, schematic, true, + world, pos, pos.offset(bounds).offset(-1, -1, -1) + ); + if (result != null) + player.setItemInHand(InteractionHand.MAIN_HAND, + SchematicItem.create(world.holderLookup(Registries.BLOCK), schematic, playerName)); + else + Lang.translate("schematicAndQuill.instant_failed") + .style(ChatFormatting.RED) + .sendStatus(player); + } + + private boolean tryDeleteOldestSchematic(Path dir) { + try (Stream stream = Files.list(dir)) { + List files = stream.toList(); + if (files.size() < getConfig().maxSchematics.get()) + return true; + Optional oldest = files.stream().min(Comparator.comparingLong(this::getLastModifiedTime)); + Files.delete(oldest.orElseThrow()); + return true; + } catch (IOException | IllegalStateException e) { + Create.LOGGER.error("Error deleting oldest schematic", e); + return false; + } + } + + private long getLastModifiedTime(Path file) { try { - // Delete schematic with same name - Files.deleteIfExists(path); - - // Too many Schematics - long count; - try (Stream list = Files.list(Paths.get(playerPath))) { - count = list.count(); - } - - if (count >= getConfig().maxSchematics.get()) { - Stream list2 = Files.list(Paths.get(playerPath)); - Optional lastFilePath = list2.filter(f -> !Files.isDirectory(f)) - .min(Comparator.comparingLong(f -> f.toFile() - .lastModified())); - list2.close(); - if (lastFilePath.isPresent()) - Files.deleteIfExists(lastFilePath.get()); - } - - StructureTemplate t = new StructureTemplate(); - t.fillFromWorld(world, pos, bounds, true, Blocks.AIR); - - try (OutputStream outputStream = Files.newOutputStream(path)) { - CompoundTag nbttagcompound = t.save(new CompoundTag()); - SchematicAndQuillItem.replaceStructureVoidWithAir(nbttagcompound); - SchematicAndQuillItem.clampGlueBoxes(world, new AABB(pos, pos.offset(bounds)), nbttagcompound); - NbtIo.writeCompressed(nbttagcompound, outputStream); - player.setItemInHand(InteractionHand.MAIN_HAND, SchematicItem.create(world.holderLookup(Registries.BLOCK), schematic, player.getGameProfile() - .getName())); - - } catch (IOException e) { - e.printStackTrace(); - } + return Files.getLastModifiedTime(file).toMillis(); } catch (IOException e) { - Create.LOGGER.error("Exception Thrown in direct Schematic Upload: " + playerSchematicId); - e.printStackTrace(); + Create.LOGGER.error("Error getting modification time of file " + file.getFileName(), e); + throw new IllegalStateException(e); } } diff --git a/src/main/java/com/simibubi/create/content/schematics/block/SchematicTableContainer.java b/src/main/java/com/simibubi/create/content/schematics/block/SchematicTableContainer.java deleted file mode 100644 index 36d9eb85b..000000000 --- a/src/main/java/com/simibubi/create/content/schematics/block/SchematicTableContainer.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.simibubi.create.content.schematics.block; - -import com.simibubi.create.AllContainerTypes; -import com.simibubi.create.AllItems; -import com.simibubi.create.foundation.gui.container.ContainerBase; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.entity.player.Inventory; -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 net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraftforge.items.SlotItemHandler; - -public class SchematicTableContainer extends ContainerBase { - - private Slot inputSlot; - private Slot outputSlot; - - public SchematicTableContainer(MenuType type, int id, Inventory inv, FriendlyByteBuf extraData) { - super(type, id, inv, extraData); - } - - public SchematicTableContainer(MenuType type, int id, Inventory inv, SchematicTableTileEntity te) { - super(type, id, inv, te); - } - - public static SchematicTableContainer create(int id, Inventory inv, SchematicTableTileEntity te) { - return new SchematicTableContainer(AllContainerTypes.SCHEMATIC_TABLE.get(), id, inv, te); - } - - public boolean canWrite() { - return inputSlot.hasItem() && !outputSlot.hasItem(); - } - - @Override - public ItemStack quickMoveStack(Player playerIn, int index) { - Slot clickedSlot = getSlot(index); - if (!clickedSlot.hasItem()) - return ItemStack.EMPTY; - - ItemStack stack = clickedSlot.getItem(); - if (index < 2) - moveItemStackTo(stack, 2, slots.size(), false); - else - moveItemStackTo(stack, 0, 1, false); - - return ItemStack.EMPTY; - } - - @Override - protected SchematicTableTileEntity createOnClient(FriendlyByteBuf extraData) { - ClientLevel world = Minecraft.getInstance().level; - BlockEntity tileEntity = world.getBlockEntity(extraData.readBlockPos()); - if (tileEntity instanceof SchematicTableTileEntity schematicTable) { - schematicTable.readClient(extraData.readNbt()); - return schematicTable; - } - return null; - } - - @Override - protected void initAndReadInventory(SchematicTableTileEntity contentHolder) { - } - - @Override - protected void addSlots() { - inputSlot = new SlotItemHandler(contentHolder.inventory, 0, 21, 57) { - @Override - public boolean mayPlace(ItemStack stack) { - return AllItems.EMPTY_SCHEMATIC.isIn(stack) || AllItems.SCHEMATIC_AND_QUILL.isIn(stack) - || AllItems.SCHEMATIC.isIn(stack); - } - }; - - outputSlot = new SlotItemHandler(contentHolder.inventory, 1, 166, 57) { - @Override - public boolean mayPlace(ItemStack stack) { - return false; - } - }; - - addSlot(inputSlot); - addSlot(outputSlot); - - // player Slots - for (int row = 0; row < 3; ++row) { - for (int col = 0; col < 9; ++col) { - this.addSlot(new Slot(player.getInventory(), col + row * 9 + 9, 38 + col * 18, 105 + row * 18)); - } - } - - for (int hotbarSlot = 0; hotbarSlot < 9; ++hotbarSlot) { - this.addSlot(new Slot(player.getInventory(), hotbarSlot, 38 + hotbarSlot * 18, 163)); - } - } - - @Override - protected void saveData(SchematicTableTileEntity contentHolder) { - } - -} diff --git a/src/main/java/com/simibubi/create/content/schematics/block/SchematicTableTileEntity.java b/src/main/java/com/simibubi/create/content/schematics/block/SchematicTableTileEntity.java deleted file mode 100644 index bcfe54721..000000000 --- a/src/main/java/com/simibubi/create/content/schematics/block/SchematicTableTileEntity.java +++ /dev/null @@ -1,131 +0,0 @@ -package com.simibubi.create.content.schematics.block; - -import java.util.List; - -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.utility.IInteractionChecker; -import com.simibubi.create.foundation.utility.Lang; - -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -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.item.ItemStack; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.items.ItemStackHandler; - -public class SchematicTableTileEntity extends SmartTileEntity implements MenuProvider, IInteractionChecker { - - public SchematicTableInventory inventory; - public boolean isUploading; - public String uploadingSchematic; - public float uploadingProgress; - public boolean sendUpdate; - - public class SchematicTableInventory extends ItemStackHandler { - public SchematicTableInventory() { - super(2); - } - - @Override - protected void onContentsChanged(int slot) { - super.onContentsChanged(slot); - setChanged(); - } - } - - public SchematicTableTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - inventory = new SchematicTableInventory(); - uploadingSchematic = null; - uploadingProgress = 0; - } - - public void sendToContainer(FriendlyByteBuf buffer) { - buffer.writeBlockPos(getBlockPos()); - buffer.writeNbt(getUpdateTag()); - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - inventory.deserializeNBT(compound.getCompound("Inventory")); - super.read(compound, clientPacket); - - if (!clientPacket) - return; - if (compound.contains("Uploading")) { - isUploading = true; - uploadingSchematic = compound.getString("Schematic"); - uploadingProgress = compound.getFloat("Progress"); - } else { - isUploading = false; - uploadingSchematic = null; - uploadingProgress = 0; - } - } - - @Override - protected void write(CompoundTag compound, boolean clientPacket) { - compound.put("Inventory", inventory.serializeNBT()); - super.write(compound, clientPacket); - - if (clientPacket && isUploading) { - compound.putBoolean("Uploading", true); - compound.putString("Schematic", uploadingSchematic); - compound.putFloat("Progress", uploadingProgress); - } - } - - @Override - public void tick() { - // Update Client Tile - if (sendUpdate) { - sendUpdate = false; - level.sendBlockUpdated(worldPosition, getBlockState(), getBlockState(), 6); - } - } - - public void startUpload(String schematic) { - isUploading = true; - uploadingProgress = 0; - uploadingSchematic = schematic; - sendUpdate = true; - inventory.setStackInSlot(0, ItemStack.EMPTY); - } - - public void finishUpload() { - isUploading = false; - uploadingProgress = 0; - uploadingSchematic = null; - sendUpdate = true; - } - - @Override - public AbstractContainerMenu createMenu(int id, Inventory inv, Player player) { - return SchematicTableContainer.create(id, inv, this); - } - - @Override - public Component getDisplayName() { - return Lang.translateDirect("gui.schematicTable.title"); - } - - @Override - public boolean canPlayerUse(Player player) { - if (level == null || level.getBlockEntity(worldPosition) != this) { - return false; - } - return player.distanceToSqr(worldPosition.getX() + 0.5D, worldPosition.getY() + 0.5D, - worldPosition.getZ() + 0.5D) <= 64.0D; - } - - @Override - public void addBehaviours(List behaviours) {} - -} diff --git a/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonBlock.java b/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonBlock.java deleted file mode 100644 index bf1807eb3..000000000 --- a/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonBlock.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.simibubi.create.content.schematics.block; - -import javax.annotation.Nullable; - -import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.foundation.block.ITE; -import com.simibubi.create.foundation.item.ItemHelper; - -import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.util.Mth; -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.entity.BlockEntityType; -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.VoxelShape; -import net.minecraftforge.network.NetworkHooks; - -public class SchematicannonBlock extends Block implements ITE { - - public SchematicannonBlock(Properties properties) { - super(properties); - } - - @Override - public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) { - return AllShapes.SCHEMATICANNON_SHAPE; - } - - @Override - public void setPlacedBy(Level level, BlockPos pos, BlockState state, @Nullable LivingEntity entity, ItemStack stack) { - if (entity != null) { - withTileEntityDo(level, pos, be -> { - be.defaultYaw = (-Mth.floor((entity.getYRot() + (entity.isShiftKeyDown() ? 180.0F : 0.0F)) * 16.0F / 360.0F + 0.5F) & 15) * 360.0F / 16.0F; - }); - } - } - - @Override - public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, - BlockHitResult hit) { - if (worldIn.isClientSide) - return InteractionResult.SUCCESS; - withTileEntityDo(worldIn, pos, - te -> NetworkHooks.openScreen((ServerPlayer) player, te, te::sendToContainer)); - return InteractionResult.SUCCESS; - } - - @Override - public void neighborChanged(BlockState state, Level worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, - boolean isMoving) { - withTileEntityDo(worldIn, pos, te -> te.neighbourCheckCooldown = 0); - } - - @Override - public void onRemove(BlockState state, Level worldIn, BlockPos pos, BlockState newState, boolean isMoving) { - if (!state.hasBlockEntity() || state.getBlock() == newState.getBlock()) - return; - - withTileEntityDo(worldIn, pos, te -> ItemHelper.dropContents(worldIn, pos, te.inventory)); - worldIn.removeBlockEntity(pos); - } - - @Override - public Class getTileEntityClass() { - return SchematicannonTileEntity.class; - } - - @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.SCHEMATICANNON.get(); - } - -} diff --git a/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonContainer.java b/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonContainer.java deleted file mode 100644 index 6d83bb020..000000000 --- a/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonContainer.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.simibubi.create.content.schematics.block; - -import com.simibubi.create.AllContainerTypes; -import com.simibubi.create.foundation.gui.container.ContainerBase; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.entity.player.Inventory; -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 net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraftforge.items.SlotItemHandler; - -public class SchematicannonContainer extends ContainerBase { - - public SchematicannonContainer(MenuType type, int id, Inventory inv, FriendlyByteBuf buffer) { - super(type, id, inv, buffer); - } - - public SchematicannonContainer(MenuType type, int id, Inventory inv, SchematicannonTileEntity te) { - super(type, id, inv, te); - } - - public static SchematicannonContainer create(int id, Inventory inv, SchematicannonTileEntity te) { - return new SchematicannonContainer(AllContainerTypes.SCHEMATICANNON.get(), id, inv, te); - } - - @Override - protected SchematicannonTileEntity createOnClient(FriendlyByteBuf extraData) { - ClientLevel world = Minecraft.getInstance().level; - BlockEntity tileEntity = world.getBlockEntity(extraData.readBlockPos()); - if (tileEntity instanceof SchematicannonTileEntity schematicannon) { - schematicannon.readClient(extraData.readNbt()); - return schematicannon; - } - return null; - } - - @Override - protected void initAndReadInventory(SchematicannonTileEntity contentHolder) { - } - - @Override - protected void addSlots() { - int x = 0; - int y = 0; - - addSlot(new SlotItemHandler(contentHolder.inventory, 0, x + 15, y + 65)); - addSlot(new SlotItemHandler(contentHolder.inventory, 1, x + 171, y + 65)); - addSlot(new SlotItemHandler(contentHolder.inventory, 2, x + 134, y + 19)); - addSlot(new SlotItemHandler(contentHolder.inventory, 3, x + 174, y + 19)); - addSlot(new SlotItemHandler(contentHolder.inventory, 4, x + 15, y + 19)); - - addPlayerSlots(37, 161); - } - - @Override - protected void saveData(SchematicannonTileEntity contentHolder) { - } - - @Override - public ItemStack quickMoveStack(Player playerIn, int index) { - Slot clickedSlot = getSlot(index); - if (!clickedSlot.hasItem()) - return ItemStack.EMPTY; - ItemStack stack = clickedSlot.getItem(); - - if (index < 5) { - moveItemStackTo(stack, 5, slots.size(), false); - } else { - if (moveItemStackTo(stack, 0, 1, false) || moveItemStackTo(stack, 2, 3, false) - || moveItemStackTo(stack, 4, 5, false)) - ; - } - - return ItemStack.EMPTY; - } - -} diff --git a/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonInventory.java b/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonInventory.java deleted file mode 100644 index e7252dd8f..000000000 --- a/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonInventory.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.simibubi.create.content.schematics.block; - -import com.simibubi.create.AllItems; - -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.minecraftforge.items.ItemStackHandler; - -public class SchematicannonInventory extends ItemStackHandler { - /** - * - */ - private final SchematicannonTileEntity te; - - public SchematicannonInventory(SchematicannonTileEntity schematicannonTileEntity) { - super(5); - te = schematicannonTileEntity; - } - - @Override - protected void onContentsChanged(int slot) { - super.onContentsChanged(slot); - te.setChanged(); - } - - @Override - public boolean isItemValid(int slot, ItemStack stack) { - switch (slot) { - case 0: // Blueprint Slot - return AllItems.SCHEMATIC.isIn(stack); - case 1: // Blueprint output - return false; - case 2: // Book input - return stack.sameItem(new ItemStack(Items.BOOK)) || stack.sameItem(new ItemStack(Items.WRITTEN_BOOK)); - case 3: // Material List output - return false; - case 4: // Gunpowder - return stack.sameItem(new ItemStack(Items.GUNPOWDER)); - default: - return super.isItemValid(slot, stack); - } - } -} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonRenderer.java b/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonRenderer.java deleted file mode 100644 index 4862ff68c..000000000 --- a/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonRenderer.java +++ /dev/null @@ -1,226 +0,0 @@ -package com.simibubi.create.content.schematics.block; - -import com.jozufozu.flywheel.backend.Backend; -import com.jozufozu.flywheel.core.model.ModelUtil; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import com.mojang.math.Axis; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.schematics.block.LaunchedItem.ForBelt; -import com.simibubi.create.content.schematics.block.LaunchedItem.ForBlockState; -import com.simibubi.create.content.schematics.block.LaunchedItem.ForEntity; -import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.block.model.ItemTransforms.TransformType; -import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.util.Mth; -import net.minecraft.util.RandomSource; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; - -public class SchematicannonRenderer extends SafeTileEntityRenderer { - - public SchematicannonRenderer(BlockEntityRendererProvider.Context context) {} - - @Override - protected void renderSafe(SchematicannonTileEntity tileEntity, float partialTicks, PoseStack ms, - MultiBufferSource buffer, int light, int overlay) { - - boolean blocksLaunching = !tileEntity.flyingBlocks.isEmpty(); - if (blocksLaunching) - renderLaunchedBlocks(tileEntity, partialTicks, ms, buffer, light, overlay); - - if (Backend.canUseInstancing(tileEntity.getLevel())) - return; - - BlockPos pos = tileEntity.getBlockPos(); - BlockState state = tileEntity.getBlockState(); - - double[] cannonAngles = getCannonAngles(tileEntity, pos, partialTicks); - - double yaw = cannonAngles[0]; - double pitch = cannonAngles[1]; - - double recoil = getRecoil(tileEntity, partialTicks); - - ms.pushPose(); - - VertexConsumer vb = buffer.getBuffer(RenderType.solid()); - - SuperByteBuffer connector = CachedBufferer.partial(AllBlockPartials.SCHEMATICANNON_CONNECTOR, state); - connector.translate(.5f, 0, .5f); - connector.rotate(Direction.UP, (float) ((yaw + 90) / 180 * Math.PI)); - connector.translate(-.5f, 0, -.5f); - connector.light(light) - .renderInto(ms, vb); - - SuperByteBuffer pipe = CachedBufferer.partial(AllBlockPartials.SCHEMATICANNON_PIPE, state); - pipe.translate(.5f, 15 / 16f, .5f); - pipe.rotate(Direction.UP, (float) ((yaw + 90) / 180 * Math.PI)); - pipe.rotate(Direction.SOUTH, (float) (pitch / 180 * Math.PI)); - pipe.translate(-.5f, -15 / 16f, -.5f); - pipe.translate(0, -recoil / 100, 0); - pipe.light(light) - .renderInto(ms, vb); - - ms.popPose(); - } - - public static double[] getCannonAngles(SchematicannonTileEntity tile, BlockPos pos, float partialTicks) { - double yaw; - double pitch; - - BlockPos target = tile.printer.getCurrentTarget(); - if (target != null) { - - // Calculate Angle of Cannon - Vec3 diff = Vec3.atLowerCornerOf(target.subtract(pos)); - if (tile.previousTarget != null) { - diff = (Vec3.atLowerCornerOf(tile.previousTarget) - .add(Vec3.atLowerCornerOf(target.subtract(tile.previousTarget)) - .scale(partialTicks))).subtract(Vec3.atLowerCornerOf(pos)); - } - - double diffX = diff.x(); - double diffZ = diff.z(); - yaw = Mth.atan2(diffX, diffZ); - yaw = yaw / Math.PI * 180; - - float distance = Mth.sqrt((float) (diffX * diffX + diffZ * diffZ)); - double yOffset = 0 + distance * 2f; - pitch = Mth.atan2(distance, diff.y() * 3 + yOffset); - pitch = pitch / Math.PI * 180 + 10; - - } else { - yaw = tile.defaultYaw; - pitch = 40; - } - - return new double[] { yaw, pitch }; - } - - public static double getRecoil(SchematicannonTileEntity tileEntityIn, float partialTicks) { - double recoil = 0; - - for (LaunchedItem launched : tileEntityIn.flyingBlocks) { - - if (launched.ticksRemaining == 0) - continue; - - // Apply Recoil if block was just launched - if ((launched.ticksRemaining + 1 - partialTicks) > launched.totalTicks - 10) - recoil = Math.max(recoil, (launched.ticksRemaining + 1 - partialTicks) - launched.totalTicks + 10); - } - - return recoil; - } - - private static void renderLaunchedBlocks(SchematicannonTileEntity tileEntityIn, float partialTicks, PoseStack ms, - MultiBufferSource buffer, int light, int overlay) { - for (LaunchedItem launched : tileEntityIn.flyingBlocks) { - - if (launched.ticksRemaining == 0) - continue; - - // Calculate position of flying block - Vec3 start = Vec3.atCenterOf(tileEntityIn.getBlockPos() - .above()); - Vec3 target = Vec3.atCenterOf(launched.target); - Vec3 distance = target.subtract(start); - - double yDifference = target.y - start.y; - double throwHeight = Math.sqrt(distance.lengthSqr()) * .6f + yDifference; - Vec3 cannonOffset = distance.add(0, throwHeight, 0) - .normalize() - .scale(2); - start = start.add(cannonOffset); - yDifference = target.y - start.y; - - float progress = - ((float) launched.totalTicks - (launched.ticksRemaining + 1 - partialTicks)) / launched.totalTicks; - Vec3 blockLocationXZ = target.subtract(start) - .scale(progress) - .multiply(1, 0, 1); - - // Height is determined through a bezier curve - float t = progress; - double yOffset = 2 * (1 - t) * t * throwHeight + t * t * yDifference; - Vec3 blockLocation = blockLocationXZ.add(0.5, yOffset + 1.5, 0.5) - .add(cannonOffset); - - // Offset to position - ms.pushPose(); - ms.translate(blockLocation.x, blockLocation.y, blockLocation.z); - - ms.translate(.125f, .125f, .125f); - ms.mulPose(Axis.YP.rotationDegrees(360 * t)); - ms.mulPose(Axis.XP.rotationDegrees(360 * t)); - ms.translate(-.125f, -.125f, -.125f); - - if (launched instanceof ForBlockState) { - // Render the Block - BlockState state; - if (launched instanceof ForBelt) { - // Render a shaft instead of the belt - state = AllBlocks.SHAFT.getDefaultState(); - } else { - state = ((ForBlockState) launched).state; - } - float scale = .3f; - ms.scale(scale, scale, scale); - Minecraft.getInstance() - .getBlockRenderer() - .renderSingleBlock(state, ms, buffer, light, overlay, - ModelUtil.VIRTUAL_DATA, null); - } else if (launched instanceof ForEntity) { - // Render the item - float scale = 1.2f; - ms.scale(scale, scale, scale); - Minecraft.getInstance() - .getItemRenderer() - .renderStatic(launched.stack, TransformType.GROUND, light, overlay, ms, buffer, 0); - } - - ms.popPose(); - - // Render particles for launch - if (launched.ticksRemaining == launched.totalTicks && tileEntityIn.firstRenderTick) { - start = start.subtract(.5, .5, .5); - tileEntityIn.firstRenderTick = false; - for (int i = 0; i < 10; i++) { - RandomSource r = tileEntityIn.getLevel() - .getRandom(); - double sX = cannonOffset.x * .01f; - double sY = (cannonOffset.y + 1) * .01f; - double sZ = cannonOffset.z * .01f; - double rX = r.nextFloat() - sX * 40; - double rY = r.nextFloat() - sY * 40; - double rZ = r.nextFloat() - sZ * 40; - tileEntityIn.getLevel() - .addParticle(ParticleTypes.CLOUD, start.x + rX, start.y + rY, start.z + rZ, sX, sY, sZ); - } - } - - } - } - - @Override - public boolean shouldRenderOffScreen(SchematicannonTileEntity tileEntity) { - return true; - } - - @Override - public int getViewDistance() { - return 128; - } - -} diff --git a/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonTileEntity.java b/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonTileEntity.java deleted file mode 100644 index f07b83f94..000000000 --- a/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonTileEntity.java +++ /dev/null @@ -1,858 +0,0 @@ -package com.simibubi.create.content.schematics.block; - -import java.util.LinkedHashSet; -import java.util.LinkedList; -import java.util.List; - -import javax.annotation.Nullable; - -import com.simibubi.create.AllBlocks; -import com.simibubi.create.AllItems; -import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.AllTags.AllBlockTags; -import com.simibubi.create.content.contraptions.relays.belt.BeltBlock; -import com.simibubi.create.content.contraptions.relays.belt.BeltPart; -import com.simibubi.create.content.contraptions.relays.belt.BeltSlope; -import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity; -import com.simibubi.create.content.contraptions.relays.elementary.AbstractSimpleShaftBlock; -import com.simibubi.create.content.schematics.ItemRequirement; -import com.simibubi.create.content.schematics.ItemRequirement.ItemUseType; -import com.simibubi.create.content.schematics.MaterialChecklist; -import com.simibubi.create.content.schematics.SchematicPrinter; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.config.CSchematics; -import com.simibubi.create.foundation.item.ItemHelper; -import com.simibubi.create.foundation.item.ItemHelper.ExtractionCountMode; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.utility.IPartialSafeNBT; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.NBTProcessors; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Direction.Axis; -import net.minecraft.core.Direction.AxisDirection; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.chat.Component; -import net.minecraft.world.MenuProvider; -import net.minecraft.world.entity.Entity; -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.BlockItem; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.piston.PistonHeadBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BedPart; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; -import net.minecraft.world.phys.AABB; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.items.CapabilityItemHandler; -import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.ItemHandlerHelper; -import net.minecraftforge.items.wrapper.EmptyHandler; - -public class SchematicannonTileEntity extends SmartTileEntity implements MenuProvider { - - public static final int NEIGHBOUR_CHECKING = 100; - public static final int MAX_ANCHOR_DISTANCE = 256; - - // Inventory - public SchematicannonInventory inventory; - - public boolean sendUpdate; - // Sync - public boolean dontUpdateChecklist; - public int neighbourCheckCooldown; - - // Printer - public SchematicPrinter printer; - public ItemStack missingItem; - public boolean positionNotLoaded; - public boolean hasCreativeCrate; - private int printerCooldown; - private int skipsLeft; - private boolean blockSkipped; - - public BlockPos previousTarget; - public LinkedHashSet> attachedInventories; - public List flyingBlocks; - public MaterialChecklist checklist; - - // Gui information - public float fuelLevel; - public float bookPrintingProgress; - public float schematicProgress; - public String statusMsg; - public State state; - public int blocksPlaced; - public int blocksToPlace; - - // Settings - public int replaceMode; - public boolean skipMissing; - public boolean replaceTileEntities; - - // Render - public boolean firstRenderTick; - public float defaultYaw; - - public SchematicannonTileEntity(BlockEntityType type, BlockPos pos, BlockState state) { - super(type, pos, state); - setLazyTickRate(30); - attachedInventories = new LinkedHashSet<>(); - flyingBlocks = new LinkedList<>(); - inventory = new SchematicannonInventory(this); - statusMsg = "idle"; - this.state = State.STOPPED; - replaceMode = 2; - checklist = new MaterialChecklist(); - printer = new SchematicPrinter(); - } - - public void findInventories() { - hasCreativeCrate = false; - attachedInventories.clear(); - for (Direction facing : Iterate.directions) { - - if (!level.isLoaded(worldPosition.relative(facing))) - continue; - - if (AllBlocks.CREATIVE_CRATE.has(level.getBlockState(worldPosition.relative(facing)))) - hasCreativeCrate = true; - - BlockEntity tileEntity = level.getBlockEntity(worldPosition.relative(facing)); - if (tileEntity != null) { - LazyOptional capability = - tileEntity.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, facing.getOpposite()); - if (capability.isPresent()) { - attachedInventories.add(capability); - } - } - } - } - - @Override - protected void read(CompoundTag compound, boolean clientPacket) { - if (!clientPacket) { - inventory.deserializeNBT(compound.getCompound("Inventory")); - } - - // Gui information - statusMsg = compound.getString("Status"); - schematicProgress = compound.getFloat("Progress"); - bookPrintingProgress = compound.getFloat("PaperProgress"); - fuelLevel = compound.getFloat("Fuel"); - String stateString = compound.getString("State"); - state = stateString.isEmpty() ? State.STOPPED : State.valueOf(compound.getString("State")); - blocksPlaced = compound.getInt("AmountPlaced"); - blocksToPlace = compound.getInt("AmountToPlace"); - - missingItem = null; - if (compound.contains("MissingItem")) - missingItem = ItemStack.of(compound.getCompound("MissingItem")); - - // Settings - CompoundTag options = compound.getCompound("Options"); - replaceMode = options.getInt("ReplaceMode"); - skipMissing = options.getBoolean("SkipMissing"); - replaceTileEntities = options.getBoolean("ReplaceTileEntities"); - - // Printer & Flying Blocks - if (compound.contains("Printer")) - printer.fromTag(compound.getCompound("Printer"), clientPacket); - if (compound.contains("FlyingBlocks")) - readFlyingBlocks(compound); - - defaultYaw = compound.getFloat("DefaultYaw"); - - super.read(compound, clientPacket); - } - - protected void readFlyingBlocks(CompoundTag compound) { - ListTag tagBlocks = compound.getList("FlyingBlocks", 10); - if (tagBlocks.isEmpty()) - flyingBlocks.clear(); - - boolean pastDead = false; - - for (int i = 0; i < tagBlocks.size(); i++) { - CompoundTag c = tagBlocks.getCompound(i); - LaunchedItem launched = LaunchedItem.fromNBT(c); - BlockPos readBlockPos = launched.target; - - // Always write to Server tile - if (level == null || !level.isClientSide) { - flyingBlocks.add(launched); - continue; - } - - // Delete all Client side blocks that are now missing on the server - while (!pastDead && !flyingBlocks.isEmpty() && !flyingBlocks.get(0).target.equals(readBlockPos)) { - flyingBlocks.remove(0); - } - - pastDead = true; - - // Add new server side blocks - if (i >= flyingBlocks.size()) { - flyingBlocks.add(launched); - continue; - } - - // Don't do anything with existing - } - } - - @Override - public void write(CompoundTag compound, boolean clientPacket) { - if (!clientPacket) { - compound.put("Inventory", inventory.serializeNBT()); - if (state == State.RUNNING) { - compound.putBoolean("Running", true); - } - } - - // Gui information - compound.putFloat("Progress", schematicProgress); - compound.putFloat("PaperProgress", bookPrintingProgress); - compound.putFloat("Fuel", fuelLevel); - compound.putString("Status", statusMsg); - compound.putString("State", state.name()); - compound.putInt("AmountPlaced", blocksPlaced); - compound.putInt("AmountToPlace", blocksToPlace); - - if (missingItem != null) - compound.put("MissingItem", missingItem.serializeNBT()); - - // Settings - CompoundTag options = new CompoundTag(); - options.putInt("ReplaceMode", replaceMode); - options.putBoolean("SkipMissing", skipMissing); - options.putBoolean("ReplaceTileEntities", replaceTileEntities); - compound.put("Options", options); - - // Printer & Flying Blocks - CompoundTag printerData = new CompoundTag(); - printer.write(printerData); - compound.put("Printer", printerData); - - ListTag tagFlyingBlocks = new ListTag(); - for (LaunchedItem b : flyingBlocks) - tagFlyingBlocks.add(b.serializeNBT()); - compound.put("FlyingBlocks", tagFlyingBlocks); - - compound.putFloat("DefaultYaw", defaultYaw); - - super.write(compound, clientPacket); - } - - @Override - public void tick() { - super.tick(); - - if (state != State.STOPPED && neighbourCheckCooldown-- <= 0) { - neighbourCheckCooldown = NEIGHBOUR_CHECKING; - findInventories(); - } - - firstRenderTick = true; - previousTarget = printer.getCurrentTarget(); - tickFlyingBlocks(); - - if (level.isClientSide) - return; - - // Update Fuel and Paper - tickPaperPrinter(); - refillFuelIfPossible(); - - // Update Printer - skipsLeft = 1000; - blockSkipped = true; - - while (blockSkipped && skipsLeft-- > 0) - tickPrinter(); - - schematicProgress = 0; - if (blocksToPlace > 0) - schematicProgress = (float) blocksPlaced / blocksToPlace; - - // Update Client Tile - if (sendUpdate) { - sendUpdate = false; - level.sendBlockUpdated(worldPosition, getBlockState(), getBlockState(), 6); - } - } - - public CSchematics config() { - return AllConfigs.SERVER.schematics; - } - - protected void tickPrinter() { - ItemStack blueprint = inventory.getStackInSlot(0); - blockSkipped = false; - - if (blueprint.isEmpty() && !statusMsg.equals("idle") && inventory.getStackInSlot(1) - .isEmpty()) { - state = State.STOPPED; - statusMsg = "idle"; - sendUpdate = true; - return; - } - - // Skip if not Active - if (state == State.STOPPED) { - if (printer.isLoaded()) - resetPrinter(); - return; - } - - if (state == State.PAUSED && !positionNotLoaded && missingItem == null && fuelLevel > getFuelUsageRate()) - return; - - // Initialize Printer - if (!printer.isLoaded()) { - initializePrinter(blueprint); - return; - } - - // Cooldown from last shot - if (printerCooldown > 0) { - printerCooldown--; - return; - } - - // Check Fuel - if (fuelLevel <= 0 && !hasCreativeCrate) { - fuelLevel = 0; - state = State.PAUSED; - statusMsg = "noGunpowder"; - sendUpdate = true; - return; - } - - if (hasCreativeCrate) { - if (missingItem != null) { - missingItem = null; - state = State.RUNNING; - } - } - - // Update Target - if (missingItem == null && !positionNotLoaded) { - if (!printer.advanceCurrentPos()) { - finishedPrinting(); - return; - } - sendUpdate = true; - } - - // Check block - if (!getLevel().isLoaded(printer.getCurrentTarget())) { - positionNotLoaded = true; - statusMsg = "targetNotLoaded"; - state = State.PAUSED; - return; - } else { - if (positionNotLoaded) { - positionNotLoaded = false; - state = State.RUNNING; - } - } - - // Get item requirement - ItemRequirement requirement = printer.getCurrentRequirement(); - if (requirement.isInvalid() || !printer.shouldPlaceCurrent(level, this::shouldPlace)) { - sendUpdate = !statusMsg.equals("searching"); - statusMsg = "searching"; - blockSkipped = true; - return; - } - - // Find item - List requiredItems = requirement.getRequiredItems(); - if (!requirement.isEmpty()) { - for (ItemRequirement.StackRequirement required : requiredItems) { - if (!grabItemsFromAttachedInventories(required, true)) { - if (skipMissing) { - statusMsg = "skipping"; - blockSkipped = true; - if (missingItem != null) { - missingItem = null; - state = State.RUNNING; - } - return; - } - - missingItem = required.stack; - state = State.PAUSED; - statusMsg = "missingBlock"; - return; - } - } - - for (ItemRequirement.StackRequirement required : requiredItems) - grabItemsFromAttachedInventories(required, false); - } - - // Success - state = State.RUNNING; - ItemStack icon = requirement.isEmpty() || requiredItems.isEmpty() ? ItemStack.EMPTY : requiredItems.get(0).stack; - printer.handleCurrentTarget((target, blockState, tile) -> { - // Launch block - statusMsg = blockState.getBlock() != Blocks.AIR ? "placing" : "clearing"; - launchBlockOrBelt(target, icon, blockState, tile); - }, (target, entity) -> { - // Launch entity - statusMsg = "placing"; - launchEntity(target, icon, entity); - }); - - printerCooldown = config().schematicannonDelay.get(); - fuelLevel -= getFuelUsageRate(); - sendUpdate = true; - missingItem = null; - } - - public double getFuelUsageRate() { - return hasCreativeCrate ? 0 : config().schematicannonFuelUsage.get() / 100f; - } - - protected void initializePrinter(ItemStack blueprint) { - if (!blueprint.hasTag()) { - state = State.STOPPED; - statusMsg = "schematicInvalid"; - sendUpdate = true; - return; - } - - if (!blueprint.getTag() - .getBoolean("Deployed")) { - state = State.STOPPED; - statusMsg = "schematicNotPlaced"; - sendUpdate = true; - return; - } - - // Load blocks into reader - printer.loadSchematic(blueprint, level, true); - - if (printer.isErrored()) { - state = State.STOPPED; - statusMsg = "schematicErrored"; - inventory.setStackInSlot(0, ItemStack.EMPTY); - inventory.setStackInSlot(1, new ItemStack(AllItems.EMPTY_SCHEMATIC.get())); - printer.resetSchematic(); - sendUpdate = true; - return; - } - - if (printer.isWorldEmpty()) { - state = State.STOPPED; - statusMsg = "schematicExpired"; - inventory.setStackInSlot(0, ItemStack.EMPTY); - inventory.setStackInSlot(1, new ItemStack(AllItems.EMPTY_SCHEMATIC.get())); - printer.resetSchematic(); - sendUpdate = true; - return; - } - - if (!printer.getAnchor() - .closerThan(getBlockPos(), MAX_ANCHOR_DISTANCE)) { - state = State.STOPPED; - statusMsg = "targetOutsideRange"; - printer.resetSchematic(); - sendUpdate = true; - return; - } - - state = State.PAUSED; - statusMsg = "ready"; - updateChecklist(); - sendUpdate = true; - blocksToPlace += blocksPlaced; - } - - protected ItemStack getItemForBlock(BlockState blockState) { - Item item = BlockItem.BY_BLOCK.getOrDefault(blockState.getBlock(), Items.AIR); - return item == Items.AIR ? ItemStack.EMPTY : new ItemStack(item); - } - - protected boolean grabItemsFromAttachedInventories(ItemRequirement.StackRequirement required, boolean simulate) { - if (hasCreativeCrate) - return true; - - attachedInventories.removeIf(cap -> !cap.isPresent()); - - ItemUseType usage = required.usage; - - // Find and apply damage - if (usage == ItemUseType.DAMAGE) { - for (LazyOptional cap : attachedInventories) { - IItemHandler iItemHandler = cap.orElse(EmptyHandler.INSTANCE); - for (int slot = 0; slot < iItemHandler.getSlots(); slot++) { - ItemStack extractItem = iItemHandler.extractItem(slot, 1, true); - if (!required.matches(extractItem)) - continue; - if (!extractItem.isDamageableItem()) - continue; - - if (!simulate) { - ItemStack stack = iItemHandler.extractItem(slot, 1, false); - stack.setDamageValue(stack.getDamageValue() + 1); - if (stack.getDamageValue() <= stack.getMaxDamage()) { - if (iItemHandler.getStackInSlot(slot) - .isEmpty()) - iItemHandler.insertItem(slot, stack, false); - else - ItemHandlerHelper.insertItem(iItemHandler, stack, false); - } - } - - return true; - } - } - - return false; - } - - // Find and remove - boolean success = false; - int amountFound = 0; - for (LazyOptional cap : attachedInventories) { - IItemHandler iItemHandler = cap.orElse(EmptyHandler.INSTANCE); - amountFound += ItemHelper - .extract(iItemHandler, required::matches, ExtractionCountMode.UPTO, - required.stack.getCount(), true) - .getCount(); - - if (amountFound < required.stack.getCount()) - continue; - - success = true; - break; - } - - if (!simulate && success) { - amountFound = 0; - for (LazyOptional cap : attachedInventories) { - IItemHandler iItemHandler = cap.orElse(EmptyHandler.INSTANCE); - amountFound += ItemHelper - .extract(iItemHandler, required::matches, ExtractionCountMode.UPTO, - required.stack.getCount(), false) - .getCount(); - if (amountFound < required.stack.getCount()) - continue; - break; - } - } - - return success; - } - - public void finishedPrinting() { - inventory.setStackInSlot(0, ItemStack.EMPTY); - inventory.setStackInSlot(1, new ItemStack(AllItems.EMPTY_SCHEMATIC.get(), inventory.getStackInSlot(1) - .getCount() + 1)); - state = State.STOPPED; - statusMsg = "finished"; - resetPrinter(); - AllSoundEvents.SCHEMATICANNON_FINISH.playOnServer(level, worldPosition); - sendUpdate = true; - } - - protected void resetPrinter() { - printer.resetSchematic(); - missingItem = null; - sendUpdate = true; - schematicProgress = 0; - blocksPlaced = 0; - blocksToPlace = 0; - } - - protected boolean shouldPlace(BlockPos pos, BlockState state, BlockEntity te, BlockState toReplace, - BlockState toReplaceOther, boolean isNormalCube) { - if (pos.closerThan(getBlockPos(), 2f)) - return false; - if (!replaceTileEntities - && (toReplace.hasBlockEntity() || (toReplaceOther != null && toReplaceOther.hasBlockEntity()))) - return false; - - if (shouldIgnoreBlockState(state, te)) - return false; - - boolean placingAir = state.isAir(); - - if (replaceMode == 3) - return true; - if (replaceMode == 2 && !placingAir) - return true; - if (replaceMode == 1 && (isNormalCube || (!toReplace.isRedstoneConductor(level, pos) - && (toReplaceOther == null || !toReplaceOther.isRedstoneConductor(level, pos)))) && !placingAir) - return true; - if (replaceMode == 0 && !toReplace.isRedstoneConductor(level, pos) - && (toReplaceOther == null || !toReplaceOther.isRedstoneConductor(level, pos)) && !placingAir) - return true; - - return false; - } - - protected boolean shouldIgnoreBlockState(BlockState state, BlockEntity te) { - // Block doesn't have a mapping (Water, lava, etc) - if (state.getBlock() == Blocks.STRUCTURE_VOID) - return true; - - ItemRequirement requirement = ItemRequirement.of(state, te); - if (requirement.isEmpty()) - return false; - if (requirement.isInvalid()) - return false; - - // Block doesn't need to be placed twice (Doors, beds, double plants) - if (state.hasProperty(BlockStateProperties.DOUBLE_BLOCK_HALF) - && state.getValue(BlockStateProperties.DOUBLE_BLOCK_HALF) == DoubleBlockHalf.UPPER) - return true; - if (state.hasProperty(BlockStateProperties.BED_PART) - && state.getValue(BlockStateProperties.BED_PART) == BedPart.HEAD) - return true; - if (state.getBlock() instanceof PistonHeadBlock) - return true; - if (AllBlocks.BELT.has(state)) - return state.getValue(BeltBlock.PART) == BeltPart.MIDDLE; - - return false; - } - - protected void tickFlyingBlocks() { - List toRemove = new LinkedList<>(); - for (LaunchedItem b : flyingBlocks) - if (b.update(level)) - toRemove.add(b); - flyingBlocks.removeAll(toRemove); - } - - protected void refillFuelIfPossible() { - if (hasCreativeCrate) - return; - if (1 - fuelLevel + 1 / 128f < getFuelAddedByGunPowder()) - return; - if (inventory.getStackInSlot(4) - .isEmpty()) - return; - - inventory.getStackInSlot(4) - .shrink(1); - fuelLevel += getFuelAddedByGunPowder(); - if (statusMsg.equals("noGunpowder")) { - if (blocksPlaced > 0) - state = State.RUNNING; - statusMsg = "ready"; - } - sendUpdate = true; - } - - public double getFuelAddedByGunPowder() { - return config().schematicannonGunpowderWorth.get() / 100f; - } - - protected void tickPaperPrinter() { - int BookInput = 2; - int BookOutput = 3; - - ItemStack blueprint = inventory.getStackInSlot(0); - ItemStack paper = inventory.extractItem(BookInput, 1, true); - boolean outputFull = inventory.getStackInSlot(BookOutput) - .getCount() == inventory.getSlotLimit(BookOutput); - - if (printer.isErrored()) - return; - - if (!printer.isLoaded()) { - if (!blueprint.isEmpty()) - initializePrinter(blueprint); - return; - } - - if (paper.isEmpty() || outputFull) { - if (bookPrintingProgress != 0) - sendUpdate = true; - bookPrintingProgress = 0; - dontUpdateChecklist = false; - return; - } - - if (bookPrintingProgress >= 1) { - bookPrintingProgress = 0; - - if (!dontUpdateChecklist) - updateChecklist(); - - dontUpdateChecklist = true; - inventory.extractItem(BookInput, 1, false); - ItemStack stack = checklist.createItem(); - stack.setCount(inventory.getStackInSlot(BookOutput) - .getCount() + 1); - inventory.setStackInSlot(BookOutput, stack); - sendUpdate = true; - return; - } - - bookPrintingProgress += 0.05f; - sendUpdate = true; - } - - public static BlockState stripBeltIfNotLast(BlockState blockState) { - BeltPart part = blockState.getValue(BeltBlock.PART); - if (part == BeltPart.MIDDLE) - return Blocks.AIR.defaultBlockState(); - - // is highest belt? - boolean isLastSegment = false; - Direction facing = blockState.getValue(BeltBlock.HORIZONTAL_FACING); - BeltSlope slope = blockState.getValue(BeltBlock.SLOPE); - boolean positive = facing.getAxisDirection() == AxisDirection.POSITIVE; - boolean start = part == BeltPart.START; - boolean end = part == BeltPart.END; - - switch (slope) { - case DOWNWARD: - isLastSegment = start; - break; - case UPWARD: - isLastSegment = end; - break; - default: - isLastSegment = positive && end || !positive && start; - } - if (isLastSegment) - return blockState; - - return AllBlocks.SHAFT.getDefaultState() - .setValue(AbstractSimpleShaftBlock.AXIS, slope == BeltSlope.SIDEWAYS ? Axis.Y : - facing.getClockWise() - .getAxis()); - } - - protected void launchBlockOrBelt(BlockPos target, ItemStack icon, BlockState blockState, BlockEntity tile) { - if (AllBlocks.BELT.has(blockState)) { - blockState = stripBeltIfNotLast(blockState); - if (tile instanceof BeltTileEntity && AllBlocks.BELT.has(blockState)) - launchBelt(target, blockState, ((BeltTileEntity) tile).beltLength); - else if (blockState != Blocks.AIR.defaultBlockState()) - launchBlock(target, icon, blockState, null); - } else { - CompoundTag data = null; - if (tile != null) { - if (AllBlockTags.SAFE_NBT.matches(blockState)) { - data = tile.saveWithFullMetadata(); - data = NBTProcessors.process(tile, data, true); - } else if (tile instanceof IPartialSafeNBT) { - data = new CompoundTag(); - ((IPartialSafeNBT) tile).writeSafe(data); - data = NBTProcessors.process(tile, data, true); - } - } - launchBlock(target, icon, blockState, data); - } - } - - protected void launchBelt(BlockPos target, BlockState state, int length) { - blocksPlaced++; - ItemStack connector = AllItems.BELT_CONNECTOR.asStack(); - flyingBlocks.add(new LaunchedItem.ForBelt(this.getBlockPos(), target, connector, state, length)); - playFiringSound(); - } - - protected void launchBlock(BlockPos target, ItemStack stack, BlockState state, @Nullable CompoundTag data) { - if (!state.isAir()) - blocksPlaced++; - flyingBlocks.add(new LaunchedItem.ForBlockState(this.getBlockPos(), target, stack, state, data)); - playFiringSound(); - } - - protected void launchEntity(BlockPos target, ItemStack stack, Entity entity) { - blocksPlaced++; - flyingBlocks.add(new LaunchedItem.ForEntity(this.getBlockPos(), target, stack, entity)); - playFiringSound(); - } - - public void playFiringSound() { - AllSoundEvents.SCHEMATICANNON_LAUNCH_BLOCK.playOnServer(level, worldPosition); - } - - public void sendToContainer(FriendlyByteBuf buffer) { - buffer.writeBlockPos(getBlockPos()); - buffer.writeNbt(getUpdateTag()); - } - - @Override - public AbstractContainerMenu createMenu(int id, Inventory inv, Player player) { - return SchematicannonContainer.create(id, inv, this); - } - - @Override - public Component getDisplayName() { - return Lang.translateDirect("gui.schematicannon.title"); - } - - public void updateChecklist() { - checklist.required.clear(); - checklist.damageRequired.clear(); - checklist.blocksNotLoaded = false; - - if (printer.isLoaded() && !printer.isErrored()) { - blocksToPlace = blocksPlaced; - blocksToPlace += printer.markAllBlockRequirements(checklist, level, this::shouldPlace); - printer.markAllEntityRequirements(checklist); - } - - checklist.gathered.clear(); - findInventories(); - for (LazyOptional cap : attachedInventories) { - if (!cap.isPresent()) - continue; - IItemHandler inventory = cap.orElse(EmptyHandler.INSTANCE); - for (int slot = 0; slot < inventory.getSlots(); slot++) { - ItemStack stackInSlot = inventory.getStackInSlot(slot); - if (inventory.extractItem(slot, 1, true) - .isEmpty()) - continue; - checklist.collect(stackInSlot); - } - } - sendUpdate = true; - } - - @Override - public void addBehaviours(List behaviours) {} - - @Override - public void lazyTick() { - super.lazyTick(); - findInventories(); - } - - @Override - @OnlyIn(Dist.CLIENT) - public AABB getRenderBoundingBox() { - return INFINITE_EXTENT_AABB; - } - - public enum State { - STOPPED, PAUSED, RUNNING; - } - -} diff --git a/src/main/java/com/simibubi/create/content/schematics/cannon/ConfigureSchematicannonPacket.java b/src/main/java/com/simibubi/create/content/schematics/cannon/ConfigureSchematicannonPacket.java new file mode 100644 index 000000000..041e0ae15 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/schematics/cannon/ConfigureSchematicannonPacket.java @@ -0,0 +1,77 @@ +package com.simibubi.create.content.schematics.cannon; + +import com.simibubi.create.content.schematics.cannon.SchematicannonBlockEntity.State; +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraftforge.network.NetworkEvent.Context; + +public class ConfigureSchematicannonPacket extends SimplePacketBase { + + public static enum Option { + DONT_REPLACE, REPLACE_SOLID, REPLACE_ANY, REPLACE_EMPTY, SKIP_MISSING, SKIP_BLOCK_ENTITIES, PLAY, PAUSE, STOP; + } + + private Option option; + private boolean set; + + public ConfigureSchematicannonPacket(Option option, boolean set) { + this.option = option; + this.set = set; + } + + public ConfigureSchematicannonPacket(FriendlyByteBuf buffer) { + this(buffer.readEnum(Option.class), buffer.readBoolean()); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeEnum(option); + buffer.writeBoolean(set); + } + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> { + ServerPlayer player = context.getSender(); + if (player == null || !(player.containerMenu instanceof SchematicannonMenu)) + return; + + SchematicannonBlockEntity be = ((SchematicannonMenu) player.containerMenu).contentHolder; + switch (option) { + case DONT_REPLACE: + case REPLACE_ANY: + case REPLACE_EMPTY: + case REPLACE_SOLID: + be.replaceMode = option.ordinal(); + break; + case SKIP_MISSING: + be.skipMissing = set; + break; + case SKIP_BLOCK_ENTITIES: + be.replaceBlockEntities = set; + break; + + case PLAY: + be.state = State.RUNNING; + be.statusMsg = "running"; + break; + case PAUSE: + be.state = State.PAUSED; + be.statusMsg = "paused"; + break; + case STOP: + be.state = State.STOPPED; + be.statusMsg = "stopped"; + break; + default: + break; + } + + be.sendUpdate = true; + }); + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/schematics/block/LaunchedItem.java b/src/main/java/com/simibubi/create/content/schematics/cannon/LaunchedItem.java similarity index 79% rename from src/main/java/com/simibubi/create/content/schematics/block/LaunchedItem.java rename to src/main/java/com/simibubi/create/content/schematics/cannon/LaunchedItem.java index 57e3a7e24..4540a976e 100644 --- a/src/main/java/com/simibubi/create/content/schematics/block/LaunchedItem.java +++ b/src/main/java/com/simibubi/create/content/schematics/cannon/LaunchedItem.java @@ -1,13 +1,16 @@ -package com.simibubi.create.content.schematics.block; +package com.simibubi.create.content.schematics.cannon; +import java.util.Arrays; import java.util.Optional; import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.relays.belt.BeltBlock; -import com.simibubi.create.content.contraptions.relays.belt.BeltPart; -import com.simibubi.create.content.contraptions.relays.belt.BeltSlope; -import com.simibubi.create.content.contraptions.relays.belt.item.BeltConnectorItem; -import com.simibubi.create.content.contraptions.relays.elementary.AbstractSimpleShaftBlock; +import com.simibubi.create.content.kinetics.belt.BeltBlock; +import com.simibubi.create.content.kinetics.belt.BeltBlockEntity; +import com.simibubi.create.content.kinetics.belt.BeltBlockEntity.CasingType; +import com.simibubi.create.content.kinetics.belt.BeltPart; +import com.simibubi.create.content.kinetics.belt.BeltSlope; +import com.simibubi.create.content.kinetics.belt.item.BeltConnectorItem; +import com.simibubi.create.content.kinetics.simpleRelays.AbstractSimpleShaftBlock; import com.simibubi.create.foundation.utility.BlockHelper; import net.minecraft.core.BlockPos; @@ -16,6 +19,7 @@ import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtUtils; import net.minecraft.nbt.Tag; +import net.minecraft.util.Mth; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.item.ItemStack; @@ -128,6 +132,7 @@ public abstract class LaunchedItem { public static class ForBelt extends ForBlockState { public int length; + public CasingType[] casings; public ForBelt() {} @@ -135,18 +140,27 @@ public abstract class LaunchedItem { public CompoundTag serializeNBT() { CompoundTag serializeNBT = super.serializeNBT(); serializeNBT.putInt("Length", length); + serializeNBT.putIntArray("Casing", Arrays.stream(casings) + .map(CasingType::ordinal) + .toList()); return serializeNBT; } @Override void readNBT(CompoundTag nbt) { length = nbt.getInt("Length"); + int[] intArray = nbt.getIntArray("Casing"); + casings = new CasingType[length]; + for (int i = 0; i < casings.length; i++) + casings[i] = i >= intArray.length ? CasingType.NONE + : CasingType.values()[Mth.clamp(intArray[i], 0, CasingType.values().length - 1)]; super.readNBT(nbt); } - public ForBelt(BlockPos start, BlockPos target, ItemStack stack, BlockState state, int length) { + public ForBelt(BlockPos start, BlockPos target, ItemStack stack, BlockState state, CasingType[] casings) { super(start, target, stack, state, null); - this.length = length; + this.casings = casings; + this.length = casings.length; } @Override @@ -162,6 +176,15 @@ public abstract class LaunchedItem { .setValue(AbstractSimpleShaftBlock.AXIS, axis)); BeltConnectorItem.createBelts(world, target, target.offset(offset.getX() * i, offset.getY() * i, offset.getZ() * i)); + + for (int segment = 0; segment < length; segment++) { + if (casings[segment] == CasingType.NONE) + continue; + BlockPos casingTarget = + target.offset(offset.getX() * segment, offset.getY() * segment, offset.getZ() * segment); + if (world.getBlockEntity(casingTarget) instanceof BeltBlockEntity bbe) + bbe.setCasingType(casings[segment]); + } } } diff --git a/src/main/java/com/simibubi/create/content/schematics/cannon/MaterialChecklist.java b/src/main/java/com/simibubi/create/content/schematics/cannon/MaterialChecklist.java new file mode 100644 index 000000000..5c87847a9 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/schematics/cannon/MaterialChecklist.java @@ -0,0 +1,258 @@ +package com.simibubi.create.content.schematics.cannon; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Locale; + +import com.google.common.collect.Sets; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.equipment.clipboard.ClipboardEntry; +import com.simibubi.create.content.equipment.clipboard.ClipboardOverrides; +import com.simibubi.create.content.equipment.clipboard.ClipboardOverrides.ClipboardType; +import com.simibubi.create.content.schematics.requirement.ItemRequirement; +import com.simibubi.create.content.schematics.requirement.ItemRequirement.ItemUseType; +import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.Lang; + +import it.unimi.dsi.fastutil.objects.Object2IntArrayMap; +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import net.minecraft.ChatFormatting; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.StringTag; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.HoverEvent; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.network.chat.Style; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; + +public class MaterialChecklist { + + public static final int MAX_ENTRIES_PER_PAGE = 5; + public static final int MAX_ENTRIES_PER_CLIPBOARD_PAGE = 7; + + public Object2IntMap gathered = new Object2IntArrayMap<>(); + public Object2IntMap required = new Object2IntArrayMap<>(); + public Object2IntMap damageRequired = new Object2IntArrayMap<>(); + public boolean blocksNotLoaded; + + public void warnBlockNotLoaded() { + blocksNotLoaded = true; + } + + public void require(ItemRequirement requirement) { + if (requirement.isEmpty()) + return; + if (requirement.isInvalid()) + return; + + for (ItemRequirement.StackRequirement stack : requirement.getRequiredItems()) { + if (stack.usage == ItemUseType.DAMAGE) + putOrIncrement(damageRequired, stack.stack); + if (stack.usage == ItemUseType.CONSUME) + putOrIncrement(required, stack.stack); + } + } + + private void putOrIncrement(Object2IntMap map, ItemStack stack) { + Item item = stack.getItem(); + if (item == Items.AIR) + return; + if (map.containsKey(item)) + map.put(item, map.getInt(item) + stack.getCount()); + else + map.put(item, stack.getCount()); + } + + public void collect(ItemStack stack) { + Item item = stack.getItem(); + if (required.containsKey(item) || damageRequired.containsKey(item)) + if (gathered.containsKey(item)) + gathered.put(item, gathered.getInt(item) + stack.getCount()); + else + gathered.put(item, stack.getCount()); + } + + public ItemStack createWrittenBook() { + ItemStack book = new ItemStack(Items.WRITTEN_BOOK); + + CompoundTag tag = book.getOrCreateTag(); + ListTag pages = new ListTag(); + + int itemsWritten = 0; + MutableComponent textComponent; + + if (blocksNotLoaded) { + textComponent = Components.literal("\n" + ChatFormatting.RED); + textComponent = textComponent.append(Lang.translateDirect("materialChecklist.blocksNotLoaded")); + pages.add(StringTag.valueOf(Component.Serializer.toJson(textComponent))); + } + + List keys = new ArrayList<>(Sets.union(required.keySet(), damageRequired.keySet())); + Collections.sort(keys, (item1, item2) -> { + Locale locale = Locale.ENGLISH; + String name1 = item1.getDescription() + .getString() + .toLowerCase(locale); + String name2 = item2.getDescription() + .getString() + .toLowerCase(locale); + return name1.compareTo(name2); + }); + + textComponent = Components.empty(); + List completed = new ArrayList<>(); + for (Item item : keys) { + int amount = getRequiredAmount(item); + if (gathered.containsKey(item)) + amount -= gathered.getInt(item); + + if (amount <= 0) { + completed.add(item); + continue; + } + + if (itemsWritten == MAX_ENTRIES_PER_PAGE) { + itemsWritten = 0; + textComponent.append(Components.literal("\n >>>") + .withStyle(ChatFormatting.BLUE)); + pages.add(StringTag.valueOf(Component.Serializer.toJson(textComponent))); + textComponent = Components.empty(); + } + + itemsWritten++; + textComponent.append(entry(new ItemStack(item), amount, true, true)); + } + + for (Item item : completed) { + if (itemsWritten == MAX_ENTRIES_PER_PAGE) { + itemsWritten = 0; + textComponent.append(Components.literal("\n >>>") + .withStyle(ChatFormatting.DARK_GREEN)); + pages.add(StringTag.valueOf(Component.Serializer.toJson(textComponent))); + textComponent = Components.empty(); + } + + itemsWritten++; + textComponent.append(entry(new ItemStack(item), getRequiredAmount(item), false, true)); + } + + pages.add(StringTag.valueOf(Component.Serializer.toJson(textComponent))); + + tag.put("pages", pages); + tag.putBoolean("readonly", true); + tag.putString("author", "Schematicannon"); + tag.putString("title", ChatFormatting.BLUE + "Material Checklist"); + textComponent = Lang.translateDirect("materialChecklist") + .setStyle(Style.EMPTY.withColor(ChatFormatting.BLUE) + .withItalic(Boolean.FALSE)); + book.getOrCreateTagElement("display") + .putString("Name", Component.Serializer.toJson(textComponent)); + book.setTag(tag); + + return book; + } + + public ItemStack createWrittenClipboard() { + ItemStack clipboard = AllBlocks.CLIPBOARD.asStack(); + CompoundTag tag = clipboard.getOrCreateTag(); + int itemsWritten = 0; + + List> pages = new ArrayList<>(); + List currentPage = new ArrayList<>(); + + if (blocksNotLoaded) { + currentPage.add(new ClipboardEntry(false, Lang.translateDirect("materialChecklist.blocksNotLoaded") + .withStyle(ChatFormatting.RED))); + } + + List keys = new ArrayList<>(Sets.union(required.keySet(), damageRequired.keySet())); + Collections.sort(keys, (item1, item2) -> { + Locale locale = Locale.ENGLISH; + String name1 = item1.getDescription() + .getString() + .toLowerCase(locale); + String name2 = item2.getDescription() + .getString() + .toLowerCase(locale); + return name1.compareTo(name2); + }); + + List completed = new ArrayList<>(); + for (Item item : keys) { + int amount = getRequiredAmount(item); + if (gathered.containsKey(item)) + amount -= gathered.getInt(item); + + if (amount <= 0) { + completed.add(item); + continue; + } + + if (itemsWritten == MAX_ENTRIES_PER_CLIPBOARD_PAGE) { + itemsWritten = 0; + currentPage.add(new ClipboardEntry(false, Components.literal(">>>") + .withStyle(ChatFormatting.DARK_GRAY))); + pages.add(currentPage); + currentPage = new ArrayList<>(); + } + + itemsWritten++; + currentPage.add(new ClipboardEntry(false, entry(new ItemStack(item), amount, true, false)) + .displayItem(new ItemStack(item))); + } + + for (Item item : completed) { + if (itemsWritten == MAX_ENTRIES_PER_CLIPBOARD_PAGE) { + itemsWritten = 0; + currentPage.add(new ClipboardEntry(true, Components.literal(">>>") + .withStyle(ChatFormatting.DARK_GREEN))); + pages.add(currentPage); + currentPage = new ArrayList<>(); + } + + itemsWritten++; + currentPage.add(new ClipboardEntry(true, entry(new ItemStack(item), getRequiredAmount(item), false, false)) + .displayItem(new ItemStack(item))); + } + + pages.add(currentPage); + ClipboardEntry.saveAll(pages, clipboard); + ClipboardOverrides.switchTo(ClipboardType.WRITTEN, clipboard); + clipboard.getOrCreateTagElement("display") + .putString("Name", Component.Serializer.toJson(Lang.translateDirect("materialChecklist") + .setStyle(Style.EMPTY.withItalic(Boolean.FALSE)))); + tag.putBoolean("Readonly", true); + clipboard.setTag(tag); + return clipboard; + } + + public int getRequiredAmount(Item item) { + int amount = required.getOrDefault(item, 0); + if (damageRequired.containsKey(item)) + amount += Math.ceil(damageRequired.getInt(item) / (float) new ItemStack(item).getMaxDamage()); + return amount; + } + + private MutableComponent entry(ItemStack item, int amount, boolean unfinished, boolean forBook) { + int stacks = amount / 64; + int remainder = amount % 64; + MutableComponent tc = Components.empty(); + tc.append(Components.translatable(item.getDescriptionId()) + .setStyle(Style.EMPTY + .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_ITEM, new HoverEvent.ItemStackInfo(item))))); + + if (!unfinished && forBook) + tc.append(" \u2714"); + if (!unfinished || forBook) + tc.withStyle(unfinished ? ChatFormatting.BLUE : ChatFormatting.DARK_GREEN); + return tc.append(Components.literal("\n" + " x" + amount) + .withStyle(ChatFormatting.BLACK)) + .append(Components.literal(" | " + stacks + "\u25A4 +" + remainder + (forBook ? "\n" : "")) + .withStyle(ChatFormatting.GRAY)); + } + +} diff --git a/src/main/java/com/simibubi/create/content/schematics/cannon/SchematicannonBlock.java b/src/main/java/com/simibubi/create/content/schematics/cannon/SchematicannonBlock.java new file mode 100644 index 000000000..bb982113c --- /dev/null +++ b/src/main/java/com/simibubi/create/content/schematics/cannon/SchematicannonBlock.java @@ -0,0 +1,83 @@ +package com.simibubi.create.content.schematics.cannon; + +import javax.annotation.Nullable; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllShapes; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.item.ItemHelper; + +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.util.Mth; +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.entity.BlockEntityType; +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.VoxelShape; +import net.minecraftforge.network.NetworkHooks; + +public class SchematicannonBlock extends Block implements IBE { + + public SchematicannonBlock(Properties properties) { + super(properties); + } + + @Override + public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) { + return AllShapes.SCHEMATICANNON_SHAPE; + } + + @Override + public void setPlacedBy(Level level, BlockPos pos, BlockState state, @Nullable LivingEntity entity, ItemStack stack) { + if (entity != null) { + withBlockEntityDo(level, pos, be -> { + be.defaultYaw = (-Mth.floor((entity.getYRot() + (entity.isShiftKeyDown() ? 180.0F : 0.0F)) * 16.0F / 360.0F + 0.5F) & 15) * 360.0F / 16.0F; + }); + } + } + + @Override + public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, + BlockHitResult hit) { + if (worldIn.isClientSide) + return InteractionResult.SUCCESS; + withBlockEntityDo(worldIn, pos, + be -> NetworkHooks.openScreen((ServerPlayer) player, be, be::sendToMenu)); + return InteractionResult.SUCCESS; + } + + @Override + public void neighborChanged(BlockState state, Level worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, + boolean isMoving) { + withBlockEntityDo(worldIn, pos, be -> be.neighbourCheckCooldown = 0); + } + + @Override + public void onRemove(BlockState state, Level worldIn, BlockPos pos, BlockState newState, boolean isMoving) { + if (!state.hasBlockEntity() || state.getBlock() == newState.getBlock()) + return; + + withBlockEntityDo(worldIn, pos, be -> ItemHelper.dropContents(worldIn, pos, be.inventory)); + worldIn.removeBlockEntity(pos); + } + + @Override + public Class getBlockEntityClass() { + return SchematicannonBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.SCHEMATICANNON.get(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/schematics/cannon/SchematicannonBlockEntity.java b/src/main/java/com/simibubi/create/content/schematics/cannon/SchematicannonBlockEntity.java new file mode 100644 index 000000000..7db7d29c2 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/schematics/cannon/SchematicannonBlockEntity.java @@ -0,0 +1,864 @@ +package com.simibubi.create.content.schematics.cannon; + +import java.util.Arrays; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; + +import javax.annotation.Nullable; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllItems; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.content.kinetics.belt.BeltBlock; +import com.simibubi.create.content.kinetics.belt.BeltBlockEntity; +import com.simibubi.create.content.kinetics.belt.BeltBlockEntity.CasingType; +import com.simibubi.create.content.kinetics.belt.BeltPart; +import com.simibubi.create.content.kinetics.belt.BeltSlope; +import com.simibubi.create.content.kinetics.simpleRelays.AbstractSimpleShaftBlock; +import com.simibubi.create.content.schematics.SchematicPrinter; +import com.simibubi.create.content.schematics.requirement.ItemRequirement; +import com.simibubi.create.content.schematics.requirement.ItemRequirement.ItemUseType; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.item.ItemHelper; +import com.simibubi.create.foundation.item.ItemHelper.ExtractionCountMode; +import com.simibubi.create.foundation.utility.BlockHelper; +import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.infrastructure.config.AllConfigs; +import com.simibubi.create.infrastructure.config.CSchematics; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.chat.Component; +import net.minecraft.world.MenuProvider; +import net.minecraft.world.entity.Entity; +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.BlockItem; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.piston.PistonHeadBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BedPart; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; +import net.minecraft.world.phys.AABB; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemHandlerHelper; +import net.minecraftforge.items.wrapper.EmptyHandler; + +public class SchematicannonBlockEntity extends SmartBlockEntity implements MenuProvider { + + public static final int NEIGHBOUR_CHECKING = 100; + public static final int MAX_ANCHOR_DISTANCE = 256; + + // Inventory + public SchematicannonInventory inventory; + + public boolean sendUpdate; + // Sync + public boolean dontUpdateChecklist; + public int neighbourCheckCooldown; + + // Printer + public SchematicPrinter printer; + public ItemStack missingItem; + public boolean positionNotLoaded; + public boolean hasCreativeCrate; + private int printerCooldown; + private int skipsLeft; + private boolean blockSkipped; + + public BlockPos previousTarget; + public LinkedHashSet> attachedInventories; + public List flyingBlocks; + public MaterialChecklist checklist; + + // Gui information + public float fuelLevel; + public float bookPrintingProgress; + public float schematicProgress; + public String statusMsg; + public State state; + public int blocksPlaced; + public int blocksToPlace; + + // Settings + public int replaceMode; + public boolean skipMissing; + public boolean replaceBlockEntities; + + // Render + public boolean firstRenderTick; + public float defaultYaw; + + public SchematicannonBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + setLazyTickRate(30); + attachedInventories = new LinkedHashSet<>(); + flyingBlocks = new LinkedList<>(); + inventory = new SchematicannonInventory(this); + statusMsg = "idle"; + this.state = State.STOPPED; + replaceMode = 2; + checklist = new MaterialChecklist(); + printer = new SchematicPrinter(); + } + + public void findInventories() { + hasCreativeCrate = false; + attachedInventories.clear(); + for (Direction facing : Iterate.directions) { + + if (!level.isLoaded(worldPosition.relative(facing))) + continue; + + if (AllBlocks.CREATIVE_CRATE.has(level.getBlockState(worldPosition.relative(facing)))) + hasCreativeCrate = true; + + BlockEntity blockEntity = level.getBlockEntity(worldPosition.relative(facing)); + if (blockEntity != null) { + LazyOptional capability = + blockEntity.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, facing.getOpposite()); + if (capability.isPresent()) { + attachedInventories.add(capability); + } + } + } + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + if (!clientPacket) { + inventory.deserializeNBT(compound.getCompound("Inventory")); + } + + // Gui information + statusMsg = compound.getString("Status"); + schematicProgress = compound.getFloat("Progress"); + bookPrintingProgress = compound.getFloat("PaperProgress"); + fuelLevel = compound.getFloat("Fuel"); + String stateString = compound.getString("State"); + state = stateString.isEmpty() ? State.STOPPED : State.valueOf(compound.getString("State")); + blocksPlaced = compound.getInt("AmountPlaced"); + blocksToPlace = compound.getInt("AmountToPlace"); + + missingItem = null; + if (compound.contains("MissingItem")) + missingItem = ItemStack.of(compound.getCompound("MissingItem")); + + // Settings + CompoundTag options = compound.getCompound("Options"); + replaceMode = options.getInt("ReplaceMode"); + skipMissing = options.getBoolean("SkipMissing"); + replaceBlockEntities = options.getBoolean("ReplaceTileEntities"); + + // Printer & Flying Blocks + if (compound.contains("Printer")) + printer.fromTag(compound.getCompound("Printer"), clientPacket); + if (compound.contains("FlyingBlocks")) + readFlyingBlocks(compound); + + defaultYaw = compound.getFloat("DefaultYaw"); + + super.read(compound, clientPacket); + } + + protected void readFlyingBlocks(CompoundTag compound) { + ListTag tagBlocks = compound.getList("FlyingBlocks", 10); + if (tagBlocks.isEmpty()) + flyingBlocks.clear(); + + boolean pastDead = false; + + for (int i = 0; i < tagBlocks.size(); i++) { + CompoundTag c = tagBlocks.getCompound(i); + LaunchedItem launched = LaunchedItem.fromNBT(c); + BlockPos readBlockPos = launched.target; + + // Always write to Server block entity + if (level == null || !level.isClientSide) { + flyingBlocks.add(launched); + continue; + } + + // Delete all Client side blocks that are now missing on the server + while (!pastDead && !flyingBlocks.isEmpty() && !flyingBlocks.get(0).target.equals(readBlockPos)) { + flyingBlocks.remove(0); + } + + pastDead = true; + + // Add new server side blocks + if (i >= flyingBlocks.size()) { + flyingBlocks.add(launched); + continue; + } + + // Don't do anything with existing + } + } + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + if (!clientPacket) { + compound.put("Inventory", inventory.serializeNBT()); + if (state == State.RUNNING) { + compound.putBoolean("Running", true); + } + } + + // Gui information + compound.putFloat("Progress", schematicProgress); + compound.putFloat("PaperProgress", bookPrintingProgress); + compound.putFloat("Fuel", fuelLevel); + compound.putString("Status", statusMsg); + compound.putString("State", state.name()); + compound.putInt("AmountPlaced", blocksPlaced); + compound.putInt("AmountToPlace", blocksToPlace); + + if (missingItem != null) + compound.put("MissingItem", missingItem.serializeNBT()); + + // Settings + CompoundTag options = new CompoundTag(); + options.putInt("ReplaceMode", replaceMode); + options.putBoolean("SkipMissing", skipMissing); + options.putBoolean("ReplaceTileEntities", replaceBlockEntities); + compound.put("Options", options); + + // Printer & Flying Blocks + CompoundTag printerData = new CompoundTag(); + printer.write(printerData); + compound.put("Printer", printerData); + + ListTag tagFlyingBlocks = new ListTag(); + for (LaunchedItem b : flyingBlocks) + tagFlyingBlocks.add(b.serializeNBT()); + compound.put("FlyingBlocks", tagFlyingBlocks); + + compound.putFloat("DefaultYaw", defaultYaw); + + super.write(compound, clientPacket); + } + + @Override + public void tick() { + super.tick(); + + if (state != State.STOPPED && neighbourCheckCooldown-- <= 0) { + neighbourCheckCooldown = NEIGHBOUR_CHECKING; + findInventories(); + } + + firstRenderTick = true; + previousTarget = printer.getCurrentTarget(); + tickFlyingBlocks(); + + if (level.isClientSide) + return; + + // Update Fuel and Paper + tickPaperPrinter(); + refillFuelIfPossible(); + + // Update Printer + skipsLeft = 1000; + blockSkipped = true; + + while (blockSkipped && skipsLeft-- > 0) + tickPrinter(); + + schematicProgress = 0; + if (blocksToPlace > 0) + schematicProgress = (float) blocksPlaced / blocksToPlace; + + // Update Client block entity + if (sendUpdate) { + sendUpdate = false; + level.sendBlockUpdated(worldPosition, getBlockState(), getBlockState(), 6); + } + } + + public CSchematics config() { + return AllConfigs.server().schematics; + } + + protected void tickPrinter() { + ItemStack blueprint = inventory.getStackInSlot(0); + blockSkipped = false; + + if (blueprint.isEmpty() && !statusMsg.equals("idle") && inventory.getStackInSlot(1) + .isEmpty()) { + state = State.STOPPED; + statusMsg = "idle"; + sendUpdate = true; + return; + } + + // Skip if not Active + if (state == State.STOPPED) { + if (printer.isLoaded()) + resetPrinter(); + return; + } + + if (state == State.PAUSED && !positionNotLoaded && missingItem == null && fuelLevel > getFuelUsageRate()) + return; + + // Initialize Printer + if (!printer.isLoaded()) { + initializePrinter(blueprint); + return; + } + + // Cooldown from last shot + if (printerCooldown > 0) { + printerCooldown--; + return; + } + + // Check Fuel + if (fuelLevel <= 0 && !hasCreativeCrate) { + fuelLevel = 0; + state = State.PAUSED; + statusMsg = "noGunpowder"; + sendUpdate = true; + return; + } + + if (hasCreativeCrate) { + if (missingItem != null) { + missingItem = null; + state = State.RUNNING; + } + } + + // Update Target + if (missingItem == null && !positionNotLoaded) { + if (!printer.advanceCurrentPos()) { + finishedPrinting(); + return; + } + sendUpdate = true; + } + + // Check block + if (!getLevel().isLoaded(printer.getCurrentTarget())) { + positionNotLoaded = true; + statusMsg = "targetNotLoaded"; + state = State.PAUSED; + return; + } else { + if (positionNotLoaded) { + positionNotLoaded = false; + state = State.RUNNING; + } + } + + // Get item requirement + ItemRequirement requirement = printer.getCurrentRequirement(); + if (requirement.isInvalid() || !printer.shouldPlaceCurrent(level, this::shouldPlace)) { + sendUpdate = !statusMsg.equals("searching"); + statusMsg = "searching"; + blockSkipped = true; + return; + } + + // Find item + List requiredItems = requirement.getRequiredItems(); + if (!requirement.isEmpty()) { + for (ItemRequirement.StackRequirement required : requiredItems) { + if (!grabItemsFromAttachedInventories(required, true)) { + if (skipMissing) { + statusMsg = "skipping"; + blockSkipped = true; + if (missingItem != null) { + missingItem = null; + state = State.RUNNING; + } + return; + } + + missingItem = required.stack; + state = State.PAUSED; + statusMsg = "missingBlock"; + return; + } + } + + for (ItemRequirement.StackRequirement required : requiredItems) + grabItemsFromAttachedInventories(required, false); + } + + // Success + state = State.RUNNING; + ItemStack icon = requirement.isEmpty() || requiredItems.isEmpty() ? ItemStack.EMPTY : requiredItems.get(0).stack; + printer.handleCurrentTarget((target, blockState, blockEntity) -> { + // Launch block + statusMsg = blockState.getBlock() != Blocks.AIR ? "placing" : "clearing"; + launchBlockOrBelt(target, icon, blockState, blockEntity); + }, (target, entity) -> { + // Launch entity + statusMsg = "placing"; + launchEntity(target, icon, entity); + }); + + printerCooldown = config().schematicannonDelay.get(); + fuelLevel -= getFuelUsageRate(); + sendUpdate = true; + missingItem = null; + } + + public double getFuelUsageRate() { + return hasCreativeCrate ? 0 : config().schematicannonFuelUsage.get() / 100f; + } + + protected void initializePrinter(ItemStack blueprint) { + if (!blueprint.hasTag()) { + state = State.STOPPED; + statusMsg = "schematicInvalid"; + sendUpdate = true; + return; + } + + if (!blueprint.getTag() + .getBoolean("Deployed")) { + state = State.STOPPED; + statusMsg = "schematicNotPlaced"; + sendUpdate = true; + return; + } + + // Load blocks into reader + printer.loadSchematic(blueprint, level, true); + + if (printer.isErrored()) { + state = State.STOPPED; + statusMsg = "schematicErrored"; + inventory.setStackInSlot(0, ItemStack.EMPTY); + inventory.setStackInSlot(1, new ItemStack(AllItems.EMPTY_SCHEMATIC.get())); + printer.resetSchematic(); + sendUpdate = true; + return; + } + + if (printer.isWorldEmpty()) { + state = State.STOPPED; + statusMsg = "schematicExpired"; + inventory.setStackInSlot(0, ItemStack.EMPTY); + inventory.setStackInSlot(1, new ItemStack(AllItems.EMPTY_SCHEMATIC.get())); + printer.resetSchematic(); + sendUpdate = true; + return; + } + + if (!printer.getAnchor() + .closerThan(getBlockPos(), MAX_ANCHOR_DISTANCE)) { + state = State.STOPPED; + statusMsg = "targetOutsideRange"; + printer.resetSchematic(); + sendUpdate = true; + return; + } + + state = State.PAUSED; + statusMsg = "ready"; + updateChecklist(); + sendUpdate = true; + blocksToPlace += blocksPlaced; + } + + protected ItemStack getItemForBlock(BlockState blockState) { + Item item = BlockItem.BY_BLOCK.getOrDefault(blockState.getBlock(), Items.AIR); + return item == Items.AIR ? ItemStack.EMPTY : new ItemStack(item); + } + + protected boolean grabItemsFromAttachedInventories(ItemRequirement.StackRequirement required, boolean simulate) { + if (hasCreativeCrate) + return true; + + attachedInventories.removeIf(cap -> !cap.isPresent()); + + ItemUseType usage = required.usage; + + // Find and apply damage + if (usage == ItemUseType.DAMAGE) { + for (LazyOptional cap : attachedInventories) { + IItemHandler itemHandler = cap.orElse(EmptyHandler.INSTANCE); + for (int slot = 0; slot < itemHandler.getSlots(); slot++) { + ItemStack extractItem = itemHandler.extractItem(slot, 1, true); + if (!required.matches(extractItem)) + continue; + if (!extractItem.isDamageableItem()) + continue; + + if (!simulate) { + ItemStack stack = itemHandler.extractItem(slot, 1, false); + stack.setDamageValue(stack.getDamageValue() + 1); + if (stack.getDamageValue() <= stack.getMaxDamage()) { + if (itemHandler.getStackInSlot(slot) + .isEmpty()) + itemHandler.insertItem(slot, stack, false); + else + ItemHandlerHelper.insertItem(itemHandler, stack, false); + } + } + + return true; + } + } + + return false; + } + + // Find and remove + boolean success = false; + int amountFound = 0; + for (LazyOptional cap : attachedInventories) { + IItemHandler itemHandler = cap.orElse(EmptyHandler.INSTANCE); + amountFound += ItemHelper + .extract(itemHandler, required::matches, ExtractionCountMode.UPTO, + required.stack.getCount(), true) + .getCount(); + + if (amountFound < required.stack.getCount()) + continue; + + success = true; + break; + } + + if (!simulate && success) { + amountFound = 0; + for (LazyOptional cap : attachedInventories) { + IItemHandler itemHandler = cap.orElse(EmptyHandler.INSTANCE); + amountFound += ItemHelper + .extract(itemHandler, required::matches, ExtractionCountMode.UPTO, + required.stack.getCount(), false) + .getCount(); + if (amountFound < required.stack.getCount()) + continue; + break; + } + } + + return success; + } + + public void finishedPrinting() { + inventory.setStackInSlot(0, ItemStack.EMPTY); + inventory.setStackInSlot(1, new ItemStack(AllItems.EMPTY_SCHEMATIC.get(), inventory.getStackInSlot(1) + .getCount() + 1)); + state = State.STOPPED; + statusMsg = "finished"; + resetPrinter(); + AllSoundEvents.SCHEMATICANNON_FINISH.playOnServer(level, worldPosition); + sendUpdate = true; + } + + protected void resetPrinter() { + printer.resetSchematic(); + missingItem = null; + sendUpdate = true; + schematicProgress = 0; + blocksPlaced = 0; + blocksToPlace = 0; + } + + protected boolean shouldPlace(BlockPos pos, BlockState state, BlockEntity be, BlockState toReplace, + BlockState toReplaceOther, boolean isNormalCube) { + if (pos.closerThan(getBlockPos(), 2f)) + return false; + if (!replaceBlockEntities + && (toReplace.hasBlockEntity() || (toReplaceOther != null && toReplaceOther.hasBlockEntity()))) + return false; + + if (shouldIgnoreBlockState(state, be)) + return false; + + boolean placingAir = state.isAir(); + + if (replaceMode == 3) + return true; + if (replaceMode == 2 && !placingAir) + return true; + if (replaceMode == 1 && (isNormalCube || (!toReplace.isRedstoneConductor(level, pos) + && (toReplaceOther == null || !toReplaceOther.isRedstoneConductor(level, pos)))) && !placingAir) + return true; + if (replaceMode == 0 && !toReplace.isRedstoneConductor(level, pos) + && (toReplaceOther == null || !toReplaceOther.isRedstoneConductor(level, pos)) && !placingAir) + return true; + + return false; + } + + protected boolean shouldIgnoreBlockState(BlockState state, BlockEntity be) { + // Block doesn't have a mapping (Water, lava, etc) + if (state.getBlock() == Blocks.STRUCTURE_VOID) + return true; + + ItemRequirement requirement = ItemRequirement.of(state, be); + if (requirement.isEmpty()) + return false; + if (requirement.isInvalid()) + return false; + + // Block doesn't need to be placed twice (Doors, beds, double plants) + if (state.hasProperty(BlockStateProperties.DOUBLE_BLOCK_HALF) + && state.getValue(BlockStateProperties.DOUBLE_BLOCK_HALF) == DoubleBlockHalf.UPPER) + return true; + if (state.hasProperty(BlockStateProperties.BED_PART) + && state.getValue(BlockStateProperties.BED_PART) == BedPart.HEAD) + return true; + if (state.getBlock() instanceof PistonHeadBlock) + return true; + if (AllBlocks.BELT.has(state)) + return state.getValue(BeltBlock.PART) == BeltPart.MIDDLE; + + return false; + } + + protected void tickFlyingBlocks() { + List toRemove = new LinkedList<>(); + for (LaunchedItem b : flyingBlocks) + if (b.update(level)) + toRemove.add(b); + flyingBlocks.removeAll(toRemove); + } + + protected void refillFuelIfPossible() { + if (hasCreativeCrate) + return; + if (1 - fuelLevel + 1 / 128f < getFuelAddedByGunPowder()) + return; + if (inventory.getStackInSlot(4) + .isEmpty()) + return; + + inventory.getStackInSlot(4) + .shrink(1); + fuelLevel += getFuelAddedByGunPowder(); + if (statusMsg.equals("noGunpowder")) { + if (blocksPlaced > 0) + state = State.RUNNING; + statusMsg = "ready"; + } + sendUpdate = true; + } + + public double getFuelAddedByGunPowder() { + return config().schematicannonGunpowderWorth.get() / 100f; + } + + protected void tickPaperPrinter() { + int BookInput = 2; + int BookOutput = 3; + + ItemStack blueprint = inventory.getStackInSlot(0); + ItemStack paper = inventory.extractItem(BookInput, 1, true); + boolean outputFull = inventory.getStackInSlot(BookOutput) + .getCount() == inventory.getSlotLimit(BookOutput); + + if (printer.isErrored()) + return; + + if (!printer.isLoaded()) { + if (!blueprint.isEmpty()) + initializePrinter(blueprint); + return; + } + + if (paper.isEmpty() || outputFull) { + if (bookPrintingProgress != 0) + sendUpdate = true; + bookPrintingProgress = 0; + dontUpdateChecklist = false; + return; + } + + if (bookPrintingProgress >= 1) { + bookPrintingProgress = 0; + + if (!dontUpdateChecklist) + updateChecklist(); + + dontUpdateChecklist = true; + ItemStack extractItem = inventory.extractItem(BookInput, 1, false); + ItemStack stack = AllBlocks.CLIPBOARD.isIn(extractItem) ? checklist.createWrittenClipboard() + : checklist.createWrittenBook(); + stack.setCount(inventory.getStackInSlot(BookOutput) + .getCount() + 1); + inventory.setStackInSlot(BookOutput, stack); + sendUpdate = true; + return; + } + + bookPrintingProgress += 0.05f; + sendUpdate = true; + } + + public static BlockState stripBeltIfNotLast(BlockState blockState) { + BeltPart part = blockState.getValue(BeltBlock.PART); + if (part == BeltPart.MIDDLE) + return Blocks.AIR.defaultBlockState(); + + // is highest belt? + boolean isLastSegment = false; + Direction facing = blockState.getValue(BeltBlock.HORIZONTAL_FACING); + BeltSlope slope = blockState.getValue(BeltBlock.SLOPE); + boolean positive = facing.getAxisDirection() == AxisDirection.POSITIVE; + boolean start = part == BeltPart.START; + boolean end = part == BeltPart.END; + + switch (slope) { + case DOWNWARD: + isLastSegment = start; + break; + case UPWARD: + isLastSegment = end; + break; + default: + isLastSegment = positive && end || !positive && start; + } + if (isLastSegment) + return blockState; + + return AllBlocks.SHAFT.getDefaultState() + .setValue(AbstractSimpleShaftBlock.AXIS, slope == BeltSlope.SIDEWAYS ? Axis.Y + : facing.getClockWise() + .getAxis()); + } + + protected void launchBlockOrBelt(BlockPos target, ItemStack icon, BlockState blockState, BlockEntity blockEntity) { + if (AllBlocks.BELT.has(blockState)) { + blockState = stripBeltIfNotLast(blockState); + if (blockEntity instanceof BeltBlockEntity bbe && AllBlocks.BELT.has(blockState)) { + CasingType[] casings = new CasingType[bbe.beltLength]; + Arrays.fill(casings, CasingType.NONE); + BlockPos currentPos = target; + for (int i = 0; i < bbe.beltLength; i++) { + BlockState currentState = bbe.getLevel() + .getBlockState(currentPos); + if (!(currentState.getBlock() instanceof BeltBlock)) + break; + if (!(bbe.getLevel() + .getBlockEntity(currentPos) instanceof BeltBlockEntity beltAtSegment)) + break; + casings[i] = beltAtSegment.casing; + currentPos = BeltBlock.nextSegmentPosition(currentState, currentPos, + blockState.getValue(BeltBlock.PART) != BeltPart.END); + } + launchBelt(target, blockState, bbe.beltLength, casings); + } else if (blockState != Blocks.AIR.defaultBlockState()) + launchBlock(target, icon, blockState, null); + return; + } + + CompoundTag data = BlockHelper.prepareBlockEntityData(blockState, blockEntity); + launchBlock(target, icon, blockState, data); + } + + protected void launchBelt(BlockPos target, BlockState state, int length, CasingType[] casings) { + blocksPlaced++; + ItemStack connector = AllItems.BELT_CONNECTOR.asStack(); + flyingBlocks.add(new LaunchedItem.ForBelt(this.getBlockPos(), target, connector, state, casings)); + playFiringSound(); + } + + protected void launchBlock(BlockPos target, ItemStack stack, BlockState state, @Nullable CompoundTag data) { + if (!state.isAir()) + blocksPlaced++; + flyingBlocks.add(new LaunchedItem.ForBlockState(this.getBlockPos(), target, stack, state, data)); + playFiringSound(); + } + + protected void launchEntity(BlockPos target, ItemStack stack, Entity entity) { + blocksPlaced++; + flyingBlocks.add(new LaunchedItem.ForEntity(this.getBlockPos(), target, stack, entity)); + playFiringSound(); + } + + public void playFiringSound() { + AllSoundEvents.SCHEMATICANNON_LAUNCH_BLOCK.playOnServer(level, worldPosition); + } + + public void sendToMenu(FriendlyByteBuf buffer) { + buffer.writeBlockPos(getBlockPos()); + buffer.writeNbt(getUpdateTag()); + } + + @Override + public AbstractContainerMenu createMenu(int id, Inventory inv, Player player) { + return SchematicannonMenu.create(id, inv, this); + } + + @Override + public Component getDisplayName() { + return Lang.translateDirect("gui.schematicannon.title"); + } + + public void updateChecklist() { + checklist.required.clear(); + checklist.damageRequired.clear(); + checklist.blocksNotLoaded = false; + + if (printer.isLoaded() && !printer.isErrored()) { + blocksToPlace = blocksPlaced; + blocksToPlace += printer.markAllBlockRequirements(checklist, level, this::shouldPlace); + printer.markAllEntityRequirements(checklist); + } + + checklist.gathered.clear(); + findInventories(); + for (LazyOptional cap : attachedInventories) { + if (!cap.isPresent()) + continue; + IItemHandler inventory = cap.orElse(EmptyHandler.INSTANCE); + for (int slot = 0; slot < inventory.getSlots(); slot++) { + ItemStack stackInSlot = inventory.getStackInSlot(slot); + if (inventory.extractItem(slot, 1, true) + .isEmpty()) + continue; + checklist.collect(stackInSlot); + } + } + sendUpdate = true; + } + + @Override + public void addBehaviours(List behaviours) {} + + @Override + public void lazyTick() { + super.lazyTick(); + findInventories(); + } + + @Override + @OnlyIn(Dist.CLIENT) + public AABB getRenderBoundingBox() { + return INFINITE_EXTENT_AABB; + } + + public enum State { + STOPPED, PAUSED, RUNNING; + } + +} diff --git a/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonInstance.java b/src/main/java/com/simibubi/create/content/schematics/cannon/SchematicannonInstance.java similarity index 82% rename from src/main/java/com/simibubi/create/content/schematics/block/SchematicannonInstance.java rename to src/main/java/com/simibubi/create/content/schematics/cannon/SchematicannonInstance.java index fc68495df..d2a447a6b 100644 --- a/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonInstance.java +++ b/src/main/java/com/simibubi/create/content/schematics/cannon/SchematicannonInstance.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.schematics.block; +package com.simibubi.create.content.schematics.cannon; import com.jozufozu.flywheel.api.Material; import com.jozufozu.flywheel.api.MaterialManager; @@ -7,23 +7,23 @@ import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance; import com.jozufozu.flywheel.core.materials.model.ModelData; import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.AllPartialModels; import com.simibubi.create.foundation.utility.AnimationTickHolder; import net.minecraft.core.Direction; -public class SchematicannonInstance extends BlockEntityInstance implements DynamicInstance { +public class SchematicannonInstance extends BlockEntityInstance implements DynamicInstance { private final ModelData connector; private final ModelData pipe; - public SchematicannonInstance(MaterialManager modelManager, SchematicannonTileEntity tile) { - super(modelManager, tile); + public SchematicannonInstance(MaterialManager materialManager, SchematicannonBlockEntity blockEntity) { + super(materialManager, blockEntity); Material mat = getTransformMaterial(); - connector = mat.getModel(AllBlockPartials.SCHEMATICANNON_CONNECTOR, blockState).createInstance(); - pipe = mat.getModel(AllBlockPartials.SCHEMATICANNON_PIPE, blockState).createInstance(); + connector = mat.getModel(AllPartialModels.SCHEMATICANNON_CONNECTOR, blockState).createInstance(); + pipe = mat.getModel(AllPartialModels.SCHEMATICANNON_PIPE, blockState).createInstance(); } @Override diff --git a/src/main/java/com/simibubi/create/content/schematics/cannon/SchematicannonInventory.java b/src/main/java/com/simibubi/create/content/schematics/cannon/SchematicannonInventory.java new file mode 100644 index 000000000..9292e6fb4 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/schematics/cannon/SchematicannonInventory.java @@ -0,0 +1,42 @@ +package com.simibubi.create.content.schematics.cannon; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllItems; + +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraftforge.items.ItemStackHandler; + +public class SchematicannonInventory extends ItemStackHandler { + private final SchematicannonBlockEntity blockEntity; + + public SchematicannonInventory(SchematicannonBlockEntity blockEntity) { + super(5); + this.blockEntity = blockEntity; + } + + @Override + protected void onContentsChanged(int slot) { + super.onContentsChanged(slot); + blockEntity.setChanged(); + } + + @Override + public boolean isItemValid(int slot, ItemStack stack) { + switch (slot) { + case 0: // Blueprint Slot + return AllItems.SCHEMATIC.isIn(stack); + case 1: // Blueprint output + return false; + case 2: // Book input + return AllBlocks.CLIPBOARD.isIn(stack) || stack.sameItem(new ItemStack(Items.BOOK)) + || stack.sameItem(new ItemStack(Items.WRITTEN_BOOK)); + case 3: // Material List output + return false; + case 4: // Gunpowder + return stack.sameItem(new ItemStack(Items.GUNPOWDER)); + default: + return super.isItemValid(slot, stack); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/content/schematics/cannon/SchematicannonMenu.java b/src/main/java/com/simibubi/create/content/schematics/cannon/SchematicannonMenu.java new file mode 100644 index 000000000..a46b07696 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/schematics/cannon/SchematicannonMenu.java @@ -0,0 +1,82 @@ +package com.simibubi.create.content.schematics.cannon; + +import com.simibubi.create.AllMenuTypes; +import com.simibubi.create.foundation.gui.menu.MenuBase; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.entity.player.Inventory; +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 net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraftforge.items.SlotItemHandler; + +public class SchematicannonMenu extends MenuBase { + + public SchematicannonMenu(MenuType type, int id, Inventory inv, FriendlyByteBuf buffer) { + super(type, id, inv, buffer); + } + + public SchematicannonMenu(MenuType type, int id, Inventory inv, SchematicannonBlockEntity be) { + super(type, id, inv, be); + } + + public static SchematicannonMenu create(int id, Inventory inv, SchematicannonBlockEntity be) { + return new SchematicannonMenu(AllMenuTypes.SCHEMATICANNON.get(), id, inv, be); + } + + @Override + protected SchematicannonBlockEntity createOnClient(FriendlyByteBuf extraData) { + ClientLevel world = Minecraft.getInstance().level; + BlockEntity blockEntity = world.getBlockEntity(extraData.readBlockPos()); + if (blockEntity instanceof SchematicannonBlockEntity schematicannon) { + schematicannon.readClient(extraData.readNbt()); + return schematicannon; + } + return null; + } + + @Override + protected void initAndReadInventory(SchematicannonBlockEntity contentHolder) { + } + + @Override + protected void addSlots() { + int x = 0; + int y = 0; + + addSlot(new SlotItemHandler(contentHolder.inventory, 0, x + 15, y + 65)); + addSlot(new SlotItemHandler(contentHolder.inventory, 1, x + 171, y + 65)); + addSlot(new SlotItemHandler(contentHolder.inventory, 2, x + 134, y + 19)); + addSlot(new SlotItemHandler(contentHolder.inventory, 3, x + 174, y + 19)); + addSlot(new SlotItemHandler(contentHolder.inventory, 4, x + 15, y + 19)); + + addPlayerSlots(37, 161); + } + + @Override + protected void saveData(SchematicannonBlockEntity contentHolder) { + } + + @Override + public ItemStack quickMoveStack(Player playerIn, int index) { + Slot clickedSlot = getSlot(index); + if (!clickedSlot.hasItem()) + return ItemStack.EMPTY; + ItemStack stack = clickedSlot.getItem(); + + if (index < 5) { + moveItemStackTo(stack, 5, slots.size(), false); + } else { + if (moveItemStackTo(stack, 0, 1, false) || moveItemStackTo(stack, 2, 3, false) + || moveItemStackTo(stack, 4, 5, false)) + ; + } + + return ItemStack.EMPTY; + } + +} diff --git a/src/main/java/com/simibubi/create/content/schematics/cannon/SchematicannonRenderer.java b/src/main/java/com/simibubi/create/content/schematics/cannon/SchematicannonRenderer.java new file mode 100644 index 000000000..e6b311793 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/schematics/cannon/SchematicannonRenderer.java @@ -0,0 +1,226 @@ +package com.simibubi.create.content.schematics.cannon; + +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.core.model.ModelUtil; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.math.Axis; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.schematics.cannon.LaunchedItem.ForBelt; +import com.simibubi.create.content.schematics.cannon.LaunchedItem.ForBlockState; +import com.simibubi.create.content.schematics.cannon.LaunchedItem.ForEntity; +import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.block.model.ItemTransforms.TransformType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class SchematicannonRenderer extends SafeBlockEntityRenderer { + + public SchematicannonRenderer(BlockEntityRendererProvider.Context context) {} + + @Override + protected void renderSafe(SchematicannonBlockEntity blockEntity, float partialTicks, PoseStack ms, + MultiBufferSource buffer, int light, int overlay) { + + boolean blocksLaunching = !blockEntity.flyingBlocks.isEmpty(); + if (blocksLaunching) + renderLaunchedBlocks(blockEntity, partialTicks, ms, buffer, light, overlay); + + if (Backend.canUseInstancing(blockEntity.getLevel())) + return; + + BlockPos pos = blockEntity.getBlockPos(); + BlockState state = blockEntity.getBlockState(); + + double[] cannonAngles = getCannonAngles(blockEntity, pos, partialTicks); + + double yaw = cannonAngles[0]; + double pitch = cannonAngles[1]; + + double recoil = getRecoil(blockEntity, partialTicks); + + ms.pushPose(); + + VertexConsumer vb = buffer.getBuffer(RenderType.solid()); + + SuperByteBuffer connector = CachedBufferer.partial(AllPartialModels.SCHEMATICANNON_CONNECTOR, state); + connector.translate(.5f, 0, .5f); + connector.rotate(Direction.UP, (float) ((yaw + 90) / 180 * Math.PI)); + connector.translate(-.5f, 0, -.5f); + connector.light(light) + .renderInto(ms, vb); + + SuperByteBuffer pipe = CachedBufferer.partial(AllPartialModels.SCHEMATICANNON_PIPE, state); + pipe.translate(.5f, 15 / 16f, .5f); + pipe.rotate(Direction.UP, (float) ((yaw + 90) / 180 * Math.PI)); + pipe.rotate(Direction.SOUTH, (float) (pitch / 180 * Math.PI)); + pipe.translate(-.5f, -15 / 16f, -.5f); + pipe.translate(0, -recoil / 100, 0); + pipe.light(light) + .renderInto(ms, vb); + + ms.popPose(); + } + + public static double[] getCannonAngles(SchematicannonBlockEntity blockEntity, BlockPos pos, float partialTicks) { + double yaw; + double pitch; + + BlockPos target = blockEntity.printer.getCurrentTarget(); + if (target != null) { + + // Calculate Angle of Cannon + Vec3 diff = Vec3.atLowerCornerOf(target.subtract(pos)); + if (blockEntity.previousTarget != null) { + diff = (Vec3.atLowerCornerOf(blockEntity.previousTarget) + .add(Vec3.atLowerCornerOf(target.subtract(blockEntity.previousTarget)) + .scale(partialTicks))).subtract(Vec3.atLowerCornerOf(pos)); + } + + double diffX = diff.x(); + double diffZ = diff.z(); + yaw = Mth.atan2(diffX, diffZ); + yaw = yaw / Math.PI * 180; + + float distance = Mth.sqrt((float) (diffX * diffX + diffZ * diffZ)); + double yOffset = 0 + distance * 2f; + pitch = Mth.atan2(distance, diff.y() * 3 + yOffset); + pitch = pitch / Math.PI * 180 + 10; + + } else { + yaw = blockEntity.defaultYaw; + pitch = 40; + } + + return new double[] { yaw, pitch }; + } + + public static double getRecoil(SchematicannonBlockEntity blockEntity, float partialTicks) { + double recoil = 0; + + for (LaunchedItem launched : blockEntity.flyingBlocks) { + + if (launched.ticksRemaining == 0) + continue; + + // Apply Recoil if block was just launched + if ((launched.ticksRemaining + 1 - partialTicks) > launched.totalTicks - 10) + recoil = Math.max(recoil, (launched.ticksRemaining + 1 - partialTicks) - launched.totalTicks + 10); + } + + return recoil; + } + + private static void renderLaunchedBlocks(SchematicannonBlockEntity blockEntity, float partialTicks, PoseStack ms, + MultiBufferSource buffer, int light, int overlay) { + for (LaunchedItem launched : blockEntity.flyingBlocks) { + + if (launched.ticksRemaining == 0) + continue; + + // Calculate position of flying block + Vec3 start = Vec3.atCenterOf(blockEntity.getBlockPos() + .above()); + Vec3 target = Vec3.atCenterOf(launched.target); + Vec3 distance = target.subtract(start); + + double yDifference = target.y - start.y; + double throwHeight = Math.sqrt(distance.lengthSqr()) * .6f + yDifference; + Vec3 cannonOffset = distance.add(0, throwHeight, 0) + .normalize() + .scale(2); + start = start.add(cannonOffset); + yDifference = target.y - start.y; + + float progress = + ((float) launched.totalTicks - (launched.ticksRemaining + 1 - partialTicks)) / launched.totalTicks; + Vec3 blockLocationXZ = target.subtract(start) + .scale(progress) + .multiply(1, 0, 1); + + // Height is determined through a bezier curve + float t = progress; + double yOffset = 2 * (1 - t) * t * throwHeight + t * t * yDifference; + Vec3 blockLocation = blockLocationXZ.add(0.5, yOffset + 1.5, 0.5) + .add(cannonOffset); + + // Offset to position + ms.pushPose(); + ms.translate(blockLocation.x, blockLocation.y, blockLocation.z); + + ms.translate(.125f, .125f, .125f); + ms.mulPose(Axis.YP.rotationDegrees(360 * t)); + ms.mulPose(Axis.XP.rotationDegrees(360 * t)); + ms.translate(-.125f, -.125f, -.125f); + + if (launched instanceof ForBlockState) { + // Render the Block + BlockState state; + if (launched instanceof ForBelt) { + // Render a shaft instead of the belt + state = AllBlocks.SHAFT.getDefaultState(); + } else { + state = ((ForBlockState) launched).state; + } + float scale = .3f; + ms.scale(scale, scale, scale); + Minecraft.getInstance() + .getBlockRenderer() + .renderSingleBlock(state, ms, buffer, light, overlay, + ModelUtil.VIRTUAL_DATA, null); + } else if (launched instanceof ForEntity) { + // Render the item + float scale = 1.2f; + ms.scale(scale, scale, scale); + Minecraft.getInstance() + .getItemRenderer() + .renderStatic(launched.stack, TransformType.GROUND, light, overlay, ms, buffer, 0); + } + + ms.popPose(); + + // Render particles for launch + if (launched.ticksRemaining == launched.totalTicks && blockEntity.firstRenderTick) { + start = start.subtract(.5, .5, .5); + blockEntity.firstRenderTick = false; + for (int i = 0; i < 10; i++) { + RandomSource r = blockEntity.getLevel() + .getRandom(); + double sX = cannonOffset.x * .01f; + double sY = (cannonOffset.y + 1) * .01f; + double sZ = cannonOffset.z * .01f; + double rX = r.nextFloat() - sX * 40; + double rY = r.nextFloat() - sY * 40; + double rZ = r.nextFloat() - sZ * 40; + blockEntity.getLevel() + .addParticle(ParticleTypes.CLOUD, start.x + rX, start.y + rY, start.z + rZ, sX, sY, sZ); + } + } + + } + } + + @Override + public boolean shouldRenderOffScreen(SchematicannonBlockEntity blockEntity) { + return true; + } + + @Override + public int getViewDistance() { + return 128; + } + +} diff --git a/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonScreen.java b/src/main/java/com/simibubi/create/content/schematics/cannon/SchematicannonScreen.java similarity index 83% rename from src/main/java/com/simibubi/create/content/schematics/block/SchematicannonScreen.java rename to src/main/java/com/simibubi/create/content/schematics/cannon/SchematicannonScreen.java index 1bc16501c..c0cc7369f 100644 --- a/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonScreen.java +++ b/src/main/java/com/simibubi/create/content/schematics/cannon/SchematicannonScreen.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.schematics.block; +package com.simibubi.create.content.schematics.cannon; import static net.minecraft.ChatFormatting.BLUE; import static net.minecraft.ChatFormatting.DARK_PURPLE; @@ -12,18 +12,17 @@ import java.util.Vector; import com.google.common.collect.ImmutableList; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.schematics.packet.ConfigureSchematicannonPacket; -import com.simibubi.create.content.schematics.packet.ConfigureSchematicannonPacket.Option; +import com.simibubi.create.AllPackets; +import com.simibubi.create.content.schematics.cannon.ConfigureSchematicannonPacket.Option; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.gui.container.AbstractSimiContainerScreen; import com.simibubi.create.foundation.gui.element.GuiGameElement; +import com.simibubi.create.foundation.gui.menu.AbstractSimiContainerScreen; import com.simibubi.create.foundation.gui.widget.IconButton; import com.simibubi.create.foundation.gui.widget.Indicator; import com.simibubi.create.foundation.gui.widget.Indicator.State; -import com.simibubi.create.foundation.item.ItemDescription.Palette; import com.simibubi.create.foundation.item.TooltipHelper; -import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.foundation.item.TooltipHelper.Palette; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Lang; @@ -33,7 +32,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.item.ItemStack; -public class SchematicannonScreen extends AbstractSimiContainerScreen { +public class SchematicannonScreen extends AbstractSimiContainerScreen { private static final AllGuiTextures BG_BOTTOM = AllGuiTextures.SCHEMATICANNON_BOTTOM; private static final AllGuiTextures BG_TOP = AllGuiTextures.SCHEMATICANNON_TOP; @@ -56,8 +55,8 @@ public class SchematicannonScreen extends AbstractSimiContainerScreen extraAreas = Collections.emptyList(); - public SchematicannonScreen(SchematicannonContainer container, Inventory inventory, Component title) { - super(container, inventory, title); + public SchematicannonScreen(SchematicannonMenu menu, Inventory inventory, Component title) { + super(menu, inventory, title); placementSettingWidgets = new ArrayList<>(); } @@ -173,13 +172,13 @@ public class SchematicannonScreen extends AbstractSimiContainerScreen { - sendOptionUpdate(Option.SKIP_TILES, !menu.contentHolder.replaceTileEntities); + skipBlockEntitiesButton = new IconButton(x + 129, y + 117, AllIcons.I_SKIP_BLOCK_ENTITIES); + skipBlockEntitiesButton.withCallback(() -> { + sendOptionUpdate(Option.SKIP_BLOCK_ENTITIES, !menu.contentHolder.replaceBlockEntities); }); - skipTilesButton.setToolTip(Lang.translateDirect("gui.schematicannon.option.skipTileEntities")); - skipTilesIndicator = new Indicator(x + 129, y + 111, Components.immutableEmpty()); - Collections.addAll(placementSettingWidgets, skipTilesButton, skipTilesIndicator); + skipBlockEntitiesButton.setToolTip(Lang.translateDirect("gui.schematicannon.option.skipBlockEntities")); + skipBlockEntitiesIndicator = new Indicator(x + 129, y + 111, Components.immutableEmpty()); + Collections.addAll(placementSettingWidgets, skipBlockEntitiesButton, skipBlockEntitiesIndicator); addRenderableWidgets(placementSettingWidgets); } @@ -192,22 +191,22 @@ public class SchematicannonScreen extends AbstractSimiContainerScreenat(x + 128, y + 49, 100) .scale(1) .render(ms); @@ -311,7 +310,7 @@ public class SchematicannonScreen extends AbstractSimiContainerScreen= fuelX && mouseY >= fuelY && mouseX <= fuelX + AllGuiTextures.SCHEMATICANNON_FUEL.width && mouseY <= fuelY + AllGuiTextures.SCHEMATICANNON_FUEL.height) { - List tooltip = getFuelLevelTooltip(te); + List tooltip = getFuelLevelTooltip(be); renderComponentTooltip(matrixStack, tooltip, mouseX, mouseY); } if (hoveredSlot != null && !hoveredSlot.hasItem()) { if (hoveredSlot.index == 0) renderComponentTooltip(matrixStack, - TooltipHelper.cutTextComponent(Lang.translateDirect(_slotSchematic), GRAY, BLUE), mouseX, mouseY); + TooltipHelper.cutTextComponent(Lang.translateDirect(_slotSchematic), Palette.GRAY_AND_BLUE), mouseX, mouseY); if (hoveredSlot.index == 2) renderComponentTooltip(matrixStack, - TooltipHelper.cutTextComponent(Lang.translateDirect(_slotListPrinter), GRAY, BLUE), mouseX, mouseY); + TooltipHelper.cutTextComponent(Lang.translateDirect(_slotListPrinter), Palette.GRAY_AND_BLUE), mouseX, mouseY); if (hoveredSlot.index == 4) renderComponentTooltip(matrixStack, - TooltipHelper.cutTextComponent(Lang.translateDirect(_slotGunpowder), GRAY, BLUE), mouseX, mouseY); + TooltipHelper.cutTextComponent(Lang.translateDirect(_slotGunpowder), Palette.GRAY_AND_BLUE), mouseX, mouseY); } - if (te.missingItem != null) { + if (be.missingItem != null) { int missingBlockX = x + 128, missingBlockY = y + 49; if (mouseX >= missingBlockX && mouseY >= missingBlockY && mouseX <= missingBlockX + 16 && mouseY <= missingBlockY + 16) { - renderTooltip(matrixStack, te.missingItem, mouseX, mouseY); + renderTooltip(matrixStack, be.missingItem, mouseX, mouseY); } } @@ -385,14 +384,14 @@ public class SchematicannonScreen extends AbstractSimiContainerScreen getFuelLevelTooltip(SchematicannonTileEntity te) { - double fuelUsageRate = te.getFuelUsageRate(); - int shotsLeft = (int) (te.fuelLevel / fuelUsageRate); - int shotsLeftWithItems = (int) (shotsLeft + te.inventory.getStackInSlot(4) - .getCount() * (te.getFuelAddedByGunPowder() / fuelUsageRate)); + protected List getFuelLevelTooltip(SchematicannonBlockEntity be) { + double fuelUsageRate = be.getFuelUsageRate(); + int shotsLeft = (int) (be.fuelLevel / fuelUsageRate); + int shotsLeftWithItems = (int) (shotsLeft + be.inventory.getStackInSlot(4) + .getCount() * (be.getFuelAddedByGunPowder() / fuelUsageRate)); List tooltip = new ArrayList<>(); - if (te.hasCreativeCrate) { + if (be.hasCreativeCrate) { tooltip.add(Lang.translateDirect(_gunpowderLevel, "" + 100)); tooltip.add(Components.literal("(").append(AllBlocks.CREATIVE_CRATE.get() .getName()) @@ -401,7 +400,7 @@ public class SchematicannonScreen extends AbstractSimiContainerScreen maxSize * 1000) { LocalPlayer player = Minecraft.getInstance().player; if (player != null) { @@ -96,7 +96,7 @@ public class ClientSchematicLoader { private void continueUpload(String schematic) { if (activeUploads.containsKey(schematic)) { - Integer maxPacketSize = AllConfigs.SERVER.schematics.maxSchematicPacketSize.get(); + Integer maxPacketSize = AllConfigs.server().schematics.maxSchematicPacketSize.get(); byte[] data = new byte[maxPacketSize]; try { int status = activeUploads.get(schematic).read(data); @@ -105,7 +105,7 @@ public class ClientSchematicLoader { if (status < maxPacketSize) data = Arrays.copyOf(data, status); if (Minecraft.getInstance().level != null) - AllPackets.channel.sendToServer(SchematicUploadPacket.write(schematic, data)); + AllPackets.getChannel().sendToServer(SchematicUploadPacket.write(schematic, data)); else { activeUploads.remove(schematic); return; @@ -122,7 +122,7 @@ public class ClientSchematicLoader { private void finishUpload(String schematic) { if (activeUploads.containsKey(schematic)) { - AllPackets.channel.sendToServer(SchematicUploadPacket.finish(schematic)); + AllPackets.getChannel().sendToServer(SchematicUploadPacket.finish(schematic)); activeUploads.remove(schematic); } } diff --git a/src/main/java/com/simibubi/create/content/schematics/client/SchematicAndQuillHandler.java b/src/main/java/com/simibubi/create/content/schematics/client/SchematicAndQuillHandler.java index f89a3be45..24dec6791 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/SchematicAndQuillHandler.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/SchematicAndQuillHandler.java @@ -1,48 +1,37 @@ package com.simibubi.create.content.schematics.client; import java.io.IOException; -import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.StandardOpenOption; - -import org.apache.commons.io.IOUtils; import com.simibubi.create.AllItems; import com.simibubi.create.AllKeys; +import com.simibubi.create.AllPackets; import com.simibubi.create.AllSpecialTextures; import com.simibubi.create.Create; import com.simibubi.create.CreateClient; -import com.simibubi.create.content.schematics.ClientSchematicLoader; -import com.simibubi.create.content.schematics.item.SchematicAndQuillItem; +import com.simibubi.create.content.schematics.SchematicExport; +import com.simibubi.create.content.schematics.SchematicExport.SchematicExportResult; import com.simibubi.create.content.schematics.packet.InstantSchematicPacket; import com.simibubi.create.foundation.gui.ScreenOpener; -import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.foundation.outliner.Outliner; import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.FilesHelper; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.RaycastHelper; import com.simibubi.create.foundation.utility.RaycastHelper.PredicateTraceResult; import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.foundation.utility.outliner.Outliner; +import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Direction.AxisDirection; import net.minecraft.core.Vec3i; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtIo; import net.minecraft.util.Mth; import net.minecraft.world.InteractionHand; import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.item.context.UseOnContext; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.levelgen.structure.BoundingBox; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult.Type; @@ -52,8 +41,8 @@ public class SchematicAndQuillHandler { private Object outlineSlot = new Object(); - private BlockPos firstPos; - private BlockPos secondPos; + public BlockPos firstPos; + public BlockPos secondPos; private BlockPos selectedPos; private Direction selectedFace; private int range = 10; @@ -213,58 +202,31 @@ public class SchematicAndQuillHandler { } public void saveSchematic(String string, boolean convertImmediately) { - StructureTemplate t = new StructureTemplate(); - BoundingBox bb = BoundingBox.fromCorners(firstPos, secondPos); - BlockPos origin = new BlockPos(bb.minX(), bb.minY(), bb.minZ()); - BlockPos bounds = new BlockPos(bb.getXSpan(), bb.getYSpan(), bb.getZSpan()); - Level level = Minecraft.getInstance().level; - - t.fillFromWorld(level, origin, bounds, true, Blocks.AIR); - - if (string.isEmpty()) - string = Lang.translateDirect("schematicAndQuill.fallbackName") - .getString(); - - String folderPath = "schematics"; - FilesHelper.createFolderIfMissing(folderPath); - String filename = FilesHelper.findFirstValidFilename(string, folderPath, "nbt"); - String filepath = folderPath + "/" + filename; - - Path path = Paths.get(filepath); - OutputStream outputStream = null; - try { - outputStream = Files.newOutputStream(path, StandardOpenOption.CREATE); - CompoundTag nbttagcompound = t.save(new CompoundTag()); - SchematicAndQuillItem.replaceStructureVoidWithAir(nbttagcompound); - SchematicAndQuillItem.clampGlueBoxes(level, new AABB(origin, origin.offset(bounds)), nbttagcompound); - NbtIo.writeCompressed(nbttagcompound, outputStream); - } catch (IOException e) { - e.printStackTrace(); - } finally { - if (outputStream != null) - IOUtils.closeQuietly(outputStream); + SchematicExportResult result = SchematicExport.saveSchematic( + SchematicExport.SCHEMATICS, string, false, + Minecraft.getInstance().level, firstPos, secondPos + ); + LocalPlayer player = Minecraft.getInstance().player; + if (result == null) { + Lang.translate("schematicAndQuill.failed") + .style(ChatFormatting.RED) + .sendStatus(player); + return; } + Path file = result.file(); + Lang.translate("schematicAndQuill.saved", file.getFileName()) + .sendStatus(player); firstPos = null; secondPos = null; - LocalPlayer player = Minecraft.getInstance().player; - Lang.translate("schematicAndQuill.saved", filepath) - .sendStatus(player); - if (!convertImmediately) return; - if (!Files.exists(path)) { - Create.LOGGER.error("Missing Schematic file: " + path.toString()); - return; - } try { - if (!ClientSchematicLoader.validateSizeLimitation(Files.size(path))) + if (!ClientSchematicLoader.validateSizeLimitation(Files.size(file))) return; - AllPackets.channel.sendToServer(new InstantSchematicPacket(filename, origin, bounds)); - + AllPackets.getChannel() + .sendToServer(new InstantSchematicPacket(result.fileName(), result.origin(), result.bounds())); } catch (IOException e) { - Create.LOGGER.error("Error finding Schematic file: " + path.toString()); - e.printStackTrace(); - return; + Create.LOGGER.error("Error instantly uploading Schematic file: " + file, e); } } @@ -272,4 +234,4 @@ public class SchematicAndQuillHandler { return CreateClient.OUTLINER; } -} \ No newline at end of file +} diff --git a/src/main/java/com/simibubi/create/content/schematics/client/SchematicHandler.java b/src/main/java/com/simibubi/create/content/schematics/client/SchematicHandler.java index 876237e84..4e461928d 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/SchematicHandler.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/SchematicHandler.java @@ -8,20 +8,20 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; import com.simibubi.create.AllKeys; +import com.simibubi.create.AllPackets; import com.simibubi.create.Create; -import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform; +import com.simibubi.create.content.contraptions.StructureTransform; +import com.simibubi.create.content.schematics.SchematicInstances; +import com.simibubi.create.content.schematics.SchematicItem; import com.simibubi.create.content.schematics.SchematicWorld; -import com.simibubi.create.content.schematics.client.tools.Tools; -import com.simibubi.create.content.schematics.filtering.SchematicInstances; -import com.simibubi.create.content.schematics.item.SchematicItem; +import com.simibubi.create.content.schematics.client.tools.ToolType; import com.simibubi.create.content.schematics.packet.SchematicPlacePacket; import com.simibubi.create.content.schematics.packet.SchematicSyncPacket; -import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.foundation.outliner.AABBOutline; import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.outliner.AABBOutline; import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; @@ -46,17 +46,18 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlac import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.Vec3; import net.minecraftforge.client.gui.overlay.ForgeGui; import net.minecraftforge.client.gui.overlay.IGuiOverlay; -public class SchematicHandler { +public class SchematicHandler implements IGuiOverlay { private String displayedSchematic; private SchematicTransformation transformation; private AABB bounds; private boolean deployed; private boolean active; - private Tools currentTool; + private ToolType currentTool; private static final int SYNC_DELAY = 10; private int syncCooldown; @@ -68,16 +69,14 @@ public class SchematicHandler { private SchematicHotbarSlotOverlay overlay; private ToolSelectionScreen selectionScreen; - private final IGuiOverlay overlayRenderer = this::renderOverlay; - public SchematicHandler() { renderers = new Vector<>(3); for (int i = 0; i < renderers.capacity(); i++) renderers.add(new SchematicRenderer()); overlay = new SchematicHotbarSlotOverlay(); - currentTool = Tools.Deploy; - selectionScreen = new ToolSelectionScreen(ImmutableList.of(Tools.Deploy), this::equip); + currentTool = ToolType.DEPLOY; + selectionScreen = new ToolSelectionScreen(ImmutableList.of(ToolType.DEPLOY), this::equip); transformation = new SchematicTransformation(); } @@ -135,14 +134,14 @@ public class SchematicHandler { active = true; if (deployed) { setupRenderer(); - Tools toolBefore = currentTool; - selectionScreen = new ToolSelectionScreen(Tools.getTools(player.isCreative()), this::equip); + ToolType toolBefore = currentTool; + selectionScreen = new ToolSelectionScreen(ToolType.getTools(player.isCreative()), this::equip); if (toolBefore != null) { selectionScreen.setSelectedElement(toolBefore); equip(toolBefore); } } else - selectionScreen = new ToolSelectionScreen(ImmutableList.of(Tools.Deploy), this::equip); + selectionScreen = new ToolSelectionScreen(ImmutableList.of(ToolType.DEPLOY), this::equip); } private void setupRenderer() { @@ -176,16 +175,16 @@ public class SchematicHandler { schematic.placeInWorld(wMirroredFB, pos, pos, placementSettings, wMirroredFB.getRandom(), Block.UPDATE_CLIENTS); transform = new StructureTransform(placementSettings.getRotationPivot(), Axis.Y, Rotation.NONE, placementSettings.getMirror()); - for (BlockEntity te : wMirroredFB.getRenderedTileEntities()) - transform.apply(te); + for (BlockEntity be : wMirroredFB.getRenderedBlockEntities()) + transform.apply(be); placementSettings.setMirror(Mirror.LEFT_RIGHT); pos = BlockPos.ZERO.south(size.getZ() - 1); schematic.placeInWorld(wMirroredLR, pos, pos, placementSettings, wMirroredFB.getRandom(), Block.UPDATE_CLIENTS); transform = new StructureTransform(placementSettings.getRotationPivot(), Axis.Y, Rotation.NONE, placementSettings.getMirror()); - for (BlockEntity te : wMirroredLR.getRenderedTileEntities()) - transform.apply(te); + for (BlockEntity be : wMirroredLR.getRenderedBlockEntities()) + transform.apply(be); renderers.get(0) .display(w); @@ -195,7 +194,7 @@ public class SchematicHandler { .display(wMirroredLR); } - public void render(PoseStack ms, SuperRenderTypeBuffer buffer) { + public void render(PoseStack ms, SuperRenderTypeBuffer buffer, Vec3 camera) { boolean present = activeSchematicItem != null; if (!active && !present) return; @@ -203,12 +202,12 @@ public class SchematicHandler { if (active) { ms.pushPose(); currentTool.getTool() - .renderTool(ms, buffer); + .renderTool(ms, buffer, camera); ms.popPose(); } ms.pushPose(); - transformation.applyGLTransformations(ms); + transformation.applyTransformations(ms, camera); if (!renderers.isEmpty()) { float pt = AnimationTickHolder.getPartialTicks(); @@ -241,11 +240,8 @@ public class SchematicHandler { } } - public IGuiOverlay getOverlayRenderer() { - return overlayRenderer; - } - - public void renderOverlay(ForgeGui gui, PoseStack poseStack, float partialTicks, int width, int height) { + @Override + public void render(ForgeGui gui, PoseStack poseStack, float partialTicks, int width, int height) { if (Minecraft.getInstance().options.hideGui || !active) return; if (activeSchematicItem != null) @@ -336,11 +332,11 @@ public class SchematicHandler { public void sync() { if (activeSchematicItem == null) return; - AllPackets.channel.sendToServer(new SchematicSyncPacket(activeHotbarSlot, transformation.toSettings(), + AllPackets.getChannel().sendToServer(new SchematicSyncPacket(activeHotbarSlot, transformation.toSettings(), transformation.getAnchor(), deployed)); } - public void equip(Tools tool) { + public void equip(ToolType tool) { this.currentTool = tool; currentTool.getTool() .init(); @@ -367,7 +363,7 @@ public class SchematicHandler { public void deploy() { if (!deployed) { - List tools = Tools.getTools(Minecraft.getInstance().player.isCreative()); + List tools = ToolType.getTools(Minecraft.getInstance().player.isCreative()); selectionScreen = new ToolSelectionScreen(tools, this::equip); } deployed = true; @@ -379,7 +375,7 @@ public class SchematicHandler { } public void printInstantly() { - AllPackets.channel.sendToServer(new SchematicPlacePacket(activeSchematicItem.copy())); + AllPackets.getChannel().sendToServer(new SchematicPlacePacket(activeSchematicItem.copy())); CompoundTag nbt = activeSchematicItem.getTag(); nbt.putBoolean("Deployed", false); activeSchematicItem.setTag(nbt); diff --git a/src/main/java/com/simibubi/create/content/schematics/client/SchematicPromptScreen.java b/src/main/java/com/simibubi/create/content/schematics/client/SchematicPromptScreen.java index 3fb353c40..4f9723252 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/SchematicPromptScreen.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/SchematicPromptScreen.java @@ -109,5 +109,4 @@ public class SchematicPromptScreen extends AbstractSimiScreen { CreateClient.SCHEMATIC_AND_QUILL_HANDLER.saveSchematic(nameField.getValue(), convertImmediately); onClose(); } - } diff --git a/src/main/java/com/simibubi/create/content/schematics/client/SchematicRenderer.java b/src/main/java/com/simibubi/create/content/schematics/client/SchematicRenderer.java index ffce00ef3..9fa2aa9dd 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/SchematicRenderer.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/SchematicRenderer.java @@ -12,9 +12,9 @@ import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexFormat; import com.simibubi.create.content.schematics.SchematicWorld; +import com.simibubi.create.foundation.render.BlockEntityRenderHelper; import com.simibubi.create.foundation.render.SuperByteBuffer; import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; -import com.simibubi.create.foundation.render.TileEntityRenderHelper; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.RenderType; @@ -76,7 +76,7 @@ public class SchematicRenderer { bufferCache.forEach((layer, buffer) -> { buffer.renderInto(ms, buffers.getBuffer(layer)); }); - TileEntityRenderHelper.renderTileEntities(schematic, schematic.getRenderedTileEntities(), ms, buffers); + BlockEntityRenderHelper.renderBlockEntities(schematic, schematic.getRenderedBlockEntities(), ms, buffers); } protected void redraw() { @@ -115,8 +115,8 @@ public class SchematicRenderer { if (state.getRenderShape() == RenderShape.MODEL) { BakedModel model = dispatcher.getBlockModel(state); - BlockEntity tileEntity = renderWorld.getBlockEntity(localPos); - ModelData modelData = tileEntity != null ? tileEntity.getModelData() : ModelData.EMPTY; + BlockEntity blockEntity = renderWorld.getBlockEntity(localPos); + ModelData modelData = blockEntity != null ? blockEntity.getModelData() : ModelData.EMPTY; long seed = state.getSeed(pos); random.setSeed(seed); if (model.getRenderTypes(state, random, modelData).contains(layer)) { diff --git a/src/main/java/com/simibubi/create/content/schematics/client/SchematicTransformation.java b/src/main/java/com/simibubi/create/content/schematics/client/SchematicTransformation.java index d9d7628aa..78d7ed7e4 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/SchematicTransformation.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/SchematicTransformation.java @@ -19,15 +19,19 @@ import net.minecraft.world.phys.Vec3; public class SchematicTransformation { - private LerpedFloat x, y, z, scaleFrontBack, scaleLeftRight; + private Vec3 chasingPos; + private Vec3 prevChasingPos; + private BlockPos target; + + private LerpedFloat scaleFrontBack, scaleLeftRight; private LerpedFloat rotation; private double xOrigin; private double zOrigin; public SchematicTransformation() { - x = LerpedFloat.linear(); - y = LerpedFloat.linear(); - z = LerpedFloat.linear(); + chasingPos = Vec3.ZERO; + prevChasingPos = Vec3.ZERO; + target = BlockPos.ZERO; scaleFrontBack = LerpedFloat.linear(); scaleLeftRight = LerpedFloat.linear(); rotation = LerpedFloat.angular(); @@ -48,20 +52,18 @@ public class SchematicTransformation { rotation.chase(0, 0.45f, Chaser.EXP) .startWithValue(r); - Vec3 vec = fromAnchor(anchor); - x.chase(0, 0.45f, Chaser.EXP) - .startWithValue((float) vec.x); - y.chase(0, 0.45f, Chaser.EXP) - .startWithValue((float) vec.y); - z.chase(0, 0.45f, Chaser.EXP) - .startWithValue((float) vec.z); + target = fromAnchor(anchor); + chasingPos = Vec3.atLowerCornerOf(target); + prevChasingPos = chasingPos; } - public void applyGLTransformations(PoseStack ms) { + public void applyTransformations(PoseStack ms, Vec3 camera) { float pt = AnimationTickHolder.getPartialTicks(); // Translation - ms.translate(x.getValue(pt), y.getValue(pt), z.getValue(pt)); + TransformStack.cast(ms) + .translate(VecHelper.lerp(pt, prevChasingPos, chasingPos) + .subtract(camera)); Vec3 rotationOffset = getRotationOffset(true); // Rotation & Mirror @@ -101,7 +103,7 @@ public class SchematicTransformation { float pt = AnimationTickHolder.getPartialTicks(); Vec3 rotationOffset = getRotationOffset(true); - vec = vec.subtract(x.getValue(pt), y.getValue(pt), z.getValue(pt)); + vec = vec.subtract(VecHelper.lerp(pt, prevChasingPos, chasingPos)); vec = vec.subtract(xOrigin + rotationOffset.x, 0, zOrigin + rotationOffset.z); vec = VecHelper.rotate(vec, -rotation.getValue(pt), Axis.Y); vec = vec.add(rotationOffset.x, 0, rotationOffset.z); @@ -157,12 +159,11 @@ public class SchematicTransformation { vec = vec.multiply(getScaleFB().getChaseTarget(), 1, getScaleLR().getChaseTarget()); vec = VecHelper.rotate(vec, rotation.getChaseTarget(), Axis.Y); vec = vec.add(xOrigin, 0, zOrigin); - - vec = vec.add(x.getChaseTarget(), y.getChaseTarget(), z.getChaseTarget()); + vec = vec.add(target.getX(), target.getY(), target.getZ()); return new BlockPos(vec.x, vec.y, vec.z); } - public Vec3 fromAnchor(BlockPos pos) { + public BlockPos fromAnchor(BlockPos pos) { Vec3 vec = Vec3.ZERO.add(.5, 0, .5); Vec3 rotationOffset = getRotationOffset(false); vec = vec.subtract(xOrigin, 0, zOrigin); @@ -170,8 +171,7 @@ public class SchematicTransformation { vec = vec.multiply(getScaleFB().getChaseTarget(), 1, getScaleLR().getChaseTarget()); vec = VecHelper.rotate(vec, rotation.getChaseTarget(), Axis.Y); vec = vec.add(xOrigin, 0, zOrigin); - - return Vec3.atLowerCornerOf(pos.subtract(new BlockPos(vec.x, vec.y, vec.z))); + return pos.subtract(new BlockPos(vec.x, vec.y, vec.z)); } public int getRotationTarget() { @@ -190,9 +190,8 @@ public class SchematicTransformation { } public void tick() { - x.tickChaser(); - y.tickChaser(); - z.tickChaser(); + prevChasingPos = chasingPos; + chasingPos = VecHelper.lerp(0.45f, chasingPos, Vec3.atLowerCornerOf(target)); getScaleLR().tickChaser(); getScaleFB().tickChaser(); rotation.tickChaser(); @@ -209,25 +208,22 @@ public class SchematicTransformation { rotation.updateChaseTarget(rotation.getChaseTarget() + (clockwise ? -90 : 90)); } - public void move(float xIn, float yIn, float zIn) { - moveTo(x.getChaseTarget() + xIn, y.getChaseTarget() + yIn, z.getChaseTarget() + zIn); + public void move(int xIn, int yIn, int zIn) { + moveTo(target.offset(xIn, yIn, zIn)); } public void startAt(BlockPos pos) { - x.startWithValue(pos.getX()); - y.startWithValue(pos.getY() - 10); - z.startWithValue(pos.getZ()); + chasingPos = Vec3.atLowerCornerOf(pos); + prevChasingPos = chasingPos; moveTo(pos); } public void moveTo(BlockPos pos) { - moveTo(pos.getX(), pos.getY(), pos.getZ()); + target = pos; } - public void moveTo(float xIn, float yIn, float zIn) { - x.updateChaseTarget(xIn); - y.updateChaseTarget(yIn); - z.updateChaseTarget(zIn); + public void moveTo(int xIn, int yIn, int zIn) { + moveTo(new BlockPos(xIn, yIn, zIn)); } public LerpedFloat getScaleFB() { diff --git a/src/main/java/com/simibubi/create/content/schematics/client/ToolSelectionScreen.java b/src/main/java/com/simibubi/create/content/schematics/client/ToolSelectionScreen.java index dbf7a5b8a..20d0058fc 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/ToolSelectionScreen.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/ToolSelectionScreen.java @@ -7,7 +7,7 @@ import com.mojang.blaze3d.platform.Window; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllKeys; -import com.simibubi.create.content.schematics.client.tools.Tools; +import com.simibubi.create.content.schematics.client.tools.ToolType; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Lang; @@ -22,8 +22,8 @@ public class ToolSelectionScreen extends Screen { .getString(); public final String holdToFocus = "gui.toolmenu.focusKey"; - protected List tools; - protected Consumer callback; + protected List tools; + protected Consumer callback; public boolean focused; private float yOffset; protected int selection; @@ -32,7 +32,7 @@ public class ToolSelectionScreen extends Screen { protected int w; protected int h; - public ToolSelectionScreen(List tools, Consumer callback) { + public ToolSelectionScreen(List tools, Consumer callback) { super(Components.literal("Tool Selection")); this.minecraft = Minecraft.getInstance(); this.tools = tools; @@ -48,7 +48,7 @@ public class ToolSelectionScreen extends Screen { h = 30; } - public void setSelectedElement(Tools tool) { + public void setSelectedElement(ToolType tool) { if (!tools.contains(tool)) return; selection = tools.indexOf(tool); diff --git a/src/main/java/com/simibubi/create/content/schematics/client/tools/DeployTool.java b/src/main/java/com/simibubi/create/content/schematics/client/tools/DeployTool.java index e2abd68c1..e27d4f34c 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/tools/DeployTool.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/tools/DeployTool.java @@ -4,9 +4,9 @@ import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllKeys; import com.simibubi.create.content.schematics.client.SchematicTransformation; +import com.simibubi.create.foundation.outliner.AABBOutline; import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.outliner.AABBOutline; import net.minecraft.core.BlockPos; import net.minecraft.nbt.NbtUtils; @@ -36,8 +36,8 @@ public class DeployTool extends PlacementToolBase { } @Override - public void renderTool(PoseStack ms, SuperRenderTypeBuffer buffer) { - super.renderTool(ms, buffer); + public void renderTool(PoseStack ms, SuperRenderTypeBuffer buffer, Vec3 camera) { + super.renderTool(ms, buffer, camera); if (selectedPos == null) return; @@ -58,7 +58,7 @@ public class DeployTool extends PlacementToolBase { double zOrigin = bounds.getZsize() / 2f; Vec3 origin = new Vec3(xOrigin, 0, zOrigin); - ms.translate(x - centerX, y, z - centerZ); + ms.translate(x - centerX - camera.x, y - camera.y, z - centerZ - camera.z); TransformStack.cast(ms) .translate(origin) .translate(rotationOffset) @@ -67,7 +67,7 @@ public class DeployTool extends PlacementToolBase { .translateBack(origin); AABBOutline outline = schematicHandler.getOutline(); - outline.render(ms, buffer, pt); + outline.render(ms, buffer, Vec3.ZERO, pt); outline.getParams() .clearTextures(); ms.popPose(); diff --git a/src/main/java/com/simibubi/create/content/schematics/client/tools/FlipTool.java b/src/main/java/com/simibubi/create/content/schematics/client/tools/FlipTool.java index 10ceb1547..14f80ea94 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/tools/FlipTool.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/tools/FlipTool.java @@ -2,9 +2,9 @@ package com.simibubi.create.content.schematics.client.tools; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllSpecialTextures; +import com.simibubi.create.foundation.outliner.AABBOutline; import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.outliner.AABBOutline; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -72,10 +72,10 @@ public class FlipTool extends PlacementToolBase { AllSpecialTextures tex = AllSpecialTextures.CHECKERED; outline.getParams() .lineWidth(1 / 16f) - .disableNormals() + .disableLineNormals() .colored(0xdddddd) .withFaceTextures(tex, tex); - outline.render(ms, buffer, AnimationTickHolder.getPartialTicks()); + outline.render(ms, buffer, Vec3.ZERO, AnimationTickHolder.getPartialTicks()); super.renderOnSchematic(ms, buffer); } diff --git a/src/main/java/com/simibubi/create/content/schematics/client/tools/ISchematicTool.java b/src/main/java/com/simibubi/create/content/schematics/client/tools/ISchematicTool.java index 7a93d5fb7..f046ea4ad 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/tools/ISchematicTool.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/tools/ISchematicTool.java @@ -3,6 +3,7 @@ package com.simibubi.create.content.schematics.client.tools; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; +import net.minecraft.world.phys.Vec3; import net.minecraftforge.client.gui.overlay.ForgeGui; public interface ISchematicTool { @@ -13,7 +14,7 @@ public interface ISchematicTool { public boolean handleRightClick(); public boolean handleMouseWheel(double delta); - public void renderTool(PoseStack ms, SuperRenderTypeBuffer buffer); + public void renderTool(PoseStack ms, SuperRenderTypeBuffer buffer, Vec3 camera); public void renderOverlay(ForgeGui gui, PoseStack poseStack, float partialTicks, int width, int height); public void renderOnSchematic(PoseStack ms, SuperRenderTypeBuffer buffer); diff --git a/src/main/java/com/simibubi/create/content/schematics/client/tools/MoveTool.java b/src/main/java/com/simibubi/create/content/schematics/client/tools/MoveTool.java index 9f1bc0bba..0fe9cf930 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/tools/MoveTool.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/tools/MoveTool.java @@ -28,7 +28,7 @@ public class MoveTool extends PlacementToolBase { Vec3 vec = Vec3.atLowerCornerOf(selectedFace.getNormal()).scale(-Math.signum(delta)); vec = vec.multiply(transformation.getMirrorModifier(Axis.X), 1, transformation.getMirrorModifier(Axis.Z)); vec = VecHelper.rotate(vec, transformation.getRotationTarget(), Axis.Y); - transformation.move((float) vec.x, 0, (float) vec.z); + transformation.move((int) vec.x, 0, (int) vec.z); schematicHandler.markDirty(); return true; diff --git a/src/main/java/com/simibubi/create/content/schematics/client/tools/MoveVerticalTool.java b/src/main/java/com/simibubi/create/content/schematics/client/tools/MoveVerticalTool.java index a3f8a6dbe..0f7c7d854 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/tools/MoveVerticalTool.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/tools/MoveVerticalTool.java @@ -1,11 +1,13 @@ package com.simibubi.create.content.schematics.client.tools; +import net.minecraft.util.Mth; + public class MoveVerticalTool extends PlacementToolBase { @Override public boolean handleMouseWheel(double delta) { if (schematicHandler.isDeployed()) { - schematicHandler.getTransformation().move(0, (float) Math.signum(delta), 0); + schematicHandler.getTransformation().move(0, Mth.sign(delta), 0); schematicHandler.markDirty(); } return true; diff --git a/src/main/java/com/simibubi/create/content/schematics/client/tools/PlacementToolBase.java b/src/main/java/com/simibubi/create/content/schematics/client/tools/PlacementToolBase.java index b008466bf..7aa1faa2c 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/tools/PlacementToolBase.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/tools/PlacementToolBase.java @@ -3,6 +3,7 @@ package com.simibubi.create.content.schematics.client.tools; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; +import net.minecraft.world.phys.Vec3; import net.minecraftforge.client.gui.overlay.ForgeGui; public abstract class PlacementToolBase extends SchematicToolBase { @@ -18,8 +19,8 @@ public abstract class PlacementToolBase extends SchematicToolBase { } @Override - public void renderTool(PoseStack ms, SuperRenderTypeBuffer buffer) { - super.renderTool(ms, buffer); + public void renderTool(PoseStack ms, SuperRenderTypeBuffer buffer, Vec3 camera) { + super.renderTool(ms, buffer, camera); } @Override diff --git a/src/main/java/com/simibubi/create/content/schematics/client/tools/RotateTool.java b/src/main/java/com/simibubi/create/content/schematics/client/tools/RotateTool.java index 55b3e3dcc..d9de64f7d 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/tools/RotateTool.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/tools/RotateTool.java @@ -1,9 +1,9 @@ package com.simibubi.create.content.schematics.client.tools; import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.foundation.outliner.LineOutline; import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.outliner.LineOutline; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; @@ -32,11 +32,11 @@ public class RotateTool extends PlacementToolBase { line.getParams() .disableCull() - .disableNormals() + .disableLineNormals() .colored(0xdddddd) .lineWidth(1 / 16f); line.set(start, end) - .render(ms, buffer, AnimationTickHolder.getPartialTicks()); + .render(ms, buffer, Vec3.ZERO, AnimationTickHolder.getPartialTicks()); super.renderOnSchematic(ms, buffer); } diff --git a/src/main/java/com/simibubi/create/content/schematics/client/tools/SchematicToolBase.java b/src/main/java/com/simibubi/create/content/schematics/client/tools/SchematicToolBase.java index b55542e4d..88bd8b0db 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/tools/SchematicToolBase.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/tools/SchematicToolBase.java @@ -9,12 +9,12 @@ import com.simibubi.create.AllSpecialTextures; import com.simibubi.create.CreateClient; import com.simibubi.create.content.schematics.client.SchematicHandler; import com.simibubi.create.content.schematics.client.SchematicTransformation; +import com.simibubi.create.foundation.outliner.AABBOutline; import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.RaycastHelper; import com.simibubi.create.foundation.utility.RaycastHelper.PredicateTraceResult; import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.foundation.utility.outliner.AABBOutline; import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; @@ -121,7 +121,7 @@ public abstract class SchematicToolBase implements ISchematicTool { } @Override - public void renderTool(PoseStack ms, SuperRenderTypeBuffer buffer) {} + public void renderTool(PoseStack ms, SuperRenderTypeBuffer buffer, Vec3 camera) {} @Override public void renderOverlay(ForgeGui gui, PoseStack poseStack, float partialTicks, int width, int height) {} @@ -143,7 +143,7 @@ public abstract class SchematicToolBase implements ISchematicTool { .colored(0x6886c5) .withFaceTexture(AllSpecialTextures.CHECKERED) .lineWidth(1 / 16f); - outline.render(ms, buffer, AnimationTickHolder.getPartialTicks()); + outline.render(ms, buffer, Vec3.ZERO, AnimationTickHolder.getPartialTicks()); outline.getParams() .clearTextures(); ms.popPose(); diff --git a/src/main/java/com/simibubi/create/content/schematics/client/tools/ToolType.java b/src/main/java/com/simibubi/create/content/schematics/client/tools/ToolType.java new file mode 100644 index 000000000..703ba4df6 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/schematics/client/tools/ToolType.java @@ -0,0 +1,54 @@ +package com.simibubi.create.content.schematics.client.tools; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import com.simibubi.create.foundation.gui.AllIcons; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; + +public enum ToolType { + + DEPLOY(new DeployTool(), AllIcons.I_TOOL_DEPLOY), + MOVE(new MoveTool(), AllIcons.I_TOOL_MOVE_XZ), + MOVE_Y(new MoveVerticalTool(), AllIcons.I_TOOL_MOVE_Y), + ROTATE(new RotateTool(), AllIcons.I_TOOL_ROTATE), + FLIP(new FlipTool(), AllIcons.I_TOOL_MIRROR), + PRINT(new PlaceTool(), AllIcons.I_CONFIRM); + + private ISchematicTool tool; + private AllIcons icon; + + private ToolType(ISchematicTool tool, AllIcons icon) { + this.tool = tool; + this.icon = icon; + } + + public ISchematicTool getTool() { + return tool; + } + + public MutableComponent getDisplayName() { + return Lang.translateDirect("schematic.tool." + Lang.asId(name())); + } + + public AllIcons getIcon() { + return icon; + } + + public static List getTools(boolean creative) { + List tools = new ArrayList<>(); + Collections.addAll(tools, MOVE, MOVE_Y, DEPLOY, ROTATE, FLIP); + if (creative) + tools.add(PRINT); + return tools; + } + + public List getDescription() { + return Lang.translatedOptions("schematic.tool." + Lang.asId(name()) + ".description", "0", "1", "2", "3"); + } + +} diff --git a/src/main/java/com/simibubi/create/content/schematics/client/tools/Tools.java b/src/main/java/com/simibubi/create/content/schematics/client/tools/Tools.java deleted file mode 100644 index 507f9565d..000000000 --- a/src/main/java/com/simibubi/create/content/schematics/client/tools/Tools.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.simibubi.create.content.schematics.client.tools; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.utility.Lang; - -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; - -public enum Tools { - - Deploy(new DeployTool(), AllIcons.I_TOOL_DEPLOY), - Move(new MoveTool(), AllIcons.I_TOOL_MOVE_XZ), - MoveY(new MoveVerticalTool(), AllIcons.I_TOOL_MOVE_Y), - Rotate(new RotateTool(), AllIcons.I_TOOL_ROTATE), - Print(new PlaceTool(), AllIcons.I_CONFIRM), - Flip(new FlipTool(), AllIcons.I_TOOL_MIRROR); - - private ISchematicTool tool; - private AllIcons icon; - - private Tools(ISchematicTool tool, AllIcons icon) { - this.tool = tool; - this.icon = icon; - } - - public ISchematicTool getTool() { - return tool; - } - - public MutableComponent getDisplayName() { - return Lang.translateDirect("schematic.tool." + Lang.asId(name())); - } - - public AllIcons getIcon() { - return icon; - } - - public static List getTools(boolean creative) { - List tools = new ArrayList<>(); - Collections.addAll(tools, Move, MoveY, Deploy, Rotate, Flip); - if (creative) - tools.add(Print); - return tools; - } - - public List getDescription() { - return Lang.translatedOptions("schematic.tool." + Lang.asId(name()) + ".description", "0", "1", "2", "3"); - } - -} diff --git a/src/main/java/com/simibubi/create/content/schematics/packet/ConfigureSchematicannonPacket.java b/src/main/java/com/simibubi/create/content/schematics/packet/ConfigureSchematicannonPacket.java deleted file mode 100644 index ee02fb8d1..000000000 --- a/src/main/java/com/simibubi/create/content/schematics/packet/ConfigureSchematicannonPacket.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.simibubi.create.content.schematics.packet; - -import java.util.function.Supplier; - -import com.simibubi.create.content.schematics.block.SchematicannonContainer; -import com.simibubi.create.content.schematics.block.SchematicannonTileEntity; -import com.simibubi.create.content.schematics.block.SchematicannonTileEntity.State; -import com.simibubi.create.foundation.networking.SimplePacketBase; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.server.level.ServerPlayer; -import net.minecraftforge.network.NetworkEvent.Context; - -public class ConfigureSchematicannonPacket extends SimplePacketBase { - - public static enum Option { - DONT_REPLACE, REPLACE_SOLID, REPLACE_ANY, REPLACE_EMPTY, SKIP_MISSING, SKIP_TILES, PLAY, PAUSE, STOP; - } - - private Option option; - private boolean set; - - public ConfigureSchematicannonPacket(Option option, boolean set) { - this.option = option; - this.set = set; - } - - public ConfigureSchematicannonPacket(FriendlyByteBuf buffer) { - this(buffer.readEnum(Option.class), buffer.readBoolean()); - } - - public void write(FriendlyByteBuf buffer) { - buffer.writeEnum(option); - buffer.writeBoolean(set); - } - - public void handle(Supplier context) { - context.get().enqueueWork(() -> { - ServerPlayer player = context.get().getSender(); - if (player == null || !(player.containerMenu instanceof SchematicannonContainer)) - return; - - SchematicannonTileEntity te = ((SchematicannonContainer) player.containerMenu).contentHolder; - switch (option) { - case DONT_REPLACE: - case REPLACE_ANY: - case REPLACE_EMPTY: - case REPLACE_SOLID: - te.replaceMode = option.ordinal(); - break; - case SKIP_MISSING: - te.skipMissing = set; - break; - case SKIP_TILES: - te.replaceTileEntities = set; - break; - - case PLAY: - te.state = State.RUNNING; - te.statusMsg = "running"; - break; - case PAUSE: - te.state = State.PAUSED; - te.statusMsg = "paused"; - break; - case STOP: - te.state = State.STOPPED; - te.statusMsg = "stopped"; - break; - default: - break; - } - - te.sendUpdate = true; - }); - context.get().setPacketHandled(true); - } - -} diff --git a/src/main/java/com/simibubi/create/content/schematics/packet/InstantSchematicPacket.java b/src/main/java/com/simibubi/create/content/schematics/packet/InstantSchematicPacket.java index 62d3f2abe..fc3757a18 100644 --- a/src/main/java/com/simibubi/create/content/schematics/packet/InstantSchematicPacket.java +++ b/src/main/java/com/simibubi/create/content/schematics/packet/InstantSchematicPacket.java @@ -1,7 +1,5 @@ package com.simibubi.create.content.schematics.packet; -import java.util.function.Supplier; - import com.simibubi.create.Create; import com.simibubi.create.foundation.networking.SimplePacketBase; @@ -36,17 +34,14 @@ public class InstantSchematicPacket extends SimplePacketBase { } @Override - public void handle(Supplier context) { - context.get() - .enqueueWork(() -> { - ServerPlayer player = context.get() - .getSender(); - if (player == null) - return; - Create.SCHEMATIC_RECEIVER.handleInstantSchematic(player, name, player.level, origin, bounds); - }); - context.get() - .setPacketHandled(true); + public boolean handle(Context context) { + context.enqueueWork(() -> { + ServerPlayer player = context.getSender(); + if (player == null) + return; + Create.SCHEMATIC_RECEIVER.handleInstantSchematic(player, name, player.level, origin, bounds); + }); + return true; } } diff --git a/src/main/java/com/simibubi/create/content/schematics/packet/SchematicPlacePacket.java b/src/main/java/com/simibubi/create/content/schematics/packet/SchematicPlacePacket.java index 70577c188..ffc8ad836 100644 --- a/src/main/java/com/simibubi/create/content/schematics/packet/SchematicPlacePacket.java +++ b/src/main/java/com/simibubi/create/content/schematics/packet/SchematicPlacePacket.java @@ -1,11 +1,9 @@ package com.simibubi.create.content.schematics.packet; -import java.util.function.Supplier; - import com.simibubi.create.content.schematics.SchematicPrinter; -import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.networking.SimplePacketBase; import com.simibubi.create.foundation.utility.BlockHelper; +import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.FriendlyByteBuf; @@ -26,15 +24,19 @@ public class SchematicPlacePacket extends SimplePacketBase { stack = buffer.readItem(); } + @Override public void write(FriendlyByteBuf buffer) { buffer.writeItem(stack); } - public void handle(Supplier context) { - context.get().enqueueWork(() -> { - ServerPlayer player = context.get().getSender(); + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> { + ServerPlayer player = context.getSender(); if (player == null) return; + if (!player.isCreative()) + return; Level world = player.getLevel(); SchematicPrinter printer = new SchematicPrinter(); @@ -42,25 +44,25 @@ public class SchematicPlacePacket extends SimplePacketBase { if (!printer.isLoaded() || printer.isErrored()) return; - boolean includeAir = AllConfigs.SERVER.schematics.creativePrintIncludesAir.get(); + boolean includeAir = AllConfigs.server().schematics.creativePrintIncludesAir.get(); while (printer.advanceCurrentPos()) { if (!printer.shouldPlaceCurrent(world)) continue; - printer.handleCurrentTarget((pos, state, tile) -> { + printer.handleCurrentTarget((pos, state, blockEntity) -> { boolean placingAir = state.isAir(); if (placingAir && !includeAir) return; - CompoundTag tileData = tile != null ? tile.saveWithFullMetadata() : null; - BlockHelper.placeSchematicBlock(world, state, pos, null, tileData); + CompoundTag data = BlockHelper.prepareBlockEntityData(state, blockEntity); + BlockHelper.placeSchematicBlock(world, state, pos, null, data); }, (pos, entity) -> { world.addFreshEntity(entity); }); } }); - context.get().setPacketHandled(true); + return true; } } diff --git a/src/main/java/com/simibubi/create/content/schematics/packet/SchematicSyncPacket.java b/src/main/java/com/simibubi/create/content/schematics/packet/SchematicSyncPacket.java index 6615b9546..9cdda5020 100644 --- a/src/main/java/com/simibubi/create/content/schematics/packet/SchematicSyncPacket.java +++ b/src/main/java/com/simibubi/create/content/schematics/packet/SchematicSyncPacket.java @@ -1,9 +1,7 @@ package com.simibubi.create.content.schematics.packet; -import java.util.function.Supplier; - import com.simibubi.create.AllItems; -import com.simibubi.create.content.schematics.filtering.SchematicInstances; +import com.simibubi.create.content.schematics.SchematicInstances; import com.simibubi.create.foundation.networking.SimplePacketBase; import net.minecraft.core.BlockPos; @@ -52,9 +50,9 @@ public class SchematicSyncPacket extends SimplePacketBase { } @Override - public void handle(Supplier context) { - context.get().enqueueWork(() -> { - ServerPlayer player = context.get().getSender(); + public boolean handle(Context context) { + context.enqueueWork(() -> { + ServerPlayer player = context.getSender(); if (player == null) return; ItemStack stack = ItemStack.EMPTY; @@ -73,7 +71,7 @@ public class SchematicSyncPacket extends SimplePacketBase { tag.putString("Mirror", mirror.name()); SchematicInstances.clearHash(stack); }); - context.get().setPacketHandled(true); + return true; } } diff --git a/src/main/java/com/simibubi/create/content/schematics/packet/SchematicUploadPacket.java b/src/main/java/com/simibubi/create/content/schematics/packet/SchematicUploadPacket.java index 7ef4c5dd7..69c19a5c2 100644 --- a/src/main/java/com/simibubi/create/content/schematics/packet/SchematicUploadPacket.java +++ b/src/main/java/com/simibubi/create/content/schematics/packet/SchematicUploadPacket.java @@ -1,9 +1,7 @@ package com.simibubi.create.content.schematics.packet; -import java.util.function.Supplier; - import com.simibubi.create.Create; -import com.simibubi.create.content.schematics.block.SchematicTableContainer; +import com.simibubi.create.content.schematics.table.SchematicTableMenu; import com.simibubi.create.foundation.networking.SimplePacketBase; import net.minecraft.core.BlockPos; @@ -53,6 +51,7 @@ public class SchematicUploadPacket extends SimplePacketBase { data = buffer.readByteArray(); } + @Override public void write(FriendlyByteBuf buffer) { buffer.writeInt(code); buffer.writeUtf(schematic); @@ -63,25 +62,23 @@ public class SchematicUploadPacket extends SimplePacketBase { buffer.writeByteArray(data); } - public void handle(Supplier context) { - context.get() - .enqueueWork(() -> { - ServerPlayer player = context.get() - .getSender(); - if (player == null) - return; - if (code == BEGIN) { - BlockPos pos = ((SchematicTableContainer) player.containerMenu).contentHolder - .getBlockPos(); - Create.SCHEMATIC_RECEIVER.handleNewUpload(player, schematic, size, pos); - } - if (code == WRITE) - Create.SCHEMATIC_RECEIVER.handleWriteRequest(player, schematic, data); - if (code == FINISH) - Create.SCHEMATIC_RECEIVER.handleFinishedUpload(player, schematic); - }); - context.get() - .setPacketHandled(true); + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> { + ServerPlayer player = context.getSender(); + if (player == null) + return; + if (code == BEGIN) { + BlockPos pos = ((SchematicTableMenu) player.containerMenu).contentHolder + .getBlockPos(); + Create.SCHEMATIC_RECEIVER.handleNewUpload(player, schematic, size, pos); + } + if (code == WRITE) + Create.SCHEMATIC_RECEIVER.handleWriteRequest(player, schematic, data); + if (code == FINISH) + Create.SCHEMATIC_RECEIVER.handleFinishedUpload(player, schematic); + }); + return true; } } diff --git a/src/main/java/com/simibubi/create/content/schematics/requirement/ISpecialBlockEntityItemRequirement.java b/src/main/java/com/simibubi/create/content/schematics/requirement/ISpecialBlockEntityItemRequirement.java new file mode 100644 index 000000000..3e2c9a2a5 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/schematics/requirement/ISpecialBlockEntityItemRequirement.java @@ -0,0 +1,9 @@ +package com.simibubi.create.content.schematics.requirement; + +import net.minecraft.world.level.block.state.BlockState; + +public interface ISpecialBlockEntityItemRequirement { + + public ItemRequirement getRequiredItems(BlockState state); + +} diff --git a/src/main/java/com/simibubi/create/content/schematics/requirement/ISpecialBlockItemRequirement.java b/src/main/java/com/simibubi/create/content/schematics/requirement/ISpecialBlockItemRequirement.java new file mode 100644 index 000000000..f55d45121 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/schematics/requirement/ISpecialBlockItemRequirement.java @@ -0,0 +1,10 @@ +package com.simibubi.create.content.schematics.requirement; + +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; + +public interface ISpecialBlockItemRequirement { + + public ItemRequirement getRequiredItems(BlockState state, BlockEntity blockEntity); + +} diff --git a/src/main/java/com/simibubi/create/content/schematics/requirement/ISpecialEntityItemRequirement.java b/src/main/java/com/simibubi/create/content/schematics/requirement/ISpecialEntityItemRequirement.java new file mode 100644 index 000000000..309500907 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/schematics/requirement/ISpecialEntityItemRequirement.java @@ -0,0 +1,7 @@ +package com.simibubi.create.content.schematics.requirement; + +public interface ISpecialEntityItemRequirement { + + public ItemRequirement getRequiredItems(); + +} diff --git a/src/main/java/com/simibubi/create/content/schematics/requirement/ItemRequirement.java b/src/main/java/com/simibubi/create/content/schematics/requirement/ItemRequirement.java new file mode 100644 index 000000000..6b07940dc --- /dev/null +++ b/src/main/java/com/simibubi/create/content/schematics/requirement/ItemRequirement.java @@ -0,0 +1,182 @@ +package com.simibubi.create.content.schematics.requirement; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import com.simibubi.create.foundation.utility.NBTProcessors; + +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.decoration.ArmorStand; +import net.minecraft.world.entity.decoration.ItemFrame; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.block.AbstractBannerBlock; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.DirtPathBlock; +import net.minecraft.world.level.block.FarmBlock; +import net.minecraft.world.level.block.SeaPickleBlock; +import net.minecraft.world.level.block.SnowLayerBlock; +import net.minecraft.world.level.block.TurtleEggBlock; +import net.minecraft.world.level.block.entity.BannerBlockEntity; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.SlabType; + +public class ItemRequirement { + public static final ItemRequirement NONE = new ItemRequirement(Collections.emptyList()); + public static final ItemRequirement INVALID = new ItemRequirement(Collections.emptyList()); + + protected List requiredItems; + + public ItemRequirement(List requiredItems) { + this.requiredItems = requiredItems; + } + + public ItemRequirement(StackRequirement stackRequirement) { + this(List.of(stackRequirement)); + } + + public ItemRequirement(ItemUseType usage, ItemStack stack) { + this(new StackRequirement(stack, usage)); + } + + public ItemRequirement(ItemUseType usage, Item item) { + this(usage, new ItemStack(item)); + } + + public ItemRequirement(ItemUseType usage, List requiredItems) { + this(requiredItems.stream() + .map(req -> new StackRequirement(req, usage)) + .collect(Collectors.toList())); + } + + public static ItemRequirement of(BlockState state, BlockEntity be) { + Block block = state.getBlock(); + + ItemRequirement requirement; + if (block instanceof ISpecialBlockItemRequirement specialBlock) { + requirement = specialBlock.getRequiredItems(state, be); + } else { + requirement = defaultOf(state, be); + } + + if (be instanceof ISpecialBlockEntityItemRequirement specialBE) + requirement = requirement.union(specialBE.getRequiredItems(state)); + + return requirement; + } + + private static ItemRequirement defaultOf(BlockState state, BlockEntity be) { + Block block = state.getBlock(); + if (block == Blocks.AIR) + return NONE; + + Item item = block.asItem(); + if (item == Items.AIR) + return INVALID; + + // double slab needs two items + if (state.hasProperty(BlockStateProperties.SLAB_TYPE) + && state.getValue(BlockStateProperties.SLAB_TYPE) == SlabType.DOUBLE) + return new ItemRequirement(ItemUseType.CONSUME, new ItemStack(item, 2)); + if (block instanceof TurtleEggBlock) + return new ItemRequirement(ItemUseType.CONSUME, new ItemStack(item, state.getValue(TurtleEggBlock.EGGS) + .intValue())); + if (block instanceof SeaPickleBlock) + return new ItemRequirement(ItemUseType.CONSUME, new ItemStack(item, state.getValue(SeaPickleBlock.PICKLES) + .intValue())); + if (block instanceof SnowLayerBlock) + return new ItemRequirement(ItemUseType.CONSUME, new ItemStack(item, state.getValue(SnowLayerBlock.LAYERS) + .intValue())); + if (block instanceof FarmBlock || block instanceof DirtPathBlock) + return new ItemRequirement(ItemUseType.CONSUME, Items.DIRT); + if (block instanceof AbstractBannerBlock && be instanceof BannerBlockEntity bannerBE) + return new ItemRequirement(new StrictNbtStackRequirement(bannerBE.getItem(), ItemUseType.CONSUME)); + + return new ItemRequirement(ItemUseType.CONSUME, item); + } + + public static ItemRequirement of(Entity entity) { + if (entity instanceof ISpecialEntityItemRequirement specialEntity) + return specialEntity.getRequiredItems(); + + if (entity instanceof ItemFrame itemFrame) { + ItemStack frame = new ItemStack(Items.ITEM_FRAME); + ItemStack displayedItem = NBTProcessors.withUnsafeNBTDiscarded(itemFrame.getItem()); + if (displayedItem.isEmpty()) + return new ItemRequirement(ItemUseType.CONSUME, Items.ITEM_FRAME); + return new ItemRequirement(List.of(new ItemRequirement.StackRequirement(frame, ItemUseType.CONSUME), + new ItemRequirement.StrictNbtStackRequirement(displayedItem, ItemUseType.CONSUME))); + } + + if (entity instanceof ArmorStand armorStand) { + List requirements = new ArrayList<>(); + requirements.add(new StackRequirement(new ItemStack(Items.ARMOR_STAND), ItemUseType.CONSUME)); + armorStand.getAllSlots() + .forEach(s -> requirements + .add(new StrictNbtStackRequirement(NBTProcessors.withUnsafeNBTDiscarded(s), ItemUseType.CONSUME))); + return new ItemRequirement(requirements); + } + + return INVALID; + } + + public boolean isEmpty() { + return NONE == this; + } + + public boolean isInvalid() { + return INVALID == this; + } + + public List getRequiredItems() { + return requiredItems; + } + + public ItemRequirement union(ItemRequirement other) { + if (this.isInvalid() || other.isInvalid()) + return INVALID; + if (this.isEmpty()) + return other; + if (other.isEmpty()) + return this; + + return new ItemRequirement(Stream.concat(requiredItems.stream(), other.requiredItems.stream()) + .collect(Collectors.toList())); + } + + public enum ItemUseType { + CONSUME, DAMAGE + } + + public static class StackRequirement { + public final ItemStack stack; + public final ItemUseType usage; + + public StackRequirement(ItemStack stack, ItemUseType usage) { + this.stack = stack; + this.usage = usage; + } + + public boolean matches(ItemStack other) { + return stack.sameItem(other); + } + } + + public static class StrictNbtStackRequirement extends StackRequirement { + public StrictNbtStackRequirement(ItemStack stack, ItemUseType usage) { + super(stack, usage); + } + + @Override + public boolean matches(ItemStack other) { + return ItemStack.isSameItemSameTags(stack, other); + } + } +} diff --git a/src/main/java/com/simibubi/create/content/schematics/block/SchematicTableBlock.java b/src/main/java/com/simibubi/create/content/schematics/table/SchematicTableBlock.java similarity index 80% rename from src/main/java/com/simibubi/create/content/schematics/block/SchematicTableBlock.java rename to src/main/java/com/simibubi/create/content/schematics/table/SchematicTableBlock.java index 6c25ab9e1..761de4383 100644 --- a/src/main/java/com/simibubi/create/content/schematics/block/SchematicTableBlock.java +++ b/src/main/java/com/simibubi/create/content/schematics/table/SchematicTableBlock.java @@ -1,8 +1,8 @@ -package com.simibubi.create.content.schematics.block; +package com.simibubi.create.content.schematics.table; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.item.ItemHelper; import net.minecraft.core.BlockPos; @@ -25,7 +25,7 @@ import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraftforge.network.NetworkHooks; -public class SchematicTableBlock extends HorizontalDirectionalBlock implements ITE { +public class SchematicTableBlock extends HorizontalDirectionalBlock implements IBE { public SchematicTableBlock(Properties properties) { super(properties); @@ -63,9 +63,8 @@ public class SchematicTableBlock extends HorizontalDirectionalBlock implements I BlockHitResult hit) { if (worldIn.isClientSide) return InteractionResult.SUCCESS; - - withTileEntityDo(worldIn, pos, - te -> NetworkHooks.openScreen((ServerPlayer) player, te, te::sendToContainer)); + withBlockEntityDo(worldIn, pos, + be -> NetworkHooks.openScreen((ServerPlayer) player, be, be::sendToMenu)); return InteractionResult.SUCCESS; } @@ -74,18 +73,18 @@ public class SchematicTableBlock extends HorizontalDirectionalBlock implements I if (!state.hasBlockEntity() || state.getBlock() == newState.getBlock()) return; - withTileEntityDo(worldIn, pos, te -> ItemHelper.dropContents(worldIn, pos, te.inventory)); + withBlockEntityDo(worldIn, pos, be -> ItemHelper.dropContents(worldIn, pos, be.inventory)); worldIn.removeBlockEntity(pos); } @Override - public Class getTileEntityClass() { - return SchematicTableTileEntity.class; + public Class getBlockEntityClass() { + return SchematicTableBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.SCHEMATIC_TABLE.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.SCHEMATIC_TABLE.get(); } @Override diff --git a/src/main/java/com/simibubi/create/content/schematics/table/SchematicTableBlockEntity.java b/src/main/java/com/simibubi/create/content/schematics/table/SchematicTableBlockEntity.java new file mode 100644 index 000000000..92eb5f38f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/schematics/table/SchematicTableBlockEntity.java @@ -0,0 +1,131 @@ +package com.simibubi.create.content.schematics.table; + +import java.util.List; + +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.IInteractionChecker; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +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.item.ItemStack; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.items.ItemStackHandler; + +public class SchematicTableBlockEntity extends SmartBlockEntity implements MenuProvider, IInteractionChecker { + + public SchematicTableInventory inventory; + public boolean isUploading; + public String uploadingSchematic; + public float uploadingProgress; + public boolean sendUpdate; + + public class SchematicTableInventory extends ItemStackHandler { + public SchematicTableInventory() { + super(2); + } + + @Override + protected void onContentsChanged(int slot) { + super.onContentsChanged(slot); + setChanged(); + } + } + + public SchematicTableBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + inventory = new SchematicTableInventory(); + uploadingSchematic = null; + uploadingProgress = 0; + } + + public void sendToMenu(FriendlyByteBuf buffer) { + buffer.writeBlockPos(getBlockPos()); + buffer.writeNbt(getUpdateTag()); + } + + @Override + protected void read(CompoundTag compound, boolean clientPacket) { + inventory.deserializeNBT(compound.getCompound("Inventory")); + super.read(compound, clientPacket); + + if (!clientPacket) + return; + if (compound.contains("Uploading")) { + isUploading = true; + uploadingSchematic = compound.getString("Schematic"); + uploadingProgress = compound.getFloat("Progress"); + } else { + isUploading = false; + uploadingSchematic = null; + uploadingProgress = 0; + } + } + + @Override + protected void write(CompoundTag compound, boolean clientPacket) { + compound.put("Inventory", inventory.serializeNBT()); + super.write(compound, clientPacket); + + if (clientPacket && isUploading) { + compound.putBoolean("Uploading", true); + compound.putString("Schematic", uploadingSchematic); + compound.putFloat("Progress", uploadingProgress); + } + } + + @Override + public void tick() { + // Update Client block entity + if (sendUpdate) { + sendUpdate = false; + level.sendBlockUpdated(worldPosition, getBlockState(), getBlockState(), 6); + } + } + + public void startUpload(String schematic) { + isUploading = true; + uploadingProgress = 0; + uploadingSchematic = schematic; + sendUpdate = true; + inventory.setStackInSlot(0, ItemStack.EMPTY); + } + + public void finishUpload() { + isUploading = false; + uploadingProgress = 0; + uploadingSchematic = null; + sendUpdate = true; + } + + @Override + public AbstractContainerMenu createMenu(int id, Inventory inv, Player player) { + return SchematicTableMenu.create(id, inv, this); + } + + @Override + public Component getDisplayName() { + return Lang.translateDirect("gui.schematicTable.title"); + } + + @Override + public boolean canPlayerUse(Player player) { + if (level == null || level.getBlockEntity(worldPosition) != this) { + return false; + } + return player.distanceToSqr(worldPosition.getX() + 0.5D, worldPosition.getY() + 0.5D, + worldPosition.getZ() + 0.5D) <= 64.0D; + } + + @Override + public void addBehaviours(List behaviours) {} + +} diff --git a/src/main/java/com/simibubi/create/content/schematics/table/SchematicTableMenu.java b/src/main/java/com/simibubi/create/content/schematics/table/SchematicTableMenu.java new file mode 100644 index 000000000..ea6841b83 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/schematics/table/SchematicTableMenu.java @@ -0,0 +1,105 @@ +package com.simibubi.create.content.schematics.table; + +import com.simibubi.create.AllItems; +import com.simibubi.create.AllMenuTypes; +import com.simibubi.create.foundation.gui.menu.MenuBase; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.entity.player.Inventory; +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 net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraftforge.items.SlotItemHandler; + +public class SchematicTableMenu extends MenuBase { + + private Slot inputSlot; + private Slot outputSlot; + + public SchematicTableMenu(MenuType type, int id, Inventory inv, FriendlyByteBuf extraData) { + super(type, id, inv, extraData); + } + + public SchematicTableMenu(MenuType type, int id, Inventory inv, SchematicTableBlockEntity be) { + super(type, id, inv, be); + } + + public static SchematicTableMenu create(int id, Inventory inv, SchematicTableBlockEntity be) { + return new SchematicTableMenu(AllMenuTypes.SCHEMATIC_TABLE.get(), id, inv, be); + } + + public boolean canWrite() { + return inputSlot.hasItem() && !outputSlot.hasItem(); + } + + @Override + public ItemStack quickMoveStack(Player playerIn, int index) { + Slot clickedSlot = getSlot(index); + if (!clickedSlot.hasItem()) + return ItemStack.EMPTY; + + ItemStack stack = clickedSlot.getItem(); + if (index < 2) + moveItemStackTo(stack, 2, slots.size(), false); + else + moveItemStackTo(stack, 0, 1, false); + + return ItemStack.EMPTY; + } + + @Override + protected SchematicTableBlockEntity createOnClient(FriendlyByteBuf extraData) { + ClientLevel world = Minecraft.getInstance().level; + BlockEntity blockEntity = world.getBlockEntity(extraData.readBlockPos()); + if (blockEntity instanceof SchematicTableBlockEntity schematicTable) { + schematicTable.readClient(extraData.readNbt()); + return schematicTable; + } + return null; + } + + @Override + protected void initAndReadInventory(SchematicTableBlockEntity contentHolder) { + } + + @Override + protected void addSlots() { + inputSlot = new SlotItemHandler(contentHolder.inventory, 0, 21, 57) { + @Override + public boolean mayPlace(ItemStack stack) { + return AllItems.EMPTY_SCHEMATIC.isIn(stack) || AllItems.SCHEMATIC_AND_QUILL.isIn(stack) + || AllItems.SCHEMATIC.isIn(stack); + } + }; + + outputSlot = new SlotItemHandler(contentHolder.inventory, 1, 166, 57) { + @Override + public boolean mayPlace(ItemStack stack) { + return false; + } + }; + + addSlot(inputSlot); + addSlot(outputSlot); + + // player Slots + for (int row = 0; row < 3; ++row) { + for (int col = 0; col < 9; ++col) { + this.addSlot(new Slot(player.getInventory(), col + row * 9 + 9, 38 + col * 18, 105 + row * 18)); + } + } + + for (int hotbarSlot = 0; hotbarSlot < 9; ++hotbarSlot) { + this.addSlot(new Slot(player.getInventory(), hotbarSlot, 38 + hotbarSlot * 18, 163)); + } + } + + @Override + protected void saveData(SchematicTableBlockEntity contentHolder) { + } + +} diff --git a/src/main/java/com/simibubi/create/content/schematics/block/SchematicTableScreen.java b/src/main/java/com/simibubi/create/content/schematics/table/SchematicTableScreen.java similarity index 95% rename from src/main/java/com/simibubi/create/content/schematics/block/SchematicTableScreen.java rename to src/main/java/com/simibubi/create/content/schematics/table/SchematicTableScreen.java index 04aa4efb7..8c9ccc713 100644 --- a/src/main/java/com/simibubi/create/content/schematics/block/SchematicTableScreen.java +++ b/src/main/java/com/simibubi/create/content/schematics/table/SchematicTableScreen.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.schematics.block; +package com.simibubi.create.content.schematics.table; import static com.simibubi.create.foundation.gui.AllGuiTextures.PLAYER_INVENTORY; import static com.simibubi.create.foundation.gui.AllGuiTextures.SCHEMATIC_TABLE_PROGRESS; @@ -11,11 +11,11 @@ import com.google.common.collect.ImmutableList; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllBlocks; import com.simibubi.create.CreateClient; -import com.simibubi.create.content.schematics.ClientSchematicLoader; +import com.simibubi.create.content.schematics.client.ClientSchematicLoader; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; -import com.simibubi.create.foundation.gui.container.AbstractSimiContainerScreen; import com.simibubi.create.foundation.gui.element.GuiGameElement; +import com.simibubi.create.foundation.gui.menu.AbstractSimiContainerScreen; import com.simibubi.create.foundation.gui.widget.IconButton; import com.simibubi.create.foundation.gui.widget.Label; import com.simibubi.create.foundation.gui.widget.ScrollInput; @@ -30,7 +30,7 @@ import net.minecraft.util.Mth; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.item.ItemStack; -public class SchematicTableScreen extends AbstractSimiContainerScreen { +public class SchematicTableScreen extends AbstractSimiContainerScreen { private final Component uploading = Lang.translateDirect("gui.schematicTable.uploading"); private final Component finished = Lang.translateDirect("gui.schematicTable.finished"); @@ -55,9 +55,9 @@ public class SchematicTableScreen extends AbstractSimiContainerScreen extraAreas = Collections.emptyList(); - public SchematicTableScreen(SchematicTableContainer container, Inventory playerInventory, + public SchematicTableScreen(SchematicTableMenu menu, Inventory playerInventory, Component title) { - super(container, playerInventory, title); + super(menu, playerInventory, title); background = AllGuiTextures.SCHEMATIC_TABLE; } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/CameraDistanceModifier.java b/src/main/java/com/simibubi/create/content/trains/CameraDistanceModifier.java similarity index 82% rename from src/main/java/com/simibubi/create/content/logistics/trains/CameraDistanceModifier.java rename to src/main/java/com/simibubi/create/content/trains/CameraDistanceModifier.java index 07bb9edf4..fb3ffc649 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/CameraDistanceModifier.java +++ b/src/main/java/com/simibubi/create/content/trains/CameraDistanceModifier.java @@ -1,8 +1,8 @@ -package com.simibubi.create.content.logistics.trains; +package com.simibubi.create.content.trains; -import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import com.simibubi.create.infrastructure.config.AllConfigs; public class CameraDistanceModifier { @@ -25,7 +25,7 @@ public class CameraDistanceModifier { } public static void zoomOut() { - zoomOut(AllConfigs.CLIENT.mountedZoomMultiplier.getF()); + zoomOut(AllConfigs.client().mountedZoomMultiplier.getF()); } public static void zoomOut(float targetMultiplier) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/particle/CubeParticle.java b/src/main/java/com/simibubi/create/content/trains/CubeParticle.java similarity index 98% rename from src/main/java/com/simibubi/create/content/contraptions/particle/CubeParticle.java rename to src/main/java/com/simibubi/create/content/trains/CubeParticle.java index 59f36cb06..d41049dad 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/particle/CubeParticle.java +++ b/src/main/java/com/simibubi/create/content/trains/CubeParticle.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.particle; +package com.simibubi.create.content.trains; import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; diff --git a/src/main/java/com/simibubi/create/content/contraptions/particle/CubeParticleData.java b/src/main/java/com/simibubi/create/content/trains/CubeParticleData.java similarity index 96% rename from src/main/java/com/simibubi/create/content/contraptions/particle/CubeParticleData.java rename to src/main/java/com/simibubi/create/content/trains/CubeParticleData.java index 7bb7e5217..e17553e1a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/particle/CubeParticleData.java +++ b/src/main/java/com/simibubi/create/content/trains/CubeParticleData.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.contraptions.particle; +package com.simibubi.create.content.trains; import java.util.Locale; @@ -7,6 +7,7 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; import com.simibubi.create.AllParticleTypes; +import com.simibubi.create.foundation.particle.ICustomParticleData; import net.minecraft.client.particle.ParticleProvider; import net.minecraft.core.particles.ParticleOptions; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/GlobalRailwayManager.java b/src/main/java/com/simibubi/create/content/trains/GlobalRailwayManager.java similarity index 84% rename from src/main/java/com/simibubi/create/content/logistics/trains/GlobalRailwayManager.java rename to src/main/java/com/simibubi/create/content/trains/GlobalRailwayManager.java index 990e876cb..b20f8b9f7 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/GlobalRailwayManager.java +++ b/src/main/java/com/simibubi/create/content/trains/GlobalRailwayManager.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains; +package com.simibubi.create.content.trains; import java.util.ArrayList; import java.util.Collections; @@ -14,14 +14,18 @@ import javax.annotation.Nullable; import org.apache.commons.lang3.mutable.MutableObject; +import com.simibubi.create.AllPackets; import com.simibubi.create.CreateClient; -import com.simibubi.create.content.contraptions.KineticDebugger; -import com.simibubi.create.content.logistics.trains.entity.Train; -import com.simibubi.create.content.logistics.trains.entity.TrainPacket; -import com.simibubi.create.content.logistics.trains.management.display.GlobalTrainDisplayData; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalEdgeGroup; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.content.kinetics.KineticDebugger; +import com.simibubi.create.content.trains.display.GlobalTrainDisplayData; +import com.simibubi.create.content.trains.entity.Train; +import com.simibubi.create.content.trains.entity.TrainPacket; +import com.simibubi.create.content.trains.graph.TrackGraph; +import com.simibubi.create.content.trains.graph.TrackGraphSync; +import com.simibubi.create.content.trains.graph.TrackGraphVisualizer; +import com.simibubi.create.content.trains.graph.TrackNodeLocation; +import com.simibubi.create.content.trains.signal.SignalEdgeGroup; +import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; @@ -63,7 +67,7 @@ public class GlobalRailwayManager { .toList(), serverPlayer); for (Train train : trains.values()) - AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> serverPlayer), + AllPackets.getChannel().send(PacketDistributor.PLAYER.with(() -> serverPlayer), new TrainPacket(train, true)); } } @@ -123,7 +127,7 @@ public class GlobalRailwayManager { public TrackGraph getOrCreateGraph(UUID graphID, int netId) { return trackNetworks.computeIfAbsent(graphID, uid -> { TrackGraph trackGraph = new TrackGraph(graphID); - trackGraph.netId = netId; + trackGraph.setNetId(netId); return trackGraph; }); } @@ -228,7 +232,7 @@ public class GlobalRailwayManager { if (train.invalid) { iterator.remove(); trains.remove(train.id); - AllPackets.channel.send(PacketDistributor.ALL.noArg(), new TrainPacket(train, false)); + AllPackets.getChannel().send(PacketDistributor.ALL.noArg(), new TrainPacket(train, false)); continue; } @@ -244,7 +248,7 @@ public class GlobalRailwayManager { if (train.invalid) { iterator.remove(); trains.remove(train.id); - AllPackets.channel.send(PacketDistributor.ALL.noArg(), new TrainPacket(train, false)); + AllPackets.getChannel().send(PacketDistributor.ALL.noArg(), new TrainPacket(train, false)); continue; } @@ -265,11 +269,15 @@ public class GlobalRailwayManager { public void clientTick() { if (isTrackGraphDebugActive()) for (TrackGraph trackGraph : trackNetworks.values()) - TrackGraphVisualizer.debugViewGraph(trackGraph); + TrackGraphVisualizer.debugViewGraph(trackGraph, isTrackGraphDebugExtended()); } - + private static boolean isTrackGraphDebugActive() { - return KineticDebugger.isF3DebugModeActive() && AllConfigs.CLIENT.showTrackGraphOnF3.get(); + return KineticDebugger.isF3DebugModeActive() && AllConfigs.client().showTrackGraphOnF3.get(); + } + + private static boolean isTrackGraphDebugExtended() { + return AllConfigs.client().showExtendedTrackGraphOnF3.get(); } public GlobalRailwayManager sided(LevelAccessor level) { diff --git a/src/main/java/com/simibubi/create/content/trains/HonkPacket.java b/src/main/java/com/simibubi/create/content/trains/HonkPacket.java new file mode 100644 index 000000000..b5f8c3f84 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/HonkPacket.java @@ -0,0 +1,73 @@ +package com.simibubi.create.content.trains; + +import java.util.UUID; + +import com.simibubi.create.AllPackets; +import com.simibubi.create.Create; +import com.simibubi.create.content.trains.entity.Train; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraftforge.network.NetworkEvent.Context; +import net.minecraftforge.network.PacketDistributor; + +public class HonkPacket extends SimplePacketBase { + + UUID trainId; + boolean isHonk; + + public HonkPacket() {} + + public HonkPacket(Train train, boolean isHonk) { + trainId = train.id; + this.isHonk = isHonk; + } + + public HonkPacket(FriendlyByteBuf buffer) { + trainId = buffer.readUUID(); + isHonk = buffer.readBoolean(); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeUUID(trainId); + buffer.writeBoolean(isHonk); + } + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> { + ServerPlayer sender = context.getSender(); + boolean clientSide = sender == null; + Train train = Create.RAILWAYS.sided(clientSide ? null : sender.level).trains.get(trainId); + if (train == null) + return; + + if (clientSide) { + if (isHonk) + train.honkTicks = train.honkTicks == 0 ? 20 : 13; + else + train.honkTicks = train.honkTicks > 5 ? 6 : 0; + } else { + AllAdvancements.TRAIN_WHISTLE.awardTo(sender); + AllPackets.getChannel().send(PacketDistributor.ALL.noArg(), new HonkPacket(train, isHonk)); + } + + }); + return true; + } + + public static class Serverbound extends HonkPacket { + + public Serverbound(FriendlyByteBuf buffer) { + super(buffer); + } + + public Serverbound(Train train, boolean isHonk) { + super(train, isHonk); + } + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/RailwaySavedData.java b/src/main/java/com/simibubi/create/content/trains/RailwaySavedData.java similarity index 88% rename from src/main/java/com/simibubi/create/content/logistics/trains/RailwaySavedData.java rename to src/main/java/com/simibubi/create/content/trains/RailwaySavedData.java index a5b2c1fb3..3a3ee63a6 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/RailwaySavedData.java +++ b/src/main/java/com/simibubi/create/content/trains/RailwaySavedData.java @@ -1,14 +1,16 @@ -package com.simibubi.create.content.logistics.trains; +package com.simibubi.create.content.trains; import java.util.HashMap; import java.util.Map; import java.util.UUID; import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.entity.Train; -import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalBoundary; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalEdgeGroup; +import com.simibubi.create.content.trains.entity.Train; +import com.simibubi.create.content.trains.graph.DimensionPalette; +import com.simibubi.create.content.trains.graph.EdgePointType; +import com.simibubi.create.content.trains.graph.TrackGraph; +import com.simibubi.create.content.trains.signal.SignalBoundary; +import com.simibubi.create.content.trains.signal.SignalEdgeGroup; import com.simibubi.create.foundation.utility.NBTHelper; import net.minecraft.nbt.CompoundTag; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/TrainHUD.java b/src/main/java/com/simibubi/create/content/trains/TrainHUD.java similarity index 85% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/TrainHUD.java rename to src/main/java/com/simibubi/create/content/trains/TrainHUD.java index 3f9d39029..52e452142 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/TrainHUD.java +++ b/src/main/java/com/simibubi/create/content/trains/TrainHUD.java @@ -1,17 +1,19 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls; +package com.simibubi.create.content.trains; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.content.logistics.trains.entity.Carriage; -import com.simibubi.create.content.logistics.trains.entity.CarriageContraptionEntity; -import com.simibubi.create.content.logistics.trains.entity.Train; -import com.simibubi.create.foundation.config.AllConfigs; +import com.simibubi.create.AllPackets; +import com.simibubi.create.content.contraptions.actors.trainControls.ControlsBlock; +import com.simibubi.create.content.contraptions.actors.trainControls.ControlsHandler; +import com.simibubi.create.content.trains.entity.Carriage; +import com.simibubi.create.content.trains.entity.CarriageContraptionEntity; +import com.simibubi.create.content.trains.entity.Train; import com.simibubi.create.foundation.gui.AllGuiTextures; -import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.foundation.placement.PlacementHelpers; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.ControlsUtil; import com.simibubi.create.foundation.utility.animation.LerpedFloat; import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; -import com.simibubi.create.foundation.utility.placement.PlacementHelpers; +import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; @@ -60,7 +62,7 @@ public class TrainHUD { Train train = carriage.train; double value = - Math.abs(train.speed) / (train.maxSpeed() * AllConfigs.SERVER.trains.manualTrainSpeedModifier.getF()); + Math.abs(train.speed) / (train.maxSpeed() * AllConfigs.server().trains.manualTrainSpeedModifier.getF()); value = Mth.clamp(value + 0.05f, 0, 1); displayedSpeed.chase((int) (value * 18) / 18f, .5f, Chaser.EXP); @@ -73,14 +75,14 @@ public class TrainHUD { if (isSprintKeyPressed && honkPacketCooldown-- <= 0) { train.determineHonk(mc.level); if (train.lowHonk != null) { - AllPackets.channel.sendToServer(new HonkPacket.Serverbound(train, true)); + AllPackets.getChannel().sendToServer(new HonkPacket.Serverbound(train, true)); honkPacketCooldown = 5; usedToHonk = true; } } if (!isSprintKeyPressed && usedToHonk) { - AllPackets.channel.sendToServer(new HonkPacket.Serverbound(train, false)); + AllPackets.getChannel().sendToServer(new HonkPacket.Serverbound(train, false)); honkPacketCooldown = 0; usedToHonk = false; } @@ -94,13 +96,13 @@ public class TrainHUD { } if (hudPacketCooldown-- <= 0) { - AllPackets.channel.sendToServer(new TrainHUDUpdatePacket.Serverbound(train, editedThrottle)); + AllPackets.getChannel().sendToServer(new TrainHUDUpdatePacket.Serverbound(train, editedThrottle)); hudPacketCooldown = 5; } } private static Carriage getCarriage() { - if (!(ControlsHandler.entityRef.get() instanceof CarriageContraptionEntity cce)) + if (!(ControlsHandler.getContraption() instanceof CarriageContraptionEntity cce)) return null; return cce.getCarriage(); } @@ -111,7 +113,7 @@ public class TrainHUD { if (mc.options.hideGui || mc.gameMode.getPlayerMode() == GameType.SPECTATOR) return; - if (!(ControlsHandler.entityRef.get() instanceof CarriageContraptionEntity cce)) + if (!(ControlsHandler.getContraption() instanceof CarriageContraptionEntity cce)) return; Carriage carriage = cce.getCarriage(); if (carriage == null) @@ -120,7 +122,7 @@ public class TrainHUD { .getCameraEntity(); if (cameraEntity == null) return; - BlockPos localPos = ControlsHandler.controlsPos; + BlockPos localPos = ControlsHandler.getControlsPos(); if (localPos == null) return; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/TrainHUDUpdatePacket.java b/src/main/java/com/simibubi/create/content/trains/TrainHUDUpdatePacket.java similarity index 81% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/TrainHUDUpdatePacket.java rename to src/main/java/com/simibubi/create/content/trains/TrainHUDUpdatePacket.java index d70180213..c0c97fceb 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/interaction/controls/TrainHUDUpdatePacket.java +++ b/src/main/java/com/simibubi/create/content/trains/TrainHUDUpdatePacket.java @@ -1,10 +1,9 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls; +package com.simibubi.create.content.trains; import java.util.UUID; -import java.util.function.Supplier; import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.entity.Train; +import com.simibubi.create.content.trains.entity.Train; import com.simibubi.create.foundation.networking.SimplePacketBase; import net.minecraft.network.FriendlyByteBuf; @@ -47,10 +46,9 @@ public class TrainHUDUpdatePacket extends SimplePacketBase { } @Override - public void handle(Supplier context) { - Context c = context.get(); - c.enqueueWork(() -> { - ServerPlayer sender = c.getSender(); + public boolean handle(Context context) { + context.enqueueWork(() -> { + ServerPlayer sender = context.getSender(); boolean clientSide = sender == null; Train train = Create.RAILWAYS.sided(clientSide ? null : sender.level).trains.get(trainId); if (train == null) @@ -62,9 +60,8 @@ public class TrainHUDUpdatePacket extends SimplePacketBase { train.speed = speed; train.fuelTicks = fuelTicks; } - }); - c.setPacketHandled(true); + return true; } public static class Serverbound extends TrainHUDUpdatePacket { diff --git a/src/main/java/com/simibubi/create/content/trains/bogey/AbstractBogeyBlock.java b/src/main/java/com/simibubi/create/content/trains/bogey/AbstractBogeyBlock.java new file mode 100644 index 000000000..75e5576e0 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/bogey/AbstractBogeyBlock.java @@ -0,0 +1,360 @@ +package com.simibubi.create.content.trains.bogey; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.EnumSet; +import java.util.List; +import java.util.Optional; +import java.util.Set; + +import javax.annotation.Nullable; + +import org.jetbrains.annotations.NotNull; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.math.Axis; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllBogeyStyles; +import com.simibubi.create.AllItems; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.content.schematics.requirement.ISpecialBlockItemRequirement; +import com.simibubi.create.content.schematics.requirement.ItemRequirement; +import com.simibubi.create.content.trains.entity.Carriage; +import com.simibubi.create.content.trains.entity.CarriageBogey; +import com.simibubi.create.content.trains.entity.TravellingPoint; +import com.simibubi.create.content.trains.track.TrackMaterial; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.block.ProperWaterloggedBlock; +import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.RegisteredObjects; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; +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.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.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.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.EnumProperty; +import net.minecraft.world.level.block.state.properties.Property; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.registries.ForgeRegistries; + +public abstract class AbstractBogeyBlock extends Block implements IBE, ProperWaterloggedBlock, ISpecialBlockItemRequirement, IWrenchable { + public static final EnumProperty AXIS = BlockStateProperties.HORIZONTAL_AXIS; + static final List BOGEYS = new ArrayList<>(); + public BogeySizes.BogeySize size; + + + public AbstractBogeyBlock(Properties pProperties, BogeySizes.BogeySize size) { + super(pProperties); + registerDefaultState(defaultBlockState().setValue(WATERLOGGED, false)); + this.size = size; + } + + public boolean isOnIncompatibleTrack(Carriage carriage, boolean leading) { + TravellingPoint point = leading ? carriage.getLeadingPoint() : carriage.getTrailingPoint(); + CarriageBogey bogey = leading ? carriage.leadingBogey() : carriage.trailingBogey(); + return point.edge.getTrackMaterial().trackType != getTrackType(bogey.getStyle()); + } + + public Set getValidPathfindingTypes(BogeyStyle style) { + return ImmutableSet.of(getTrackType(style)); + } + + public abstract TrackMaterial.TrackType getTrackType(BogeyStyle style); + + /** + * Only for internal Create use. If you have your own style set, do not call this method + */ + @Deprecated + public static void registerStandardBogey(ResourceLocation block) { + BOGEYS.add(block); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder builder) { + builder.add(AXIS, WATERLOGGED); + super.createBlockStateDefinition(builder); + } + + @Override + public BlockState updateShape(BlockState pState, Direction pDirection, BlockState pNeighborState, + LevelAccessor pLevel, BlockPos pCurrentPos, BlockPos pNeighborPos) { + updateWater(pLevel, pState, pCurrentPos); + return pState; + } + + @Override + public FluidState getFluidState(BlockState pState) { + return fluidState(pState); + } + + static final EnumSet STICKY_X = EnumSet.of(Direction.EAST, Direction.WEST); + static final EnumSet STICKY_Z = EnumSet.of(Direction.SOUTH, Direction.NORTH); + + public EnumSet getStickySurfaces(BlockGetter world, BlockPos pos, BlockState state) { + return state.getValue(BlockStateProperties.HORIZONTAL_AXIS) == Direction.Axis.X ? STICKY_X : STICKY_Z; + } + + public abstract double getWheelPointSpacing(); + + public abstract double getWheelRadius(); + + public Vec3 getConnectorAnchorOffset(boolean upsideDown) { + return getConnectorAnchorOffset(); + } + + /** + * This should be implemented, but not called directly + */ + protected abstract Vec3 getConnectorAnchorOffset(); + + public boolean allowsSingleBogeyCarriage() { + return true; + } + + public abstract BogeyStyle getDefaultStyle(); + + /** + * Legacy system doesn't capture bogey block entities when constructing a train + */ + public boolean captureBlockEntityForTrain() { + return false; + } + + @OnlyIn(Dist.CLIENT) + public void render(@Nullable BlockState state, float wheelAngle, PoseStack ms, float partialTicks, + MultiBufferSource buffers, int light, int overlay, BogeyStyle style, CompoundTag bogeyData) { + if (style == null) + style = getDefaultStyle(); + + final Optional commonRenderer + = style.getInWorldCommonRenderInstance(); + final BogeyRenderer renderer = style.getInWorldRenderInstance(this.getSize()); + if (state != null) { + ms.translate(.5f, .5f, .5f); + if (state.getValue(AXIS) == Direction.Axis.X) + ms.mulPose(Axis.YP.rotationDegrees(90)); + } + ms.translate(0, -1.5 - 1 / 128f, 0); + VertexConsumer vb = buffers.getBuffer(RenderType.cutoutMipped()); + if (bogeyData == null) + bogeyData = new CompoundTag(); + renderer.render(bogeyData, wheelAngle, ms, light, vb, state == null); + CompoundTag finalBogeyData = bogeyData; + commonRenderer.ifPresent(common -> + common.render(finalBogeyData, wheelAngle, ms, light, vb, state == null)); + } + + public BogeySizes.BogeySize getSize() { + return this.size; + } + + public Direction getBogeyUpDirection() { + return Direction.UP; + } + + public boolean isTrackAxisAlongFirstCoordinate(BlockState state) { + return state.getValue(AXIS) == Direction.Axis.X; + } + + @Nullable + public BlockState getMatchingBogey(Direction upDirection, boolean axisAlongFirst) { + if (upDirection != Direction.UP) + return null; + return defaultBlockState().setValue(AXIS, axisAlongFirst ? Direction.Axis.X : Direction.Axis.Z); + } + + @Override + public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, + BlockHitResult hit) { + if (level.isClientSide) + return InteractionResult.PASS; + ItemStack stack = player.getItemInHand(hand); + + if (!player.isShiftKeyDown() && stack.is(AllItems.WRENCH.get()) && !player.getCooldowns().isOnCooldown(stack.getItem()) + && AllBogeyStyles.BOGEY_STYLES.size() > 1) { + + BlockEntity be = level.getBlockEntity(pos); + + if (!(be instanceof AbstractBogeyBlockEntity sbbe)) + return InteractionResult.FAIL; + + player.getCooldowns().addCooldown(stack.getItem(), 20); + BogeyStyle currentStyle = sbbe.getStyle(); + + BogeySizes.BogeySize size = getSize(); + + BogeyStyle style = this.getNextStyle(currentStyle); + if (style == currentStyle) + return InteractionResult.PASS; + + Set validSizes = style.validSizes(); + + for (int i = 0; i < BogeySizes.count(); i++) { + if (validSizes.contains(size)) break; + size = size.increment(); + } + + sbbe.setBogeyStyle(style); + + CompoundTag defaultData = style.defaultData; + sbbe.setBogeyData(sbbe.getBogeyData().merge(defaultData)); + + if (size == getSize()) { + player.displayClientMessage(Lang.translateDirect("bogey.style.updated_style") + .append(": ").append(style.displayName), true); + } else { + CompoundTag oldData = sbbe.getBogeyData(); + level.setBlock(pos, this.getStateOfSize(sbbe, size), 3); + BlockEntity newBlockEntity = level.getBlockEntity(pos); + if (!(newBlockEntity instanceof AbstractBogeyBlockEntity newBlockEntity1)) + return InteractionResult.FAIL; + newBlockEntity1.setBogeyData(oldData); + player.displayClientMessage(Lang.translateDirect("bogey.style.updated_style_and_size") + .append(": ").append(style.displayName), true); + } + + return InteractionResult.CONSUME; + } + + return InteractionResult.PASS; + } + + /** + * If, instead of using the style-based cycling system you prefer to use separate blocks, return them from this method + */ + protected List getBogeyBlockCycle() { + return BOGEYS; + } + + + @Override + public BlockState getRotatedBlockState(BlockState state, Direction targetedFace) { + Block block = state.getBlock(); + List bogeyCycle = getBogeyBlockCycle(); + int indexOf = bogeyCycle.indexOf(RegisteredObjects.getKeyOrThrow(block)); + if (indexOf == -1) + return state; + int index = (indexOf + 1) % bogeyCycle.size(); + Direction bogeyUpDirection = getBogeyUpDirection(); + boolean trackAxisAlongFirstCoordinate = isTrackAxisAlongFirstCoordinate(state); + + while (index != indexOf) { + ResourceLocation id = bogeyCycle.get(index); + Block newBlock = ForgeRegistries.BLOCKS.getValue(id); + if (newBlock instanceof AbstractBogeyBlock bogey) { + BlockState matchingBogey = bogey.getMatchingBogey(bogeyUpDirection, trackAxisAlongFirstCoordinate); + if (matchingBogey != null) + return copyProperties(state, matchingBogey); + } + index = (index + 1) % bogeyCycle.size(); + } + + return state; + } + + public BlockState getNextSize(Level level, BlockPos pos) { + BlockEntity be = level.getBlockEntity(pos); + if (be instanceof AbstractBogeyBlockEntity sbbe) + return this.getNextSize(sbbe); + return level.getBlockState(pos); + } + + /** + * List of BlockState Properties to copy between sizes + */ + public List> propertiesToCopy() { + return ImmutableList.of(WATERLOGGED, AXIS); + } + + // generic method needed to satisfy Property and BlockState's generic requirements + private > BlockState copyProperty(BlockState source, BlockState target, Property property) { + if (source.hasProperty(property) && target.hasProperty(property)) { + return target.setValue(property, source.getValue(property)); + } + return target; + } + + private BlockState copyProperties(BlockState source, BlockState target) { + for (Property property : propertiesToCopy()) + target = copyProperty(source, target, property); + return target; + } + + public BlockState getNextSize(AbstractBogeyBlockEntity sbte) { + BogeySizes.BogeySize size = this.getSize(); + BogeyStyle style = sbte.getStyle(); + BlockState nextBlock = style.getNextBlock(size).defaultBlockState(); + nextBlock = copyProperties(sbte.getBlockState(), nextBlock); + return nextBlock; + } + + public BlockState getStateOfSize(AbstractBogeyBlockEntity sbte, BogeySizes.BogeySize size) { + BogeyStyle style = sbte.getStyle(); + BlockState state = style.getBlockOfSize(size).defaultBlockState(); + return copyProperties(sbte.getBlockState(), state); + } + + public BogeyStyle getNextStyle(Level level, BlockPos pos) { + BlockEntity te = level.getBlockEntity(pos); + if (te instanceof AbstractBogeyBlockEntity sbbe) + return this.getNextStyle(sbbe.getStyle()); + return getDefaultStyle(); + } + + public BogeyStyle getNextStyle(BogeyStyle style) { + Collection allStyles = style.getCycleGroup().values(); + if (allStyles.size() <= 1) + return style; + List list = new ArrayList<>(allStyles); + return Iterate.cycleValue(list, style); + } + + + @Override + public @NotNull BlockState rotate(@NotNull BlockState pState, Rotation pRotation) { + return switch (pRotation) { + case COUNTERCLOCKWISE_90, CLOCKWISE_90 -> pState.cycle(AXIS); + default -> pState; + }; + } + + @Override + public ItemRequirement getRequiredItems(BlockState state, BlockEntity te) { + return new ItemRequirement(ItemRequirement.ItemUseType.CONSUME, AllBlocks.RAILWAY_CASING.asStack()); + } + + public boolean canBeUpsideDown() { + return false; + } + + public boolean isUpsideDown(BlockState state) { + return false; + } + + public BlockState getVersion(BlockState base, boolean upsideDown) { + return base; + } +} diff --git a/src/main/java/com/simibubi/create/content/trains/bogey/AbstractBogeyBlockEntity.java b/src/main/java/com/simibubi/create/content/trains/bogey/AbstractBogeyBlockEntity.java new file mode 100644 index 000000000..59985cc7a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/bogey/AbstractBogeyBlockEntity.java @@ -0,0 +1,118 @@ +package com.simibubi.create.content.trains.bogey; + +import static com.simibubi.create.content.trains.entity.CarriageBogey.UPSIDE_DOWN_KEY; + +import org.jetbrains.annotations.NotNull; + +import com.simibubi.create.AllBogeyStyles; +import com.simibubi.create.foundation.blockEntity.CachedRenderBBBlockEntity; +import com.simibubi.create.foundation.utility.NBTHelper; +import com.simibubi.create.foundation.utility.animation.LerpedFloat; + +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.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; + +public abstract class AbstractBogeyBlockEntity extends CachedRenderBBBlockEntity { + public static final String BOGEY_STYLE_KEY = "BogeyStyle"; + public static final String BOGEY_DATA_KEY = "BogeyData"; + + private CompoundTag bogeyData; + + public AbstractBogeyBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + public abstract BogeyStyle getDefaultStyle(); + + public CompoundTag getBogeyData() { + if (this.bogeyData == null || !this.bogeyData.contains(BOGEY_STYLE_KEY)) + this.bogeyData = this.createBogeyData(); + return this.bogeyData; + } + + public void setBogeyData(@NotNull CompoundTag newData) { + if (!newData.contains(BOGEY_STYLE_KEY)) { + ResourceLocation style = getDefaultStyle().name; + NBTHelper.writeResourceLocation(newData, BOGEY_STYLE_KEY, style); + } + this.bogeyData = newData; + } + + public void setBogeyStyle(@NotNull BogeyStyle style) { + ResourceLocation location = style.name; + CompoundTag data = this.getBogeyData(); + NBTHelper.writeResourceLocation(data, BOGEY_STYLE_KEY, location); + markUpdated(); + } + + @NotNull + public BogeyStyle getStyle() { + CompoundTag data = this.getBogeyData(); + ResourceLocation currentStyle = NBTHelper.readResourceLocation(data, BOGEY_STYLE_KEY); + BogeyStyle style = AllBogeyStyles.BOGEY_STYLES.get(currentStyle); + if (style == null) { + setBogeyStyle(getDefaultStyle()); + return getStyle(); + } + return style; + } + + @Override + protected void saveAdditional(@NotNull CompoundTag pTag) { + CompoundTag data = this.getBogeyData(); + if (data != null) pTag.put(BOGEY_DATA_KEY, data); // Now contains style + super.saveAdditional(pTag); + } + + @Override + public void load(CompoundTag pTag) { + if (pTag.contains(BOGEY_DATA_KEY)) + this.bogeyData = pTag.getCompound(BOGEY_DATA_KEY); + else + this.bogeyData = this.createBogeyData(); + super.load(pTag); + } + + private CompoundTag createBogeyData() { + CompoundTag nbt = new CompoundTag(); + NBTHelper.writeResourceLocation(nbt, BOGEY_STYLE_KEY, getDefaultStyle().name); + boolean upsideDown = false; + if (getBlockState().getBlock() instanceof AbstractBogeyBlock bogeyBlock) + upsideDown = bogeyBlock.isUpsideDown(getBlockState()); + nbt.putBoolean(UPSIDE_DOWN_KEY, upsideDown); + return nbt; + } + + @Override + protected AABB createRenderBoundingBox() { + return super.createRenderBoundingBox().inflate(2); + } + + // Ponder + LerpedFloat virtualAnimation = LerpedFloat.angular(); + + public float getVirtualAngle(float partialTicks) { + return virtualAnimation.getValue(partialTicks); + } + + public void animate(float distanceMoved) { + BlockState blockState = getBlockState(); + if (!(blockState.getBlock() instanceof AbstractBogeyBlock type)) + return; + double angleDiff = 360 * distanceMoved / (Math.PI * 2 * type.getWheelRadius()); + double newWheelAngle = (virtualAnimation.getValue() - angleDiff) % 360; + virtualAnimation.setValue(newWheelAngle); + } + + private void markUpdated() { + setChanged(); + Level level = getLevel(); + if (level != null) + getLevel().sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 3); + } +} diff --git a/src/main/java/com/simibubi/create/content/trains/bogey/BackupBogeyRenderer.java b/src/main/java/com/simibubi/create/content/trains/bogey/BackupBogeyRenderer.java new file mode 100644 index 000000000..0ba43df26 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/bogey/BackupBogeyRenderer.java @@ -0,0 +1,21 @@ +package com.simibubi.create.content.trains.bogey; + +import com.jozufozu.flywheel.api.MaterialManager; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; + +import net.minecraft.nbt.CompoundTag; + +public class BackupBogeyRenderer extends BogeyRenderer.CommonRenderer { + public static BackupBogeyRenderer INSTANCE = new BackupBogeyRenderer(); + + @Override + public void render(CompoundTag bogeyData, float wheelAngle, PoseStack ms, int light, VertexConsumer vb, boolean inContraption) { + + } + + @Override + public void initialiseContraptionModelData(MaterialManager materialManager) { + + } +} diff --git a/src/main/java/com/simibubi/create/content/trains/bogey/BogeyBlockEntityRenderer.java b/src/main/java/com/simibubi/create/content/trains/bogey/BogeyBlockEntityRenderer.java new file mode 100644 index 000000000..e570fa26b --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/bogey/BogeyBlockEntityRenderer.java @@ -0,0 +1,26 @@ +package com.simibubi.create.content.trains.bogey; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; + +public class BogeyBlockEntityRenderer extends SafeBlockEntityRenderer { + + public BogeyBlockEntityRenderer(BlockEntityRendererProvider.Context context) {} + + @Override + protected void renderSafe(T be, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light, + int overlay) { + BlockState blockState = be.getBlockState(); + if (be instanceof AbstractBogeyBlockEntity sbbe) { + float angle = sbbe.getVirtualAngle(partialTicks); + if (blockState.getBlock() instanceof AbstractBogeyBlock bogey) + bogey.render(blockState, angle, ms, partialTicks, buffer, light, overlay, sbbe.getStyle(), sbbe.getBogeyData()); + } + } + +} diff --git a/src/main/java/com/simibubi/create/content/trains/bogey/BogeyInstance.java b/src/main/java/com/simibubi/create/content/trains/bogey/BogeyInstance.java new file mode 100644 index 000000000..1c68ef95e --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/bogey/BogeyInstance.java @@ -0,0 +1,65 @@ +package com.simibubi.create.content.trains.bogey; + +import java.util.Optional; + +import com.jozufozu.flywheel.api.MaterialManager; +import com.jozufozu.flywheel.util.AnimationTickHolder; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.content.trains.entity.CarriageBogey; +import com.simibubi.create.content.trains.entity.CarriageContraptionEntity; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.LightLayer; +import net.minecraft.world.phys.Vec3; + +public final class BogeyInstance { + private final BogeySizes.BogeySize size; + private final BogeyStyle style; + + public final CarriageBogey bogey; + public final BogeyRenderer renderer; + public final Optional commonRenderer; + + public BogeyInstance(CarriageBogey bogey, BogeyStyle style, BogeySizes.BogeySize size, + MaterialManager materialManager) { + this.bogey = bogey; + this.size = size; + this.style = style; + + this.renderer = this.style.createRendererInstance(this.size); + this.commonRenderer = this.style.getNewCommonRenderInstance(); + + commonRenderer.ifPresent(bogeyRenderer -> bogeyRenderer.initialiseContraptionModelData(materialManager)); + renderer.initialiseContraptionModelData(materialManager); + } + + public void beginFrame(float wheelAngle, PoseStack ms) { + if (ms == null) { + renderer.emptyTransforms(); + return; + } + + commonRenderer.ifPresent(bogeyRenderer -> bogeyRenderer.render(bogey.bogeyData, wheelAngle, ms)); + renderer.render(bogey.bogeyData, wheelAngle, ms); + } + + public void updateLight(BlockAndTintGetter world, CarriageContraptionEntity entity) { + var lightPos = new BlockPos(getLightPos(entity)); + commonRenderer + .ifPresent(bogeyRenderer -> bogeyRenderer.updateLight(world.getBrightness(LightLayer.BLOCK, lightPos), + world.getBrightness(LightLayer.SKY, lightPos))); + renderer.updateLight(world.getBrightness(LightLayer.BLOCK, lightPos), + world.getBrightness(LightLayer.SKY, lightPos)); + } + + private Vec3 getLightPos(CarriageContraptionEntity entity) { + return bogey.getAnchorPosition() != null ? bogey.getAnchorPosition() + : entity.getLightProbePosition(AnimationTickHolder.getPartialTicks()); + } + + @FunctionalInterface + interface BogeyInstanceFactory { + BogeyInstance create(CarriageBogey bogey, BogeySizes.BogeySize size, MaterialManager materialManager); + } +} diff --git a/src/main/java/com/simibubi/create/content/trains/bogey/BogeyRenderer.java b/src/main/java/com/simibubi/create/content/trains/bogey/BogeyRenderer.java new file mode 100644 index 000000000..1d8055be0 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/bogey/BogeyRenderer.java @@ -0,0 +1,304 @@ +package com.simibubi.create.content.trains.bogey; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.jetbrains.annotations.Nullable; + +import com.jozufozu.flywheel.api.MaterialManager; +import com.jozufozu.flywheel.core.Materials; +import com.jozufozu.flywheel.core.PartialModel; +import com.jozufozu.flywheel.core.materials.model.ModelData; +import com.jozufozu.flywheel.util.transform.Transform; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public abstract class BogeyRenderer { + Map contraptionModelData = new HashMap<>(); + + /** + * A common interface for getting transform data for both in-world and in-contraption model data safely from a + * partial model + * + * @param model The key for the model data to instantiate or retrieve + * @param ms The posestack used for contraption model data + * @param inInstancedContraption The type of model needed + * @param size The amount of models needed + * @return A generic transform which can be used for both in-world and in-contraption models + */ + public Transform[] getTransformsFromPartial(PartialModel model, PoseStack ms, boolean inInstancedContraption, int size) { + return (inInstancedContraption) ? transformContraptionModelData(keyFromModel(model), ms) : createModelData(model, size); + } + + /** + * A common interface for getting transform data for both in-world and in-contraption model data safely from a + * blockstate + * + * @param state The key for the model data to instantiate or retrieve + * @param ms The posestack used for contraption model data + * @param inContraption The type of model needed + * @param size The amount of models needed + * @return A generic transform which can be used for both in-world and in-contraption models + */ + public Transform[] getTransformsFromBlockState(BlockState state, PoseStack ms, boolean inContraption, int size) { + return inContraption ? transformContraptionModelData(keyFromModel(state), ms) : createModelData(state, size); + } + + /** + * Used for calling both in-world and in-contraption rendering + * + * @param bogeyData Custom data stored on the bogey able to be used for rendering + * @param wheelAngle The angle of the wheel + * @param ms The posestack to render to + * @param light (Optional) Light used for in-world rendering + * @param vb (Optional) Vertex Consumer used for in-world rendering + */ + @OnlyIn(Dist.CLIENT) + public abstract void render(CompoundTag bogeyData, float wheelAngle, PoseStack ms, int light, VertexConsumer vb, boolean inContraption); + + /** + * Used for calling in-contraption rendering ensuring that falsey data is handled correctly + * + * @param bogeyData Custom data stored on the bogey able to be used for rendering + * @param wheelAngle The angle of the wheel + * @param ms The posestack to render to + */ + @OnlyIn(Dist.CLIENT) + public void render(CompoundTag bogeyData, float wheelAngle, PoseStack ms) { + this.render(bogeyData, wheelAngle, ms, 0, null, true); + } + + public abstract BogeySizes.BogeySize getSize(); + + /** + * Used to collect Contraption Model Data for in-contraption rendering, should not be utilised directly when + * rendering to prevent render type mismatch + * + * @param key The key used to access the model + * @param ms Posestack of the contraption to bind the model data to + * @return A generic transform which can be used for both in-world and in-contraption models + */ + private Transform[] transformContraptionModelData(String key, PoseStack ms) { + ModelData[] modelData = contraptionModelData.get(key); + Arrays.stream(modelData).forEach(modelDataElement -> modelDataElement.setTransform(ms)); + return modelData; + } + + + /** + * Used for in world rendering, creates a set count of model data to be rendered, allowing for a generic response + * when rendering multiple models both in-world and in-contraption for example, with wheels + * + * @param model The partial model of the model data ot be made + * @param size The Amount of models needed + * @return A generic transform which can be used for both in-world and in-contraption models + */ + private Transform[] createModelData(PartialModel model, int size) { + BlockState air = Blocks.AIR.defaultBlockState(); + SuperByteBuffer[] data = { CachedBufferer.partial(model, air) }; + return expandArrayToLength(data, size); + } + + /** + * Used for in world rendering, creates a set count of model data to be rendered, allowing for a generic response + * when rendering multiple models both in-world and in-contraption for example, with wheels + * + * @param state The state of the model data to be made + * @param size Amount of models needed + * @return A generic transform which can be used for both in-world and in-contraption models + */ + private Transform[] createModelData(BlockState state, int size) { + SuperByteBuffer[] data = { CachedBufferer.block(state) }; + return expandArrayToLength(data, size); + } + + /** + * Utility function to clone in-world models to a set size to allow for common handling of rendering with multiple + * instances of the same model for example with wheels + * + * @param data An in-world model to be replicated + * @param size Amount of models needed + * @return A generic transform which can be used for both in-world and in-contraption models + */ + private Transform[] expandArrayToLength(SuperByteBuffer[] data, int size) { + return Arrays.stream(Collections.nCopies(size, data).toArray()) + .flatMap(inner -> Arrays.stream((SuperByteBuffer[]) inner)) + .toArray(SuperByteBuffer[]::new); + } + + /** + * Helper function to collect or create a single model from a partial model used for both in-world and + * in-contraption rendering + * + * @param model The key of the model to be collected or instantiated + * @param ms Posestack to bind the model to if it is within a contraption + * @param inInstancedContraption Type of rendering required + * @return A generic transform which can be used for both in-world and in-contraption models + */ + public Transform getTransformFromPartial(PartialModel model, PoseStack ms, boolean inInstancedContraption) { + BlockState air = Blocks.AIR.defaultBlockState(); + return inInstancedContraption ? contraptionModelData.get(keyFromModel(model))[0].setTransform(ms) + : CachedBufferer.partial(model, air); + } + + /** + * A common interface for getting transform data for blockstates, for a single model + * + * @param state The state of the model to be collected or instantiated + * @param ms Posestack to bind the model to if it is within a contraption + * @param inContraption Type of model required + * @return A generic transform which can be used for both in-world and in-contraption models + */ + public Transform getTransformFromBlockState(BlockState state, PoseStack ms, boolean inContraption) { + return (inContraption) ? contraptionModelData.get(keyFromModel(state))[0].setTransform(ms) + : CachedBufferer.block(state); + } + + /** + * Provides render implementations a point in setup to instantiate all model data to be needed + * + * @param materialManager The material manager + */ + @OnlyIn(Dist.CLIENT) + public abstract void initialiseContraptionModelData(MaterialManager materialManager); + + /** + * Creates instances of models for in-world rendering to a set length from a provided partial model + * + * @param materialManager The material manager + * @param model Partial model to be instanced + * @param count Amount of models neeeded + */ + public void createModelInstances(MaterialManager materialManager, PartialModel model, int count) { + ModelData[] modelData = new ModelData[count]; + materialManager.defaultSolid().material(Materials.TRANSFORMED) + .getModel(model).createInstances(modelData); + contraptionModelData.put(keyFromModel(model), modelData); + } + + /** + * Creates instances of models for in-contraption rendering to a set length from a provided blockstate + * + * @param materialManager The material manager + * @param state Blockstate of the model to be created + * @param count Amount of models needed + */ + public void createModelInstances(MaterialManager materialManager, BlockState state, int count) { + ModelData[] modelData = new ModelData[count]; + materialManager.defaultSolid().material(Materials.TRANSFORMED) + .getModel(state).createInstances(modelData); + contraptionModelData.put(keyFromModel(state), modelData); + } + + /** + * Creates a single instance of models for in-contraption rendering from a provided blockstate + * + * @param materialManager The material manager + * @param state Blockstate of the model to be created + */ + public void createModelInstance(MaterialManager materialManager, BlockState state) { + this.createModelInstances(materialManager, state, 1); + } + + /** + * Helper function to create a single model instance for in-contraption rendering + * + * @param materialManager The material manager + * @param models The type of model to create instances of + */ + public void createModelInstances(MaterialManager materialManager, PartialModel... models) { + for (PartialModel model : models) + createModelInstances(materialManager, model, 1); + } + + /** + * Handles scale for all model data and renders non contraption model data + * + * @param b The model data itself + * @param ms Pose stack to render to + * @param light light level of the scene + * @param vb Vertex Consumber to render to + * @param Generic alias for both contraption and in-world model data + */ + + public static > void finalize(B b, PoseStack ms, int light, @Nullable VertexConsumer vb) { + b.scale(1 - 1/512f); + if (b instanceof SuperByteBuffer byteBuf && vb != null) + byteBuf.light(light).renderInto(ms, vb); + } + + /** + * Automatic handling for setting empty transforms for all model data + * + */ + + public void emptyTransforms() { + for (ModelData[] data : contraptionModelData.values()) + for (ModelData model : data) + model.setEmptyTransform(); + } + + /** + * Automatic handling for updating all model data's light + * + * @param blockLight the blocklight to be applied + * @param skyLight the skylight to be applied + */ + + public void updateLight(int blockLight, int skyLight) { + for (ModelData[] data : contraptionModelData.values()) + for (ModelData model : data) + model.setBlockLight(blockLight).setSkyLight(skyLight); + } + + /** + * Automatic handling for clearing all model data of a contraption + * + */ + + public void remove() { + for (ModelData[] data : contraptionModelData.values()) + for (ModelData model : data) + model.delete(); + contraptionModelData.clear(); + } + + /** + * Create a model key from a partial model, so it can be easily accessed + * + * @param partialModel the model we want a unique key for + * @return Key of the model + */ + + private String keyFromModel(PartialModel partialModel) { + return partialModel.getLocation().toString(); + } + + /** + * Create a model key from a blockstate, so it can be easily accessed + * + * @param state Blockstate of the model + * @return Key of the model + */ + + private String keyFromModel(BlockState state) { + return state.toString(); + } + + public static abstract class CommonRenderer extends BogeyRenderer { + @Override + public BogeySizes.BogeySize getSize() { + return null; + } + } +} diff --git a/src/main/java/com/simibubi/create/content/trains/bogey/BogeySizes.java b/src/main/java/com/simibubi/create/content/trains/bogey/BogeySizes.java new file mode 100644 index 000000000..e9bcc2d48 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/bogey/BogeySizes.java @@ -0,0 +1,70 @@ +package com.simibubi.create.content.trains.bogey; + +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.List; +import java.util.stream.Collectors; + +import com.simibubi.create.Create; + +import net.minecraft.resources.ResourceLocation; + +public class BogeySizes { + private static final Collection BOGEY_SIZES = new HashSet<>(); + public static final BogeySize SMALL = new BogeySize(Create.ID, "small", 6.5f / 16f); + public static final BogeySize LARGE = new BogeySize(Create.ID, "large", 12.5f / 16f); + + static { + BOGEY_SIZES.add(SMALL); + BOGEY_SIZES.add(LARGE); + } + + public static BogeySize addSize(String modId, String name, float size) { + ResourceLocation location = new ResourceLocation(modId, name); + return addSize(location, size); + } + + public static BogeySize addSize(ResourceLocation location, float size) { + BogeySize customSize = new BogeySize(location, size); + BOGEY_SIZES.add(customSize); + return customSize; + } + + public static List getAllSizesSmallToLarge() { + return BOGEY_SIZES.stream() + .sorted(Comparator.comparing(BogeySize::wheelRadius)) + .collect(Collectors.toList()); + } + + public static List getAllSizesLargeToSmall() { + List sizes = getAllSizesSmallToLarge(); + Collections.reverse(sizes); + return sizes; + } + + public static int count() { + return BOGEY_SIZES.size(); + } + + public record BogeySize(ResourceLocation location, float wheelRadius) { + public BogeySize(String modId, String name, float wheelRadius) { + this(new ResourceLocation(modId, name), wheelRadius); + } + + public BogeySize increment() { + List values = getAllSizesSmallToLarge(); + int ordinal = values.indexOf(this); + return values.get((ordinal + 1) % values.size()); + } + + public boolean is(BogeySize size) { + return size.location == this.location; + } + } + + public static void init() { + + } +} diff --git a/src/main/java/com/simibubi/create/content/trains/bogey/BogeyStyle.java b/src/main/java/com/simibubi/create/content/trains/bogey/BogeyStyle.java new file mode 100644 index 000000000..c1b63f785 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/bogey/BogeyStyle.java @@ -0,0 +1,133 @@ +package com.simibubi.create.content.trains.bogey; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.function.Supplier; +import java.util.stream.Stream; + +import org.jetbrains.annotations.NotNull; + +import com.jozufozu.flywheel.api.MaterialManager; +import com.simibubi.create.AllBogeyStyles; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.content.trains.bogey.BogeyRenderer.CommonRenderer; +import com.simibubi.create.content.trains.entity.CarriageBogey; + +import net.minecraft.core.particles.ParticleOptions; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.level.block.Block; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.registries.ForgeRegistries; + + +public class BogeyStyle { + + public final ResourceLocation name; + public final ResourceLocation cycleGroup; + public final Component displayName; + public final ResourceLocation soundType; + public final ParticleOptions contactParticle; + public final ParticleOptions smokeParticle; + public final CompoundTag defaultData; + + private Optional> commonRendererFactory; + private Map sizes; + + @OnlyIn(Dist.CLIENT) + private Map sizeRenderers; + + @OnlyIn(Dist.CLIENT) + private Optional commonRenderer; + + public BogeyStyle(ResourceLocation name, ResourceLocation cycleGroup, Component displayName, + ResourceLocation soundType, ParticleOptions contactParticle, ParticleOptions smokeParticle, + CompoundTag defaultData, Map sizes, + Map> sizeRenderers, + Optional> commonRenderer) { + + this.name = name; + this.cycleGroup = cycleGroup; + this.displayName = displayName; + this.soundType = soundType; + this.contactParticle = contactParticle; + this.smokeParticle = smokeParticle; + this.defaultData = defaultData; + this.sizes = sizes; + + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { + this.sizeRenderers = new HashMap<>(); + sizeRenderers.forEach((k, v) -> this.sizeRenderers.put(k, v.get())); + + this.commonRendererFactory = commonRenderer; + this.commonRenderer = commonRenderer.map(Supplier::get); + }); + } + + public Map getCycleGroup() { + return AllBogeyStyles.getCycleGroup(cycleGroup); + } + + public Block getNextBlock(BogeySizes.BogeySize currentSize) { + return Stream.iterate(currentSize.increment(), BogeySizes.BogeySize::increment) + .filter(sizes::containsKey) + .findFirst() + .map(this::getBlockOfSize) + .orElse(getBlockOfSize(currentSize)); + } + + public Block getBlockOfSize(BogeySizes.BogeySize size) { + return ForgeRegistries.BLOCKS.getValue(sizes.get(size)); + } + + public Set validSizes() { + return sizes.keySet(); + } + + @NotNull + public SoundEvent getSoundType() { + AllSoundEvents.SoundEntry entry = AllSoundEvents.ALL.get(this.soundType); + if (entry == null || entry.getMainEvent() == null) entry = AllSoundEvents.TRAIN2; + return entry.getMainEvent(); + } + + @OnlyIn(Dist.CLIENT) + public BogeyRenderer createRendererInstance(BogeySizes.BogeySize size) { + return this.sizeRenderers.get(size).createRenderInstance(); + } + + @OnlyIn(Dist.CLIENT) + public BogeyRenderer getInWorldRenderInstance(BogeySizes.BogeySize size) { + SizeRenderData sizeData = this.sizeRenderers.get(size); + return sizeData != null ? sizeData.getInWorldInstance() : BackupBogeyRenderer.INSTANCE; + } + + public Optional getInWorldCommonRenderInstance() { + return this.commonRenderer; + } + + public Optional getNewCommonRenderInstance() { + return this.commonRendererFactory.map(Supplier::get); + } + + public BogeyInstance createInstance(CarriageBogey bogey, BogeySizes.BogeySize size, MaterialManager materialManager) { + return new BogeyInstance(bogey, this, size, materialManager); + } + + @OnlyIn(Dist.CLIENT) + public record SizeRenderData(Supplier rendererFactory, BogeyRenderer instance) { + public BogeyRenderer createRenderInstance() { + return rendererFactory.get(); + } + + public BogeyRenderer getInWorldInstance() { + return instance; + } + } +} diff --git a/src/main/java/com/simibubi/create/content/trains/bogey/StandardBogeyBlock.java b/src/main/java/com/simibubi/create/content/trains/bogey/StandardBogeyBlock.java new file mode 100644 index 000000000..b4bceecfa --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/bogey/StandardBogeyBlock.java @@ -0,0 +1,69 @@ +package com.simibubi.create.content.trains.bogey; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllBogeyStyles; +import com.simibubi.create.content.schematics.requirement.ISpecialBlockItemRequirement; +import com.simibubi.create.content.trains.track.TrackMaterial; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.block.ProperWaterloggedBlock; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.Vec3; + +public class StandardBogeyBlock extends AbstractBogeyBlock + implements IBE, ProperWaterloggedBlock, ISpecialBlockItemRequirement { + + public StandardBogeyBlock(Properties props, BogeySizes.BogeySize size) { + super(props, size); + registerDefaultState(defaultBlockState().setValue(WATERLOGGED, false)); + } + + @Override + public TrackMaterial.TrackType getTrackType(BogeyStyle style) { + return TrackMaterial.TrackType.STANDARD; + } + + @Override + public double getWheelPointSpacing() { + return 2; + } + + @Override + public double getWheelRadius() { + return (size == BogeySizes.LARGE ? 12.5 : 6.5) / 16d; + } + + @Override + public Vec3 getConnectorAnchorOffset() { + return new Vec3(0, 7 / 32f, 1); + } + + @Override + public BogeyStyle getDefaultStyle() { + return AllBogeyStyles.STANDARD; + } + + @Override + public ItemStack getCloneItemStack(BlockState state, HitResult target, BlockGetter level, BlockPos pos, + Player player) { + return AllBlocks.RAILWAY_CASING.asStack(); + } + + @Override + public Class getBlockEntityClass() { + return StandardBogeyBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.BOGEY.get(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/trains/bogey/StandardBogeyBlockEntity.java b/src/main/java/com/simibubi/create/content/trains/bogey/StandardBogeyBlockEntity.java new file mode 100644 index 000000000..d60c88da6 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/bogey/StandardBogeyBlockEntity.java @@ -0,0 +1,19 @@ +package com.simibubi.create.content.trains.bogey; + +import com.simibubi.create.AllBogeyStyles; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; + +public class StandardBogeyBlockEntity extends AbstractBogeyBlockEntity { + + public StandardBogeyBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + public BogeyStyle getDefaultStyle() { + return AllBogeyStyles.STANDARD; + } +} diff --git a/src/main/java/com/simibubi/create/content/trains/bogey/StandardBogeyRenderer.java b/src/main/java/com/simibubi/create/content/trains/bogey/StandardBogeyRenderer.java new file mode 100644 index 000000000..429be66f2 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/bogey/StandardBogeyRenderer.java @@ -0,0 +1,134 @@ +package com.simibubi.create.content.trains.bogey; + +import static com.simibubi.create.AllPartialModels.BOGEY_DRIVE; +import static com.simibubi.create.AllPartialModels.BOGEY_FRAME; +import static com.simibubi.create.AllPartialModels.BOGEY_PIN; +import static com.simibubi.create.AllPartialModels.BOGEY_PISTON; +import static com.simibubi.create.AllPartialModels.LARGE_BOGEY_WHEELS; +import static com.simibubi.create.AllPartialModels.SMALL_BOGEY_WHEELS; + +import com.jozufozu.flywheel.api.MaterialManager; +import com.jozufozu.flywheel.util.transform.Transform; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.kinetics.simpleRelays.ShaftBlock; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.Iterate; + +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; + +public class StandardBogeyRenderer { + public static class CommonStandardBogeyRenderer extends BogeyRenderer.CommonRenderer { + @Override + public void initialiseContraptionModelData(MaterialManager materialManager) { + createModelInstances(materialManager, AllBlocks.SHAFT.getDefaultState() + .setValue(ShaftBlock.AXIS, Direction.Axis.Z), 2); + } + + @Override + public void render(CompoundTag bogeyData, float wheelAngle, PoseStack ms, int light, VertexConsumer vb, boolean inContraption) { + boolean inInstancedContraption = vb == null; + Transform[] shafts = getTransformsFromBlockState(AllBlocks.SHAFT.getDefaultState() + .setValue(ShaftBlock.AXIS, Direction.Axis.Z), ms, inInstancedContraption, 2); + for (int i : Iterate.zeroAndOne) { + shafts[i].translate(-.5f, .25f, i * -1) + .centre() + .rotateZ(wheelAngle) + .unCentre(); + finalize(shafts[i], ms, light, vb); + } + } + } + + + public static class SmallStandardBogeyRenderer extends BogeyRenderer { + @Override + public void initialiseContraptionModelData(MaterialManager materialManager) { + createModelInstances(materialManager, SMALL_BOGEY_WHEELS, 2); + createModelInstances(materialManager, BOGEY_FRAME); + } + + + @Override + public BogeySizes.BogeySize getSize() { + return BogeySizes.SMALL; + } + + @Override + public void render(CompoundTag bogeyData, float wheelAngle, PoseStack ms, int light, VertexConsumer vb, boolean inContraption) { + boolean inInstancedContraption = vb == null; + Transform transform = getTransformFromPartial(BOGEY_FRAME, ms, inInstancedContraption); + finalize(transform, ms, light, vb); + + Transform[] wheels = getTransformsFromPartial(SMALL_BOGEY_WHEELS, ms, inInstancedContraption, 2); + for (int side : Iterate.positiveAndNegative) { + if (!inInstancedContraption) + ms.pushPose(); + Transform wheel = wheels[(side + 1)/2]; + wheel.translate(0, 12 / 16f, side) + .rotateX(wheelAngle); + finalize(wheel, ms, light, vb); + if (!inInstancedContraption) + ms.popPose(); + } + } + } + + public static class LargeStandardBogeyRenderer extends BogeyRenderer { + @Override + public void initialiseContraptionModelData(MaterialManager materialManager) { + createModelInstances(materialManager, LARGE_BOGEY_WHEELS, BOGEY_DRIVE, BOGEY_PISTON, BOGEY_PIN); + createModelInstances(materialManager, AllBlocks.SHAFT.getDefaultState() + .setValue(ShaftBlock.AXIS, Direction.Axis.X), 2); + } + + @Override + public BogeySizes.BogeySize getSize() { + return BogeySizes.LARGE; + } + + @Override + public void render(CompoundTag bogeyData, float wheelAngle, PoseStack ms, int light, VertexConsumer vb, boolean inContraption) { + boolean inInstancedContraption = vb == null; + + Transform[] secondaryShafts = getTransformsFromBlockState(AllBlocks.SHAFT.getDefaultState() + .setValue(ShaftBlock.AXIS, Direction.Axis.X), ms, inInstancedContraption, 2); + + for (int i : Iterate.zeroAndOne) { + Transform secondShaft = secondaryShafts[i]; + secondShaft.translate(-.5f, .25f, .5f + i * -2) + .centre() + .rotateX(wheelAngle) + .unCentre(); + finalize(secondShaft, ms, light, vb); + } + + Transform bogeyDrive = getTransformFromPartial(BOGEY_DRIVE, ms, inInstancedContraption); + finalize(bogeyDrive, ms, light, vb); + + Transform bogeyPiston = getTransformFromPartial(BOGEY_PISTON, ms, inInstancedContraption) + .translate(0, 0, 1 / 4f * Math.sin(AngleHelper.rad(wheelAngle))); + finalize(bogeyPiston, ms, light, vb); + + if (!inInstancedContraption) + ms.pushPose(); + + Transform bogeyWheels = getTransformFromPartial(LARGE_BOGEY_WHEELS, ms, inInstancedContraption) + .translate(0, 1, 0) + .rotateX(wheelAngle); + finalize(bogeyWheels, ms, light, vb); + + Transform bogeyPin = getTransformFromPartial(BOGEY_PIN, ms, inInstancedContraption) + .translate(0, 1, 0) + .rotateX(wheelAngle) + .translate(0, 1 / 4f, 0) + .rotateX(-wheelAngle); + finalize(bogeyPin, ms, light, vb); + + if (!inInstancedContraption) + ms.popPose(); + } + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/display/FlapDisplayBlock.java b/src/main/java/com/simibubi/create/content/trains/display/FlapDisplayBlock.java similarity index 82% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/display/FlapDisplayBlock.java rename to src/main/java/com/simibubi/create/content/trains/display/FlapDisplayBlock.java index b1a81bd0e..9abf42398 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/display/FlapDisplayBlock.java +++ b/src/main/java/com/simibubi/create/content/trains/display/FlapDisplayBlock.java @@ -1,22 +1,24 @@ -package com.simibubi.create.content.logistics.trains.management.display; +package com.simibubi.create.content.trains.display; import static net.minecraft.world.level.block.state.properties.BlockStateProperties.WATERLOGGED; import java.util.List; import java.util.function.Predicate; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.base.HorizontalKineticBlock; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.relays.elementary.ICogWheel; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.content.equipment.clipboard.ClipboardEntry; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.content.kinetics.base.HorizontalKineticBlock; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.content.kinetics.simpleRelays.ICogWheel; +import com.simibubi.create.foundation.block.IBE; +import com.simibubi.create.foundation.placement.IPlacementHelper; +import com.simibubi.create.foundation.placement.PlacementHelpers; +import com.simibubi.create.foundation.placement.PlacementOffset; +import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.placement.IPlacementHelper; -import com.simibubi.create.foundation.utility.placement.PlacementHelpers; -import com.simibubi.create.foundation.utility.placement.PlacementOffset; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; @@ -26,6 +28,7 @@ import net.minecraft.core.Direction.Axis; import net.minecraft.core.Direction.AxisDirection; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; @@ -57,7 +60,7 @@ import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.ticks.LevelTickAccess; public class FlapDisplayBlock extends HorizontalKineticBlock - implements ITE, IWrenchable, ICogWheel, SimpleWaterloggedBlock { + implements IBE, IWrenchable, ICogWheel, SimpleWaterloggedBlock { public static final BooleanProperty UP = BooleanProperty.create("up"); public static final BooleanProperty DOWN = BooleanProperty.create("down"); @@ -127,12 +130,12 @@ public class FlapDisplayBlock extends HorizontalKineticBlock return placementHelper.getOffset(player, world, state, pos, ray) .placeInWorld(world, (BlockItem) heldItem.getItem(), player, hand, ray); - FlapDisplayTileEntity flapTe = getTileEntity(world, pos); + FlapDisplayBlockEntity flapBE = getBlockEntity(world, pos); - if (flapTe == null) + if (flapBE == null) return InteractionResult.PASS; - flapTe = flapTe.getController(); - if (flapTe == null) + flapBE = flapBE.getController(); + if (flapBE == null) return InteractionResult.PASS; double yCoord = ray.getLocation() @@ -141,29 +144,30 @@ public class FlapDisplayBlock extends HorizontalKineticBlock .getNormal()) .scale(.125f)).y; - int lineIndex = flapTe.getLineIndexAt(yCoord); + int lineIndex = flapBE.getLineIndexAt(yCoord); if (heldItem.isEmpty()) { - if (!flapTe.isSpeedRequirementFulfilled()) + if (!flapBE.isSpeedRequirementFulfilled()) return InteractionResult.PASS; - flapTe.applyTextManually(lineIndex, null); + flapBE.applyTextManually(lineIndex, null); return InteractionResult.SUCCESS; } if (heldItem.getItem() == Items.GLOW_INK_SAC) { if (!world.isClientSide) { world.playSound(null, pos, SoundEvents.INK_SAC_USE, SoundSource.BLOCKS, 1.0F, 1.0F); - flapTe.setGlowing(lineIndex); + flapBE.setGlowing(lineIndex); } return InteractionResult.SUCCESS; } - boolean display = heldItem.getItem() == Items.NAME_TAG && heldItem.hasCustomHoverName(); + boolean display = + heldItem.getItem() == Items.NAME_TAG && heldItem.hasCustomHoverName() || AllBlocks.CLIPBOARD.isIn(heldItem); DyeColor dye = DyeColor.getColor(heldItem); if (!display && dye == null) return InteractionResult.PASS; - if (dye == null && !flapTe.isSpeedRequirementFulfilled()) + if (dye == null && !flapBE.isSpeedRequirementFulfilled()) return InteractionResult.PASS; if (world.isClientSide) return InteractionResult.SUCCESS; @@ -171,11 +175,23 @@ public class FlapDisplayBlock extends HorizontalKineticBlock CompoundTag tag = heldItem.getTagElement("display"); String tagElement = tag != null && tag.contains("Name", Tag.TAG_STRING) ? tag.getString("Name") : null; - if (display) - flapTe.applyTextManually(lineIndex, tagElement); + if (display) { + if (AllBlocks.CLIPBOARD.isIn(heldItem)) { + List entries = ClipboardEntry.getLastViewedEntries(heldItem); + int line = lineIndex; + for (int i = 0; i < entries.size(); i++) { + for (String string : entries.get(i).text.getString() + .split("\n")) + flapBE.applyTextManually(line++, Component.Serializer.toJson(Components.literal(string))); + } + return InteractionResult.SUCCESS; + } + + flapBE.applyTextManually(lineIndex, tagElement); + } if (dye != null) { world.playSound(null, pos, SoundEvents.DYE_USE, SoundSource.BLOCKS, 1.0F, 1.0F); - flapTe.setColour(lineIndex, dye); + flapBE.setColour(lineIndex, dye); } return InteractionResult.SUCCESS; @@ -187,13 +203,13 @@ public class FlapDisplayBlock extends HorizontalKineticBlock } @Override - public Class getTileEntityClass() { - return FlapDisplayTileEntity.class; + public Class getBlockEntityClass() { + return FlapDisplayBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.FLAP_DISPLAY.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.FLAP_DISPLAY.get(); } @Override @@ -257,8 +273,8 @@ public class FlapDisplayBlock extends HorizontalKineticBlock pPos.relative(Direction.fromAxisAndDirection(getConnectionAxis(pState), AxisDirection.NEGATIVE)); BlockState belowState = pLevel.getBlockState(belowPos); if (!canConnect(pState, belowState)) - KineticTileEntity.switchToBlockState(pLevel, pPos, updateColumn(pLevel, pPos, pState, true)); - withTileEntityDo(pLevel, pPos, FlapDisplayTileEntity::updateControllerStatus); + KineticBlockEntity.switchToBlockState(pLevel, pPos, updateColumn(pLevel, pPos, pState, true)); + withBlockEntityDo(pLevel, pPos, FlapDisplayBlockEntity::updateControllerStatus); } @Override @@ -315,7 +331,8 @@ public class FlapDisplayBlock extends HorizontalKineticBlock BlockPos relative = pPos.relative(d); BlockState adjacent = pLevel.getBlockState(relative); if (canConnect(pState, adjacent)) - KineticTileEntity.switchToBlockState(pLevel, relative, updateColumn(pLevel, relative, adjacent, false)); + KineticBlockEntity.switchToBlockState(pLevel, relative, + updateColumn(pLevel, relative, adjacent, false)); } } diff --git a/src/main/java/com/simibubi/create/content/trains/display/FlapDisplayBlockEntity.java b/src/main/java/com/simibubi/create/content/trains/display/FlapDisplayBlockEntity.java new file mode 100644 index 000000000..06813e48e --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/display/FlapDisplayBlockEntity.java @@ -0,0 +1,334 @@ +package com.simibubi.create.content.trains.display; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import com.google.gson.JsonElement; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.content.kinetics.base.KineticBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.DyeHelper; +import com.simibubi.create.foundation.utility.DynamicComponent; +import com.simibubi.create.foundation.utility.NBTHelper; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Vec3i; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.util.Mth; +import net.minecraft.world.item.DyeColor; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; + +public class FlapDisplayBlockEntity extends KineticBlockEntity { + + public List lines; + public boolean isController; + public boolean isRunning; + public int xSize, ySize; + public DyeColor[] colour; + public boolean[] glowingLines; + public boolean[] manualLines; + + public FlapDisplayBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + setLazyTickRate(10); + isController = false; + xSize = 1; + ySize = 1; + colour = new DyeColor[2]; + manualLines = new boolean[2]; + glowingLines = new boolean[2]; + } + + @Override + public void initialize() { + super.initialize(); + } + + @Override + public void lazyTick() { + super.lazyTick(); + updateControllerStatus(); + } + + public void updateControllerStatus() { + if (level.isClientSide) + return; + + BlockState blockState = getBlockState(); + if (!(blockState.getBlock() instanceof FlapDisplayBlock)) + return; + + Direction leftDirection = blockState.getValue(FlapDisplayBlock.HORIZONTAL_FACING) + .getClockWise(); + boolean shouldBeController = !blockState.getValue(FlapDisplayBlock.UP) + && level.getBlockState(worldPosition.relative(leftDirection)) != blockState; + + int newXSize = 1; + int newYSize = 1; + + if (shouldBeController) { + for (int xOffset = 1; xOffset < 32; xOffset++) { + if (level.getBlockState(worldPosition.relative(leftDirection.getOpposite(), xOffset)) != blockState) + break; + newXSize++; + } + for (int yOffset = 0; yOffset < 32; yOffset++) { + if (!level.getBlockState(worldPosition.relative(Direction.DOWN, yOffset)) + .getOptionalValue(FlapDisplayBlock.DOWN) + .orElse(false)) + break; + newYSize++; + } + } + + if (isController == shouldBeController && newXSize == xSize && newYSize == ySize) + return; + + isController = shouldBeController; + xSize = newXSize; + ySize = newYSize; + colour = Arrays.copyOf(colour, ySize * 2); + glowingLines = Arrays.copyOf(glowingLines, ySize * 2); + manualLines = new boolean[ySize * 2]; + lines = null; + sendData(); + } + + @Override + public void tick() { + super.tick(); + isRunning = super.isSpeedRequirementFulfilled(); + if ((!level.isClientSide || !isRunning) && !isVirtual()) + return; + int activeFlaps = 0; + boolean instant = getSpeed() > 128; + for (FlapDisplayLayout line : lines) + for (FlapDisplaySection section : line.getSections()) + activeFlaps += section.tick(instant); + if (activeFlaps == 0) + return; + + float volume = Mth.clamp(activeFlaps / 20f, 0.25f, 1.5f); + float bgVolume = Mth.clamp(activeFlaps / 40f, 0.25f, 1f); + BlockPos middle = worldPosition.relative(getDirection().getClockWise(), xSize / 2) + .relative(Direction.DOWN, ySize / 2); + AllSoundEvents.SCROLL_VALUE.playAt(level, middle, volume, 0.56f, false); + level.playLocalSound(middle.getX(), middle.getY(), middle.getZ(), SoundEvents.CALCITE_HIT, SoundSource.BLOCKS, + .35f * bgVolume, 1.95f, false); + } + + @Override + protected boolean isNoisy() { + return false; + } + + @Override + public boolean isSpeedRequirementFulfilled() { + return isRunning; + } + + public void applyTextManually(int lineIndex, String rawComponentText) { + List lines = getLines(); + if (lineIndex >= lines.size()) + return; + + FlapDisplayLayout layout = lines.get(lineIndex); + if (!layout.isLayout("Default")) + layout.loadDefault(getMaxCharCount()); + List sections = layout.getSections(); + + FlapDisplaySection flapDisplaySection = sections.get(0); + if (rawComponentText == null) { + manualLines[lineIndex] = false; + flapDisplaySection.setText(Components.immutableEmpty()); + notifyUpdate(); + return; + } + + JsonElement json = DynamicComponent.getJsonFromString(rawComponentText); + if (json == null) + return; + + manualLines[lineIndex] = true; + Component text = isVirtual() ? Component.Serializer.fromJson(rawComponentText) + : DynamicComponent.parseCustomText(level, worldPosition, json); + flapDisplaySection.setText(text); + if (isVirtual()) + flapDisplaySection.refresh(true); + else + notifyUpdate(); + } + + public void setColour(int lineIndex, DyeColor color) { + colour[lineIndex] = color == DyeColor.WHITE ? null : color; + notifyUpdate(); + } + + public void setGlowing(int lineIndex) { + glowingLines[lineIndex] = true; + notifyUpdate(); + } + + public List getLines() { + if (lines == null) + initDefaultSections(); + return lines; + } + + public void initDefaultSections() { + lines = new ArrayList<>(); + for (int i = 0; i < ySize * 2; i++) + lines.add(new FlapDisplayLayout(getMaxCharCount())); + } + + public int getMaxCharCount() { + return getMaxCharCount(0); + } + + public int getMaxCharCount(int gaps) { + return (int) ((xSize * 16f - 2f - 4f * gaps) / 3.5f); + } + + @Override + protected void write(CompoundTag tag, boolean clientPacket) { + super.write(tag, clientPacket); + + tag.putBoolean("Controller", isController); + tag.putInt("XSize", xSize); + tag.putInt("YSize", ySize); + + for (int j = 0; j < manualLines.length; j++) + if (manualLines[j]) + NBTHelper.putMarker(tag, "CustomLine" + j); + + for (int j = 0; j < glowingLines.length; j++) + if (glowingLines[j]) + NBTHelper.putMarker(tag, "GlowingLine" + j); + + for (int j = 0; j < colour.length; j++) + if (colour[j] != null) + NBTHelper.writeEnum(tag, "Dye" + j, colour[j]); + + List lines = getLines(); + for (int i = 0; i < lines.size(); i++) + tag.put("Display" + i, lines.get(i) + .write()); + } + + @Override + protected void read(CompoundTag tag, boolean clientPacket) { + super.read(tag, clientPacket); + boolean wasActive = isController; + int prevX = xSize; + int prevY = ySize; + + isController = tag.getBoolean("Controller"); + xSize = tag.getInt("XSize"); + ySize = tag.getInt("YSize"); + + manualLines = new boolean[ySize * 2]; + for (int i = 0; i < ySize * 2; i++) + manualLines[i] = tag.contains("CustomLine" + i); + + glowingLines = new boolean[ySize * 2]; + for (int i = 0; i < ySize * 2; i++) + glowingLines[i] = tag.contains("GlowingLine" + i); + + colour = new DyeColor[ySize * 2]; + for (int i = 0; i < ySize * 2; i++) + colour[i] = tag.contains("Dye" + i) ? NBTHelper.readEnum(tag, "Dye" + i, DyeColor.class) : null; + + if (clientPacket && wasActive != isController || prevX != xSize || prevY != ySize) { + invalidateRenderBoundingBox(); + lines = null; + } + + List lines = getLines(); + for (int i = 0; i < lines.size(); i++) + lines.get(i) + .read(tag.getCompound("Display" + i)); + } + + public int getLineIndexAt(double yCoord) { + return (int) Mth.clamp(Math.floor(2 * (worldPosition.getY() - yCoord + 1)), 0, ySize * 2); + } + + public FlapDisplayBlockEntity getController() { + if (isController) + return this; + + BlockState blockState = getBlockState(); + if (!(blockState.getBlock() instanceof FlapDisplayBlock)) + return null; + + MutableBlockPos pos = getBlockPos().mutable(); + Direction side = blockState.getValue(FlapDisplayBlock.HORIZONTAL_FACING) + .getClockWise(); + + for (int i = 0; i < 64; i++) { + BlockState other = level.getBlockState(pos); + + if (other.getOptionalValue(FlapDisplayBlock.UP) + .orElse(false)) { + pos.move(Direction.UP); + continue; + } + + if (!level.getBlockState(pos.relative(side)) + .getOptionalValue(FlapDisplayBlock.UP) + .orElse(true)) { + pos.move(side); + continue; + } + + BlockEntity found = level.getBlockEntity(pos); + if (found instanceof FlapDisplayBlockEntity flap && flap.isController) + return flap; + + break; + } + + return null; + } + + @Override + protected AABB createRenderBoundingBox() { + AABB aabb = new AABB(worldPosition); + if (!isController) + return aabb; + Vec3i normal = getDirection().getClockWise() + .getNormal(); + return aabb.expandTowards(normal.getX() * xSize, -ySize, normal.getZ() * xSize); + } + + public Direction getDirection() { + return getBlockState().getOptionalValue(FlapDisplayBlock.HORIZONTAL_FACING) + .orElse(Direction.SOUTH) + .getOpposite(); + } + + @Override + public void addBehaviours(List behaviours) {} + + public int getLineColor(int line) { + DyeColor color = colour[line]; + return color == null ? 0xFF_D3C6BA + : DyeHelper.DYE_TABLE.get(color) + .getFirst() | 0xFF_000000; + } + + public boolean isLineGlowing(int line) { + return glowingLines[line]; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/display/FlapDisplayLayout.java b/src/main/java/com/simibubi/create/content/trains/display/FlapDisplayLayout.java similarity index 95% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/display/FlapDisplayLayout.java rename to src/main/java/com/simibubi/create/content/trains/display/FlapDisplayLayout.java index 192467846..24188f469 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/display/FlapDisplayLayout.java +++ b/src/main/java/com/simibubi/create/content/trains/display/FlapDisplayLayout.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.management.display; +package com.simibubi.create.content.trains.display; import java.util.Arrays; import java.util.List; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/display/FlapDisplayRenderer.java b/src/main/java/com/simibubi/create/content/trains/display/FlapDisplayRenderer.java similarity index 85% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/display/FlapDisplayRenderer.java rename to src/main/java/com/simibubi/create/content/trains/display/FlapDisplayRenderer.java index c71ac925b..bab9d8b9e 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/display/FlapDisplayRenderer.java +++ b/src/main/java/com/simibubi/create/content/trains/display/FlapDisplayRenderer.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.management.display; +package com.simibubi.create.content.trains.display; import java.util.List; @@ -9,9 +9,8 @@ import com.mojang.blaze3d.font.GlyphInfo; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack.Pose; import com.mojang.blaze3d.vertex.VertexConsumer; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.kinetics.base.KineticBlockEntityRenderer; import com.simibubi.create.foundation.render.CachedBufferer; import com.simibubi.create.foundation.render.SuperByteBuffer; import com.simibubi.create.foundation.utility.AngleHelper; @@ -35,34 +34,31 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -public class FlapDisplayRenderer extends KineticTileEntityRenderer { +public class FlapDisplayRenderer extends KineticBlockEntityRenderer { public FlapDisplayRenderer(BlockEntityRendererProvider.Context context) { super(context); } @Override - protected void renderSafe(KineticTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, + protected void renderSafe(FlapDisplayBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light, int overlay) { - super.renderSafe(te, partialTicks, ms, buffer, light, overlay); + super.renderSafe(be, partialTicks, ms, buffer, light, overlay); Font fontRenderer = Minecraft.getInstance().font; FontSet fontSet = fontRenderer.getFontSet(Style.DEFAULT_FONT); float scale = 1 / 32f; - if (!(te instanceof FlapDisplayTileEntity flapTe)) + if (!be.isController) return; - if (!flapTe.isController) - return; - - List lines = flapTe.getLines(); + List lines = be.getLines(); ms.pushPose(); TransformStack.cast(ms) .centre() - .rotateY(AngleHelper.horizontalAngle(te.getBlockState() + .rotateY(AngleHelper.horizontalAngle(be.getBlockState() .getValue(FlapDisplayBlock.HORIZONTAL_FACING))) .unCentre() .translate(0, 0, -3 / 16f); @@ -75,22 +71,22 @@ public class FlapDisplayRenderer extends KineticTileEntityRenderer { for (int j = 0; j < lines.size(); j++) { List line = lines.get(j) .getSections(); - int color = flapTe.getLineColor(j); + int color = be.getLineColor(j); ms.pushPose(); float w = 0; for (FlapDisplaySection section : line) w += section.getSize() + (section.hasGap ? 8 : 1); - ms.translate(flapTe.xSize * 16 - w / 2 + 1, 4.5f, 0); + ms.translate(be.xSize * 16 - w / 2 + 1, 4.5f, 0); Pose transform = ms.last(); FlapDisplayRenderOutput renderOutput = new FlapDisplayRenderOutput(buffer, color, transform.pose(), light, - j, !te.isSpeedRequirementFulfilled(), te.getLevel(), flapTe.isLineGlowing(j)); + j, !be.isSpeedRequirementFulfilled(), be.getLevel(), be.isLineGlowing(j)); for (int i = 0; i < line.size(); i++) { FlapDisplaySection section = line.get(i); renderOutput.nextSection(section); - int ticks = AnimationTickHolder.getTicks(te.getLevel()); + int ticks = AnimationTickHolder.getTicks(be.getLevel()); String text = section.renderCharsIndividually() || !section.spinning[0] ? section.text : section.cyclingOptions[((ticks / 3) + i * 13) % section.cyclingOptions.length]; StringDecomposer.iterateFormatted(text, Style.EMPTY, renderOutput); @@ -232,14 +228,14 @@ public class FlapDisplayRenderer extends KineticTileEntityRenderer { } @Override - protected SuperByteBuffer getRotatedModel(KineticTileEntity te, BlockState state) { - return CachedBufferer.partialFacingVertical(AllBlockPartials.SHAFTLESS_COGWHEEL, state, + protected SuperByteBuffer getRotatedModel(FlapDisplayBlockEntity be, BlockState state) { + return CachedBufferer.partialFacingVertical(AllPartialModels.SHAFTLESS_COGWHEEL, state, state.getValue(FlapDisplayBlock.HORIZONTAL_FACING)); } @Override - public boolean shouldRenderOffScreen(KineticTileEntity pBlockEntity) { - return ((FlapDisplayTileEntity) pBlockEntity).isController; + public boolean shouldRenderOffScreen(FlapDisplayBlockEntity be) { + return be.isController; } } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/display/FlapDisplaySection.java b/src/main/java/com/simibubi/create/content/trains/display/FlapDisplaySection.java similarity index 92% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/display/FlapDisplaySection.java rename to src/main/java/com/simibubi/create/content/trains/display/FlapDisplaySection.java index 4481a80ca..06c75eab6 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/display/FlapDisplaySection.java +++ b/src/main/java/com/simibubi/create/content/trains/display/FlapDisplaySection.java @@ -1,11 +1,11 @@ -package com.simibubi.create.content.logistics.trains.management.display; +package com.simibubi.create.content.trains.display; import java.util.HashMap; import java.util.Locale; import java.util.Map; +import java.util.Random; import com.google.common.base.Strings; -import com.simibubi.create.Create; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.NBTHelper; @@ -16,6 +16,7 @@ import net.minecraft.util.Mth; public class FlapDisplaySection { static final Map LOADED_FLAP_CYCLES = new HashMap<>(); + static Random r = new Random(); public static final float MONOSPACE = 7; public static final float WIDE_MONOSPACE = 9; @@ -83,35 +84,35 @@ public class FlapDisplaySection { spinningTicks = 0; } - public int tick() { + public int tick(boolean instant) { if (cyclingOptions == null) return 0; int max = Math.max(4, (int) (cyclingOptions.length * 1.75f)); if (spinningTicks > max) return 0; - + spinningTicks++; if (spinningTicks <= max && spinningTicks < 2) return spinningTicks == 1 ? 0 : spinning.length; - + int spinningFlaps = 0; for (int i = 0; i < spinning.length; i++) { int increasingChance = Mth.clamp(8 - spinningTicks, 1, 10); - boolean continueSpin = Create.RANDOM.nextInt(increasingChance * max / 4) != 0; + boolean continueSpin = !instant && r.nextInt(increasingChance * max / 4) != 0; continueSpin &= max > 5 || spinningTicks < 2; spinning[i] &= continueSpin; - if (i > 0 && Create.RANDOM.nextInt(3) > 0) + if (i > 0 && r.nextInt(3) > 0) spinning[i - 1] &= continueSpin; - if (i < spinning.length - 1 && Create.RANDOM.nextInt(3) > 0) + if (i < spinning.length - 1 && r.nextInt(3) > 0) spinning[i + 1] &= continueSpin; if (spinningTicks > max) spinning[i] = false; - + if (spinning[i]) spinningFlaps++; } - + return spinningFlaps; } @@ -169,10 +170,14 @@ public class FlapDisplaySection { return !singleFlap; } + public Component getText() { + return component; + } + public static String[] getFlapCycle(String key) { return LOADED_FLAP_CYCLES.computeIfAbsent(key, k -> Lang.translateDirect("flap_display.cycles." + key) .getString() .split(";")); } -} \ No newline at end of file +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/display/GlobalTrainDisplayData.java b/src/main/java/com/simibubi/create/content/trains/display/GlobalTrainDisplayData.java similarity index 89% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/display/GlobalTrainDisplayData.java rename to src/main/java/com/simibubi/create/content/trains/display/GlobalTrainDisplayData.java index 605d6c03f..dd8c622c0 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/display/GlobalTrainDisplayData.java +++ b/src/main/java/com/simibubi/create/content/trains/display/GlobalTrainDisplayData.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.management.display; +package com.simibubi.create.content.trains.display; import java.util.ArrayList; import java.util.Collection; @@ -7,7 +7,7 @@ import java.util.List; import java.util.Map; import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.entity.Train; +import com.simibubi.create.content.trains.entity.Train; import net.minecraft.network.chat.MutableComponent; @@ -30,10 +30,11 @@ public class GlobalTrainDisplayData { } public static List prepare(String filter, int maxLines) { + String regex = filter.isBlank() ? filter : "\\Q" + filter.replace("*", "\\E.*\\Q") + "\\E"; return statusByDestination.entrySet() .stream() .filter(e -> e.getKey() - .matches(filter.replace("*", ".*"))) + .matches(regex)) .flatMap(e -> e.getValue() .stream()) .sorted() diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/ArrivalSoundQueue.java b/src/main/java/com/simibubi/create/content/trains/entity/ArrivalSoundQueue.java similarity index 93% rename from src/main/java/com/simibubi/create/content/logistics/trains/entity/ArrivalSoundQueue.java rename to src/main/java/com/simibubi/create/content/trains/entity/ArrivalSoundQueue.java index 7251b7612..ed33925d5 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/ArrivalSoundQueue.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/ArrivalSoundQueue.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.entity; +package com.simibubi.create.content.trains.entity; import java.util.ArrayList; import java.util.HashMap; @@ -9,9 +9,9 @@ import com.google.common.collect.Multimap; import com.google.common.collect.Multimaps; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.content.contraptions.components.steam.whistle.WhistleBlock; -import com.simibubi.create.content.contraptions.components.steam.whistle.WhistleBlock.WhistleSize; -import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.decoration.steamWhistle.WhistleBlock; +import com.simibubi.create.content.decoration.steamWhistle.WhistleBlock.WhistleSize; import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.Pair; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/Carriage.java b/src/main/java/com/simibubi/create/content/trains/entity/Carriage.java similarity index 93% rename from src/main/java/com/simibubi/create/content/logistics/trains/entity/Carriage.java rename to src/main/java/com/simibubi/create/content/trains/entity/Carriage.java index 12d25eea7..86a2c3eee 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/Carriage.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/Carriage.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.entity; +package com.simibubi.create.content.trains.entity; import java.lang.ref.WeakReference; import java.util.HashMap; @@ -18,13 +18,13 @@ import javax.annotation.Nullable; import org.apache.commons.lang3.mutable.MutableDouble; -import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; -import com.simibubi.create.content.contraptions.components.structureMovement.train.TrainCargoManager; -import com.simibubi.create.content.logistics.trains.DimensionPalette; -import com.simibubi.create.content.logistics.trains.TrackGraph; -import com.simibubi.create.content.logistics.trains.TrackNodeLocation; -import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.IEdgePointListener; -import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.ITrackSelector; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.contraptions.minecart.TrainCargoManager; +import com.simibubi.create.content.trains.entity.TravellingPoint.IEdgePointListener; +import com.simibubi.create.content.trains.entity.TravellingPoint.ITrackSelector; +import com.simibubi.create.content.trains.graph.DimensionPalette; +import com.simibubi.create.content.trains.graph.TrackGraph; +import com.simibubi.create.content.trains.graph.TrackNodeLocation; import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Iterate; @@ -85,6 +85,11 @@ public class Carriage { bogey2.carriage = this; } + public boolean isOnIncompatibleTrack() { + return leadingBogey().type.isOnIncompatibleTrack(this, true) + || trailingBogey().type.isOnIncompatibleTrack(this, false); + } + public void setTrain(Train train) { this.train = train; } @@ -103,7 +108,7 @@ public class Carriage { DimensionalCarriageEntity dimensional = getDimensional(level); dimensional.alignEntity(entity); - dimensional.removeAndSaveEntity(entity, false); + dimensional.removeAndSaveEntity(entity, true); } public DimensionalCarriageEntity getDimensional(Level level) { @@ -306,6 +311,9 @@ public class Carriage { double leadingWheelSpacing = leadingBogey.type.getWheelPointSpacing(); double trailingWheelSpacing = trailingBogey.type.getWheelPointSpacing(); + boolean leadingUpsideDown = leadingBogey.isUpsideDown(); + boolean trailingUpsideDown = trailingBogey.isUpsideDown(); + for (boolean leading : Iterate.trueAndFalse) { TravellingPoint point = leading ? getLeadingPoint() : getTrailingPoint(); TravellingPoint otherPoint = !leading ? getLeadingPoint() : getTrailingPoint(); @@ -321,24 +329,31 @@ public class Carriage { dce.positionAnchor = dimension.equals(leadingBogeyDim) ? leadingBogey.getAnchorPosition() : pivoted(dce, dimension, point, - leading ? leadingWheelSpacing / 2 : bogeySpacing + trailingWheelSpacing / 2); + leading ? leadingWheelSpacing / 2 : bogeySpacing + trailingWheelSpacing / 2, + leadingUpsideDown, trailingUpsideDown); + + boolean backAnchorFlip = trailingBogey.isUpsideDown() ^ leadingBogey.isUpsideDown(); if (isOnTwoBogeys()) { dce.rotationAnchors.setFirst(dimension.equals(leadingBogeyDim) ? leadingBogey.getAnchorPosition() : pivoted(dce, dimension, point, - leading ? leadingWheelSpacing / 2 : bogeySpacing + trailingWheelSpacing / 2)); - dce.rotationAnchors.setSecond(dimension.equals(trailingBogeyDim) ? trailingBogey.getAnchorPosition() + leading ? leadingWheelSpacing / 2 : bogeySpacing + trailingWheelSpacing / 2, + leadingUpsideDown, trailingUpsideDown)); + dce.rotationAnchors.setSecond(dimension.equals(trailingBogeyDim) ? trailingBogey.getAnchorPosition(backAnchorFlip) : pivoted(dce, dimension, point, - leading ? leadingWheelSpacing / 2 + bogeySpacing : trailingWheelSpacing / 2)); + leading ? leadingWheelSpacing / 2 + bogeySpacing : trailingWheelSpacing / 2, + leadingUpsideDown, trailingUpsideDown)); } else { if (dimension.equals(otherDimension)) { - dce.rotationAnchors = leadingBogey.points.map(TravellingPoint::getPosition); + dce.rotationAnchors = leadingBogey.points.map(tp -> tp.getPosition(train.graph)); } else { - dce.rotationAnchors.setFirst(leadingBogey.points.getFirst() == point ? point.getPosition() - : pivoted(dce, dimension, point, leadingWheelSpacing)); - dce.rotationAnchors.setSecond(leadingBogey.points.getSecond() == point ? point.getPosition() - : pivoted(dce, dimension, point, leadingWheelSpacing)); + dce.rotationAnchors.setFirst(leadingBogey.points.getFirst() == point + ? point.getPosition(train.graph) + : pivoted(dce, dimension, point, leadingWheelSpacing, leadingUpsideDown, trailingUpsideDown)); + dce.rotationAnchors.setSecond(leadingBogey.points.getSecond() == point + ? point.getPosition(train.graph) + : pivoted(dce, dimension, point, leadingWheelSpacing, leadingUpsideDown, trailingUpsideDown)); } } @@ -356,15 +371,16 @@ public class Carriage { } private Vec3 pivoted(DimensionalCarriageEntity dce, ResourceKey dimension, TravellingPoint start, - double offset) { + double offset, boolean leadingUpsideDown, boolean trailingUpsideDown) { if (train.graph == null) return dce.pivot == null ? null : dce.pivot.getLocation(); TrackNodeLocation pivot = dce.findPivot(dimension, start == getLeadingPoint()); if (pivot == null) return null; - Vec3 startVec = start.getPosition(); + boolean flipped = start != getLeadingPoint() && (leadingUpsideDown != trailingUpsideDown); + Vec3 startVec = start.getPosition(train.graph, flipped); Vec3 portalVec = pivot.getLocation() - .add(0, 1, 0); + .add(0, leadingUpsideDown ? -1.0 : 1.0, 0); return VecHelper.lerp((float) (offset / startVec.distanceTo(portalVec)), startVec, portalVec); } @@ -723,8 +739,8 @@ public class Carriage { } - private void dismountPlayer(ServerLevel sLevel, ServerPlayer sp, Integer seat, boolean portal) { - if (!portal) { + private void dismountPlayer(ServerLevel sLevel, ServerPlayer sp, Integer seat, boolean capture) { + if (!capture) { sp.stopRiding(); return; } diff --git a/src/main/java/com/simibubi/create/content/trains/entity/CarriageBogey.java b/src/main/java/com/simibubi/create/content/trains/entity/CarriageBogey.java new file mode 100644 index 000000000..b313bf02f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/entity/CarriageBogey.java @@ -0,0 +1,227 @@ +package com.simibubi.create.content.trains.entity; + +import static com.simibubi.create.content.trains.bogey.AbstractBogeyBlockEntity.BOGEY_DATA_KEY; +import static com.simibubi.create.content.trains.bogey.AbstractBogeyBlockEntity.BOGEY_STYLE_KEY; + +import javax.annotation.Nullable; + +import com.jozufozu.flywheel.api.MaterialManager; +import com.simibubi.create.AllBogeyStyles; +import com.simibubi.create.Create; +import com.simibubi.create.content.trains.bogey.AbstractBogeyBlock; +import com.simibubi.create.content.trains.bogey.AbstractBogeyBlockEntity; +import com.simibubi.create.content.trains.bogey.BogeyInstance; +import com.simibubi.create.content.trains.bogey.BogeyStyle; +import com.simibubi.create.content.trains.graph.DimensionPalette; +import com.simibubi.create.content.trains.graph.TrackGraph; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.Couple; +import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.NBTHelper; +import com.simibubi.create.foundation.utility.RegisteredObjects; +import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.animation.LerpedFloat; + +import net.minecraft.core.Direction.Axis; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.registries.ForgeRegistries; + +public class CarriageBogey { + + public static final String UPSIDE_DOWN_KEY = "UpsideDown"; + + public Carriage carriage; + boolean isLeading; + + public CompoundTag bogeyData; + + AbstractBogeyBlock type; + boolean upsideDown; + Couple points; + + LerpedFloat wheelAngle; + LerpedFloat yaw; + LerpedFloat pitch; + + public Couple couplingAnchors; + + int derailAngle; + + public CarriageBogey(AbstractBogeyBlock type, boolean upsideDown, CompoundTag bogeyData, TravellingPoint point, TravellingPoint point2) { + this.type = type; + this.upsideDown = type.canBeUpsideDown() && upsideDown; + point.upsideDown = this.upsideDown; + point2.upsideDown = this.upsideDown; + if (bogeyData == null || bogeyData.isEmpty()) + bogeyData = this.createBogeyData(); // Prevent Crash When Updating + bogeyData.putBoolean(UPSIDE_DOWN_KEY, upsideDown); + this.bogeyData = bogeyData; + points = Couple.create(point, point2); + wheelAngle = LerpedFloat.angular(); + yaw = LerpedFloat.angular(); + pitch = LerpedFloat.angular(); + derailAngle = Create.RANDOM.nextInt(60) - 30; + couplingAnchors = Couple.create(null, null); + } + + public ResourceKey getDimension() { + TravellingPoint leading = leading(); + TravellingPoint trailing = trailing(); + if (leading.edge == null || trailing.edge == null) + return null; + if (leading.edge.isInterDimensional() || trailing.edge.isInterDimensional()) + return null; + ResourceKey dimension1 = leading.node1.getLocation().dimension; + ResourceKey dimension2 = trailing.node1.getLocation().dimension; + if (dimension1.equals(dimension2)) + return dimension1; + return null; + } + + public void updateAngles(CarriageContraptionEntity entity, double distanceMoved) { + double angleDiff = 360 * distanceMoved / (Math.PI * 2 * type.getWheelRadius()); + + float xRot = 0; + float yRot = 0; + + if (leading().edge == null || carriage.train.derailed) { + yRot = -90 + entity.yaw - derailAngle; + } else if (!entity.level.dimension() + .equals(getDimension())) { + yRot = -90 + entity.yaw; + xRot = 0; + } else { + Vec3 positionVec = leading().getPosition(carriage.train.graph); + Vec3 coupledVec = trailing().getPosition(carriage.train.graph); + double diffX = positionVec.x - coupledVec.x; + double diffY = positionVec.y - coupledVec.y; + double diffZ = positionVec.z - coupledVec.z; + yRot = AngleHelper.deg(Mth.atan2(diffZ, diffX)) + 90; + xRot = AngleHelper.deg(Math.atan2(diffY, Math.sqrt(diffX * diffX + diffZ * diffZ))); + } + + double newWheelAngle = (wheelAngle.getValue() - angleDiff) % 360; + + for (boolean twice : Iterate.trueAndFalse) { + if (twice && !entity.firstPositionUpdate) + continue; + wheelAngle.setValue(newWheelAngle); + pitch.setValue(xRot); + yaw.setValue(-yRot); + } + } + + public TravellingPoint leading() { + TravellingPoint point = points.getFirst(); + point.upsideDown = isUpsideDown(); + return point; + } + + public TravellingPoint trailing() { + TravellingPoint point = points.getSecond(); + point.upsideDown = isUpsideDown(); + return point; + } + + public double getStress() { + if (getDimension() == null) + return 0; + if (carriage.train.derailed) + return 0; + return type.getWheelPointSpacing() - leading().getPosition(carriage.train.graph) + .distanceTo(trailing().getPosition(carriage.train.graph)); + } + + @Nullable + public Vec3 getAnchorPosition() { + return getAnchorPosition(false); + } + + @Nullable + public Vec3 getAnchorPosition(boolean flipUpsideDown) { + if (leading().edge == null) + return null; + return points.getFirst() + .getPosition(carriage.train.graph, flipUpsideDown) + .add(points.getSecond() + .getPosition(carriage.train.graph, flipUpsideDown)) + .scale(.5); + } + + public void updateCouplingAnchor(Vec3 entityPos, float entityXRot, float entityYRot, int bogeySpacing, + float partialTicks, boolean leading) { + boolean selfUpsideDown = isUpsideDown(); + boolean leadingUpsideDown = carriage.leadingBogey().isUpsideDown(); + Vec3 thisOffset = type.getConnectorAnchorOffset(selfUpsideDown); + thisOffset = thisOffset.multiply(1, 1, leading ? -1 : 1); + + thisOffset = VecHelper.rotate(thisOffset, pitch.getValue(partialTicks), Axis.X); + thisOffset = VecHelper.rotate(thisOffset, yaw.getValue(partialTicks), Axis.Y); + thisOffset = VecHelper.rotate(thisOffset, -entityYRot - 90, Axis.Y); + thisOffset = VecHelper.rotate(thisOffset, entityXRot, Axis.X); + thisOffset = VecHelper.rotate(thisOffset, -180, Axis.Y); + thisOffset = thisOffset.add(0, 0, leading ? 0 : -bogeySpacing); + thisOffset = VecHelper.rotate(thisOffset, 180, Axis.Y); + thisOffset = VecHelper.rotate(thisOffset, -entityXRot, Axis.X); + thisOffset = VecHelper.rotate(thisOffset, entityYRot + 90, Axis.Y); + if (selfUpsideDown != leadingUpsideDown) + thisOffset = thisOffset.add(0, selfUpsideDown ? -2 : 2, 0); + + couplingAnchors.set(leading, entityPos.add(thisOffset)); + } + + public CompoundTag write(DimensionPalette dimensions) { + CompoundTag tag = new CompoundTag(); + tag.putString("Type", RegisteredObjects.getKeyOrThrow((Block) type) + .toString()); + tag.put("Points", points.serializeEach(tp -> tp.write(dimensions))); + tag.putBoolean("UpsideDown", upsideDown); + bogeyData.putBoolean(UPSIDE_DOWN_KEY, upsideDown); + NBTHelper.writeResourceLocation(bogeyData, BOGEY_STYLE_KEY, getStyle().name); + tag.put(BOGEY_DATA_KEY, bogeyData); + return tag; + } + + public static CarriageBogey read(CompoundTag tag, TrackGraph graph, DimensionPalette dimensions) { + ResourceLocation location = new ResourceLocation(tag.getString("Type")); + AbstractBogeyBlock type = (AbstractBogeyBlock) ForgeRegistries.BLOCKS.getValue(location); + boolean upsideDown = tag.getBoolean("UpsideDown"); + Couple points = Couple.deserializeEach(tag.getList("Points", Tag.TAG_COMPOUND), + c -> TravellingPoint.read(c, graph, dimensions)); + CompoundTag data = tag.getCompound(AbstractBogeyBlockEntity.BOGEY_DATA_KEY); + return new CarriageBogey(type, upsideDown, data, points.getFirst(), points.getSecond()); + } + + public BogeyInstance createInstance(MaterialManager materialManager) { + return this.getStyle().createInstance(this, type.getSize(), materialManager); + } + + public BogeyStyle getStyle() { + ResourceLocation location = NBTHelper.readResourceLocation(this.bogeyData, BOGEY_STYLE_KEY); + BogeyStyle style = AllBogeyStyles.BOGEY_STYLES.get(location); + return style != null ? style : AllBogeyStyles.STANDARD; // just for safety + } + + private CompoundTag createBogeyData() { + BogeyStyle style = type != null ? type.getDefaultStyle() : AllBogeyStyles.STANDARD; + CompoundTag nbt = style.defaultData != null ? style.defaultData : new CompoundTag(); + NBTHelper.writeResourceLocation(nbt, BOGEY_STYLE_KEY, style.name); + nbt.putBoolean(UPSIDE_DOWN_KEY, isUpsideDown()); + return nbt; + } + + void setLeading() { + isLeading = true; + } + + public boolean isUpsideDown() { + return type.canBeUpsideDown() && upsideDown; + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraption.java b/src/main/java/com/simibubi/create/content/trains/entity/CarriageContraption.java similarity index 85% rename from src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraption.java rename to src/main/java/com/simibubi/create/content/trains/entity/CarriageContraption.java index ad2396191..f8be4a9c0 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraption.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/CarriageContraption.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.entity; +package com.simibubi.create.content.trains.entity; import java.util.ArrayList; import java.util.Collection; @@ -11,18 +11,18 @@ import java.util.Optional; import org.apache.commons.lang3.tuple.Pair; import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException; -import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; -import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType; -import com.simibubi.create.content.contraptions.components.structureMovement.MountedStorageManager; -import com.simibubi.create.content.contraptions.components.structureMovement.NonStationaryLighter; -import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionLighter; -import com.simibubi.create.content.contraptions.components.structureMovement.train.TrainCargoManager; -import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock; -import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.HeatLevel; -import com.simibubi.create.content.logistics.trains.IBogeyBlock; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.AssemblyException; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.contraptions.ContraptionType; +import com.simibubi.create.content.contraptions.MountedStorageManager; +import com.simibubi.create.content.contraptions.actors.trainControls.ControlsBlock; +import com.simibubi.create.content.contraptions.minecart.TrainCargoManager; +import com.simibubi.create.content.contraptions.render.ContraptionLighter; +import com.simibubi.create.content.contraptions.render.NonStationaryLighter; +import com.simibubi.create.content.processing.burner.BlazeBurnerBlock; +import com.simibubi.create.content.processing.burner.BlazeBurnerBlock.HeatLevel; +import com.simibubi.create.content.trains.bogey.AbstractBogeyBlock; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Lang; @@ -71,7 +71,7 @@ public class CarriageContraption extends Contraption { // render public int portalCutoffMin; public int portalCutoffMax; - + static final IItemHandlerModifiable fallbackItems = new ItemStackHandler(); static final IFluidHandler fallbackFluids = new FluidTank(0); @@ -126,7 +126,7 @@ public class CarriageContraption extends Contraption { if (!blocks.containsKey(controlsPos)) return false; StructureBlockInfo info = blocks.get(controlsPos); - if (!AllBlocks.CONTROLS.has(info.state)) + if (!AllBlocks.TRAIN_CONTROLS.has(info.state)) return false; return info.state.getValue(ControlsBlock.FACING) == direction.getOpposite(); } @@ -162,18 +162,20 @@ public class CarriageContraption extends Contraption { .getStep(), toLocalPos(pos)); } - if (blockState.getBlock() instanceof IBogeyBlock) { + if (blockState.getBlock() instanceof AbstractBogeyBlock bogey) { + boolean captureBE = bogey.captureBlockEntityForTrain(); bogeys++; if (bogeys == 2) secondBogeyPos = pos; - return Pair.of(new StructureBlockInfo(pos, blockState, null), null); + return Pair.of(new StructureBlockInfo(pos, blockState, captureBE ? getBlockEntityNBT(world, pos) : null), + captureBE ? world.getBlockEntity(pos) : null); } if (AllBlocks.BLAZE_BURNER.has(blockState) && blockState.getValue(BlazeBurnerBlock.HEAT_LEVEL) != HeatLevel.NONE) assembledBlazeBurners.add(toLocalPos(pos)); - if (AllBlocks.CONTROLS.has(blockState)) { + if (AllBlocks.TRAIN_CONTROLS.has(blockState)) { Direction facing = blockState.getValue(ControlsBlock.FACING); if (facing.getAxis() != assemblyDirection.getAxis()) sidewaysControls = true; @@ -235,9 +237,9 @@ public class CarriageContraption extends Contraption { protected MountedStorageManager getStorageForSpawnPacket() { return storageProxy; } - + @Override - protected ContraptionType getType() { + public ContraptionType getType() { return ContraptionType.CARRIAGE; } @@ -263,17 +265,17 @@ public class CarriageContraption extends Contraption { return secondBogeyPos; } - private Collection specialRenderedTEsOutsidePortal = new ArrayList<>(); + private Collection specialRenderedBEsOutsidePortal = new ArrayList<>(); @Override public Collection getRenderedBlocks() { if (notInPortal()) return super.getRenderedBlocks(); - specialRenderedTEsOutsidePortal = new ArrayList<>(); - specialRenderedTileEntities.stream() - .filter(te -> !isHiddenInPortal(te.getBlockPos())) - .forEach(specialRenderedTEsOutsidePortal::add); + specialRenderedBEsOutsidePortal = new ArrayList<>(); + specialRenderedBlockEntities.stream() + .filter(be -> !isHiddenInPortal(be.getBlockPos())) + .forEach(specialRenderedBEsOutsidePortal::add); Collection values = new ArrayList<>(); for (Entry entry : blocks.entrySet()) { @@ -290,7 +292,7 @@ public class CarriageContraption extends Contraption { public Collection getSpecialRenderedTEs() { if (notInPortal()) return super.getSpecialRenderedTEs(); - return specialRenderedTEsOutsidePortal; + return specialRenderedBEsOutsidePortal; } @Override diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntity.java b/src/main/java/com/simibubi/create/content/trains/entity/CarriageContraptionEntity.java similarity index 93% rename from src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntity.java rename to src/main/java/com/simibubi/create/content/trains/entity/CarriageContraptionEntity.java index b420a8a59..a7c86d7a3 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntity.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/CarriageContraptionEntity.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.entity; +package com.simibubi.create.content.trains.entity; import java.lang.ref.WeakReference; import java.util.Collection; @@ -11,26 +11,26 @@ import java.util.UUID; import com.google.common.base.Strings; import com.simibubi.create.AllEntityDataSerializers; import com.simibubi.create.AllEntityTypes; +import com.simibubi.create.AllPackets; import com.simibubi.create.Create; import com.simibubi.create.CreateClient; -import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionBlockChangedPacket; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; -import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.TrainHUDUpdatePacket; -import com.simibubi.create.content.contraptions.particle.CubeParticleData; -import com.simibubi.create.content.logistics.trains.TrackGraph; -import com.simibubi.create.content.logistics.trains.entity.Carriage.DimensionalCarriageEntity; -import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.SteerDirection; -import com.simibubi.create.content.logistics.trains.management.edgePoint.station.GlobalStation; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.content.contraptions.ContraptionBlockChangedPacket; +import com.simibubi.create.content.contraptions.OrientedContraptionEntity; +import com.simibubi.create.content.contraptions.actors.trainControls.ControlsBlock; +import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.content.trains.CubeParticleData; +import com.simibubi.create.content.trains.TrainHUDUpdatePacket; +import com.simibubi.create.content.trains.entity.Carriage.DimensionalCarriageEntity; +import com.simibubi.create.content.trains.entity.TravellingPoint.SteerDirection; +import com.simibubi.create.content.trains.graph.TrackGraph; +import com.simibubi.create.content.trains.station.GlobalStation; import com.simibubi.create.foundation.utility.Color; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -201,7 +201,7 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { carriage.forEachPresentEntity(cce -> { cce.contraption.getBlocks() .put(localPos, newInfo); - AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> cce), + AllPackets.getChannel().send(PacketDistributor.TRACKING_ENTITY.with(() -> cce), new ContraptionBlockChangedPacket(cce.getId(), localPos, newInfo.state)); }); } @@ -563,7 +563,7 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { .equals(initialOrientation); if (hudPacketCooldown-- <= 0 && player instanceof ServerPlayer sp) { - AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> sp), new TrainHUDUpdatePacket(carriage.train)); + AllPackets.getChannel().send(PacketDistributor.PLAYER.with(() -> sp), new TrainHUDUpdatePacket(carriage.train)); hudPacketCooldown = 5; } @@ -654,7 +654,7 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { carriage.train.manualSteer = targetSteer < 0 ? SteerDirection.RIGHT : targetSteer > 0 ? SteerDirection.LEFT : SteerDirection.NONE; - double topSpeed = carriage.train.maxSpeed() * AllConfigs.SERVER.trains.manualTrainSpeedModifier.getF(); + double topSpeed = carriage.train.maxSpeed() * AllConfigs.server().trains.manualTrainSpeedModifier.getF(); double cappedTopSpeed = topSpeed * carriage.train.throttle; if (carriage.getLeadingPoint().edge != null && carriage.getLeadingPoint().edge.isTurn() @@ -677,7 +677,7 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity { private void sendPrompt(Player player, MutableComponent component, boolean shadow) { if (player instanceof ServerPlayer sp) - AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> sp), new TrainPromptPacket(component, shadow)); + AllPackets.getChannel().send(PacketDistributor.PLAYER.with(() -> sp), new TrainPromptPacket(component, shadow)); } boolean stationMessage = false; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntityRenderer.java b/src/main/java/com/simibubi/create/content/trains/entity/CarriageContraptionEntityRenderer.java similarity index 88% rename from src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntityRenderer.java rename to src/main/java/com/simibubi/create/content/trains/entity/CarriageContraptionEntityRenderer.java index 5de635e4a..30e3f0a48 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionEntityRenderer.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/CarriageContraptionEntityRenderer.java @@ -1,11 +1,11 @@ -package com.simibubi.create.content.logistics.trains.entity; +package com.simibubi.create.content.trains.entity; import java.util.Objects; import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionEntityRenderer; +import com.simibubi.create.content.contraptions.render.ContraptionEntityRenderer; import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.MultiBufferSource; @@ -37,7 +37,7 @@ public class CarriageContraptionEntityRenderer extends ContraptionEntityRenderer MultiBufferSource buffers, int overlay) { if (!entity.validForRender || entity.firstPositionUpdate) return; - + super.render(entity, yaw, partialTicks, ms, buffers, overlay); Carriage carriage = entity.getCarriage(); @@ -65,8 +65,9 @@ public class CarriageContraptionEntityRenderer extends ContraptionEntityRenderer translateBogey(ms, bogey, bogeySpacing, viewYRot, viewXRot, partialTicks); int light = getBogeyLightCoords(entity, bogey, partialTicks); + bogey.type.render(null, bogey.wheelAngle.getValue(partialTicks), ms, partialTicks, buffers, light, - overlay); + overlay, bogey.getStyle(), bogey.bogeyData); ms.popPose(); } @@ -80,6 +81,8 @@ public class CarriageContraptionEntityRenderer extends ContraptionEntityRenderer public static void translateBogey(PoseStack ms, CarriageBogey bogey, int bogeySpacing, float viewYRot, float viewXRot, float partialTicks) { + boolean selfUpsideDown = bogey.isUpsideDown(); + boolean leadingUpsideDown = bogey.carriage.leadingBogey().isUpsideDown(); TransformStack.cast(ms) .rotateY(viewYRot + 90) .rotateX(-viewXRot) @@ -90,7 +93,9 @@ public class CarriageContraptionEntityRenderer extends ContraptionEntityRenderer .rotateY(-viewYRot - 90) .rotateY(bogey.yaw.getValue(partialTicks)) .rotateX(bogey.pitch.getValue(partialTicks)) - .translate(0, .5f, 0); + .translate(0, .5f, 0) + .rotateZ(selfUpsideDown ? 180 : 0) + .translateY(selfUpsideDown != leadingUpsideDown ? 2 : 0); } public static int getBogeyLightCoords(CarriageContraptionEntity entity, CarriageBogey bogey, float partialTicks) { diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionInstance.java b/src/main/java/com/simibubi/create/content/trains/entity/CarriageContraptionInstance.java similarity index 83% rename from src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionInstance.java rename to src/main/java/com/simibubi/create/content/trains/entity/CarriageContraptionInstance.java index 9ce283971..748a66723 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageContraptionInstance.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/CarriageContraptionInstance.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.entity; +package com.simibubi.create.content.trains.entity; import org.joml.Vector3f; @@ -8,6 +8,8 @@ import com.jozufozu.flywheel.backend.instancing.entity.EntityInstance; import com.jozufozu.flywheel.util.AnimationTickHolder; import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.content.trains.bogey.BogeyInstance; +import com.simibubi.create.content.trains.bogey.BogeyRenderer; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Iterate; @@ -32,7 +34,8 @@ public class CarriageContraptionInstance extends EntityInstance + bogey.getStyle().createInstance(bogey, bogey.type.getSize(), manager), materialManager); updateLight(); } @@ -65,7 +68,7 @@ public class CarriageContraptionInstance extends EntityInstance { - if (instance != null) - instance.remove(); + if (instance != null) { + instance.commonRenderer.ifPresent(BogeyRenderer::remove); + instance.renderer.remove(); + } }); } diff --git a/src/main/java/com/simibubi/create/content/trains/entity/CarriageCouplingRenderer.java b/src/main/java/com/simibubi/create/content/trains/entity/CarriageCouplingRenderer.java new file mode 100644 index 000000000..e941000f2 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/entity/CarriageCouplingRenderer.java @@ -0,0 +1,131 @@ +package com.simibubi.create.content.trains.entity; + +import java.util.Collection; +import java.util.List; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.CreateClient; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.AnimationTickHolder; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.core.BlockPos; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LightLayer; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class CarriageCouplingRenderer { + + public static void renderAll(PoseStack ms, MultiBufferSource buffer, Vec3 camera) { + Collection trains = CreateClient.RAILWAYS.trains.values(); + VertexConsumer vb = buffer.getBuffer(RenderType.solid()); + BlockState air = Blocks.AIR.defaultBlockState(); + float partialTicks = AnimationTickHolder.getPartialTicks(); + Level level = Minecraft.getInstance().level; + + for (Train train : trains) { + List carriages = train.carriages; + for (int i = 0; i < carriages.size() - 1; i++) { + Carriage carriage = carriages.get(i); + CarriageContraptionEntity entity = carriage.getDimensional(level).entity.get(); + Carriage carriage2 = carriages.get(i + 1); + CarriageContraptionEntity entity2 = carriage.getDimensional(level).entity.get(); + + if (entity == null || entity2 == null) + continue; + + CarriageBogey bogey1 = carriage.trailingBogey(); + CarriageBogey bogey2 = carriage2.leadingBogey(); + Vec3 anchor = bogey1.couplingAnchors.getSecond(); + Vec3 anchor2 = bogey2.couplingAnchors.getFirst(); + + if (anchor == null || anchor2 == null) + continue; + if (!anchor.closerThan(camera, 64)) + continue; + + int lightCoords = getPackedLightCoords(entity, partialTicks); + int lightCoords2 = getPackedLightCoords(entity2, partialTicks); + + double diffX = anchor2.x - anchor.x; + double diffY = anchor2.y - anchor.y; + double diffZ = anchor2.z - anchor.z; + float yRot = AngleHelper.deg(Mth.atan2(diffZ, diffX)) + 90; + float xRot = AngleHelper.deg(Math.atan2(diffY, Math.sqrt(diffX * diffX + diffZ * diffZ))); + + Vec3 position = entity.getPosition(partialTicks); + Vec3 position2 = entity2.getPosition(partialTicks); + + ms.pushPose(); + + { + ms.pushPose(); + ms.translate(anchor.x - camera.x, anchor.y - camera.y, anchor.z - camera.z); + CachedBufferer.partial(AllPartialModels.TRAIN_COUPLING_HEAD, air) + .rotateY(-yRot) + .rotateX(xRot) + .light(lightCoords) + .renderInto(ms, vb); + + float margin = 3 / 16f; + double couplingDistance = train.carriageSpacing.get(i) - 2 * margin + - bogey1.type.getConnectorAnchorOffset(bogey1.isUpsideDown()).z - bogey2.type.getConnectorAnchorOffset(bogey2.isUpsideDown()).z; + int couplingSegments = (int) Math.round(couplingDistance * 4); + double stretch = ((anchor2.distanceTo(anchor) - 2 * margin) * 4) / couplingSegments; + for (int j = 0; j < couplingSegments; j++) { + CachedBufferer.partial(AllPartialModels.TRAIN_COUPLING_CABLE, air) + .rotateY(-yRot + 180) + .rotateX(-xRot) + .translate(0, 0, margin + 2 / 16f) + .scale(1, 1, (float) stretch) + .translate(0, 0, j / 4f) + .light(lightCoords) + .renderInto(ms, vb); + } + ms.popPose(); + } + + { + ms.pushPose(); + Vec3 translation = position2.subtract(position) + .add(anchor2) + .subtract(camera); + ms.translate(translation.x, translation.y, translation.z); + CachedBufferer.partial(AllPartialModels.TRAIN_COUPLING_HEAD, air) + .rotateY(-yRot + 180) + .rotateX(-xRot) + .light(lightCoords2) + .renderInto(ms, vb); + ms.popPose(); + } + + ms.popPose(); + } + } + + } + + public static int getPackedLightCoords(Entity pEntity, float pPartialTicks) { + BlockPos blockpos = new BlockPos(pEntity.getLightProbePosition(pPartialTicks)); + return LightTexture.pack(getBlockLightLevel(pEntity, blockpos), getSkyLightLevel(pEntity, blockpos)); + } + + protected static int getSkyLightLevel(Entity pEntity, BlockPos pPos) { + return pEntity.level.getBrightness(LightLayer.SKY, pPos); + } + + protected static int getBlockLightLevel(Entity pEntity, BlockPos pPos) { + return pEntity.isOnFire() ? 15 : pEntity.level.getBrightness(LightLayer.BLOCK, pPos); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageEntityHandler.java b/src/main/java/com/simibubi/create/content/trains/entity/CarriageEntityHandler.java similarity index 95% rename from src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageEntityHandler.java rename to src/main/java/com/simibubi/create/content/trains/entity/CarriageEntityHandler.java index 3cc309af5..1d1baa1a6 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageEntityHandler.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/CarriageEntityHandler.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.entity; +package com.simibubi.create.content.trains.entity; import net.minecraft.core.BlockPos; import net.minecraft.core.SectionPos; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageParticles.java b/src/main/java/com/simibubi/create/content/trains/entity/CarriageParticles.java similarity index 91% rename from src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageParticles.java rename to src/main/java/com/simibubi/create/content/trains/entity/CarriageParticles.java index b8fae41d9..b153a6d68 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageParticles.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/CarriageParticles.java @@ -1,6 +1,6 @@ -package com.simibubi.create.content.logistics.trains.entity; +package com.simibubi.create.content.trains.entity; -import com.simibubi.create.content.logistics.trains.entity.Carriage.DimensionalCarriageEntity; +import com.simibubi.create.content.trains.entity.Carriage.DimensionalCarriageEntity; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.animation.LerpedFloat; @@ -8,7 +8,6 @@ import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; import net.minecraft.client.Minecraft; import net.minecraft.core.Direction.Axis; -import net.minecraft.core.particles.ParticleTypes; import net.minecraft.util.RandomSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.Level; @@ -109,7 +108,7 @@ public class CarriageParticles { m = m.add(contraptionMotion.scale(.75f)); - level.addParticle(spark ? ParticleTypes.CRIT : ParticleTypes.POOF, v.x, v.y, v.z, m.x, m.y, m.z); + level.addParticle(spark ? bogey.getStyle().contactParticle : bogey.getStyle().smokeParticle, v.x, v.y, v.z, m.x, m.y, m.z); } } } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageSounds.java b/src/main/java/com/simibubi/create/content/trains/entity/CarriageSounds.java similarity index 90% rename from src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageSounds.java rename to src/main/java/com/simibubi/create/content/trains/entity/CarriageSounds.java index 1c5a0349b..53ce0df96 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageSounds.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/CarriageSounds.java @@ -1,8 +1,9 @@ -package com.simibubi.create.content.logistics.trains.entity; +package com.simibubi.create.content.trains.entity; import com.simibubi.create.AllSoundEvents; import com.simibubi.create.AllSoundEvents.SoundEntry; -import com.simibubi.create.content.logistics.trains.entity.Carriage.DimensionalCarriageEntity; +import com.simibubi.create.content.trains.entity.Carriage.DimensionalCarriageEntity; +import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.animation.LerpedFloat; import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; @@ -30,6 +31,9 @@ public class CarriageSounds { LoopingSound sharedWheelSoundSeated; LoopingSound sharedHonkSound; + Couple bogeySounds; + SoundEvent closestBogeySound; + boolean arrived; int tick; @@ -37,6 +41,10 @@ public class CarriageSounds { public CarriageSounds(CarriageContraptionEntity entity) { this.entity = entity; + bogeySounds = entity.getCarriage().bogeys.map(bogey -> + bogey != null && bogey.getStyle() != null ? bogey.getStyle().getSoundType() + : AllSoundEvents.TRAIN2.getMainEvent()); + closestBogeySound = bogeySounds.getFirst(); distanceFactor = LerpedFloat.linear(); speedFactor = LerpedFloat.linear(); approachFactor = LerpedFloat.linear(); @@ -80,6 +88,15 @@ public class CarriageSounds { double distance1 = toBogey1.length(); double distance2 = toBogey2.length(); + Couple bogeys = entity.getCarriage().bogeys; + CarriageBogey relevantBogey = bogeys.get(distance1 > distance2); + if (relevantBogey == null) { + relevantBogey = bogeys.getFirst(); + } + if (relevantBogey != null) { + closestBogeySound = relevantBogey.getStyle().getSoundType(); + } + Vec3 toCarriage = distance1 > distance2 ? toBogey2 : toBogey1; double distance = Math.min(distance1, distance2); Vec3 soundLocation = cam.add(toCarriage); @@ -98,7 +115,7 @@ public class CarriageSounds { seatCrossfade.tickChaser(); minecartEsqueSound = playIfMissing(mc, minecartEsqueSound, AllSoundEvents.TRAIN.getMainEvent()); - sharedWheelSound = playIfMissing(mc, sharedWheelSound, AllSoundEvents.TRAIN2.getMainEvent()); + sharedWheelSound = playIfMissing(mc, sharedWheelSound, closestBogeySound); sharedWheelSoundSeated = playIfMissing(mc, sharedWheelSoundSeated, AllSoundEvents.TRAIN3.getMainEvent()); float volume = Math.min(Math.min(speedFactor.getValue(), distanceFactor.getValue() / 100), @@ -206,7 +223,7 @@ public class CarriageSounds { public void submitSharedSoundVolume(Vec3 location, float volume) { Minecraft mc = Minecraft.getInstance(); minecartEsqueSound = playIfMissing(mc, minecartEsqueSound, AllSoundEvents.TRAIN.getMainEvent()); - sharedWheelSound = playIfMissing(mc, sharedWheelSound, AllSoundEvents.TRAIN2.getMainEvent()); + sharedWheelSound = playIfMissing(mc, sharedWheelSound, closestBogeySound); sharedWheelSoundSeated = playIfMissing(mc, sharedWheelSoundSeated, AllSoundEvents.TRAIN3.getMainEvent()); boolean approach = true; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageSyncData.java b/src/main/java/com/simibubi/create/content/trains/entity/CarriageSyncData.java similarity index 96% rename from src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageSyncData.java rename to src/main/java/com/simibubi/create/content/trains/entity/CarriageSyncData.java index 50ad64dc3..70ac8d235 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageSyncData.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/CarriageSyncData.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.entity; +package com.simibubi.create.content.trains.entity; import java.util.ArrayList; import java.util.HashSet; @@ -13,11 +13,11 @@ import java.util.Vector; import org.apache.commons.lang3.mutable.MutableBoolean; -import com.simibubi.create.content.logistics.trains.TrackEdge; -import com.simibubi.create.content.logistics.trains.TrackGraph; -import com.simibubi.create.content.logistics.trains.TrackNode; -import com.simibubi.create.content.logistics.trains.entity.Carriage.DimensionalCarriageEntity; -import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.ITrackSelector; +import com.simibubi.create.content.trains.entity.Carriage.DimensionalCarriageEntity; +import com.simibubi.create.content.trains.entity.TravellingPoint.ITrackSelector; +import com.simibubi.create.content.trains.graph.TrackEdge; +import com.simibubi.create.content.trains.graph.TrackGraph; +import com.simibubi.create.content.trains.graph.TrackNode; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Pair; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageSyncDataSerializer.java b/src/main/java/com/simibubi/create/content/trains/entity/CarriageSyncDataSerializer.java similarity index 90% rename from src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageSyncDataSerializer.java rename to src/main/java/com/simibubi/create/content/trains/entity/CarriageSyncDataSerializer.java index 762998b35..723685f75 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/CarriageSyncDataSerializer.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/CarriageSyncDataSerializer.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.entity; +package com.simibubi.create.content.trains.entity; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.syncher.EntityDataSerializer; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/Navigation.java b/src/main/java/com/simibubi/create/content/trains/entity/Navigation.java similarity index 91% rename from src/main/java/com/simibubi/create/content/logistics/trains/entity/Navigation.java rename to src/main/java/com/simibubi/create/content/trains/entity/Navigation.java index 258bc4da1..0bca29673 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/Navigation.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/Navigation.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.entity; +package com.simibubi.create.content.trains.entity; import java.util.ArrayList; import java.util.HashMap; @@ -18,19 +18,21 @@ import org.apache.commons.lang3.mutable.MutableDouble; import org.apache.commons.lang3.mutable.MutableObject; import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.DimensionPalette; -import com.simibubi.create.content.logistics.trains.TrackEdge; -import com.simibubi.create.content.logistics.trains.TrackGraph; -import com.simibubi.create.content.logistics.trains.TrackNode; -import com.simibubi.create.content.logistics.trains.TrackNodeLocation; -import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.ITrackSelector; -import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgeData; -import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalBlock.SignalType; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalBoundary; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalEdgeGroup; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.TrackEdgePoint; -import com.simibubi.create.content.logistics.trains.management.edgePoint.station.GlobalStation; +import com.simibubi.create.content.trains.entity.TravellingPoint.ITrackSelector; +import com.simibubi.create.content.trains.graph.DimensionPalette; +import com.simibubi.create.content.trains.graph.EdgeData; +import com.simibubi.create.content.trains.graph.EdgePointType; +import com.simibubi.create.content.trains.graph.TrackEdge; +import com.simibubi.create.content.trains.graph.TrackGraph; +import com.simibubi.create.content.trains.graph.TrackNode; +import com.simibubi.create.content.trains.graph.TrackNodeLocation; +import com.simibubi.create.content.trains.signal.SignalBlock.SignalType; +import com.simibubi.create.content.trains.signal.SignalBoundary; +import com.simibubi.create.content.trains.signal.SignalEdgeGroup; +import com.simibubi.create.content.trains.signal.TrackEdgePoint; +import com.simibubi.create.content.trains.station.GlobalStation; +import com.simibubi.create.content.trains.track.BezierConnection; +import com.simibubi.create.content.trains.track.TrackMaterial; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.NBTHelper; @@ -200,6 +202,20 @@ public class Navigation { return false; }, (distance, edge) -> { + BezierConnection turn = edge.getTurn(); + double vDistance = Math.abs(turn.starts.getFirst().y - turn.starts.getSecond().y); + + // ignore turn if its a straight & mild slope + if (turn != null && vDistance > 1 / 16f) { + if (turn.axes.getFirst() + .multiply(1, 0, 1) + .distanceTo(turn.axes.getSecond() + .multiply(1, 0, 1) + .scale(-1)) < 1 / 64f + && vDistance / turn.getLength() < .225f) + return; + } + float current = curveDistanceTracker.floatValue(); if (current == -1 || distance < current) curveDistanceTracker.setValue(distance); @@ -251,7 +267,7 @@ public class Navigation { return; } } - + topSpeed *= train.throttle; double turnTopSpeed = Math.min(topSpeed, train.maxTurnSpeed()); @@ -540,6 +556,21 @@ public class Navigation { if (graph == null) return; + // Cache the list of track types that the train can travel on + Set validTypes = new HashSet<>(); + for (int i = 0; i < train.carriages.size(); i++) { + Carriage carriage = train.carriages.get(i); + if (i == 0) { + validTypes.addAll(carriage.leadingBogey().type.getValidPathfindingTypes(carriage.leadingBogey().getStyle())); + } else { + validTypes.retainAll(carriage.leadingBogey().type.getValidPathfindingTypes(carriage.leadingBogey().getStyle())); + } + if (carriage.isOnTwoBogeys()) + validTypes.retainAll(carriage.trailingBogey().type.getValidPathfindingTypes(carriage.trailingBogey().getStyle())); + } + if (validTypes.isEmpty()) // if there are no valid track types, a route can't be found + return; + Map penalties = new IdentityHashMap<>(); boolean costRelevant = maxCost >= 0; if (costRelevant) { @@ -579,7 +610,7 @@ public class Navigation { .get(initialNode2); if (initialEdge == null) return; - + double distanceToNode2 = forward ? initialEdge.getLength() - startingPoint.position : startingPoint.position; frontier.add(new FrontierEntry(distanceToNode2, 0, initialNode1, initialNode2, initialEdge)); @@ -659,6 +690,8 @@ public class Navigation { continue; for (Entry target : validTargets) { + if (!validTypes.contains(target.getValue().getTrackMaterial().trackType)) + continue; TrackNode newNode = target.getKey(); TrackEdge newEdge = target.getValue(); double newDistance = newEdge.getLength() + distance; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/Train.java b/src/main/java/com/simibubi/create/content/trains/entity/Train.java similarity index 90% rename from src/main/java/com/simibubi/create/content/logistics/trains/entity/Train.java rename to src/main/java/com/simibubi/create/content/trains/entity/Train.java index 7bd014b38..3901bd197 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/Train.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/Train.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.entity; +package com.simibubi.create.content.trains.entity; import java.util.ArrayList; import java.util.Collection; @@ -21,36 +21,37 @@ import org.apache.commons.lang3.mutable.MutableBoolean; import org.apache.commons.lang3.mutable.MutableObject; import com.simibubi.create.AllMovementBehaviours; +import com.simibubi.create.AllPackets; import com.simibubi.create.Create; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; -import com.simibubi.create.content.logistics.item.filter.FilterItem; -import com.simibubi.create.content.logistics.trains.DimensionPalette; -import com.simibubi.create.content.logistics.trains.GraphLocation; -import com.simibubi.create.content.logistics.trains.TrackEdge; -import com.simibubi.create.content.logistics.trains.TrackGraph; -import com.simibubi.create.content.logistics.trains.TrackNode; -import com.simibubi.create.content.logistics.trains.entity.Carriage.DimensionalCarriageEntity; -import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.IEdgePointListener; -import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.SteerDirection; -import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgeData; -import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType; -import com.simibubi.create.content.logistics.trains.management.edgePoint.observer.TrackObserver; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalBlock.SignalType; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalBoundary; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalEdgeGroup; -import com.simibubi.create.content.logistics.trains.management.edgePoint.station.GlobalStation; -import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationTileEntity; -import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleRuntime; -import com.simibubi.create.content.logistics.trains.management.schedule.ScheduleRuntime.State; +import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; +import com.simibubi.create.content.logistics.filter.FilterItem; +import com.simibubi.create.content.trains.bogey.AbstractBogeyBlockEntity; +import com.simibubi.create.content.trains.entity.Carriage.DimensionalCarriageEntity; +import com.simibubi.create.content.trains.entity.TravellingPoint.IEdgePointListener; +import com.simibubi.create.content.trains.entity.TravellingPoint.SteerDirection; +import com.simibubi.create.content.trains.graph.DimensionPalette; +import com.simibubi.create.content.trains.graph.EdgeData; +import com.simibubi.create.content.trains.graph.EdgePointType; +import com.simibubi.create.content.trains.graph.TrackEdge; +import com.simibubi.create.content.trains.graph.TrackGraph; +import com.simibubi.create.content.trains.graph.TrackGraphLocation; +import com.simibubi.create.content.trains.graph.TrackNode; +import com.simibubi.create.content.trains.observer.TrackObserver; +import com.simibubi.create.content.trains.schedule.ScheduleRuntime; +import com.simibubi.create.content.trains.schedule.ScheduleRuntime.State; +import com.simibubi.create.content.trains.signal.SignalBlock.SignalType; +import com.simibubi.create.content.trains.signal.SignalBoundary; +import com.simibubi.create.content.trains.signal.SignalEdgeGroup; +import com.simibubi.create.content.trains.station.GlobalStation; +import com.simibubi.create.content.trains.station.StationBlockEntity; import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.Pair; import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -66,6 +67,7 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.Level.ExplosionInteraction; +import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.phys.Vec3; import net.minecraftforge.common.ForgeHooks; import net.minecraftforge.fluids.FluidStack; @@ -86,6 +88,7 @@ public class Train { public boolean honk = false; public UUID id; + @Nullable public UUID owner; public TrackGraph graph; public Navigation navigation; @@ -124,7 +127,7 @@ public class Train { public int honkPitch; public float accumulatedSteamRelease; - + int tickOffset; double[] stress; @@ -277,7 +280,7 @@ public class Train { int carriageCount = carriages.size(); boolean stalled = false; double maxStress = 0; - + if (carriageWaitingForChunks != -1) distance = 0; @@ -313,11 +316,17 @@ public class Train { if (leadingAnchor == null || trailingAnchor == null) continue; - total += leadingAnchor.distanceTo(trailingAnchor); + double distanceTo = leadingAnchor.distanceToSqr(trailingAnchor); + if (carriage.leadingBogey().isUpsideDown() != previousCarriage.trailingBogey().isUpsideDown()) { + distanceTo = Math.sqrt(distanceTo - 4); + } else { + distanceTo = Math.sqrt(distanceTo); + } + total += distanceTo; entries++; } } - + if (entries > 0) actual = total / entries; @@ -369,13 +378,13 @@ public class Train { .getLeadingPoint(); double totalStress = derailed ? 0 : leadingStress + trailingStress; - + boolean first = i == 0; boolean last = i == carriageCount - 1; int carriageType = first ? last ? Carriage.BOTH : Carriage.FIRST : last ? Carriage.LAST : Carriage.MIDDLE; double actualDistance = carriage.travel(level, graph, distance + totalStress, toFollowForward, toFollowBackward, carriageType); - blocked |= carriage.blocked; + blocked |= carriage.blocked || carriage.isOnIncompatibleTrack(); boolean onTwoBogeys = carriage.isOnTwoBogeys(); maxStress = Math.max(maxStress, onTwoBogeys ? carriage.bogeySpacing - carriage.getAnchorDiff() : 0); @@ -589,8 +598,8 @@ public class Train { if (!dimension.equals(trailingPoint.node1.getLocation().dimension)) return; - Vec3 start = (speed < 0 ? trailingPoint : leadingPoint).getPosition(); - Vec3 end = (speed < 0 ? leadingPoint : trailingPoint).getPosition(); + Vec3 start = (speed < 0 ? trailingPoint : leadingPoint).getPosition(graph); + Vec3 end = (speed < 0 ? leadingPoint : trailingPoint).getPosition(graph); Pair collision = findCollidingTrain(level, start, end, this, dimension); if (collision == null) @@ -632,8 +641,8 @@ public class Train { if (!otherDimension.equals(dimension)) continue; - Vec3 start2 = otherLeading.getPosition(); - Vec3 end2 = otherTrailing.getPosition(); + Vec3 start2 = otherLeading.getPosition(train.graph); + Vec3 end2 = otherTrailing.getPosition(train.graph); if (betweenBits) { end2 = start2; start2 = lastPoint; @@ -722,9 +731,20 @@ public class Train { if (entity.getContraption()instanceof CarriageContraption cc) cc.returnStorageForDisassembly(carriage.storage); entity.setPos(Vec3 - .atLowerCornerOf(pos.relative(assemblyDirection, backwards ? offset + carriage.bogeySpacing : offset))); + .atLowerCornerOf(pos.relative(assemblyDirection, backwards ? offset + carriage.bogeySpacing : offset).below(carriage.leadingBogey().isUpsideDown() ? 2 : 0))); entity.disassemble(); + for (CarriageBogey bogey : carriage.bogeys) { + if (bogey == null) + continue; + Vec3 bogeyPosition = bogey.getAnchorPosition(); + if (bogeyPosition == null) continue; + BlockEntity be = level.getBlockEntity(new BlockPos(bogeyPosition)); + if (!(be instanceof AbstractBogeyBlockEntity sbbe)) + continue; + sbbe.setBogeyData(bogey.bogeyData); + } + offset += carriage.bogeySpacing; if (i < carriageSpacing.size()) @@ -734,13 +754,13 @@ public class Train { GlobalStation currentStation = getCurrentStation(); if (currentStation != null) { currentStation.cancelReservation(this); - BlockPos tilePos = currentStation.getTilePos(); - if (level.getBlockEntity(tilePos)instanceof StationTileEntity ste) - ste.lastDisassembledTrainName = name.copy(); + BlockPos blockEntityPos = currentStation.getBlockEntityPos(); + if (level.getBlockEntity(blockEntityPos) instanceof StationBlockEntity sbe) + sbe.lastDisassembledTrainName = name.copy(); } Create.RAILWAYS.removeTrain(id); - AllPackets.channel.send(PacketDistributor.ALL.noArg(), new TrainPacket(this, false)); + AllPackets.getChannel().send(PacketDistributor.ALL.noArg(), new TrainPacket(this, false)); return true; } @@ -823,11 +843,11 @@ public class Train { } Set> entrySet = new HashSet<>(Create.RAILWAYS.trackNetworks.entrySet()); - Map> successfulMigrations = new HashMap<>(); + Map> successfulMigrations = new HashMap<>(); for (TrainMigration md : migratingPoints) { for (Iterator> iterator = entrySet.iterator(); iterator.hasNext();) { Entry entry = iterator.next(); - GraphLocation gl = md.tryMigratingTo(entry.getValue()); + TrackGraphLocation gl = md.tryMigratingTo(entry.getValue()); if (gl == null) { iterator.remove(); continue; @@ -846,7 +866,7 @@ public class Train { for (Entry entry : entrySet) { graph = entry.getValue(); - List locations = successfulMigrations.get(entry.getKey()); + List locations = successfulMigrations.get(entry.getKey()); forEachTravellingPoint(tp -> tp.migrateTo(locations)); migratingPoints.clear(); if (derailed) @@ -944,7 +964,7 @@ public class Train { occupiedObservers.clear(); cachedObserverFiltering.clear(); - TravellingPoint signalScout = new TravellingPoint(node1, node2, edge, position); + TravellingPoint signalScout = new TravellingPoint(node1, node2, edge, position, false); Map allGroups = Create.RAILWAYS.signalEdgeGroups; MutableObject prevGroup = new MutableObject<>(null); @@ -1070,24 +1090,25 @@ public class Train { } public float maxSpeed() { - return (fuelTicks > 0 ? AllConfigs.SERVER.trains.poweredTrainTopSpeed.getF() - : AllConfigs.SERVER.trains.trainTopSpeed.getF()) / 20; + return (fuelTicks > 0 ? AllConfigs.server().trains.poweredTrainTopSpeed.getF() + : AllConfigs.server().trains.trainTopSpeed.getF()) / 20; } public float maxTurnSpeed() { - return (fuelTicks > 0 ? AllConfigs.SERVER.trains.poweredTrainTurningTopSpeed.getF() - : AllConfigs.SERVER.trains.trainTurningTopSpeed.getF()) / 20; + return (fuelTicks > 0 ? AllConfigs.server().trains.poweredTrainTurningTopSpeed.getF() + : AllConfigs.server().trains.trainTurningTopSpeed.getF()) / 20; } public float acceleration() { - return (fuelTicks > 0 ? AllConfigs.SERVER.trains.poweredTrainAcceleration.getF() - : AllConfigs.SERVER.trains.trainAcceleration.getF()) / 400; + return (fuelTicks > 0 ? AllConfigs.server().trains.poweredTrainAcceleration.getF() + : AllConfigs.server().trains.trainAcceleration.getF()) / 400; } public CompoundTag write(DimensionPalette dimensions) { CompoundTag tag = new CompoundTag(); tag.putUUID("Id", id); - tag.putUUID("Owner", owner); + if (owner != null) + tag.putUUID("Owner", owner); if (graph != null) tag.putUUID("Graph", graph.id); tag.put("Carriages", NBTHelper.writeCompoundList(carriages, c -> c.write(dimensions))); @@ -1133,7 +1154,7 @@ public class Train { public static Train read(CompoundTag tag, Map trackNetworks, DimensionPalette dimensions) { UUID id = tag.getUUID("Id"); - UUID owner = tag.getUUID("Owner"); + UUID owner = tag.contains("Owner") ? tag.getUUID("Owner") : null; UUID graphId = tag.contains("Graph") ? tag.getUUID("Graph") : null; TrackGraph graph = graphId == null ? null : trackNetworks.get(graphId); List carriages = new ArrayList<>(); diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainIconType.java b/src/main/java/com/simibubi/create/content/trains/entity/TrainIconType.java similarity index 97% rename from src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainIconType.java rename to src/main/java/com/simibubi/create/content/trains/entity/TrainIconType.java index 3db2e3800..fa2d55bb5 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainIconType.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/TrainIconType.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.entity; +package com.simibubi.create.content.trains.entity; import java.util.HashMap; import java.util.Map; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainMigration.java b/src/main/java/com/simibubi/create/content/trains/entity/TrainMigration.java similarity index 83% rename from src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainMigration.java rename to src/main/java/com/simibubi/create/content/trains/entity/TrainMigration.java index 31185549e..2153b1cc4 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainMigration.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/TrainMigration.java @@ -1,13 +1,13 @@ -package com.simibubi.create.content.logistics.trains.entity; +package com.simibubi.create.content.trains.entity; import java.util.Map.Entry; -import com.simibubi.create.content.logistics.trains.DimensionPalette; -import com.simibubi.create.content.logistics.trains.GraphLocation; -import com.simibubi.create.content.logistics.trains.TrackEdge; -import com.simibubi.create.content.logistics.trains.TrackGraph; -import com.simibubi.create.content.logistics.trains.TrackNode; -import com.simibubi.create.content.logistics.trains.TrackNodeLocation; +import com.simibubi.create.content.trains.graph.DimensionPalette; +import com.simibubi.create.content.trains.graph.TrackEdge; +import com.simibubi.create.content.trains.graph.TrackGraph; +import com.simibubi.create.content.trains.graph.TrackGraphLocation; +import com.simibubi.create.content.trains.graph.TrackNode; +import com.simibubi.create.content.trains.graph.TrackNodeLocation; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.VecHelper; @@ -27,20 +27,20 @@ public class TrainMigration { public TrainMigration(TravellingPoint point) { double t = point.position / point.edge.getLength(); - fallback = point.edge.getPosition(t); + fallback = point.edge.getPosition(null, t); curve = point.edge.isTurn(); positionOnOldEdge = point.position; locations = Couple.create(point.node1.getLocation(), point.node2.getLocation()); } - public GraphLocation tryMigratingTo(TrackGraph graph) { + public TrackGraphLocation tryMigratingTo(TrackGraph graph) { TrackNode node1 = graph.locateNode(locations.getFirst()); TrackNode node2 = graph.locateNode(locations.getSecond()); if (node1 != null && node2 != null) { TrackEdge edge = graph.getConnectionsFrom(node1) .get(node2); if (edge != null) { - GraphLocation graphLocation = new GraphLocation(); + TrackGraphLocation graphLocation = new TrackGraphLocation(); graphLocation.graph = graph; graphLocation.edge = locations; graphLocation.position = positionOnOldEdge; @@ -88,7 +88,7 @@ public class TrainMigration { if (position > edgeLength) continue; - GraphLocation graphLocation = new GraphLocation(); + TrackGraphLocation graphLocation = new TrackGraphLocation(); graphLocation.graph = graph; graphLocation.edge = Couple.create(loc, newNode2.getLocation()); graphLocation.position = position; diff --git a/src/main/java/com/simibubi/create/content/trains/entity/TrainPacket.java b/src/main/java/com/simibubi/create/content/trains/entity/TrainPacket.java new file mode 100644 index 000000000..288555ea4 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/entity/TrainPacket.java @@ -0,0 +1,122 @@ +package com.simibubi.create.content.trains.entity; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import com.simibubi.create.CreateClient; +import com.simibubi.create.content.trains.bogey.AbstractBogeyBlock; +import com.simibubi.create.foundation.networking.SimplePacketBase; +import com.simibubi.create.foundation.utility.Couple; +import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.RegisteredObjects; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.chat.Component; +import net.minecraft.world.level.block.Block; +import net.minecraftforge.network.NetworkEvent.Context; +import net.minecraftforge.registries.ForgeRegistries; + +public class TrainPacket extends SimplePacketBase { + + UUID trainId; + Train train; + boolean add; + + public TrainPacket(Train train, boolean add) { + this.train = train; + this.add = add; + } + + public TrainPacket(FriendlyByteBuf buffer) { + add = buffer.readBoolean(); + trainId = buffer.readUUID(); + + if (!add) + return; + + UUID owner = null; + if (buffer.readBoolean()) + owner = buffer.readUUID(); + + List carriages = new ArrayList<>(); + List carriageSpacing = new ArrayList<>(); + + int size = buffer.readVarInt(); + for (int i = 0; i < size; i++) { + Couple bogies = Couple.create(null, null); + for (boolean isFirst : Iterate.trueAndFalse) { + if (!isFirst && !buffer.readBoolean()) + continue; + AbstractBogeyBlock type = (AbstractBogeyBlock) ForgeRegistries.BLOCKS.getValue(buffer.readResourceLocation()); + boolean upsideDown = buffer.readBoolean(); + CompoundTag data = buffer.readNbt(); + bogies.set(isFirst, new CarriageBogey(type, upsideDown, data, new TravellingPoint(), new TravellingPoint())); + } + int spacing = buffer.readVarInt(); + carriages.add(new Carriage(bogies.getFirst(), bogies.getSecond(), spacing)); + } + + size = buffer.readVarInt(); + for (int i = 0; i < size; i++) + carriageSpacing.add(buffer.readVarInt()); + + boolean doubleEnded = buffer.readBoolean(); + train = new Train(trainId, owner, null, carriages, carriageSpacing, doubleEnded); + + train.name = Component.Serializer.fromJson(buffer.readUtf()); + train.icon = TrainIconType.byId(buffer.readResourceLocation()); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeBoolean(add); + buffer.writeUUID(train.id); + + if (!add) + return; + + buffer.writeBoolean(train.owner != null); + if (train.owner != null) + buffer.writeUUID(train.owner); + + buffer.writeVarInt(train.carriages.size()); + for (Carriage carriage : train.carriages) { + for (boolean first : Iterate.trueAndFalse) { + if (!first) { + boolean onTwoBogeys = carriage.isOnTwoBogeys(); + buffer.writeBoolean(onTwoBogeys); + if (!onTwoBogeys) + continue; + } + CarriageBogey bogey = carriage.bogeys.get(first); + buffer.writeResourceLocation(RegisteredObjects.getKeyOrThrow((Block) bogey.type)); + buffer.writeBoolean(bogey.upsideDown); + buffer.writeNbt(bogey.bogeyData); + } + buffer.writeVarInt(carriage.bogeySpacing); + } + + buffer.writeVarInt(train.carriageSpacing.size()); + train.carriageSpacing.forEach(buffer::writeVarInt); + + buffer.writeBoolean(train.doubleEnded); + buffer.writeUtf(Component.Serializer.toJson(train.name)); + buffer.writeResourceLocation(train.icon.id); + } + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> { + Map trains = CreateClient.RAILWAYS.trains; + if (add) + trains.put(train.id, train); + else + trains.remove(trainId); + }); + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/trains/entity/TrainPromptPacket.java b/src/main/java/com/simibubi/create/content/trains/entity/TrainPromptPacket.java new file mode 100644 index 000000000..3e5acbcfd --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/entity/TrainPromptPacket.java @@ -0,0 +1,47 @@ +package com.simibubi.create.content.trains.entity; + +import com.simibubi.create.content.trains.TrainHUD; +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.chat.Component; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.network.NetworkEvent.Context; + +public class TrainPromptPacket extends SimplePacketBase { + + private Component text; + private boolean shadow; + + public TrainPromptPacket(Component text, boolean shadow) { + this.text = text; + this.shadow = shadow; + } + + public TrainPromptPacket(FriendlyByteBuf buffer) { + text = buffer.readComponent(); + shadow = buffer.readBoolean(); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeComponent(text); + buffer.writeBoolean(shadow); + } + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> this::apply)); + return true; + } + + @OnlyIn(Dist.CLIENT) + public void apply() { + TrainHUD.currentPrompt = text; + TrainHUD.currentPromptShadow = shadow; + TrainHUD.promptKeepAlive = 30; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainRelocationPacket.java b/src/main/java/com/simibubi/create/content/trains/entity/TrainRelocationPacket.java similarity index 81% rename from src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainRelocationPacket.java rename to src/main/java/com/simibubi/create/content/trains/entity/TrainRelocationPacket.java index 9db23eb93..8762dbd5f 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainRelocationPacket.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/TrainRelocationPacket.java @@ -1,16 +1,15 @@ -package com.simibubi.create.content.logistics.trains.entity; +package com.simibubi.create.content.trains.entity; import java.util.UUID; -import java.util.function.Supplier; +import com.simibubi.create.AllPackets; import com.simibubi.create.Create; -import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionRelocationPacket; -import com.simibubi.create.content.logistics.trains.track.BezierTrackPointLocation; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.content.contraptions.ContraptionRelocationPacket; +import com.simibubi.create.content.trains.track.BezierTrackPointLocation; import com.simibubi.create.foundation.networking.SimplePacketBase; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; @@ -65,10 +64,9 @@ public class TrainRelocationPacket extends SimplePacketBase { } @Override - public void handle(Supplier context) { - Context ctx = context.get(); - ctx.enqueueWork(() -> { - ServerPlayer sender = ctx.getSender(); + public boolean handle(Context context) { + context.enqueueWork(() -> { + ServerPlayer sender = context.getSender(); Train train = Create.RAILWAYS.trains.get(trainId); Entity entity = sender.level.getEntity(entityId); @@ -84,7 +82,7 @@ public class TrainRelocationPacket extends SimplePacketBase { if (!train.id.equals(cce.trainId)) return; - int verifyDistance = AllConfigs.SERVER.trains.maxTrackPlacementLength.get() * 2; + int verifyDistance = AllConfigs.server().trains.maxTrackPlacementLength.get() * 2; if (!sender.position() .closerThan(Vec3.atCenterOf(pos), verifyDistance)) { Create.LOGGER.warn(messagePrefix + train.name.getString() + ": player too far from clicked pos"); @@ -102,16 +100,15 @@ public class TrainRelocationPacket extends SimplePacketBase { .withStyle(ChatFormatting.GREEN), true); train.carriages.forEach(c -> c.forEachPresentEntity(e -> { e.nonDamageTicks = 10; - AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> e), + AllPackets.getChannel().send(PacketDistributor.TRACKING_ENTITY.with(() -> e), new ContraptionRelocationPacket(e.getId())); })); return; } Create.LOGGER.warn(messagePrefix + train.name.getString() + ": relocation failed server-side"); - }); - ctx.setPacketHandled(true); + return true; } } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainRelocator.java b/src/main/java/com/simibubi/create/content/trains/entity/TrainRelocator.java similarity index 87% rename from src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainRelocator.java rename to src/main/java/com/simibubi/create/content/trains/entity/TrainRelocator.java index 57858ca6e..afe3e23fe 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainRelocator.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/TrainRelocator.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.entity; +package com.simibubi.create.content.trains.entity; import java.lang.ref.WeakReference; import java.util.ArrayList; @@ -13,25 +13,25 @@ import org.apache.commons.lang3.mutable.MutableBoolean; import org.apache.commons.lang3.mutable.MutableInt; import com.simibubi.create.AllItems; +import com.simibubi.create.AllPackets; import com.simibubi.create.Create; import com.simibubi.create.CreateClient; -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionHandlerClient; -import com.simibubi.create.content.logistics.trains.GraphLocation; -import com.simibubi.create.content.logistics.trains.ITrackBlock; -import com.simibubi.create.content.logistics.trains.TrackEdge; -import com.simibubi.create.content.logistics.trains.TrackGraph; -import com.simibubi.create.content.logistics.trains.TrackGraphHelper; -import com.simibubi.create.content.logistics.trains.TrackNode; -import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.IEdgePointListener; -import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.ITrackSelector; -import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.ITurnListener; -import com.simibubi.create.content.logistics.trains.entity.TravellingPoint.SteerDirection; -import com.simibubi.create.content.logistics.trains.track.BezierTrackPointLocation; -import com.simibubi.create.content.logistics.trains.track.TrackBlockOutline; -import com.simibubi.create.content.logistics.trains.track.TrackBlockOutline.BezierPointSelection; +import com.simibubi.create.content.contraptions.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.ContraptionHandlerClient; +import com.simibubi.create.content.trains.entity.TravellingPoint.IEdgePointListener; +import com.simibubi.create.content.trains.entity.TravellingPoint.ITrackSelector; +import com.simibubi.create.content.trains.entity.TravellingPoint.ITurnListener; +import com.simibubi.create.content.trains.entity.TravellingPoint.SteerDirection; +import com.simibubi.create.content.trains.graph.TrackEdge; +import com.simibubi.create.content.trains.graph.TrackGraph; +import com.simibubi.create.content.trains.graph.TrackGraphHelper; +import com.simibubi.create.content.trains.graph.TrackGraphLocation; +import com.simibubi.create.content.trains.graph.TrackNode; +import com.simibubi.create.content.trains.track.BezierTrackPointLocation; +import com.simibubi.create.content.trains.track.ITrackBlock; +import com.simibubi.create.content.trains.track.TrackBlockOutline; +import com.simibubi.create.content.trains.track.TrackBlockOutline.BezierPointSelection; import com.simibubi.create.foundation.item.TooltipHelper; -import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Pair; @@ -115,20 +115,23 @@ public class TrainRelocator { BlockPos blockPos = blockhit.getBlockPos(); BezierTrackPointLocation hoveredBezier = null; + boolean upsideDown = relocating.carriages.get(0).leadingBogey().isUpsideDown(); + Vec3 offset = upsideDown ? new Vec3(0, -0.5, 0) : Vec3.ZERO; + if (simulate && toVisualise != null && lastHoveredResult != null) { for (int i = 0; i < toVisualise.size() - 1; i++) { - Vec3 vec1 = toVisualise.get(i); - Vec3 vec2 = toVisualise.get(i + 1); + Vec3 vec1 = toVisualise.get(i).add(offset); + Vec3 vec2 = toVisualise.get(i + 1).add(offset); CreateClient.OUTLINER.showLine(Pair.of(relocating, i), vec1.add(0, -.925f, 0), vec2.add(0, -.925f, 0)) .colored(lastHoveredResult || i != toVisualise.size() - 2 ? 0x95CD41 : 0xEA5C2B) - .disableNormals() + .disableLineNormals() .lineWidth(i % 2 == 1 ? 1 / 6f : 1 / 4f); } } BezierPointSelection bezierSelection = TrackBlockOutline.result; if (bezierSelection != null) { - blockPos = bezierSelection.te() + blockPos = bezierSelection.blockEntity() .getBlockPos(); hoveredBezier = bezierSelection.loc(); } @@ -150,8 +153,8 @@ public class TrainRelocator { boolean direction = bezierSelection != null && lookAngle.dot(bezierSelection.direction()) < 0; boolean result = relocate(relocating, mc.level, blockPos, hoveredBezier, direction, lookAngle, true); if (!simulate && result) { - relocating.carriages.forEach(c -> c.forEachPresentEntity(e -> e.nonDamageTicks = 10)); - AllPackets.channel.sendToServer(new TrainRelocationPacket(relocatingTrain, blockPos, hoveredBezier, + relocating.carriages.forEach(c -> c.forEachPresentEntity(e -> e.nonDamageTicks = 10)); + AllPackets.getChannel().sendToServer(new TrainRelocationPacket(relocatingTrain, blockPos, hoveredBezier, direction, lookAngle, relocatingEntityId)); } @@ -165,7 +168,7 @@ public class TrainRelocator { return false; Pair nearestTrackAxis = track.getNearestTrackAxis(level, pos, blockState, lookAngle); - GraphLocation graphLocation = bezier != null + TrackGraphLocation graphLocation = bezier != null ? TrackGraphHelper.getBezierGraphLocationAt(level, pos, bezierDirection ? AxisDirection.POSITIVE : AxisDirection.NEGATIVE, bezier) : TrackGraphHelper.getGraphLocationAt(level, pos, nearestTrackAxis.getSecond(), @@ -182,14 +185,14 @@ public class TrainRelocator { if (edge == null) return false; - TravellingPoint probe = new TravellingPoint(node1, node2, edge, graphLocation.position); + TravellingPoint probe = new TravellingPoint(node1, node2, edge, graphLocation.position, false); IEdgePointListener ignoreSignals = probe.ignoreEdgePoints(); ITurnListener ignoreTurns = probe.ignoreTurns(); List, Double>> recordedLocations = new ArrayList<>(); List recordedVecs = new ArrayList<>(); Consumer recorder = tp -> { recordedLocations.add(Pair.of(Couple.create(tp.node1, tp.node2), tp.position)); - recordedVecs.add(tp.getPosition()); + recordedVecs.add(tp.getPosition(graph)); }; ITrackSelector steer = probe.steer(SteerDirection.NONE, track.getUpNormal(level, pos, blockState)); MutableBoolean blocked = new MutableBoolean(false); @@ -269,7 +272,7 @@ public class TrainRelocator { public static void visualise(Train train, int i, Vec3 v1, Vec3 v2, boolean valid) { CreateClient.OUTLINER.showLine(Pair.of(train, i), v1.add(0, -.825f, 0), v2.add(0, -.825f, 0)) .colored(valid ? 0x95CD41 : 0xEA5C2B) - .disableNormals() + .disableLineNormals() .lineWidth(i % 2 == 1 ? 1 / 6f : 1 / 4f); } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainStatus.java b/src/main/java/com/simibubi/create/content/trains/entity/TrainStatus.java similarity index 98% rename from src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainStatus.java rename to src/main/java/com/simibubi/create/content/trains/entity/TrainStatus.java index 79b5bb9db..1a3e73d84 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TrainStatus.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/TrainStatus.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.entity; +package com.simibubi.create.content.trains.entity; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TravellingPoint.java b/src/main/java/com/simibubi/create/content/trains/entity/TravellingPoint.java similarity index 88% rename from src/main/java/com/simibubi/create/content/logistics/trains/entity/TravellingPoint.java rename to src/main/java/com/simibubi/create/content/trains/entity/TravellingPoint.java index 194d926a6..2ac9e964c 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/entity/TravellingPoint.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/TravellingPoint.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.entity; +package com.simibubi.create.content.trains.entity; import java.util.ArrayList; import java.util.HashSet; @@ -16,14 +16,14 @@ import java.util.function.Predicate; import javax.annotation.Nullable; import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.DimensionPalette; -import com.simibubi.create.content.logistics.trains.GraphLocation; -import com.simibubi.create.content.logistics.trains.TrackEdge; -import com.simibubi.create.content.logistics.trains.TrackGraph; -import com.simibubi.create.content.logistics.trains.TrackNode; -import com.simibubi.create.content.logistics.trains.TrackNodeLocation; -import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgeData; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.TrackEdgePoint; +import com.simibubi.create.content.trains.graph.DimensionPalette; +import com.simibubi.create.content.trains.graph.EdgeData; +import com.simibubi.create.content.trains.graph.TrackEdge; +import com.simibubi.create.content.trains.graph.TrackGraph; +import com.simibubi.create.content.trains.graph.TrackGraphLocation; +import com.simibubi.create.content.trains.graph.TrackNode; +import com.simibubi.create.content.trains.graph.TrackNodeLocation; +import com.simibubi.create.content.trains.signal.TrackEdgePoint; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Pair; @@ -38,6 +38,7 @@ public class TravellingPoint { public TrackEdge edge; public double position; public boolean blocked; + public boolean upsideDown; public static enum SteerDirection { NONE(0), LEFT(-1), RIGHT(1); @@ -64,11 +65,12 @@ public class TravellingPoint { public TravellingPoint() {} - public TravellingPoint(TrackNode node1, TrackNode node2, TrackEdge edge, double position) { + public TravellingPoint(TrackNode node1, TrackNode node2, TrackEdge edge, double position, boolean upsideDown) { this.node1 = node1; this.node2 = node2; this.edge = edge; this.position = position; + this.upsideDown = upsideDown; } public IEdgePointListener ignoreEdgePoints() { @@ -358,7 +360,7 @@ public class TravellingPoint { return traveled; } - private Double edgeTraversedFrom(TrackGraph graph, boolean forward, IEdgePointListener edgePointListener, + protected Double edgeTraversedFrom(TrackGraph graph, boolean forward, IEdgePointListener edgePointListener, ITurnListener turnListener, double prevPos, double totalDistance) { if (edge.isTurn()) turnListener.accept(Math.max(0, totalDistance), edge); @@ -394,19 +396,23 @@ public class TravellingPoint { .get(node2); } - public Vec3 getPosition() { - return getPositionWithOffset(0); + public Vec3 getPosition(@Nullable TrackGraph trackGraph) { + return getPosition(trackGraph, false); } - public Vec3 getPositionWithOffset(double offset) { + public Vec3 getPosition(@Nullable TrackGraph trackGraph, boolean flipUpsideDown) { + return getPositionWithOffset(trackGraph, 0, flipUpsideDown); + } + + public Vec3 getPositionWithOffset(@Nullable TrackGraph trackGraph, double offset, boolean flipUpsideDown) { double t = (position + offset) / edge.getLength(); - return edge.getPosition(t) - .add(edge.getNormal(node1, node2, t) - .scale(1)); + return edge.getPosition(trackGraph, t) + .add(edge.getNormal(trackGraph, t) + .scale(upsideDown ^ flipUpsideDown ? -1 : 1)); } - public void migrateTo(List locations) { - GraphLocation location = locations.remove(0); + public void migrateTo(List locations) { + TrackGraphLocation location = locations.remove(0); TrackGraph graph = location.graph; node1 = graph.locateNode(location.edge.getFirst()); node2 = graph.locateNode(location.edge.getSecond()); @@ -423,12 +429,13 @@ public class TravellingPoint { tag.put("Nodes", nodes.map(TrackNode::getLocation) .serializeEach(loc -> loc.write(dimensions))); tag.putDouble("Position", position); + tag.putBoolean("UpsideDown", upsideDown); return tag; } public static TravellingPoint read(CompoundTag tag, TrackGraph graph, DimensionPalette dimensions) { if (graph == null) - return new TravellingPoint(null, null, null, 0); + return new TravellingPoint(null, null, null, 0, false); Couple locs = tag.contains("Nodes") ? Couple.deserializeEach(tag.getList("Nodes", Tag.TAG_COMPOUND), c -> TrackNodeLocation.read(c, dimensions)) @@ -436,11 +443,11 @@ public class TravellingPoint { : Couple.create(null, null); if (locs.either(Objects::isNull)) - return new TravellingPoint(null, null, null, 0); + return new TravellingPoint(null, null, null, 0, false); double position = tag.getDouble("Position"); return new TravellingPoint(locs.getFirst(), locs.getSecond(), graph.getConnectionsFrom(locs.getFirst()) - .get(locs.getSecond()), position); + .get(locs.getSecond()), position, tag.getBoolean("UpsideDown")); } } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/DimensionPalette.java b/src/main/java/com/simibubi/create/content/trains/graph/DimensionPalette.java similarity index 97% rename from src/main/java/com/simibubi/create/content/logistics/trains/DimensionPalette.java rename to src/main/java/com/simibubi/create/content/trains/graph/DimensionPalette.java index 98cba027f..2f8ae4b18 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/DimensionPalette.java +++ b/src/main/java/com/simibubi/create/content/trains/graph/DimensionPalette.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains; +package com.simibubi.create.content.trains.graph; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/EdgeData.java b/src/main/java/com/simibubi/create/content/trains/graph/EdgeData.java similarity index 90% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/EdgeData.java rename to src/main/java/com/simibubi/create/content/trains/graph/EdgeData.java index 942ccc02c..8e15284f6 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/EdgeData.java +++ b/src/main/java/com/simibubi/create/content/trains/graph/EdgeData.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.management.edgePoint; +package com.simibubi.create.content.trains.graph; import java.util.ArrayList; import java.util.Iterator; @@ -10,14 +10,9 @@ import javax.annotation.Nullable; import com.google.common.base.Objects; import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.DimensionPalette; -import com.simibubi.create.content.logistics.trains.TrackEdge; -import com.simibubi.create.content.logistics.trains.TrackGraph; -import com.simibubi.create.content.logistics.trains.TrackNode; -import com.simibubi.create.content.logistics.trains.TrackNodeLocation; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalBoundary; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalEdgeGroup; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.TrackEdgePoint; +import com.simibubi.create.content.trains.signal.SignalBoundary; +import com.simibubi.create.content.trains.signal.SignalEdgeGroup; +import com.simibubi.create.content.trains.signal.TrackEdgePoint; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.NBTHelper; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/EdgePointManager.java b/src/main/java/com/simibubi/create/content/trains/graph/EdgePointManager.java similarity index 77% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/EdgePointManager.java rename to src/main/java/com/simibubi/create/content/trains/graph/EdgePointManager.java index ecca7e8d4..fafe1109f 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/EdgePointManager.java +++ b/src/main/java/com/simibubi/create/content/trains/graph/EdgePointManager.java @@ -1,11 +1,7 @@ -package com.simibubi.create.content.logistics.trains.management.edgePoint; +package com.simibubi.create.content.trains.graph; import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.TrackEdge; -import com.simibubi.create.content.logistics.trains.TrackGraph; -import com.simibubi.create.content.logistics.trains.TrackNode; -import com.simibubi.create.content.logistics.trains.TrackNodeLocation; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.TrackEdgePoint; +import com.simibubi.create.content.trains.signal.TrackEdgePoint; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Iterate; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/EdgePointStorage.java b/src/main/java/com/simibubi/create/content/trains/graph/EdgePointStorage.java similarity index 89% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/EdgePointStorage.java rename to src/main/java/com/simibubi/create/content/trains/graph/EdgePointStorage.java index d12c50d9c..b4ff98c61 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/EdgePointStorage.java +++ b/src/main/java/com/simibubi/create/content/trains/graph/EdgePointStorage.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.management.edgePoint; +package com.simibubi.create.content.trains.graph; import java.util.Collection; import java.util.HashMap; @@ -7,9 +7,7 @@ import java.util.Map.Entry; import java.util.UUID; import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.DimensionPalette; -import com.simibubi.create.content.logistics.trains.TrackGraph; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.TrackEdgePoint; +import com.simibubi.create.content.trains.signal.TrackEdgePoint; import com.simibubi.create.foundation.utility.NBTHelper; import net.minecraft.nbt.CompoundTag; diff --git a/src/main/java/com/simibubi/create/content/trains/graph/EdgePointType.java b/src/main/java/com/simibubi/create/content/trains/graph/EdgePointType.java new file mode 100644 index 000000000..411e27875 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/graph/EdgePointType.java @@ -0,0 +1,58 @@ +package com.simibubi.create.content.trains.graph; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.Supplier; + +import com.simibubi.create.Create; +import com.simibubi.create.content.trains.observer.TrackObserver; +import com.simibubi.create.content.trains.signal.SignalBoundary; +import com.simibubi.create.content.trains.signal.TrackEdgePoint; +import com.simibubi.create.content.trains.station.GlobalStation; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; + +public class EdgePointType { + + public static final Map> TYPES = new HashMap<>(); + private ResourceLocation id; + private Supplier factory; + + public static final EdgePointType SIGNAL = + register(Create.asResource("signal"), SignalBoundary::new); + public static final EdgePointType STATION = + register(Create.asResource("station"), GlobalStation::new); + public static final EdgePointType OBSERVER = + register(Create.asResource("observer"), TrackObserver::new); + + public static EdgePointType register(ResourceLocation id, Supplier factory) { + EdgePointType type = new EdgePointType<>(id, factory); + TYPES.put(id, type); + return type; + } + + public EdgePointType(ResourceLocation id, Supplier factory) { + this.id = id; + this.factory = factory; + } + + public T create() { + T t = factory.get(); + t.setType(this); + return t; + } + + public ResourceLocation getId() { + return id; + } + + public static TrackEdgePoint read(FriendlyByteBuf buffer, DimensionPalette dimensions) { + ResourceLocation type = buffer.readResourceLocation(); + EdgePointType edgePointType = TYPES.get(type); + TrackEdgePoint point = edgePointType.create(); + point.read(buffer, dimensions); + return point; + } + +} diff --git a/src/main/java/com/simibubi/create/content/trains/graph/TrackEdge.java b/src/main/java/com/simibubi/create/content/trains/graph/TrackEdge.java new file mode 100644 index 000000000..997b21f3e --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/graph/TrackEdge.java @@ -0,0 +1,253 @@ +package com.simibubi.create.content.trains.graph; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; + +import javax.annotation.Nullable; + +import com.google.common.collect.ImmutableList; +import com.simibubi.create.content.trains.track.BezierConnection; +import com.simibubi.create.content.trains.track.TrackMaterial; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction.Axis; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.Mth; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; + +public class TrackEdge { + + public TrackNode node1; + public TrackNode node2; + BezierConnection turn; + EdgeData edgeData; + boolean interDimensional; + TrackMaterial trackMaterial; + + public TrackEdge(TrackNode node1, TrackNode node2, BezierConnection turn, TrackMaterial trackMaterial) { + this.interDimensional = !node1.location.dimension.equals(node2.location.dimension); + this.edgeData = new EdgeData(this); + this.node1 = node1; + this.node2 = node2; + this.turn = turn; + this.trackMaterial = trackMaterial; + } + + public TrackMaterial getTrackMaterial() { + return trackMaterial; + } + + public boolean isTurn() { + return turn != null; + } + + public boolean isInterDimensional() { + return interDimensional; + } + + public EdgeData getEdgeData() { + return edgeData; + } + + public BezierConnection getTurn() { + return turn; + } + + public Vec3 getDirection(boolean fromFirst) { + return getPosition(null, fromFirst ? 0.25f : 1).subtract(getPosition(null, fromFirst ? 0 : 0.75f)) + .normalize(); + } + + public Vec3 getDirectionAt(double t) { + double length = getLength(); + double step = .5f / length; + t /= length; + Vec3 ahead = getPosition(null, Math.min(1, t + step)); + Vec3 behind = getPosition(null, Math.max(0, t - step)); + return ahead.subtract(behind) + .normalize(); + } + + public boolean canTravelTo(TrackEdge other) { + if (isInterDimensional() || other.isInterDimensional()) + return true; + Vec3 newDirection = other.getDirection(true); + return getDirection(false).dot(newDirection) > 7 / 8f; + } + + public double getLength() { + return isInterDimensional() ? 0 + : isTurn() ? turn.getLength() + : node1.location.getLocation() + .distanceTo(node2.location.getLocation()); + } + + public double incrementT(double currentT, double distance) { + boolean tooFar = Math.abs(distance) > 5; + double length = getLength(); + distance = distance / (length == 0 ? 1 : length); + return !tooFar && isTurn() ? turn.incrementT(currentT, distance) : currentT + distance; + } + + public Vec3 getPosition(@Nullable TrackGraph trackGraph, double t) { + if (isTurn()) + return turn.getPosition(Mth.clamp(t, 0, 1)); + if (trackGraph != null && (node1.location.yOffsetPixels != 0 || node2.location.yOffsetPixels != 0)) { + Vec3 positionSmoothed = getPositionSmoothed(trackGraph, t); + if (positionSmoothed != null) + return positionSmoothed; + } + return VecHelper.lerp((float) t, node1.location.getLocation(), node2.location.getLocation()); + } + + public Vec3 getNormal(@Nullable TrackGraph trackGraph, double t) { + if (isTurn()) + return turn.getNormal(Mth.clamp(t, 0, 1)); + if (trackGraph != null && (node1.location.yOffsetPixels != 0 || node2.location.yOffsetPixels != 0)) { + Vec3 normalSmoothed = getNormalSmoothed(trackGraph, t); + if (normalSmoothed != null) + return normalSmoothed; + } + return node1.getNormal(); + } + + @Nullable + public Vec3 getPositionSmoothed(TrackGraph trackGraph, double t) { + Vec3 node1Location = null; + Vec3 node2Location = null; + for (TrackEdge trackEdge : trackGraph.getConnectionsFrom(node1) + .values()) + if (trackEdge.isTurn()) + node1Location = trackEdge.getPosition(trackGraph, 0); + for (TrackEdge trackEdge : trackGraph.getConnectionsFrom(node2) + .values()) + if (trackEdge.isTurn()) + node2Location = trackEdge.getPosition(trackGraph, 0); + if (node1Location == null || node2Location == null) + return null; + return VecHelper.lerp((float) t, node1Location, node2Location); + } + + @Nullable + public Vec3 getNormalSmoothed(TrackGraph trackGraph, double t) { + Vec3 node1Normal = null; + Vec3 node2Normal = null; + for (TrackEdge trackEdge : trackGraph.getConnectionsFrom(node1) + .values()) + if (trackEdge.isTurn()) + node1Normal = trackEdge.getNormal(trackGraph, 0); + for (TrackEdge trackEdge : trackGraph.getConnectionsFrom(node2) + .values()) + if (trackEdge.isTurn()) + node2Normal = trackEdge.getNormal(trackGraph, 0); + if (node1Normal == null || node2Normal == null) + return null; + return VecHelper.lerp(0.5f, node1Normal, node2Normal); + } + + public Collection getIntersection(TrackNode node1, TrackNode node2, TrackEdge other, TrackNode other1, + TrackNode other2) { + Vec3 v1 = node1.location.getLocation(); + Vec3 v2 = node2.location.getLocation(); + Vec3 w1 = other1.location.getLocation(); + Vec3 w2 = other2.location.getLocation(); + + if (isInterDimensional() || other.isInterDimensional()) + return Collections.emptyList(); + if (v1.y != v2.y || v1.y != w1.y || v1.y != w2.y) + return Collections.emptyList(); + + if (!isTurn()) { + if (!other.isTurn()) + return ImmutableList.of(VecHelper.intersectRanged(v1, w1, v2, w2, Axis.Y)); + return other.getIntersection(other1, other2, this, node1, node2) + .stream() + .map(a -> new double[] { a[1], a[0] }) + .toList(); + } + + AABB bb = turn.getBounds(); + + if (!other.isTurn()) { + if (!bb.intersects(w1, w2)) + return Collections.emptyList(); + + Vec3 seg1 = v1; + Vec3 seg2 = null; + double t = 0; + + Collection intersections = new ArrayList<>(); + for (int i = 0; i < turn.getSegmentCount(); i++) { + double tOffset = t; + t += .5; + seg2 = getPosition(null, t / getLength()); + double[] intersection = VecHelper.intersectRanged(seg1, w1, seg2, w2, Axis.Y); + seg1 = seg2; + if (intersection == null) + continue; + intersection[0] += tOffset; + intersections.add(intersection); + } + + return intersections; + } + + if (!bb.intersects(other.turn.getBounds())) + return Collections.emptyList(); + + Vec3 seg1 = v1; + Vec3 seg2 = null; + double t = 0; + + Collection intersections = new ArrayList<>(); + for (int i = 0; i < turn.getSegmentCount(); i++) { + double tOffset = t; + t += .5; + seg2 = getPosition(null, t / getLength()); + + Vec3 otherSeg1 = w1; + Vec3 otherSeg2 = null; + double u = 0; + + for (int j = 0; j < other.turn.getSegmentCount(); j++) { + double uOffset = u; + u += .5; + otherSeg2 = other.getPosition(null, u / other.getLength()); + + double[] intersection = VecHelper.intersectRanged(seg1, otherSeg1, seg2, otherSeg2, Axis.Y); + otherSeg1 = otherSeg2; + + if (intersection == null) + continue; + + intersection[0] += tOffset; + intersection[1] += uOffset; + intersections.add(intersection); + } + + seg1 = seg2; + } + + return intersections; + } + + public CompoundTag write(DimensionPalette dimensions) { + CompoundTag baseCompound = isTurn() ? turn.write(BlockPos.ZERO) : new CompoundTag(); + baseCompound.put("Signals", edgeData.write(dimensions)); + baseCompound.putString("Material", getTrackMaterial().id.toString()); + return baseCompound; + } + + public static TrackEdge read(TrackNode node1, TrackNode node2, CompoundTag tag, TrackGraph graph, + DimensionPalette dimensions) { + TrackEdge trackEdge = + new TrackEdge(node1, node2, tag.contains("Positions") ? new BezierConnection(tag, BlockPos.ZERO) : null, + TrackMaterial.deserialize(tag.getString("Material"))); + trackEdge.edgeData = EdgeData.read(tag.getCompound("Signals"), trackEdge, graph, dimensions); + return trackEdge; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/TrackEdgeIntersection.java b/src/main/java/com/simibubi/create/content/trains/graph/TrackEdgeIntersection.java similarity index 88% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/TrackEdgeIntersection.java rename to src/main/java/com/simibubi/create/content/trains/graph/TrackEdgeIntersection.java index eeea62a1e..954df2a81 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/TrackEdgeIntersection.java +++ b/src/main/java/com/simibubi/create/content/trains/graph/TrackEdgeIntersection.java @@ -1,9 +1,7 @@ -package com.simibubi.create.content.logistics.trains.management.edgePoint; +package com.simibubi.create.content.trains.graph; import java.util.UUID; -import com.simibubi.create.content.logistics.trains.DimensionPalette; -import com.simibubi.create.content.logistics.trains.TrackNodeLocation; import com.simibubi.create.foundation.utility.Couple; import net.minecraft.nbt.CompoundTag; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraph.java b/src/main/java/com/simibubi/create/content/trains/graph/TrackGraph.java similarity index 94% rename from src/main/java/com/simibubi/create/content/logistics/trains/TrackGraph.java rename to src/main/java/com/simibubi/create/content/trains/graph/TrackGraph.java index 897713e94..10cace626 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraph.java +++ b/src/main/java/com/simibubi/create/content/trains/graph/TrackGraph.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains; +package com.simibubi.create.content.trains.graph; import java.util.ArrayList; import java.util.Collection; @@ -19,15 +19,12 @@ import java.util.stream.Collectors; import javax.annotation.Nullable; import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.TrackNodeLocation.DiscoveredLocation; -import com.simibubi.create.content.logistics.trains.entity.Train; -import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgeData; -import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointManager; -import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointStorage; -import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType; -import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackEdgeIntersection; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalEdgeGroup; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.TrackEdgePoint; +import com.simibubi.create.content.trains.entity.Train; +import com.simibubi.create.content.trains.graph.TrackNodeLocation.DiscoveredLocation; +import com.simibubi.create.content.trains.signal.SignalEdgeGroup; +import com.simibubi.create.content.trains.signal.TrackEdgePoint; +import com.simibubi.create.content.trains.track.BezierConnection; +import com.simibubi.create.content.trains.track.TrackMaterial; import com.simibubi.create.foundation.utility.Color; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.NBTHelper; @@ -393,14 +390,15 @@ public class TrackGraph { return connectionsFrom.get(nodes.getSecond()); } - public void connectNodes(LevelAccessor reader, TrackNodeLocation location, TrackNodeLocation location2, + public void connectNodes(LevelAccessor reader, DiscoveredLocation location, DiscoveredLocation location2, @Nullable BezierConnection turn) { TrackNode node1 = nodes.get(location); TrackNode node2 = nodes.get(location2); boolean bezier = turn != null; - TrackEdge edge = new TrackEdge(node1, node2, turn); - TrackEdge edge2 = new TrackEdge(node2, node1, bezier ? turn.secondary() : null); + TrackMaterial material = bezier ? turn.getMaterial() : location2.materialA; + TrackEdge edge = new TrackEdge(node1, node2, turn, material); + TrackEdge edge2 = new TrackEdge(node2, node1, bezier ? turn.secondary() : null, material); for (TrackGraph graph : Create.RAILWAYS.trackNetworks.values()) { for (TrackNode otherNode1 : graph.nodes.values()) { diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphBounds.java b/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphBounds.java similarity index 89% rename from src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphBounds.java rename to src/main/java/com/simibubi/create/content/trains/graph/TrackGraphBounds.java index 52e30d0f8..e2d06385c 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphBounds.java +++ b/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphBounds.java @@ -1,9 +1,11 @@ -package com.simibubi.create.content.logistics.trains; +package com.simibubi.create.content.trains.graph; import java.util.ArrayList; import java.util.List; import java.util.Map; +import com.simibubi.create.content.trains.track.BezierConnection; + import net.minecraft.resources.ResourceKey; import net.minecraft.world.level.Level; import net.minecraft.world.phys.AABB; diff --git a/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphHelper.java b/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphHelper.java new file mode 100644 index 000000000..a29a6f29d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphHelper.java @@ -0,0 +1,194 @@ +package com.simibubi.create.content.trains.graph; + +import java.util.Collection; +import java.util.Map; +import java.util.Map.Entry; + +import javax.annotation.Nullable; + +import com.simibubi.create.Create; +import com.simibubi.create.content.trains.graph.TrackNodeLocation.DiscoveredLocation; +import com.simibubi.create.content.trains.track.BezierConnection; +import com.simibubi.create.content.trains.track.BezierTrackPointLocation; +import com.simibubi.create.content.trains.track.ITrackBlock; +import com.simibubi.create.content.trains.track.TrackBlockEntity; +import com.simibubi.create.foundation.utility.Couple; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class TrackGraphHelper { + + @Nullable + public static TrackGraphLocation getGraphLocationAt(Level level, BlockPos pos, AxisDirection targetDirection, + Vec3 targetAxis) { + BlockState trackBlockState = level.getBlockState(pos); + if (!(trackBlockState.getBlock()instanceof ITrackBlock track)) + return null; + + Vec3 axis = targetAxis.scale(targetDirection.getStep()); + double length = axis.length(); + TrackGraph graph = null; + + // Case 1: Centre of block lies on a node + + TrackNodeLocation location = new TrackNodeLocation(Vec3.atBottomCenterOf(pos) + .add(0, track.getElevationAtCenter(level, pos, trackBlockState), 0)).in(level); + graph = Create.RAILWAYS.sided(level) + .getGraph(level, location); + if (graph != null) { + TrackNode node = graph.locateNode(location); + if (node != null) { + Map connectionsFrom = graph.getConnectionsFrom(node); + for (Entry entry : connectionsFrom.entrySet()) { + TrackNode backNode = entry.getKey(); + Vec3 direction = entry.getValue() + .getDirection(true); + if (direction.scale(length) + .distanceToSqr(axis.scale(-1)) > 1 / 4096f) + continue; + + TrackGraphLocation graphLocation = new TrackGraphLocation(); + graphLocation.edge = Couple.create(node.getLocation(), backNode.getLocation()); + graphLocation.position = 0; + graphLocation.graph = graph; + return graphLocation; + } + } + } + + // Case 2: Center of block is between two nodes + + Collection ends = track.getConnected(level, pos, trackBlockState, true, null); + Vec3 start = Vec3.atBottomCenterOf(pos) + .add(0, track.getElevationAtCenter(level, pos, trackBlockState), 0); + + TrackNode frontNode = null; + TrackNode backNode = null; + double position = 0; + boolean singleTrackPiece = true; + + for (DiscoveredLocation current : ends) { + Vec3 offset = current.getLocation() + .subtract(start) + .normalize() + .scale(length); + + Vec3 compareOffset = offset.multiply(1, 0, 1) + .normalize(); + boolean forward = compareOffset.distanceToSqr(axis.multiply(-1, 0, -1) + .normalize()) < 1 / 4096f; + boolean backwards = compareOffset.distanceToSqr(axis.multiply(1, 0, 1) + .normalize()) < 1 / 4096f; + + if (!forward && !backwards) + continue; + + DiscoveredLocation previous = null; + double distance = 0; + + for (int i = 0; i < 100 && distance < 32; i++) { + DiscoveredLocation loc = current; + if (graph == null) + graph = Create.RAILWAYS.sided(level) + .getGraph(level, loc); + + if (graph == null || graph.locateNode(loc) == null) { + singleTrackPiece = false; + Collection list = ITrackBlock.walkConnectedTracks(level, loc, true); + for (DiscoveredLocation discoveredLocation : list) { + if (discoveredLocation == previous) + continue; + Vec3 diff = discoveredLocation.getLocation() + .subtract(loc.getLocation()); + if ((forward ? axis.scale(-1) : axis).distanceToSqr(diff.normalize() + .scale(length)) > 1 / 4096f) + continue; + + previous = current; + current = discoveredLocation; + distance += diff.length(); + break; + } + continue; + } + + TrackNode node = graph.locateNode(loc); + if (forward) + frontNode = node; + if (backwards) { + backNode = node; + position = distance + axis.length() / 2; + } + break; + } + } + + if (frontNode == null || backNode == null) + return null; + + if (singleTrackPiece) + position = frontNode.getLocation() + .getLocation() + .distanceTo(backNode.getLocation() + .getLocation()) + / 2.0; + + TrackGraphLocation graphLocation = new TrackGraphLocation(); + graphLocation.edge = Couple.create(backNode.getLocation(), frontNode.getLocation()); + graphLocation.position = position; + graphLocation.graph = graph; + return graphLocation; + } + + @Nullable + public static TrackGraphLocation getBezierGraphLocationAt(Level level, BlockPos pos, AxisDirection targetDirection, + BezierTrackPointLocation targetBezier) { + BlockState state = level.getBlockState(pos); + + if (!(state.getBlock() instanceof ITrackBlock track)) + return null; + if (!(level.getBlockEntity(pos) instanceof TrackBlockEntity trackBE)) + return null; + BezierConnection bc = trackBE.getConnections() + .get(targetBezier.curveTarget()); + if (bc == null || !bc.isPrimary()) + return null; + + TrackNodeLocation targetLoc = new TrackNodeLocation(bc.starts.getSecond()).in(level); + if (bc.smoothing != null) + targetLoc.yOffsetPixels = bc.smoothing.getSecond(); + + for (DiscoveredLocation location : track.getConnected(level, pos, state, true, null)) { + TrackGraph graph = Create.RAILWAYS.sided(level) + .getGraph(level, location); + if (graph == null) + continue; + TrackNode targetNode = graph.locateNode(targetLoc); + if (targetNode == null) + continue; + TrackNode node = graph.locateNode(location); + TrackEdge edge = graph.getConnectionsFrom(node) + .get(targetNode); + if (edge == null) + continue; + + TrackGraphLocation graphLocation = new TrackGraphLocation(); + graphLocation.graph = graph; + graphLocation.edge = Couple.create(location, targetLoc); + graphLocation.position = (targetBezier.segment() + 1) / 2f; + if (targetDirection == AxisDirection.POSITIVE) { + graphLocation.edge = graphLocation.edge.swap(); + graphLocation.position = edge.getLength() - graphLocation.position; + } + + return graphLocation; + } + + return null; + } + +} diff --git a/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphLocation.java b/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphLocation.java new file mode 100644 index 000000000..edf6ff213 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphLocation.java @@ -0,0 +1,11 @@ +package com.simibubi.create.content.trains.graph; + +import com.simibubi.create.foundation.utility.Couple; + +public class TrackGraphLocation { + + public TrackGraph graph; + public Couple edge; + public double position; + +} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphPacket.java b/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphPacket.java new file mode 100644 index 000000000..8a2811761 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphPacket.java @@ -0,0 +1,25 @@ +package com.simibubi.create.content.trains.graph; + +import java.util.UUID; + +import com.simibubi.create.CreateClient; +import com.simibubi.create.content.trains.GlobalRailwayManager; +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraftforge.network.NetworkEvent.Context; + +public abstract class TrackGraphPacket extends SimplePacketBase { + + public UUID graphId; + public int netId; + public boolean packetDeletesGraph; + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> handle(CreateClient.RAILWAYS, CreateClient.RAILWAYS.getOrCreateGraph(graphId, netId))); + return true; + } + + protected abstract void handle(GlobalRailwayManager manager, TrackGraph graph); + +} diff --git a/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphRequestPacket.java b/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphRequestPacket.java new file mode 100644 index 000000000..982158f19 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphRequestPacket.java @@ -0,0 +1,39 @@ +package com.simibubi.create.content.trains.graph; + +import com.simibubi.create.Create; +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.network.NetworkEvent.Context; + +public class TrackGraphRequestPacket extends SimplePacketBase { + + private int netId; + + public TrackGraphRequestPacket(int netId) { + this.netId = netId; + } + + public TrackGraphRequestPacket(FriendlyByteBuf buffer) { + netId = buffer.readInt(); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeInt(netId); + } + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> { + for (TrackGraph trackGraph : Create.RAILWAYS.trackNetworks.values()) { + if (trackGraph.netId == netId) { + Create.RAILWAYS.sync.sendFullGraphTo(trackGraph, context.getSender()); + break; + } + } + }); + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphRollCallPacket.java b/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphRollCallPacket.java new file mode 100644 index 000000000..f95e768e2 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphRollCallPacket.java @@ -0,0 +1,79 @@ +package com.simibubi.create.content.trains.graph; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +import com.simibubi.create.AllPackets; +import com.simibubi.create.Create; +import com.simibubi.create.content.trains.GlobalRailwayManager; +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.network.NetworkEvent.Context; + +public class TrackGraphRollCallPacket extends SimplePacketBase { + + int[] ints; + + public TrackGraphRollCallPacket() { + GlobalRailwayManager manager = Create.RAILWAYS; + ints = new int[manager.trackNetworks.size() * 2]; + int i = 0; + for (TrackGraph trackGraph : manager.trackNetworks.values()) { + ints[i] = trackGraph.netId; + ints[i + 1] = trackGraph.getChecksum(); + i += 2; + } + } + + public TrackGraphRollCallPacket(FriendlyByteBuf buffer) { + ints = new int[buffer.readVarInt()]; + for (int i = 0; i < ints.length; i++) + ints[i] = buffer.readInt(); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeVarInt(ints.length); + for (int i : ints) + buffer.writeInt(i); + } + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> { + GlobalRailwayManager manager = Create.RAILWAYS.sided(null); + Set unusedIds = new HashSet<>(manager.trackNetworks.keySet()); + List failedIds = new ArrayList<>(); + Map idByNetId = new HashMap<>(); + manager.trackNetworks.forEach((uuid, g) -> idByNetId.put(g.netId, uuid)); + + for (int i = 0; i < ints.length; i += 2) { + UUID uuid = idByNetId.get(ints[i]); + if (uuid == null) { + failedIds.add(ints[i]); + continue; + } + unusedIds.remove(uuid); + TrackGraph trackGraph = manager.trackNetworks.get(uuid); + if (trackGraph.getChecksum() == ints[i + 1]) + continue; + Create.LOGGER.warn("Track network: " + uuid.toString() + .substring(0, 6) + " failed its checksum; Requesting refresh"); + failedIds.add(ints[i]); + } + + for (Integer failed : failedIds) + AllPackets.getChannel().sendToServer(new TrackGraphRequestPacket(failed)); + for (UUID unused : unusedIds) + manager.trackNetworks.remove(unused); + }); + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphSync.java b/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphSync.java similarity index 82% rename from src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphSync.java rename to src/main/java/com/simibubi/create/content/trains/graph/TrackGraphSync.java index dfd5d0e36..b9ac69f6a 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphSync.java +++ b/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphSync.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains; +package com.simibubi.create.content.trains.graph; import java.util.ArrayList; import java.util.Collections; @@ -9,12 +9,11 @@ import java.util.UUID; import javax.annotation.Nullable; import com.google.common.collect.ImmutableList; +import com.simibubi.create.AllPackets; import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.EdgeGroupColor; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalEdgeGroupPacket; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.TrackEdgePoint; -import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.content.trains.signal.EdgeGroupColor; +import com.simibubi.create.content.trains.signal.SignalEdgeGroupPacket; +import com.simibubi.create.content.trains.signal.TrackEdgePoint; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Pair; @@ -33,7 +32,7 @@ public class TrackGraphSync { for (TrackGraphPacket packet : queuedPackets) { if (!packet.packetDeletesGraph && !Create.RAILWAYS.trackNetworks.containsKey(packet.graphId)) continue; - AllPackets.channel.send(PacketDistributor.ALL.noArg(), packet); + AllPackets.getChannel().send(PacketDistributor.ALL.noArg(), packet); rollCallIn = 3; } @@ -60,7 +59,7 @@ public class TrackGraphSync { public void edgeAdded(TrackGraph graph, TrackNode node1, TrackNode node2, TrackEdge edge) { flushGraphPacket(graph); currentGraphSyncPacket.addedEdges - .add(Pair.of(Couple.create(node1.getNetId(), node2.getNetId()), edge.getTurn())); + .add(Pair.of(Pair.of(Couple.create(node1.getNetId(), node2.getNetId()), edge.getTrackMaterial()), edge.getTurn())); currentPayload++; } @@ -82,7 +81,7 @@ public class TrackGraphSync { if (currentGraphSyncPacket.addedNodes.remove(nodeId) == null) currentGraphSyncPacket.removedNodes.add(nodeId); currentGraphSyncPacket.addedEdges.removeIf(pair -> { - Couple ids = pair.getFirst(); + Couple ids = pair.getFirst().getFirst(); return ids.getFirst() .intValue() == nodeId || ids.getSecond() @@ -106,16 +105,16 @@ public class TrackGraphSync { // public void sendEdgeGroups(List ids, List colors, ServerPlayer player) { - AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> player), + AllPackets.getChannel().send(PacketDistributor.PLAYER.with(() -> player), new SignalEdgeGroupPacket(ids, colors, true)); } public void edgeGroupCreated(UUID id, EdgeGroupColor color) { - AllPackets.channel.send(PacketDistributor.ALL.noArg(), new SignalEdgeGroupPacket(id, color)); + AllPackets.getChannel().send(PacketDistributor.ALL.noArg(), new SignalEdgeGroupPacket(id, color)); } public void edgeGroupRemoved(UUID id) { - AllPackets.channel.send(PacketDistributor.ALL.noArg(), + AllPackets.getChannel().send(PacketDistributor.ALL.noArg(), new SignalEdgeGroupPacket(ImmutableList.of(id), Collections.emptyList(), false)); } @@ -156,7 +155,7 @@ public class TrackGraphSync { graph.connectionsByNode.get(node) .forEach((node2, edge) -> { Couple key = Couple.create(node.getNetId(), node2.getNetId()); - currentPacket.addedEdges.add(Pair.of(key, edge.getTurn())); + currentPacket.addedEdges.add(Pair.of(Pair.of(key, edge.getTrackMaterial()), edge.getTurn())); currentPacket.syncEdgeData(node, node2, edge); }); @@ -184,11 +183,11 @@ public class TrackGraphSync { } private void sendRollCall() { - AllPackets.channel.send(PacketDistributor.ALL.noArg(), new TrackGraphRollCallPacket()); + AllPackets.getChannel().send(PacketDistributor.ALL.noArg(), new TrackGraphRollCallPacket()); } private TrackGraphSyncPacket flushAndCreateNew(TrackGraph graph, ServerPlayer player, TrackGraphSyncPacket packet) { - AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> player), packet); + AllPackets.getChannel().send(PacketDistributor.PLAYER.with(() -> player), packet); packet = new TrackGraphSyncPacket(graph.id, graph.netId); return packet; } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphSyncPacket.java b/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphSyncPacket.java similarity index 90% rename from src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphSyncPacket.java rename to src/main/java/com/simibubi/create/content/trains/graph/TrackGraphSyncPacket.java index 33e5e0790..e5cda7b42 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphSyncPacket.java +++ b/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphSyncPacket.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains; +package com.simibubi.create.content.trains.graph; import java.util.ArrayList; import java.util.HashMap; @@ -9,9 +9,10 @@ import java.util.Objects; import java.util.UUID; import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgeData; -import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.TrackEdgePoint; +import com.simibubi.create.content.trains.GlobalRailwayManager; +import com.simibubi.create.content.trains.signal.TrackEdgePoint; +import com.simibubi.create.content.trains.track.BezierConnection; +import com.simibubi.create.content.trains.track.TrackMaterial; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Pair; import com.simibubi.create.foundation.utility.VecHelper; @@ -22,7 +23,7 @@ import net.minecraft.world.phys.Vec3; public class TrackGraphSyncPacket extends TrackGraphPacket { Map> addedNodes; - List, BezierConnection>> addedEdges; + List, TrackMaterial>, BezierConnection>> addedEdges; List removedNodes; List addedEdgePoints; List removedEdgePoints; @@ -79,7 +80,7 @@ public class TrackGraphSyncPacket extends TrackGraphPacket { size = buffer.readVarInt(); for (int i = 0; i < size; i++) addedEdges.add( - Pair.of(Couple.create(buffer::readVarInt), buffer.readBoolean() ? new BezierConnection(buffer) : null)); + Pair.of(Pair.of(Couple.create(buffer::readVarInt), TrackMaterial.deserialize(buffer.readUtf())), buffer.readBoolean() ? new BezierConnection(buffer) : null)); size = buffer.readVarInt(); for (int i = 0; i < size; i++) @@ -134,8 +135,9 @@ public class TrackGraphSyncPacket extends TrackGraphPacket { buffer.writeVarInt(addedEdges.size()); addedEdges.forEach(pair -> { - pair.getFirst() + pair.getFirst().getFirst() .forEach(buffer::writeVarInt); + buffer.writeUtf(pair.getFirst().getSecond().id.toString()); BezierConnection turn = pair.getSecond(); buffer.writeBoolean(turn != null); if (turn != null) @@ -192,13 +194,13 @@ public class TrackGraphSyncPacket extends TrackGraphPacket { graph.loadNode(nodeLocation.getFirst(), nodeId, nodeLocation.getSecond()); } - for (Pair, BezierConnection> pair : addedEdges) { - Couple nodes = pair.getFirst() + for (Pair, TrackMaterial>, BezierConnection> pair : addedEdges) { + Couple nodes = pair.getFirst().getFirst() .map(graph::getNode); TrackNode node1 = nodes.getFirst(); TrackNode node2 = nodes.getSecond(); if (node1 != null && node2 != null) - graph.putConnection(node1, node2, new TrackEdge(node1, node2, pair.getSecond())); + graph.putConnection(node1, node2, new TrackEdge(node1, node2, pair.getSecond(), pair.getFirst().getSecond())); } for (TrackEdgePoint edgePoint : addedEdgePoints) @@ -268,4 +270,4 @@ public class TrackGraphSyncPacket extends TrackGraphPacket { updatedEdgeData.put(key, Pair.of(groupType, list)); } -} \ No newline at end of file +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphVisualizer.java b/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphVisualizer.java similarity index 78% rename from src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphVisualizer.java rename to src/main/java/com/simibubi/create/content/trains/graph/TrackGraphVisualizer.java index 66988f041..3083ba5a5 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/TrackGraphVisualizer.java +++ b/src/main/java/com/simibubi/create/content/trains/graph/TrackGraphVisualizer.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains; +package com.simibubi.create.content.trains.graph; import java.util.Iterator; import java.util.Map; @@ -10,13 +10,13 @@ import org.lwjgl.glfw.GLFW; import com.simibubi.create.AllKeys; import com.simibubi.create.Create; import com.simibubi.create.CreateClient; -import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgeData; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalBoundary; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalEdgeGroup; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.TrackEdgePoint; +import com.simibubi.create.content.trains.signal.SignalBoundary; +import com.simibubi.create.content.trains.signal.SignalEdgeGroup; +import com.simibubi.create.content.trains.signal.TrackEdgePoint; +import com.simibubi.create.content.trains.track.BezierConnection; +import com.simibubi.create.foundation.outliner.Outliner; import com.simibubi.create.foundation.utility.Color; import com.simibubi.create.foundation.utility.Pair; -import com.simibubi.create.foundation.utility.outliner.Outliner; import net.minecraft.client.Minecraft; import net.minecraft.world.entity.Entity; @@ -37,7 +37,6 @@ public class TrackGraphVisualizer { Vec3 camera = cameraEntity.getEyePosition(); Outliner outliner = CreateClient.OUTLINER; - boolean ctrl = false; // AllKeys.isKeyDown(GLFW.GLFW_KEY_LEFT_CONTROL); Map allGroups = Create.RAILWAYS.sided(null).signalEdgeGroups; float width = 1 / 8f; @@ -71,8 +70,8 @@ public class TrackGraphVisualizer { continue; Vec3 yOffset = new Vec3(0, (other.hashCode() > hashCode ? 6 : 5) / 64f, 0); - Vec3 startPoint = edge.getPosition(0); - Vec3 endPoint = edge.getPosition(1); + Vec3 startPoint = edge.getPosition(graph, 0); + Vec3 endPoint = edge.getPosition(graph, 1); if (!edge.isTurn()) { @@ -91,11 +90,13 @@ public class TrackGraphVisualizer { group = allGroups.get(boundary.getGroup(node)); if (group != null) - outliner.showLine(Pair.of(boundary, edge), - edge.getPosition(prev + (prev == 0 ? 0 : 1 / 16f / length)) - .add(yOffset), - edge.getPosition((prev = boundary.getLocationOn(edge) / length) - 1 / 16f / length) - .add(yOffset)) + outliner + .showLine(Pair.of(boundary, edge), + edge.getPosition(graph, prev + (prev == 0 ? 0 : 1 / 16f / length)) + .add(yOffset), + edge.getPosition(graph, + (prev = boundary.getLocationOn(edge) / length) - 1 / 16f / length) + .add(yOffset)) .colored(group.color.get()) .lineWidth(width); @@ -104,7 +105,7 @@ public class TrackGraphVisualizer { if (prevBoundary != null) { group = allGroups.get(prevBoundary.getGroup(other)); if (group != null) - outliner.showLine(edge, edge.getPosition(prev + 1 / 16f / length) + outliner.showLine(edge, edge.getPosition(graph, prev + 1 / 16f / length) .add(yOffset), endPoint.add(yOffset)) .colored(group.color.get()) .lineWidth(width); @@ -154,16 +155,18 @@ public class TrackGraphVisualizer { for (int i = 0; i <= turn.getSegmentCount(); i++) { double f = i * 1f / turn.getSegmentCount(); double position = f * turn.getLength(); - Vec3 current = edge.getPosition(f); + Vec3 current = edge.getPosition(graph, f); if (previous != null) { if (currentBoundary != null && position > currentBoundaryPosition) { - current = edge.getPosition((currentBoundaryPosition - width) / turn.getLength()); + current = + edge.getPosition(graph, (currentBoundaryPosition - width) / turn.getLength()); outliner .showLine(Pair.of(edge, previous), previous.add(yOffset), current.add(yOffset)) .colored(currentColour) .lineWidth(width); - current = edge.getPosition((currentBoundaryPosition + width) / turn.getLength()); + current = + edge.getPosition(graph, (currentBoundaryPosition + width) / turn.getLength()); previous = current; UUID newId = currentBoundary.getGroup(other); if (newId != null && allGroups.containsKey(newId)) @@ -197,7 +200,7 @@ public class TrackGraphVisualizer { Vec3 previous = null; BezierConnection turn = edge.getTurn(); for (int i = 0; i <= turn.getSegmentCount(); i++) { - Vec3 current = edge.getPosition(i * 1f / turn.getSegmentCount()); + Vec3 current = edge.getPosition(graph, i * 1f / turn.getSegmentCount()); if (previous != null) outliner.showLine(Pair.of(edge, previous), previous.add(yOffset), current.add(yOffset)) .colored(singleEdgeGroup.color.get()) @@ -209,7 +212,7 @@ public class TrackGraphVisualizer { } } - public static void debugViewGraph(TrackGraph graph) { + public static void debugViewGraph(TrackGraph graph, boolean extended) { Minecraft mc = Minecraft.getInstance(); Entity cameraEntity = mc.cameraEntity; if (cameraEntity == null) @@ -262,9 +265,20 @@ public class TrackGraphVisualizer { yOffset = new Vec3(0, (other.hashCode() > hashCode ? 6 : 4) / 16f, 0); if (!edge.isTurn()) { - CreateClient.OUTLINER.showLine(edge, edge.getPosition(0) + if (extended) { + Vec3 materialPos = edge.getPosition(graph, 0.5) + .add(0, 1, 0); + CreateClient.OUTLINER.showItem(Pair.of(edge, edge.edgeData), materialPos, + edge.getTrackMaterial() + .asStack()); + CreateClient.OUTLINER.showAABB(edge.edgeData, AABB.ofSize(materialPos, .25, 0, .25) + .move(0, -0.5, 0)) + .lineWidth(1 / 16f) + .colored(graph.color); + } + CreateClient.OUTLINER.showLine(edge, edge.getPosition(graph, 0) .add(yOffset), - edge.getPosition(1) + edge.getPosition(graph, 1) .add(yOffset)) .colored(graph.color) .lineWidth(1 / 16f); @@ -273,8 +287,18 @@ public class TrackGraphVisualizer { Vec3 previous = null; BezierConnection turn = edge.getTurn(); + if (extended) { + Vec3 materialPos = edge.getPosition(graph, 0.5) + .add(0, 1, 0); + CreateClient.OUTLINER.showItem(Pair.of(edge, edge.edgeData), materialPos, edge.getTrackMaterial() + .asStack()); + CreateClient.OUTLINER.showAABB(edge.edgeData, AABB.ofSize(materialPos, .25, 0, .25) + .move(0, -0.5, 0)) + .lineWidth(1 / 16f) + .colored(graph.color); + } for (int i = 0; i <= turn.getSegmentCount(); i++) { - Vec3 current = edge.getPosition(i * 1f / turn.getSegmentCount()); + Vec3 current = edge.getPosition(graph, i * 1f / turn.getSegmentCount()); if (previous != null) CreateClient.OUTLINER .showLine(Pair.of(edge, previous), previous.add(yOffset), current.add(yOffset)) diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/TrackNode.java b/src/main/java/com/simibubi/create/content/trains/graph/TrackNode.java similarity index 88% rename from src/main/java/com/simibubi/create/content/logistics/trains/TrackNode.java rename to src/main/java/com/simibubi/create/content/trains/graph/TrackNode.java index 0944aaf64..3fc8312eb 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/TrackNode.java +++ b/src/main/java/com/simibubi/create/content/trains/graph/TrackNode.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains; +package com.simibubi.create.content.trains.graph; import net.minecraft.world.phys.Vec3; diff --git a/src/main/java/com/simibubi/create/content/trains/graph/TrackNodeLocation.java b/src/main/java/com/simibubi/create/content/trains/graph/TrackNodeLocation.java new file mode 100644 index 000000000..868bbc77c --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/graph/TrackNodeLocation.java @@ -0,0 +1,214 @@ +package com.simibubi.create.content.trains.graph; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +import com.simibubi.create.content.trains.track.BezierConnection; +import com.simibubi.create.content.trains.track.TrackMaterial; +import com.simibubi.create.foundation.utility.Iterate; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Vec3i; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; + +public class TrackNodeLocation extends Vec3i { + + public ResourceKey dimension; + public int yOffsetPixels; + + public TrackNodeLocation(Vec3 vec) { + this(vec.x, vec.y, vec.z); + } + + public TrackNodeLocation(double x, double y, double z) { + super(Math.round(x * 2), Math.floor(y) * 2, Math.round(z * 2)); + } + + public TrackNodeLocation in(Level level) { + return in(level.dimension()); + } + + public TrackNodeLocation in(ResourceKey dimension) { + this.dimension = dimension; + return this; + } + + private static TrackNodeLocation fromPackedPos(BlockPos bufferPos) { + return new TrackNodeLocation(bufferPos); + } + + private TrackNodeLocation(BlockPos readBlockPos) { + super(readBlockPos.getX(), readBlockPos.getY(), readBlockPos.getZ()); + } + + public Vec3 getLocation() { + return new Vec3(getX() / 2.0, getY() / 2.0 + yOffsetPixels / 16.0, getZ() / 2.0); + } + + public ResourceKey getDimension() { + return dimension; + } + + @Override + public boolean equals(Object pOther) { + return equalsIgnoreDim(pOther) && pOther instanceof TrackNodeLocation tnl + && Objects.equals(tnl.dimension, dimension); + } + + public boolean equalsIgnoreDim(Object pOther) { + return super.equals(pOther) && pOther instanceof TrackNodeLocation tnl && tnl.yOffsetPixels == yOffsetPixels; + } + + @Override + public int hashCode() { + return (getY() + ((getZ() + yOffsetPixels * 31) * 31 + dimension.hashCode()) * 31) * 31 + getX(); + } + + public CompoundTag write(DimensionPalette dimensions) { + CompoundTag c = NbtUtils.writeBlockPos(new BlockPos(this)); + if (dimensions != null) + c.putInt("D", dimensions.encode(dimension)); + if (yOffsetPixels != 0) + c.putInt("YO", yOffsetPixels); + return c; + } + + public static TrackNodeLocation read(CompoundTag tag, DimensionPalette dimensions) { + TrackNodeLocation location = fromPackedPos(NbtUtils.readBlockPos(tag)); + if (dimensions != null) + location.dimension = dimensions.decode(tag.getInt("D")); + location.yOffsetPixels = tag.getInt("YO"); + return location; + } + + public void send(FriendlyByteBuf buffer, DimensionPalette dimensions) { + buffer.writeVarInt(getX()); + buffer.writeShort(getY()); + buffer.writeVarInt(getZ()); + buffer.writeVarInt(yOffsetPixels); + buffer.writeVarInt(dimensions.encode(dimension)); + } + + public static TrackNodeLocation receive(FriendlyByteBuf buffer, DimensionPalette dimensions) { + TrackNodeLocation location = fromPackedPos(new BlockPos( + buffer.readVarInt(), + buffer.readShort(), + buffer.readVarInt() + )); + location.yOffsetPixels = buffer.readVarInt(); + location.dimension = dimensions.decode(buffer.readVarInt()); + return location; + } + + public Collection allAdjacent() { + Set set = new HashSet<>(); + Vec3 vec3 = getLocation().subtract(0, yOffsetPixels / 16.0, 0); + double step = 1 / 8f; + for (int x : Iterate.positiveAndNegative) + for (int y : Iterate.positiveAndNegative) + for (int z : Iterate.positiveAndNegative) + set.add(new BlockPos(vec3.add(x * step, y * step, z * step))); + return set; + } + + public static class DiscoveredLocation extends TrackNodeLocation { + + BezierConnection turn = null; + boolean forceNode = false; + Vec3 direction; + Vec3 normal; + TrackMaterial materialA; + TrackMaterial materialB; + + public DiscoveredLocation(Level level, double x, double y, double z) { + super(x, y, z); + in(level); + } + + public DiscoveredLocation(ResourceKey dimension, Vec3 vec) { + super(vec); + in(dimension); + } + + public DiscoveredLocation(Level level, Vec3 vec) { + this(level.dimension(), vec); + } + + public DiscoveredLocation materialA(TrackMaterial material) { + this.materialA = material; + return this; + } + + public DiscoveredLocation materialB(TrackMaterial material) { + this.materialB = material; + return this; + } + + public DiscoveredLocation materials(TrackMaterial materialA, TrackMaterial materialB) { + this.materialA = materialA; + this.materialB = materialB; + return this; + } + + public DiscoveredLocation viaTurn(BezierConnection turn) { + this.turn = turn; + if (turn != null) + forceNode(); + return this; + } + + public DiscoveredLocation forceNode() { + forceNode = true; + return this; + } + + public DiscoveredLocation withNormal(Vec3 normal) { + this.normal = normal; + return this; + } + + public DiscoveredLocation withYOffset(int yOffsetPixels) { + this.yOffsetPixels = yOffsetPixels; + return this; + } + + public DiscoveredLocation withDirection(Vec3 direction) { + this.direction = direction == null ? null : direction.normalize(); + return this; + } + + public boolean connectedViaTurn() { + return turn != null; + } + + public BezierConnection getTurn() { + return turn; + } + + public boolean shouldForceNode() { + return forceNode; + } + + public boolean differentMaterials() { + return materialA != materialB; + } + + public boolean notInLineWith(Vec3 direction) { + return this.direction != null + && Math.max(direction.dot(this.direction), direction.dot(this.direction.scale(-1))) < 7 / 8f; + } + + public Vec3 getDirection() { + return direction; + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/trains/observer/TrackObserver.java b/src/main/java/com/simibubi/create/content/trains/observer/TrackObserver.java new file mode 100644 index 000000000..fb599f296 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/observer/TrackObserver.java @@ -0,0 +1,111 @@ +package com.simibubi.create.content.trains.observer; + +import java.util.UUID; + +import com.simibubi.create.Create; +import com.simibubi.create.content.trains.entity.Train; +import com.simibubi.create.content.trains.graph.DimensionPalette; +import com.simibubi.create.content.trains.graph.TrackEdge; +import com.simibubi.create.content.trains.graph.TrackGraph; +import com.simibubi.create.content.trains.signal.SignalPropagator; +import com.simibubi.create.content.trains.signal.SingleBlockEntityEdgePoint; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; + +public class TrackObserver extends SingleBlockEntityEdgePoint { + + private int activated; + private ItemStack filter; + private UUID currentTrain; + + public TrackObserver() { + activated = 0; + filter = ItemStack.EMPTY; + currentTrain = null; + } + + @Override + public void blockEntityAdded(BlockEntity blockEntity, boolean front) { + super.blockEntityAdded(blockEntity, front); + FilteringBehaviour filteringBehaviour = BlockEntityBehaviour.get(blockEntity, FilteringBehaviour.TYPE); + if (filteringBehaviour != null) + setFilterAndNotify(blockEntity.getLevel(), filteringBehaviour.getFilter()); + } + + @Override + public void tick(TrackGraph graph, boolean preTrains) { + super.tick(graph, preTrains); + if (isActivated()) + activated--; + if (!isActivated()) + currentTrain = null; + } + + public void setFilterAndNotify(Level level, ItemStack filter) { + this.filter = filter; + notifyTrains(level); + } + + private void notifyTrains(Level level) { + TrackGraph graph = Create.RAILWAYS.sided(level) + .getGraph(level, edgeLocation.getFirst()); + if (graph == null) + return; + TrackEdge edge = graph.getConnection(edgeLocation.map(graph::locateNode)); + if (edge == null) + return; + SignalPropagator.notifyTrains(graph, edge); + } + + public ItemStack getFilter() { + return filter; + } + + public UUID getCurrentTrain() { + return currentTrain; + } + + public boolean isActivated() { + return activated > 0; + } + + public void keepAlive(Train train) { + activated = 8; + currentTrain = train.id; + } + + @Override + public void read(CompoundTag nbt, boolean migration, DimensionPalette dimensions) { + super.read(nbt, migration, dimensions); + activated = nbt.getInt("Activated"); + filter = ItemStack.of(nbt.getCompound("Filter")); + if (nbt.contains("TrainId")) + currentTrain = nbt.getUUID("TrainId"); + } + + @Override + public void read(FriendlyByteBuf buffer, DimensionPalette dimensions) { + super.read(buffer, dimensions); + } + + @Override + public void write(CompoundTag nbt, DimensionPalette dimensions) { + super.write(nbt, dimensions); + nbt.putInt("Activated", activated); + nbt.put("Filter", filter.serializeNBT()); + if (currentTrain != null) + nbt.putUUID("TrainId", currentTrain); + } + + @Override + public void write(FriendlyByteBuf buffer, DimensionPalette dimensions) { + super.write(buffer, dimensions); + } + +} diff --git a/src/main/java/com/simibubi/create/content/trains/observer/TrackObserverBlock.java b/src/main/java/com/simibubi/create/content/trains/observer/TrackObserverBlock.java new file mode 100644 index 000000000..efc99dc27 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/observer/TrackObserverBlock.java @@ -0,0 +1,62 @@ +package com.simibubi.create.content.trains.observer; + +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.foundation.block.IBE; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +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.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition.Builder; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.BooleanProperty; + +public class TrackObserverBlock extends Block implements IBE, IWrenchable { + + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; + + public TrackObserverBlock(Properties p_49795_) { + super(p_49795_); + registerDefaultState(defaultBlockState().setValue(POWERED, false)); + } + + @Override + protected void createBlockStateDefinition(Builder pBuilder) { + super.createBlockStateDefinition(pBuilder.add(POWERED)); + } + + @Override + public boolean isSignalSource(BlockState state) { + return true; + } + + @Override + public int getSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { + return blockState.getValue(POWERED) ? 15 : 0; + } + + @Override + public boolean canConnectRedstone(BlockState state, BlockGetter world, BlockPos pos, Direction side) { + return true; + } + + @Override + public Class getBlockEntityClass() { + return TrackObserverBlockEntity.class; + } + + @Override + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.TRACK_OBSERVER.get(); + } + + @Override + public void onRemove(BlockState state, Level worldIn, BlockPos pos, BlockState newState, boolean isMoving) { + IBE.onRemove(state, worldIn, pos, newState); + } + +} diff --git a/src/main/java/com/simibubi/create/content/trains/observer/TrackObserverBlockEntity.java b/src/main/java/com/simibubi/create/content/trains/observer/TrackObserverBlockEntity.java new file mode 100644 index 000000000..48e01b499 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/observer/TrackObserverBlockEntity.java @@ -0,0 +1,113 @@ +package com.simibubi.create.content.trains.observer; + +import java.util.List; + +import javax.annotation.Nullable; + +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.content.contraptions.ITransformableBlockEntity; +import com.simibubi.create.content.contraptions.StructureTransform; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkBlock; +import com.simibubi.create.content.trains.graph.EdgePointType; +import com.simibubi.create.content.trains.track.TrackTargetingBehaviour; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; + +public class TrackObserverBlockEntity extends SmartBlockEntity implements ITransformableBlockEntity { + + public TrackTargetingBehaviour edgePoint; + + private FilteringBehaviour filtering; + + public TrackObserverBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + public void addBehaviours(List behaviours) { + behaviours.add(edgePoint = new TrackTargetingBehaviour<>(this, EdgePointType.OBSERVER)); + behaviours.add(filtering = createFilter().withCallback(this::onFilterChanged)); + filtering.setLabel(Lang.translateDirect("logistics.train_observer.cargo_filter")); + } + + private void onFilterChanged(ItemStack newFilter) { + if (level.isClientSide()) + return; + TrackObserver observer = getObserver(); + if (observer != null) + observer.setFilterAndNotify(level, newFilter); + } + + @Override + public void tick() { + super.tick(); + + if (level.isClientSide()) + return; + + boolean shouldBePowered = false; + TrackObserver observer = getObserver(); + if (observer != null) + shouldBePowered = observer.isActivated(); + if (isBlockPowered() == shouldBePowered) + return; + + BlockState blockState = getBlockState(); + if (blockState.hasProperty(TrackObserverBlock.POWERED)) + level.setBlock(worldPosition, blockState.setValue(TrackObserverBlock.POWERED, shouldBePowered), 3); + DisplayLinkBlock.notifyGatherers(level, worldPosition); + } + + @Nullable + public TrackObserver getObserver() { + return edgePoint.getEdgePoint(); + } + + public ItemStack getFilter() { + return filtering.getFilter(); + } + + public boolean isBlockPowered() { + return getBlockState().getOptionalValue(TrackObserverBlock.POWERED) + .orElse(false); + } + + @Override + protected AABB createRenderBoundingBox() { + return new AABB(worldPosition, edgePoint.getGlobalPosition()).inflate(2); + } + + @Override + public void transform(StructureTransform transform) { + edgePoint.transform(transform); + } + + public FilteringBehaviour createFilter() { + return new FilteringBehaviour(this, new ValueBoxTransform() { + + @Override + public void rotate(BlockState state, PoseStack ms) { + TransformStack.cast(ms) + .rotateX(90); + } + + @Override + public Vec3 getLocalOffset(BlockState state) { + return new Vec3(0.5, 15.5 / 16d, 0.5); + } + + }); + } + +} diff --git a/src/main/java/com/simibubi/create/content/trains/observer/TrackObserverRenderer.java b/src/main/java/com/simibubi/create/content/trains/observer/TrackObserverRenderer.java new file mode 100644 index 000000000..f55302396 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/observer/TrackObserverRenderer.java @@ -0,0 +1,48 @@ +package com.simibubi.create.content.trains.observer; + +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.content.trains.track.ITrackBlock; +import com.simibubi.create.content.trains.track.TrackTargetingBehaviour; +import com.simibubi.create.content.trains.track.TrackTargetingBehaviour.RenderedTrackOverlayType; +import com.simibubi.create.foundation.blockEntity.renderer.SmartBlockEntityRenderer; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider.Context; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; + +public class TrackObserverRenderer extends SmartBlockEntityRenderer { + + public TrackObserverRenderer(Context context) { + super(context); + } + + @Override + protected void renderSafe(TrackObserverBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + super.renderSafe(be, partialTicks, ms, buffer, light, overlay); + BlockPos pos = be.getBlockPos(); + + TrackTargetingBehaviour target = be.edgePoint; + BlockPos targetPosition = target.getGlobalPosition(); + Level level = be.getLevel(); + BlockState trackState = level.getBlockState(targetPosition); + Block block = trackState.getBlock(); + + if (!(block instanceof ITrackBlock)) + return; + + ms.pushPose(); + TransformStack.cast(ms) + .translate(targetPosition.subtract(pos)); + RenderedTrackOverlayType type = RenderedTrackOverlayType.OBSERVER; + TrackTargetingBehaviour.render(level, targetPosition, target.getTargetDirection(), target.getTargetBezier(), ms, + buffer, light, overlay, type, 1); + ms.popPose(); + + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/DestinationSuggestions.java b/src/main/java/com/simibubi/create/content/trains/schedule/DestinationSuggestions.java similarity index 97% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/DestinationSuggestions.java rename to src/main/java/com/simibubi/create/content/trains/schedule/DestinationSuggestions.java index 43ff18a2b..bbcbf0f63 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/DestinationSuggestions.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/DestinationSuggestions.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.management.schedule; +package com.simibubi.create.content.trains.schedule; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/IScheduleInput.java b/src/main/java/com/simibubi/create/content/trains/schedule/IScheduleInput.java similarity index 93% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/IScheduleInput.java rename to src/main/java/com/simibubi/create/content/trains/schedule/IScheduleInput.java index 4858e0974..5e0faf255 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/IScheduleInput.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/IScheduleInput.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.management.schedule; +package com.simibubi.create.content.trains.schedule; import java.util.List; @@ -25,6 +25,8 @@ public interface IScheduleInput { public abstract CompoundTag getData(); + public abstract void setData(CompoundTag data); + public default int slotsTargeted() { return 0; } @@ -40,7 +42,7 @@ public interface IScheduleInput { } public default void setItem(int slot, ItemStack stack) {} - + public default ItemStack getItem(int slot) { return ItemStack.EMPTY; } @@ -58,4 +60,4 @@ public interface IScheduleInput { return false; } -} \ No newline at end of file +} diff --git a/src/main/java/com/simibubi/create/content/trains/schedule/Schedule.java b/src/main/java/com/simibubi/create/content/trains/schedule/Schedule.java new file mode 100644 index 000000000..b23680b57 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/schedule/Schedule.java @@ -0,0 +1,100 @@ +package com.simibubi.create.content.trains.schedule; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +import com.simibubi.create.Create; +import com.simibubi.create.content.trains.schedule.condition.FluidThresholdCondition; +import com.simibubi.create.content.trains.schedule.condition.IdleCargoCondition; +import com.simibubi.create.content.trains.schedule.condition.ItemThresholdCondition; +import com.simibubi.create.content.trains.schedule.condition.PlayerPassengerCondition; +import com.simibubi.create.content.trains.schedule.condition.RedstoneLinkCondition; +import com.simibubi.create.content.trains.schedule.condition.ScheduleWaitCondition; +import com.simibubi.create.content.trains.schedule.condition.ScheduledDelay; +import com.simibubi.create.content.trains.schedule.condition.StationPoweredCondition; +import com.simibubi.create.content.trains.schedule.condition.StationUnloadedCondition; +import com.simibubi.create.content.trains.schedule.condition.TimeOfDayCondition; +import com.simibubi.create.content.trains.schedule.destination.ChangeThrottleInstruction; +import com.simibubi.create.content.trains.schedule.destination.ChangeTitleInstruction; +import com.simibubi.create.content.trains.schedule.destination.DestinationInstruction; +import com.simibubi.create.content.trains.schedule.destination.ScheduleInstruction; +import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.NBTHelper; +import com.simibubi.create.foundation.utility.Pair; + +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; + +public class Schedule { + + public static List>> INSTRUCTION_TYPES = + new ArrayList<>(); + public static List>> CONDITION_TYPES = + new ArrayList<>(); + + static { + registerInstruction("destination", DestinationInstruction::new); + registerInstruction("rename", ChangeTitleInstruction::new); + registerInstruction("throttle", ChangeThrottleInstruction::new); + registerCondition("delay", ScheduledDelay::new); + registerCondition("time_of_day", TimeOfDayCondition::new); + registerCondition("fluid_threshold", FluidThresholdCondition::new); + registerCondition("item_threshold", ItemThresholdCondition::new); + registerCondition("redstone_link", RedstoneLinkCondition::new); + registerCondition("player_count", PlayerPassengerCondition::new); + registerCondition("idle", IdleCargoCondition::new); + registerCondition("unloaded", StationUnloadedCondition::new); + registerCondition("powered", StationPoweredCondition::new); + } + + private static void registerInstruction(String name, Supplier factory) { + INSTRUCTION_TYPES.add(Pair.of(Create.asResource(name), factory)); + } + + private static void registerCondition(String name, Supplier factory) { + CONDITION_TYPES.add(Pair.of(Create.asResource(name), factory)); + } + + public static List getTypeOptions(List> list) { + String langSection = list.equals(INSTRUCTION_TYPES) ? "instruction." : "condition."; + return list.stream() + .map(Pair::getFirst) + .map(rl -> rl.getNamespace() + ".schedule." + langSection + rl.getPath()) + .map(Components::translatable) + .toList(); + } + + public List entries; + public boolean cyclic; + public int savedProgress; + + public Schedule() { + entries = new ArrayList<>(); + cyclic = true; + savedProgress = 0; + } + + public CompoundTag write() { + CompoundTag tag = new CompoundTag(); + ListTag list = NBTHelper.writeCompoundList(entries, ScheduleEntry::write); + tag.put("Entries", list); + tag.putBoolean("Cyclic", cyclic); + if (savedProgress > 0) + tag.putInt("Progress", savedProgress); + return tag; + } + + public static Schedule fromTag(CompoundTag tag) { + Schedule schedule = new Schedule(); + schedule.entries = NBTHelper.readCompoundList(tag.getList("Entries", Tag.TAG_COMPOUND), ScheduleEntry::fromTag); + schedule.cyclic = tag.getBoolean("Cyclic"); + if (tag.contains("Progress")) + schedule.savedProgress = tag.getInt("Progress"); + return schedule; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleDataEntry.java b/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleDataEntry.java similarity index 81% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleDataEntry.java rename to src/main/java/com/simibubi/create/content/trains/schedule/ScheduleDataEntry.java index 58b2eae7a..4712df960 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleDataEntry.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleDataEntry.java @@ -1,35 +1,41 @@ -package com.simibubi.create.content.logistics.trains.management.schedule; +package com.simibubi.create.content.trains.schedule; import net.minecraft.nbt.CompoundTag; public abstract class ScheduleDataEntry implements IScheduleInput { - + protected CompoundTag data; - + public ScheduleDataEntry() { data = new CompoundTag(); } - + @Override public CompoundTag getData() { return data; } - + + @Override + public void setData(CompoundTag data) { + this.data = data; + readAdditional(data); + } + protected void writeAdditional(CompoundTag tag) {}; protected void readAdditional(CompoundTag tag) {}; - + protected T enumData(String key, Class enumClass) { T[] enumConstants = enumClass.getEnumConstants(); return enumConstants[data.getInt(key) % enumConstants.length]; } - + protected String textData(String key) { return data.getString(key); } - + protected int intData(String key) { return data.getInt(key); } - + } diff --git a/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleEditPacket.java b/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleEditPacket.java new file mode 100644 index 000000000..33c062af9 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleEditPacket.java @@ -0,0 +1,51 @@ +package com.simibubi.create.content.trains.schedule; + +import com.simibubi.create.AllItems; +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.network.NetworkEvent.Context; + +public class ScheduleEditPacket extends SimplePacketBase { + + private Schedule schedule; + + public ScheduleEditPacket(Schedule schedule) { + this.schedule = schedule; + } + + public ScheduleEditPacket(FriendlyByteBuf buffer) { + schedule = Schedule.fromTag(buffer.readNbt()); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeNbt(schedule.write()); + } + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> { + ServerPlayer sender = context.getSender(); + ItemStack mainHandItem = sender.getMainHandItem(); + if (!AllItems.SCHEDULE.isIn(mainHandItem)) + return; + + CompoundTag tag = mainHandItem.getOrCreateTag(); + if (schedule.entries.isEmpty()) { + tag.remove("Schedule"); + if (tag.isEmpty()) + mainHandItem.setTag(null); + } else + tag.put("Schedule", schedule.write()); + + sender.getCooldowns() + .addCooldown(mainHandItem.getItem(), 5); + }); + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleEntry.java b/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleEntry.java similarity index 82% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleEntry.java rename to src/main/java/com/simibubi/create/content/trains/schedule/ScheduleEntry.java index 1aeefc729..44e7cf2d8 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleEntry.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleEntry.java @@ -1,10 +1,10 @@ -package com.simibubi.create.content.logistics.trains.management.schedule; +package com.simibubi.create.content.trains.schedule; import java.util.ArrayList; import java.util.List; -import com.simibubi.create.content.logistics.trains.management.schedule.condition.ScheduleWaitCondition; -import com.simibubi.create.content.logistics.trains.management.schedule.destination.ScheduleInstruction; +import com.simibubi.create.content.trains.schedule.condition.ScheduleWaitCondition; +import com.simibubi.create.content.trains.schedule.destination.ScheduleInstruction; import com.simibubi.create.foundation.utility.NBTHelper; import net.minecraft.nbt.CompoundTag; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleItem.java b/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleItem.java similarity index 90% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleItem.java rename to src/main/java/com/simibubi/create/content/trains/schedule/ScheduleItem.java index 0b89df6b3..c41f57673 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleItem.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleItem.java @@ -1,14 +1,14 @@ -package com.simibubi.create.content.logistics.trains.management.schedule; +package com.simibubi.create.content.trains.schedule; import java.util.List; -import com.simibubi.create.AllContainerTypes; +import com.simibubi.create.AllMenuTypes; import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; -import com.simibubi.create.content.logistics.trains.entity.CarriageContraption; -import com.simibubi.create.content.logistics.trains.entity.CarriageContraptionEntity; -import com.simibubi.create.content.logistics.trains.entity.Train; -import com.simibubi.create.content.logistics.trains.management.schedule.destination.DestinationInstruction; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.trains.entity.CarriageContraption; +import com.simibubi.create.content.trains.entity.CarriageContraptionEntity; +import com.simibubi.create.content.trains.entity.Train; +import com.simibubi.create.content.trains.schedule.destination.DestinationInstruction; import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Couple; @@ -159,7 +159,7 @@ public class ScheduleItem extends Item implements MenuProvider { @Override public AbstractContainerMenu createMenu(int id, Inventory inv, Player player) { ItemStack heldItem = player.getMainHandItem(); - return new ScheduleContainer(AllContainerTypes.SCHEDULE.get(), id, inv, heldItem); + return new ScheduleMenu(AllMenuTypes.SCHEDULE.get(), id, inv, heldItem); } @Override diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleItemEntityInteraction.java b/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleItemEntityInteraction.java similarity index 90% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleItemEntityInteraction.java rename to src/main/java/com/simibubi/create/content/trains/schedule/ScheduleItemEntityInteraction.java index f2ba64612..11b067933 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleItemEntityInteraction.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleItemEntityInteraction.java @@ -1,11 +1,11 @@ -package com.simibubi.create.content.logistics.trains.management.schedule; +package com.simibubi.create.content.trains.schedule; import com.simibubi.create.AllItems; import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; -import com.simibubi.create.content.logistics.trains.entity.CarriageContraption; -import com.simibubi.create.content.logistics.trains.entity.CarriageContraptionEntity; -import com.simibubi.create.content.logistics.trains.entity.Train; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.trains.entity.CarriageContraption; +import com.simibubi.create.content.trains.entity.CarriageContraptionEntity; +import com.simibubi.create.content.trains.entity.Train; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Lang; diff --git a/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleMenu.java b/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleMenu.java new file mode 100644 index 000000000..14585c6cb --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleMenu.java @@ -0,0 +1,107 @@ +package com.simibubi.create.content.trains.schedule; + +import com.simibubi.create.foundation.gui.menu.GhostItemMenu; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.Container; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +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.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemStackHandler; +import net.minecraftforge.items.SlotItemHandler; + +public class ScheduleMenu extends GhostItemMenu { + + public boolean slotsActive = true; + public int targetSlotsActive = 1; + + static final int slots = 2; + + public ScheduleMenu(MenuType type, int id, Inventory inv, FriendlyByteBuf extraData) { + super(type, id, inv, extraData); + } + + public ScheduleMenu(MenuType type, int id, Inventory inv, ItemStack contentHolder) { + super(type, id, inv, contentHolder); + } + + @Override + protected ItemStackHandler createGhostInventory() { + return new ItemStackHandler(slots); + } + + @Override + public void clicked(int slotId, int dragType, ClickType clickTypeIn, Player player) { + if (slotId != playerInventory.selected || clickTypeIn == ClickType.THROW) + super.clicked(slotId, dragType, clickTypeIn, player); + } + + @Override + protected boolean allowRepeats() { + return true; + } + + @Override + protected ItemStack createOnClient(FriendlyByteBuf extraData) { + return extraData.readItem(); + } + + @Override + protected void addSlots() { + addPlayerSlots(46, 140); + for (int i = 0; i < slots; i++) + addSlot(new InactiveItemHandlerSlot(ghostInventory, i, i, 54 + 20 * i, 88)); + } + + @Override + protected void addPlayerSlots(int x, int y) { + for (int hotbarSlot = 0; hotbarSlot < 9; ++hotbarSlot) + this.addSlot(new InactiveSlot(playerInventory, hotbarSlot, x + hotbarSlot * 18, y + 58)); + for (int row = 0; row < 3; ++row) + for (int col = 0; col < 9; ++col) + this.addSlot(new InactiveSlot(playerInventory, col + row * 9 + 9, x + col * 18, y + row * 18)); + } + + @Override + protected void saveData(ItemStack contentHolder) {} + + @Override + public boolean stillValid(Player player) { + return playerInventory.getSelected() == contentHolder; + } + + class InactiveSlot extends Slot { + + public InactiveSlot(Container pContainer, int pIndex, int pX, int pY) { + super(pContainer, pIndex, pX, pY); + } + + @Override + public boolean isActive() { + return slotsActive; + } + + } + + class InactiveItemHandlerSlot extends SlotItemHandler { + + private int targetIndex; + + public InactiveItemHandlerSlot(IItemHandler itemHandler, int targetIndex, int index, int xPosition, + int yPosition) { + super(itemHandler, index, xPosition, yPosition); + this.targetIndex = targetIndex; + } + + @Override + public boolean isActive() { + return slotsActive && targetIndex < targetSlotsActive; + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleRuntime.java b/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleRuntime.java similarity index 92% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleRuntime.java rename to src/main/java/com/simibubi/create/content/trains/schedule/ScheduleRuntime.java index f7bc8a340..5147edf96 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleRuntime.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleRuntime.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.management.schedule; +package com.simibubi.create.content.trains.schedule; import java.util.ArrayList; import java.util.Collection; @@ -6,17 +6,17 @@ import java.util.List; import java.util.Objects; import com.simibubi.create.AllItems; -import com.simibubi.create.content.logistics.trains.entity.Carriage; -import com.simibubi.create.content.logistics.trains.entity.Train; -import com.simibubi.create.content.logistics.trains.management.display.GlobalTrainDisplayData.TrainDeparturePrediction; -import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType; -import com.simibubi.create.content.logistics.trains.management.edgePoint.station.GlobalStation; -import com.simibubi.create.content.logistics.trains.management.schedule.condition.ScheduleWaitCondition; -import com.simibubi.create.content.logistics.trains.management.schedule.condition.ScheduledDelay; -import com.simibubi.create.content.logistics.trains.management.schedule.destination.ChangeThrottleInstruction; -import com.simibubi.create.content.logistics.trains.management.schedule.destination.ChangeTitleInstruction; -import com.simibubi.create.content.logistics.trains.management.schedule.destination.DestinationInstruction; -import com.simibubi.create.content.logistics.trains.management.schedule.destination.ScheduleInstruction; +import com.simibubi.create.content.trains.display.GlobalTrainDisplayData.TrainDeparturePrediction; +import com.simibubi.create.content.trains.entity.Carriage; +import com.simibubi.create.content.trains.entity.Train; +import com.simibubi.create.content.trains.graph.EdgePointType; +import com.simibubi.create.content.trains.schedule.condition.ScheduleWaitCondition; +import com.simibubi.create.content.trains.schedule.condition.ScheduledDelay; +import com.simibubi.create.content.trains.schedule.destination.ChangeThrottleInstruction; +import com.simibubi.create.content.trains.schedule.destination.ChangeTitleInstruction; +import com.simibubi.create.content.trains.schedule.destination.DestinationInstruction; +import com.simibubi.create.content.trains.schedule.destination.ScheduleInstruction; +import com.simibubi.create.content.trains.station.GlobalStation; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.NBTHelper; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleScreen.java b/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleScreen.java similarity index 96% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleScreen.java rename to src/main/java/com/simibubi/create/content/trains/schedule/ScheduleScreen.java index 84320e5a0..c1879fcf7 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/ScheduleScreen.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/ScheduleScreen.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.management.schedule; +package com.simibubi.create.content.trains.schedule; import java.util.ArrayList; import java.util.Collections; @@ -18,29 +18,29 @@ import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.platform.InputConstants; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllPackets; import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.GlobalRailwayManager; -import com.simibubi.create.content.logistics.trains.TrackGraph; -import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType; -import com.simibubi.create.content.logistics.trains.management.edgePoint.station.GlobalStation; -import com.simibubi.create.content.logistics.trains.management.schedule.condition.ScheduleWaitCondition; -import com.simibubi.create.content.logistics.trains.management.schedule.condition.ScheduledDelay; -import com.simibubi.create.content.logistics.trains.management.schedule.destination.DestinationInstruction; -import com.simibubi.create.content.logistics.trains.management.schedule.destination.ScheduleInstruction; +import com.simibubi.create.content.trains.GlobalRailwayManager; +import com.simibubi.create.content.trains.graph.EdgePointType; +import com.simibubi.create.content.trains.graph.TrackGraph; +import com.simibubi.create.content.trains.schedule.condition.ScheduleWaitCondition; +import com.simibubi.create.content.trains.schedule.condition.ScheduledDelay; +import com.simibubi.create.content.trains.schedule.destination.DestinationInstruction; +import com.simibubi.create.content.trains.schedule.destination.ScheduleInstruction; +import com.simibubi.create.content.trains.station.GlobalStation; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.gui.ModularGuiLine; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; import com.simibubi.create.foundation.gui.UIRenderHelper; -import com.simibubi.create.foundation.gui.container.AbstractSimiContainerScreen; -import com.simibubi.create.foundation.gui.container.GhostItemSubmitPacket; import com.simibubi.create.foundation.gui.element.GuiGameElement; +import com.simibubi.create.foundation.gui.menu.AbstractSimiContainerScreen; +import com.simibubi.create.foundation.gui.menu.GhostItemSubmitPacket; import com.simibubi.create.foundation.gui.widget.IconButton; import com.simibubi.create.foundation.gui.widget.Indicator; import com.simibubi.create.foundation.gui.widget.Indicator.State; import com.simibubi.create.foundation.gui.widget.Label; import com.simibubi.create.foundation.gui.widget.SelectionScrollInput; -import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.IntAttached; import com.simibubi.create.foundation.utility.Lang; @@ -64,7 +64,7 @@ import net.minecraft.world.item.Items; import net.minecraft.world.phys.Vec3; import net.minecraftforge.client.gui.ScreenUtils; -public class ScheduleScreen extends AbstractSimiContainerScreen { +public class ScheduleScreen extends AbstractSimiContainerScreen { private static final int CARD_HEADER = 22; private static final int CARD_WIDTH = 195; @@ -94,14 +94,14 @@ public class ScheduleScreen extends AbstractSimiContainerScreen g.getPoints(EdgePointType.STATION) .stream()) - .filter(station -> station.tilePos != null) + .filter(station -> station.blockEntityPos != null) .filter(station -> visited.add(station.name)) - .map(station -> IntAttached.with((int) Vec3.atBottomCenterOf(station.tilePos) + .map(station -> IntAttached.with((int) Vec3.atBottomCenterOf(station.blockEntityPos) .distanceTo(position), station.name)) .toList(); } @@ -1070,7 +1070,7 @@ public class ScheduleScreen extends AbstractSimiContainerScreen ms.translate(0, -2.25f / 16f, 0); msr.rotateX(-8.5f); BlockState air = Blocks.AIR.defaultBlockState(); - CachedBufferer.partial(AllBlockPartials.TRAIN_HAT, air) + CachedBufferer.partial(AllPartialModels.TRAIN_HAT, air) .forEntityRender() .light(light) .renderInto(ms, buffer.getBuffer(renderType)); diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/TrainHatOffsets.java b/src/main/java/com/simibubi/create/content/trains/schedule/TrainHatOffsets.java similarity index 97% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/TrainHatOffsets.java rename to src/main/java/com/simibubi/create/content/trains/schedule/TrainHatOffsets.java index a98383e95..772156ac7 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/TrainHatOffsets.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/TrainHatOffsets.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.management.schedule; +package com.simibubi.create.content.trains.schedule; import net.minecraft.client.model.AgeableListModel; import net.minecraft.client.model.AxolotlModel; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/CargoThresholdCondition.java b/src/main/java/com/simibubi/create/content/trains/schedule/condition/CargoThresholdCondition.java similarity index 94% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/CargoThresholdCondition.java rename to src/main/java/com/simibubi/create/content/trains/schedule/condition/CargoThresholdCondition.java index 75b1f0a07..337d732f0 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/CargoThresholdCondition.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/condition/CargoThresholdCondition.java @@ -1,11 +1,11 @@ -package com.simibubi.create.content.logistics.trains.management.schedule.condition; +package com.simibubi.create.content.trains.schedule.condition; import java.util.Arrays; import java.util.List; import com.google.common.collect.ImmutableList; -import com.simibubi.create.content.logistics.trains.entity.Carriage; -import com.simibubi.create.content.logistics.trains.entity.Train; +import com.simibubi.create.content.trains.entity.Carriage; +import com.simibubi.create.content.trains.entity.Train; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Lang; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/FluidThresholdCondition.java b/src/main/java/com/simibubi/create/content/trains/schedule/condition/FluidThresholdCondition.java similarity index 87% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/FluidThresholdCondition.java rename to src/main/java/com/simibubi/create/content/trains/schedule/condition/FluidThresholdCondition.java index 0c3f25f55..6fedc7789 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/FluidThresholdCondition.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/condition/FluidThresholdCondition.java @@ -1,13 +1,13 @@ -package com.simibubi.create.content.logistics.trains.management.schedule.condition; +package com.simibubi.create.content.trains.schedule.condition; import java.util.List; import com.google.common.collect.ImmutableList; import com.simibubi.create.Create; -import com.simibubi.create.content.contraptions.processing.EmptyingByBasin; -import com.simibubi.create.content.logistics.item.filter.FilterItem; -import com.simibubi.create.content.logistics.trains.entity.Carriage; -import com.simibubi.create.content.logistics.trains.entity.Train; +import com.simibubi.create.content.fluids.transfer.GenericItemEmptying; +import com.simibubi.create.content.logistics.filter.FilterItem; +import com.simibubi.create.content.trains.entity.Carriage; +import com.simibubi.create.content.trains.entity.Train; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Lang; @@ -68,7 +68,8 @@ public class FluidThresholdCondition extends CargoThresholdCondition { @Override protected void readAdditional(CompoundTag tag) { super.readAdditional(tag); - compareStack = ItemStack.of(tag.getCompound("Bucket")); + if (tag.contains("Bucket")) + compareStack = ItemStack.of(tag.getCompound("Bucket")); } @Override @@ -81,9 +82,9 @@ public class FluidThresholdCondition extends CargoThresholdCondition { if (fluidStack != null) return fluidStack; fluidStack = FluidStack.EMPTY; - if (!EmptyingByBasin.canItemBeEmptied(Minecraft.getInstance().level, compareStack)) + if (!GenericItemEmptying.canItemBeEmptied(Minecraft.getInstance().level, compareStack)) return fluidStack; - FluidStack fluidInFilter = EmptyingByBasin.emptyItem(Minecraft.getInstance().level, compareStack, true) + FluidStack fluidInFilter = GenericItemEmptying.emptyItem(Minecraft.getInstance().level, compareStack, true) .getFirst(); if (fluidInFilter == null) return fluidStack; @@ -139,4 +140,4 @@ public class FluidThresholdCondition extends CargoThresholdCondition { Math.max(0, getThreshold() + offset), Lang.translateDirect("schedule.condition.threshold.buckets")); } -} \ No newline at end of file +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/IdleCargoCondition.java b/src/main/java/com/simibubi/create/content/trains/schedule/condition/IdleCargoCondition.java similarity index 82% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/IdleCargoCondition.java rename to src/main/java/com/simibubi/create/content/trains/schedule/condition/IdleCargoCondition.java index d4801c0ca..dc7bfcc54 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/IdleCargoCondition.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/condition/IdleCargoCondition.java @@ -1,8 +1,8 @@ -package com.simibubi.create.content.logistics.trains.management.schedule.condition; +package com.simibubi.create.content.trains.schedule.condition; import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.entity.Carriage; -import com.simibubi.create.content.logistics.trains.entity.Train; +import com.simibubi.create.content.trains.entity.Carriage; +import com.simibubi.create.content.trains.entity.Train; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Pair; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/ItemThresholdCondition.java b/src/main/java/com/simibubi/create/content/trains/schedule/condition/ItemThresholdCondition.java similarity index 92% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/ItemThresholdCondition.java rename to src/main/java/com/simibubi/create/content/trains/schedule/condition/ItemThresholdCondition.java index 78905d201..8b71e2344 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/ItemThresholdCondition.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/condition/ItemThresholdCondition.java @@ -1,12 +1,12 @@ -package com.simibubi.create.content.logistics.trains.management.schedule.condition; +package com.simibubi.create.content.trains.schedule.condition; import java.util.List; import com.google.common.collect.ImmutableList; import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.item.filter.FilterItem; -import com.simibubi.create.content.logistics.trains.entity.Carriage; -import com.simibubi.create.content.logistics.trains.entity.Train; +import com.simibubi.create.content.logistics.filter.FilterItem; +import com.simibubi.create.content.trains.entity.Carriage; +import com.simibubi.create.content.trains.entity.Train; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Lang; @@ -69,7 +69,8 @@ public class ItemThresholdCondition extends CargoThresholdCondition { @Override protected void readAdditional(CompoundTag tag) { super.readAdditional(tag); - stack = ItemStack.of(tag.getCompound("Item")); + if (tag.contains("Item")) + stack = ItemStack.of(tag.getCompound("Item")); } @Override @@ -131,4 +132,4 @@ public class ItemThresholdCondition extends CargoThresholdCondition { Math.max(0, getThreshold() + offset), Lang.translateDirect("schedule.condition.threshold." + (inStacks() ? "stacks" : "items"))); } -} \ No newline at end of file +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/LazyTickedScheduleCondition.java b/src/main/java/com/simibubi/create/content/trains/schedule/condition/LazyTickedScheduleCondition.java similarity index 81% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/LazyTickedScheduleCondition.java rename to src/main/java/com/simibubi/create/content/trains/schedule/condition/LazyTickedScheduleCondition.java index ce17a254a..6d2bce181 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/LazyTickedScheduleCondition.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/condition/LazyTickedScheduleCondition.java @@ -1,6 +1,6 @@ -package com.simibubi.create.content.logistics.trains.management.schedule.condition; +package com.simibubi.create.content.trains.schedule.condition; -import com.simibubi.create.content.logistics.trains.entity.Train; +import com.simibubi.create.content.trains.entity.Train; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.level.Level; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/PlayerPassengerCondition.java b/src/main/java/com/simibubi/create/content/trains/schedule/condition/PlayerPassengerCondition.java similarity index 95% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/PlayerPassengerCondition.java rename to src/main/java/com/simibubi/create/content/trains/schedule/condition/PlayerPassengerCondition.java index b94d7c051..37cccce41 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/PlayerPassengerCondition.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/condition/PlayerPassengerCondition.java @@ -1,11 +1,11 @@ -package com.simibubi.create.content.logistics.trains.management.schedule.condition; +package com.simibubi.create.content.trains.schedule.condition; import java.util.List; import com.google.common.collect.ImmutableList; import com.simibubi.create.AllBlocks; import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.entity.Train; +import com.simibubi.create.content.trains.entity.Train; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Lang; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/RedstoneLinkCondition.java b/src/main/java/com/simibubi/create/content/trains/schedule/condition/RedstoneLinkCondition.java similarity index 91% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/RedstoneLinkCondition.java rename to src/main/java/com/simibubi/create/content/trains/schedule/condition/RedstoneLinkCondition.java index 9bb8f4190..87b07f6e8 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/RedstoneLinkCondition.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/condition/RedstoneLinkCondition.java @@ -1,12 +1,12 @@ -package com.simibubi.create.content.logistics.trains.management.schedule.condition; +package com.simibubi.create.content.trains.schedule.condition; import java.util.List; import com.google.common.collect.ImmutableList; import com.simibubi.create.AllBlocks; import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.RedstoneLinkNetworkHandler.Frequency; -import com.simibubi.create.content.logistics.trains.entity.Train; +import com.simibubi.create.content.redstone.link.RedstoneLinkNetworkHandler.Frequency; +import com.simibubi.create.content.trains.entity.Train; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Couple; @@ -107,7 +107,8 @@ public class RedstoneLinkCondition extends ScheduleWaitCondition { @Override protected void readAdditional(CompoundTag tag) { - freq = Couple.deserializeEach(tag.getList("Frequency", Tag.TAG_COMPOUND), c -> Frequency.of(ItemStack.of(c))); + if (tag.contains("Frequency")) + freq = Couple.deserializeEach(tag.getList("Frequency", Tag.TAG_COMPOUND), c -> Frequency.of(ItemStack.of(c))); } @Override @@ -118,7 +119,7 @@ public class RedstoneLinkCondition extends ScheduleWaitCondition { .titled(Lang.translateDirect("schedule.condition.redstone_link.frequency_state")), "Inverted"); } - + @Override public MutableComponent getWaitingStatus(Level level, Train train, CompoundTag tag) { return Lang.translateDirect("schedule.condition.redstone_link.status"); diff --git a/src/main/java/com/simibubi/create/content/trains/schedule/condition/ScheduleWaitCondition.java b/src/main/java/com/simibubi/create/content/trains/schedule/condition/ScheduleWaitCondition.java new file mode 100644 index 000000000..e36d5de68 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/schedule/condition/ScheduleWaitCondition.java @@ -0,0 +1,57 @@ +package com.simibubi.create.content.trains.schedule.condition; + +import java.util.function.Supplier; + +import com.simibubi.create.Create; +import com.simibubi.create.content.trains.entity.Train; +import com.simibubi.create.content.trains.schedule.Schedule; +import com.simibubi.create.content.trains.schedule.ScheduleDataEntry; +import com.simibubi.create.foundation.utility.Pair; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.Level; + +public abstract class ScheduleWaitCondition extends ScheduleDataEntry { + + public abstract boolean tickCompletion(Level level, Train train, CompoundTag context); + + protected void requestStatusToUpdate(CompoundTag context) { + context.putInt("StatusVersion", context.getInt("StatusVersion") + 1); + } + + public final CompoundTag write() { + CompoundTag tag = new CompoundTag(); + CompoundTag dataCopy = data.copy(); + writeAdditional(dataCopy); + tag.putString("Id", getId().toString()); + tag.put("Data", dataCopy); + return tag; + } + + public static ScheduleWaitCondition fromTag(CompoundTag tag) { + ResourceLocation location = new ResourceLocation(tag.getString("Id")); + Supplier supplier = null; + for (Pair> pair : Schedule.CONDITION_TYPES) + if (pair.getFirst() + .equals(location)) + supplier = pair.getSecond(); + + if (supplier == null) { + Create.LOGGER.warn("Could not parse waiting condition type: " + location); + return null; + } + + ScheduleWaitCondition condition = supplier.get(); + // Left around for migration purposes. Data added in writeAdditional has moved into the "Data" tag + condition.readAdditional(tag); + CompoundTag data = tag.getCompound("Data"); + condition.readAdditional(data); + condition.data = data; + return condition; + } + + public abstract MutableComponent getWaitingStatus(Level level, Train train, CompoundTag tag); + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/ScheduledDelay.java b/src/main/java/com/simibubi/create/content/trains/schedule/condition/ScheduledDelay.java similarity index 86% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/ScheduledDelay.java rename to src/main/java/com/simibubi/create/content/trains/schedule/condition/ScheduledDelay.java index 2b6b9cd15..87de19b40 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/ScheduledDelay.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/condition/ScheduledDelay.java @@ -1,7 +1,7 @@ -package com.simibubi.create.content.logistics.trains.management.schedule.condition; +package com.simibubi.create.content.trains.schedule.condition; import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.entity.Train; +import com.simibubi.create.content.trains.entity.Train; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Pair; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/StationPoweredCondition.java b/src/main/java/com/simibubi/create/content/trains/schedule/condition/StationPoweredCondition.java similarity index 81% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/StationPoweredCondition.java rename to src/main/java/com/simibubi/create/content/trains/schedule/condition/StationPoweredCondition.java index 2f57368af..c4ae0447b 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/StationPoweredCondition.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/condition/StationPoweredCondition.java @@ -1,8 +1,8 @@ -package com.simibubi.create.content.logistics.trains.management.schedule.condition; +package com.simibubi.create.content.trains.schedule.condition; import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.entity.Train; -import com.simibubi.create.content.logistics.trains.management.edgePoint.station.GlobalStation; +import com.simibubi.create.content.trains.entity.Train; +import com.simibubi.create.content.trains.station.GlobalStation; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Pair; @@ -28,8 +28,8 @@ public class StationPoweredCondition extends ScheduleWaitCondition { GlobalStation currentStation = train.getCurrentStation(); if (currentStation == null) return false; - BlockPos stationPos = currentStation.getTilePos(); - ResourceKey stationDim = currentStation.getTileDimension(); + BlockPos stationPos = currentStation.getBlockEntityPos(); + ResourceKey stationDim = currentStation.getBlockEntityDimension(); MinecraftServer server = level.getServer(); if (server == null) return false; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/StationUnloadedCondition.java b/src/main/java/com/simibubi/create/content/trains/schedule/condition/StationUnloadedCondition.java similarity index 83% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/StationUnloadedCondition.java rename to src/main/java/com/simibubi/create/content/trains/schedule/condition/StationUnloadedCondition.java index e0c723949..ec957edd1 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/StationUnloadedCondition.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/condition/StationUnloadedCondition.java @@ -1,8 +1,8 @@ -package com.simibubi.create.content.logistics.trains.management.schedule.condition; +package com.simibubi.create.content.trains.schedule.condition; import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.entity.Train; -import com.simibubi.create.content.logistics.trains.management.edgePoint.station.GlobalStation; +import com.simibubi.create.content.trains.entity.Train; +import com.simibubi.create.content.trains.station.GlobalStation; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Pair; @@ -27,7 +27,7 @@ public class StationUnloadedCondition extends ScheduleWaitCondition { GlobalStation currentStation = train.getCurrentStation(); if (currentStation == null) return false; - ResourceKey stationDim = currentStation.getTileDimension(); + ResourceKey stationDim = currentStation.getBlockEntityDimension(); MinecraftServer server = level.getServer(); if (server == null) return false; @@ -35,7 +35,7 @@ public class StationUnloadedCondition extends ScheduleWaitCondition { if (stationLevel == null) { return false; } - return !stationLevel.isPositionEntityTicking(currentStation.getTilePos()); + return !stationLevel.isPositionEntityTicking(currentStation.getBlockEntityPos()); } @Override diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/TimeOfDayCondition.java b/src/main/java/com/simibubi/create/content/trains/schedule/condition/TimeOfDayCondition.java similarity index 97% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/TimeOfDayCondition.java rename to src/main/java/com/simibubi/create/content/trains/schedule/condition/TimeOfDayCondition.java index 9d0a10b0a..1596b57f0 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/TimeOfDayCondition.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/condition/TimeOfDayCondition.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.management.schedule.condition; +package com.simibubi.create.content.trains.schedule.condition; import java.util.List; @@ -8,7 +8,7 @@ import com.google.common.collect.ImmutableList; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.entity.Train; +import com.simibubi.create.content.trains.entity.Train; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; import com.simibubi.create.foundation.gui.widget.Label; import com.simibubi.create.foundation.gui.widget.ScrollInput; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/TimedWaitCondition.java b/src/main/java/com/simibubi/create/content/trains/schedule/condition/TimedWaitCondition.java similarity index 96% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/TimedWaitCondition.java rename to src/main/java/com/simibubi/create/content/trains/schedule/condition/TimedWaitCondition.java index 489d24e51..996d28352 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/condition/TimedWaitCondition.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/condition/TimedWaitCondition.java @@ -1,9 +1,9 @@ -package com.simibubi.create.content.logistics.trains.management.schedule.condition; +package com.simibubi.create.content.trains.schedule.condition; import java.util.List; import com.google.common.collect.ImmutableList; -import com.simibubi.create.content.logistics.trains.entity.Train; +import com.simibubi.create.content.trains.entity.Train; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Lang; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/destination/ChangeThrottleInstruction.java b/src/main/java/com/simibubi/create/content/trains/schedule/destination/ChangeThrottleInstruction.java similarity index 94% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/destination/ChangeThrottleInstruction.java rename to src/main/java/com/simibubi/create/content/trains/schedule/destination/ChangeThrottleInstruction.java index 36d71f3d3..1fd5a7f70 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/destination/ChangeThrottleInstruction.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/destination/ChangeThrottleInstruction.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.management.schedule.destination; +package com.simibubi.create.content.trains.schedule.destination; import java.util.List; @@ -73,7 +73,7 @@ public class ChangeThrottleInstruction extends ScheduleInstruction { } private ItemStack icon() { - return AllBlocks.CONTROLS.asStack(); + return AllBlocks.TRAIN_CONTROLS.asStack(); } @Override diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/destination/ChangeTitleInstruction.java b/src/main/java/com/simibubi/create/content/trains/schedule/destination/ChangeTitleInstruction.java similarity index 94% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/destination/ChangeTitleInstruction.java rename to src/main/java/com/simibubi/create/content/trains/schedule/destination/ChangeTitleInstruction.java index 92419fc59..2265014f1 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/destination/ChangeTitleInstruction.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/destination/ChangeTitleInstruction.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.management.schedule.destination; +package com.simibubi.create.content.trains.schedule.destination; import java.util.List; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/destination/DestinationInstruction.java b/src/main/java/com/simibubi/create/content/trains/schedule/destination/DestinationInstruction.java similarity index 95% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/destination/DestinationInstruction.java rename to src/main/java/com/simibubi/create/content/trains/schedule/destination/DestinationInstruction.java index d3b15cd41..ada430049 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/destination/DestinationInstruction.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/destination/DestinationInstruction.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.management.schedule.destination; +package com.simibubi.create.content.trains.schedule.destination; import java.util.List; diff --git a/src/main/java/com/simibubi/create/content/trains/schedule/destination/ScheduleInstruction.java b/src/main/java/com/simibubi/create/content/trains/schedule/destination/ScheduleInstruction.java new file mode 100644 index 000000000..2dd9571ca --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/schedule/destination/ScheduleInstruction.java @@ -0,0 +1,48 @@ +package com.simibubi.create.content.trains.schedule.destination; + +import java.util.function.Supplier; + +import com.simibubi.create.Create; +import com.simibubi.create.content.trains.schedule.Schedule; +import com.simibubi.create.content.trains.schedule.ScheduleDataEntry; +import com.simibubi.create.foundation.utility.Pair; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; + +public abstract class ScheduleInstruction extends ScheduleDataEntry { + + public abstract boolean supportsConditions(); + + public final CompoundTag write() { + CompoundTag tag = new CompoundTag(); + CompoundTag dataCopy = data.copy(); + writeAdditional(dataCopy); + tag.putString("Id", getId().toString()); + tag.put("Data", dataCopy); + return tag; + } + + public static ScheduleInstruction fromTag(CompoundTag tag) { + ResourceLocation location = new ResourceLocation(tag.getString("Id")); + Supplier supplier = null; + for (Pair> pair : Schedule.INSTRUCTION_TYPES) + if (pair.getFirst() + .equals(location)) + supplier = pair.getSecond(); + + if (supplier == null) { + Create.LOGGER.warn("Could not parse schedule instruction type: " + location); + return new DestinationInstruction(); + } + + ScheduleInstruction scheduleDestination = supplier.get(); + // Left around for migration purposes. Data added in writeAdditional has moved into the "Data" tag + scheduleDestination.readAdditional(tag); + CompoundTag data = tag.getCompound("Data"); + scheduleDestination.readAdditional(data); + scheduleDestination.data = data; + return scheduleDestination; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/destination/TextScheduleInstruction.java b/src/main/java/com/simibubi/create/content/trains/schedule/destination/TextScheduleInstruction.java similarity index 93% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/destination/TextScheduleInstruction.java rename to src/main/java/com/simibubi/create/content/trains/schedule/destination/TextScheduleInstruction.java index 42abcbf11..c18ca2702 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/schedule/destination/TextScheduleInstruction.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/destination/TextScheduleInstruction.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.management.schedule.destination; +package com.simibubi.create.content.trains.schedule.destination; import java.util.List; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/signal/EdgeGroupColor.java b/src/main/java/com/simibubi/create/content/trains/signal/EdgeGroupColor.java similarity index 91% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/signal/EdgeGroupColor.java rename to src/main/java/com/simibubi/create/content/trains/signal/EdgeGroupColor.java index 6c0161ec1..6d3d4c1f0 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/signal/EdgeGroupColor.java +++ b/src/main/java/com/simibubi/create/content/trains/signal/EdgeGroupColor.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.management.edgePoint.signal; +package com.simibubi.create.content.trains.signal; import com.simibubi.create.foundation.utility.Color; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/signal/SignalBlock.java b/src/main/java/com/simibubi/create/content/trains/signal/SignalBlock.java similarity index 84% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/signal/SignalBlock.java rename to src/main/java/com/simibubi/create/content/trains/signal/SignalBlock.java index 041e26702..eca416bb9 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/signal/SignalBlock.java +++ b/src/main/java/com/simibubi/create/content/trains/signal/SignalBlock.java @@ -1,10 +1,10 @@ -package com.simibubi.create.content.logistics.trains.management.edgePoint.signal; +package com.simibubi.create.content.trains.signal; import javax.annotation.Nullable; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.AllBlockEntityTypes; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.utility.Lang; import net.minecraft.core.BlockPos; @@ -26,7 +26,7 @@ import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraft.world.level.block.state.properties.EnumProperty; -public class SignalBlock extends Block implements ITE, IWrenchable { +public class SignalBlock extends Block implements IBE, IWrenchable { public static final EnumProperty TYPE = EnumProperty.create("type", SignalType.class); public static final BooleanProperty POWERED = BlockStateProperties.POWERED; @@ -47,8 +47,8 @@ public class SignalBlock extends Block implements ITE, IWrench } @Override - public Class getTileEntityClass() { - return SignalTileEntity.class; + public Class getBlockEntityClass() { + return SignalBlockEntity.class; } @Override @@ -92,12 +92,12 @@ public class SignalBlock extends Block implements ITE, IWrench @Override public void onRemove(BlockState state, Level worldIn, BlockPos pos, BlockState newState, boolean isMoving) { - ITE.onRemove(state, worldIn, pos, newState); + IBE.onRemove(state, worldIn, pos, newState); } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.TRACK_SIGNAL.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.TRACK_SIGNAL.get(); } @Override @@ -106,7 +106,7 @@ public class SignalBlock extends Block implements ITE, IWrench BlockPos pos = context.getClickedPos(); if (level.isClientSide) return InteractionResult.SUCCESS; - withTileEntityDo(level, pos, ste -> { + withBlockEntityDo(level, pos, ste -> { SignalBoundary signal = ste.getSignal(); Player player = context.getPlayer(); if (signal != null) { @@ -127,7 +127,7 @@ public class SignalBlock extends Block implements ITE, IWrench @Override public int getAnalogOutputSignal(BlockState pState, Level blockAccess, BlockPos pPos) { - return getTileEntityOptional(blockAccess, pPos).filter(SignalTileEntity::isPowered) + return getBlockEntityOptional(blockAccess, pPos).filter(SignalBlockEntity::isPowered) .map($ -> 15) .orElse(0); } diff --git a/src/main/java/com/simibubi/create/content/trains/signal/SignalBlockEntity.java b/src/main/java/com/simibubi/create/content/trains/signal/SignalBlockEntity.java new file mode 100644 index 000000000..bfae67e6f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/signal/SignalBlockEntity.java @@ -0,0 +1,167 @@ +package com.simibubi.create.content.trains.signal; + +import java.util.List; + +import javax.annotation.Nullable; + +import com.simibubi.create.content.contraptions.ITransformableBlockEntity; +import com.simibubi.create.content.contraptions.StructureTransform; +import com.simibubi.create.content.trains.graph.EdgePointType; +import com.simibubi.create.content.trains.signal.SignalBlock.SignalType; +import com.simibubi.create.content.trains.track.TrackTargetingBehaviour; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.NBTHelper; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; + +public class SignalBlockEntity extends SmartBlockEntity implements ITransformableBlockEntity { + + public static enum OverlayState { + RENDER, SKIP, DUAL + } + + public static enum SignalState { + RED, YELLOW, GREEN, INVALID; + + public boolean isRedLight(float renderTime) { + return this == RED || this == INVALID && renderTime % 40 < 3; + } + + public boolean isYellowLight(float renderTime) { + return this == YELLOW; + } + + public boolean isGreenLight(float renderTime) { + return this == GREEN; + } + } + + public TrackTargetingBehaviour edgePoint; + + private SignalState state; + private OverlayState overlay; + private int switchToRedAfterTrainEntered; + private boolean lastReportedPower; + + public SignalBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + this.state = SignalState.INVALID; + this.overlay = OverlayState.SKIP; + this.lastReportedPower = false; + } + + @Override + protected void write(CompoundTag tag, boolean clientPacket) { + super.write(tag, clientPacket); + NBTHelper.writeEnum(tag, "State", state); + NBTHelper.writeEnum(tag, "Overlay", overlay); + tag.putBoolean("Power", lastReportedPower); + } + + @Override + protected void read(CompoundTag tag, boolean clientPacket) { + super.read(tag, clientPacket); + state = NBTHelper.readEnum(tag, "State", SignalState.class); + overlay = NBTHelper.readEnum(tag, "Overlay", OverlayState.class); + lastReportedPower = tag.getBoolean("Power"); + invalidateRenderBoundingBox(); + } + + @Nullable + public SignalBoundary getSignal() { + return edgePoint.getEdgePoint(); + } + + public boolean isPowered() { + return state == SignalState.RED; + } + + @Override + public void addBehaviours(List behaviours) { + edgePoint = new TrackTargetingBehaviour<>(this, EdgePointType.SIGNAL); + behaviours.add(edgePoint); + } + + @Override + public void tick() { + super.tick(); + if (level.isClientSide) + return; + + SignalBoundary boundary = getSignal(); + if (boundary == null) { + enterState(SignalState.INVALID); + setOverlay(OverlayState.RENDER); + return; + } + + BlockState blockState = getBlockState(); + + blockState.getOptionalValue(SignalBlock.POWERED).ifPresent(powered -> { + if (lastReportedPower == powered) + return; + lastReportedPower = powered; + boundary.updateBlockEntityPower(this); + notifyUpdate(); + }); + + blockState.getOptionalValue(SignalBlock.TYPE) + .ifPresent(stateType -> { + SignalType targetType = boundary.getTypeFor(worldPosition); + if (stateType != targetType) { + level.setBlock(worldPosition, blockState.setValue(SignalBlock.TYPE, targetType), 3); + refreshBlockState(); + } + }); + + enterState(boundary.getStateFor(worldPosition)); + setOverlay(boundary.getOverlayFor(worldPosition)); + } + + public boolean getReportedPower() { + return lastReportedPower; + } + + public SignalState getState() { + return state; + } + + public OverlayState getOverlay() { + return overlay; + } + + public void setOverlay(OverlayState state) { + if (this.overlay == state) + return; + this.overlay = state; + notifyUpdate(); + } + + public void enterState(SignalState state) { + if (switchToRedAfterTrainEntered > 0) + switchToRedAfterTrainEntered--; + if (this.state == state) + return; + if (state == SignalState.RED && switchToRedAfterTrainEntered > 0) + return; + this.state = state; + switchToRedAfterTrainEntered = state == SignalState.GREEN || state == SignalState.YELLOW ? 15 : 0; + notifyUpdate(); + } + + @Override + protected AABB createRenderBoundingBox() { + return new AABB(worldPosition, edgePoint.getGlobalPosition()).inflate(2); + } + + @Override + public void transform(StructureTransform transform) { + edgePoint.transform(transform); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/signal/SignalBoundary.java b/src/main/java/com/simibubi/create/content/trains/signal/SignalBoundary.java similarity index 86% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/signal/SignalBoundary.java rename to src/main/java/com/simibubi/create/content/trains/signal/SignalBoundary.java index 6d57f86e2..327b525c2 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/signal/SignalBoundary.java +++ b/src/main/java/com/simibubi/create/content/trains/signal/SignalBoundary.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.management.edgePoint.signal; +package com.simibubi.create.content.trains.signal; import java.util.HashMap; import java.util.Map; @@ -7,13 +7,13 @@ import java.util.UUID; import com.google.common.base.Objects; import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.DimensionPalette; -import com.simibubi.create.content.logistics.trains.TrackGraph; -import com.simibubi.create.content.logistics.trains.TrackNode; -import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalBlock.SignalType; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalTileEntity.OverlayState; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalTileEntity.SignalState; +import com.simibubi.create.content.trains.graph.DimensionPalette; +import com.simibubi.create.content.trains.graph.EdgePointType; +import com.simibubi.create.content.trains.graph.TrackGraph; +import com.simibubi.create.content.trains.graph.TrackNode; +import com.simibubi.create.content.trains.signal.SignalBlock.SignalType; +import com.simibubi.create.content.trains.signal.SignalBlockEntity.OverlayState; +import com.simibubi.create.content.trains.signal.SignalBlockEntity.SignalState; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.NBTHelper; @@ -96,24 +96,24 @@ public class SignalBoundary extends TrackEdgePoint { } @Override - public void tileAdded(BlockEntity tile, boolean front) { - Map tilesOnSide = blockEntities.get(front); - if (tilesOnSide.isEmpty()) - tile.getBlockState() + public void blockEntityAdded(BlockEntity blockEntity, boolean front) { + Map blockEntitiesOnSide = blockEntities.get(front); + if (blockEntitiesOnSide.isEmpty()) + blockEntity.getBlockState() .getOptionalValue(SignalBlock.TYPE) .ifPresent(type -> types.set(front, type)); - tilesOnSide.put(tile.getBlockPos(), tile instanceof SignalTileEntity ste && ste.getReportedPower()); + blockEntitiesOnSide.put(blockEntity.getBlockPos(), blockEntity instanceof SignalBlockEntity ste && ste.getReportedPower()); } - public void updateTilePower(SignalTileEntity tile) { + public void updateBlockEntityPower(SignalBlockEntity blockEntity) { for (boolean front : Iterate.trueAndFalse) blockEntities.get(front) - .computeIfPresent(tile.getBlockPos(), (p, c) -> tile.getReportedPower()); + .computeIfPresent(blockEntity.getBlockPos(), (p, c) -> blockEntity.getReportedPower()); } @Override - public void tileRemoved(BlockPos tilePos, boolean front) { - blockEntities.forEach(s -> s.remove(tilePos)); + public void blockEntityRemoved(BlockPos blockEntityPos, boolean front) { + blockEntities.forEach(s -> s.remove(blockEntityPos)); if (blockEntities.both(Map::isEmpty)) removeFromAllGraphs(); } @@ -138,11 +138,11 @@ public class SignalBoundary extends TrackEdgePoint { .isEmpty(); } - public OverlayState getOverlayFor(BlockPos tile) { + public OverlayState getOverlayFor(BlockPos blockEntity) { for (boolean first : Iterate.trueAndFalse) { Map set = blockEntities.get(first); for (BlockPos blockPos : set.keySet()) { - if (blockPos.equals(tile)) + if (blockPos.equals(blockEntity)) return blockEntities.get(!first) .isEmpty() ? OverlayState.RENDER : OverlayState.DUAL; return OverlayState.SKIP; @@ -151,15 +151,15 @@ public class SignalBoundary extends TrackEdgePoint { return OverlayState.SKIP; } - public SignalType getTypeFor(BlockPos tile) { + public SignalType getTypeFor(BlockPos blockEntity) { return types.get(blockEntities.getFirst() - .containsKey(tile)); + .containsKey(blockEntity)); } - public SignalState getStateFor(BlockPos tile) { + public SignalState getStateFor(BlockPos blockEntity) { for (boolean first : Iterate.trueAndFalse) { Map set = blockEntities.get(first); - if (set.containsKey(tile)) + if (set.containsKey(blockEntity)) return cachedStates.get(first); } return SignalState.INVALID; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/signal/SignalEdgeGroup.java b/src/main/java/com/simibubi/create/content/trains/signal/SignalEdgeGroup.java similarity index 96% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/signal/SignalEdgeGroup.java rename to src/main/java/com/simibubi/create/content/trains/signal/SignalEdgeGroup.java index 3f84a6f47..9f38ffb71 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/signal/SignalEdgeGroup.java +++ b/src/main/java/com/simibubi/create/content/trains/signal/SignalEdgeGroup.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.management.edgePoint.signal; +package com.simibubi.create.content.trains.signal; import java.util.HashMap; import java.util.HashSet; @@ -12,7 +12,7 @@ import org.apache.commons.lang3.mutable.MutableInt; import com.google.common.base.Predicates; import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.entity.Train; +import com.simibubi.create.content.trains.entity.Train; import com.simibubi.create.foundation.utility.NBTHelper; import net.minecraft.nbt.CompoundTag; diff --git a/src/main/java/com/simibubi/create/content/trains/signal/SignalEdgeGroupPacket.java b/src/main/java/com/simibubi/create/content/trains/signal/SignalEdgeGroupPacket.java new file mode 100644 index 000000000..4b6b2c999 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/signal/SignalEdgeGroupPacket.java @@ -0,0 +1,73 @@ +package com.simibubi.create.content.trains.signal; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import com.google.common.collect.ImmutableList; +import com.simibubi.create.CreateClient; +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.network.NetworkEvent.Context; + +public class SignalEdgeGroupPacket extends SimplePacketBase { + + List ids; + List colors; + boolean add; + + public SignalEdgeGroupPacket(UUID id, EdgeGroupColor color) { + this(ImmutableList.of(id), ImmutableList.of(color), true); + } + + public SignalEdgeGroupPacket(List ids, List colors, boolean add) { + this.ids = ids; + this.colors = colors; + this.add = add; + } + + public SignalEdgeGroupPacket(FriendlyByteBuf buffer) { + ids = new ArrayList<>(); + colors = new ArrayList<>(); + add = buffer.readBoolean(); + int size = buffer.readVarInt(); + for (int i = 0; i < size; i++) + ids.add(buffer.readUUID()); + size = buffer.readVarInt(); + for (int i = 0; i < size; i++) + colors.add(EdgeGroupColor.values()[buffer.readVarInt()]); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeBoolean(add); + buffer.writeVarInt(ids.size()); + ids.forEach(buffer::writeUUID); + buffer.writeVarInt(colors.size()); + colors.forEach(c -> buffer.writeVarInt(c.ordinal())); + } + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> { + Map signalEdgeGroups = CreateClient.RAILWAYS.signalEdgeGroups; + int i = 0; + for (UUID id : ids) { + if (!add) { + signalEdgeGroups.remove(id); + continue; + } + + SignalEdgeGroup group = new SignalEdgeGroup(id); + signalEdgeGroups.put(id, group); + if (colors.size() > i) + group.color = colors.get(i); + i++; + } + }); + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/signal/SignalPropagator.java b/src/main/java/com/simibubi/create/content/trains/signal/SignalPropagator.java similarity index 91% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/signal/SignalPropagator.java rename to src/main/java/com/simibubi/create/content/trains/signal/SignalPropagator.java index 6eaf4319f..33e8b8509 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/signal/SignalPropagator.java +++ b/src/main/java/com/simibubi/create/content/trains/signal/SignalPropagator.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.management.edgePoint.signal; +package com.simibubi.create.content.trains.signal; import java.util.ArrayList; import java.util.HashMap; @@ -12,14 +12,14 @@ import java.util.function.Predicate; import com.google.common.base.Predicates; import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.TrackEdge; -import com.simibubi.create.content.logistics.trains.TrackGraph; -import com.simibubi.create.content.logistics.trains.TrackGraphSync; -import com.simibubi.create.content.logistics.trains.TrackNode; -import com.simibubi.create.content.logistics.trains.TrackNodeLocation; -import com.simibubi.create.content.logistics.trains.entity.Train; -import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgeData; -import com.simibubi.create.content.logistics.trains.management.edgePoint.EdgePointType; +import com.simibubi.create.content.trains.entity.Train; +import com.simibubi.create.content.trains.graph.EdgeData; +import com.simibubi.create.content.trains.graph.EdgePointType; +import com.simibubi.create.content.trains.graph.TrackEdge; +import com.simibubi.create.content.trains.graph.TrackGraph; +import com.simibubi.create.content.trains.graph.TrackGraphSync; +import com.simibubi.create.content.trains.graph.TrackNode; +import com.simibubi.create.content.trains.graph.TrackNodeLocation; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Pair; diff --git a/src/main/java/com/simibubi/create/content/trains/signal/SignalRenderer.java b/src/main/java/com/simibubi/create/content/trains/signal/SignalRenderer.java new file mode 100644 index 000000000..6d5bb09eb --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/signal/SignalRenderer.java @@ -0,0 +1,66 @@ +package com.simibubi.create.content.trains.signal; + +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.trains.signal.SignalBlockEntity.OverlayState; +import com.simibubi.create.content.trains.signal.SignalBlockEntity.SignalState; +import com.simibubi.create.content.trains.track.ITrackBlock; +import com.simibubi.create.content.trains.track.TrackTargetingBehaviour; +import com.simibubi.create.content.trains.track.TrackTargetingBehaviour.RenderedTrackOverlayType; +import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.utility.AnimationTickHolder; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; + +public class SignalRenderer extends SafeBlockEntityRenderer { + + public SignalRenderer(BlockEntityRendererProvider.Context context) {} + + @Override + protected void renderSafe(SignalBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + BlockState blockState = be.getBlockState(); + SignalState signalState = be.getState(); + OverlayState overlayState = be.getOverlay(); + + float renderTime = AnimationTickHolder.getRenderTime(be.getLevel()); + if (signalState.isRedLight(renderTime)) + CachedBufferer.partial(AllPartialModels.SIGNAL_ON, blockState) + .renderInto(ms, buffer.getBuffer(RenderType.solid())); + else + CachedBufferer.partial(AllPartialModels.SIGNAL_OFF, blockState) + .light(light) + .renderInto(ms, buffer.getBuffer(RenderType.solid())); + + BlockPos pos = be.getBlockPos(); + TrackTargetingBehaviour target = be.edgePoint; + BlockPos targetPosition = target.getGlobalPosition(); + Level level = be.getLevel(); + BlockState trackState = level.getBlockState(targetPosition); + Block block = trackState.getBlock(); + + if (!(block instanceof ITrackBlock)) + return; + if (overlayState == OverlayState.SKIP) + return; + + ms.pushPose(); + TransformStack.cast(ms) + .translate(targetPosition.subtract(pos)); + RenderedTrackOverlayType type = + overlayState == OverlayState.DUAL ? RenderedTrackOverlayType.DUAL_SIGNAL : RenderedTrackOverlayType.SIGNAL; + TrackTargetingBehaviour.render(level, targetPosition, target.getTargetDirection(), target.getTargetBezier(), ms, + buffer, light, overlay, type, 1); + ms.popPose(); + + } + +} diff --git a/src/main/java/com/simibubi/create/content/trains/signal/SingleBlockEntityEdgePoint.java b/src/main/java/com/simibubi/create/content/trains/signal/SingleBlockEntityEdgePoint.java new file mode 100644 index 000000000..096a03b90 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/signal/SingleBlockEntityEdgePoint.java @@ -0,0 +1,64 @@ +package com.simibubi.create.content.trains.signal; + +import com.simibubi.create.content.trains.graph.DimensionPalette; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.entity.BlockEntity; + +public abstract class SingleBlockEntityEdgePoint extends TrackEdgePoint { + + public ResourceKey blockEntityDimension; + public BlockPos blockEntityPos; + + public BlockPos getBlockEntityPos() { + return blockEntityPos; + } + + public ResourceKey getBlockEntityDimension() { + return blockEntityDimension; + } + + @Override + public void blockEntityAdded(BlockEntity blockEntity, boolean front) { + this.blockEntityPos = blockEntity.getBlockPos(); + this.blockEntityDimension = blockEntity.getLevel() + .dimension(); + } + + @Override + public void blockEntityRemoved(BlockPos blockEntityPos, boolean front) { + removeFromAllGraphs(); + } + + @Override + public void invalidate(LevelAccessor level) { + invalidateAt(level, blockEntityPos); + } + + @Override + public boolean canMerge() { + return false; + } + + @Override + public void read(CompoundTag nbt, boolean migration, DimensionPalette dimensions) { + super.read(nbt, migration, dimensions); + if (migration) + return; + blockEntityPos = NbtUtils.readBlockPos(nbt.getCompound("TilePos")); + blockEntityDimension = dimensions.decode(nbt.contains("TileDimension") ? nbt.getInt("TileDimension") : -1); + } + + @Override + public void write(CompoundTag nbt, DimensionPalette dimensions) { + super.write(nbt, dimensions); + nbt.put("TilePos", NbtUtils.writeBlockPos(blockEntityPos)); + nbt.putInt("TileDimension", dimensions.encode(blockEntityDimension)); + } + +} diff --git a/src/main/java/com/simibubi/create/content/trains/signal/TrackEdgePoint.java b/src/main/java/com/simibubi/create/content/trains/signal/TrackEdgePoint.java new file mode 100644 index 000000000..5b9e1c5e2 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/signal/TrackEdgePoint.java @@ -0,0 +1,126 @@ +package com.simibubi.create.content.trains.signal; + +import java.util.UUID; + +import com.simibubi.create.Create; +import com.simibubi.create.content.trains.graph.DimensionPalette; +import com.simibubi.create.content.trains.graph.EdgePointType; +import com.simibubi.create.content.trains.graph.TrackEdge; +import com.simibubi.create.content.trains.graph.TrackGraph; +import com.simibubi.create.content.trains.graph.TrackNode; +import com.simibubi.create.content.trains.graph.TrackNodeLocation; +import com.simibubi.create.content.trains.track.TrackTargetingBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.Couple; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.block.entity.BlockEntity; + +public abstract class TrackEdgePoint { + + public UUID id; + public Couple edgeLocation; + public double position; + private EdgePointType type; + + public void setId(UUID id) { + this.id = id; + } + + public UUID getId() { + return id; + } + + public void setType(EdgePointType type) { + this.type = type; + } + + public EdgePointType getType() { + return type; + } + + public abstract boolean canMerge(); + + public boolean canCoexistWith(EdgePointType otherType, boolean front) { + return false; + } + + public abstract void invalidate(LevelAccessor level); + + protected void invalidateAt(LevelAccessor level, BlockPos blockEntityPos) { + TrackTargetingBehaviour behaviour = BlockEntityBehaviour.get(level, blockEntityPos, TrackTargetingBehaviour.TYPE); + if (behaviour == null) + return; + CompoundTag migrationData = new CompoundTag(); + DimensionPalette dimensions = new DimensionPalette(); + write(migrationData, dimensions); + dimensions.write(migrationData); + behaviour.invalidateEdgePoint(migrationData); + } + + public abstract void blockEntityAdded(BlockEntity blockEntity, boolean front); + + public abstract void blockEntityRemoved(BlockPos blockEntityPos, boolean front); + + public void onRemoved(TrackGraph graph) {} + + public void setLocation(Couple nodes, double position) { + this.edgeLocation = nodes; + this.position = position; + } + + public double getLocationOn(TrackEdge edge) { + return isPrimary(edge.node1) ? edge.getLength() - position : position; + } + + public boolean canNavigateVia(TrackNode side) { + return true; + } + + public boolean isPrimary(TrackNode node1) { + return edgeLocation.getSecond() + .equals(node1.getLocation()); + } + + public void read(CompoundTag nbt, boolean migration, DimensionPalette dimensions) { + if (migration) + return; + + id = nbt.getUUID("Id"); + position = nbt.getDouble("Position"); + edgeLocation = Couple.deserializeEach(nbt.getList("Edge", Tag.TAG_COMPOUND), + tag -> TrackNodeLocation.read(tag, dimensions)); + } + + public void read(FriendlyByteBuf buffer, DimensionPalette dimensions) { + id = buffer.readUUID(); + edgeLocation = Couple.create(() -> TrackNodeLocation.receive(buffer, dimensions)); + position = buffer.readDouble(); + } + + public void write(CompoundTag nbt, DimensionPalette dimensions) { + nbt.putUUID("Id", id); + nbt.putDouble("Position", position); + nbt.put("Edge", edgeLocation.serializeEach(loc -> loc.write(dimensions))); + } + + public void write(FriendlyByteBuf buffer, DimensionPalette dimensions) { + buffer.writeResourceLocation(type.getId()); + buffer.writeUUID(id); + edgeLocation.forEach(loc -> loc.send(buffer, dimensions)); + buffer.writeDouble(position); + } + + public void tick(TrackGraph graph, boolean preTrains) {} + + protected void removeFromAllGraphs() { + for (TrackGraph trackGraph : Create.RAILWAYS.trackNetworks.values()) + if (trackGraph.removePoint(getType(), id) != null) + return; + } + +} diff --git a/src/main/java/com/simibubi/create/content/trains/station/AbstractStationScreen.java b/src/main/java/com/simibubi/create/content/trains/station/AbstractStationScreen.java new file mode 100644 index 000000000..40fe26487 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/station/AbstractStationScreen.java @@ -0,0 +1,130 @@ +package com.simibubi.create.content.trains.station; + +import java.lang.ref.WeakReference; +import java.util.List; + +import com.jozufozu.flywheel.core.PartialModel; +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.CreateClient; +import com.simibubi.create.compat.computercraft.ComputerScreen; +import com.simibubi.create.content.trains.entity.Carriage; +import com.simibubi.create.content.trains.entity.Train; +import com.simibubi.create.content.trains.entity.TrainIconType; +import com.simibubi.create.foundation.gui.AbstractSimiScreen; +import com.simibubi.create.foundation.gui.AllGuiTextures; +import com.simibubi.create.foundation.gui.AllIcons; +import com.simibubi.create.foundation.gui.element.GuiGameElement; +import com.simibubi.create.foundation.gui.widget.IconButton; +import com.simibubi.create.foundation.utility.Components; + +import net.minecraft.world.level.block.state.properties.BlockStateProperties; + +public abstract class AbstractStationScreen extends AbstractSimiScreen { + + protected AllGuiTextures background; + protected StationBlockEntity blockEntity; + protected GlobalStation station; + + protected WeakReference displayedTrain; + + private IconButton confirmButton; + + public AbstractStationScreen(StationBlockEntity be, GlobalStation station) { + super(be.getBlockState() + .getBlock() + .getName()); + this.blockEntity = be; + this.station = station; + displayedTrain = new WeakReference<>(null); + } + + @Override + protected void init() { + if (blockEntity.computerBehaviour.hasAttachedComputer()) + minecraft.setScreen(new ComputerScreen(title, () -> Components.literal(station.name), + this::renderAdditional, this, blockEntity.computerBehaviour::hasAttachedComputer)); + + setWindowSize(background.width, background.height); + super.init(); + clearWidgets(); + + int x = guiLeft; + int y = guiTop; + + confirmButton = new IconButton(x + background.width - 33, y + background.height - 24, AllIcons.I_CONFIRM); + confirmButton.withCallback(this::onClose); + addRenderableWidget(confirmButton); + } + + public int getTrainIconWidth(Train train) { + TrainIconType icon = train.icon; + List carriages = train.carriages; + + int w = icon.getIconWidth(TrainIconType.ENGINE); + if (carriages.size() == 1) + return w; + + for (int i = 1; i < carriages.size(); i++) { + if (i == carriages.size() - 1 && train.doubleEnded) { + w += icon.getIconWidth(TrainIconType.FLIPPED_ENGINE) + 1; + break; + } + Carriage carriage = carriages.get(i); + w += icon.getIconWidth(carriage.bogeySpacing) + 1; + } + + return w; + } + + @Override + public void tick() { + super.tick(); + + if (blockEntity.computerBehaviour.hasAttachedComputer()) + minecraft.setScreen(new ComputerScreen(title, () -> Components.literal(station.name), + this::renderAdditional, this, blockEntity.computerBehaviour::hasAttachedComputer)); + } + + @Override + protected void renderWindow(PoseStack ms, int mouseX, int mouseY, float partialTicks) { + int x = guiLeft; + int y = guiTop; + + background.render(ms, x, y, this); + renderAdditional(ms, mouseX, mouseY, partialTicks, x, y, background); + } + + private void renderAdditional(PoseStack ms, int mouseX, int mouseY, float partialTicks, int guiLeft, int guiTop, AllGuiTextures background) { + ms.pushPose(); + TransformStack msr = TransformStack.cast(ms); + msr.pushPose() + .translate(guiLeft + background.width + 4, guiTop + background.height + 4, 100) + .scale(40) + .rotateX(-22) + .rotateY(63); + GuiGameElement.of(blockEntity.getBlockState() + .setValue(BlockStateProperties.WATERLOGGED, false)) + .render(ms); + + if (blockEntity.resolveFlagAngle()) { + msr.translate(1 / 16f, -19 / 16f, -12 / 16f); + StationRenderer.transformFlag(msr, blockEntity, partialTicks, 180, false); + GuiGameElement.of(getFlag(partialTicks)) + .render(ms); + } + + ms.popPose(); + } + + protected abstract PartialModel getFlag(float partialTicks); + + protected Train getImminent() { + return blockEntity.imminentTrain == null ? null : CreateClient.RAILWAYS.trains.get(blockEntity.imminentTrain); + } + + protected boolean trainPresent() { + return blockEntity.trainPresent; + } + +} diff --git a/src/main/java/com/simibubi/create/content/trains/station/AssemblyScreen.java b/src/main/java/com/simibubi/create/content/trains/station/AssemblyScreen.java new file mode 100644 index 000000000..202ff2dd6 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/station/AssemblyScreen.java @@ -0,0 +1,176 @@ +package com.simibubi.create.content.trains.station; + +import java.lang.ref.WeakReference; +import java.util.List; + +import com.jozufozu.flywheel.core.PartialModel; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllPackets; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.contraptions.AssemblyException; +import com.simibubi.create.content.trains.entity.Carriage; +import com.simibubi.create.content.trains.entity.Train; +import com.simibubi.create.content.trains.entity.TrainIconType; +import com.simibubi.create.foundation.gui.AllGuiTextures; +import com.simibubi.create.foundation.gui.AllIcons; +import com.simibubi.create.foundation.gui.widget.IconButton; +import com.simibubi.create.foundation.gui.widget.ScrollInput; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.client.gui.components.Renderable; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.resources.ResourceLocation; + +public class AssemblyScreen extends AbstractStationScreen { + + private IconButton quitAssembly; + private IconButton toggleAssemblyButton; + private List iconTypes; + private ScrollInput iconTypeScroll; + + public AssemblyScreen(StationBlockEntity be, GlobalStation station) { + super(be, station); + background = AllGuiTextures.STATION_ASSEMBLING; + } + + @Override + protected void init() { + super.init(); + int x = guiLeft; + int y = guiTop; + int by = y + background.height - 24; + + Renderable widget = renderables.get(0); + if (widget instanceof IconButton ib) { + ib.setIcon(AllIcons.I_PRIORITY_VERY_LOW); + ib.setToolTip(Lang.translateDirect("station.close")); + } + + iconTypes = TrainIconType.REGISTRY.keySet() + .stream() + .toList(); + iconTypeScroll = new ScrollInput(x + 4, y + 17, 184, 14).titled(Lang.translateDirect("station.icon_type")); + iconTypeScroll.withRange(0, iconTypes.size()); + iconTypeScroll.withStepFunction(ctx -> -iconTypeScroll.standardStep() + .apply(ctx)); + iconTypeScroll.calling(s -> { + Train train = displayedTrain.get(); + if (train != null) + train.icon = TrainIconType.byId(iconTypes.get(s)); + }); + iconTypeScroll.active = iconTypeScroll.visible = false; + addRenderableWidget(iconTypeScroll); + + toggleAssemblyButton = new WideIconButton(x + 94, by, AllGuiTextures.I_ASSEMBLE_TRAIN); + toggleAssemblyButton.active = false; + toggleAssemblyButton.setToolTip(Lang.translateDirect("station.assemble_train")); + toggleAssemblyButton.withCallback(() -> { + AllPackets.getChannel() + .sendToServer(StationEditPacket.tryAssemble(blockEntity.getBlockPos())); + }); + + quitAssembly = new IconButton(x + 73, by, AllIcons.I_DISABLE); + quitAssembly.active = true; + quitAssembly.setToolTip(Lang.translateDirect("station.cancel")); + quitAssembly.withCallback(() -> { + AllPackets.getChannel() + .sendToServer(StationEditPacket.configure(blockEntity.getBlockPos(), false, station.name, null)); + minecraft.setScreen(new StationScreen(blockEntity, station)); + }); + + addRenderableWidget(toggleAssemblyButton); + addRenderableWidget(quitAssembly); + + tickTrainDisplay(); + } + + @Override + public void tick() { + super.tick(); + tickTrainDisplay(); + Train train = displayedTrain.get(); + toggleAssemblyButton.active = blockEntity.bogeyCount > 0 || train != null; + + if (train != null) { + AllPackets.getChannel() + .sendToServer(StationEditPacket.configure(blockEntity.getBlockPos(), false, station.name, null)); + minecraft.setScreen(new StationScreen(blockEntity, station)); + for (Carriage carriage : train.carriages) + carriage.updateConductors(); + } + } + + private void tickTrainDisplay() { + if (getImminent() == null) { + displayedTrain = new WeakReference<>(null); + quitAssembly.active = true; + iconTypeScroll.active = iconTypeScroll.visible = false; + toggleAssemblyButton.setToolTip(Lang.translateDirect("station.assemble_train")); + toggleAssemblyButton.setIcon(AllGuiTextures.I_ASSEMBLE_TRAIN); + toggleAssemblyButton.withCallback(() -> { + AllPackets.getChannel() + .sendToServer(StationEditPacket.tryAssemble(blockEntity.getBlockPos())); + }); + } else { + AllPackets.getChannel() + .sendToServer(StationEditPacket.configure(blockEntity.getBlockPos(), false, station.name, null)); + minecraft.setScreen(new StationScreen(blockEntity, station)); + } + } + + @Override + protected void renderWindow(PoseStack ms, int mouseX, int mouseY, float partialTicks) { + super.renderWindow(ms, mouseX, mouseY, partialTicks); + int x = guiLeft; + int y = guiTop; + + MutableComponent header = Lang.translateDirect("station.assembly_title"); + font.draw(ms, header, x + background.width / 2 - font.width(header) / 2, y + 4, 0x0E2233); + + AssemblyException lastAssemblyException = blockEntity.lastException; + if (lastAssemblyException != null) { + MutableComponent text = Lang.translateDirect("station.failed"); + font.draw(ms, text, x + 97 - font.width(text) / 2, y + 47, 0x775B5B); + int offset = 0; + if (blockEntity.failedCarriageIndex != -1) { + font.draw(ms, Lang.translateDirect("station.carriage_number", blockEntity.failedCarriageIndex), x + 30, + y + 67, 0x7A7A7A); + offset += 10; + } + font.drawWordWrap(lastAssemblyException.component, x + 30, y + 67 + offset, 134, 0x775B5B); + offset += font.split(lastAssemblyException.component, 134) + .size() * 9 + 5; + font.drawWordWrap(Lang.translateDirect("station.retry"), x + 30, y + 67 + offset, 134, 0x7A7A7A); + return; + } + + int bogeyCount = blockEntity.bogeyCount; + + MutableComponent text = Lang.translateDirect( + bogeyCount == 0 ? "station.no_bogeys" : bogeyCount == 1 ? "station.one_bogey" : "station.more_bogeys", + bogeyCount); + font.draw(ms, text, x + 97 - font.width(text) / 2, y + 47, 0x7A7A7A); + + font.drawWordWrap(Lang.translateDirect("station.how_to"), x + 28, y + 62, 134, 0x7A7A7A); + font.drawWordWrap(Lang.translateDirect("station.how_to_1"), x + 28, y + 94, 134, 0x7A7A7A); + font.drawWordWrap(Lang.translateDirect("station.how_to_2"), x + 28, y + 117, 138, 0x7A7A7A); + } + + @Override + public void removed() { + super.removed(); + Train train = displayedTrain.get(); + if (train != null) { + ResourceLocation iconId = iconTypes.get(iconTypeScroll.getState()); + train.icon = TrainIconType.byId(iconId); + AllPackets.getChannel() + .sendToServer(new TrainEditPacket(train.id, "", iconId)); + } + } + + @Override + protected PartialModel getFlag(float partialTicks) { + return AllPartialModels.STATION_ASSEMBLE; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/GlobalStation.java b/src/main/java/com/simibubi/create/content/trains/station/GlobalStation.java similarity index 79% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/GlobalStation.java rename to src/main/java/com/simibubi/create/content/trains/station/GlobalStation.java index d7db61a8f..bc025316c 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/GlobalStation.java +++ b/src/main/java/com/simibubi/create/content/trains/station/GlobalStation.java @@ -1,20 +1,20 @@ -package com.simibubi.create.content.logistics.trains.management.edgePoint.station; +package com.simibubi.create.content.trains.station; import java.lang.ref.WeakReference; import javax.annotation.Nullable; -import com.simibubi.create.content.logistics.trains.DimensionPalette; -import com.simibubi.create.content.logistics.trains.TrackNode; -import com.simibubi.create.content.logistics.trains.entity.Train; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SingleTileEdgePoint; +import com.simibubi.create.content.trains.entity.Train; +import com.simibubi.create.content.trains.graph.DimensionPalette; +import com.simibubi.create.content.trains.graph.TrackNode; +import com.simibubi.create.content.trains.signal.SingleBlockEntityEdgePoint; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; -public class GlobalStation extends SingleTileEdgePoint { +public class GlobalStation extends SingleBlockEntityEdgePoint { public String name; public WeakReference nearestTrain; @@ -26,9 +26,9 @@ public class GlobalStation extends SingleTileEdgePoint { } @Override - public void tileAdded(BlockEntity tile, boolean front) { - super.tileAdded(tile, front); - BlockState state = tile.getBlockState(); + public void blockEntityAdded(BlockEntity blockEntity, boolean front) { + super.blockEntityAdded(blockEntity, front); + BlockState state = blockEntity.getBlockState(); assembling = state != null && state.hasProperty(StationBlock.ASSEMBLING) && state.getValue(StationBlock.ASSEMBLING); } @@ -47,7 +47,7 @@ public class GlobalStation extends SingleTileEdgePoint { name = buffer.readUtf(); assembling = buffer.readBoolean(); if (buffer.readBoolean()) - tilePos = buffer.readBlockPos(); + blockEntityPos = buffer.readBlockPos(); } @Override @@ -62,9 +62,9 @@ public class GlobalStation extends SingleTileEdgePoint { super.write(buffer, dimensions); buffer.writeUtf(name); buffer.writeBoolean(assembling); - buffer.writeBoolean(tilePos != null); - if (tilePos != null) - buffer.writeBlockPos(tilePos); + buffer.writeBoolean(blockEntityPos != null); + if (blockEntityPos != null) + buffer.writeBlockPos(blockEntityPos); } public boolean canApproachFrom(TrackNode side) { diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/NoShadowFontWrapper.java b/src/main/java/com/simibubi/create/content/trains/station/NoShadowFontWrapper.java similarity index 98% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/NoShadowFontWrapper.java rename to src/main/java/com/simibubi/create/content/trains/station/NoShadowFontWrapper.java index 855f30675..8d21697a1 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/NoShadowFontWrapper.java +++ b/src/main/java/com/simibubi/create/content/trains/station/NoShadowFontWrapper.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.management.edgePoint.station; +package com.simibubi.create.content.trains.station; import java.util.List; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationBlock.java b/src/main/java/com/simibubi/create/content/trains/station/StationBlock.java similarity index 81% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationBlock.java rename to src/main/java/com/simibubi/create/content/trains/station/StationBlock.java index de0473e11..9544e6efe 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationBlock.java +++ b/src/main/java/com/simibubi/create/content/trains/station/StationBlock.java @@ -1,13 +1,13 @@ -package com.simibubi.create.content.logistics.trains.management.edgePoint.station; +package com.simibubi.create.content.trains.station; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllItems; import com.simibubi.create.AllShapes; import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; -import com.simibubi.create.content.logistics.block.depot.SharedDepotBlockMethods; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.content.logistics.depot.SharedDepotBlockMethods; import com.simibubi.create.foundation.advancement.AdvancementBehaviour; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.block.ProperWaterloggedBlock; import com.simibubi.create.foundation.gui.ScreenOpener; @@ -41,7 +41,7 @@ import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.fml.DistExecutor; -public class StationBlock extends Block implements ITE, IWrenchable, ProperWaterloggedBlock { +public class StationBlock extends Block implements IBE, IWrenchable, ProperWaterloggedBlock { public static final BooleanProperty ASSEMBLING = BooleanProperty.create("assembling"); @@ -86,13 +86,13 @@ public class StationBlock extends Block implements ITE, IWren @Override public int getAnalogOutputSignal(BlockState pState, Level pLevel, BlockPos pPos) { - return getTileEntityOptional(pLevel, pPos).map(ste -> ste.trainPresent ? 15 : 0) + return getBlockEntityOptional(pLevel, pPos).map(ste -> ste.trainPresent ? 15 : 0) .orElse(0); } @Override public void onRemove(BlockState state, Level worldIn, BlockPos pos, BlockState newState, boolean isMoving) { - ITE.onRemove(state, worldIn, pos, newState); + IBE.onRemove(state, worldIn, pos, newState); } @Override @@ -112,7 +112,7 @@ public class StationBlock extends Block implements ITE, IWren return InteractionResult.PASS; if (itemInHand.getItem() == Items.FILLED_MAP) { - return onTileEntityUse(pLevel, pPos, station -> { + return onBlockEntityUse(pLevel, pPos, station -> { if (pLevel.isClientSide) return InteractionResult.SUCCESS; @@ -130,7 +130,7 @@ public class StationBlock extends Block implements ITE, IWren }); } - InteractionResult result = onTileEntityUse(pLevel, pPos, station -> { + InteractionResult result = onBlockEntityUse(pLevel, pPos, station -> { ItemStack autoSchedule = station.getAutoSchedule(); if (autoSchedule.isEmpty()) return InteractionResult.PASS; @@ -146,20 +146,20 @@ public class StationBlock extends Block implements ITE, IWren if (result == InteractionResult.PASS) DistExecutor.unsafeRunWhenOn(Dist.CLIENT, - () -> () -> withTileEntityDo(pLevel, pPos, te -> this.displayScreen(te, pPlayer))); + () -> () -> withBlockEntityDo(pLevel, pPos, be -> this.displayScreen(be, pPlayer))); return InteractionResult.SUCCESS; } @OnlyIn(value = Dist.CLIENT) - protected void displayScreen(StationTileEntity te, Player player) { + protected void displayScreen(StationBlockEntity be, Player player) { if (!(player instanceof LocalPlayer)) return; - GlobalStation station = te.getStation(); - BlockState blockState = te.getBlockState(); + GlobalStation station = be.getStation(); + BlockState blockState = be.getBlockState(); if (station == null || blockState == null) return; boolean assembling = blockState.getBlock() == this && blockState.getValue(ASSEMBLING); - ScreenOpener.open(assembling ? new AssemblyScreen(te, station) : new StationScreen(te, station)); + ScreenOpener.open(assembling ? new AssemblyScreen(be, station) : new StationScreen(be, station)); } @Override @@ -168,13 +168,13 @@ public class StationBlock extends Block implements ITE, IWren } @Override - public Class getTileEntityClass() { - return StationTileEntity.class; + public Class getBlockEntityClass() { + return StationBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.TRACK_STATION.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.TRACK_STATION.get(); } @Override diff --git a/src/main/java/com/simibubi/create/content/trains/station/StationBlockEntity.java b/src/main/java/com/simibubi/create/content/trains/station/StationBlockEntity.java new file mode 100644 index 000000000..44657b81f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/station/StationBlockEntity.java @@ -0,0 +1,934 @@ +package com.simibubi.create.content.trains.station; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; +import java.util.UUID; +import java.util.function.Consumer; + +import javax.annotation.Nullable; + +import org.jetbrains.annotations.NotNull; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllItems; +import com.simibubi.create.AllPackets; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.Create; +import com.simibubi.create.compat.computercraft.AbstractComputerBehaviour; +import com.simibubi.create.compat.computercraft.ComputerCraftProxy; +import com.simibubi.create.content.contraptions.AssemblyException; +import com.simibubi.create.content.contraptions.ITransformableBlockEntity; +import com.simibubi.create.content.contraptions.StructureTransform; +import com.simibubi.create.content.decoration.slidingDoor.DoorControlBehaviour; +import com.simibubi.create.content.logistics.depot.DepotBehaviour; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkBlock; +import com.simibubi.create.content.trains.bogey.AbstractBogeyBlock; +import com.simibubi.create.content.trains.bogey.AbstractBogeyBlockEntity; +import com.simibubi.create.content.trains.entity.Carriage; +import com.simibubi.create.content.trains.entity.CarriageBogey; +import com.simibubi.create.content.trains.entity.CarriageContraption; +import com.simibubi.create.content.trains.entity.Train; +import com.simibubi.create.content.trains.entity.TrainPacket; +import com.simibubi.create.content.trains.entity.TravellingPoint; +import com.simibubi.create.content.trains.graph.EdgePointType; +import com.simibubi.create.content.trains.graph.TrackEdge; +import com.simibubi.create.content.trains.graph.TrackGraph; +import com.simibubi.create.content.trains.graph.TrackGraphLocation; +import com.simibubi.create.content.trains.graph.TrackNode; +import com.simibubi.create.content.trains.graph.TrackNodeLocation; +import com.simibubi.create.content.trains.graph.TrackNodeLocation.DiscoveredLocation; +import com.simibubi.create.content.trains.schedule.Schedule; +import com.simibubi.create.content.trains.schedule.ScheduleItem; +import com.simibubi.create.content.trains.track.ITrackBlock; +import com.simibubi.create.content.trains.track.TrackTargetingBehaviour; +import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.foundation.block.ProperWaterloggedBlock; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.NBTHelper; +import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.WorldAttached; +import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.minecraft.ChatFormatting; +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.core.particles.ParticleTypes; +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.sounds.SoundSource; +import net.minecraft.util.Mth; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.structure.BoundingBox; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.network.PacketDistributor; + +public class StationBlockEntity extends SmartBlockEntity implements ITransformableBlockEntity { + + public TrackTargetingBehaviour edgePoint; + public DoorControlBehaviour doorControls; + public LerpedFloat flag; + + protected int failedCarriageIndex; + protected AssemblyException lastException; + protected DepotBehaviour depotBehaviour; + public AbstractComputerBehaviour computerBehaviour; + + // for display + UUID imminentTrain; + boolean trainPresent; + boolean trainBackwards; + boolean trainCanDisassemble; + boolean trainHasSchedule; + boolean trainHasAutoSchedule; + + int flagYRot = -1; + boolean flagFlipped; + + public Component lastDisassembledTrainName; + + public StationBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + setLazyTickRate(20); + lastException = null; + failedCarriageIndex = -1; + flag = LerpedFloat.linear() + .startWithValue(0); + } + + @Override + public void addBehaviours(List behaviours) { + behaviours.add(edgePoint = new TrackTargetingBehaviour<>(this, EdgePointType.STATION)); + behaviours.add(doorControls = new DoorControlBehaviour(this)); + behaviours.add(depotBehaviour = new DepotBehaviour(this).onlyAccepts(AllItems.SCHEDULE::isIn) + .withCallback(s -> applyAutoSchedule())); + depotBehaviour.addSubBehaviours(behaviours); + registerAwardables(behaviours, AllAdvancements.CONTRAPTION_ACTORS, AllAdvancements.TRAIN, + AllAdvancements.LONG_TRAIN, AllAdvancements.CONDUCTOR); + behaviours.add(computerBehaviour = ComputerCraftProxy.behaviour(this)); + } + + @Override + protected void read(CompoundTag tag, boolean clientPacket) { + lastException = AssemblyException.read(tag); + failedCarriageIndex = tag.getInt("FailedCarriageIndex"); + super.read(tag, clientPacket); + invalidateRenderBoundingBox(); + + if (tag.contains("ForceFlag")) + trainPresent = tag.getBoolean("ForceFlag"); + if (tag.contains("PrevTrainName")) + lastDisassembledTrainName = Component.Serializer.fromJson(tag.getString("PrevTrainName")); + + if (!clientPacket) + return; + if (!tag.contains("ImminentTrain")) { + imminentTrain = null; + trainPresent = false; + trainCanDisassemble = false; + trainBackwards = false; + return; + } + + imminentTrain = tag.getUUID("ImminentTrain"); + trainPresent = tag.contains("TrainPresent"); + trainCanDisassemble = tag.contains("TrainCanDisassemble"); + trainBackwards = tag.contains("TrainBackwards"); + trainHasSchedule = tag.contains("TrainHasSchedule"); + trainHasAutoSchedule = tag.contains("TrainHasAutoSchedule"); + } + + @Override + protected void write(CompoundTag tag, boolean clientPacket) { + AssemblyException.write(tag, lastException); + tag.putInt("FailedCarriageIndex", failedCarriageIndex); + + if (lastDisassembledTrainName != null) + tag.putString("PrevTrainName", Component.Serializer.toJson(lastDisassembledTrainName)); + + super.write(tag, clientPacket); + + if (!clientPacket) + return; + if (imminentTrain == null) + return; + + tag.putUUID("ImminentTrain", imminentTrain); + + if (trainPresent) + NBTHelper.putMarker(tag, "TrainPresent"); + if (trainCanDisassemble) + NBTHelper.putMarker(tag, "TrainCanDisassemble"); + if (trainBackwards) + NBTHelper.putMarker(tag, "TrainBackwards"); + if (trainHasSchedule) + NBTHelper.putMarker(tag, "TrainHasSchedule"); + if (trainHasAutoSchedule) + NBTHelper.putMarker(tag, "TrainHasAutoSchedule"); + } + + @Nullable + public GlobalStation getStation() { + return edgePoint.getEdgePoint(); + } + + // Train Assembly + + public static WorldAttached> assemblyAreas = new WorldAttached<>(w -> new HashMap<>()); + + Direction assemblyDirection; + int assemblyLength; + int[] bogeyLocations; + AbstractBogeyBlock[] bogeyTypes; + boolean[] upsideDownBogeys; + int bogeyCount; + + @Override + public void lazyTick() { + if (isAssembling() && !level.isClientSide) + refreshAssemblyInfo(); + super.lazyTick(); + } + + @Override + public void tick() { + if (isAssembling() && level.isClientSide) + refreshAssemblyInfo(); + super.tick(); + + if (level.isClientSide) { + float currentTarget = flag.getChaseTarget(); + if (currentTarget == 0 || flag.settled()) { + int target = trainPresent || isAssembling() ? 1 : 0; + if (target != currentTarget) { + flag.chase(target, 0.1f, Chaser.LINEAR); + if (target == 1) + AllSoundEvents.CONTRAPTION_ASSEMBLE.playAt(level, worldPosition, 1, 2, true); + } + } + boolean settled = flag.getValue() > .15f; + flag.tickChaser(); + if (currentTarget == 0 && settled != flag.getValue() > .15f) + AllSoundEvents.CONTRAPTION_DISASSEMBLE.playAt(level, worldPosition, 0.75f, 1.5f, true); + return; + } + + GlobalStation station = getStation(); + if (station == null) + return; + + Train imminentTrain = station.getImminentTrain(); + boolean trainPresent = imminentTrain != null && imminentTrain.getCurrentStation() == station; + boolean canDisassemble = trainPresent && imminentTrain.canDisassemble(); + UUID imminentID = imminentTrain != null ? imminentTrain.id : null; + boolean trainHasSchedule = trainPresent && imminentTrain.runtime.getSchedule() != null; + boolean trainHasAutoSchedule = trainHasSchedule && imminentTrain.runtime.isAutoSchedule; + boolean newlyArrived = this.trainPresent != trainPresent; + + if (trainPresent && imminentTrain.runtime.displayLinkUpdateRequested) { + DisplayLinkBlock.notifyGatherers(level, worldPosition); + imminentTrain.runtime.displayLinkUpdateRequested = false; + } + + if (newlyArrived) + applyAutoSchedule(); + + if (newlyArrived || this.trainCanDisassemble != canDisassemble + || !Objects.equals(imminentID, this.imminentTrain) || this.trainHasSchedule != trainHasSchedule + || this.trainHasAutoSchedule != trainHasAutoSchedule) { + + this.imminentTrain = imminentID; + this.trainPresent = trainPresent; + this.trainCanDisassemble = canDisassemble; + this.trainBackwards = imminentTrain != null && imminentTrain.currentlyBackwards; + this.trainHasSchedule = trainHasSchedule; + this.trainHasAutoSchedule = trainHasAutoSchedule; + + notifyUpdate(); + } + } + + public boolean trackClicked(Player player, InteractionHand hand, ITrackBlock track, BlockState state, + BlockPos pos) { + refreshAssemblyInfo(); + BoundingBox bb = assemblyAreas.get(level) + .get(worldPosition); + if (bb == null || !bb.isInside(pos)) + return false; + + BlockPos up = new BlockPos(track.getUpNormal(level, pos, state)); + BlockPos down = new BlockPos(track.getUpNormal(level, pos, state).scale(-1)); + int bogeyOffset = pos.distManhattan(edgePoint.getGlobalPosition()) - 1; + + if (!isValidBogeyOffset(bogeyOffset)) { + for (boolean upsideDown : Iterate.falseAndTrue) { + for (int i = -1; i <= 1; i++) { + BlockPos bogeyPos = pos.relative(assemblyDirection, i) + .offset(upsideDown ? down : up); + BlockState blockState = level.getBlockState(bogeyPos); + if (!(blockState.getBlock() instanceof AbstractBogeyBlock bogey)) + continue; + BlockEntity be = level.getBlockEntity(bogeyPos); + if (!(be instanceof AbstractBogeyBlockEntity oldBE)) + continue; + CompoundTag oldData = oldBE.getBogeyData(); + BlockState newBlock = bogey.getNextSize(oldBE); + if (newBlock.getBlock() == bogey) + player.displayClientMessage(Lang.translateDirect("bogey.style.no_other_sizes") + .withStyle(ChatFormatting.RED), true); + level.setBlock(bogeyPos, newBlock, 3); + BlockEntity newEntity = level.getBlockEntity(bogeyPos); + if (!(newEntity instanceof AbstractBogeyBlockEntity newBE)) + continue; + newBE.setBogeyData(oldData); + bogey.playRotateSound(level, bogeyPos); + return true; + } + } + + return false; + } + + ItemStack handItem = player.getItemInHand(hand); + if (!player.isCreative() && !AllBlocks.RAILWAY_CASING.isIn(handItem)) { + player.displayClientMessage(Lang.translateDirect("train_assembly.requires_casing"), true); + return false; + } + + boolean upsideDown = (player.getViewXRot(1.0F) < 0 && (track.getBogeyAnchor(level, pos, state)).getBlock() instanceof AbstractBogeyBlock bogey && bogey.canBeUpsideDown()); + + BlockPos targetPos = upsideDown ? pos.offset(down) : pos.offset(up); + if (level.getBlockState(targetPos) + .getDestroySpeed(level, targetPos) == -1) { + return false; + } + + level.destroyBlock(targetPos, true); + + BlockState bogeyAnchor = track.getBogeyAnchor(level, pos, state); + if (bogeyAnchor.getBlock() instanceof AbstractBogeyBlock bogey) { + bogeyAnchor = bogey.getVersion(bogeyAnchor, upsideDown); + } + bogeyAnchor = ProperWaterloggedBlock.withWater(level, bogeyAnchor, pos); + level.setBlock(targetPos, bogeyAnchor, 3); + player.displayClientMessage(Lang.translateDirect("train_assembly.bogey_created"), true); + SoundType soundtype = bogeyAnchor.getBlock() + .getSoundType(state, level, pos, player); + level.playSound(null, pos, soundtype.getPlaceSound(), SoundSource.BLOCKS, (soundtype.getVolume() + 1.0F) / 2.0F, + soundtype.getPitch() * 0.8F); + + if (!player.isCreative()) { + ItemStack itemInHand = player.getItemInHand(hand); + itemInHand.shrink(1); + if (itemInHand.isEmpty()) + player.setItemInHand(hand, ItemStack.EMPTY); + } + + return true; + } + + public boolean enterAssemblyMode(@Nullable ServerPlayer sender) { + if (isAssembling()) + return false; + + tryDisassembleTrain(sender); + if (!tryEnterAssemblyMode()) + return false; + + BlockState newState = getBlockState().setValue(StationBlock.ASSEMBLING, true); + level.setBlock(getBlockPos(), newState, 3); + refreshBlockState(); + refreshAssemblyInfo(); + + updateStationState(station -> station.assembling = true); + GlobalStation station = getStation(); + if (station != null) { + for (Train train : Create.RAILWAYS.sided(level).trains.values()) { + if (train.navigation.destination != station) + continue; + + GlobalStation preferredDestination = train.runtime.startCurrentInstruction(); + train.navigation.startNavigation(preferredDestination != null ? preferredDestination : station, Double.MAX_VALUE, false); + } + } + + return true; + } + + public boolean exitAssemblyMode() { + if (!isAssembling()) + return false; + + cancelAssembly(); + BlockState newState = getBlockState().setValue(StationBlock.ASSEMBLING, false); + level.setBlock(getBlockPos(), newState, 3); + refreshBlockState(); + + return updateStationState(station -> station.assembling = false); + } + + public boolean tryDisassembleTrain(@Nullable ServerPlayer sender) { + GlobalStation station = getStation(); + if (station == null) + return false; + + Train train = station.getPresentTrain(); + if (train == null) + return false; + + BlockPos trackPosition = edgePoint.getGlobalPosition(); + if (!train.disassemble(getAssemblyDirection(), trackPosition.above())) + return false; + + dropSchedule(sender); + return true; + } + + public boolean isAssembling() { + BlockState state = getBlockState(); + return state.hasProperty(StationBlock.ASSEMBLING) && state.getValue(StationBlock.ASSEMBLING); + } + + public boolean tryEnterAssemblyMode() { + if (!edgePoint.hasValidTrack()) + return false; + + BlockPos targetPosition = edgePoint.getGlobalPosition(); + BlockState trackState = edgePoint.getTrackBlockState(); + ITrackBlock track = edgePoint.getTrack(); + Vec3 trackAxis = track.getTrackAxes(level, targetPosition, trackState) + .get(0); + + boolean axisFound = false; + for (Axis axis : Iterate.axes) { + if (trackAxis.get(axis) == 0) + continue; + if (axisFound) + return false; + axisFound = true; + } + + return true; + } + + public void dropSchedule(@Nullable ServerPlayer sender) { + GlobalStation station = getStation(); + if (station == null) + return; + + Train train = station.getPresentTrain(); + if (train == null) + return; + + ItemStack schedule = train.runtime.returnSchedule(); + if (schedule.isEmpty()) + return; + if (sender != null && sender.getMainHandItem().isEmpty()) { + sender.getInventory() + .placeItemBackInInventory(schedule); + return; + } + + Vec3 v = VecHelper.getCenterOf(getBlockPos()); + ItemEntity itemEntity = new ItemEntity(getLevel(), v.x, v.y, v.z, schedule); + itemEntity.setDeltaMovement(Vec3.ZERO); + getLevel().addFreshEntity(itemEntity); + } + + private boolean updateStationState(Consumer updateState) { + GlobalStation station = getStation(); + TrackGraphLocation graphLocation = edgePoint.determineGraphLocation(); + if (station == null || graphLocation == null) + return false; + + updateState.accept(station); + Create.RAILWAYS.sync.pointAdded(graphLocation.graph, station); + Create.RAILWAYS.markTracksDirty(); + return true; + } + + public void refreshAssemblyInfo() { + if (!edgePoint.hasValidTrack()) + return; + + if (!isVirtual()) { + GlobalStation station = getStation(); + if (station == null || station.getPresentTrain() != null) + return; + } + + int prevLength = assemblyLength; + BlockPos targetPosition = edgePoint.getGlobalPosition(); + BlockState trackState = edgePoint.getTrackBlockState(); + ITrackBlock track = edgePoint.getTrack(); + getAssemblyDirection(); + + MutableBlockPos currentPos = targetPosition.mutable(); + currentPos.move(assemblyDirection); + + BlockPos bogeyOffset = new BlockPos(track.getUpNormal(level, targetPosition, trackState)); + + int MAX_LENGTH = AllConfigs.server().trains.maxAssemblyLength.get(); + int MAX_BOGEY_COUNT = AllConfigs.server().trains.maxBogeyCount.get(); + + int bogeyIndex = 0; + int maxBogeyCount = MAX_BOGEY_COUNT; + if (bogeyLocations == null) + bogeyLocations = new int[maxBogeyCount]; + if (bogeyTypes == null) + bogeyTypes = new AbstractBogeyBlock[maxBogeyCount]; + if (upsideDownBogeys == null) + upsideDownBogeys = new boolean[maxBogeyCount]; + Arrays.fill(bogeyLocations, -1); + Arrays.fill(bogeyTypes, null); + Arrays.fill(upsideDownBogeys, false); + + for (int i = 0; i < MAX_LENGTH; i++) { + if (i == MAX_LENGTH - 1) { + assemblyLength = i; + break; + } + if (!track.trackEquals(trackState, level.getBlockState(currentPos))) { + assemblyLength = Math.max(0, i - 1); + break; + } + + BlockState potentialBogeyState = level.getBlockState(bogeyOffset.offset(currentPos)); + BlockPos upsideDownBogeyOffset = new BlockPos(bogeyOffset.getX(), bogeyOffset.getY()*-1, bogeyOffset.getZ()); + if (bogeyIndex < bogeyLocations.length) { + if (potentialBogeyState.getBlock() instanceof AbstractBogeyBlock bogey && !bogey.isUpsideDown(potentialBogeyState)) { + bogeyTypes[bogeyIndex] = bogey; + bogeyLocations[bogeyIndex] = i; + upsideDownBogeys[bogeyIndex] = false; + bogeyIndex++; + } else if ((potentialBogeyState = level.getBlockState(upsideDownBogeyOffset.offset(currentPos))).getBlock() instanceof AbstractBogeyBlock bogey && bogey.isUpsideDown(potentialBogeyState)) { + bogeyTypes[bogeyIndex] = bogey; + bogeyLocations[bogeyIndex] = i; + upsideDownBogeys[bogeyIndex] = true; + bogeyIndex++; + } + } + + currentPos.move(assemblyDirection); + } + + bogeyCount = bogeyIndex; + + if (level.isClientSide) + return; + if (prevLength == assemblyLength) + return; + if (isVirtual()) + return; + + Map map = assemblyAreas.get(level); + BlockPos startPosition = targetPosition.relative(assemblyDirection); + BlockPos trackEnd = startPosition.relative(assemblyDirection, assemblyLength - 1); + map.put(worldPosition, BoundingBox.fromCorners(startPosition, trackEnd)); + } + + public boolean updateName(String name) { + if (!updateStationState(station -> station.name = name)) + return false; + notifyUpdate(); + + return true; + } + + public boolean isValidBogeyOffset(int i) { + if ((i < 3 || bogeyCount == 0) && i != 0) + return false; + for (int j : bogeyLocations) { + if (j == -1) + break; + if (i >= j - 2 && i <= j + 2) + return false; + } + return true; + } + + public Direction getAssemblyDirection() { + if (assemblyDirection != null) + return assemblyDirection; + if (!edgePoint.hasValidTrack()) + return null; + BlockPos targetPosition = edgePoint.getGlobalPosition(); + BlockState trackState = edgePoint.getTrackBlockState(); + ITrackBlock track = edgePoint.getTrack(); + AxisDirection axisDirection = edgePoint.getTargetDirection(); + Vec3 axis = track.getTrackAxes(level, targetPosition, trackState) + .get(0) + .normalize() + .scale(axisDirection.getStep()); + return assemblyDirection = Direction.getNearest(axis.x, axis.y, axis.z); + } + + @Override + public void remove() { + assemblyAreas.get(level) + .remove(worldPosition); + super.remove(); + } + + public void assemble(UUID playerUUID) { + refreshAssemblyInfo(); + + if (bogeyLocations == null) + return; + + if (bogeyLocations[0] != 0) { + exception(new AssemblyException(Lang.translateDirect("train_assembly.frontmost_bogey_at_station")), -1); + return; + } + + if (!edgePoint.hasValidTrack()) + return; + + BlockPos trackPosition = edgePoint.getGlobalPosition(); + BlockState trackState = edgePoint.getTrackBlockState(); + ITrackBlock track = edgePoint.getTrack(); + BlockPos bogeyOffset = new BlockPos(track.getUpNormal(level, trackPosition, trackState)); + + TrackNodeLocation location = null; + Vec3 centre = Vec3.atBottomCenterOf(trackPosition) + .add(0, track.getElevationAtCenter(level, trackPosition, trackState), 0); + Collection ends = track.getConnected(level, trackPosition, trackState, true, null); + Vec3 targetOffset = Vec3.atLowerCornerOf(assemblyDirection.getNormal()); + for (DiscoveredLocation end : ends) + if (Mth.equal(0, targetOffset.distanceToSqr(end.getLocation() + .subtract(centre) + .normalize()))) + location = end; + if (location == null) + return; + + List pointOffsets = new ArrayList<>(); + int iPrevious = -100; + for (int i = 0; i < bogeyLocations.length; i++) { + int loc = bogeyLocations[i]; + if (loc == -1) + break; + + if (loc - iPrevious < 3) { + exception(new AssemblyException(Lang.translateDirect("train_assembly.bogeys_too_close", i, i + 1)), -1); + return; + } + + double bogeySize = bogeyTypes[i].getWheelPointSpacing(); + pointOffsets.add(Double.valueOf(loc + .5 - bogeySize / 2)); + pointOffsets.add(Double.valueOf(loc + .5 + bogeySize / 2)); + iPrevious = loc; + } + + List points = new ArrayList<>(); + Vec3 directionVec = Vec3.atLowerCornerOf(assemblyDirection.getNormal()); + TrackGraph graph = null; + TrackNode secondNode = null; + + for (int j = 0; j < assemblyLength * 2 + 40; j++) { + double i = j / 2d; + if (points.size() == pointOffsets.size()) + break; + + TrackNodeLocation currentLocation = location; + location = new TrackNodeLocation(location.getLocation() + .add(directionVec.scale(.5))).in(location.dimension); + + if (graph == null) + graph = Create.RAILWAYS.getGraph(level, currentLocation); + if (graph == null) + continue; + TrackNode node = graph.locateNode(currentLocation); + if (node == null) + continue; + + for (int pointIndex = points.size(); pointIndex < pointOffsets.size(); pointIndex++) { + double offset = pointOffsets.get(pointIndex); + if (offset > i) + break; + double positionOnEdge = i - offset; + + Map connectionsFromNode = graph.getConnectionsFrom(node); + + if (secondNode == null) + for (Entry entry : connectionsFromNode.entrySet()) { + TrackEdge edge = entry.getValue(); + TrackNode otherNode = entry.getKey(); + if (edge.isTurn()) + continue; + Vec3 edgeDirection = edge.getDirection(true); + if (Mth.equal(edgeDirection.normalize() + .dot(directionVec), -1d)) + secondNode = otherNode; + } + + if (secondNode == null) { + Create.LOGGER.warn("Cannot assemble: No valid starting node found"); + return; + } + + TrackEdge edge = connectionsFromNode.get(secondNode); + + if (edge == null) { + Create.LOGGER.warn("Cannot assemble: Missing graph edge"); + return; + } + + points.add(new TravellingPoint(node, secondNode, edge, positionOnEdge, false)); + } + + secondNode = node; + } + + if (points.size() != pointOffsets.size()) { + Create.LOGGER.warn("Cannot assemble: Not all Points created"); + return; + } + + if (points.size() == 0) { + exception(new AssemblyException(Lang.translateDirect("train_assembly.no_bogeys")), -1); + return; + } + + List contraptions = new ArrayList<>(); + List carriages = new ArrayList<>(); + List spacing = new ArrayList<>(); + boolean atLeastOneForwardControls = false; + + for (int bogeyIndex = 0; bogeyIndex < bogeyCount; bogeyIndex++) { + int pointIndex = bogeyIndex * 2; + if (bogeyIndex > 0) + spacing.add(bogeyLocations[bogeyIndex] - bogeyLocations[bogeyIndex - 1]); + CarriageContraption contraption = new CarriageContraption(assemblyDirection); + BlockPos bogeyPosOffset = trackPosition.offset(bogeyOffset); + BlockPos upsideDownBogeyPosOffset = trackPosition.offset(new BlockPos(bogeyOffset.getX(), bogeyOffset.getY() * -1, bogeyOffset.getZ())); + + try { + int offset = bogeyLocations[bogeyIndex] + 1; + boolean success = contraption.assemble(level, upsideDownBogeys[bogeyIndex] ? upsideDownBogeyPosOffset.relative(assemblyDirection, offset) : bogeyPosOffset.relative(assemblyDirection, offset)); + atLeastOneForwardControls |= contraption.hasForwardControls(); + contraption.setSoundQueueOffset(offset); + if (!success) { + exception(new AssemblyException(Lang.translateDirect("train_assembly.nothing_attached", bogeyIndex + 1)), + -1); + return; + } + } catch (AssemblyException e) { + exception(e, contraptions.size() + 1); + return; + } + + AbstractBogeyBlock typeOfFirstBogey = bogeyTypes[bogeyIndex]; + boolean firstBogeyIsUpsideDown = upsideDownBogeys[bogeyIndex]; + BlockPos firstBogeyPos = contraption.anchor; + AbstractBogeyBlockEntity firstBogeyBlockEntity = (AbstractBogeyBlockEntity) level.getBlockEntity(firstBogeyPos); + CarriageBogey firstBogey = + new CarriageBogey(typeOfFirstBogey, firstBogeyIsUpsideDown, firstBogeyBlockEntity.getBogeyData(), points.get(pointIndex), points.get(pointIndex + 1)); + CarriageBogey secondBogey = null; + BlockPos secondBogeyPos = contraption.getSecondBogeyPos(); + int bogeySpacing = 0; + + if (secondBogeyPos != null) { + if (bogeyIndex == bogeyCount - 1 || !secondBogeyPos + .equals((upsideDownBogeys[bogeyIndex + 1] ? upsideDownBogeyPosOffset : bogeyPosOffset).relative(assemblyDirection, bogeyLocations[bogeyIndex + 1] + 1))) { + exception(new AssemblyException(Lang.translateDirect("train_assembly.not_connected_in_order")), + contraptions.size() + 1); + return; + } + AbstractBogeyBlockEntity secondBogeyBlockEntity = + (AbstractBogeyBlockEntity) level.getBlockEntity(secondBogeyPos); + bogeySpacing = bogeyLocations[bogeyIndex + 1] - bogeyLocations[bogeyIndex]; + secondBogey = new CarriageBogey(bogeyTypes[bogeyIndex + 1], upsideDownBogeys[bogeyIndex + 1], secondBogeyBlockEntity.getBogeyData(), + points.get(pointIndex + 2), points.get(pointIndex + 3)); + bogeyIndex++; + + } else if (!typeOfFirstBogey.allowsSingleBogeyCarriage()) { + exception(new AssemblyException(Lang.translateDirect("train_assembly.single_bogey_carriage")), + contraptions.size() + 1); + return; + } + + contraptions.add(contraption); + carriages.add(new Carriage(firstBogey, secondBogey, bogeySpacing)); + } + + if (!atLeastOneForwardControls) { + exception(new AssemblyException(Lang.translateDirect("train_assembly.no_controls")), -1); + return; + } + + for (CarriageContraption contraption : contraptions) { + contraption.removeBlocksFromWorld(level, BlockPos.ZERO); + contraption.expandBoundsAroundAxis(Axis.Y); + } + + Train train = new Train(UUID.randomUUID(), playerUUID, graph, carriages, spacing, contraptions.stream() + .anyMatch(CarriageContraption::hasBackwardControls)); + + if (lastDisassembledTrainName != null) { + train.name = lastDisassembledTrainName; + lastDisassembledTrainName = null; + } + + for (int i = 0; i < contraptions.size(); i++) { + CarriageContraption contraption = contraptions.get(i); + Carriage carriage = carriages.get(i); + carriage.setContraption(level, contraption); + if (contraption.containsBlockBreakers()) + award(AllAdvancements.CONTRAPTION_ACTORS); + } + + GlobalStation station = getStation(); + if (station != null) { + train.setCurrentStation(station); + station.reserveFor(train); + } + + train.collectInitiallyOccupiedSignalBlocks(); + Create.RAILWAYS.addTrain(train); + AllPackets.getChannel().send(PacketDistributor.ALL.noArg(), new TrainPacket(train, true)); + clearException(); + + award(AllAdvancements.TRAIN); + if (contraptions.size() >= 6) + award(AllAdvancements.LONG_TRAIN); + } + + public void cancelAssembly() { + assemblyLength = 0; + assemblyAreas.get(level) + .remove(worldPosition); + clearException(); + } + + private void clearException() { + exception(null, -1); + } + + private void exception(AssemblyException exception, int carriage) { + failedCarriageIndex = carriage; + lastException = exception; + sendData(); + } + + @Override + @OnlyIn(Dist.CLIENT) + public AABB getRenderBoundingBox() { + if (isAssembling()) + return INFINITE_EXTENT_AABB; + return super.getRenderBoundingBox(); + } + + @Override + protected AABB createRenderBoundingBox() { + return new AABB(worldPosition, edgePoint.getGlobalPosition()).inflate(2); + } + + public ItemStack getAutoSchedule() { + return depotBehaviour.getHeldItemStack(); + } + + @Override + public @NotNull LazyOptional getCapability(@NotNull Capability cap, Direction side) { + if (isItemHandlerCap(cap)) + return depotBehaviour.getItemCapability(cap, side); + if (computerBehaviour.isPeripheralCap(cap)) + return computerBehaviour.getPeripheralCapability(); + return super.getCapability(cap, side); + } + + @Override + public void invalidateCaps() { + super.invalidateCaps(); + computerBehaviour.removePeripheral(); + } + + private void applyAutoSchedule() { + ItemStack stack = getAutoSchedule(); + if (!AllItems.SCHEDULE.isIn(stack)) + return; + Schedule schedule = ScheduleItem.getSchedule(stack); + if (schedule == null || schedule.entries.isEmpty()) + return; + GlobalStation station = getStation(); + if (station == null) + return; + Train imminentTrain = station.getImminentTrain(); + if (imminentTrain == null || imminentTrain.getCurrentStation() != station) + return; + + award(AllAdvancements.CONDUCTOR); + imminentTrain.runtime.setSchedule(schedule, true); + AllSoundEvents.CONFIRM.playOnServer(level, worldPosition, 1, 1); + + if (!(level instanceof ServerLevel server)) + return; + + Vec3 v = Vec3.atBottomCenterOf(worldPosition.above()); + server.sendParticles(ParticleTypes.HAPPY_VILLAGER, v.x, v.y, v.z, 8, 0.35, 0.05, 0.35, 1); + server.sendParticles(ParticleTypes.END_ROD, v.x, v.y + .25f, v.z, 10, 0.05, 1, 0.05, 0.005f); + } + + public boolean resolveFlagAngle() { + if (flagYRot != -1) + return true; + + BlockState target = edgePoint.getTrackBlockState(); + if (!(target.getBlock() instanceof ITrackBlock def)) + return false; + + Vec3 axis = null; + BlockPos trackPos = edgePoint.getGlobalPosition(); + for (Vec3 vec3 : def.getTrackAxes(level, trackPos, target)) + axis = vec3.scale(edgePoint.getTargetDirection() + .getStep()); + if (axis == null) + return false; + + Direction nearest = Direction.getNearest(axis.x, 0, axis.z); + flagYRot = (int) (-nearest.toYRot() - 90); + + Vec3 diff = Vec3.atLowerCornerOf(trackPos.subtract(worldPosition)) + .multiply(1, 0, 1); + if (diff.lengthSqr() == 0) + return true; + + flagFlipped = diff.dot(Vec3.atLowerCornerOf(nearest.getClockWise() + .getNormal())) > 0; + + return true; + } + + @Override + public void transform(StructureTransform transform) { + edgePoint.transform(transform); + } + +} diff --git a/src/main/java/com/simibubi/create/content/trains/station/StationEditPacket.java b/src/main/java/com/simibubi/create/content/trains/station/StationEditPacket.java new file mode 100644 index 000000000..ca13624f9 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/station/StationEditPacket.java @@ -0,0 +1,137 @@ +package com.simibubi.create.content.trains.station; + +import com.simibubi.create.content.decoration.slidingDoor.DoorControl; +import com.simibubi.create.foundation.networking.BlockEntityConfigurationPacket; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.util.Mth; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; + +public class StationEditPacket extends BlockEntityConfigurationPacket { + + boolean dropSchedule; + boolean assemblyMode; + Boolean tryAssemble; + DoorControl doorControl; + String name; + + public static StationEditPacket dropSchedule(BlockPos pos) { + StationEditPacket packet = new StationEditPacket(pos); + packet.dropSchedule = true; + return packet; + } + + public static StationEditPacket tryAssemble(BlockPos pos) { + StationEditPacket packet = new StationEditPacket(pos); + packet.tryAssemble = true; + return packet; + } + + public static StationEditPacket tryDisassemble(BlockPos pos) { + StationEditPacket packet = new StationEditPacket(pos); + packet.tryAssemble = false; + return packet; + } + + public static StationEditPacket configure(BlockPos pos, boolean assemble, String name, DoorControl doorControl) { + StationEditPacket packet = new StationEditPacket(pos); + packet.assemblyMode = assemble; + packet.tryAssemble = null; + packet.name = name; + packet.doorControl = doorControl; + return packet; + } + + public StationEditPacket(FriendlyByteBuf buffer) { + super(buffer); + } + + public StationEditPacket(BlockPos pos) { + super(pos); + } + + @Override + protected void writeSettings(FriendlyByteBuf buffer) { + buffer.writeBoolean(dropSchedule); + if (dropSchedule) + return; + buffer.writeBoolean(doorControl != null); + if (doorControl != null) + buffer.writeVarInt(doorControl.ordinal()); + buffer.writeBoolean(tryAssemble != null); + if (tryAssemble != null) { + buffer.writeBoolean(tryAssemble); + return; + } + buffer.writeBoolean(assemblyMode); + buffer.writeUtf(name); + } + + @Override + protected void readSettings(FriendlyByteBuf buffer) { + if (buffer.readBoolean()) { + dropSchedule = true; + return; + } + if (buffer.readBoolean()) + doorControl = DoorControl.values()[Mth.clamp(buffer.readVarInt(), 0, DoorControl.values().length)]; + name = ""; + if (buffer.readBoolean()) { + tryAssemble = buffer.readBoolean(); + return; + } + assemblyMode = buffer.readBoolean(); + name = buffer.readUtf(256); + } + + @Override + protected void applySettings(ServerPlayer player, StationBlockEntity be) { + Level level = be.getLevel(); + BlockPos blockPos = be.getBlockPos(); + BlockState blockState = level.getBlockState(blockPos); + + if (dropSchedule) { + be.dropSchedule(player); + return; + } + + if (doorControl != null) + be.doorControls.set(doorControl); + + if (!name.isBlank()) + be.updateName(name); + + if (!(blockState.getBlock() instanceof StationBlock)) + return; + + Boolean isAssemblyMode = blockState.getValue(StationBlock.ASSEMBLING); + boolean assemblyComplete = false; + + if (tryAssemble != null) { + if (!isAssemblyMode) + return; + if (tryAssemble) { + be.assemble(player.getUUID()); + assemblyComplete = be.getStation() != null && be.getStation() + .getPresentTrain() != null; + } else { + if (be.tryDisassembleTrain(player) && be.tryEnterAssemblyMode()) + be.refreshAssemblyInfo(); + } + if (!assemblyComplete) + return; + } + + if (assemblyMode) + be.enterAssemblyMode(player); + else + be.exitAssemblyMode(); + } + + @Override + protected void applySettings(StationBlockEntity be) {} + +} diff --git a/src/main/java/com/simibubi/create/content/trains/station/StationMapData.java b/src/main/java/com/simibubi/create/content/trains/station/StationMapData.java new file mode 100644 index 000000000..308506ee8 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/station/StationMapData.java @@ -0,0 +1,12 @@ +package com.simibubi.create.content.trains.station; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.LevelAccessor; + +public interface StationMapData { + + boolean toggleStation(LevelAccessor level, BlockPos pos, StationBlockEntity stationBlockEntity); + + void addStationMarker(StationMarker marker); + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationMarker.java b/src/main/java/com/simibubi/create/content/trains/station/StationMarker.java similarity index 91% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationMarker.java rename to src/main/java/com/simibubi/create/content/trains/station/StationMarker.java index fa3357d9d..9e0bb91b0 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationMarker.java +++ b/src/main/java/com/simibubi/create/content/trains/station/StationMarker.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.management.edgePoint.station; +package com.simibubi.create.content.trains.station; import java.util.Objects; import java.util.Optional; @@ -7,11 +7,11 @@ import org.joml.Matrix4f; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; -import com.simibubi.create.AllTileEntities; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBehaviour; +import com.simibubi.create.content.trains.track.TrackTargetingBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.map.CustomRenderedMapDecoration; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.utility.Components; import net.minecraft.client.Minecraft; @@ -53,14 +53,14 @@ public class StationMarker { } public static StationMarker fromWorld(BlockGetter level, BlockPos pos) { - Optional stationOption = AllTileEntities.TRACK_STATION.get(level, pos); + Optional stationOption = AllBlockEntityTypes.TRACK_STATION.get(level, pos); if (stationOption.isEmpty() || stationOption.get().getStation() == null) return null; String name = stationOption.get() .getStation().name; - return new StationMarker(pos, TileEntityBehaviour.get(stationOption.get(), TrackTargetingBehaviour.TYPE) + return new StationMarker(pos, BlockEntityBehaviour.get(stationOption.get(), TrackTargetingBehaviour.TYPE) .getPositionForMapMarker(), Components.literal(name)); } diff --git a/src/main/java/com/simibubi/create/content/trains/station/StationRenderer.java b/src/main/java/com/simibubi/create/content/trains/station/StationRenderer.java new file mode 100644 index 000000000..c76a0d493 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/station/StationRenderer.java @@ -0,0 +1,154 @@ +package com.simibubi.create.content.trains.station; + +import com.jozufozu.flywheel.core.PartialModel; +import com.jozufozu.flywheel.util.transform.Transform; +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.logistics.depot.DepotRenderer; +import com.simibubi.create.content.trains.track.ITrackBlock; +import com.simibubi.create.content.trains.track.TrackTargetingBehaviour; +import com.simibubi.create.content.trains.track.TrackTargetingBehaviour.RenderedTrackOverlayType; +import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; +import com.simibubi.create.foundation.render.CachedBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; + +import net.minecraft.client.renderer.LevelRenderer; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockPos.MutableBlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; + +public class StationRenderer extends SafeBlockEntityRenderer { + + public StationRenderer(BlockEntityRendererProvider.Context context) {} + + @Override + protected void renderSafe(StationBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + + BlockPos pos = be.getBlockPos(); + TrackTargetingBehaviour target = be.edgePoint; + BlockPos targetPosition = target.getGlobalPosition(); + Level level = be.getLevel(); + + DepotRenderer.renderItemsOf(be, partialTicks, ms, buffer, light, overlay, be.depotBehaviour); + + BlockState trackState = level.getBlockState(targetPosition); + Block block = trackState.getBlock(); + if (!(block instanceof ITrackBlock)) + return; + + GlobalStation station = be.getStation(); + boolean isAssembling = be.getBlockState() + .getValue(StationBlock.ASSEMBLING); + + if (!isAssembling || (station == null || station.getPresentTrain() != null) && !be.isVirtual()) { + renderFlag( + be.flag.getValue(partialTicks) > 0.75f ? AllPartialModels.STATION_ON : AllPartialModels.STATION_OFF, be, + partialTicks, ms, buffer, light, overlay); + ms.pushPose(); + TransformStack.cast(ms) + .translate(targetPosition.subtract(pos)); + TrackTargetingBehaviour.render(level, targetPosition, target.getTargetDirection(), target.getTargetBezier(), + ms, buffer, light, overlay, RenderedTrackOverlayType.STATION, 1); + ms.popPose(); + return; + } + + renderFlag(AllPartialModels.STATION_ASSEMBLE, be, partialTicks, ms, buffer, light, overlay); + + ITrackBlock track = (ITrackBlock) block; + Direction direction = be.assemblyDirection; + + if (be.isVirtual() && be.bogeyLocations == null) + be.refreshAssemblyInfo(); + + if (direction == null || be.assemblyLength == 0 || be.bogeyLocations == null) + return; + + ms.pushPose(); + BlockPos offset = targetPosition.subtract(pos); + ms.translate(offset.getX(), offset.getY(), offset.getZ()); + + MutableBlockPos currentPos = targetPosition.mutable(); + + PartialModel assemblyOverlay = track.prepareAssemblyOverlay(level, targetPosition, trackState, direction, ms); + int colorWhenValid = 0x96B5FF; + int colorWhenCarriage = 0xCAFF96; + VertexConsumer vb = buffer.getBuffer(RenderType.cutoutMipped()); + + currentPos.move(direction, 1); + ms.translate(0, 0, 1); + + for (int i = 0; i < be.assemblyLength; i++) { + int valid = be.isValidBogeyOffset(i) ? colorWhenValid : -1; + + for (int j : be.bogeyLocations) + if (i == j) { + valid = colorWhenCarriage; + break; + } + + if (valid != -1) { + int lightColor = LevelRenderer.getLightColor(level, currentPos); + SuperByteBuffer sbb = CachedBufferer.partial(assemblyOverlay, trackState); + sbb.color(valid); + sbb.light(lightColor); + sbb.renderInto(ms, vb); + } + ms.translate(0, 0, 1); + currentPos.move(direction); + } + + ms.popPose(); + } + + public static void renderFlag(PartialModel flag, StationBlockEntity be, float partialTicks, PoseStack ms, + MultiBufferSource buffer, int light, int overlay) { + if (!be.resolveFlagAngle()) + return; + SuperByteBuffer flagBB = CachedBufferer.partial(flag, be.getBlockState()); + transformFlag(flagBB, be, partialTicks, be.flagYRot, be.flagFlipped); + flagBB.translate(0.5f / 16, 0, 0) + .rotateY(be.flagFlipped ? 0 : 180) + .translate(-0.5f / 16, 0, 0) + .light(light) + .renderInto(ms, buffer.getBuffer(RenderType.cutoutMipped())); + } + + public static void transformFlag(Transform flag, StationBlockEntity be, float partialTicks, int yRot, + boolean flipped) { + float value = be.flag.getValue(partialTicks); + float progress = (float) (Math.pow(Math.min(value * 5, 1), 2)); + if (be.flag.getChaseTarget() > 0 && !be.flag.settled() && progress == 1) { + float wiggleProgress = (value - .2f) / .8f; + progress += (Math.sin(wiggleProgress * (2 * Mth.PI) * 4) / 8f) / Math.max(1, 8f * wiggleProgress); + } + + float nudge = 1 / 512f; + flag.centre() + .rotateY(yRot) + .translate(nudge, 9.5f / 16f, flipped ? 14f / 16f - nudge : 2f / 16f + nudge) + .unCentre() + .rotateX((flipped ? 1 : -1) * (progress * 90 + 270)); + } + + @Override + public boolean shouldRenderOffScreen(StationBlockEntity pBlockEntity) { + return true; + } + + @Override + public int getViewDistance() { + return 96 * 2; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationScreen.java b/src/main/java/com/simibubi/create/content/trains/station/StationScreen.java similarity index 77% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationScreen.java rename to src/main/java/com/simibubi/create/content/trains/station/StationScreen.java index 5d3fb0f8d..212ae6c9b 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/StationScreen.java +++ b/src/main/java/com/simibubi/create/content/trains/station/StationScreen.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.management.edgePoint.station; +package com.simibubi.create.content.trains.station; import java.lang.ref.WeakReference; import java.util.List; @@ -8,17 +8,22 @@ import com.jozufozu.flywheel.core.PartialModel; import com.mojang.blaze3d.platform.InputConstants; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.logistics.trains.entity.Carriage; -import com.simibubi.create.content.logistics.trains.entity.Train; -import com.simibubi.create.content.logistics.trains.entity.TrainIconType; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPackets; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.decoration.slidingDoor.DoorControl; +import com.simibubi.create.content.trains.entity.Carriage; +import com.simibubi.create.content.trains.entity.Train; +import com.simibubi.create.content.trains.entity.TrainIconType; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.gui.UIRenderHelper; import com.simibubi.create.foundation.gui.widget.IconButton; -import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.foundation.gui.widget.Label; +import com.simibubi.create.foundation.gui.widget.ScrollInput; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.Pair; import com.simibubi.create.foundation.utility.animation.LerpedFloat; import net.minecraft.ChatFormatting; @@ -37,16 +42,18 @@ public class StationScreen extends AbstractStationScreen { private int leavingAnimation; private LerpedFloat trainPosition; + private DoorControl doorControl; private boolean switchingToAssemblyMode; - public StationScreen(StationTileEntity te, GlobalStation station) { - super(te, station); + public StationScreen(StationBlockEntity be, GlobalStation station) { + super(be, station); background = AllGuiTextures.STATION; leavingAnimation = 0; trainPosition = LerpedFloat.linear() .startWithValue(0); switchingToAssemblyMode = false; + doorControl = be.doorControls.mode; } @Override @@ -62,7 +69,7 @@ public class StationScreen extends AbstractStationScreen { Components.literal(station.name)); nameBox.setBordered(false); nameBox.setMaxLength(25); - nameBox.setTextColor(0x442000); + nameBox.setTextColor(0x592424); nameBox.setValue(station.name); nameBox.changeFocus(false); nameBox.mouseClicked(0, 0, 0); @@ -72,7 +79,7 @@ public class StationScreen extends AbstractStationScreen { Runnable assemblyCallback = () -> { switchingToAssemblyMode = true; - minecraft.setScreen(new AssemblyScreen(te, station)); + minecraft.setScreen(new AssemblyScreen(blockEntity, station)); }; newTrainButton = new WideIconButton(x + 84, y + 65, AllGuiTextures.I_NEW_TRAIN); @@ -88,8 +95,8 @@ public class StationScreen extends AbstractStationScreen { dropScheduleButton = new IconButton(x + 73, y + 65, AllIcons.I_VIEW_SCHEDULE); dropScheduleButton.active = false; dropScheduleButton.visible = false; - dropScheduleButton - .withCallback(() -> AllPackets.channel.sendToServer(StationEditPacket.dropSchedule(te.getBlockPos()))); + dropScheduleButton.withCallback(() -> AllPackets.getChannel() + .sendToServer(StationEditPacket.dropSchedule(blockEntity.getBlockPos()))); addRenderableWidget(dropScheduleButton); onTextChanged = s -> trainNameBox.setX(nameBoxX(s, trainNameBox)); @@ -103,6 +110,11 @@ public class StationScreen extends AbstractStationScreen { trainNameBox.active = false; tickTrainDisplay(); + + Pair doorControlWidgets = + DoorControl.createWidget(x + 35, y + 102, mode -> doorControl = mode, doorControl); + addRenderableWidget(doorControlWidgets.getFirst()); + addRenderableWidget(doorControlWidgets.getSecond()); } @Override @@ -121,9 +133,9 @@ public class StationScreen extends AbstractStationScreen { super.tick(); - updateAssemblyTooltip(te.edgePoint.isOnCurve() ? "no_assembly_curve" - : !te.edgePoint.isOrthogonal() ? "no_assembly_diagonal" - : trainPresent() && !te.trainCanDisassemble ? "train_not_aligned" : null); + updateAssemblyTooltip(blockEntity.edgePoint.isOnCurve() ? "no_assembly_curve" + : !blockEntity.edgePoint.isOrthogonal() ? "no_assembly_diagonal" + : trainPresent() && !blockEntity.trainCanDisassemble ? "train_not_aligned" : null); } private void tickTrainDisplay() { @@ -136,7 +148,7 @@ public class StationScreen extends AbstractStationScreen { } leavingAnimation = 0; - newTrainButton.active = te.edgePoint.isOrthogonal(); + newTrainButton.active = blockEntity.edgePoint.isOrthogonal(); newTrainButton.visible = true; Train imminentTrain = getImminent(); @@ -146,7 +158,7 @@ public class StationScreen extends AbstractStationScreen { newTrainButton.visible = false; disassembleTrainButton.active = false; disassembleTrainButton.visible = true; - dropScheduleButton.active = te.trainHasSchedule; + dropScheduleButton.active = blockEntity.trainHasSchedule; dropScheduleButton.visible = true; trainNameBox.active = true; @@ -192,12 +204,13 @@ public class StationScreen extends AbstractStationScreen { } boolean trainAtStation = trainPresent(); - disassembleTrainButton.active = trainAtStation && te.trainCanDisassemble && te.edgePoint.isOrthogonal(); - dropScheduleButton.active = te.trainHasSchedule; + disassembleTrainButton.active = + trainAtStation && blockEntity.trainCanDisassemble && blockEntity.edgePoint.isOrthogonal(); + dropScheduleButton.active = blockEntity.trainHasSchedule; - if (te.trainHasSchedule) - dropScheduleButton.setToolTip( - Lang.translateDirect(te.trainHasAutoSchedule ? "station.remove_auto_schedule" : "station.remove_schedule")); + if (blockEntity.trainHasSchedule) + dropScheduleButton.setToolTip(Lang.translateDirect( + blockEntity.trainHasAutoSchedule ? "station.remove_auto_schedule" : "station.remove_schedule")); else dropScheduleButton.getToolTip() .clear(); @@ -237,6 +250,8 @@ public class StationScreen extends AbstractStationScreen { if (!nameBox.isFocused()) AllGuiTextures.STATION_EDIT_NAME.render(ms, nameBoxX(text, nameBox) + font.width(text) + 5, y + 1); + itemRenderer.renderGuiItem(AllBlocks.TRAIN_DOOR.asStack(), x + 14, y + 103); + Train train = displayedTrain.get(); if (train == null) { MutableComponent header = Lang.translateDirect("station.idle"); @@ -256,11 +271,7 @@ public class StationScreen extends AbstractStationScreen { for (int i = carriages.size() - 1; i > 0; i--) { RenderSystem.setShaderColor(1, 1, 1, Math.min(1f, Math.min((position + offset - 10) / 30f, (background.width - 40 - position - offset) / 30f))); -// if (i == carriages.size() - 1 && train.doubleEnded) { -// offset += icon.render(TrainIconType.FLIPPED_ENGINE, ms, x + offset, y + 20) + 1; -// continue; -// } - Carriage carriage = carriages.get(te.trainBackwards ? carriages.size() - i - 1 : i); + Carriage carriage = carriages.get(blockEntity.trainBackwards ? carriages.size() - i - 1 : i); offset += icon.render(carriage.bogeySpacing, ms, x + offset, y + 20) + 1; } @@ -272,8 +283,8 @@ public class StationScreen extends AbstractStationScreen { RenderSystem.setShaderColor(1, 1, 1, 1); - UIRenderHelper.drawStretched(ms, x + 21, y + 43, 150, 46, -100, AllGuiTextures.STATION_TEXTBOX_MIDDLE); AllGuiTextures.STATION_TEXTBOX_TOP.render(ms, x + 21, y + 42); + UIRenderHelper.drawStretched(ms, x + 21, y + 60, 150, 26, 0, AllGuiTextures.STATION_TEXTBOX_MIDDLE); AllGuiTextures.STATION_TEXTBOX_BOTTOM.render(ms, x + 21, y + 86); ms.pushPose(); @@ -333,32 +344,40 @@ public class StationScreen extends AbstractStationScreen { Train train = displayedTrain.get(); if (train != null && !trainNameBox.getValue() .equals(train.name.getString())) - AllPackets.channel.sendToServer(new TrainEditPacket(train.id, trainNameBox.getValue(), train.icon.getId())); + AllPackets.getChannel() + .sendToServer(new TrainEditPacket(train.id, trainNameBox.getValue(), train.icon.getId())); } private void syncStationName() { if (!nameBox.getValue() .equals(station.name)) - AllPackets.channel.sendToServer(StationEditPacket.configure(te.getBlockPos(), false, nameBox.getValue())); + AllPackets.getChannel() + .sendToServer( + StationEditPacket.configure(blockEntity.getBlockPos(), false, nameBox.getValue(), doorControl)); } @Override public void removed() { super.removed(); - AllPackets.channel - .sendToServer(StationEditPacket.configure(te.getBlockPos(), switchingToAssemblyMode, nameBox.getValue())); + if (nameBox == null || trainNameBox == null) + return; + AllPackets.getChannel() + .sendToServer(StationEditPacket.configure(blockEntity.getBlockPos(), switchingToAssemblyMode, + nameBox.getValue(), doorControl)); Train train = displayedTrain.get(); if (train == null) return; if (!switchingToAssemblyMode) - AllPackets.channel.sendToServer(new TrainEditPacket(train.id, trainNameBox.getValue(), train.icon.getId())); + AllPackets.getChannel() + .sendToServer(new TrainEditPacket(train.id, trainNameBox.getValue(), train.icon.getId())); else - te.imminentTrain = null; + blockEntity.imminentTrain = null; } @Override protected PartialModel getFlag(float partialTicks) { - return te.flag.getValue(partialTicks) > 0.75f ? AllBlockPartials.STATION_ON : AllBlockPartials.STATION_OFF; + return blockEntity.flag.getValue(partialTicks) > 0.75f ? AllPartialModels.STATION_ON + : AllPartialModels.STATION_OFF; } } diff --git a/src/main/java/com/simibubi/create/content/trains/station/TrainEditPacket.java b/src/main/java/com/simibubi/create/content/trains/station/TrainEditPacket.java new file mode 100644 index 000000000..41365547f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/station/TrainEditPacket.java @@ -0,0 +1,73 @@ +package com.simibubi.create.content.trains.station; + +import java.util.UUID; + +import com.simibubi.create.AllPackets; +import com.simibubi.create.Create; +import com.simibubi.create.content.trains.entity.Train; +import com.simibubi.create.content.trains.entity.TrainIconType; +import com.simibubi.create.foundation.networking.SimplePacketBase; +import com.simibubi.create.foundation.utility.Components; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.level.Level; +import net.minecraftforge.network.NetworkEvent.Context; +import net.minecraftforge.network.PacketDistributor; + +public class TrainEditPacket extends SimplePacketBase { + + private String name; + private UUID id; + private ResourceLocation iconType; + + public TrainEditPacket(UUID id, String name, ResourceLocation iconType) { + this.name = name; + this.id = id; + this.iconType = iconType; + } + + public TrainEditPacket(FriendlyByteBuf buffer) { + id = buffer.readUUID(); + name = buffer.readUtf(256); + iconType = buffer.readResourceLocation(); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeUUID(id); + buffer.writeUtf(name); + buffer.writeResourceLocation(iconType); + } + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> { + ServerPlayer sender = context.getSender(); + Level level = sender == null ? null : sender.level; + Train train = Create.RAILWAYS.sided(level).trains.get(id); + if (train == null) + return; + if (!name.isBlank()) + train.name = Components.literal(name); + train.icon = TrainIconType.byId(iconType); + if (sender != null) + AllPackets.getChannel().send(PacketDistributor.ALL.noArg(), new TrainEditReturnPacket(id, name, iconType)); + }); + return true; + } + + public static class TrainEditReturnPacket extends TrainEditPacket { + + public TrainEditReturnPacket(FriendlyByteBuf buffer) { + super(buffer); + } + + public TrainEditReturnPacket(UUID id, String name, ResourceLocation iconType) { + super(id, name, iconType); + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/WideIconButton.java b/src/main/java/com/simibubi/create/content/trains/station/WideIconButton.java similarity index 87% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/WideIconButton.java rename to src/main/java/com/simibubi/create/content/trains/station/WideIconButton.java index 5ef707600..2c424ce19 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/station/WideIconButton.java +++ b/src/main/java/com/simibubi/create/content/trains/station/WideIconButton.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.management.edgePoint.station; +package com.simibubi.create.content.trains.station; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.foundation.gui.AllGuiTextures; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/BezierConnection.java b/src/main/java/com/simibubi/create/content/trains/track/BezierConnection.java similarity index 85% rename from src/main/java/com/simibubi/create/content/logistics/trains/BezierConnection.java rename to src/main/java/com/simibubi/create/content/trains/track/BezierConnection.java index 5c543536d..8bce70138 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/BezierConnection.java +++ b/src/main/java/com/simibubi/create/content/trains/track/BezierConnection.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains; +package com.simibubi.create.content.trains.track; import java.util.Iterator; @@ -6,9 +6,9 @@ import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack.Pose; import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.logistics.trains.track.TrackRenderer; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.core.BlockPos; @@ -24,6 +24,7 @@ import net.minecraft.util.Mth; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.GameRules; import net.minecraft.world.level.Level; import net.minecraft.world.phys.AABB; @@ -37,8 +38,10 @@ public class BezierConnection implements Iterable { public Couple starts; public Couple axes; public Couple normals; + public Couple smoothing; public boolean primary; public boolean hasGirder; + protected TrackMaterial trackMaterial; // runtime @@ -55,19 +58,47 @@ public class BezierConnection implements Iterable { private AABB bounds; public BezierConnection(Couple positions, Couple starts, Couple axes, Couple normals, - boolean primary, boolean girder) { + boolean primary, boolean girder, TrackMaterial material) { tePositions = positions; this.starts = starts; this.axes = axes; this.normals = normals; this.primary = primary; this.hasGirder = girder; + this.trackMaterial = material; resolved = false; } public BezierConnection secondary() { - return new BezierConnection(tePositions.swap(), starts.swap(), axes.swap(), normals.swap(), !primary, - hasGirder); + BezierConnection bezierConnection = new BezierConnection(tePositions.swap(), starts.swap(), axes.swap(), + normals.swap(), !primary, hasGirder, trackMaterial); + if (smoothing != null) + bezierConnection.smoothing = smoothing.swap(); + return bezierConnection; + } + + public BezierConnection clone() { + return secondary().secondary(); + } + + private static boolean coupleEquals(Couple a, Couple b) { + return (a.getFirst() + .equals(b.getFirst()) + && a.getSecond() + .equals(b.getSecond())) + || (a.getFirst() instanceof Vec3 aFirst && a.getSecond() instanceof Vec3 aSecond + && b.getFirst() instanceof Vec3 bFirst && b.getSecond() instanceof Vec3 bSecond + && aFirst.closerThan(bFirst, 1e-6) && aSecond.closerThan(bSecond, 1e-6)); + } + + public boolean equalsSansMaterial(BezierConnection other) { + return equalsSansMaterialInner(other) || equalsSansMaterialInner(other.secondary()); + } + + private boolean equalsSansMaterialInner(BezierConnection other) { + return this == other || (other != null && coupleEquals(this.tePositions, other.tePositions) + && coupleEquals(this.starts, other.starts) && coupleEquals(this.axes, other.axes) + && coupleEquals(this.normals, other.normals) && this.hasGirder == other.hasGirder); } public BezierConnection(CompoundTag compound, BlockPos localTo) { @@ -77,7 +108,11 @@ public class BezierConnection implements Iterable { .map(v -> v.add(Vec3.atLowerCornerOf(localTo))), Couple.deserializeEach(compound.getList("Axes", Tag.TAG_COMPOUND), VecHelper::readNBTCompound), Couple.deserializeEach(compound.getList("Normals", Tag.TAG_COMPOUND), VecHelper::readNBTCompound), - compound.getBoolean("Primary"), compound.getBoolean("Girder")); + compound.getBoolean("Primary"), compound.getBoolean("Girder"), TrackMaterial.deserialize(compound.getString("Material"))); + + if (compound.contains("Smoothing")) + smoothing = + Couple.deserializeEach(compound.getList("Smoothing", Tag.TAG_COMPOUND), NBTHelper::intFromCompound); } public CompoundTag write(BlockPos localTo) { @@ -91,13 +126,20 @@ public class BezierConnection implements Iterable { compound.put("Starts", starts.serializeEach(VecHelper::writeNBTCompound)); compound.put("Axes", axes.serializeEach(VecHelper::writeNBTCompound)); compound.put("Normals", normals.serializeEach(VecHelper::writeNBTCompound)); + compound.putString("Material", getMaterial().id.toString()); + + if (smoothing != null) + compound.put("Smoothing", smoothing.serializeEach(NBTHelper::intToCompound)); + return compound; } public BezierConnection(FriendlyByteBuf buffer) { this(Couple.create(buffer::readBlockPos), Couple.create(() -> VecHelper.read(buffer)), Couple.create(() -> VecHelper.read(buffer)), Couple.create(() -> VecHelper.read(buffer)), - buffer.readBoolean(), buffer.readBoolean()); + buffer.readBoolean(), buffer.readBoolean(), TrackMaterial.deserialize(buffer.readUtf())); + if (buffer.readBoolean()) + smoothing = Couple.create(buffer::readVarInt); } public void write(FriendlyByteBuf buffer) { @@ -107,6 +149,10 @@ public class BezierConnection implements Iterable { normals.forEach(v -> VecHelper.write(v, buffer)); buffer.writeBoolean(primary); buffer.writeBoolean(hasGirder); + buffer.writeUtf(getMaterial().id.toString()); + buffer.writeBoolean(smoothing != null); + if (smoothing != null) + smoothing.forEach(buffer::writeVarInt); } public BlockPos getKey() { @@ -117,6 +163,16 @@ public class BezierConnection implements Iterable { return primary; } + public int yOffsetAt(Vec3 end) { + if (smoothing == null) + return 0; + if (TrackBlockEntityTilt.compareHandles(starts.getFirst(), end)) + return smoothing.getFirst(); + if (TrackBlockEntityTilt.compareHandles(starts.getSecond(), end)) + return smoothing.getSecond(); + return 0; + } + // Runtime information public double getLength() { @@ -300,7 +356,7 @@ public class BezierConnection implements Iterable { Inventory inv = player.getInventory(); int tracks = getTrackItemCost(); while (tracks > 0) { - inv.placeItemBackInInventory(AllBlocks.TRACK.asStack(Math.min(64, tracks))); + inv.placeItemBackInInventory(new ItemStack(getMaterial().getBlock(), Math.min(64, tracks))); tracks -= 64; } int girders = getGirderItemCost(); @@ -328,7 +384,7 @@ public class BezierConnection implements Iterable { continue; Vec3 v = VecHelper.offsetRandomly(segment.position, level.random, .125f) .add(origin); - ItemEntity entity = new ItemEntity(level, v.x, v.y, v.z, AllBlocks.TRACK.asStack()); + ItemEntity entity = new ItemEntity(level, v.x, v.y, v.z, getMaterial().asStack()); entity.setDefaultPickUpDelay(); level.addFreshEntity(entity); if (!hasGirder) @@ -342,7 +398,7 @@ public class BezierConnection implements Iterable { } public void spawnDestroyParticles(Level level) { - BlockParticleOption data = new BlockParticleOption(ParticleTypes.BLOCK, AllBlocks.TRACK.getDefaultState()); + BlockParticleOption data = new BlockParticleOption(ParticleTypes.BLOCK, getMaterial().getBlock().defaultBlockState()); BlockParticleOption girderData = new BlockParticleOption(ParticleTypes.BLOCK, AllBlocks.METAL_GIRDER.getDefaultState()); if (!(level instanceof ServerLevel slevel)) @@ -360,6 +416,14 @@ public class BezierConnection implements Iterable { } } + public TrackMaterial getMaterial() { + return trackMaterial; + } + + public void setMaterial(TrackMaterial material) { + trackMaterial = material; + } + public static class Segment { public int index; @@ -500,7 +564,7 @@ public class BezierConnection implements Iterable { .rotateYRadians(anglesI.y) .rotateXRadians(anglesI.x) .rotateZRadians(anglesI.z) - .translate(0, -2 / 16f + (i % 2 == 0 ? 1 : -1) / 2048f - 1 / 256f, -1 / 32f) + .translate(0, -2 / 16f - 1 / 256f, -1 / 32f) .scale(1, 1, (float) diff.length() * scale); angles.railTransforms.set(first, poseStack.last()); } diff --git a/src/main/java/com/simibubi/create/content/trains/track/BezierTrackPointLocation.java b/src/main/java/com/simibubi/create/content/trains/track/BezierTrackPointLocation.java new file mode 100644 index 000000000..67b9047b1 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/track/BezierTrackPointLocation.java @@ -0,0 +1,6 @@ +package com.simibubi.create.content.trains.track; + +import net.minecraft.core.BlockPos; + +public record BezierTrackPointLocation(BlockPos curveTarget, int segment) { +} diff --git a/src/main/java/com/simibubi/create/content/trains/track/CurvedTrackDestroyPacket.java b/src/main/java/com/simibubi/create/content/trains/track/CurvedTrackDestroyPacket.java new file mode 100644 index 000000000..35282aad9 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/track/CurvedTrackDestroyPacket.java @@ -0,0 +1,92 @@ +package com.simibubi.create.content.trains.track; + +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.Create; +import com.simibubi.create.foundation.networking.BlockEntityConfigurationPacket; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.state.BlockState; + +public class CurvedTrackDestroyPacket extends BlockEntityConfigurationPacket { + + private BlockPos targetPos; + private BlockPos soundSource; + private boolean wrench; + + public CurvedTrackDestroyPacket(BlockPos pos, BlockPos targetPos, BlockPos soundSource, boolean wrench) { + super(pos); + this.targetPos = targetPos; + this.soundSource = soundSource; + this.wrench = wrench; + } + + public CurvedTrackDestroyPacket(FriendlyByteBuf buffer) { + super(buffer); + } + + @Override + protected void writeSettings(FriendlyByteBuf buffer) { + buffer.writeBlockPos(targetPos); + buffer.writeBlockPos(soundSource); + buffer.writeBoolean(wrench); + } + + @Override + protected void readSettings(FriendlyByteBuf buffer) { + targetPos = buffer.readBlockPos(); + soundSource = buffer.readBlockPos(); + wrench = buffer.readBoolean(); + } + + @Override + protected void applySettings(ServerPlayer player, TrackBlockEntity be) { + int verifyDistance = AllConfigs.server().trains.maxTrackPlacementLength.get() * 4; + if (!be.getBlockPos() + .closerThan(player.blockPosition(), verifyDistance)) { + Create.LOGGER.warn(player.getScoreboardName() + " too far away from destroyed Curve track"); + return; + } + + Level level = be.getLevel(); + BezierConnection bezierConnection = be.getConnections() + .get(targetPos); + + be.removeConnection(targetPos); + if (level.getBlockEntity(targetPos)instanceof TrackBlockEntity other) + other.removeConnection(pos); + + BlockState blockState = be.getBlockState(); + TrackPropagator.onRailRemoved(level, pos, blockState); + + if (wrench) { + AllSoundEvents.WRENCH_REMOVE.playOnServer(player.level, soundSource, 1, + Create.RANDOM.nextFloat() * .5f + .5f); + if (!player.isCreative() && bezierConnection != null) + bezierConnection.addItemsToPlayer(player); + } else if (!player.isCreative() && bezierConnection != null) + bezierConnection.spawnItems(level); + + bezierConnection.spawnDestroyParticles(level); + SoundType soundtype = blockState.getSoundType(level, pos, player); + if (soundtype == null) + return; + + level.playSound(null, soundSource, soundtype.getBreakSound(), SoundSource.BLOCKS, + (soundtype.getVolume() + 1.0F) / 2.0F, soundtype.getPitch() * 0.8F); + } + + @Override + protected int maxRange() { + return 64; + } + + @Override + protected void applySettings(TrackBlockEntity be) {} + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/track/CurvedTrackInteraction.java b/src/main/java/com/simibubi/create/content/trains/track/CurvedTrackInteraction.java similarity index 87% rename from src/main/java/com/simibubi/create/content/logistics/trains/track/CurvedTrackInteraction.java rename to src/main/java/com/simibubi/create/content/trains/track/CurvedTrackInteraction.java index b15f50616..152213484 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/track/CurvedTrackInteraction.java +++ b/src/main/java/com/simibubi/create/content/trains/track/CurvedTrackInteraction.java @@ -1,10 +1,9 @@ -package com.simibubi.create.content.logistics.trains.track; +package com.simibubi.create.content.trains.track; -import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; -import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBlockItem; -import com.simibubi.create.content.logistics.trains.track.TrackBlockOutline.BezierPointSelection; -import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.AllPackets; +import com.simibubi.create.AllTags; +import com.simibubi.create.content.trains.track.TrackBlockOutline.BezierPointSelection; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.VecHelper; @@ -44,7 +43,7 @@ public class CurvedTrackInteraction { return; if (mc.options.keyAttack.isDown() && result != null) { - breakPos = result.te() + breakPos = result.blockEntity() .getBlockPos(); BlockState blockState = level.getBlockState(breakPos); if (blockState.isAir()) { @@ -74,7 +73,7 @@ public class CurvedTrackInteraction { player.swing(InteractionHand.MAIN_HAND); if (breakProgress >= 1) { - AllPackets.channel.sendToServer(new CurvedTrackDestroyPacket(breakPos, result.loc() + AllPackets.getChannel().sendToServer(new CurvedTrackDestroyPacket(breakPos, result.loc() .curveTarget(), new BlockPos(result.vec()), false)); resetBreakProgress(); } @@ -117,7 +116,7 @@ public class CurvedTrackInteraction { if (event.isUseItem()) { ItemStack heldItem = player.getMainHandItem(); Item item = heldItem.getItem(); - if (AllBlocks.TRACK.isIn(heldItem)) { + if (AllTags.AllBlockTags.TRACKS.matches(heldItem)) { player.displayClientMessage(Lang.translateDirect("track.turn_start") .withStyle(ChatFormatting.RED), true); player.swing(InteractionHand.MAIN_HAND); @@ -128,7 +127,7 @@ public class CurvedTrackInteraction { return true; } if (AllItems.WRENCH.isIn(heldItem) && player.isSteppingCarefully()) { - AllPackets.channel.sendToServer(new CurvedTrackDestroyPacket(result.te() + AllPackets.getChannel().sendToServer(new CurvedTrackDestroyPacket(result.blockEntity() .getBlockPos(), result.loc() .curveTarget(), diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/CurvedTrackSelectionPacket.java b/src/main/java/com/simibubi/create/content/trains/track/CurvedTrackSelectionPacket.java similarity index 82% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/CurvedTrackSelectionPacket.java rename to src/main/java/com/simibubi/create/content/trains/track/CurvedTrackSelectionPacket.java index f248780f2..b8d5aac03 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/CurvedTrackSelectionPacket.java +++ b/src/main/java/com/simibubi/create/content/trains/track/CurvedTrackSelectionPacket.java @@ -1,13 +1,12 @@ -package com.simibubi.create.content.logistics.trains.management.edgePoint; +package com.simibubi.create.content.trains.track; import org.apache.commons.lang3.mutable.MutableObject; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBlockItem.OverlapResult; -import com.simibubi.create.content.logistics.trains.track.BezierTrackPointLocation; -import com.simibubi.create.content.logistics.trains.track.TrackTileEntity; -import com.simibubi.create.foundation.networking.TileEntityConfigurationPacket; +import com.simibubi.create.content.trains.graph.EdgePointType; +import com.simibubi.create.content.trains.track.TrackTargetingBlockItem.OverlapResult; +import com.simibubi.create.foundation.networking.BlockEntityConfigurationPacket; import com.simibubi.create.foundation.utility.Lang; import net.minecraft.ChatFormatting; @@ -18,7 +17,7 @@ import net.minecraft.network.FriendlyByteBuf; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.item.ItemStack; -public class CurvedTrackSelectionPacket extends TileEntityConfigurationPacket { +public class CurvedTrackSelectionPacket extends BlockEntityConfigurationPacket { private BlockPos targetPos; private boolean front; @@ -54,7 +53,7 @@ public class CurvedTrackSelectionPacket extends TileEntityConfigurationPacket type, BlockPos pos, BlockState state) { + super(type, pos, state); + keepAlive(); + } + + public void randomTick() { + keepAlive--; + if (keepAlive > 0) + return; + level.removeBlock(worldPosition, false); + } + + public void keepAlive() { + keepAlive = 3; + } + + +} diff --git a/src/main/java/com/simibubi/create/content/trains/track/ITrackBlock.java b/src/main/java/com/simibubi/create/content/trains/track/ITrackBlock.java new file mode 100644 index 000000000..cfa41eb44 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/track/ITrackBlock.java @@ -0,0 +1,193 @@ +package com.simibubi.create.content.trains.track; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.function.BiFunction; +import java.util.function.Function; + +import javax.annotation.Nullable; + +import com.jozufozu.flywheel.core.PartialModel; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.content.trains.graph.TrackNodeLocation; +import com.simibubi.create.content.trains.graph.TrackNodeLocation.DiscoveredLocation; +import com.simibubi.create.content.trains.track.TrackTargetingBehaviour.RenderedTrackOverlayType; +import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.Pair; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.AxisDirection; +import net.minecraft.resources.ResourceKey; +import net.minecraft.server.level.ServerLevel; +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.state.BlockState; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public interface ITrackBlock { + + public Vec3 getUpNormal(BlockGetter world, BlockPos pos, BlockState state); + + public List getTrackAxes(BlockGetter world, BlockPos pos, BlockState state); + + public Vec3 getCurveStart(BlockGetter world, BlockPos pos, BlockState state, Vec3 axis); + + public default int getYOffsetAt(BlockGetter world, BlockPos pos, BlockState state, Vec3 end) { + return 0; + } + + public BlockState getBogeyAnchor(BlockGetter world, BlockPos pos, BlockState state); // should be on bogey side + + public boolean trackEquals(BlockState state1, BlockState state2); + + public default BlockState overlay(BlockGetter world, BlockPos pos, BlockState existing, BlockState placed) { + return existing; + } + + public default double getElevationAtCenter(BlockGetter world, BlockPos pos, BlockState state) { + return isSlope(world, pos, state) ? .5 : 0; + } + + public static Collection walkConnectedTracks(BlockGetter worldIn, TrackNodeLocation location, + boolean linear) { + BlockGetter world = location != null && worldIn instanceof ServerLevel sl ? sl.getServer() + .getLevel(location.dimension) : worldIn; + List list = new ArrayList<>(); + for (BlockPos blockPos : location.allAdjacent()) { + BlockState blockState = world.getBlockState(blockPos); + if (blockState.getBlock()instanceof ITrackBlock track) + list.addAll(track.getConnected(world, blockPos, blockState, linear, location)); + } + return list; + } + + public default Collection getConnected(BlockGetter worldIn, BlockPos pos, BlockState state, + boolean linear, @Nullable TrackNodeLocation connectedTo) { + BlockGetter world = connectedTo != null && worldIn instanceof ServerLevel sl ? sl.getServer() + .getLevel(connectedTo.dimension) : worldIn; + Vec3 center = Vec3.atBottomCenterOf(pos) + .add(0, getElevationAtCenter(world, pos, state), 0); + List list = new ArrayList<>(); + TrackShape shape = state.getValue(TrackBlock.SHAPE); + List trackAxes = getTrackAxes(world, pos, state); + + trackAxes.forEach(axis -> { + BiFunction offsetFactory = (d, b) -> axis.scale(b ? d : -d) + .add(center); + Function> dimensionFactory = + b -> world instanceof Level l ? l.dimension() : Level.OVERWORLD; + Function yOffsetFactory = v -> getYOffsetAt(world, pos, state, v); + + addToListIfConnected(connectedTo, list, offsetFactory, b -> shape.getNormal(), dimensionFactory, + yOffsetFactory, axis, null, (b, v) -> getMaterialSimple(world, v)); + }); + + return list; + } + + public static TrackMaterial getMaterialSimple(BlockGetter world, Vec3 pos) { + return getMaterialSimple(world, pos, TrackMaterial.ANDESITE); + } + + public static TrackMaterial getMaterialSimple(BlockGetter world, Vec3 pos, TrackMaterial defaultMaterial) { + if (defaultMaterial == null) + defaultMaterial = TrackMaterial.ANDESITE; + if (world != null) { + Block block = world.getBlockState(new BlockPos(pos)).getBlock(); + if (block instanceof ITrackBlock track) { + return track.getMaterial(); + } + } + return defaultMaterial; + } + + public static void addToListIfConnected(@Nullable TrackNodeLocation fromEnd, Collection list, + BiFunction offsetFactory, Function normalFactory, + Function> dimensionFactory, Function yOffsetFactory, Vec3 axis, + BezierConnection viaTurn, BiFunction materialFactory) { + + Vec3 firstOffset = offsetFactory.apply(0.5d, true); + DiscoveredLocation firstLocation = + new DiscoveredLocation(dimensionFactory.apply(true), firstOffset).viaTurn(viaTurn) + .materialA(materialFactory.apply(true, offsetFactory.apply(0.0d, true))) + .materialB(materialFactory.apply(true, offsetFactory.apply(1.0d, true))) + .withNormal(normalFactory.apply(true)) + .withDirection(axis) + .withYOffset(yOffsetFactory.apply(firstOffset)); + + Vec3 secondOffset = offsetFactory.apply(0.5d, false); + DiscoveredLocation secondLocation = + new DiscoveredLocation(dimensionFactory.apply(false), secondOffset).viaTurn(viaTurn) + .materialA(materialFactory.apply(false, offsetFactory.apply(0.0d, false))) + .materialB(materialFactory.apply(false, offsetFactory.apply(1.0d, false))) + .withNormal(normalFactory.apply(false)) + .withDirection(axis) + .withYOffset(yOffsetFactory.apply(secondOffset)); + + if (!firstLocation.dimension.equals(secondLocation.dimension)) { + firstLocation.forceNode(); + secondLocation.forceNode(); + } + + boolean skipFirst = false; + boolean skipSecond = false; + + if (fromEnd != null) { + boolean equalsFirst = firstLocation.equals(fromEnd); + boolean equalsSecond = secondLocation.equals(fromEnd); + + // not reachable from this end + if (!equalsFirst && !equalsSecond) + return; + + if (equalsFirst) + skipFirst = true; + if (equalsSecond) + skipSecond = true; + } + + if (!skipFirst) + list.add(firstLocation); + if (!skipSecond) + list.add(secondLocation); + } + + @OnlyIn(Dist.CLIENT) + public PartialModel prepareTrackOverlay(BlockGetter world, BlockPos pos, BlockState state, + BezierTrackPointLocation bezierPoint, AxisDirection direction, PoseStack transform, + RenderedTrackOverlayType type); + + @OnlyIn(Dist.CLIENT) + public PartialModel prepareAssemblyOverlay(BlockGetter world, BlockPos pos, BlockState state, Direction direction, + PoseStack ms); + + public default boolean isSlope(BlockGetter world, BlockPos pos, BlockState state) { + return getTrackAxes(world, pos, state).get(0).y != 0; + } + + public default Pair getNearestTrackAxis(BlockGetter world, BlockPos pos, BlockState state, + Vec3 lookVec) { + Vec3 best = null; + double bestDiff = Double.MAX_VALUE; + for (Vec3 vec3 : getTrackAxes(world, pos, state)) { + for (int opposite : Iterate.positiveAndNegative) { + double distanceTo = vec3.normalize() + .distanceTo(lookVec.scale(opposite)); + if (distanceTo > bestDiff) + continue; + bestDiff = distanceTo; + best = vec3; + } + } + return Pair.of(best, lookVec.dot(best.multiply(1, 0, 1) + .normalize()) < 0 ? AxisDirection.POSITIVE : AxisDirection.NEGATIVE); + } + + TrackMaterial getMaterial(); + +} diff --git a/src/main/java/com/simibubi/create/content/trains/track/PlaceExtendedCurvePacket.java b/src/main/java/com/simibubi/create/content/trains/track/PlaceExtendedCurvePacket.java new file mode 100644 index 000000000..6fe153c66 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/track/PlaceExtendedCurvePacket.java @@ -0,0 +1,48 @@ +package com.simibubi.create.content.trains.track; + +import com.simibubi.create.AllTags; +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.network.NetworkEvent.Context; + +public class PlaceExtendedCurvePacket extends SimplePacketBase { + + boolean mainHand; + boolean ctrlDown; + + public PlaceExtendedCurvePacket(boolean mainHand, boolean ctrlDown) { + this.mainHand = mainHand; + this.ctrlDown = ctrlDown; + } + + public PlaceExtendedCurvePacket(FriendlyByteBuf buffer) { + mainHand = buffer.readBoolean(); + ctrlDown = buffer.readBoolean(); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeBoolean(mainHand); + buffer.writeBoolean(ctrlDown); + } + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> { + ServerPlayer sender = context.getSender(); + ItemStack stack = sender.getItemInHand(mainHand ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND); + if (!AllTags.AllBlockTags.TRACKS.matches(stack) || !stack.hasTag()) + return; + CompoundTag tag = stack.getTag(); + tag.putBoolean("ExtendCurve", true); + stack.setTag(tag); + }); + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackBlock.java b/src/main/java/com/simibubi/create/content/trains/track/TrackBlock.java similarity index 78% rename from src/main/java/com/simibubi/create/content/logistics/trains/track/TrackBlock.java rename to src/main/java/com/simibubi/create/content/trains/track/TrackBlock.java index c05eb85a5..0c58a3b83 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackBlock.java +++ b/src/main/java/com/simibubi/create/content/trains/track/TrackBlock.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.track; +package com.simibubi.create.content.trains.track; import static com.simibubi.create.AllShapes.TRACK_ASC; import static com.simibubi.create.AllShapes.TRACK_CROSS; @@ -25,25 +25,23 @@ import com.google.common.base.Predicates; import com.jozufozu.flywheel.core.PartialModel; import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPartialModels; import com.simibubi.create.AllShapes; -import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueEntity; -import com.simibubi.create.content.contraptions.particle.CubeParticleData; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; -import com.simibubi.create.content.curiosities.girder.GirderBlock; -import com.simibubi.create.content.logistics.trains.BezierConnection; -import com.simibubi.create.content.logistics.trains.ITrackBlock; -import com.simibubi.create.content.logistics.trains.TrackNodeLocation; -import com.simibubi.create.content.logistics.trains.TrackNodeLocation.DiscoveredLocation; -import com.simibubi.create.content.logistics.trains.TrackPropagator; -import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBehaviour.RenderedTrackOverlayType; -import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationTileEntity; -import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement; -import com.simibubi.create.content.schematics.ItemRequirement; -import com.simibubi.create.content.schematics.ItemRequirement.ItemUseType; -import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.AllTags; +import com.simibubi.create.content.contraptions.glue.SuperGlueEntity; +import com.simibubi.create.content.decoration.girder.GirderBlock; +import com.simibubi.create.content.equipment.wrench.IWrenchable; +import com.simibubi.create.content.schematics.requirement.ISpecialBlockItemRequirement; +import com.simibubi.create.content.schematics.requirement.ItemRequirement; +import com.simibubi.create.content.schematics.requirement.ItemRequirement.ItemUseType; +import com.simibubi.create.content.trains.CubeParticleData; +import com.simibubi.create.content.trains.graph.TrackNodeLocation; +import com.simibubi.create.content.trains.graph.TrackNodeLocation.DiscoveredLocation; +import com.simibubi.create.content.trains.station.StationBlockEntity; +import com.simibubi.create.content.trains.track.TrackTargetingBehaviour.RenderedTrackOverlayType; +import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.block.ProperWaterloggedBlock; import com.simibubi.create.foundation.block.render.MultiPosDestructionHandler; import com.simibubi.create.foundation.block.render.ReducedDestroyEffects; @@ -55,6 +53,8 @@ import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Pair; import com.simibubi.create.foundation.utility.VecHelper; +import it.unimi.dsi.fastutil.objects.Object2IntArrayMap; +import it.unimi.dsi.fastutil.objects.Object2IntMap; import net.minecraft.ChatFormatting; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.core.BlockPos; @@ -109,21 +109,24 @@ import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.client.extensions.common.IClientBlockExtensions; public class TrackBlock extends Block - implements ITE, IWrenchable, ITrackBlock, ISpecialBlockItemRequirement, ProperWaterloggedBlock { + implements IBE, IWrenchable, ITrackBlock, ISpecialBlockItemRequirement, ProperWaterloggedBlock { public static final EnumProperty SHAPE = EnumProperty.create("shape", TrackShape.class); - public static final BooleanProperty HAS_TE = BooleanProperty.create("turn"); + public static final BooleanProperty HAS_BE = BooleanProperty.create("turn"); - public TrackBlock(Properties p_49795_) { + protected final TrackMaterial material; + + public TrackBlock(Properties p_49795_, TrackMaterial material) { super(p_49795_); registerDefaultState(defaultBlockState().setValue(SHAPE, TrackShape.ZO) - .setValue(HAS_TE, false) + .setValue(HAS_BE, false) .setValue(WATERLOGGED, false)); + this.material = material; } @Override protected void createBlockStateDefinition(Builder p_49915_) { - super.createBlockStateDefinition(p_49915_.add(SHAPE, HAS_TE, WATERLOGGED)); + super.createBlockStateDefinition(p_49915_.add(SHAPE, HAS_BE, WATERLOGGED)); } @Override @@ -208,15 +211,15 @@ public class TrackBlock extends Block return; if (!pPlayer.isCreative()) return; - withTileEntityDo(pLevel, pPos, te -> { - te.cancelDrops = true; - te.removeInboundConnections(); + withBlockEntityDo(pLevel, pPos, be -> { + be.cancelDrops = true; + be.removeInboundConnections(true); }); } @Override public void onPlace(BlockState pState, Level pLevel, BlockPos pPos, BlockState pOldState, boolean pIsMoving) { - if (pOldState.getBlock() == this && pState.setValue(HAS_TE, true) == pOldState.setValue(HAS_TE, true)) + if (pOldState.getBlock() == this && pState.setValue(HAS_BE, true) == pOldState.setValue(HAS_BE, true)) return; if (pLevel.isClientSide) return; @@ -229,12 +232,13 @@ public class TrackBlock extends Block @Override public void setPlacedBy(Level pLevel, BlockPos pPos, BlockState pState, LivingEntity pPlacer, ItemStack pStack) { super.setPlacedBy(pLevel, pPos, pState, pPlacer, pStack); - withTileEntityDo(pLevel, pPos, TrackTileEntity::validateConnections); + withBlockEntityDo(pLevel, pPos, TrackBlockEntity::validateConnections); } @Override public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource p_60465_) { TrackPropagator.onRailAdded(level, pos, state); + withBlockEntityDo(level, pos, tbe -> tbe.tilt.undoSmoothing()); if (!state.getValue(SHAPE) .isPortal()) connectToNether(level, pos, state); @@ -275,16 +279,16 @@ public class TrackBlock extends Block } level.setBlock(pos, state.setValue(SHAPE, TrackShape.asPortal(d)) - .setValue(HAS_TE, true), 3); - BlockEntity te = level.getBlockEntity(pos); - if (te instanceof TrackTileEntity tte) - tte.bind(otherLevel.dimension(), otherTrackPos); + .setValue(HAS_BE, true), 3); + BlockEntity be = level.getBlockEntity(pos); + if (be instanceof TrackBlockEntity tbe) + tbe.bind(otherLevel.dimension(), otherTrackPos); otherLevel.setBlock(otherTrackPos, state.setValue(SHAPE, TrackShape.asPortal(otherTrack.getFace())) - .setValue(HAS_TE, true), 3); - BlockEntity otherTe = otherLevel.getBlockEntity(otherTrackPos); - if (otherTe instanceof TrackTileEntity tte) - tte.bind(level.dimension(), pos); + .setValue(HAS_BE, true), 3); + BlockEntity otherBE = otherLevel.getBlockEntity(otherTrackPos); + if (otherBE instanceof TrackBlockEntity tbe) + tbe.bind(level.dimension(), pos); pop = false; } @@ -299,12 +303,14 @@ public class TrackBlock extends Block Player player = level.getNearestPlayer(pos.getX(), pos.getY(), pos.getZ(), 10, Predicates.alwaysTrue()); if (player == null) return; - player.displayClientMessage(Components.literal(" ").append(Lang.translateDirect("portal_track.failed")) + player.displayClientMessage(Components.literal(" ") + .append(Lang.translateDirect("portal_track.failed")) .withStyle(ChatFormatting.GOLD), false); - MutableComponent component = - failPos != null ? Lang.translateDirect("portal_track." + fail, failPos.getX(), failPos.getY(), failPos.getZ()) - : Lang.translateDirect("portal_track." + fail); - player.displayClientMessage(Components.literal(" - ").withStyle(ChatFormatting.GRAY) + MutableComponent component = failPos != null + ? Lang.translateDirect("portal_track." + fail, failPos.getX(), failPos.getY(), failPos.getZ()) + : Lang.translateDirect("portal_track." + fail); + player.displayClientMessage(Components.literal(" - ") + .withStyle(ChatFormatting.GRAY) .append(component.withStyle(st -> st.withColor(0xFFD3B4))), false); } @@ -363,6 +369,12 @@ public class TrackBlock extends Block return state; } + @Override + public int getYOffsetAt(BlockGetter world, BlockPos pos, BlockState state, Vec3 end) { + return getBlockEntityOptional(world, pos).map(tbe -> tbe.tilt.getYOffsetForAxisEnd(end)) + .orElse(0); + } + @Override public Collection getConnected(BlockGetter worldIn, BlockPos pos, BlockState state, boolean linear, TrackNodeLocation connectedTo) { @@ -380,36 +392,37 @@ public class TrackBlock extends Block ITrackBlock.addToListIfConnected(connectedTo, list, (d, b) -> axis.scale(b ? 0 : fromCenter ? -d : d) .add(center), - b -> shape.getNormal(), b -> world instanceof Level l ? l.dimension() : Level.OVERWORLD, axis, - null); + b -> shape.getNormal(), b -> world instanceof Level l ? l.dimension() : Level.OVERWORLD, v -> 0, + axis, null, (b, v) -> ITrackBlock.getMaterialSimple(world, v)); } else list = ITrackBlock.super.getConnected(world, pos, state, linear, connectedTo); - if (!state.getValue(HAS_TE)) + if (!state.getValue(HAS_BE)) return list; if (linear) return list; BlockEntity blockEntity = world.getBlockEntity(pos); - if (!(blockEntity instanceof TrackTileEntity trackTE)) + if (!(blockEntity instanceof TrackBlockEntity trackBE)) return list; - Map connections = trackTE.getConnections(); + Map connections = trackBE.getConnections(); connections.forEach((connectedPos, bc) -> ITrackBlock.addToListIfConnected(connectedTo, list, (d, b) -> d == 1 ? Vec3.atLowerCornerOf(bc.tePositions.get(b)) : bc.starts.get(b), bc.normals::get, - b -> world instanceof Level l ? l.dimension() : Level.OVERWORLD, null, bc)); + b -> world instanceof Level l ? l.dimension() : Level.OVERWORLD, bc::yOffsetAt, null, bc, + (b, v) -> ITrackBlock.getMaterialSimple(world, v, bc.getMaterial()))); - if (trackTE.boundLocation == null || !(world instanceof ServerLevel level)) + if (trackBE.boundLocation == null || !(world instanceof ServerLevel level)) return list; - ResourceKey otherDim = trackTE.boundLocation.getFirst(); + ResourceKey otherDim = trackBE.boundLocation.getFirst(); ServerLevel otherLevel = level.getServer() .getLevel(otherDim); if (otherLevel == null) return list; - BlockPos boundPos = trackTE.boundLocation.getSecond(); + BlockPos boundPos = trackBE.boundLocation.getSecond(); BlockState boundState = otherLevel.getBlockState(boundPos); - if (!AllBlocks.TRACK.has(boundState)) + if (!AllTags.AllBlockTags.TRACKS.matches(boundState)) return list; Vec3 center = Vec3.atBottomCenterOf(pos) @@ -423,7 +436,8 @@ public class TrackBlock extends Block getTrackAxes(world, pos, state).forEach(axis -> { ITrackBlock.addToListIfConnected(connectedTo, list, (d, b) -> (b ? axis : boundAxis).scale(d) .add(b ? center : boundCenter), b -> (b ? shape : boundShape).getNormal(), - b -> b ? level.dimension() : otherLevel.dimension(), axis, null); + b -> b ? level.dimension() : otherLevel.dimension(), v -> 0, axis, null, + (b, v) -> ITrackBlock.getMaterialSimple(b ? level : otherLevel, v)); }); return list; @@ -443,17 +457,19 @@ public class TrackBlock extends Block @Override public void onRemove(BlockState pState, Level pLevel, BlockPos pPos, BlockState pNewState, boolean pIsMoving) { - boolean removeTE = false; - if (pState.getValue(HAS_TE) && (!pState.is(pNewState.getBlock()) || !pNewState.getValue(HAS_TE))) { + boolean removeBE = false; + if (pState.getValue(HAS_BE) && (!pState.is(pNewState.getBlock()) || !pNewState.getValue(HAS_BE))) { BlockEntity blockEntity = pLevel.getBlockEntity(pPos); - if (blockEntity instanceof TrackTileEntity && !pLevel.isClientSide) - ((TrackTileEntity) blockEntity).removeInboundConnections(); - removeTE = true; + if (blockEntity instanceof TrackBlockEntity tbe && !pLevel.isClientSide) { + tbe.cancelDrops |= pNewState.getBlock() == this; + tbe.removeInboundConnections(true); + } + removeBE = true; } - if (pNewState.getBlock() != this || pState.setValue(HAS_TE, true) != pNewState.setValue(HAS_TE, true)) + if (pNewState.getBlock() != this || pState.setValue(HAS_BE, true) != pNewState.setValue(HAS_BE, true)) TrackPropagator.onRailRemoved(pLevel, pPos, pState); - if (removeTE) + if (removeBE) pLevel.removeBlockEntity(pPos); if (!pLevel.isClientSide) updateGirders(pState, pLevel, pPos, pLevel.getBlockTicks()); @@ -465,12 +481,12 @@ public class TrackBlock extends Block if (world.isClientSide) return InteractionResult.SUCCESS; - for (Entry entry : StationTileEntity.assemblyAreas.get(world) + for (Entry entry : StationBlockEntity.assemblyAreas.get(world) .entrySet()) { if (!entry.getValue() .isInside(pos)) continue; - if (world.getBlockEntity(entry.getKey()) instanceof StationTileEntity station) + if (world.getBlockEntity(entry.getKey()) instanceof StationBlockEntity station) if (station.trackClicked(player, hand, this, state, pos)) return InteractionResult.SUCCESS; } @@ -566,19 +582,19 @@ public class TrackBlock extends Block @Override public BlockEntity newBlockEntity(BlockPos p_153215_, BlockState state) { - if (!state.getValue(HAS_TE)) + if (!state.getValue(HAS_BE)) return null; - return AllTileEntities.TRACK.create(p_153215_, state); + return AllBlockEntityTypes.TRACK.create(p_153215_, state); } @Override - public Class getTileEntityClass() { - return TrackTileEntity.class; + public Class getBlockEntityClass() { + return TrackBlockEntity.class; } @Override - public BlockEntityType getTileEntityType() { - return AllTileEntities.TRACK.get(); + public BlockEntityType getBlockEntityType() { + return AllBlockEntityTypes.TRACK.get(); } @Override @@ -610,11 +626,11 @@ public class TrackBlock extends Block public InteractionResult onSneakWrenched(BlockState state, UseOnContext context) { Player player = context.getPlayer(); Level level = context.getLevel(); - if (!level.isClientSide && !player.isCreative() && state.getValue(HAS_TE)) { + if (!level.isClientSide && !player.isCreative() && state.getValue(HAS_BE)) { BlockEntity blockEntity = level.getBlockEntity(context.getClickedPos()); - if (blockEntity instanceof TrackTileEntity trackTE) { - trackTE.cancelDrops = true; - trackTE.connections.values() + if (blockEntity instanceof TrackBlockEntity trackBE) { + trackBE.cancelDrops = true; + trackBE.connections.values() .forEach(bc -> bc.addItemsToPlayer(player)); } } @@ -677,7 +693,7 @@ public class TrackBlock extends Block PoseStack ms) { TransformStack.cast(ms) .rotateCentered(Direction.UP, AngleHelper.rad(AngleHelper.horizontalAngle(direction))); - return AllBlockPartials.TRACK_ASSEMBLING_OVERLAY; + return AllPartialModels.TRACK_ASSEMBLING_OVERLAY; } @Override @@ -691,8 +707,8 @@ public class TrackBlock extends Block Vec3 normal = null; Vec3 offset = null; - if (bezierPoint != null && world.getBlockEntity(pos) instanceof TrackTileEntity trackTE) { - BezierConnection bc = trackTE.connections.get(bezierPoint.curveTarget()); + if (bezierPoint != null && world.getBlockEntity(pos) instanceof TrackBlockEntity trackBE) { + BezierConnection bc = trackBE.connections.get(bezierPoint.curveTarget()); if (bc != null) { double length = Mth.floor(bc.getLength() * 2); int seg = bezierPoint.segment() + 1; @@ -736,39 +752,63 @@ public class TrackBlock extends Block msr.rotateCentered(Direction.UP, Mth.PI); } + if (bezierPoint == null && world.getBlockEntity(pos) instanceof TrackBlockEntity trackTE + && trackTE.isTilted()) { + double yOffset = 0; + for (BezierConnection bc : trackTE.connections.values()) + yOffset += bc.starts.getFirst().y - pos.getY(); + msr.centre() + .rotateX(-direction.getStep() * trackTE.tilt.smoothingAngle.get()) + .unCentre() + .translate(0, yOffset / 2, 0); + } + return switch (type) { - case DUAL_SIGNAL -> AllBlockPartials.TRACK_SIGNAL_DUAL_OVERLAY; - case OBSERVER -> AllBlockPartials.TRACK_OBSERVER_OVERLAY; - case SIGNAL -> AllBlockPartials.TRACK_SIGNAL_OVERLAY; - case STATION -> AllBlockPartials.TRACK_STATION_OVERLAY; + case DUAL_SIGNAL -> AllPartialModels.TRACK_SIGNAL_DUAL_OVERLAY; + case OBSERVER -> AllPartialModels.TRACK_OBSERVER_OVERLAY; + case SIGNAL -> AllPartialModels.TRACK_SIGNAL_OVERLAY; + case STATION -> AllPartialModels.TRACK_STATION_OVERLAY; }; } @Override public boolean trackEquals(BlockState state1, BlockState state2) { return state1.getBlock() == this && state2.getBlock() == this - && state1.setValue(HAS_TE, false) == state2.setValue(HAS_TE, false); + && state1.setValue(HAS_BE, false) == state2.setValue(HAS_BE, false); } @Override - public ItemRequirement getRequiredItems(BlockState state, BlockEntity te) { - int trackAmount = 1; + public ItemRequirement getRequiredItems(BlockState state, BlockEntity be) { + int sameTypeTrackAmount = 1; + Object2IntMap otherTrackAmounts = new Object2IntArrayMap<>(); int girderAmount = 0; - if (te instanceof TrackTileEntity track) { + if (be instanceof TrackBlockEntity track) { for (BezierConnection bezierConnection : track.getConnections() .values()) { if (!bezierConnection.isPrimary()) continue; - trackAmount += bezierConnection.getTrackItemCost(); + TrackMaterial material = bezierConnection.getMaterial(); + if (material == getMaterial()) { + sameTypeTrackAmount += bezierConnection.getTrackItemCost(); + } else { + otherTrackAmounts.put(material, otherTrackAmounts.getOrDefault(material, 0) + 1); + } girderAmount += bezierConnection.getGirderItemCost(); } } List stacks = new ArrayList<>(); - while (trackAmount > 0) { - stacks.add(AllBlocks.TRACK.asStack(Math.min(trackAmount, 64))); - trackAmount -= 64; + while (sameTypeTrackAmount > 0) { + stacks.add(new ItemStack(state.getBlock(), Math.min(sameTypeTrackAmount, 64))); + sameTypeTrackAmount -= 64; + } + for (TrackMaterial material : otherTrackAmounts.keySet()) { + int amt = otherTrackAmounts.getOrDefault(material, 0); + while (amt > 0) { + stacks.add(material.asStack(Math.min(amt, 64))); + amt -= 64; + } } while (girderAmount > 0) { stacks.add(AllBlocks.METAL_GIRDER.asStack(Math.min(girderAmount, 64))); @@ -778,13 +818,17 @@ public class TrackBlock extends Block return new ItemRequirement(ItemUseType.CONSUME, stacks); } + @Override + public TrackMaterial getMaterial() { + return material; + } + public static class RenderProperties extends ReducedDestroyEffects implements MultiPosDestructionHandler { @Override @Nullable - public Set getExtraPositions(ClientLevel level, BlockPos pos, BlockState blockState, - int progress) { + public Set getExtraPositions(ClientLevel level, BlockPos pos, BlockState blockState, int progress) { BlockEntity blockEntity = level.getBlockEntity(pos); - if (blockEntity instanceof TrackTileEntity track) { + if (blockEntity instanceof TrackBlockEntity track) { return new HashSet<>(track.connections.keySet()); } return null; diff --git a/src/main/java/com/simibubi/create/content/trains/track/TrackBlockEntity.java b/src/main/java/com/simibubi/create/content/trains/track/TrackBlockEntity.java new file mode 100644 index 000000000..99fd7758e --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/track/TrackBlockEntity.java @@ -0,0 +1,445 @@ +package com.simibubi.create.content.trains.track; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Optional; +import java.util.Set; + +import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPackets; +import com.simibubi.create.AllTags; +import com.simibubi.create.content.contraptions.ITransformableBlockEntity; +import com.simibubi.create.content.contraptions.StructureTransform; +import com.simibubi.create.content.trains.graph.TrackNodeLocation; +import com.simibubi.create.foundation.block.ProperWaterloggedBlock; +import com.simibubi.create.foundation.blockEntity.IMergeableBE; +import com.simibubi.create.foundation.blockEntity.RemoveBlockEntityPacket; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.Pair; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction.Axis; +import net.minecraft.core.registries.Registries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.nbt.Tag; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.Mth; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.level.material.Fluids; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.client.model.data.ModelData; +import net.minecraftforge.fml.DistExecutor; + +public class TrackBlockEntity extends SmartBlockEntity implements ITransformableBlockEntity, IMergeableBE { + + Map connections; + boolean cancelDrops; + + public Pair, BlockPos> boundLocation; + public TrackBlockEntityTilt tilt; + + public TrackBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + connections = new HashMap<>(); + setLazyTickRate(100); + tilt = new TrackBlockEntityTilt(this); + } + + public Map getConnections() { + return connections; + } + + @Override + public void initialize() { + super.initialize(); + if (!level.isClientSide && hasInteractableConnections()) + registerToCurveInteraction(); + } + + @Override + public void tick() { + super.tick(); + tilt.undoSmoothing(); + } + + @Override + public void lazyTick() { + for (BezierConnection connection : connections.values()) + if (connection.isPrimary()) + manageFakeTracksAlong(connection, false); + } + + public void validateConnections() { + Set invalid = new HashSet<>(); + + for (Entry entry : connections.entrySet()) { + BlockPos key = entry.getKey(); + BezierConnection bc = entry.getValue(); + + if (!key.equals(bc.getKey()) || !worldPosition.equals(bc.tePositions.getFirst())) { + invalid.add(key); + continue; + } + + BlockState blockState = level.getBlockState(key); + if (blockState.getBlock()instanceof ITrackBlock trackBlock && !blockState.getValue(TrackBlock.HAS_BE)) + for (Vec3 v : trackBlock.getTrackAxes(level, key, blockState)) { + Vec3 bcEndAxis = bc.axes.getSecond(); + if (v.distanceTo(bcEndAxis) < 1 / 1024f || v.distanceTo(bcEndAxis.scale(-1)) < 1 / 1024f) + level.setBlock(key, blockState.setValue(TrackBlock.HAS_BE, true), 3); + } + + BlockEntity blockEntity = level.getBlockEntity(key); + if (!(blockEntity instanceof TrackBlockEntity trackBE) || blockEntity.isRemoved()) { + invalid.add(key); + continue; + } + + if (!trackBE.connections.containsKey(worldPosition)) { + trackBE.addConnection(bc.secondary()); + trackBE.tilt.tryApplySmoothing(); + } + } + + for (BlockPos blockPos : invalid) + removeConnection(blockPos); + } + + public void addConnection(BezierConnection connection) { + // don't replace existing connections with different materials + if (connections.containsKey(connection.getKey()) && connection.equalsSansMaterial(connections.get(connection.getKey()))) + return; + connections.put(connection.getKey(), connection); + level.scheduleTick(worldPosition, getBlockState().getBlock(), 1); + notifyUpdate(); + + if (connection.isPrimary()) + manageFakeTracksAlong(connection, false); + } + + public void removeConnection(BlockPos target) { + if (isTilted()) + tilt.captureSmoothingHandles(); + + BezierConnection removed = connections.remove(target); + notifyUpdate(); + + if (removed != null) + manageFakeTracksAlong(removed, true); + + if (!connections.isEmpty() || getBlockState().getOptionalValue(TrackBlock.SHAPE) + .orElse(TrackShape.NONE) + .isPortal()) + return; + + BlockState blockState = level.getBlockState(worldPosition); + if (blockState.hasProperty(TrackBlock.HAS_BE)) + level.setBlockAndUpdate(worldPosition, blockState.setValue(TrackBlock.HAS_BE, false)); + AllPackets.getChannel().send(packetTarget(), new RemoveBlockEntityPacket(worldPosition)); + } + + public void removeInboundConnections(boolean dropAndDiscard) { + for (BezierConnection bezierConnection : connections.values()) { + if (!(level.getBlockEntity(bezierConnection.getKey())instanceof TrackBlockEntity tbe)) + return; + tbe.removeConnection(bezierConnection.tePositions.getFirst()); + if (!dropAndDiscard) + continue; + if (!cancelDrops) + bezierConnection.spawnItems(level); + bezierConnection.spawnDestroyParticles(level); + } + if (dropAndDiscard) + AllPackets.getChannel().send(packetTarget(), new RemoveBlockEntityPacket(worldPosition)); + } + + public void bind(ResourceKey boundDimension, BlockPos boundLocation) { + this.boundLocation = Pair.of(boundDimension, boundLocation); + setChanged(); + } + + public boolean isTilted() { + return tilt.smoothingAngle.isPresent(); + } + + @Override + public void writeSafe(CompoundTag tag) { + super.writeSafe(tag); + writeTurns(tag, true); + } + + @Override + protected void write(CompoundTag tag, boolean clientPacket) { + super.write(tag, clientPacket); + writeTurns(tag, false); + if (isTilted()) + tag.putDouble("Smoothing", tilt.smoothingAngle.get()); + if (boundLocation == null) + return; + tag.put("BoundLocation", NbtUtils.writeBlockPos(boundLocation.getSecond())); + tag.putString("BoundDimension", boundLocation.getFirst() + .location() + .toString()); + } + + private void writeTurns(CompoundTag tag, boolean restored) { + ListTag listTag = new ListTag(); + for (BezierConnection bezierConnection : connections.values()) + listTag.add((restored ? tilt.restoreToOriginalCurve(bezierConnection.clone()) : bezierConnection) + .write(worldPosition)); + tag.put("Connections", listTag); + } + + @Override + protected void read(CompoundTag tag, boolean clientPacket) { + super.read(tag, clientPacket); + connections.clear(); + for (Tag t : tag.getList("Connections", Tag.TAG_COMPOUND)) { + if (!(t instanceof CompoundTag)) + return; + BezierConnection connection = new BezierConnection((CompoundTag) t, worldPosition); + connections.put(connection.getKey(), connection); + } + + boolean smoothingPreviously = tilt.smoothingAngle.isPresent(); + tilt.smoothingAngle = Optional.ofNullable(tag.contains("Smoothing") ? tag.getDouble("Smoothing") : null); + if (smoothingPreviously != tilt.smoothingAngle.isPresent() && clientPacket) { + requestModelDataUpdate(); + level.sendBlockUpdated(worldPosition, getBlockState(), getBlockState(), 16); + } + + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(this)); + + if (hasInteractableConnections()) + registerToCurveInteraction(); + else + removeFromCurveInteraction(); + + if (tag.contains("BoundLocation")) + boundLocation = Pair.of( + ResourceKey.create(Registries.DIMENSION, new ResourceLocation(tag.getString("BoundDimension"))), + NbtUtils.readBlockPos(tag.getCompound("BoundLocation"))); + } + + @Override + @OnlyIn(Dist.CLIENT) + public AABB getRenderBoundingBox() { + return INFINITE_EXTENT_AABB; + } + + @Override + public void addBehaviours(List behaviours) {} + + @Override + public void accept(BlockEntity other) { + if (other instanceof TrackBlockEntity track) + connections.putAll(track.connections); + validateConnections(); + level.scheduleTick(worldPosition, getBlockState().getBlock(), 1); + } + + public boolean hasInteractableConnections() { + for (BezierConnection connection : connections.values()) + if (connection.isPrimary()) + return true; + return false; + } + + @Override + public void transform(StructureTransform transform) { + Map restoredConnections = new HashMap<>(); + for (Entry entry : connections.entrySet()) + restoredConnections.put(entry.getKey(), + tilt.restoreToOriginalCurve(tilt.restoreToOriginalCurve(entry.getValue() + .secondary()) + .secondary())); + connections = restoredConnections; + tilt.smoothingAngle = Optional.empty(); + + if (transform.rotationAxis != Axis.Y) + return; + + Map transformedConnections = new HashMap<>(); + for (Entry entry : connections.entrySet()) { + BezierConnection newConnection = entry.getValue(); + newConnection.normals.replace(transform::applyWithoutOffsetUncentered); + newConnection.axes.replace(transform::applyWithoutOffsetUncentered); + + BlockPos diff = newConnection.tePositions.getSecond() + .subtract(newConnection.tePositions.getFirst()); + newConnection.tePositions.setSecond(new BlockPos(Vec3.atCenterOf(newConnection.tePositions.getFirst()) + .add(transform.applyWithoutOffsetUncentered(Vec3.atLowerCornerOf(diff))))); + + Vec3 beVec = Vec3.atLowerCornerOf(worldPosition); + Vec3 teCenterVec = beVec.add(0.5, 0.5, 0.5); + Vec3 start = newConnection.starts.getFirst(); + Vec3 startToBE = start.subtract(teCenterVec); + Vec3 endToStart = newConnection.starts.getSecond() + .subtract(start); + startToBE = transform.applyWithoutOffsetUncentered(startToBE) + .add(teCenterVec); + endToStart = transform.applyWithoutOffsetUncentered(endToStart) + .add(startToBE); + + newConnection.starts.setFirst(new TrackNodeLocation(startToBE).getLocation()); + newConnection.starts.setSecond(new TrackNodeLocation(endToStart).getLocation()); + + BlockPos newTarget = newConnection.getKey(); + transformedConnections.put(newTarget, newConnection); + } + + connections = transformedConnections; + } + + @Override + public void invalidate() { + super.invalidate(); + if (level.isClientSide) + removeFromCurveInteraction(); + } + + @Override + public void remove() { + super.remove(); + + for (BezierConnection connection : connections.values()) + manageFakeTracksAlong(connection, true); + + if (boundLocation != null && level instanceof ServerLevel) { + ServerLevel otherLevel = level.getServer() + .getLevel(boundLocation.getFirst()); + if (otherLevel == null) + return; + if (AllTags.AllBlockTags.TRACKS.matches(otherLevel.getBlockState(boundLocation.getSecond()))) + otherLevel.destroyBlock(boundLocation.getSecond(), false); + } + } + + private void registerToCurveInteraction() { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> this::registerToCurveInteractionUnsafe); + } + + private void removeFromCurveInteraction() { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> this::removeFromCurveInteractionUnsafe); + } + + @Override + public ModelData getModelData() { + if (!isTilted()) + return super.getModelData(); + return ModelData.builder() + .with(TrackBlockEntityTilt.ASCENDING_PROPERTY, tilt.smoothingAngle.get()) + .build(); + } + + @OnlyIn(Dist.CLIENT) + private void registerToCurveInteractionUnsafe() { + TrackBlockOutline.TRACKS_WITH_TURNS.get(level) + .put(worldPosition, this); + } + + @OnlyIn(Dist.CLIENT) + private void removeFromCurveInteractionUnsafe() { + TrackBlockOutline.TRACKS_WITH_TURNS.get(level) + .remove(worldPosition); + } + + public void manageFakeTracksAlong(BezierConnection bc, boolean remove) { + Map, Double> yLevels = new HashMap<>(); + BlockPos tePosition = bc.tePositions.getFirst(); + Vec3 end1 = bc.starts.getFirst() + .subtract(Vec3.atLowerCornerOf(tePosition)) + .add(0, 3 / 16f, 0); + Vec3 end2 = bc.starts.getSecond() + .subtract(Vec3.atLowerCornerOf(tePosition)) + .add(0, 3 / 16f, 0); + Vec3 axis1 = bc.axes.getFirst(); + Vec3 axis2 = bc.axes.getSecond(); + + double handleLength = bc.getHandleLength(); + + Vec3 finish1 = axis1.scale(handleLength) + .add(end1); + Vec3 finish2 = axis2.scale(handleLength) + .add(end2); + + Vec3 faceNormal1 = bc.normals.getFirst(); + Vec3 faceNormal2 = bc.normals.getSecond(); + + int segCount = bc.getSegmentCount(); + float[] lut = bc.getStepLUT(); + + for (int i = 0; i < segCount; i++) { + float t = i == segCount ? 1 : i * lut[i] / segCount; + t += 0.5f / segCount; + + Vec3 result = VecHelper.bezier(end1, end2, finish1, finish2, t); + Vec3 derivative = VecHelper.bezierDerivative(end1, end2, finish1, finish2, t) + .normalize(); + Vec3 faceNormal = + faceNormal1.equals(faceNormal2) ? faceNormal1 : VecHelper.slerp(t, faceNormal1, faceNormal2); + Vec3 normal = faceNormal.cross(derivative) + .normalize(); + Vec3 below = result.add(faceNormal.scale(-.25f)); + Vec3 rail1 = below.add(normal.scale(.05f)); + Vec3 rail2 = below.subtract(normal.scale(.05f)); + Vec3 railMiddle = rail1.add(rail2) + .scale(.5); + + for (Vec3 vec : new Vec3[] { railMiddle }) { + BlockPos pos = new BlockPos(vec); + Pair key = Pair.of(pos.getX(), pos.getZ()); + if (!yLevels.containsKey(key) || yLevels.get(key) > vec.y) + yLevels.put(key, vec.y); + } + } + + for (Entry, Double> entry : yLevels.entrySet()) { + double yValue = entry.getValue(); + int floor = Mth.floor(yValue); + BlockPos targetPos = new BlockPos(entry.getKey() + .getFirst(), floor, + entry.getKey() + .getSecond()); + targetPos = targetPos.offset(tePosition) + .above(1); + + BlockState stateAtPos = level.getBlockState(targetPos); + boolean present = AllBlocks.FAKE_TRACK.has(stateAtPos); + + if (remove) { + if (present) + level.removeBlock(targetPos, false); + continue; + } + + FluidState fluidState = stateAtPos.getFluidState(); + if (!fluidState.isEmpty() && !fluidState.isSourceOfType(Fluids.WATER)) + continue; + + if (!present && stateAtPos.getMaterial() + .isReplaceable()) + level.setBlock(targetPos, + ProperWaterloggedBlock.withWater(level, AllBlocks.FAKE_TRACK.getDefaultState(), targetPos), 3); + FakeTrackBlock.keepAlive(level, targetPos); + } + } + +} diff --git a/src/main/java/com/simibubi/create/content/trains/track/TrackBlockEntityTilt.java b/src/main/java/com/simibubi/create/content/trains/track/TrackBlockEntityTilt.java new file mode 100644 index 000000000..847929bc1 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/track/TrackBlockEntityTilt.java @@ -0,0 +1,231 @@ +package com.simibubi.create.content.trains.track; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +import com.simibubi.create.content.trains.graph.TrackNodeLocation; +import com.simibubi.create.foundation.utility.Couple; +import com.simibubi.create.foundation.utility.Pair; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.Mth; +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.Vec3; +import net.minecraftforge.client.model.data.ModelProperty; + +public class TrackBlockEntityTilt { + + public static final ModelProperty ASCENDING_PROPERTY = new ModelProperty<>(); + + public Optional smoothingAngle; + private Couple> previousSmoothingHandles; + + private TrackBlockEntity blockEntity; + + public TrackBlockEntityTilt(TrackBlockEntity blockEntity) { + this.blockEntity = blockEntity; + smoothingAngle = Optional.empty(); + } + + public void tryApplySmoothing() { + if (smoothingAngle.isPresent()) + return; + + Couple discoveredSlopes = Couple.create(null, null); + Vec3 axis = null; + + BlockState blockState = blockEntity.getBlockState(); + BlockPos worldPosition = blockEntity.getBlockPos(); + Level level = blockEntity.getLevel(); + + if (!(blockState.getBlock()instanceof ITrackBlock itb)) + return; + List axes = itb.getTrackAxes(level, worldPosition, blockState); + if (axes.size() != 1) + return; + if (axes.get(0).y != 0) + return; + if (blockEntity.boundLocation != null) + return; + + for (BezierConnection bezierConnection : blockEntity.connections.values()) { + if (bezierConnection.starts.getFirst().y == bezierConnection.starts.getSecond().y) + continue; + Vec3 normedAxis = bezierConnection.axes.getFirst() + .normalize(); + + if (axis != null) { + if (discoveredSlopes.getSecond() != null) + return; + if (normedAxis.dot(axis) > -1 + 1 / 64.0) + return; + discoveredSlopes.setSecond(bezierConnection); + continue; + } + + axis = normedAxis; + discoveredSlopes.setFirst(bezierConnection); + } + + if (discoveredSlopes.either(Objects::isNull)) + return; + if (discoveredSlopes.getFirst().starts.getSecond().y > discoveredSlopes.getSecond().starts.getSecond().y) + discoveredSlopes = discoveredSlopes.swap(); + + Couple lowStarts = discoveredSlopes.getFirst().starts; + Couple highStarts = discoveredSlopes.getSecond().starts; + Vec3 lowestPoint = lowStarts.getSecond(); + Vec3 highestPoint = highStarts.getSecond(); + + if (lowestPoint.y > lowStarts.getFirst().y) + return; + if (highestPoint.y < highStarts.getFirst().y) + return; + + blockEntity.removeInboundConnections(false); + blockEntity.connections.clear(); + TrackPropagator.onRailRemoved(level, worldPosition, blockState); + + double hDistance = discoveredSlopes.getFirst() + .getLength() + + discoveredSlopes.getSecond() + .getLength(); + Vec3 baseAxis = discoveredSlopes.getFirst().axes.getFirst(); + double baseAxisLength = baseAxis.x != 0 && baseAxis.z != 0 ? Math.sqrt(2) : 1; + double vDistance = highestPoint.y - lowestPoint.y; + double m = vDistance / (hDistance); + + Vec3 diff = highStarts.getFirst() + .subtract(lowStarts.getFirst()); + boolean flipRotation = diff.dot(new Vec3(1, 0, 2).normalize()) <= 0; + smoothingAngle = Optional.of(Math.toDegrees(Mth.atan2(m, 1)) * (flipRotation ? -1 : 1)); + + int smoothingParam = Mth.clamp((int) (m * baseAxisLength * 16), 0, 15); + + Couple smoothingResult = Couple.create(0, smoothingParam); + Vec3 raisedOffset = diff.normalize() + .add(0, Mth.clamp(m, 0, 1 - 1 / 512.0), 0) + .normalize() + .scale(baseAxisLength); + + highStarts.setFirst(lowStarts.getFirst() + .add(raisedOffset)); + + boolean first = true; + for (BezierConnection bezierConnection : discoveredSlopes) { + int smoothingToApply = smoothingResult.get(first); + + if (bezierConnection.smoothing == null) + bezierConnection.smoothing = Couple.create(0, 0); + bezierConnection.smoothing.setFirst(smoothingToApply); + bezierConnection.axes.setFirst(bezierConnection.axes.getFirst() + .add(0, (first ? 1 : -1) * -m, 0) + .normalize()); + + first = false; + BlockPos otherPosition = bezierConnection.getKey(); + BlockState otherState = level.getBlockState(otherPosition); + if (!(otherState.getBlock() instanceof TrackBlock)) + continue; + level.setBlockAndUpdate(otherPosition, otherState.setValue(TrackBlock.HAS_BE, true)); + BlockEntity otherBE = level.getBlockEntity(otherPosition); + if (otherBE instanceof TrackBlockEntity tbe) { + blockEntity.addConnection(bezierConnection); + tbe.addConnection(bezierConnection.secondary()); + } + } + } + + public void captureSmoothingHandles() { + boolean first = true; + previousSmoothingHandles = Couple.create(null, null); + for (BezierConnection bezierConnection : blockEntity.connections.values()) { + previousSmoothingHandles.set(first, Pair.of(bezierConnection.starts.getFirst(), + bezierConnection.smoothing == null ? 0 : bezierConnection.smoothing.getFirst())); + first = false; + } + } + + public void undoSmoothing() { + if (smoothingAngle.isEmpty()) + return; + if (previousSmoothingHandles == null) + return; + if (blockEntity.connections.size() == 2) + return; + + BlockState blockState = blockEntity.getBlockState(); + BlockPos worldPosition = blockEntity.getBlockPos(); + Level level = blockEntity.getLevel(); + + List validConnections = new ArrayList<>(); + for (BezierConnection bezierConnection : blockEntity.connections.values()) { + BlockPos otherPosition = bezierConnection.getKey(); + BlockEntity otherBE = level.getBlockEntity(otherPosition); + if (otherBE instanceof TrackBlockEntity tbe && tbe.connections.containsKey(worldPosition)) + validConnections.add(bezierConnection); + } + + blockEntity.removeInboundConnections(false); + TrackPropagator.onRailRemoved(level, worldPosition, blockState); + blockEntity.connections.clear(); + smoothingAngle = Optional.empty(); + + for (BezierConnection bezierConnection : validConnections) { + blockEntity.addConnection(restoreToOriginalCurve(bezierConnection)); + + BlockPos otherPosition = bezierConnection.getKey(); + BlockState otherState = level.getBlockState(otherPosition); + if (!(otherState.getBlock() instanceof TrackBlock)) + continue; + level.setBlockAndUpdate(otherPosition, otherState.setValue(TrackBlock.HAS_BE, true)); + BlockEntity otherBE = level.getBlockEntity(otherPosition); + if (otherBE instanceof TrackBlockEntity tbe) + tbe.addConnection(bezierConnection.secondary()); + } + + blockEntity.notifyUpdate(); + previousSmoothingHandles = null; + TrackPropagator.onRailAdded(level, worldPosition, blockState); + } + + public BezierConnection restoreToOriginalCurve(BezierConnection bezierConnection) { + if (bezierConnection.smoothing != null) { + bezierConnection.smoothing.setFirst(0); + if (bezierConnection.smoothing.getFirst() == 0 && bezierConnection.smoothing.getSecond() == 0) + bezierConnection.smoothing = null; + } + Vec3 raisedStart = bezierConnection.starts.getFirst(); + bezierConnection.starts.setFirst(new TrackNodeLocation(raisedStart).getLocation()); + bezierConnection.axes.setFirst(bezierConnection.axes.getFirst() + .multiply(1, 0, 1) + .normalize()); + return bezierConnection; + } + + public int getYOffsetForAxisEnd(Vec3 end) { + if (smoothingAngle.isEmpty()) + return 0; + for (BezierConnection bezierConnection : blockEntity.connections.values()) + if (compareHandles(bezierConnection.starts.getFirst(), end)) + return bezierConnection.yOffsetAt(end); + if (previousSmoothingHandles == null) + return 0; + for (Pair handle : previousSmoothingHandles) + if (handle != null && compareHandles(handle.getFirst(), end)) + return handle.getSecond(); + return 0; + } + + public static boolean compareHandles(Vec3 handle1, Vec3 handle2) { + return new TrackNodeLocation(handle1).getLocation() + .multiply(1, 0, 1) + .distanceToSqr(new TrackNodeLocation(handle2).getLocation() + .multiply(1, 0, 1)) < 1 / 512f; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackBlockItem.java b/src/main/java/com/simibubi/create/content/trains/track/TrackBlockItem.java similarity index 88% rename from src/main/java/com/simibubi/create/content/logistics/trains/track/TrackBlockItem.java rename to src/main/java/com/simibubi/create/content/trains/track/TrackBlockItem.java index a8b5929dc..898f07216 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackBlockItem.java +++ b/src/main/java/com/simibubi/create/content/trains/track/TrackBlockItem.java @@ -1,10 +1,10 @@ -package com.simibubi.create.content.logistics.trains.track; +package com.simibubi.create.content.trains.track; import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPackets; import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.content.logistics.trains.ITrackBlock; -import com.simibubi.create.content.logistics.trains.track.TrackPlacement.PlacementInfo; -import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.AllTags; +import com.simibubi.create.content.trains.track.TrackPlacement.PlacementInfo; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Pair; import com.simibubi.create.foundation.utility.VecHelper; @@ -59,13 +59,20 @@ public class TrackBlockItem extends BlockItem { Vec3 lookAngle = player.getLookAngle(); if (!isFoil(stack)) { - if (state.getBlock()instanceof TrackBlock track && track.getTrackAxes(level, pos, state) + if (state.getBlock() instanceof TrackBlock track && track.getTrackAxes(level, pos, state) .size() > 1) { if (!level.isClientSide) player.displayClientMessage(Lang.translateDirect("track.junction_start") .withStyle(ChatFormatting.RED), true); return InteractionResult.SUCCESS; } + + if (level.getBlockEntity(pos) instanceof TrackBlockEntity tbe && tbe.isTilted()) { + if (!level.isClientSide) + player.displayClientMessage(Lang.translateDirect("track.turn_start") + .withStyle(ChatFormatting.RED), true); + return InteractionResult.SUCCESS; + } if (select(level, pos, lookAngle, stack)) { level.playSound(null, pos, SoundEvents.ITEM_FRAME_ADD_ITEM, SoundSource.BLOCKS, 0.75f, 1); @@ -111,7 +118,7 @@ public class TrackBlockItem extends BlockItem { return InteractionResult.SUCCESS; stack = player.getMainHandItem(); - if (AllBlocks.TRACK.isIn(stack)) { + if (AllTags.AllBlockTags.TRACKS.matches(stack)) { stack.setTag(null); player.setItemInHand(pContext.getHand(), stack); } @@ -154,10 +161,10 @@ public class TrackBlockItem extends BlockItem { @OnlyIn(Dist.CLIENT) public static void sendExtenderPacket(PlayerInteractEvent.RightClickBlock event) { ItemStack stack = event.getItemStack(); - if (!AllBlocks.TRACK.isIn(stack) || !stack.hasTag()) + if (!AllTags.AllBlockTags.TRACKS.matches(stack) || !stack.hasTag()) return; if (Minecraft.getInstance().options.keySprint.isDown()) - AllPackets.channel + AllPackets.getChannel() .sendToServer(new PlaceExtendedCurvePacket(event.getHand() == InteractionHand.MAIN_HAND, true)); } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackBlockOutline.java b/src/main/java/com/simibubi/create/content/trains/track/TrackBlockOutline.java similarity index 88% rename from src/main/java/com/simibubi/create/content/logistics/trains/track/TrackBlockOutline.java rename to src/main/java/com/simibubi/create/content/trains/track/TrackBlockOutline.java index b30b26895..cf50be35c 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackBlockOutline.java +++ b/src/main/java/com/simibubi/create/content/trains/track/TrackBlockOutline.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.track; +package com.simibubi.create.content.trains.track; import java.util.HashMap; import java.util.Map; @@ -8,9 +8,8 @@ import java.util.function.Consumer; import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; -import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; -import com.simibubi.create.content.logistics.trains.BezierConnection; +import com.simibubi.create.AllTags; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.Iterate; @@ -44,7 +43,7 @@ import net.minecraftforge.fml.common.Mod.EventBusSubscriber; @EventBusSubscriber(Dist.CLIENT) public class TrackBlockOutline { - public static WorldAttached> TRACKS_WITH_TURNS = + public static WorldAttached> TRACKS_WITH_TURNS = new WorldAttached<>(w -> new HashMap<>()); public static BezierPointSelection result; @@ -66,10 +65,10 @@ public class TrackBlockOutline { AttributeInstance range = player.getAttribute(ForgeMod.REACH_DISTANCE.get()); Vec3 target = RaycastHelper.getTraceTarget(player, Math.min(maxRange, range.getValue()) + 1, origin); - Map turns = TRACKS_WITH_TURNS.get(mc.level); + Map turns = TRACKS_WITH_TURNS.get(mc.level); - for (TrackTileEntity te : turns.values()) { - for (BezierConnection bc : te.connections.values()) { + for (TrackBlockEntity be : turns.values()) { + for (BezierConnection bc : be.connections.values()) { if (!bc.isPrimary()) continue; @@ -125,7 +124,7 @@ public class TrackBlockOutline { .distanceToSqr(0, 0.25f, 0); BezierTrackPointLocation location = new BezierTrackPointLocation(bc.getKey(), i); - result = new BezierPointSelection(te, location, anchor, angles, diff.normalize()); + result = new BezierPointSelection(be, location, anchor, angles, diff.normalize()); } if (bestSegment != -1) @@ -142,7 +141,7 @@ public class TrackBlockOutline { } } - public static void drawCurveSelection(PoseStack ms, MultiBufferSource buffer) { + public static void drawCurveSelection(PoseStack ms, MultiBufferSource buffer, Vec3 camera) { Minecraft mc = Minecraft.getInstance(); if (mc.options.hideGui || mc.gameMode.getPlayerMode() == GameType.SPECTATOR) return; @@ -152,7 +151,8 @@ public class TrackBlockOutline { return; VertexConsumer vb = buffer.getBuffer(RenderType.lines()); - Vec3 vec = result.vec(); + Vec3 vec = result.vec() + .subtract(camera); Vec3 angles = result.angles(); TransformStack.cast(ms) .pushPose() @@ -161,7 +161,7 @@ public class TrackBlockOutline { .rotateXRadians(angles.x) .translate(-.5, -.125f, -.5); - boolean holdingTrack = AllBlocks.TRACK.isIn(Minecraft.getInstance().player.getMainHandItem()); + boolean holdingTrack = AllTags.AllBlockTags.TRACKS.matches(Minecraft.getInstance().player.getMainHandItem()); renderShape(AllShapes.TRACK_ORTHO.get(Direction.SOUTH), ms, vb, holdingTrack ? false : null); ms.popPose(); } @@ -189,18 +189,20 @@ public class TrackBlockOutline { ms.pushPose(); ms.translate(pos.getX() - camPos.x, pos.getY() - camPos.y, pos.getZ() - camPos.z); - boolean holdingTrack = AllBlocks.TRACK.isIn(Minecraft.getInstance().player.getMainHandItem()); + boolean holdingTrack = AllTags.AllBlockTags.TRACKS.matches(Minecraft.getInstance().player.getMainHandItem()); TrackShape shape = blockstate.getValue(TrackBlock.SHAPE); - boolean isJunction = shape.isJunction(); + boolean canConnectFrom = !shape.isJunction() + && !(mc.level.getBlockEntity(pos)instanceof TrackBlockEntity tbe && tbe.isTilted()); + walkShapes(shape, TransformStack.cast(ms), s -> { - renderShape(s, ms, vb, holdingTrack ? !isJunction : null); + renderShape(s, ms, vb, holdingTrack ? canConnectFrom : null); event.setCanceled(true); }); ms.popPose(); } - private static void renderShape(VoxelShape s, PoseStack ms, VertexConsumer vb, Boolean valid) { + public static void renderShape(VoxelShape s, PoseStack ms, VertexConsumer vb, Boolean valid) { PoseStack.Pose transform = ms.last(); s.forAllEdges((x1, y1, z1, x2, y2, z2) -> { float xDiff = (float) (x2 - x1); @@ -288,8 +290,8 @@ public class TrackBlockOutline { renderer.accept(LONG_ORTHO); } - public static record BezierPointSelection(TrackTileEntity te, BezierTrackPointLocation loc, Vec3 vec, Vec3 angles, - Vec3 direction) { + public static record BezierPointSelection(TrackBlockEntity blockEntity, BezierTrackPointLocation loc, Vec3 vec, + Vec3 angles, Vec3 direction) { } } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackBlockStateGenerator.java b/src/main/java/com/simibubi/create/content/trains/track/TrackBlockStateGenerator.java similarity index 94% rename from src/main/java/com/simibubi/create/content/logistics/trains/track/TrackBlockStateGenerator.java rename to src/main/java/com/simibubi/create/content/trains/track/TrackBlockStateGenerator.java index a14da5a73..81e1931c1 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackBlockStateGenerator.java +++ b/src/main/java/com/simibubi/create/content/trains/track/TrackBlockStateGenerator.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.track; +package com.simibubi.create.content.trains.track; import com.simibubi.create.Create; import com.simibubi.create.foundation.data.SpecialBlockStateGen; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackInstance.java b/src/main/java/com/simibubi/create/content/trains/track/TrackInstance.java similarity index 86% rename from src/main/java/com/simibubi/create/content/logistics/trains/track/TrackInstance.java rename to src/main/java/com/simibubi/create/content/trains/track/TrackInstance.java index 7bb371ede..fd785c560 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackInstance.java +++ b/src/main/java/com/simibubi/create/content/trains/track/TrackInstance.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.track; +package com.simibubi.create.content.trains.track; import java.util.ArrayList; import java.util.List; @@ -16,21 +16,20 @@ import com.jozufozu.flywheel.util.box.ImmutableBox; import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack.Pose; -import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.logistics.trains.BezierConnection; -import com.simibubi.create.content.logistics.trains.BezierConnection.GirderAngles; -import com.simibubi.create.content.logistics.trains.BezierConnection.SegmentAngles; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.content.trains.track.BezierConnection.GirderAngles; +import com.simibubi.create.content.trains.track.BezierConnection.SegmentAngles; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Iterate; import net.minecraft.client.renderer.RenderType; import net.minecraft.core.BlockPos; -public class TrackInstance extends BlockEntityInstance { +public class TrackInstance extends BlockEntityInstance { private List instances; - public TrackInstance(MaterialManager materialManager, TrackTileEntity track) { + public TrackInstance(MaterialManager materialManager, TrackBlockEntity track) { super(materialManager, track); update(); @@ -38,7 +37,7 @@ public class TrackInstance extends BlockEntityInstance { @Override public void update() { - if (blockEntity.connections.isEmpty()) + if (blockEntity.connections.isEmpty()) return; remove(); @@ -97,9 +96,7 @@ public class TrackInstance extends BlockEntityInstance { PoseStack pose = new PoseStack(); TransformStack.cast(pose) - .translate(getInstancePosition()) - .nudge((int) bc.tePositions.getFirst() - .asLong()); + .translate(getInstancePosition()); var mat = materialManager.cutout(RenderType.cutoutMipped()) .material(Materials.TRANSFORMED); @@ -112,11 +109,13 @@ public class TrackInstance extends BlockEntityInstance { leftLightPos = new BlockPos[segCount]; rightLightPos = new BlockPos[segCount]; - mat.getModel(AllBlockPartials.TRACK_TIE) + TrackMaterial.TrackModelHolder modelHolder = bc.getMaterial().getModelHolder(); + + mat.getModel(modelHolder.tie()) .createInstances(ties); - mat.getModel(AllBlockPartials.TRACK_SEGMENT_LEFT) + mat.getModel(modelHolder.segment_left()) .createInstances(left); - mat.getModel(AllBlockPartials.TRACK_SEGMENT_RIGHT) + mat.getModel(modelHolder.segment_right()) .createInstances(right); SegmentAngles[] segments = bc.getBakedSegments(); @@ -184,9 +183,9 @@ public class TrackInstance extends BlockEntityInstance { beams = Couple.create(() -> new ModelData[segCount]); beamCaps = Couple.create(() -> Couple.create(() -> new ModelData[segCount])); lightPos = new BlockPos[segCount]; - beams.forEach(mat.getModel(AllBlockPartials.GIRDER_SEGMENT_MIDDLE)::createInstances); - beamCaps.forEachWithContext((c, top) -> c.forEach(mat.getModel(top ? AllBlockPartials.GIRDER_SEGMENT_TOP - : AllBlockPartials.GIRDER_SEGMENT_BOTTOM)::createInstances)); + beams.forEach(mat.getModel(AllPartialModels.GIRDER_SEGMENT_MIDDLE)::createInstances); + beamCaps.forEachWithContext((c, top) -> c.forEach(mat.getModel(top ? AllPartialModels.GIRDER_SEGMENT_TOP + : AllPartialModels.GIRDER_SEGMENT_BOTTOM)::createInstances)); GirderAngles[] bakedGirders = bc.getBakedGirders(); for (int i = 1; i < bakedGirders.length; i++) { diff --git a/src/main/java/com/simibubi/create/content/trains/track/TrackMaterial.java b/src/main/java/com/simibubi/create/content/trains/track/TrackMaterial.java new file mode 100644 index 000000000..0c8a3a10c --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/track/TrackMaterial.java @@ -0,0 +1,170 @@ +package com.simibubi.create.content.trains.track; + +import static com.simibubi.create.content.trains.track.TrackMaterialFactory.make; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Supplier; + +import org.jetbrains.annotations.Nullable; + +import com.jozufozu.flywheel.core.PartialModel; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPartialModels; +import com.simibubi.create.Create; +import com.tterrag.registrate.util.nullness.NonNullSupplier; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.fml.DistExecutor; + +public class TrackMaterial { + public static final Map ALL = new HashMap<>(); + + public static final TrackMaterial ANDESITE = make(Create.asResource("andesite")) + .lang("Andesite") + .block(NonNullSupplier.lazy(() -> AllBlocks.TRACK)) + .particle(Create.asResource("block/palettes/stone_types/polished/andesite_cut_polished")) + .defaultModels() + .build(); + + public final ResourceLocation id; + public final String langName; + public final NonNullSupplier> trackBlock; + public final Ingredient sleeperIngredient; + public final Ingredient railsIngredient; + public final ResourceLocation particle; + public final TrackType trackType; + + @Nullable + private final TrackMaterial.TrackType.TrackBlockFactory customFactory; + + @OnlyIn(Dist.CLIENT) + protected TrackModelHolder modelHolder; + + @OnlyIn(Dist.CLIENT) + public TrackModelHolder getModelHolder() { + return modelHolder; + } + + public TrackMaterial(ResourceLocation id, String langName, NonNullSupplier> trackBlock, + ResourceLocation particle, Ingredient sleeperIngredient, Ingredient railsIngredient, + TrackType trackType, Supplier> modelHolder) { + this(id, langName, trackBlock, particle, sleeperIngredient, railsIngredient, trackType, modelHolder, null); + } + + public TrackMaterial(ResourceLocation id, String langName, NonNullSupplier> trackBlock, + ResourceLocation particle, Ingredient sleeperIngredient, Ingredient railsIngredient, + TrackType trackType, Supplier> modelHolder, + @Nullable TrackType.TrackBlockFactory customFactory) { + this.id = id; + this.langName = langName; + this.trackBlock = trackBlock; + this.sleeperIngredient = sleeperIngredient; + this.railsIngredient = railsIngredient; + this.particle = particle; + this.trackType = trackType; + this.customFactory = customFactory; + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> this.modelHolder = modelHolder.get().get()); + ALL.put(this.id, this); + } + + public NonNullSupplier getBlockSupplier() { + return this.trackBlock.get(); + } + + public TrackBlock getBlock() { + return getBlockSupplier().get(); + } + + public ItemStack asStack() { + return asStack(1); + } + + public ItemStack asStack(int count) { + return new ItemStack(getBlock(), count); + } + + public TrackBlock createBlock(BlockBehaviour.Properties properties) { + return (this.customFactory != null ? this.customFactory : this.trackType.factory) + .create(properties, this); + } + + public boolean isFromMod(String modId) { + return this.id.getNamespace().equals(modId); + } + + public static List allFromMod(String modid) { + return ALL.values().stream().filter(tm -> tm.isFromMod(modid)).toList(); + } + + public static List> allBlocksFromMod(String modid) { + List> list = new ArrayList<>(); + for (TrackMaterial material : allFromMod(modid)) { + list.add(material.getBlockSupplier()); + } + return list; + } + + public static List> allBlocks() { + List> list = new ArrayList<>(); + for (TrackMaterial material : ALL.values()) { + list.add(material.getBlockSupplier()); + } + return list; + } + + public String resourceName() { + return this.id.getPath(); + } + + public static TrackMaterial deserialize(String serializedName) { + if (serializedName.isBlank()) // Data migrating from 0.5 + return ANDESITE; + + ResourceLocation id = ResourceLocation.tryParse(serializedName); + if (ALL.containsKey(id)) + return ALL.get(id); + + Create.LOGGER.error("Failed to locate serialized track material: " + serializedName); + return ANDESITE; + } + + public static class TrackType { + @FunctionalInterface + public interface TrackBlockFactory { + TrackBlock create(BlockBehaviour.Properties properties, TrackMaterial material); + } + + public static final TrackType STANDARD = new TrackType(Create.asResource("standard"), TrackBlock::new); + + public final ResourceLocation id; + protected final TrackBlockFactory factory; + + public TrackType(ResourceLocation id, TrackBlockFactory factory) { + this.id = id; + this.factory = factory; + } + } + + public static TrackMaterial fromItem(Item item) { + if (item instanceof BlockItem blockItem && blockItem.getBlock() instanceof ITrackBlock trackBlock) + return trackBlock.getMaterial(); + return TrackMaterial.ANDESITE; + } + + @OnlyIn(Dist.CLIENT) + public record TrackModelHolder(PartialModel tie, PartialModel segment_left, PartialModel segment_right) { + static final TrackModelHolder DEFAULT = new TrackModelHolder(AllPartialModels.TRACK_TIE, + AllPartialModels.TRACK_SEGMENT_LEFT, AllPartialModels.TRACK_SEGMENT_RIGHT); + } +} diff --git a/src/main/java/com/simibubi/create/content/trains/track/TrackMaterialFactory.java b/src/main/java/com/simibubi/create/content/trains/track/TrackMaterialFactory.java new file mode 100644 index 000000000..67e048caa --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/track/TrackMaterialFactory.java @@ -0,0 +1,141 @@ +package com.simibubi.create.content.trains.track; + +import java.util.function.Supplier; +import java.util.stream.Stream; + +import org.jetbrains.annotations.Nullable; + +import com.jozufozu.flywheel.core.PartialModel; +import com.simibubi.create.AllTags; +import com.tterrag.registrate.util.nullness.NonNullSupplier; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.level.ItemLike; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.fml.DistExecutor; + +public class TrackMaterialFactory { + private final ResourceLocation id; + private String langName; + private NonNullSupplier> trackBlock; + private Ingredient sleeperIngredient = Ingredient.EMPTY; + private Ingredient railsIngredient = Ingredient.fromValues(Stream.of(new Ingredient.TagValue(AllTags.forgeItemTag("nuggets/iron")), new Ingredient.TagValue(AllTags.forgeItemTag("nuggets/zinc")))); + private ResourceLocation particle; + private TrackMaterial.TrackType trackType = TrackMaterial.TrackType.STANDARD; + + @Nullable + private TrackMaterial.TrackType.TrackBlockFactory customFactory = null; + + @OnlyIn(Dist.CLIENT) + private TrackMaterial.TrackModelHolder modelHolder; + @OnlyIn(Dist.CLIENT) + private PartialModel tieModel; + @OnlyIn(Dist.CLIENT) + private PartialModel leftSegmentModel; + @OnlyIn(Dist.CLIENT) + private PartialModel rightSegmentModel; + + public TrackMaterialFactory(ResourceLocation id) { + this.id = id; + } + + public static TrackMaterialFactory make(ResourceLocation id) { // Convenience function for static import + return new TrackMaterialFactory(id); + } + + public TrackMaterialFactory lang(String langName) { + this.langName = langName; + return this; + } + + public TrackMaterialFactory block(NonNullSupplier> trackBlock) { + this.trackBlock = trackBlock; + return this; + } + + public TrackMaterialFactory defaultModels() { // was setBuiltin + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> this.modelHolder = TrackMaterial.TrackModelHolder.DEFAULT); + return this; + } + + public TrackMaterialFactory sleeper(Ingredient sleeperIngredient) { + this.sleeperIngredient = sleeperIngredient; + return this; + } + + public TrackMaterialFactory sleeper(ItemLike... items) { + this.sleeperIngredient = Ingredient.of(items); + return this; + } + + public TrackMaterialFactory rails(Ingredient railsIngredient) { + this.railsIngredient = railsIngredient; + return this; + } + + public TrackMaterialFactory rails(ItemLike... items) { + this.railsIngredient = Ingredient.of(items); + return this; + } + + public TrackMaterialFactory noRecipeGen() { + this.railsIngredient = Ingredient.EMPTY; + this.sleeperIngredient = Ingredient.EMPTY; + return this; + } + + public TrackMaterialFactory particle(ResourceLocation particle) { + this.particle = particle; + return this; + } + + public TrackMaterialFactory trackType(TrackMaterial.TrackType trackType) { + this.trackType = trackType; + return this; + } + + public TrackMaterialFactory standardModels() { // was defaultModels + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { + String namespace = id.getNamespace(); + String prefix = "block/track/" + id.getPath() + "/"; + tieModel = new PartialModel(new ResourceLocation(namespace, prefix + "tie")); + leftSegmentModel = new PartialModel(new ResourceLocation(namespace, prefix + "segment_left")); + rightSegmentModel = new PartialModel(new ResourceLocation(namespace, prefix + "segment_right")); + }); + return this; + } + + public TrackMaterialFactory customModels(Supplier> tieModel, Supplier> leftSegmentModel, Supplier> rightSegmentModel) { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { + this.tieModel = tieModel.get().get(); + this.leftSegmentModel = leftSegmentModel.get().get(); + this.rightSegmentModel = rightSegmentModel.get().get(); + }); + return this; + } + + public TrackMaterialFactory customBlockFactory(TrackMaterial.TrackType.TrackBlockFactory factory) { + this.customFactory = factory; + return this; + } + + public TrackMaterial build() { + assert trackBlock != null; + assert langName != null; + assert particle != null; + assert trackType != null; + assert sleeperIngredient != null; + assert railsIngredient != null; + assert id != null; + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { + assert modelHolder != null; + if (tieModel != null || leftSegmentModel != null || rightSegmentModel != null) { + assert tieModel != null && leftSegmentModel != null && rightSegmentModel != null; + modelHolder = new TrackMaterial.TrackModelHolder(tieModel, leftSegmentModel, rightSegmentModel); + } + }); + return new TrackMaterial(id, langName, trackBlock, particle, sleeperIngredient, railsIngredient, trackType, () -> () -> modelHolder, customFactory); + } +} diff --git a/src/main/java/com/simibubi/create/content/trains/track/TrackModel.java b/src/main/java/com/simibubi/create/content/trains/track/TrackModel.java new file mode 100644 index 000000000..308998258 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/track/TrackModel.java @@ -0,0 +1,82 @@ +package com.simibubi.create.content.trains.track; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.UnaryOperator; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.foundation.model.BakedQuadHelper; +import com.simibubi.create.foundation.utility.VecHelper; + +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.core.Direction.Axis; +import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.client.model.BakedModelWrapper; +import net.minecraftforge.client.model.data.ModelData; + +public class TrackModel extends BakedModelWrapper { + + public TrackModel(BakedModel originalModel) { + super(originalModel); + } + + @Override + public @NotNull List getQuads(@Nullable BlockState state, @Nullable Direction side, + @NotNull RandomSource rand, @NotNull ModelData extraData, @Nullable RenderType renderType) { + List templateQuads = super.getQuads(state, side, rand, extraData, renderType); + if (templateQuads.isEmpty()) + return templateQuads; + if (!extraData.has(TrackBlockEntityTilt.ASCENDING_PROPERTY)) + return templateQuads; + + double angleIn = extraData.get(TrackBlockEntityTilt.ASCENDING_PROPERTY); + double angle = Math.abs(angleIn); + boolean flip = angleIn < 0; + + TrackShape trackShape = state.getValue(TrackBlock.SHAPE); + double hAngle = switch (trackShape) { + case XO -> 0; + case PD -> 45; + case ZO -> 90; + case ND -> 135; + default -> 0; + }; + + Vec3 verticalOffset = new Vec3(0, -0.25, 0); + Vec3 diagonalRotationPoint = + (trackShape == TrackShape.ND || trackShape == TrackShape.PD) ? new Vec3((Mth.SQRT_OF_TWO - 1) / 2, 0, 0) + : Vec3.ZERO; + + UnaryOperator transform = v -> { + v = v.add(verticalOffset); + v = VecHelper.rotateCentered(v, hAngle, Axis.Y); + v = v.add(diagonalRotationPoint); + v = VecHelper.rotate(v, angle, Axis.Z); + v = v.subtract(diagonalRotationPoint); + v = VecHelper.rotateCentered(v, -hAngle + (flip ? 180 : 0), Axis.Y); + v = v.subtract(verticalOffset); + return v; + }; + + int size = templateQuads.size(); + List quads = new ArrayList<>(); + for (int i = 0; i < size; i++) { + BakedQuad quad = BakedQuadHelper.clone(templateQuads.get(i)); + int[] vertexData = quad.getVertices(); + for (int j = 0; j < 4; j++) + BakedQuadHelper.setXYZ(vertexData, j, transform.apply(BakedQuadHelper.getXYZ(vertexData, j))); + quads.add(quad); + } + + return quads; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackPaver.java b/src/main/java/com/simibubi/create/content/trains/track/TrackPaver.java similarity index 97% rename from src/main/java/com/simibubi/create/content/logistics/trains/track/TrackPaver.java rename to src/main/java/com/simibubi/create/content/trains/track/TrackPaver.java index 9c70d7ca6..cf1e25569 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackPaver.java +++ b/src/main/java/com/simibubi/create/content/trains/track/TrackPaver.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.track; +package com.simibubi.create.content.trains.track; import java.util.HashMap; import java.util.HashSet; @@ -7,8 +7,7 @@ import java.util.Map.Entry; import java.util.Set; import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.curiosities.girder.GirderBlock; -import com.simibubi.create.content.logistics.trains.BezierConnection; +import com.simibubi.create.content.decoration.girder.GirderBlock; import com.simibubi.create.foundation.block.ProperWaterloggedBlock; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Pair; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackPlacement.java b/src/main/java/com/simibubi/create/content/trains/track/TrackPlacement.java similarity index 88% rename from src/main/java/com/simibubi/create/content/logistics/trains/track/TrackPlacement.java rename to src/main/java/com/simibubi/create/content/trains/track/TrackPlacement.java index 5ba52a756..7c73f9da3 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackPlacement.java +++ b/src/main/java/com/simibubi/create/content/trains/track/TrackPlacement.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.track; +package com.simibubi.create.content.trains.track; import java.util.ArrayList; import java.util.Collection; @@ -7,15 +7,11 @@ import java.util.List; import java.util.Set; import com.jozufozu.flywheel.util.Color; -import com.simibubi.create.AllBlocks; import com.simibubi.create.AllSpecialTextures; +import com.simibubi.create.AllTags; import com.simibubi.create.CreateClient; -import com.simibubi.create.content.curiosities.tools.BlueprintOverlayRenderer; -import com.simibubi.create.content.logistics.trains.BezierConnection; -import com.simibubi.create.content.logistics.trains.ITrackBlock; -import com.simibubi.create.foundation.advancement.AllAdvancements; +import com.simibubi.create.content.equipment.blueprint.BlueprintOverlayRenderer; import com.simibubi.create.foundation.block.ProperWaterloggedBlock; -import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Iterate; @@ -24,6 +20,7 @@ import com.simibubi.create.foundation.utility.Pair; import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.animation.LerpedFloat; import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; +import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; @@ -47,6 +44,7 @@ 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.properties.Property; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.HitResult.Type; @@ -58,6 +56,11 @@ import net.minecraftforge.items.ItemHandlerHelper; public class TrackPlacement { public static class PlacementInfo { + + public PlacementInfo(TrackMaterial material) { + this.trackMaterial = material; + } + BezierConnection curve = null; boolean valid = false; int end1Extent = 0; @@ -69,6 +72,7 @@ public class TrackPlacement { public int requiredPavement = 0; public boolean hasRequiredPavement = false; + public final TrackMaterial trackMaterial; // for visualisation Vec3 end1; @@ -98,17 +102,19 @@ public class TrackPlacement { static int hoveringAngle; static ItemStack lastItem; + static int extraTipWarmup; + public static PlacementInfo tryConnect(Level level, Player player, BlockPos pos2, BlockState state2, ItemStack stack, boolean girder, boolean maximiseTurn) { Vec3 lookVec = player.getLookAngle(); int lookAngle = (int) (22.5 + AngleHelper.deg(Mth.atan2(lookVec.z, lookVec.x)) % 360) / 8; - int maxLength = AllConfigs.SERVER.trains.maxTrackPlacementLength.get(); + int maxLength = AllConfigs.server().trains.maxTrackPlacementLength.get(); if (level.isClientSide && cached != null && pos2.equals(hoveringPos) && stack.equals(lastItem) && hoveringMaxed == maximiseTurn && lookAngle == hoveringAngle) return cached; - PlacementInfo info = new PlacementInfo(); + PlacementInfo info = new PlacementInfo(TrackMaterial.fromItem(stack.getItem())); hoveringMaxed = maximiseTurn; hoveringAngle = lookAngle; hoveringPos = pos2; @@ -148,8 +154,10 @@ public class TrackPlacement { if (pos1.distSqr(pos2) > maxLength * maxLength) return info.withMessage("too_far") .tooJumbly(); - if (!state1.hasProperty(TrackBlock.HAS_TE)) + if (!state1.hasProperty(TrackBlock.HAS_BE)) return info.withMessage("original_missing"); + if (level.getBlockEntity(pos2) instanceof TrackBlockEntity tbe && tbe.isTilted()) + return info.withMessage("turn_start"); if (axis1.dot(end2.subtract(end1)) < 0) { axis1 = axis1.scale(-1); @@ -192,7 +200,7 @@ public class TrackPlacement { BlockPos targetPos2 = pos2.offset(offset2.x, offset2.y, offset2.z); info.curve = new BezierConnection(Couple.create(targetPos1, targetPos2), Couple.create(end1.add(offset1), end2.add(offset2)), Couple.create(normedAxis1, normedAxis2), - Couple.create(normal1, normal2), true, girder); + Couple.create(normal1, normal2), true, girder, TrackMaterial.fromItem(stack.getItem())); } // S curve or Straight @@ -217,7 +225,7 @@ public class TrackPlacement { info.end1Extent = (int) Math.round((dist + 1) / axis1.length()); } else { - if (!Mth.equal(ascend, 0)) + if (!Mth.equal(ascend, 0) || normedAxis1.y != 0) return info.withMessage("ascending_s_curve"); double targetT = u <= 1 ? 3 : u * 2; @@ -281,10 +289,10 @@ public class TrackPlacement { if (skipCurve && !Mth.equal(ascend, 0)) { int hDistance = info.end1Extent; if (axis1.y == 0 || !Mth.equal(absAscend + 1, dist / axis1.length())) { - + if (axis1.y != 0 && axis1.y == -axis2.y) return info.withMessage("ascending_s_curve"); - + info.end1Extent = 0; double minHDistance = Math.max(absAscend < 4 ? absAscend * 4 : absAscend * 3, 6) / axis1.length(); if (hDistance < minHDistance) @@ -352,7 +360,7 @@ public class TrackPlacement { info.curve = skipCurve ? null : new BezierConnection(Couple.create(targetPos1, targetPos2), Couple.create(end1.add(offset1), end2.add(offset2)), Couple.create(normedAxis1, normedAxis2), - Couple.create(normal1, normal2), true, girder); + Couple.create(normal1, normal2), true, girder, TrackMaterial.fromItem(stack.getItem())); info.valid = true; @@ -397,7 +405,7 @@ public class TrackPlacement { continue; ItemStack stackInSlot = (offhand ? inv.offhand : inv.items).get(i); - boolean isTrack = AllBlocks.TRACK.isIn(stackInSlot); + boolean isTrack = AllTags.AllBlockTags.TRACKS.matches(stackInSlot) && stackInSlot.is(stack.getItem()); if (!isTrack && (!shouldPave || offhandItem.getItem() != stackInSlot.getItem())) continue; if (isTrack ? foundTracks >= tracks : foundPavement >= pavement) @@ -445,10 +453,6 @@ public class TrackPlacement { BlockItem paveItem = (BlockItem) offhandItem.getItem(); paveTracks(level, info, paveItem, false); } - - if (info.curve != null && info.curve.getLength() > 29) - AllAdvancements.LONG_BEND.awardTo(player); - return placeTracks(level, info, state1, state2, targetPos1, targetPos2, false); } @@ -474,6 +478,18 @@ public class TrackPlacement { info.requiredPavement += TrackPaver.paveCurve(level, info.curve, block, simulate, visited); } + private static BlockState copyProperties(BlockState from, BlockState onto) { + for (Property property : onto.getProperties()) { + if (from.hasProperty(property)) + onto = onto.setValue(property, from.getValue(property)); + } + return onto; + } + + private static BlockState copyProperties(BlockState from, BlockState onto, boolean keepFrom) { + return keepFrom ? from : copyProperties(from, onto); + } + private static PlacementInfo placeTracks(Level level, PlacementInfo info, BlockState state1, BlockState state2, BlockPos targetPos1, BlockPos targetPos2, boolean simulate) { info.requiredTracks = 0; @@ -483,8 +499,8 @@ public class TrackPlacement { Vec3 axis = first ? info.axis1 : info.axis2; BlockPos pos = first ? info.pos1 : info.pos2; BlockState state = first ? state1 : state2; - if (state.hasProperty(TrackBlock.HAS_TE) && !simulate) - state = state.setValue(TrackBlock.HAS_TE, false); + if (state.hasProperty(TrackBlock.HAS_BE) && !simulate) + state = state.setValue(TrackBlock.HAS_BE, false); switch (state.getValue(TrackBlock.SHAPE)) { case TE, TW: @@ -501,7 +517,8 @@ public class TrackPlacement { Vec3 offset = axis.scale(i); BlockPos offsetPos = pos.offset(offset.x, offset.y, offset.z); BlockState stateAtPos = level.getBlockState(offsetPos); - BlockState toPlace = state; + // copy over all shared properties from the shaped state to the correct track material block + BlockState toPlace = copyProperties(state, info.trackMaterial.getBlock().defaultBlockState()); boolean canPlace = stateAtPos.getMaterial() .isReplaceable(); @@ -524,28 +541,29 @@ public class TrackPlacement { return info; if (!simulate) { + BlockState onto = info.trackMaterial.getBlock().defaultBlockState(); BlockState stateAtPos = level.getBlockState(targetPos1); level.setBlock(targetPos1, ProperWaterloggedBlock.withWater(level, - (stateAtPos.getBlock() == state1.getBlock() ? stateAtPos : state1).setValue(TrackBlock.HAS_TE, true), - targetPos1), 3); + (AllTags.AllBlockTags.TRACKS.matches(stateAtPos) ? stateAtPos : copyProperties(state1, onto)) + .setValue(TrackBlock.HAS_BE, true), targetPos1), 3); stateAtPos = level.getBlockState(targetPos2); level.setBlock(targetPos2, ProperWaterloggedBlock.withWater(level, - (stateAtPos.getBlock() == state2.getBlock() ? stateAtPos : state2).setValue(TrackBlock.HAS_TE, true), - targetPos2), 3); + (AllTags.AllBlockTags.TRACKS.matches(stateAtPos) ? stateAtPos : copyProperties(state2, onto)) + .setValue(TrackBlock.HAS_BE, true), targetPos2), 3); } BlockEntity te1 = level.getBlockEntity(targetPos1); BlockEntity te2 = level.getBlockEntity(targetPos2); int requiredTracksForTurn = (info.curve.getSegmentCount() + 1) / 2; - if (!(te1 instanceof TrackTileEntity) || !(te2 instanceof TrackTileEntity)) { + if (!(te1 instanceof TrackBlockEntity) || !(te2 instanceof TrackBlockEntity)) { info.requiredTracks += requiredTracksForTurn; return info; } - TrackTileEntity tte1 = (TrackTileEntity) te1; - TrackTileEntity tte2 = (TrackTileEntity) te2; + TrackBlockEntity tte1 = (TrackBlockEntity) te1; + TrackBlockEntity tte2 = (TrackBlockEntity) te2; if (!tte1.getConnections() .containsKey(tte2.getBlockPos())) @@ -556,6 +574,8 @@ public class TrackPlacement { tte1.addConnection(info.curve); tte2.addConnection(info.curve.secondary()); + tte1.tilt.tryApplySmoothing(); + tte2.tilt.tryApplySmoothing(); return info; } @@ -572,6 +592,8 @@ public class TrackPlacement { LocalPlayer player = Minecraft.getInstance().player; ItemStack stack = player.getMainHandItem(); HitResult hitResult = Minecraft.getInstance().hitResult; + int restoreWarmup = extraTipWarmup; + extraTipWarmup = 0; if (hitResult == null) return; @@ -579,10 +601,10 @@ public class TrackPlacement { return; InteractionHand hand = InteractionHand.MAIN_HAND; - if (!AllBlocks.TRACK.isIn(stack)) { + if (!AllTags.AllBlockTags.TRACKS.matches(stack)) { stack = player.getOffhandItem(); hand = InteractionHand.OFF_HAND; - if (!AllBlocks.TRACK.isIn(stack)) + if (!AllTags.AllBlockTags.TRACKS.matches(stack)) return; } @@ -605,8 +627,14 @@ public class TrackPlacement { if (!(hitState.getBlock() instanceof TrackBlock)) return; + extraTipWarmup = restoreWarmup; boolean maxTurns = Minecraft.getInstance().options.keySprint.isDown(); PlacementInfo info = tryConnect(level, player, pos, hitState, stack, false, maxTurns); + if (extraTipWarmup < 20) + extraTipWarmup++; + if (!info.valid || !hoveringMaxed && (info.end1Extent == 0 || info.end2Extent == 0)) + extraTipWarmup = 0; + if (!player.isCreative() && (info.valid || !info.hasRequiredTracks || !info.hasRequiredPavement)) BlueprintOverlayRenderer.displayTrackRequirements(info, player.getOffhandItem()); @@ -621,7 +649,7 @@ public class TrackPlacement { if (bhr.getDirection() == Direction.UP) { Vec3 lookVec = player.getLookAngle(); int lookAngle = (int) (22.5 + AngleHelper.deg(Mth.atan2(lookVec.z, lookVec.x)) % 360) / 8; - + if (!pos.equals(hintPos) || lookAngle != hintAngle) { hints = Couple.create(ArrayList::new); hintAngle = lookAngle; @@ -726,13 +754,13 @@ public class TrackPlacement { .showLine(Pair.of(key, i * 2), VecHelper.lerp(s, middle1, previous1), VecHelper.lerp(s, middle1, rail1)) .colored(railcolor) - .disableNormals() + .disableLineNormals() .lineWidth(lw); CreateClient.OUTLINER .showLine(Pair.of(key, i * 2 + 1), VecHelper.lerp(s, middle2, previous2), VecHelper.lerp(s, middle2, rail2)) .colored(railcolor) - .disableNormals() + .disableLineNormals() .lineWidth(lw); } @@ -753,7 +781,7 @@ public class TrackPlacement { int color = Color.mixColors(0xEA5C2B, 0x95CD41, animation.getValue()); CreateClient.OUTLINER.showLine(Pair.of("start", id), v1.subtract(o1), v1.add(ex)) .lineWidth(1 / 8f) - .disableNormals() + .disableLineNormals() .colored(color); } diff --git a/src/main/java/com/simibubi/create/content/trains/track/TrackPlacementOverlay.java b/src/main/java/com/simibubi/create/content/trains/track/TrackPlacementOverlay.java new file mode 100644 index 000000000..eacda223d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/trains/track/TrackPlacementOverlay.java @@ -0,0 +1,52 @@ +package com.simibubi.create.content.trains.track; + +import com.mojang.blaze3d.platform.Window; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.foundation.utility.Color; +import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Gui; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.util.Mth; +import net.minecraft.world.level.GameType; +import net.minecraftforge.client.gui.overlay.ForgeGui; +import net.minecraftforge.client.gui.overlay.IGuiOverlay; +import net.minecraftforge.fml.util.ObfuscationReflectionHelper; + +public class TrackPlacementOverlay implements IGuiOverlay { + public static final TrackPlacementOverlay INSTANCE = new TrackPlacementOverlay(); + + @Override + public void render(ForgeGui gui, PoseStack poseStack, float partialTicks, int width, int height) { + Minecraft mc = Minecraft.getInstance(); + if (mc.options.hideGui || mc.gameMode.getPlayerMode() == GameType.SPECTATOR) + return; + if (TrackPlacement.hoveringPos == null) + return; + if (TrackPlacement.cached == null || TrackPlacement.cached.curve == null || !TrackPlacement.cached.valid) + return; + if (TrackPlacement.extraTipWarmup < 4) + return; + + if (ObfuscationReflectionHelper.getPrivateValue(Gui.class, gui, + "toolHighlightTimer") instanceof Integer toolHighlightTimer && toolHighlightTimer > 0) + return; + + boolean active = mc.options.keySprint.isDown(); + MutableComponent text = Lang.translateDirect("track.hold_for_smooth_curve", Components.keybind("key.sprint") + .withStyle(active ? ChatFormatting.WHITE : ChatFormatting.GRAY)); + + Window window = mc.getWindow(); + int x = (window.getGuiScaledWidth() - gui.getFont() + .width(text)) / 2; + int y = window.getGuiScaledHeight() - 61; + Color color = new Color(0x4ADB4A).setAlpha(Mth.clamp((TrackPlacement.extraTipWarmup - 4) / 3f, 0.1f, 1)); + gui.getFont() + .draw(poseStack, text, x, y, color.getRGB()); + + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/TrackPropagator.java b/src/main/java/com/simibubi/create/content/trains/track/TrackPropagator.java similarity index 91% rename from src/main/java/com/simibubi/create/content/logistics/trains/TrackPropagator.java rename to src/main/java/com/simibubi/create/content/trains/track/TrackPropagator.java index 611787364..c94c8014e 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/TrackPropagator.java +++ b/src/main/java/com/simibubi/create/content/trains/track/TrackPropagator.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains; +package com.simibubi.create.content.trains.track; import java.util.ArrayList; import java.util.Collection; @@ -8,14 +8,20 @@ import java.util.List; import java.util.Set; import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.TrackNodeLocation.DiscoveredLocation; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SignalPropagator; +import com.simibubi.create.api.event.TrackGraphMergeEvent; +import com.simibubi.create.content.trains.GlobalRailwayManager; +import com.simibubi.create.content.trains.graph.TrackGraph; +import com.simibubi.create.content.trains.graph.TrackGraphSync; +import com.simibubi.create.content.trains.graph.TrackNode; +import com.simibubi.create.content.trains.graph.TrackNodeLocation.DiscoveredLocation; +import com.simibubi.create.content.trains.signal.SignalPropagator; import net.minecraft.core.BlockPos; import net.minecraft.util.Mth; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; +import net.minecraftforge.common.MinecraftForge; public class TrackPropagator { @@ -135,6 +141,7 @@ public class TrackPropagator { if (graph == null) graph = other; else { + MinecraftForge.EVENT_BUS.post(new TrackGraphMergeEvent(other, graph)); other.transferAll(graph); manager.removeGraphAndGroup(other); sync.graphRemoved(other); @@ -234,11 +241,13 @@ public class TrackPropagator { return true; if (location.shouldForceNode()) return true; + if (location.differentMaterials()) + return true; if (next.stream() .anyMatch(DiscoveredLocation::shouldForceNode)) return true; - - Vec3 direction = location.direction; + + Vec3 direction = location.getDirection(); if (direction != null && next.stream() .anyMatch(dl -> dl.notInLineWith(direction))) return true; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackRenderer.java b/src/main/java/com/simibubi/create/content/trains/track/TrackRenderer.java similarity index 75% rename from src/main/java/com/simibubi/create/content/logistics/trains/track/TrackRenderer.java rename to src/main/java/com/simibubi/create/content/trains/track/TrackRenderer.java index 1ee412ea0..65ef7ea1e 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackRenderer.java +++ b/src/main/java/com/simibubi/create/content/trains/track/TrackRenderer.java @@ -1,22 +1,17 @@ -package com.simibubi.create.content.logistics.trains.track; +package com.simibubi.create.content.trains.track; -import static com.simibubi.create.AllBlockPartials.GIRDER_SEGMENT_BOTTOM; -import static com.simibubi.create.AllBlockPartials.GIRDER_SEGMENT_MIDDLE; -import static com.simibubi.create.AllBlockPartials.GIRDER_SEGMENT_TOP; -import static com.simibubi.create.AllBlockPartials.TRACK_SEGMENT_LEFT; -import static com.simibubi.create.AllBlockPartials.TRACK_SEGMENT_RIGHT; -import static com.simibubi.create.AllBlockPartials.TRACK_TIE; +import static com.simibubi.create.AllPartialModels.GIRDER_SEGMENT_BOTTOM; +import static com.simibubi.create.AllPartialModels.GIRDER_SEGMENT_MIDDLE; +import static com.simibubi.create.AllPartialModels.GIRDER_SEGMENT_TOP; import com.jozufozu.flywheel.backend.Backend; -import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack.Pose; import com.mojang.blaze3d.vertex.VertexConsumer; -import com.simibubi.create.content.logistics.trains.BezierConnection; -import com.simibubi.create.content.logistics.trains.BezierConnection.GirderAngles; -import com.simibubi.create.content.logistics.trains.BezierConnection.SegmentAngles; +import com.simibubi.create.content.trains.track.BezierConnection.GirderAngles; +import com.simibubi.create.content.trains.track.BezierConnection.SegmentAngles; +import com.simibubi.create.foundation.blockEntity.renderer.SafeBlockEntityRenderer; import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.VecHelper; @@ -33,18 +28,18 @@ import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; -public class TrackRenderer extends SafeTileEntityRenderer { +public class TrackRenderer extends SafeBlockEntityRenderer { public TrackRenderer(BlockEntityRendererProvider.Context context) {} @Override - protected void renderSafe(TrackTileEntity te, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light, + protected void renderSafe(TrackBlockEntity be, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light, int overlay) { - Level level = te.getLevel(); + Level level = be.getLevel(); if (Backend.canUseInstancing(level)) return; VertexConsumer vb = buffer.getBuffer(RenderType.cutoutMipped()); - te.connections.values() + be.connections.values() .forEach(bc -> renderBezierTurn(level, bc, ms, vb)); } @@ -57,16 +52,15 @@ public class TrackRenderer extends SafeTileEntityRenderer { BlockState air = Blocks.AIR.defaultBlockState(); SegmentAngles[] segments = bc.getBakedSegments(); - TransformStack.cast(ms) - .nudge((int) tePosition.asLong()); - renderGirder(level, bc, ms, vb, tePosition); for (int i = 1; i < segments.length; i++) { SegmentAngles segment = segments[i]; int light = LevelRenderer.getLightColor(level, segment.lightPosition.offset(tePosition)); - CachedBufferer.partial(TRACK_TIE, air) + TrackMaterial.TrackModelHolder modelHolder = bc.getMaterial().getModelHolder(); + + CachedBufferer.partial(modelHolder.tie(), air) .mulPose(segment.tieTransform.pose()) .mulNormal(segment.tieTransform.normal()) .light(light) @@ -74,7 +68,7 @@ public class TrackRenderer extends SafeTileEntityRenderer { for (boolean first : Iterate.trueAndFalse) { Pose transform = segment.railTransforms.get(first); - CachedBufferer.partial(first ? TRACK_SEGMENT_LEFT : TRACK_SEGMENT_RIGHT, air) + CachedBufferer.partial(first ? modelHolder.segment_left() : modelHolder.segment_right(), air) .mulPose(transform.pose()) .mulNormal(transform.normal()) .light(light) @@ -140,7 +134,7 @@ public class TrackRenderer extends SafeTileEntityRenderer { } @Override - public boolean shouldRenderOffScreen(TrackTileEntity pBlockEntity) { + public boolean shouldRenderOffScreen(TrackBlockEntity pBlockEntity) { return true; } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackShape.java b/src/main/java/com/simibubi/create/content/trains/track/TrackShape.java similarity index 98% rename from src/main/java/com/simibubi/create/content/logistics/trains/track/TrackShape.java rename to src/main/java/com/simibubi/create/content/trains/track/TrackShape.java index 0c3e2332b..660db94ce 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackShape.java +++ b/src/main/java/com/simibubi/create/content/trains/track/TrackShape.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.track; +package com.simibubi.create.content.trains.track; import java.util.EnumMap; import java.util.List; diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/TrackTargetingBehaviour.java b/src/main/java/com/simibubi/create/content/trains/track/TrackTargetingBehaviour.java similarity index 82% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/TrackTargetingBehaviour.java rename to src/main/java/com/simibubi/create/content/trains/track/TrackTargetingBehaviour.java index 6771084d8..006c7b981 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/TrackTargetingBehaviour.java +++ b/src/main/java/com/simibubi/create/content/trains/track/TrackTargetingBehaviour.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.management.edgePoint; +package com.simibubi.create.content.trains.track; import java.util.List; import java.util.UUID; @@ -8,25 +8,23 @@ import javax.annotation.Nullable; import com.jozufozu.flywheel.core.PartialModel; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.Create; -import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform; -import com.simibubi.create.content.logistics.trains.BezierConnection; -import com.simibubi.create.content.logistics.trains.DimensionPalette; -import com.simibubi.create.content.logistics.trains.GraphLocation; -import com.simibubi.create.content.logistics.trains.ITrackBlock; -import com.simibubi.create.content.logistics.trains.TrackEdge; -import com.simibubi.create.content.logistics.trains.TrackGraph; -import com.simibubi.create.content.logistics.trains.TrackGraphHelper; -import com.simibubi.create.content.logistics.trains.TrackNode; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.SingleTileEdgePoint; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.TrackEdgePoint; -import com.simibubi.create.content.logistics.trains.track.BezierTrackPointLocation; -import com.simibubi.create.content.logistics.trains.track.TrackTileEntity; +import com.simibubi.create.content.contraptions.StructureTransform; import com.simibubi.create.content.schematics.SchematicWorld; +import com.simibubi.create.content.trains.graph.DimensionPalette; +import com.simibubi.create.content.trains.graph.EdgeData; +import com.simibubi.create.content.trains.graph.EdgePointType; +import com.simibubi.create.content.trains.graph.TrackEdge; +import com.simibubi.create.content.trains.graph.TrackGraph; +import com.simibubi.create.content.trains.graph.TrackGraphHelper; +import com.simibubi.create.content.trains.graph.TrackGraphLocation; +import com.simibubi.create.content.trains.graph.TrackNode; +import com.simibubi.create.content.trains.signal.SingleBlockEntityEdgePoint; +import com.simibubi.create.content.trains.signal.TrackEdgePoint; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.ponder.PonderWorld; import com.simibubi.create.foundation.render.CachedBufferer; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.VecHelper; @@ -48,7 +46,7 @@ import net.minecraft.world.phys.Vec3; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; -public class TrackTargetingBehaviour extends TileEntityBehaviour { +public class TrackTargetingBehaviour extends BlockEntityBehaviour { public static final BehaviourType> TYPE = new BehaviourType<>(); @@ -65,8 +63,8 @@ public class TrackTargetingBehaviour extends TileEntit private T edgePoint; private boolean orthogonal; - public TrackTargetingBehaviour(SmartTileEntity te, EdgePointType edgePointType) { - super(te); + public TrackTargetingBehaviour(SmartBlockEntity be, EdgePointType edgePointType) { + super(be); this.edgePointType = edgePointType; targetDirection = AxisDirection.POSITIVE; targetTrack = BlockPos.ZERO; @@ -133,7 +131,7 @@ public class TrackTargetingBehaviour extends TileEntit public void invalidateEdgePoint(CompoundTag migrationData) { this.migrationData = migrationData; edgePoint = null; - tileEntity.sendData(); + blockEntity.sendData(); } @Override @@ -159,7 +157,7 @@ public class TrackTargetingBehaviour extends TileEntit return null; if (!hasValidTrack()) return null; - GraphLocation loc = determineGraphLocation(); + TrackGraphLocation loc = determineGraphLocation(); if (loc == null) return null; @@ -214,9 +212,9 @@ public class TrackTargetingBehaviour extends TileEntit } if (!otherPoint.canMerge()) return null; - otherPoint.tileAdded(tileEntity, front); + otherPoint.blockEntityAdded(blockEntity, front); id = otherPoint.getId(); - tileEntity.notifyUpdate(); + blockEntity.notifyUpdate(); return (T) otherPoint; } } @@ -225,11 +223,11 @@ public class TrackTargetingBehaviour extends TileEntit point.read(data, true, DimensionPalette.read(data)); point.setId(id); - boolean reverseEdge = front || point instanceof SingleTileEdgePoint; + boolean reverseEdge = front || point instanceof SingleBlockEntityEdgePoint; point.setLocation(reverseEdge ? loc.edge : loc.edge.swap(), reverseEdge ? loc.position : length - loc.position); - point.tileAdded(tileEntity, front); + point.blockEntityAdded(blockEntity, front); loc.graph.addPoint(edgePointType, point); - tileEntity.sendData(); + blockEntity.sendData(); return point; } @@ -237,7 +235,7 @@ public class TrackTargetingBehaviour extends TileEntit public void destroy() { super.destroy(); if (edgePoint != null && !getWorld().isClientSide) - edgePoint.tileRemoved(getPos(), getTargetDirection() == AxisDirection.POSITIVE); + edgePoint.blockEntityRemoved(getPos(), getTargetDirection() == AxisDirection.POSITIVE); } @Override @@ -266,13 +264,13 @@ public class TrackTargetingBehaviour extends TileEntit } public BlockPos getGlobalPosition() { - return targetTrack.offset(tileEntity.getBlockPos()); + return targetTrack.offset(blockEntity.getBlockPos()); } public BlockPos getPositionForMapMarker() { - BlockPos target = targetTrack.offset(tileEntity.getBlockPos()); - if (targetBezier != null && getWorld().getBlockEntity(target) instanceof TrackTileEntity tte) { - BezierConnection bc = tte.getConnections() + BlockPos target = targetTrack.offset(blockEntity.getBlockPos()); + if (targetBezier != null && getWorld().getBlockEntity(target) instanceof TrackBlockEntity tbe) { + BezierConnection bc = tbe.getConnections() .get(targetBezier.curveTarget()); if (bc == null) return target; @@ -292,7 +290,7 @@ public class TrackTargetingBehaviour extends TileEntit return targetBezier; } - public GraphLocation determineGraphLocation() { + public TrackGraphLocation determineGraphLocation() { Level level = getWorld(); BlockPos pos = getGlobalPosition(); BlockState state = getTrackBlockState(); @@ -322,8 +320,6 @@ public class TrackTargetingBehaviour extends TileEntit return; ms.pushPose(); - ms.translate(pos.getX(), pos.getY(), pos.getZ()); - ITrackBlock track = (ITrackBlock) block; PartialModel partial = track.prepareTrackOverlay(level, pos, trackState, bezier, direction, ms, type); if (partial != null) @@ -333,7 +329,6 @@ public class TrackTargetingBehaviour extends TileEntit .translate(-.5, 0, -.5) .light(LevelRenderer.getLightColor(level, pos)) .renderInto(ms, buffer.getBuffer(RenderType.cutoutMipped())); - ms.popPose(); } @@ -346,7 +341,7 @@ public class TrackTargetingBehaviour extends TileEntit targetBezier = new BezierTrackPointLocation(transform.applyWithoutOffset(targetBezier.curveTarget() .subtract(getPos())) .offset(getPos()), targetBezier.segment()); - tileEntity.notifyUpdate(); + blockEntity.notifyUpdate(); } } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/TrackTargetingBlockItem.java b/src/main/java/com/simibubi/create/content/trains/track/TrackTargetingBlockItem.java similarity index 87% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/TrackTargetingBlockItem.java rename to src/main/java/com/simibubi/create/content/trains/track/TrackTargetingBlockItem.java index c03f511d1..bae77d799 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/TrackTargetingBlockItem.java +++ b/src/main/java/com/simibubi/create/content/trains/track/TrackTargetingBlockItem.java @@ -1,22 +1,21 @@ -package com.simibubi.create.content.logistics.trains.management.edgePoint; +package com.simibubi.create.content.trains.track; import java.util.List; import java.util.function.BiConsumer; import org.apache.commons.lang3.mutable.MutableObject; +import com.simibubi.create.AllPackets; import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.content.logistics.trains.GraphLocation; -import com.simibubi.create.content.logistics.trains.ITrackBlock; -import com.simibubi.create.content.logistics.trains.TrackEdge; -import com.simibubi.create.content.logistics.trains.TrackGraphHelper; -import com.simibubi.create.content.logistics.trains.TrackNode; -import com.simibubi.create.content.logistics.trains.management.edgePoint.signal.TrackEdgePoint; -import com.simibubi.create.content.logistics.trains.track.BezierTrackPointLocation; -import com.simibubi.create.content.logistics.trains.track.TrackBlockOutline.BezierPointSelection; -import com.simibubi.create.content.logistics.trains.track.TrackTileEntity; +import com.simibubi.create.content.trains.graph.EdgeData; +import com.simibubi.create.content.trains.graph.EdgePointType; +import com.simibubi.create.content.trains.graph.TrackEdge; +import com.simibubi.create.content.trains.graph.TrackGraphHelper; +import com.simibubi.create.content.trains.graph.TrackGraphLocation; +import com.simibubi.create.content.trains.graph.TrackNode; +import com.simibubi.create.content.trains.signal.TrackEdgePoint; +import com.simibubi.create.content.trains.track.TrackBlockOutline.BezierPointSelection; import com.simibubi.create.foundation.advancement.AllAdvancements; -import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Lang; import com.tterrag.registrate.util.nullness.NonNullBiFunction; @@ -156,12 +155,12 @@ public class TrackTargetingBlockItem extends BlockItem { public boolean useOnCurve(BezierPointSelection selection, ItemStack stack) { Minecraft mc = Minecraft.getInstance(); LocalPlayer player = mc.player; - TrackTileEntity te = selection.te(); + TrackBlockEntity be = selection.blockEntity(); BezierTrackPointLocation loc = selection.loc(); boolean front = player.getLookAngle() .dot(selection.direction()) < 0; - AllPackets.channel.sendToServer(new CurvedTrackSelectionPacket(te.getBlockPos(), loc.curveTarget(), + AllPackets.getChannel().sendToServer(new CurvedTrackSelectionPacket(be.getBlockPos(), loc.curveTarget(), loc.segment(), front, player.getInventory().selected)); return true; } @@ -185,7 +184,7 @@ public class TrackTargetingBlockItem extends BlockItem { public static void withGraphLocation(Level level, BlockPos pos, boolean front, BezierTrackPointLocation targetBezier, EdgePointType type, - BiConsumer callback) { + BiConsumer callback) { BlockState state = level.getBlockState(pos); @@ -201,7 +200,7 @@ public class TrackTargetingBlockItem extends BlockItem { } AxisDirection targetDirection = front ? AxisDirection.POSITIVE : AxisDirection.NEGATIVE; - GraphLocation location = + TrackGraphLocation location = targetBezier != null ? TrackGraphHelper.getBezierGraphLocationAt(level, pos, targetDirection, targetBezier) : TrackGraphHelper.getGraphLocationAt(level, pos, targetDirection, trackAxes.get(0)); diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/TrackTargetingClient.java b/src/main/java/com/simibubi/create/content/trains/track/TrackTargetingClient.java similarity index 84% rename from src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/TrackTargetingClient.java rename to src/main/java/com/simibubi/create/content/trains/track/TrackTargetingClient.java index 94f629068..26fc72bdb 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/management/edgePoint/TrackTargetingClient.java +++ b/src/main/java/com/simibubi/create/content/trains/track/TrackTargetingClient.java @@ -1,15 +1,14 @@ -package com.simibubi.create.content.logistics.trains.management.edgePoint; +package com.simibubi.create.content.trains.track; import com.google.common.base.Objects; +import com.jozufozu.flywheel.util.transform.TransformStack; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.trains.GraphLocation; -import com.simibubi.create.content.logistics.trains.ITrackBlock; -import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBehaviour.RenderedTrackOverlayType; -import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingBlockItem.OverlapResult; -import com.simibubi.create.content.logistics.trains.track.BezierTrackPointLocation; -import com.simibubi.create.content.logistics.trains.track.TrackBlockOutline; -import com.simibubi.create.content.logistics.trains.track.TrackBlockOutline.BezierPointSelection; +import com.simibubi.create.content.trains.graph.EdgePointType; +import com.simibubi.create.content.trains.graph.TrackGraphLocation; +import com.simibubi.create.content.trains.track.TrackBlockOutline.BezierPointSelection; +import com.simibubi.create.content.trains.track.TrackTargetingBehaviour.RenderedTrackOverlayType; +import com.simibubi.create.content.trains.track.TrackTargetingBlockItem.OverlapResult; import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; import net.minecraft.client.Minecraft; @@ -35,7 +34,7 @@ public class TrackTargetingClient { static BezierTrackPointLocation lastHoveredBezierSegment; static OverlapResult lastResult; - static GraphLocation lastLocation; + static TrackGraphLocation lastLocation; public static void clientTick() { Minecraft mc = Minecraft.getInstance(); @@ -72,7 +71,7 @@ public class TrackTargetingClient { } } else if (bezierSelection != null) { - hovered = bezierSelection.te() + hovered = bezierSelection.blockEntity() .getBlockPos(); hoveredBezier = bezierSelection.loc(); direction = lookAngle.dot(bezierSelection.direction()) < 0; @@ -116,7 +115,7 @@ public class TrackTargetingClient { }); } - public static void render(PoseStack ms, SuperRenderTypeBuffer buffer) { + public static void render(PoseStack ms, SuperRenderTypeBuffer buffer, Vec3 camera) { if (lastLocation == null || lastResult.feedback != null) return; @@ -128,8 +127,13 @@ public class TrackTargetingClient { RenderedTrackOverlayType type = lastType == EdgePointType.SIGNAL ? RenderedTrackOverlayType.SIGNAL : lastType == EdgePointType.OBSERVER ? RenderedTrackOverlayType.OBSERVER : RenderedTrackOverlayType.STATION; + ms.pushPose(); + TransformStack.cast(ms) + .translate(Vec3.atLowerCornerOf(pos) + .subtract(camera)); TrackTargetingBehaviour.render(mc.level, pos, direction, lastHoveredBezierSegment, ms, buffer, light, OverlayTexture.NO_OVERLAY, type, 1 + 1 / 16f); + ms.popPose(); } } diff --git a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackVoxelShapes.java b/src/main/java/com/simibubi/create/content/trains/track/TrackVoxelShapes.java similarity index 96% rename from src/main/java/com/simibubi/create/content/logistics/trains/track/TrackVoxelShapes.java rename to src/main/java/com/simibubi/create/content/trains/track/TrackVoxelShapes.java index 653de6e45..38bdd2350 100644 --- a/src/main/java/com/simibubi/create/content/logistics/trains/track/TrackVoxelShapes.java +++ b/src/main/java/com/simibubi/create/content/trains/track/TrackVoxelShapes.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics.trains.track; +package com.simibubi.create.content.trains.track; import net.minecraft.world.level.block.Block; import net.minecraft.world.phys.shapes.BooleanOp; diff --git a/src/main/java/com/simibubi/create/events/ClientEvents.java b/src/main/java/com/simibubi/create/events/ClientEvents.java deleted file mode 100644 index 33ddbb374..000000000 --- a/src/main/java/com/simibubi/create/events/ClientEvents.java +++ /dev/null @@ -1,424 +0,0 @@ -package com.simibubi.create.events; - -import java.util.ArrayList; -import java.util.List; - -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.PoseStack; -import com.simibubi.create.AllFluids; -import com.simibubi.create.AllItems; -import com.simibubi.create.Create; -import com.simibubi.create.CreateClient; -import com.simibubi.create.content.contraptions.KineticDebugger; -import com.simibubi.create.content.contraptions.base.IRotate; -import com.simibubi.create.content.contraptions.components.fan.AirCurrent; -import com.simibubi.create.content.contraptions.components.steam.SteamEngineBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionHandler; -import com.simibubi.create.content.contraptions.components.structureMovement.chassis.ChassisRangeDisplay; -import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsHandler; -import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.TrainHUD; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; -import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingHandlerClient; -import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingPhysics; -import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingRenderer; -import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.CapabilityMinecartController; -import com.simibubi.create.content.contraptions.components.turntable.TurntableHandler; -import com.simibubi.create.content.contraptions.goggles.GoggleOverlayRenderer; -import com.simibubi.create.content.contraptions.itemAssembly.SequencedAssemblyRecipe; -import com.simibubi.create.content.contraptions.relays.belt.item.BeltConnectorHandler; -import com.simibubi.create.content.curiosities.armor.CopperBacktankArmorLayer; -import com.simibubi.create.content.curiosities.girder.GirderWrenchBehavior; -import com.simibubi.create.content.curiosities.toolbox.ToolboxHandlerClient; -import com.simibubi.create.content.curiosities.tools.BlueprintOverlayRenderer; -import com.simibubi.create.content.curiosities.tools.ExtendoGripRenderHandler; -import com.simibubi.create.content.curiosities.zapper.ZapperItem; -import com.simibubi.create.content.curiosities.zapper.terrainzapper.WorldshaperRenderHandler; -import com.simibubi.create.content.logistics.block.depot.EjectorTargetHandler; -import com.simibubi.create.content.logistics.block.display.DisplayLinkBlockItem; -import com.simibubi.create.content.logistics.block.mechanicalArm.ArmInteractionPointHandler; -import com.simibubi.create.content.logistics.item.LinkedControllerClientHandler; -import com.simibubi.create.content.logistics.trains.CameraDistanceModifier; -import com.simibubi.create.content.logistics.trains.entity.CarriageContraptionEntity; -import com.simibubi.create.content.logistics.trains.entity.CarriageCouplingRenderer; -import com.simibubi.create.content.logistics.trains.entity.TrainRelocator; -import com.simibubi.create.content.logistics.trains.management.edgePoint.TrackTargetingClient; -import com.simibubi.create.content.logistics.trains.management.schedule.TrainHatArmorLayer; -import com.simibubi.create.content.logistics.trains.track.CurvedTrackInteraction; -import com.simibubi.create.content.logistics.trains.track.TrackBlockOutline; -import com.simibubi.create.content.logistics.trains.track.TrackPlacement; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.config.ui.BaseConfigScreen; -import com.simibubi.create.foundation.fluid.FluidHelper; -import com.simibubi.create.foundation.item.ItemDescription; -import com.simibubi.create.foundation.item.TooltipHelper; -import com.simibubi.create.foundation.networking.AllPackets; -import com.simibubi.create.foundation.networking.LeftClickPacket; -import com.simibubi.create.foundation.ponder.PonderTooltipHandler; -import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; -import com.simibubi.create.foundation.sound.SoundScapes; -import com.simibubi.create.foundation.tileEntity.behaviour.edgeInteraction.EdgeInteractionRenderer; -import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringRenderer; -import com.simibubi.create.foundation.tileEntity.behaviour.linked.LinkRenderer; -import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueHandler; -import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueRenderer; -import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.CameraAngleAnimationService; -import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.ServerSpeedProvider; -import com.simibubi.create.foundation.utility.placement.PlacementHelpers; -import com.simibubi.create.foundation.utility.worldWrappers.WrappedClientWorld; - -import net.minecraft.client.Camera; -import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.renderer.entity.EntityRenderDispatcher; -import net.minecraft.core.BlockPos; -import net.minecraft.network.chat.Component; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.material.Fluid; -import net.minecraft.world.level.material.FluidState; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.client.ConfigScreenHandler; -import net.minecraftforge.client.event.ClientPlayerNetworkEvent; -import net.minecraftforge.client.event.EntityRenderersEvent; -import net.minecraftforge.client.event.RegisterClientReloadListenersEvent; -import net.minecraftforge.client.event.RegisterGuiOverlaysEvent; -import net.minecraftforge.client.event.RenderLevelLastEvent; -import net.minecraftforge.client.event.RenderTooltipEvent; -import net.minecraftforge.client.event.ViewportEvent; -import net.minecraftforge.client.gui.overlay.VanillaGuiOverlay; -import net.minecraftforge.event.TickEvent.ClientTickEvent; -import net.minecraftforge.event.TickEvent.Phase; -import net.minecraftforge.event.TickEvent.RenderTickEvent; -import net.minecraftforge.event.entity.EntityMountEvent; -import net.minecraftforge.event.entity.player.ItemTooltipEvent; -import net.minecraftforge.event.entity.player.PlayerInteractEvent; -import net.minecraftforge.event.level.LevelEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.ModContainer; -import net.minecraftforge.fml.ModList; -import net.minecraftforge.fml.common.Mod.EventBusSubscriber; -import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent; - -@EventBusSubscriber(Dist.CLIENT) -public class ClientEvents { - - private static final String ITEM_PREFIX = "item." + Create.ID; - private static final String BLOCK_PREFIX = "block." + Create.ID; - - @SubscribeEvent - public static void onTick(ClientTickEvent event) { - if (!isGameActive()) - return; - - Level world = Minecraft.getInstance().level; - if (event.phase == Phase.START) { - LinkedControllerClientHandler.tick(); - ControlsHandler.tick(); - AirCurrent.tickClientPlayerSounds(); - return; - } - - SoundScapes.tick(); - AnimationTickHolder.tick(); - ScrollValueHandler.tick(); - - CreateClient.SCHEMATIC_SENDER.tick(); - CreateClient.SCHEMATIC_AND_QUILL_HANDLER.tick(); - CreateClient.GLUE_HANDLER.tick(); - CreateClient.SCHEMATIC_HANDLER.tick(); - CreateClient.ZAPPER_RENDER_HANDLER.tick(); - CreateClient.POTATO_CANNON_RENDER_HANDLER.tick(); - CreateClient.SOUL_PULSE_EFFECT_HANDLER.tick(world); - CreateClient.RAILWAYS.clientTick(); - - ContraptionHandler.tick(world); - CapabilityMinecartController.tick(world); - CouplingPhysics.tick(world); - - PonderTooltipHandler.tick(); - // ScreenOpener.tick(); - ServerSpeedProvider.clientTick(); - BeltConnectorHandler.tick(); -// BeltSlicer.tickHoveringInformation(); - FilteringRenderer.tick(); - LinkRenderer.tick(); - ScrollValueRenderer.tick(); - ChassisRangeDisplay.tick(); - EdgeInteractionRenderer.tick(); - GirderWrenchBehavior.tick(); - WorldshaperRenderHandler.tick(); - CouplingHandlerClient.tick(); - CouplingRenderer.tickDebugModeRenders(); - KineticDebugger.tick(); - ExtendoGripRenderHandler.tick(); - // CollisionDebugger.tick(); - ArmInteractionPointHandler.tick(); - EjectorTargetHandler.tick(); - PlacementHelpers.tick(); - CreateClient.OUTLINER.tickOutlines(); - CreateClient.GHOST_BLOCKS.tickGhosts(); - ContraptionRenderDispatcher.tick(world); - BlueprintOverlayRenderer.tick(); - ToolboxHandlerClient.clientTick(); - TrackTargetingClient.clientTick(); - TrackPlacement.clientTick(); - TrainRelocator.clientTick(); - DisplayLinkBlockItem.clientTick(); - CurvedTrackInteraction.clientTick(); - CameraDistanceModifier.tick(); - CameraAngleAnimationService.tick(); - TrainHUD.tick(); - } - - @SubscribeEvent - public static void onJoin(ClientPlayerNetworkEvent.LoggingIn event) { - CreateClient.checkGraphicsFanciness(); - } - - @SubscribeEvent - public static void onLeave(ClientPlayerNetworkEvent.LoggingOut event) { - CreateClient.RAILWAYS.cleanUp(); - } - - @SubscribeEvent - public static void onLoadWorld(LevelEvent.Load event) { - LevelAccessor world = event.getLevel(); - if (world.isClientSide() && world instanceof ClientLevel && !(world instanceof WrappedClientWorld)) { - CreateClient.invalidateRenderers(); - AnimationTickHolder.reset(); - } - } - - @SubscribeEvent - public static void onUnloadWorld(LevelEvent.Unload event) { - if (!event.getLevel() - .isClientSide()) - return; - CreateClient.invalidateRenderers(); - CreateClient.SOUL_PULSE_EFFECT_HANDLER.refresh(); - AnimationTickHolder.reset(); - ControlsHandler.levelUnloaded(event.getLevel()); - } - - @SubscribeEvent - public static void onRenderWorld(RenderLevelLastEvent event) { - Vec3 cameraPos = Minecraft.getInstance().gameRenderer.getMainCamera() - .getPosition(); - float pt = AnimationTickHolder.getPartialTicks(); - - PoseStack ms = event.getPoseStack(); - ms.pushPose(); - ms.translate(-cameraPos.x(), -cameraPos.y(), -cameraPos.z()); - SuperRenderTypeBuffer buffer = SuperRenderTypeBuffer.getInstance(); - - TrackBlockOutline.drawCurveSelection(ms, buffer); - TrackTargetingClient.render(ms, buffer); - CouplingRenderer.renderAll(ms, buffer); - CarriageCouplingRenderer.renderAll(ms, buffer); - CreateClient.SCHEMATIC_HANDLER.render(ms, buffer); - CreateClient.GHOST_BLOCKS.renderAll(ms, buffer); - - CreateClient.OUTLINER.renderOutlines(ms, buffer, pt); - buffer.draw(); - RenderSystem.enableCull(); - - ms.popPose(); - } - - @SubscribeEvent - public static void onCameraSetup(ViewportEvent.ComputeCameraAngles event) { - float partialTicks = AnimationTickHolder.getPartialTicks(); - - if (CameraAngleAnimationService.isYawAnimating()) - event.setYaw(CameraAngleAnimationService.getYaw(partialTicks)); - - if (CameraAngleAnimationService.isPitchAnimating()) - event.setPitch(CameraAngleAnimationService.getPitch(partialTicks)); - } - - @SubscribeEvent - public static void getItemTooltipColor(RenderTooltipEvent.Color event) { - PonderTooltipHandler.handleTooltipColor(event); - } - - @SubscribeEvent - public static void addToItemTooltip(ItemTooltipEvent event) { - if (!AllConfigs.CLIENT.tooltips.get()) - return; - if (event.getEntity() == null) - return; - - ItemStack stack = event.getItemStack(); - String translationKey = stack.getItem() - .getDescriptionId(stack); - - if (translationKey.startsWith(ITEM_PREFIX) || translationKey.startsWith(BLOCK_PREFIX)) - if (TooltipHelper.hasTooltip(stack, event.getEntity())) { - List itemTooltip = event.getToolTip(); - List toolTip = new ArrayList<>(); - toolTip.add(itemTooltip.remove(0)); - TooltipHelper.getTooltip(stack) - .addInformation(toolTip); - itemTooltip.addAll(0, toolTip); - } - - if (stack.getItem() instanceof BlockItem) { - BlockItem item = (BlockItem) stack.getItem(); - if (item.getBlock() instanceof IRotate || item.getBlock() instanceof SteamEngineBlock) { - List kineticStats = ItemDescription.getKineticStats(item.getBlock()); - if (!kineticStats.isEmpty()) { - event.getToolTip() - .add(Components.immutableEmpty()); - event.getToolTip() - .addAll(kineticStats); - } - } - } - - PonderTooltipHandler.addToTooltip(event.getToolTip(), stack); - SequencedAssemblyRecipe.addToTooltip(event.getToolTip(), stack); - } - - @SubscribeEvent - public static void onRenderTick(RenderTickEvent event) { - if (!isGameActive()) - return; - TurntableHandler.gameRenderTick(); - } - - @SubscribeEvent - public static void onMount(EntityMountEvent event) { - if (event.getEntityMounting() != Minecraft.getInstance().player) - return; - - if (event.isDismounting()) { - CameraDistanceModifier.reset(); - return; - } - - if (!event.isMounting() || !(event.getEntityBeingMounted() instanceof CarriageContraptionEntity carriage)) { - return; - } - - CameraDistanceModifier.zoomOut(); - } - - protected static boolean isGameActive() { - return !(Minecraft.getInstance().level == null || Minecraft.getInstance().player == null); - } - - @SubscribeEvent - public static void getFogDensity(ViewportEvent.RenderFog event) { - Camera info = event.getCamera(); - Level level = Minecraft.getInstance().level; - BlockPos blockPos = info.getBlockPosition(); - FluidState fluidState = level.getFluidState(blockPos); - if (info.getPosition().y > blockPos.getY() + fluidState.getHeight(level, blockPos)) - return; - - Fluid fluid = fluidState.getType(); - - if (AllFluids.CHOCOLATE.get() - .isSame(fluid)) { - event.scaleFarPlaneDistance(1f/32f); - event.setCanceled(true); - return; - } - - if (AllFluids.HONEY.get() - .isSame(fluid)) { - event.scaleFarPlaneDistance(1f/8f); - event.setCanceled(true); - return; - } - - if (FluidHelper.isWater(fluid) && AllItems.DIVING_HELMET.get() - .isWornBy(Minecraft.getInstance().cameraEntity)) { - event.scaleFarPlaneDistance(6.25f); - event.setCanceled(true); - return; - } - } - - @SubscribeEvent - public static void getFogColor(ViewportEvent.ComputeFogColor event) { - Camera info = event.getCamera(); - Level level = Minecraft.getInstance().level; - BlockPos blockPos = info.getBlockPosition(); - FluidState fluidState = level.getFluidState(blockPos); - if (info.getPosition().y > blockPos.getY() + fluidState.getHeight(level, blockPos)) - return; - - Fluid fluid = fluidState.getType(); - - if (AllFluids.CHOCOLATE.get() - .isSame(fluid)) { - event.setRed(98 / 255f); - event.setGreen(32 / 255f); - event.setBlue(32 / 255f); - return; - } - - if (AllFluids.HONEY.get() - .isSame(fluid)) { - event.setRed(234 / 255f); - event.setGreen(174 / 255f); - event.setBlue(47 / 255f); - return; - } - } - - @SubscribeEvent - public static void leftClickEmpty(PlayerInteractEvent.LeftClickEmpty event) { - ItemStack stack = event.getItemStack(); - if (stack.getItem() instanceof ZapperItem) { - AllPackets.channel.sendToServer(new LeftClickPacket()); - } - } - - @EventBusSubscriber(value = Dist.CLIENT, bus = EventBusSubscriber.Bus.MOD) - public static class ModBusEvents { - - @SubscribeEvent - public static void registerClientReloadListeners(RegisterClientReloadListenersEvent event) { - event.registerReloadListener(CreateClient.RESOURCE_RELOAD_LISTENER); - } - - @SubscribeEvent - public static void addEntityRendererLayers(EntityRenderersEvent.AddLayers event) { - EntityRenderDispatcher dispatcher = Minecraft.getInstance() - .getEntityRenderDispatcher(); - CopperBacktankArmorLayer.registerOnAll(dispatcher); - TrainHatArmorLayer.registerOnAll(dispatcher); - } - - @SubscribeEvent - public static void registerGuiOverlays(RegisterGuiOverlaysEvent event) { - // Register overlays in reverse order - event.registerAbove(VanillaGuiOverlay.AIR_LEVEL.id(), "remaining_air", CopperBacktankArmorLayer.REMAINING_AIR_OVERLAY); - event.registerAbove(VanillaGuiOverlay.EXPERIENCE_BAR.id(), "train_hud", TrainHUD.OVERLAY); - event.registerAbove(VanillaGuiOverlay.HOTBAR.id(), "goggle_info", GoggleOverlayRenderer.OVERLAY); - event.registerAbove(VanillaGuiOverlay.HOTBAR.id(), "blueprint", BlueprintOverlayRenderer.OVERLAY); - event.registerAbove(VanillaGuiOverlay.HOTBAR.id(), "linked_controller", LinkedControllerClientHandler.OVERLAY); - event.registerAbove(VanillaGuiOverlay.HOTBAR.id(), "schematic", CreateClient.SCHEMATIC_HANDLER.getOverlayRenderer()); - event.registerAbove(VanillaGuiOverlay.HOTBAR.id(), "toolbox", ToolboxHandlerClient.OVERLAY); - } - - @SubscribeEvent - public static void onLoadComplete(FMLLoadCompleteEvent event) { - ModContainer createContainer = ModList.get() - .getModContainerById(Create.ID) - .orElseThrow(() -> new IllegalStateException("Create mod container missing on LoadComplete")); - createContainer.registerExtensionPoint(ConfigScreenHandler.ConfigScreenFactory.class, - () -> new ConfigScreenHandler.ConfigScreenFactory( - (mc, previousScreen) -> BaseConfigScreen.forCreate(previousScreen))); - } - - } - -} diff --git a/src/main/java/com/simibubi/create/foundation/advancement/AdvancementBehaviour.java b/src/main/java/com/simibubi/create/foundation/advancement/AdvancementBehaviour.java index 1729f3782..f52bd1453 100644 --- a/src/main/java/com/simibubi/create/foundation/advancement/AdvancementBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/advancement/AdvancementBehaviour.java @@ -4,9 +4,9 @@ import java.util.HashSet; import java.util.Set; import java.util.UUID; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; @@ -18,15 +18,15 @@ import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; import net.minecraftforge.common.util.FakePlayer; -public class AdvancementBehaviour extends TileEntityBehaviour { +public class AdvancementBehaviour extends BlockEntityBehaviour { public static final BehaviourType TYPE = new BehaviourType<>(); private UUID playerId; private Set advancements; - public AdvancementBehaviour(SmartTileEntity te, CreateAdvancement... advancements) { - super(te); + public AdvancementBehaviour(SmartBlockEntity be, CreateAdvancement... advancements) { + super(be); this.advancements = new HashSet<>(); add(advancements); } @@ -46,7 +46,7 @@ public class AdvancementBehaviour extends TileEntityBehaviour { return; playerId = id; removeAwarded(); - tileEntity.setChanged(); + blockEntity.setChanged(); } @Override @@ -62,7 +62,7 @@ public class AdvancementBehaviour extends TileEntityBehaviour { advancements.removeIf(c -> c.isAlreadyAwardedTo(player)); if (advancements.isEmpty()) { playerId = null; - tileEntity.setChanged(); + blockEntity.setChanged(); } } @@ -114,13 +114,13 @@ public class AdvancementBehaviour extends TileEntityBehaviour { } public static void tryAward(BlockGetter reader, BlockPos pos, CreateAdvancement advancement) { - AdvancementBehaviour behaviour = TileEntityBehaviour.get(reader, pos, AdvancementBehaviour.TYPE); + AdvancementBehaviour behaviour = BlockEntityBehaviour.get(reader, pos, AdvancementBehaviour.TYPE); if (behaviour != null) behaviour.awardPlayer(advancement); } public static void setPlacedBy(Level worldIn, BlockPos pos, LivingEntity placer) { - AdvancementBehaviour behaviour = TileEntityBehaviour.get(worldIn, pos, TYPE); + AdvancementBehaviour behaviour = BlockEntityBehaviour.get(worldIn, pos, TYPE); if (behaviour == null) return; if (placer instanceof FakePlayer) diff --git a/src/main/java/com/simibubi/create/foundation/advancement/AllAdvancements.java b/src/main/java/com/simibubi/create/foundation/advancement/AllAdvancements.java index d4ae912d3..84eb95035 100644 --- a/src/main/java/com/simibubi/create/foundation/advancement/AllAdvancements.java +++ b/src/main/java/com/simibubi/create/foundation/advancement/AllAdvancements.java @@ -266,7 +266,7 @@ public class AllAdvancements implements DataProvider { .description("Create a Copper Backtank and make it accumulate air pressure") .after(STEAM_WHISTLE)), - DIVING_SUIT = create("diving_suit", b -> b.icon(AllItems.DIVING_HELMET) + DIVING_SUIT = create("diving_suit", b -> b.icon(AllItems.COPPER_DIVING_HELMET) .title("Ready for the Depths") .description("Equip a Diving Helmet and a Copper Backtank, then jump into water") .after(BACKTANK)), @@ -327,7 +327,7 @@ public class AllAdvancements implements DataProvider { // Copper - Hidden - DIVING_SUIT_LAVA = create("diving_suit_lava", b -> b.icon(AllItems.DIVING_HELMET) + DIVING_SUIT_LAVA = create("diving_suit_lava", b -> b.icon(AllItems.COPPER_DIVING_HELMET) .title("Swimming with the Striders") .description("Attempt to take a dive in lava with your diving gear") .after(BACKTANK) @@ -561,16 +561,10 @@ public class AllAdvancements implements DataProvider { .after(STURDY_SHEET) .special(EXPERT)), - LONG_BEND = create("long_bend", b -> b.icon(AllBlocks.TRACK) - .title("The Longest Bend") - .description("Create a curved track section that spans more than 30 blocks in length") - .after(TRACK_CRAFTING) - .special(EXPERT)), - LONG_TRAIN = create("long_train", b -> b.icon(Items.MINECART) .title("Ambitious Endeavours") .description("Create a Train with at least 6 carriages") - .after(LONG_BEND) + .after(TRACK_CRAFTING) .special(EXPERT)), LONG_TRAVEL = create("long_travel", b -> b.icon(AllBlocks.SEATS.get(DyeColor.GREEN)) diff --git a/src/main/java/com/simibubi/create/foundation/block/BigOutlines.java b/src/main/java/com/simibubi/create/foundation/block/BigOutlines.java index c5414b80c..25f9319f5 100644 --- a/src/main/java/com/simibubi/create/foundation/block/BigOutlines.java +++ b/src/main/java/com/simibubi/create/foundation/block/BigOutlines.java @@ -1,7 +1,7 @@ package com.simibubi.create.foundation.block; -import com.simibubi.create.content.curiosities.deco.SlidingDoorBlock; -import com.simibubi.create.content.logistics.trains.track.TrackBlock; +import com.simibubi.create.content.decoration.slidingDoor.SlidingDoorBlock; +import com.simibubi.create.content.trains.track.TrackBlock; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.RaycastHelper; import com.simibubi.create.foundation.utility.VecHelper; diff --git a/src/main/java/com/simibubi/create/foundation/block/IBE.java b/src/main/java/com/simibubi/create/foundation/block/IBE.java new file mode 100644 index 000000000..b616490d4 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/block/IBE.java @@ -0,0 +1,83 @@ +package com.simibubi.create.foundation.block; + +import java.util.Optional; +import java.util.function.Consumer; +import java.util.function.Function; + +import javax.annotation.Nullable; + +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntityTicker; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; +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; + +public interface IBE extends EntityBlock { + + Class getBlockEntityClass(); + + BlockEntityType getBlockEntityType(); + + default void withBlockEntityDo(BlockGetter world, BlockPos pos, Consumer action) { + getBlockEntityOptional(world, pos).ifPresent(action); + } + + default InteractionResult onBlockEntityUse(BlockGetter world, BlockPos pos, Function action) { + return getBlockEntityOptional(world, pos).map(action) + .orElse(InteractionResult.PASS); + } + + /** + * if the IBE is bound to a SmartBlockEntity, which implements destroy(),
+ * call this method in BlockBehaviour::onRemove (replace super call) + */ + public static void onRemove(BlockState blockState, Level level, BlockPos pos, BlockState newBlockState) { + if (!blockState.hasBlockEntity()) + return; + if (blockState.is(newBlockState.getBlock()) && newBlockState.hasBlockEntity()) + return; + BlockEntity blockEntity = level.getBlockEntity(pos); + if (blockEntity instanceof SmartBlockEntity sbe) + sbe.destroy(); + level.removeBlockEntity(pos); + } + + default Optional getBlockEntityOptional(BlockGetter world, BlockPos pos) { + return Optional.ofNullable(getBlockEntity(world, pos)); + } + + @Override + default BlockEntity newBlockEntity(BlockPos p_153215_, BlockState p_153216_) { + return getBlockEntityType().create(p_153215_, p_153216_); + } + + @Override + default BlockEntityTicker getTicker(Level p_153212_, BlockState p_153213_, + BlockEntityType p_153214_) { + if (SmartBlockEntity.class.isAssignableFrom(getBlockEntityClass())) + return new SmartBlockEntityTicker<>(); + return null; + } + + @Nullable + @SuppressWarnings("unchecked") + default T getBlockEntity(BlockGetter worldIn, BlockPos pos) { + BlockEntity blockEntity = worldIn.getBlockEntity(pos); + Class expectedClass = getBlockEntityClass(); + + if (blockEntity == null) + return null; + if (!expectedClass.isInstance(blockEntity)) + return null; + + return (T) blockEntity; + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/block/ITE.java b/src/main/java/com/simibubi/create/foundation/block/ITE.java deleted file mode 100644 index c79d96ee0..000000000 --- a/src/main/java/com/simibubi/create/foundation/block/ITE.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.simibubi.create.foundation.block; - -import java.util.Optional; -import java.util.function.Consumer; -import java.util.function.Function; - -import javax.annotation.Nullable; - -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.SmartTileEntityTicker; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -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; - -public interface ITE extends EntityBlock { - - Class getTileEntityClass(); - - BlockEntityType getTileEntityType(); - - default void withTileEntityDo(BlockGetter world, BlockPos pos, Consumer action) { - getTileEntityOptional(world, pos).ifPresent(action); - } - - default InteractionResult onTileEntityUse(BlockGetter world, BlockPos pos, Function action) { - return getTileEntityOptional(world, pos).map(action) - .orElse(InteractionResult.PASS); - } - - /** - * if the ITE is bound to a SmartTileEntity, which implements destroy(),
- * call this method in BlockBehaviour::onRemove (replace super call) - */ - public static void onRemove(BlockState blockState, Level level, BlockPos pos, BlockState newBlockState) { - if (!blockState.hasBlockEntity()) - return; - if (blockState.is(newBlockState.getBlock()) && newBlockState.hasBlockEntity()) - return; - BlockEntity blockEntity = level.getBlockEntity(pos); - if (blockEntity instanceof SmartTileEntity ste) - ste.destroy(); - level.removeBlockEntity(pos); - } - - default Optional getTileEntityOptional(BlockGetter world, BlockPos pos) { - return Optional.ofNullable(getTileEntity(world, pos)); - } - - @Override - default BlockEntity newBlockEntity(BlockPos p_153215_, BlockState p_153216_) { - return getTileEntityType().create(p_153215_, p_153216_); - } - - @Override - default BlockEntityTicker getTicker(Level p_153212_, BlockState p_153213_, - BlockEntityType p_153214_) { - if (SmartTileEntity.class.isAssignableFrom(getTileEntityClass())) - return new SmartTileEntityTicker<>(); - return null; - } - - @Nullable - @SuppressWarnings("unchecked") - default T getTileEntity(BlockGetter worldIn, BlockPos pos) { - BlockEntity tileEntity = worldIn.getBlockEntity(pos); - Class expectedClass = getTileEntityClass(); - - if (tileEntity == null) - return null; - if (!expectedClass.isInstance(tileEntity)) - return null; - - return (T) tileEntity; - } - -} diff --git a/src/main/java/com/simibubi/create/foundation/block/ProperWaterloggedBlock.java b/src/main/java/com/simibubi/create/foundation/block/ProperWaterloggedBlock.java index e6439e5fd..b455f1656 100644 --- a/src/main/java/com/simibubi/create/foundation/block/ProperWaterloggedBlock.java +++ b/src/main/java/com/simibubi/create/foundation/block/ProperWaterloggedBlock.java @@ -38,9 +38,11 @@ public interface ProperWaterloggedBlock extends SimpleWaterloggedBlock { static BlockState withWater(LevelAccessor level, BlockState placementState, BlockPos pos) { if (placementState == null) return null; + FluidState ifluidstate = level.getFluidState(pos); + if (placementState.isAir()) + return ifluidstate.getType() == Fluids.WATER ? ifluidstate.createLegacyBlock() : placementState; if (!(placementState.getBlock() instanceof SimpleWaterloggedBlock)) return placementState; - FluidState ifluidstate = level.getFluidState(pos); return placementState.setValue(BlockStateProperties.WATERLOGGED, ifluidstate.getType() == Fluids.WATER); } diff --git a/src/main/java/com/simibubi/create/foundation/block/WrenchableDirectionalBlock.java b/src/main/java/com/simibubi/create/foundation/block/WrenchableDirectionalBlock.java index 7d8820886..03edbb8d4 100644 --- a/src/main/java/com/simibubi/create/foundation/block/WrenchableDirectionalBlock.java +++ b/src/main/java/com/simibubi/create/foundation/block/WrenchableDirectionalBlock.java @@ -1,6 +1,6 @@ package com.simibubi.create.foundation.block; -import com.simibubi.create.content.contraptions.wrench.IWrenchable; +import com.simibubi.create.content.equipment.wrench.IWrenchable; import net.minecraft.core.Direction; import net.minecraft.world.item.context.BlockPlaceContext; diff --git a/src/main/java/com/simibubi/create/foundation/block/connected/CTModel.java b/src/main/java/com/simibubi/create/foundation/block/connected/CTModel.java index 3cff9e07b..a9ef18947 100644 --- a/src/main/java/com/simibubi/create/foundation/block/connected/CTModel.java +++ b/src/main/java/com/simibubi/create/foundation/block/connected/CTModel.java @@ -4,8 +4,10 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import com.simibubi.create.content.decoration.copycat.CopycatBlock; import com.simibubi.create.foundation.block.connected.ConnectedTextureBehaviour.CTContext; -import com.simibubi.create.foundation.block.render.QuadHelper; +import com.simibubi.create.foundation.model.BakedModelWrapperWithData; +import com.simibubi.create.foundation.model.BakedQuadHelper; import com.simibubi.create.foundation.utility.Iterate; import net.minecraft.client.renderer.RenderType; @@ -34,7 +36,8 @@ public class CTModel extends BakedModelWrapperWithData { } @Override - protected Builder gatherModelData(Builder builder, BlockAndTintGetter world, BlockPos pos, BlockState state) { + protected ModelData.Builder gatherModelData(Builder builder, BlockAndTintGetter world, BlockPos pos, BlockState state, + ModelData blockEntityData) { return builder.with(CT_PROPERTY, createCTData(world, pos, state)); } @@ -42,10 +45,13 @@ public class CTModel extends BakedModelWrapperWithData { CTData data = new CTData(); MutableBlockPos mutablePos = new MutableBlockPos(); for (Direction face : Iterate.directions) { + BlockState actualState = world.getBlockState(pos); if (!behaviour.buildContextForOccludedDirections() - && !Block.shouldRenderFace(state, world, pos, face, mutablePos.setWithOffset(pos, face))) + && !Block.shouldRenderFace(state, world, pos, face, mutablePos.setWithOffset(pos, face)) + && !(actualState.getBlock()instanceof CopycatBlock ufb + && !ufb.canFaceBeOccluded(actualState, face))) continue; - CTType dataType = behaviour.getDataType(state, face); + CTType dataType = behaviour.getDataType(world, pos, state, face); if (dataType == null) continue; CTContext context = behaviour.buildContext(world, pos, state, face, dataType.getContextRequirement()); @@ -76,14 +82,14 @@ public class CTModel extends BakedModelWrapperWithData { if (quad.getSprite() != spriteShift.getOriginal()) continue; - BakedQuad newQuad = QuadHelper.clone(quad); + BakedQuad newQuad = BakedQuadHelper.clone(quad); int[] vertexData = newQuad.getVertices(); for (int vertex = 0; vertex < 4; vertex++) { - float u = QuadHelper.getU(vertexData, vertex); - float v = QuadHelper.getV(vertexData, vertex); - QuadHelper.setU(vertexData, vertex, spriteShift.getTargetU(u, index)); - QuadHelper.setV(vertexData, vertex, spriteShift.getTargetV(v, index)); + float u = BakedQuadHelper.getU(vertexData, vertex); + float v = BakedQuadHelper.getV(vertexData, vertex); + BakedQuadHelper.setU(vertexData, vertex, spriteShift.getTargetU(u, index)); + BakedQuadHelper.setV(vertexData, vertex, spriteShift.getTargetV(v, index)); } quads.set(i, newQuad); diff --git a/src/main/java/com/simibubi/create/foundation/block/connected/CTSpriteShifter.java b/src/main/java/com/simibubi/create/foundation/block/connected/CTSpriteShifter.java index e3c61883c..7fb456fb8 100644 --- a/src/main/java/com/simibubi/create/foundation/block/connected/CTSpriteShifter.java +++ b/src/main/java/com/simibubi/create/foundation/block/connected/CTSpriteShifter.java @@ -6,6 +6,8 @@ import java.util.Map; import com.simibubi.create.foundation.block.render.SpriteShiftEntry; import net.minecraft.resources.ResourceLocation; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; public class CTSpriteShifter { @@ -17,7 +19,7 @@ public class CTSpriteShifter { return (CTSpriteShiftEntry) ENTRY_CACHE.get(key); CTSpriteShiftEntry entry = new CTSpriteShiftEntry(type); - entry.set(blockTexture, connectedTexture); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> entry.set(blockTexture, connectedTexture)); ENTRY_CACHE.put(key, entry); return entry; } diff --git a/src/main/java/com/simibubi/create/foundation/block/connected/ConnectedTextureBehaviour.java b/src/main/java/com/simibubi/create/foundation/block/connected/ConnectedTextureBehaviour.java index 906273a80..14ddabc41 100644 --- a/src/main/java/com/simibubi/create/foundation/block/connected/ConnectedTextureBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/block/connected/ConnectedTextureBehaviour.java @@ -9,16 +9,18 @@ import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; import net.minecraft.core.Direction.AxisDirection; import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; public abstract class ConnectedTextureBehaviour { @Nullable - public abstract CTSpriteShiftEntry getShift(BlockState state, Direction direction, @NotNull TextureAtlasSprite sprite); + public abstract CTSpriteShiftEntry getShift(BlockState state, Direction direction, + @NotNull TextureAtlasSprite sprite); // TODO: allow more than one data type per state/face? @Nullable - public abstract CTType getDataType(BlockState state, Direction direction); + public abstract CTType getDataType(BlockAndTintGetter world, BlockPos pos, BlockState state, Direction direction); public boolean buildContextForOccludedDirections() { return false; @@ -27,10 +29,19 @@ public abstract class ConnectedTextureBehaviour { protected boolean isBeingBlocked(BlockState state, BlockAndTintGetter reader, BlockPos pos, BlockPos otherPos, Direction face) { BlockPos blockingPos = otherPos.relative(face); - return face.getAxis() - .choose(pos.getX(), pos.getY(), pos.getZ()) == face.getAxis() - .choose(otherPos.getX(), otherPos.getY(), otherPos.getZ()) - && connectsTo(state, reader.getBlockState(blockingPos), reader, pos, blockingPos, face); + BlockState blockState = reader.getBlockState(pos); + BlockState blockingState = reader.getBlockState(blockingPos); + + if (!Block.isFaceFull(blockingState.getShape(reader, blockingPos), face.getOpposite())) + return false; + if (face.getAxis() + .choose(pos.getX(), pos.getY(), pos.getZ()) != face.getAxis() + .choose(otherPos.getX(), otherPos.getY(), otherPos.getZ())) + return false; + + return connectsTo(state, + getCTBlockState(reader, blockState, face.getOpposite(), pos.relative(face), blockingPos), reader, pos, + blockingPos, face); } public boolean connectsTo(BlockState state, BlockState other, BlockAndTintGetter reader, BlockPos pos, @@ -43,14 +54,22 @@ public abstract class ConnectedTextureBehaviour { return !isBeingBlocked(state, reader, pos, otherPos, face) && state.getBlock() == other.getBlock(); } - private boolean testConnection(BlockAndTintGetter reader, BlockPos pos, BlockState state, Direction face, - final Direction horizontal, final Direction vertical, int sh, int sv) { - BlockPos p = pos.relative(horizontal, sh) + private boolean testConnection(BlockAndTintGetter reader, BlockPos currentPos, BlockState connectiveCurrentState, + Direction textureSide, final Direction horizontal, final Direction vertical, int sh, int sv) { + BlockState trueCurrentState = reader.getBlockState(currentPos); + BlockPos targetPos = currentPos.relative(horizontal, sh) .relative(vertical, sv); - boolean test = connectsTo(state, reader.getBlockState(p), reader, pos, p, face, + BlockState connectiveTargetState = + getCTBlockState(reader, trueCurrentState, textureSide, currentPos, targetPos); + return connectsTo(connectiveCurrentState, connectiveTargetState, reader, currentPos, targetPos, textureSide, sh == 0 ? null : sh == -1 ? horizontal.getOpposite() : horizontal, sv == 0 ? null : sv == -1 ? vertical.getOpposite() : vertical); - return test; + } + + public BlockState getCTBlockState(BlockAndTintGetter reader, BlockState reference, Direction face, BlockPos fromPos, + BlockPos toPos) { + BlockState blockState = reader.getBlockState(toPos); + return blockState.getAppearance(reader, toPos, face, reference, fromPos); } protected boolean reverseUVs(BlockState state, Direction face) { @@ -75,7 +94,8 @@ public abstract class ConnectedTextureBehaviour { return axis == Axis.X ? Direction.SOUTH : Direction.WEST; } - public CTContext buildContext(BlockAndTintGetter reader, BlockPos pos, BlockState state, Direction face, ContextRequirement requirement) { + public CTContext buildContext(BlockAndTintGetter reader, BlockPos pos, BlockState state, Direction face, + ContextRequirement requirement) { boolean positive = face.getAxisDirection() == AxisDirection.POSITIVE; Direction h = getRightDirection(reader, pos, state, face); Direction v = getUpDirection(reader, pos, state, face); @@ -139,7 +159,8 @@ public abstract class ConnectedTextureBehaviour { public final boolean up, down, left, right; public final boolean topLeft, topRight, bottomLeft, bottomRight; - public ContextRequirement(boolean up, boolean down, boolean left, boolean right, boolean topLeft, boolean topRight, boolean bottomLeft, boolean bottomRight) { + public ContextRequirement(boolean up, boolean down, boolean left, boolean right, boolean topLeft, + boolean topRight, boolean bottomLeft, boolean bottomRight) { this.up = up; this.down = down; this.left = left; @@ -239,11 +260,12 @@ public abstract class ConnectedTextureBehaviour { public static abstract class Base extends ConnectedTextureBehaviour { @Override @Nullable - public abstract CTSpriteShiftEntry getShift(BlockState state, Direction direction, @Nullable TextureAtlasSprite sprite); + public abstract CTSpriteShiftEntry getShift(BlockState state, Direction direction, + @Nullable TextureAtlasSprite sprite); @Override @Nullable - public CTType getDataType(BlockState state, Direction direction) { + public CTType getDataType(BlockAndTintGetter world, BlockPos pos, BlockState state, Direction direction) { CTSpriteShiftEntry shift = getShift(state, direction, null); if (shift == null) { return null; diff --git a/src/main/java/com/simibubi/create/foundation/block/connected/RotatedPillarCTBehaviour.java b/src/main/java/com/simibubi/create/foundation/block/connected/RotatedPillarCTBehaviour.java index 55611e2bf..b6e5e70ae 100644 --- a/src/main/java/com/simibubi/create/foundation/block/connected/RotatedPillarCTBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/block/connected/RotatedPillarCTBehaviour.java @@ -1,7 +1,8 @@ package com.simibubi.create.foundation.block.connected; -import com.simibubi.create.content.palettes.ConnectedPillarBlock; -import com.simibubi.create.content.palettes.LayeredBlock; +import com.simibubi.create.content.decoration.copycat.CopycatBlock; +import com.simibubi.create.content.decoration.palettes.ConnectedPillarBlock; +import com.simibubi.create.content.decoration.palettes.LayeredBlock; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.core.BlockPos; @@ -27,6 +28,10 @@ public class RotatedPillarCTBehaviour extends HorizontalCTBehaviour { return false; if (isBeingBlocked(state, reader, pos, otherPos, face)) return false; + if (reader.getBlockState(pos).getBlock() instanceof CopycatBlock) + return true; + if (reader.getBlockState(otherPos).getBlock() instanceof CopycatBlock) + return true; if (primaryOffset != null && primaryOffset.getAxis() != stateAxis && !ConnectedPillarBlock.getConnection(state, primaryOffset)) return false; diff --git a/src/main/java/com/simibubi/create/foundation/block/render/CustomBlockModels.java b/src/main/java/com/simibubi/create/foundation/block/render/CustomBlockModels.java index 8dc43b692..a6abf0101 100644 --- a/src/main/java/com/simibubi/create/foundation/block/render/CustomBlockModels.java +++ b/src/main/java/com/simibubi/create/foundation/block/render/CustomBlockModels.java @@ -16,7 +16,8 @@ import net.minecraftforge.registries.ForgeRegistries; public class CustomBlockModels { private final Multimap> modelFuncs = MultimapBuilder.hashKeys().arrayListValues().build(); - private final Map> finalModelFunc = new IdentityHashMap<>(); + private final Map> finalModelFuncs = new IdentityHashMap<>(); + private boolean funcsLoaded = false; public void register(ResourceLocation block, NonNullFunction func) { modelFuncs.put(block, func); @@ -24,16 +25,18 @@ public class CustomBlockModels { public void forEach(NonNullBiConsumer> consumer) { loadEntriesIfMissing(); - finalModelFunc.forEach(consumer); + finalModelFuncs.forEach(consumer); } private void loadEntriesIfMissing() { - if (finalModelFunc.isEmpty()) + if (!funcsLoaded) { loadEntries(); + funcsLoaded = true; + } } private void loadEntries() { - finalModelFunc.clear(); + finalModelFuncs.clear(); modelFuncs.asMap().forEach((location, funcList) -> { Block block = ForgeRegistries.BLOCKS.getValue(location); if (block == null) { @@ -49,7 +52,7 @@ public class CustomBlockModels { } } - finalModelFunc.put(block, finalFunc); + finalModelFuncs.put(block, finalFunc); }); } diff --git a/src/main/java/com/simibubi/create/foundation/block/render/QuadHelper.java b/src/main/java/com/simibubi/create/foundation/block/render/QuadHelper.java deleted file mode 100644 index 8c59fccc3..000000000 --- a/src/main/java/com/simibubi/create/foundation/block/render/QuadHelper.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.simibubi.create.foundation.block.render; - -import java.util.Arrays; - -import com.mojang.blaze3d.vertex.DefaultVertexFormat; -import com.mojang.blaze3d.vertex.VertexFormat; - -import net.minecraft.client.renderer.block.model.BakedQuad; - -public final class QuadHelper { - - public static final VertexFormat FORMAT = DefaultVertexFormat.BLOCK; - public static final int VERTEX_STRIDE = FORMAT.getIntegerSize(); - - public static final int X_OFFSET = 0; - public static final int Y_OFFSET = 1; - public static final int Z_OFFSET = 2; - public static final int COLOR_OFFSET = 3; - public static final int U_OFFSET = 4; - public static final int V_OFFSET = 5; - public static final int LIGHT_OFFSET = 6; - public static final int NORMAL_OFFSET = 7; - - private QuadHelper() {} - - public static BakedQuad clone(BakedQuad quad) { - return new BakedQuad(Arrays.copyOf(quad.getVertices(), quad.getVertices().length), - quad.getTintIndex(), quad.getDirection(), quad.getSprite(), quad.isShade()); - } - - public static float getU(int[] vertexData, int vertex) { - return Float.intBitsToFloat(vertexData[vertex * VERTEX_STRIDE + U_OFFSET]); - } - - public static float getV(int[] vertexData, int vertex) { - return Float.intBitsToFloat(vertexData[vertex * VERTEX_STRIDE + V_OFFSET]); - } - - public static void setU(int[] vertexData, int vertex, float u) { - vertexData[vertex * VERTEX_STRIDE + U_OFFSET] = Float.floatToRawIntBits(u); - } - - public static void setV(int[] vertexData, int vertex, float v) { - vertexData[vertex * VERTEX_STRIDE + V_OFFSET] = Float.floatToRawIntBits(v); - } - -} diff --git a/src/main/java/com/simibubi/create/foundation/block/render/SpriteShifter.java b/src/main/java/com/simibubi/create/foundation/block/render/SpriteShifter.java index 0b97d60b7..a9bcb3644 100644 --- a/src/main/java/com/simibubi/create/foundation/block/render/SpriteShifter.java +++ b/src/main/java/com/simibubi/create/foundation/block/render/SpriteShifter.java @@ -4,6 +4,8 @@ import java.util.HashMap; import java.util.Map; import net.minecraft.resources.ResourceLocation; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; public class SpriteShifter { @@ -15,7 +17,7 @@ public class SpriteShifter { return ENTRY_CACHE.get(key); SpriteShiftEntry entry = new SpriteShiftEntry(); - entry.set(originalLocation, targetLocation); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> entry.set(originalLocation, targetLocation)); ENTRY_CACHE.put(key, entry); return entry; } diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/CachedRenderBBBlockEntity.java b/src/main/java/com/simibubi/create/foundation/blockEntity/CachedRenderBBBlockEntity.java new file mode 100644 index 000000000..d8cd7d641 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/CachedRenderBBBlockEntity.java @@ -0,0 +1,35 @@ +package com.simibubi.create.foundation.blockEntity; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public abstract class CachedRenderBBBlockEntity extends SyncedBlockEntity { + + private AABB renderBoundingBox; + + public CachedRenderBBBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + @OnlyIn(Dist.CLIENT) + public AABB getRenderBoundingBox() { + if (renderBoundingBox == null) { + renderBoundingBox = createRenderBoundingBox(); + } + return renderBoundingBox; + } + + protected void invalidateRenderBoundingBox() { + renderBoundingBox = null; + } + + protected AABB createRenderBoundingBox() { + return super.getRenderBoundingBox(); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/ComparatorUtil.java b/src/main/java/com/simibubi/create/foundation/blockEntity/ComparatorUtil.java new file mode 100644 index 000000000..344e1f46e --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/ComparatorUtil.java @@ -0,0 +1,27 @@ +package com.simibubi.create.foundation.blockEntity; + +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.fluid.SmartFluidTankBehaviour; +import com.simibubi.create.foundation.fluid.SmartFluidTank; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.Mth; +import net.minecraft.world.level.BlockGetter; + +public class ComparatorUtil { + + public static int fractionToRedstoneLevel(double frac) { + return Mth.floor(Mth.clamp(frac * 14 + (frac > 0 ? 1 : 0), 0, 15)); + } + + public static int levelOfSmartFluidTank(BlockGetter world, BlockPos pos) { + SmartFluidTankBehaviour fluidBehaviour = BlockEntityBehaviour.get(world, pos, SmartFluidTankBehaviour.TYPE); + if (fluidBehaviour == null) + return 0; + SmartFluidTank primaryHandler = fluidBehaviour.getPrimaryHandler(); + double fillFraction = (double) primaryHandler.getFluid() + .getAmount() / primaryHandler.getCapacity(); + return fractionToRedstoneLevel(fillFraction); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/IMergeableBE.java b/src/main/java/com/simibubi/create/foundation/blockEntity/IMergeableBE.java new file mode 100644 index 000000000..d96340cb1 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/IMergeableBE.java @@ -0,0 +1,9 @@ +package com.simibubi.create.foundation.blockEntity; + +import net.minecraft.world.level.block.entity.BlockEntity; + +public interface IMergeableBE { + + public void accept(BlockEntity other); + +} diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/IMultiBlockEntityContainer.java b/src/main/java/com/simibubi/create/foundation/blockEntity/IMultiBlockEntityContainer.java new file mode 100644 index 000000000..7fc3e8dd0 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/IMultiBlockEntityContainer.java @@ -0,0 +1,75 @@ +package com.simibubi.create.foundation.blockEntity; + +import javax.annotation.Nullable; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.IFluidTank; + +public interface IMultiBlockEntityContainer { + + BlockPos getController(); + T getControllerBE (); + boolean isController(); + void setController(BlockPos pos); + void removeController (boolean keepContents); + BlockPos getLastKnownPos(); + + void preventConnectivityUpdate (); + void notifyMultiUpdated (); + + // only used for FluidTank windows at present. Might be useful for similar properties on other things? + default void setExtraData (@Nullable Object data) {} + @Nullable + default Object getExtraData () { return null; } + default Object modifyExtraData (Object data) { return data; } + + // multiblock structural information + Direction.Axis getMainConnectionAxis(); + default Direction.Axis getMainAxisOf (BlockEntity be) { // this feels redundant, but it gives us a default to use when defining ::getMainConnectionAxis + BlockState state = be.getBlockState(); + + Direction.Axis axis; + if (state.hasProperty(BlockStateProperties.HORIZONTAL_AXIS)) { + axis = state.getValue(BlockStateProperties.HORIZONTAL_AXIS); + } + else if (state.hasProperty(BlockStateProperties.FACING)) { + axis = state.getValue(BlockStateProperties.FACING).getAxis(); + } + else if (state.hasProperty(BlockStateProperties.HORIZONTAL_FACING)) { + axis = state.getValue(BlockStateProperties.HORIZONTAL_FACING).getAxis(); + } + else axis = Direction.Axis.Y; + + return axis; + } + + int getMaxLength (Direction.Axis longAxis, int width); + int getMaxWidth (); + + int getHeight (); + void setHeight (int height); + int getWidth (); + void setWidth (int width); + + public interface Inventory extends IMultiBlockEntityContainer { + default boolean hasInventory() { return false; } + } + + public interface Fluid extends IMultiBlockEntityContainer { + // done here rather than through the Capability to allow greater flexibility + default boolean hasTank() { return false; } + + default int getTankSize(int tank) { return 0; } + + default void setTankSize(int tank, int blocks) {} + + default IFluidTank getTank(int tank) { return null; } + + default FluidStack getFluid(int tank) { return FluidStack.EMPTY; } + } +} diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/RemoveBlockEntityPacket.java b/src/main/java/com/simibubi/create/foundation/blockEntity/RemoveBlockEntityPacket.java new file mode 100644 index 000000000..8cd7ce215 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/RemoveBlockEntityPacket.java @@ -0,0 +1,32 @@ +package com.simibubi.create.foundation.blockEntity; + +import com.simibubi.create.foundation.networking.BlockEntityDataPacket; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.FriendlyByteBuf; + +public class RemoveBlockEntityPacket extends BlockEntityDataPacket { + + public RemoveBlockEntityPacket(BlockPos pos) { + super(pos); + } + + public RemoveBlockEntityPacket(FriendlyByteBuf buffer) { + super(buffer); + } + + @Override + protected void writeData(FriendlyByteBuf buffer) {} + + @Override + protected void handlePacket(SyncedBlockEntity be) { + if (!be.hasLevel()) { + be.setRemoved(); + return; + } + + be.getLevel() + .removeBlockEntity(pos); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/SmartBlockEntity.java b/src/main/java/com/simibubi/create/foundation/blockEntity/SmartBlockEntity.java new file mode 100644 index 000000000..0e3931ad0 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/SmartBlockEntity.java @@ -0,0 +1,269 @@ +package com.simibubi.create.foundation.blockEntity; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; + +import com.simibubi.create.api.event.BlockEntityBehaviourEvent; +import com.simibubi.create.content.schematics.requirement.ISpecialBlockEntityItemRequirement; +import com.simibubi.create.content.schematics.requirement.ItemRequirement; +import com.simibubi.create.foundation.advancement.AdvancementBehaviour; +import com.simibubi.create.foundation.advancement.CreateAdvancement; +import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.utility.IInteractionChecker; +import com.simibubi.create.foundation.utility.IPartialSafeNBT; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.items.CapabilityItemHandler; + +public abstract class SmartBlockEntity extends CachedRenderBBBlockEntity + implements IPartialSafeNBT, IInteractionChecker, ISpecialBlockEntityItemRequirement { + + private final Map, BlockEntityBehaviour> behaviours = new HashMap<>(); + private boolean initialized = false; + private boolean firstNbtRead = true; + protected int lazyTickRate; + protected int lazyTickCounter; + private boolean chunkUnloaded; + + // Used for simulating this BE in a client-only setting + private boolean virtualMode; + + public SmartBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + + setLazyTickRate(10); + + ArrayList list = new ArrayList<>(); + addBehaviours(list); + list.forEach(b -> behaviours.put(b.getType(), b)); + } + + public abstract void addBehaviours(List behaviours); + + /** + * Gets called just before reading block entity data for behaviours. Register + * anything here that depends on your custom BE data. + */ + public void addBehavioursDeferred(List behaviours) {} + + public void initialize() { + if (firstNbtRead) { + firstNbtRead = false; + MinecraftForge.EVENT_BUS.post(new BlockEntityBehaviourEvent<>(this, behaviours)); + } + + forEachBehaviour(BlockEntityBehaviour::initialize); + lazyTick(); + } + + public void tick() { + if (!initialized && hasLevel()) { + initialize(); + initialized = true; + } + + if (lazyTickCounter-- <= 0) { + lazyTickCounter = lazyTickRate; + lazyTick(); + } + + forEachBehaviour(BlockEntityBehaviour::tick); + } + + public void lazyTick() {} + + /** + * Hook only these in future subclasses of STE + */ + protected void write(CompoundTag tag, boolean clientPacket) { + super.saveAdditional(tag); + forEachBehaviour(tb -> tb.write(tag, clientPacket)); + } + + @Override + public void writeSafe(CompoundTag tag) { + super.saveAdditional(tag); + forEachBehaviour(tb -> { + if (tb.isSafeNBT()) + tb.write(tag, false); + }); + } + + /** + * Hook only these in future subclasses of STE + */ + protected void read(CompoundTag tag, boolean clientPacket) { + if (firstNbtRead) { + firstNbtRead = false; + ArrayList list = new ArrayList<>(); + addBehavioursDeferred(list); + list.forEach(b -> behaviours.put(b.getType(), b)); + MinecraftForge.EVENT_BUS.post(new BlockEntityBehaviourEvent<>(this, behaviours)); + } + super.load(tag); + forEachBehaviour(tb -> tb.read(tag, clientPacket)); + } + + @Override + public final void load(CompoundTag tag) { + read(tag, false); + } + + @Override + public void onChunkUnloaded() { + super.onChunkUnloaded(); + chunkUnloaded = true; + } + + @Override + public final void setRemoved() { + super.setRemoved(); + if (!chunkUnloaded) + remove(); + invalidate(); + } + + /** + * Block destroyed or Chunk unloaded. Usually invalidates capabilities + */ + public void invalidate() { + forEachBehaviour(BlockEntityBehaviour::unload); + } + + /** + * Block destroyed or picked up by a contraption. Usually detaches kinetics + */ + public void remove() {} + + /** + * Block destroyed or replaced. Requires Block to call IBE::onRemove + */ + public void destroy() { + forEachBehaviour(BlockEntityBehaviour::destroy); + } + + @Override + public final void saveAdditional(CompoundTag tag) { + write(tag, false); + } + + @Override + public final void readClient(CompoundTag tag) { + read(tag, true); + } + + @Override + public final CompoundTag writeClient(CompoundTag tag) { + write(tag, true); + return tag; + } + + @SuppressWarnings("unchecked") + public T getBehaviour(BehaviourType type) { + return (T) behaviours.get(type); + } + + public void forEachBehaviour(Consumer action) { + getAllBehaviours().forEach(action); + } + + public Collection getAllBehaviours() { + return behaviours.values(); + } + + protected void attachBehaviourLate(BlockEntityBehaviour behaviour) { + behaviours.put(behaviour.getType(), behaviour); + behaviour.initialize(); + } + + public ItemRequirement getRequiredItems(BlockState state) { + return getAllBehaviours().stream() + .reduce(ItemRequirement.NONE, (r, b) -> r.union(b.getRequiredItems()), (r, r1) -> r.union(r1)); + } + + protected void removeBehaviour(BehaviourType type) { + BlockEntityBehaviour remove = behaviours.remove(type); + if (remove != null) { + remove.unload(); + } + } + + public void setLazyTickRate(int slowTickRate) { + this.lazyTickRate = slowTickRate; + this.lazyTickCounter = slowTickRate; + } + + public void markVirtual() { + virtualMode = true; + } + + public boolean isVirtual() { + return virtualMode; + } + + public boolean isChunkUnloaded() { + return chunkUnloaded; + } + + @Override + public boolean canPlayerUse(Player player) { + if (level == null || level.getBlockEntity(worldPosition) != this) + return false; + return player.distanceToSqr(worldPosition.getX() + 0.5D, worldPosition.getY() + 0.5D, + worldPosition.getZ() + 0.5D) <= 64.0D; + } + + public void sendToMenu(FriendlyByteBuf buffer) { + buffer.writeBlockPos(getBlockPos()); + buffer.writeNbt(getUpdateTag()); + } + + @SuppressWarnings("deprecation") + public void refreshBlockState() { + setBlockState(getLevel().getBlockState(getBlockPos())); + } + + protected boolean isItemHandlerCap(Capability cap) { + return cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY; + } + + protected boolean isFluidHandlerCap(Capability cap) { + return cap == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY; + } + + public void registerAwardables(List behaviours, CreateAdvancement... advancements) { + for (BlockEntityBehaviour behaviour : behaviours) { + if (behaviour instanceof AdvancementBehaviour ab) { + ab.add(advancements); + return; + } + } + behaviours.add(new AdvancementBehaviour(this, advancements)); + } + + public void award(CreateAdvancement advancement) { + AdvancementBehaviour behaviour = getBehaviour(AdvancementBehaviour.TYPE); + if (behaviour != null) + behaviour.awardPlayer(advancement); + } + + public void awardIfNear(CreateAdvancement advancement, int range) { + AdvancementBehaviour behaviour = getBehaviour(AdvancementBehaviour.TYPE); + if (behaviour != null) + behaviour.awardPlayerIfNear(advancement, range); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/SmartBlockEntityTicker.java b/src/main/java/com/simibubi/create/foundation/blockEntity/SmartBlockEntityTicker.java new file mode 100644 index 000000000..7485e7f85 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/SmartBlockEntityTicker.java @@ -0,0 +1,18 @@ +package com.simibubi.create.foundation.blockEntity; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityTicker; +import net.minecraft.world.level.block.state.BlockState; + +public class SmartBlockEntityTicker implements BlockEntityTicker { + + @Override + public void tick(Level p_155253_, BlockPos p_155254_, BlockState p_155255_, T p_155256_) { + if (!p_155256_.hasLevel()) + p_155256_.setLevel(p_155253_); + ((SmartBlockEntity) p_155256_).tick(); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/SyncedBlockEntity.java b/src/main/java/com/simibubi/create/foundation/blockEntity/SyncedBlockEntity.java new file mode 100644 index 000000000..842077a84 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/SyncedBlockEntity.java @@ -0,0 +1,74 @@ +package com.simibubi.create.foundation.blockEntity; + +import javax.annotation.ParametersAreNonnullByDefault; + +import net.minecraft.MethodsReturnNonnullByDefault; +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.server.level.ServerLevel; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraftforge.network.PacketDistributor; + +@MethodsReturnNonnullByDefault +@ParametersAreNonnullByDefault +public abstract class SyncedBlockEntity extends BlockEntity { + + public SyncedBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @Override + public CompoundTag getUpdateTag() { + return writeClient(new CompoundTag()); + } + + @Override + public ClientboundBlockEntityDataPacket getUpdatePacket() { + return ClientboundBlockEntityDataPacket.create(this); + } + + @Override + public void handleUpdateTag(CompoundTag tag) { + readClient(tag); + } + + @Override + public void onDataPacket(Connection connection, ClientboundBlockEntityDataPacket packet) { + CompoundTag tag = packet.getTag(); + readClient(tag == null ? new CompoundTag() : tag); + } + + // Special handling for client update packets + public void readClient(CompoundTag tag) { + load(tag); + } + + // Special handling for client update packets + public CompoundTag writeClient(CompoundTag tag) { + saveAdditional(tag); + return tag; + } + + public void sendData() { + if (level instanceof ServerLevel serverLevel) + serverLevel.getChunkSource().blockChanged(getBlockPos()); + } + + public void notifyUpdate() { + setChanged(); + sendData(); + } + + public PacketDistributor.PacketTarget packetTarget() { + return PacketDistributor.TRACKING_CHUNK.with(this::containedChunk); + } + + public LevelChunk containedChunk() { + return level.getChunkAt(worldPosition); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/BehaviourType.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/BehaviourType.java new file mode 100644 index 000000000..4ef84aa6e --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/BehaviourType.java @@ -0,0 +1,23 @@ +package com.simibubi.create.foundation.blockEntity.behaviour; + +public class BehaviourType { + + private String name; + + public BehaviourType(String name) { + this.name = name; + } + + public BehaviourType() { + this(""); + } + + public String getName() { + return name; + } + + @Override + public int hashCode() { + return super.hashCode() * 31 * 493286711; // Better hash table distribution + } +} diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/BlockEntityBehaviour.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/BlockEntityBehaviour.java new file mode 100644 index 000000000..d52125dea --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/BlockEntityBehaviour.java @@ -0,0 +1,109 @@ +package com.simibubi.create.foundation.blockEntity.behaviour; + +import java.util.ConcurrentModificationException; + +import com.simibubi.create.content.schematics.requirement.ItemRequirement; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +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; + +public abstract class BlockEntityBehaviour { + + public SmartBlockEntity blockEntity; + private int lazyTickRate; + private int lazyTickCounter; + + public BlockEntityBehaviour(SmartBlockEntity be) { + blockEntity = be; + setLazyTickRate(10); + } + + public abstract BehaviourType getType(); + + public void initialize() { + + } + + public void tick() { + if (lazyTickCounter-- <= 0) { + lazyTickCounter = lazyTickRate; + lazyTick(); + } + + } + + public void read(CompoundTag nbt, boolean clientPacket) { + + } + + public void write(CompoundTag nbt, boolean clientPacket) { + + } + + public boolean isSafeNBT() { + return false; + } + + public ItemRequirement getRequiredItems() { + return ItemRequirement.NONE; + } + + public void onBlockChanged(BlockState oldState) { + + } + + public void onNeighborChanged(BlockPos neighborPos) { + + } + + /** + * Block destroyed or Chunk unloaded. Usually invalidates capabilities + */ + public void unload() {} + + /** + * Block destroyed or removed. Requires block to call ITE::onRemove + */ + public void destroy() {} + + public void setLazyTickRate(int slowTickRate) { + this.lazyTickRate = slowTickRate; + this.lazyTickCounter = slowTickRate; + } + + public void lazyTick() { + + } + + public BlockPos getPos() { + return blockEntity.getBlockPos(); + } + + public Level getWorld() { + return blockEntity.getLevel(); + } + + public static T get(BlockGetter reader, BlockPos pos, BehaviourType type) { + BlockEntity be; + try { + be = reader.getBlockEntity(pos); + } catch (ConcurrentModificationException e) { + be = null; + } + return get(be, type); + } + + public static T get(BlockEntity be, BehaviourType type) { + if (be == null) + return null; + if (!(be instanceof SmartBlockEntity)) + return null; + SmartBlockEntity ste = (SmartBlockEntity) be; + return ste.getBehaviour(type); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/CenteredSideValueBoxTransform.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/CenteredSideValueBoxTransform.java similarity index 88% rename from src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/CenteredSideValueBoxTransform.java rename to src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/CenteredSideValueBoxTransform.java index 634cd4204..6ecd7615e 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/CenteredSideValueBoxTransform.java +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/CenteredSideValueBoxTransform.java @@ -1,4 +1,4 @@ -package com.simibubi.create.foundation.tileEntity.behaviour; +package com.simibubi.create.foundation.blockEntity.behaviour; import java.util.function.BiPredicate; @@ -22,7 +22,7 @@ public class CenteredSideValueBoxTransform extends ValueBoxTransform.Sided { @Override protected Vec3 getSouthLocation() { - return VecHelper.voxelSpace(8, 8, 16); + return VecHelper.voxelSpace(8, 8, 15.5); } @Override diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueBox.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueBox.java new file mode 100644 index 000000000..95b3cc5bb --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueBox.java @@ -0,0 +1,238 @@ +package com.simibubi.create.foundation.blockEntity.behaviour; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.content.logistics.filter.FilterItem; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform.Sided; +import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.INamedIconOptions; +import com.simibubi.create.foundation.gui.AllIcons; +import com.simibubi.create.foundation.outliner.ChasingAABBOutline; +import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; +import com.simibubi.create.foundation.utility.Components; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.entity.ItemRenderer; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; + +public class ValueBox extends ChasingAABBOutline { + + protected Component label; + protected Component sublabel = Components.immutableEmpty(); + protected Component scrollTooltip = Components.immutableEmpty(); + protected Vec3 labelOffset = Vec3.ZERO; + + public int overrideColor = -1; + + public boolean isPassive; + + protected BlockPos pos; + protected ValueBoxTransform transform; + protected BlockState blockState; + + protected AllIcons outline = AllIcons.VALUE_BOX_HOVER_4PX; + + public ValueBox(Component label, AABB bb, BlockPos pos) { + this(label, bb, pos, Minecraft.getInstance().level.getBlockState(pos)); + } + + public ValueBox(Component label, AABB bb, BlockPos pos, BlockState state) { + super(bb); + this.label = label; + this.pos = pos; + this.blockState = state; + } + + public ValueBox transform(ValueBoxTransform transform) { + this.transform = transform; + return this; + } + + public ValueBox wideOutline() { + this.outline = AllIcons.VALUE_BOX_HOVER_6PX; + return this; + } + + public ValueBox passive(boolean passive) { + this.isPassive = passive; + return this; + } + + public ValueBox withColor(int color) { + this.overrideColor = color; + return this; + } + + @Override + public void render(PoseStack ms, SuperRenderTypeBuffer buffer, Vec3 camera, float pt) { + boolean hasTransform = transform != null; + if (transform instanceof Sided && params.getHighlightedFace() != null) + ((Sided) transform).fromSide(params.getHighlightedFace()); + if (hasTransform && !transform.shouldRender(blockState)) + return; + + ms.pushPose(); + ms.translate(pos.getX() - camera.x, pos.getY() - camera.y, pos.getZ() - camera.z); + if (hasTransform) + transform.transform(blockState, ms); + + if (!isPassive) { + ms.pushPose(); + ms.scale(-2.01f, -2.01f, 2.01f); + ms.translate(-8 / 16.0, -8 / 16.0, -.5 / 16.0); + getOutline().render(ms, buffer, 0xffffff); + ms.popPose(); + } + + float fontScale = hasTransform ? -transform.getFontScale() : -1 / 64f; + ms.scale(fontScale, fontScale, fontScale); + renderContents(ms, buffer); + + ms.popPose(); + } + + public AllIcons getOutline() { + return outline; + } + + public void renderContents(PoseStack ms, MultiBufferSource buffer) {} + + public static class ItemValueBox extends ValueBox { + ItemStack stack; + int count; + boolean upTo; + + public ItemValueBox(Component label, AABB bb, BlockPos pos, ItemStack stack, int count, boolean upTo) { + super(label, bb, pos); + this.stack = stack; + this.count = count; + this.upTo = upTo; + } + + @Override + public AllIcons getOutline() { + if (!stack.isEmpty()) + return AllIcons.VALUE_BOX_HOVER_6PX; + return super.getOutline(); + } + + @Override + public void renderContents(PoseStack ms, MultiBufferSource buffer) { + super.renderContents(ms, buffer); + if (count == -1) + return; + + Font font = Minecraft.getInstance().font; + boolean wildcard = count == 0 || upTo && count == stack.getMaxStackSize(); + Component countString = Components.literal(wildcard ? "*" : count + ""); + ms.translate(17.5f, -5f, 7f); + + boolean isFilter = stack.getItem() instanceof FilterItem; + boolean isEmpty = stack.isEmpty(); + + ItemRenderer itemRenderer = Minecraft.getInstance() + .getItemRenderer(); + BakedModel modelWithOverrides = itemRenderer.getModel(stack, null, null, 0); + boolean blockItem = modelWithOverrides.isGui3d() && modelWithOverrides.getRenderPasses(stack, false) + .size() <= 1; + + float scale = 1.5f; + ms.translate(-font.width(countString), 0, 0); + + if (isFilter) + ms.translate(-5, 8, 7.25f); + else if (isEmpty) { + ms.translate(-15, -1f, -2.75f); + scale = 1.65f; + } else + ms.translate(-7, 10, blockItem ? 10 + 1 / 4f : 0); + + if (wildcard) + ms.translate(-1, 3f, 0); + + ms.scale(scale, scale, scale); + drawString(ms, buffer, countString, 0, 0, isFilter ? 0xFFFFFF : 0xEDEDED); + ms.translate(0, 0, -1 / 16f); + drawString(ms, buffer, countString, 1 - 1 / 8f, 1 - 1 / 8f, 0x4F4F4F); + } + + } + + public static class TextValueBox extends ValueBox { + Component text; + + public TextValueBox(Component label, AABB bb, BlockPos pos, Component text) { + super(label, bb, pos); + this.text = text; + } + + public TextValueBox(Component label, AABB bb, BlockPos pos, BlockState state, Component text) { + super(label, bb, pos, state); + this.text = text; + } + + @Override + public void renderContents(PoseStack ms, MultiBufferSource buffer) { + super.renderContents(ms, buffer); + Font font = Minecraft.getInstance().font; + float scale = 3; + ms.scale(scale, scale, 1); + ms.translate(-4, -3.75, 5); + + int stringWidth = font.width(text); + float numberScale = (float) font.lineHeight / stringWidth; + boolean singleDigit = stringWidth < 10; + if (singleDigit) + numberScale = numberScale / 2; + float verticalMargin = (stringWidth - font.lineHeight) / 2f; + + ms.scale(numberScale, numberScale, numberScale); + ms.translate(singleDigit ? stringWidth / 2 : 0, singleDigit ? -verticalMargin : verticalMargin, 0); + + int overrideColor = transform.getOverrideColor(); + renderHoveringText(ms, buffer, text, overrideColor != -1 ? overrideColor : 0xEDEDED); + } + + } + + public static class IconValueBox extends ValueBox { + AllIcons icon; + + public IconValueBox(Component label, INamedIconOptions iconValue, AABB bb, BlockPos pos) { + super(label, bb, pos); + icon = iconValue.getIcon(); + } + + @Override + public void renderContents(PoseStack ms, MultiBufferSource buffer) { + super.renderContents(ms, buffer); + float scale = 2 * 16; + ms.scale(scale, scale, scale); + ms.translate(-.5f, -.5f, 5 / 32f); + + int overrideColor = transform.getOverrideColor(); + icon.render(ms, buffer, overrideColor != -1 ? overrideColor : 0xFFFFFF); + } + + } + + protected void renderHoveringText(PoseStack ms, MultiBufferSource buffer, Component text, int color) { + ms.pushPose(); + drawString(ms, buffer, text, 0, 0, color); + ms.popPose(); + } + + private static void drawString(PoseStack ms, MultiBufferSource buffer, Component text, float x, float y, + int color) { + Minecraft.getInstance().font.drawInBatch(text, x, y, color, false, ms.last() + .pose(), buffer, false, 0, LightTexture.FULL_BRIGHT); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueBoxRenderer.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueBoxRenderer.java new file mode 100644 index 000000000..88ef38d93 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueBoxRenderer.java @@ -0,0 +1,95 @@ +package com.simibubi.create.foundation.blockEntity.behaviour; + +import org.joml.Matrix3f; + +import com.jozufozu.flywheel.util.transform.TransformStack; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.content.kinetics.simpleRelays.AbstractSimpleShaftBlock; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.block.model.ItemTransforms.TransformType; +import net.minecraft.client.renderer.entity.ItemRenderer; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.tags.BlockTags; +import net.minecraft.util.Mth; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.Item; +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.FenceBlock; + +public class ValueBoxRenderer { + + public static void renderItemIntoValueBox(ItemStack filter, PoseStack ms, MultiBufferSource buffer, int light, + int overlay) { + ItemRenderer itemRenderer = Minecraft.getInstance() + .getItemRenderer(); + BakedModel modelWithOverrides = itemRenderer.getModel(filter, null, null, 0); + boolean blockItem = modelWithOverrides.isGui3d() && modelWithOverrides.getRenderPasses(filter, false).size() <= 1; + float scale = (!blockItem ? .5f : 1f) + 1 / 64f; + float zOffset = (!blockItem ? -.15f : 0) + customZOffset(filter.getItem()); + ms.scale(scale, scale, scale); + ms.translate(0, 0, zOffset); + itemRenderer.renderStatic(filter, TransformType.FIXED, light, overlay, ms, buffer, 0); + } + + public static void renderFlatItemIntoValueBox(ItemStack filter, PoseStack ms, MultiBufferSource buffer, int light, + int overlay) { + if (filter.isEmpty()) + return; + + int bl = light >> 4 & 0xf; + int sl = light >> 20 & 0xf; + int itemLight = Mth.floor(sl + .5) << 20 | (Mth.floor(bl + .5) & 0xf) << 4; + + ms.pushPose(); + TransformStack.cast(ms) + .rotateX(230); + Matrix3f copy = new Matrix3f(ms.last() + .normal()); + ms.popPose(); + + ms.pushPose(); + TransformStack.cast(ms) + .translate(0, 0, -1 / 4f) + .translate(0, 0, 1 / 32f + .001) + .rotateY(180); + + PoseStack squashedMS = new PoseStack(); + squashedMS.last() + .pose() + .mul(ms.last() + .pose()); + squashedMS.scale(.5f, .5f, 1 / 1024f); + squashedMS.last() + .normal() + .set(copy); + Minecraft.getInstance() + .getItemRenderer() + .renderStatic(filter, TransformType.GUI, itemLight, OverlayTexture.NO_OVERLAY, squashedMS, buffer, 0); + + ms.popPose(); + } + + @SuppressWarnings("deprecation") + private static float customZOffset(Item item) { + float nudge = -.1f; + if (item instanceof BlockItem) { + Block block = ((BlockItem) item).getBlock(); + if (block instanceof AbstractSimpleShaftBlock) + return nudge; + if (block instanceof FenceBlock) + return nudge; + if (block.builtInRegistryHolder() + .is(BlockTags.BUTTONS)) + return nudge; + if (block == Blocks.END_ROD) + return nudge; + } + return 0; + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/ValueBoxTransform.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueBoxTransform.java similarity index 89% rename from src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/ValueBoxTransform.java rename to src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueBoxTransform.java index 9158b824d..65f30cca5 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/ValueBoxTransform.java +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueBoxTransform.java @@ -1,4 +1,4 @@ -package com.simibubi.create.foundation.tileEntity.behaviour; +package com.simibubi.create.foundation.blockEntity.behaviour; import java.util.function.Function; @@ -20,9 +20,9 @@ public abstract class ValueBoxTransform { protected float scale = getScale(); - protected abstract Vec3 getLocalOffset(BlockState state); + public abstract Vec3 getLocalOffset(BlockState state); - protected abstract void rotate(BlockState state, PoseStack ms); + public abstract void rotate(BlockState state, PoseStack ms); public boolean testHit(BlockState state, Vec3 localHit) { Vec3 offset = getLocalOffset(state); @@ -43,6 +43,10 @@ public abstract class ValueBoxTransform { public boolean shouldRender(BlockState state) { return state.getMaterial() != Material.AIR && getLocalOffset(state) != null; } + + public int getOverrideColor() { + return -1; + } protected Vec3 rotateHorizontally(BlockState state, Vec3 vec) { float yRot = 0; @@ -53,11 +57,11 @@ public abstract class ValueBoxTransform { return VecHelper.rotateCentered(vec, yRot, Axis.Y); } - protected float getScale() { - return .4f; + public float getScale() { + return .5f; } - protected float getFontScale() { + public float getFontScale() { return 1 / 64f; } @@ -96,7 +100,7 @@ public abstract class ValueBoxTransform { } @Override - protected Vec3 getLocalOffset(BlockState state) { + public Vec3 getLocalOffset(BlockState state) { Vec3 location = getSouthLocation(); location = VecHelper.rotateCentered(location, AngleHelper.horizontalAngle(getSide()), Axis.Y); location = VecHelper.rotateCentered(location, AngleHelper.verticalAngle(getSide()), Axis.X); @@ -106,7 +110,7 @@ public abstract class ValueBoxTransform { protected abstract Vec3 getSouthLocation(); @Override - protected void rotate(BlockState state, PoseStack ms) { + public void rotate(BlockState state, PoseStack ms) { float yRot = AngleHelper.horizontalAngle(getSide()) + 180; float xRot = getSide() == Direction.UP ? 90 : getSide() == Direction.DOWN ? 270 : 0; TransformStack.cast(ms) diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsBehaviour.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsBehaviour.java new file mode 100644 index 000000000..1c320fc28 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsBehaviour.java @@ -0,0 +1,86 @@ +package com.simibubi.create.foundation.blockEntity.behaviour; + +import com.simibubi.create.content.equipment.clipboard.ClipboardCloneable; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.Vec3; + +public interface ValueSettingsBehaviour extends ClipboardCloneable { + + public static record ValueSettings(int row, int value) { + + public MutableComponent format() { + return Lang.number(value) + .component(); + } + + }; + + public boolean testHit(Vec3 hit); + + public boolean isActive(); + + default boolean onlyVisibleWithWrench() { + return false; + } + + default void newSettingHovered(ValueSettings valueSetting) {} + + public ValueBoxTransform getSlotPositioning(); + + public ValueSettingsBoard createBoard(Player player, BlockHitResult hitResult); + + public void setValueSettings(Player player, ValueSettings valueSetting, boolean ctrlDown); + + public ValueSettings getValueSettings(); + + default boolean acceptsValueSettings() { + return true; + } + + @Override + default String getClipboardKey() { + return "Settings"; + } + + @Override + default boolean writeToClipboard(CompoundTag tag, Direction side) { + if (!acceptsValueSettings()) + return false; + ValueSettings valueSettings = getValueSettings(); + tag.putInt("Value", valueSettings.value()); + tag.putInt("Row", valueSettings.row()); + return true; + } + + @Override + default boolean readFromClipboard(CompoundTag tag, Player player, Direction side, boolean simulate) { + if (!acceptsValueSettings()) + return false; + if (!tag.contains("Value") || !tag.contains("Row")) + return false; + if (simulate) + return true; + setValueSettings(player, new ValueSettings(tag.getInt("Row"), tag.getInt("Value")), false); + return true; + } + + default void playFeedbackSound(BlockEntityBehaviour origin) { + origin.getWorld() + .playSound(null, origin.getPos(), SoundEvents.ITEM_FRAME_ADD_ITEM, SoundSource.BLOCKS, 0.25f, 2f); + origin.getWorld() + .playSound(null, origin.getPos(), SoundEvents.NOTE_BLOCK_IRON_XYLOPHONE.get(), SoundSource.BLOCKS, 0.03f, + 1.125f); + } + + default void onShortInteract(Player player, InteractionHand hand, Direction side) {} + +} diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsBoard.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsBoard.java new file mode 100644 index 000000000..625e64e22 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsBoard.java @@ -0,0 +1,9 @@ +package com.simibubi.create.foundation.blockEntity.behaviour; + +import java.util.List; + +import net.minecraft.network.chat.Component; + +public record ValueSettingsBoard(Component title, int maxValue, int milestoneInterval, List rows, + ValueSettingsFormatter formatter) { +} diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsClient.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsClient.java new file mode 100644 index 000000000..3d4214a8b --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsClient.java @@ -0,0 +1,143 @@ +package com.simibubi.create.foundation.blockEntity.behaviour; + +import java.util.List; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllPackets; +import com.simibubi.create.foundation.gui.ScreenOpener; +import com.simibubi.create.foundation.utility.Color; + +import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.HitResult; +import net.minecraftforge.client.gui.overlay.ForgeGui; +import net.minecraftforge.client.gui.overlay.IGuiOverlay; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; + +public class ValueSettingsClient implements IGuiOverlay { + + private Minecraft mc; + + public int interactHeldTicks = -1; + public BlockPos interactHeldPos = null; + public BehaviourType interactHeldBehaviour = null; + public InteractionHand interactHeldHand = null; + public Direction interactHeldFace = null; + + public List lastHoverTip; + public int hoverTicks; + public int hoverWarmup; + + public ValueSettingsClient() { + mc = Minecraft.getInstance(); + } + + public void cancelIfWarmupAlreadyStarted(PlayerInteractEvent.RightClickBlock event) { + if (interactHeldTicks != -1 && event.getPos() + .equals(interactHeldPos)) { + event.setCanceled(true); + event.setCancellationResult(InteractionResult.FAIL); + } + } + + public void startInteractionWith(BlockPos pos, BehaviourType behaviourType, InteractionHand hand, + Direction side) { + interactHeldTicks = 0; + interactHeldPos = pos; + interactHeldBehaviour = behaviourType; + interactHeldHand = hand; + interactHeldFace = side; + } + + public void cancelInteraction() { + interactHeldTicks = -1; + } + + public void tick() { + if (hoverWarmup > 0) + hoverWarmup--; + if (hoverTicks > 0) + hoverTicks--; + if (interactHeldTicks == -1) + return; + Player player = mc.player; + + if (!ValueSettingsInputHandler.canInteract(player) || AllBlocks.CLIPBOARD.isIn(player.getMainHandItem())) { + cancelInteraction(); + return; + } + HitResult hitResult = mc.hitResult; + if (!(hitResult instanceof BlockHitResult blockHitResult) || !blockHitResult.getBlockPos() + .equals(interactHeldPos)) { + cancelInteraction(); + return; + } + BlockEntityBehaviour behaviour = BlockEntityBehaviour.get(mc.level, interactHeldPos, interactHeldBehaviour); + if (!(behaviour instanceof ValueSettingsBehaviour valueSettingBehaviour) + || !valueSettingBehaviour.testHit(blockHitResult.getLocation())) { + cancelInteraction(); + return; + } + if (!mc.options.keyUse.isDown()) { + AllPackets.getChannel() + .sendToServer( + new ValueSettingsPacket(interactHeldPos, 0, 0, interactHeldHand, interactHeldFace, false)); + cancelInteraction(); + return; + } + + if (interactHeldTicks > 3) + player.swinging = false; + if (interactHeldTicks++ < 5) + return; + ScreenOpener + .open(new ValueSettingsScreen(interactHeldPos, valueSettingBehaviour.createBoard(player, blockHitResult), + valueSettingBehaviour.getValueSettings(), valueSettingBehaviour::newSettingHovered)); + interactHeldTicks = -1; + } + + public void showHoverTip(List tip) { + if (mc.screen != null) + return; + if (hoverWarmup < 6) { + hoverWarmup += 2; + return; + } else + hoverWarmup++; + hoverTicks = hoverTicks == 0 ? 11 : Math.max(hoverTicks, 6); + lastHoverTip = tip; + } + + @Override + public void render(ForgeGui gui, PoseStack poseStack, float partialTicks, int width, int height) { + Minecraft mc = Minecraft.getInstance(); + if (mc.options.hideGui || !ValueSettingsInputHandler.canInteract(mc.player)) + return; + if (hoverTicks == 0 || lastHoverTip == null) + return; + + int x = width / 2; + int y = height - 75 - lastHoverTip.size() * 12; + float alpha = hoverTicks > 5 ? (11 - hoverTicks) / 5f : Math.min(1, hoverTicks / 5f); + + Color color = new Color(0xffffff); + Color titleColor = new Color(0xFBDC7D); + color.setAlpha(alpha); + titleColor.setAlpha(alpha); + + for (int i = 0; i < lastHoverTip.size(); i++) { + MutableComponent mutableComponent = lastHoverTip.get(i); + mc.font.drawShadow(poseStack, mutableComponent, x - mc.font.width(mutableComponent) / 2, y, + (i == 0 ? titleColor : color).getRGB()); + y += 12; + } + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsFormatter.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsFormatter.java new file mode 100644 index 000000000..c8151c9f2 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsFormatter.java @@ -0,0 +1,39 @@ +package com.simibubi.create.foundation.blockEntity.behaviour; + +import java.util.function.Function; + +import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsBehaviour.ValueSettings; +import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.INamedIconOptions; +import com.simibubi.create.foundation.gui.AllIcons; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.network.chat.MutableComponent; + +public class ValueSettingsFormatter { + + private Function formatter; + + public ValueSettingsFormatter(Function formatter) { + this.formatter = formatter; + } + + public MutableComponent format(ValueSettings valueSettings) { + return formatter.apply(valueSettings); + } + + public static class ScrollOptionSettingsFormatter extends ValueSettingsFormatter { + + private INamedIconOptions[] options; + + public ScrollOptionSettingsFormatter(INamedIconOptions[] options) { + super(v -> Lang.translateDirect(options[v.value()].getTranslationKey())); + this.options = options; + } + + public AllIcons getIcon(ValueSettings valueSettings) { + return options[valueSettings.value()].getIcon(); + } + + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsInputHandler.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsInputHandler.java new file mode 100644 index 000000000..5ab4fd684 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsInputHandler.java @@ -0,0 +1,98 @@ +package com.simibubi.create.foundation.blockEntity.behaviour; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllTags.AllItemTags; +import com.simibubi.create.CreateClient; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.SidedFilteringBehaviour; +import com.simibubi.create.foundation.utility.RaycastHelper; + +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.phys.BlockHitResult; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.common.util.FakePlayer; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.fml.LogicalSide; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; + +@EventBusSubscriber +public class ValueSettingsInputHandler { + + @SubscribeEvent + public static void onBlockActivated(PlayerInteractEvent.RightClickBlock event) { + Level world = event.getLevel(); + BlockPos pos = event.getPos(); + Player player = event.getEntity(); + InteractionHand hand = event.getHand(); + + if (!canInteract(player)) + return; + if (AllBlocks.CLIPBOARD.isIn(player.getMainHandItem())) + return; + if (!(world.getBlockEntity(pos)instanceof SmartBlockEntity sbe)) + return; + + if (event.getSide() == LogicalSide.CLIENT) + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, + () -> () -> CreateClient.VALUE_SETTINGS_HANDLER.cancelIfWarmupAlreadyStarted(event)); + + if (event.isCanceled()) + return; + + for (BlockEntityBehaviour behaviour : sbe.getAllBehaviours()) { + if (!(behaviour instanceof ValueSettingsBehaviour valueSettingsBehaviour)) + continue; + + BlockHitResult ray = RaycastHelper.rayTraceRange(world, player, 10); + if (ray == null) + return; + if (behaviour instanceof SidedFilteringBehaviour) { + behaviour = ((SidedFilteringBehaviour) behaviour).get(ray.getDirection()); + if (behaviour == null) + continue; + } + + if (!valueSettingsBehaviour.isActive()) + continue; + if (valueSettingsBehaviour.onlyVisibleWithWrench() + && !AllItemTags.WRENCH.matches(player.getItemInHand(hand))) + continue; + if (valueSettingsBehaviour.getSlotPositioning()instanceof ValueBoxTransform.Sided sidedSlot) { + if (!sidedSlot.isSideActive(sbe.getBlockState(), ray.getDirection())) + continue; + sidedSlot.fromSide(ray.getDirection()); + } + + boolean fakePlayer = player instanceof FakePlayer; + if (!valueSettingsBehaviour.testHit(ray.getLocation()) && !fakePlayer) + continue; + + event.setCanceled(true); + event.setCancellationResult(InteractionResult.SUCCESS); + + if (!valueSettingsBehaviour.acceptsValueSettings() || fakePlayer) { + valueSettingsBehaviour.onShortInteract(player, hand, ray.getDirection()); + return; + } + + if (event.getSide() == LogicalSide.CLIENT) { + BehaviourType type = behaviour.getType(); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> CreateClient.VALUE_SETTINGS_HANDLER + .startInteractionWith(pos, type, hand, ray.getDirection())); + } + + return; + } + } + + public static boolean canInteract(Player player) { + return player != null && !player.isSpectator() && !player.isShiftKeyDown(); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsPacket.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsPacket.java new file mode 100644 index 000000000..27638e80d --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsPacket.java @@ -0,0 +1,77 @@ +package com.simibubi.create.foundation.blockEntity.behaviour; + +import javax.annotation.Nullable; + +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsBehaviour.ValueSettings; +import com.simibubi.create.foundation.networking.BlockEntityConfigurationPacket; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; + +public class ValueSettingsPacket extends BlockEntityConfigurationPacket { + + private int row; + private int value; + private InteractionHand interactHand; + private Direction side; + private boolean ctrlDown; + + public ValueSettingsPacket(BlockPos pos, int row, int value, @Nullable InteractionHand interactHand, Direction side, + boolean ctrlDown) { + super(pos); + this.row = row; + this.value = value; + this.interactHand = interactHand; + this.side = side; + this.ctrlDown = ctrlDown; + } + + public ValueSettingsPacket(FriendlyByteBuf buffer) { + super(buffer); + } + + @Override + protected void writeSettings(FriendlyByteBuf buffer) { + buffer.writeVarInt(value); + buffer.writeVarInt(row); + buffer.writeBoolean(interactHand != null); + if (interactHand != null) + buffer.writeBoolean(interactHand == InteractionHand.MAIN_HAND); + buffer.writeVarInt(side.ordinal()); + buffer.writeBoolean(ctrlDown); + } + + @Override + protected void readSettings(FriendlyByteBuf buffer) { + value = buffer.readVarInt(); + row = buffer.readVarInt(); + if (buffer.readBoolean()) + interactHand = buffer.readBoolean() ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND; + side = Direction.values()[buffer.readVarInt()]; + ctrlDown = buffer.readBoolean(); + } + + @Override + protected void applySettings(ServerPlayer player, SmartBlockEntity be) { + for (BlockEntityBehaviour behaviour : be.getAllBehaviours()) { + if (!(behaviour instanceof ValueSettingsBehaviour valueSettingsBehaviour)) + continue; + if (!valueSettingsBehaviour.acceptsValueSettings()) + continue; + if (interactHand != null) { + valueSettingsBehaviour.onShortInteract(player, interactHand, side); + return; + } + valueSettingsBehaviour.setValueSettings(player, new ValueSettings(row, value), ctrlDown); + return; + } + } + + @Override + protected void applySettings(SmartBlockEntity be) {} + +} diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsScreen.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsScreen.java new file mode 100644 index 000000000..b6192fc8b --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/ValueSettingsScreen.java @@ -0,0 +1,332 @@ +package com.simibubi.create.foundation.blockEntity.behaviour; + +import java.util.function.Consumer; + +import org.lwjgl.glfw.GLFW; + +import com.mojang.blaze3d.platform.Window; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllKeys; +import com.simibubi.create.AllPackets; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsBehaviour.ValueSettings; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsFormatter.ScrollOptionSettingsFormatter; +import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollValueHandler; +import com.simibubi.create.foundation.gui.AbstractSimiScreen; +import com.simibubi.create.foundation.gui.AllGuiTextures; +import com.simibubi.create.foundation.gui.AllIcons; +import com.simibubi.create.foundation.gui.UIRenderHelper; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.client.resources.sounds.SimpleSoundInstance; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.network.chat.Component; +import net.minecraft.util.Mth; +import net.minecraft.world.phys.Vec2; + +public class ValueSettingsScreen extends AbstractSimiScreen { + + private int ticksOpen; + private ValueSettingsBoard board; + private int maxLabelWidth; + private int valueBarWidth; + private BlockPos pos; + private ValueSettings initialSettings; + private ValueSettings lastHovered = new ValueSettings(-1, -1); + private Consumer onHover; + private boolean iconMode; + private int milestoneSize; + private int soundCoolDown; + + public ValueSettingsScreen(BlockPos pos, ValueSettingsBoard board, ValueSettings valueSettings, + Consumer onHover) { + this.pos = pos; + this.board = board; + this.initialSettings = valueSettings; + this.onHover = onHover; + this.iconMode = board.formatter() instanceof ScrollOptionSettingsFormatter; + this.milestoneSize = iconMode ? 8 : 4; + } + + @Override + protected void init() { + int maxValue = board.maxValue(); + maxLabelWidth = 0; + int milestoneCount = maxValue / board.milestoneInterval() + 1; + int scale = maxValue > 128 ? 1 : 2; + + for (Component component : board.rows()) + maxLabelWidth = Math.max(maxLabelWidth, font.width(component)); + if (iconMode) + maxLabelWidth = -18; + + valueBarWidth = (maxValue + 1) * scale + 1 + milestoneCount * milestoneSize; + int width = (maxLabelWidth + 14) + (valueBarWidth + 10); + int height = (board.rows() + .size() * 11); + + setWindowSize(width, height); + super.init(); + + Vec2 coordinateOfValue = getCoordinateOfValue(initialSettings.row(), initialSettings.value()); + setCursor(coordinateOfValue); + } + + private void setCursor(Vec2 coordinateOfValue) { + double guiScale = minecraft.getWindow() + .getGuiScale(); + GLFW.glfwSetCursorPos(minecraft.getWindow() + .getWindow(), coordinateOfValue.x * guiScale, coordinateOfValue.y * guiScale); + } + + public ValueSettings getClosestCoordinate(int mouseX, int mouseY) { + int row = 0; + int column = 0; + boolean milestonesOnly = hasShiftDown(); + + double bestDiff = Double.MAX_VALUE; + for (; row < board.rows() + .size(); row++) { + Vec2 coord = getCoordinateOfValue(row, 0); + double diff = Math.abs(coord.y - mouseY); + if (bestDiff < diff) + break; + bestDiff = diff; + } + row -= 1; + + bestDiff = Double.MAX_VALUE; + for (; column <= board.maxValue(); column++) { + Vec2 coord = getCoordinateOfValue(row, milestonesOnly ? column * board.milestoneInterval() : column); + double diff = Math.abs(coord.x - mouseX); + if (bestDiff < diff) + break; + bestDiff = diff; + } + column -= 1; + + return new ValueSettings(row, + milestonesOnly ? Math.min(column * board.milestoneInterval(), board.maxValue()) : column); + } + + public Vec2 getCoordinateOfValue(int row, int column) { + int scale = board.maxValue() > 128 ? 1 : 2; + float xOut = + guiLeft + ((Math.max(1, column) - 1) / board.milestoneInterval()) * milestoneSize + column * scale + 1.5f; + xOut += maxLabelWidth + 14 + 4; + + if (column % board.milestoneInterval() == 0) + xOut += milestoneSize / 2; + if (column > 0) + xOut += milestoneSize; + + float yOut = guiTop + (row + .5f) * 11 - .5f; + return new Vec2(xOut, yOut); + } + + @Override + protected void renderWindow(PoseStack ms, int mouseX, int mouseY, float partialTicks) { + int x = guiLeft; + int y = guiTop; + int milestoneCount = board.maxValue() / board.milestoneInterval() + 1; + int blitOffset = getBlitOffset(); + int scale = board.maxValue() > 128 ? 1 : 2; + + Component title = board.title(); + Component tip = Lang.translateDirect("gui.value_settings.release_to_confirm", Components.keybind("key.use")); + double fadeIn = Math.pow(Mth.clamp((ticksOpen + partialTicks) / 4.0, 0, 1), 1); + + int fattestLabel = Math.max(font.width(tip), font.width(title)); + if (iconMode) + for (int i = 0; i <= board.maxValue(); i++) + fattestLabel = Math.max(fattestLabel, font.width(board.formatter() + .format(new ValueSettings(0, i)))); + + int fatTipOffset = Math.max(0, fattestLabel + 10 - (windowWidth + 13)) / 2; + int bgWidth = Math.max((windowWidth + 13), fattestLabel + 10); + int fadeInWidth = (int) (bgWidth * fadeIn); + int fadeInStart = (bgWidth - fadeInWidth) / 2 - fatTipOffset; + int additionalHeight = iconMode ? 46 : 33; + + UIRenderHelper.drawStretched(ms, x - 11 + fadeInStart, y - 17, fadeInWidth, windowHeight + additionalHeight, + blitOffset, AllGuiTextures.VALUE_SETTINGS_OUTER_BG); + UIRenderHelper.drawStretched(ms, x - 10 + fadeInStart, y - 18, fadeInWidth - 2, 1, blitOffset, + AllGuiTextures.VALUE_SETTINGS_OUTER_BG); + UIRenderHelper.drawStretched(ms, x - 10 + fadeInStart, y - 17 + windowHeight + additionalHeight, + fadeInWidth - 2, 1, blitOffset, AllGuiTextures.VALUE_SETTINGS_OUTER_BG); + + if (fadeInWidth > fattestLabel) { + int textX = x - 11 - fatTipOffset + bgWidth / 2; + font.draw(ms, title, textX - font.width(title) / 2, y - 14, 0xdddddd); + font.draw(ms, tip, textX - font.width(tip) / 2, y + windowHeight + additionalHeight - 27, 0xdddddd); + } + + renderBrassFrame(ms, x + maxLabelWidth + 14, y - 3, valueBarWidth + 8, board.rows() + .size() * 11 + 5); + UIRenderHelper.drawStretched(ms, x + maxLabelWidth + 17, y, valueBarWidth + 2, board.rows() + .size() * 11 - 1, blitOffset, AllGuiTextures.VALUE_SETTINGS_BAR_BG); + + int originalY = y; + for (Component component : board.rows()) { + int valueBarX = x + maxLabelWidth + 14 + 4; + + if (!iconMode) { + UIRenderHelper.drawCropped(ms, x - 4, y, maxLabelWidth + 8, 11, blitOffset, + AllGuiTextures.VALUE_SETTINGS_LABEL_BG); + for (int w = 0; w < valueBarWidth; w += AllGuiTextures.VALUE_SETTINGS_BAR.width - 1) + UIRenderHelper.drawCropped(ms, valueBarX + w, y + 1, + Math.min(AllGuiTextures.VALUE_SETTINGS_BAR.width - 1, valueBarWidth - w), 8, blitOffset, + AllGuiTextures.VALUE_SETTINGS_BAR); + font.draw(ms, component, x, y + 1, 0x442000); + } + + int milestoneX = valueBarX; + for (int milestone = 0; milestone < milestoneCount; milestone++) { + if (iconMode) + AllGuiTextures.VALUE_SETTINGS_WIDE_MILESTONE.render(ms, milestoneX, y + 1); + else + AllGuiTextures.VALUE_SETTINGS_MILESTONE.render(ms, milestoneX, y + 1); + milestoneX += milestoneSize + board.milestoneInterval() * scale; + } + + y += 11; + } + + if (!iconMode) + renderBrassFrame(ms, x - 7, originalY - 3, maxLabelWidth + 14, board.rows() + .size() * 11 + 5); + + if (ticksOpen < 1) + return; + + ValueSettings closest = getClosestCoordinate(mouseX, mouseY); + + if (!closest.equals(lastHovered)) { + onHover.accept(closest); + if (soundCoolDown == 0) { + float pitch = (closest.value()) / (float) (board.maxValue()); + pitch = Mth.lerp(pitch, 1.15f, 1.5f); + minecraft.getSoundManager() + .play(SimpleSoundInstance.forUI(AllSoundEvents.SCROLL_VALUE.getMainEvent(), pitch, 0.25F)); + ScrollValueHandler.wrenchCog.bump(3, -(closest.value() - lastHovered.value()) * 10); + soundCoolDown = 1; + } + } + lastHovered = closest; + + Vec2 coordinate = getCoordinateOfValue(closest.row(), closest.value()); + Component cursorText = board.formatter() + .format(closest); + + AllIcons cursorIcon = null; + if (board.formatter() instanceof ScrollOptionSettingsFormatter sosf) + cursorIcon = sosf.getIcon(closest); + + int cursorWidth = ((cursorIcon != null ? 16 : font.width(cursorText)) / 2) * 2 + 3; + int cursorX = ((int) (coordinate.x)) - cursorWidth / 2; + int cursorY = ((int) (coordinate.y)) - 7; + + if (cursorIcon != null) { + AllGuiTextures.VALUE_SETTINGS_CURSOR_ICON.render(ms, cursorX - 2, cursorY - 3); + RenderSystem.setShaderColor(0.265625f, 0.125f, 0, 1); + cursorIcon.render(ms, cursorX + 1, cursorY - 1); + RenderSystem.setShaderColor(1, 1, 1, 1); + if (fadeInWidth > fattestLabel) + font.draw(ms, cursorText, x - 11 - fatTipOffset + (bgWidth - font.width(cursorText)) / 2, + originalY + windowHeight + additionalHeight - 40, 0xFBDC7D); + return; + } + + AllGuiTextures.VALUE_SETTINGS_CURSOR_LEFT.render(ms, cursorX - 3, cursorY); + UIRenderHelper.drawCropped(ms, cursorX, cursorY, cursorWidth, 14, blitOffset, + AllGuiTextures.VALUE_SETTINGS_CURSOR); + AllGuiTextures.VALUE_SETTINGS_CURSOR_RIGHT.render(ms, cursorX + cursorWidth, cursorY); + + font.draw(ms, cursorText, cursorX + 2, cursorY + 3, 0x442000); + } + + protected void renderBrassFrame(PoseStack ms, int x, int y, int w, int h) { + AllGuiTextures.BRASS_FRAME_TL.render(ms, x, y); + AllGuiTextures.BRASS_FRAME_TR.render(ms, x + w - 4, y); + AllGuiTextures.BRASS_FRAME_BL.render(ms, x, y + h - 4); + AllGuiTextures.BRASS_FRAME_BR.render(ms, x + w - 4, y + h - 4); + + if (h > 8) { + UIRenderHelper.drawStretched(ms, x, y + 4, 3, h - 8, getBlitOffset(), AllGuiTextures.BRASS_FRAME_LEFT); + UIRenderHelper.drawStretched(ms, x + w - 3, y + 4, 3, h - 8, getBlitOffset(), + AllGuiTextures.BRASS_FRAME_RIGHT); + } + + if (w > 8) { + UIRenderHelper.drawCropped(ms, x + 4, y, w - 8, 3, getBlitOffset(), AllGuiTextures.BRASS_FRAME_TOP); + UIRenderHelper.drawCropped(ms, x + 4, y + h - 3, w - 8, 3, getBlitOffset(), + AllGuiTextures.BRASS_FRAME_BOTTOM); + } + + } + + @Override + public void renderBackground(PoseStack p_238651_1_, int p_238651_2_) { + int a = ((int) (0x50 * Math.min(1, (ticksOpen + AnimationTickHolder.getPartialTicks()) / 20f))) << 24; + fillGradient(p_238651_1_, 0, 0, this.width, this.height, 0x101010 | a, 0x101010 | a); + } + + @Override + public void tick() { + ticksOpen++; + if (soundCoolDown > 0) + soundCoolDown--; + super.tick(); + } + + @Override + public boolean mouseScrolled(double pMouseX, double pMouseY, double pDelta) { + ValueSettings closest = getClosestCoordinate((int) pMouseX, (int) pMouseY); + int column = closest.value() + ((int) Math.signum(pDelta)) * (hasShiftDown() ? board.milestoneInterval() : 1); + column = Mth.clamp(column, 0, board.maxValue()); + if (column == closest.value()) + return false; + setCursor(getCoordinateOfValue(closest.row(), column)); + return true; + } + + @Override + public boolean keyReleased(int pKeyCode, int pScanCode, int pModifiers) { + if (minecraft.options.keyUse.matches(pKeyCode, pScanCode)) { + Window window = minecraft.getWindow(); + double x = minecraft.mouseHandler.xpos() * window.getGuiScaledWidth() / window.getScreenWidth(); + double y = minecraft.mouseHandler.ypos() * window.getGuiScaledHeight() / window.getScreenHeight(); + saveAndClose(x, y); + return true; + } + return super.keyReleased(pKeyCode, pScanCode, pModifiers); + } + + @Override + public boolean mouseReleased(double pMouseX, double pMouseY, int pButton) { + if (minecraft.options.keyUse.matchesMouse(pButton)) { + saveAndClose(pMouseX, pMouseY); + return true; + } + return super.mouseReleased(pMouseX, pMouseY, pButton); + } + + protected void saveAndClose(double pMouseX, double pMouseY) { + ValueSettings closest = getClosestCoordinate((int) pMouseX, (int) pMouseY); + // FIXME: value settings may be face-sensitive on future components + AllPackets.getChannel() + .sendToServer(new ValueSettingsPacket(pos, closest.row(), closest.value(), null, Direction.UP, + AllKeys.ctrlDown())); + onClose(); + } + + @Override + public void onClose() { + super.onClose(); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/edgeInteraction/EdgeInteractionBehaviour.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/edgeInteraction/EdgeInteractionBehaviour.java new file mode 100644 index 000000000..9adb39e0c --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/edgeInteraction/EdgeInteractionBehaviour.java @@ -0,0 +1,54 @@ +package com.simibubi.create.foundation.blockEntity.behaviour.edgeInteraction; + +import java.util.Optional; + +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.Level; + +public class EdgeInteractionBehaviour extends BlockEntityBehaviour { + + public static final BehaviourType TYPE = new BehaviourType<>(); + + ConnectionCallback connectionCallback; + ConnectivityPredicate connectivityPredicate; + Optional requiredItem; + + public EdgeInteractionBehaviour(SmartBlockEntity be, ConnectionCallback callback) { + super(be); + this.connectionCallback = callback; + requiredItem = Optional.empty(); + connectivityPredicate = (world, pos, face, face2) -> true; + } + + public EdgeInteractionBehaviour connectivity(ConnectivityPredicate pred) { + this.connectivityPredicate = pred; + return this; + } + + public EdgeInteractionBehaviour require(Item item) { + this.requiredItem = Optional.of(item); + return this; + } + + @Override + public BehaviourType getType() { + return TYPE; + } + + @FunctionalInterface + public interface ConnectionCallback { + public void apply(Level world, BlockPos clicked, BlockPos neighbour); + } + + @FunctionalInterface + public interface ConnectivityPredicate { + public boolean test(Level world, BlockPos pos, Direction selectedFace, Direction connectedFace); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/edgeInteraction/EdgeInteractionHandler.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/edgeInteraction/EdgeInteractionHandler.java similarity index 92% rename from src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/edgeInteraction/EdgeInteractionHandler.java rename to src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/edgeInteraction/EdgeInteractionHandler.java index 99798bc13..ee72e8c30 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/edgeInteraction/EdgeInteractionHandler.java +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/edgeInteraction/EdgeInteractionHandler.java @@ -1,9 +1,9 @@ -package com.simibubi.create.foundation.tileEntity.behaviour.edgeInteraction; +package com.simibubi.create.foundation.blockEntity.behaviour.edgeInteraction; import java.util.ArrayList; import java.util.List; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.utility.BlockHelper; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.RaycastHelper; @@ -39,7 +39,7 @@ public class EdgeInteractionHandler { if (player.isShiftKeyDown() || player.isSpectator()) return; - EdgeInteractionBehaviour behaviour = TileEntityBehaviour.get(world, pos, EdgeInteractionBehaviour.TYPE); + EdgeInteractionBehaviour behaviour = BlockEntityBehaviour.get(world, pos, EdgeInteractionBehaviour.TYPE); if (behaviour == null) return; if (behaviour.requiredItem.isPresent() && behaviour.requiredItem.get() != heldItem.getItem()) @@ -96,7 +96,7 @@ public class EdgeInteractionHandler { int x = vec.getX(); int y = vec.getY(); int z = vec.getZ(); - double margin = 12 / 16f; + double margin = 10 / 16f; double absX = Math.abs(x) * margin; double absY = Math.abs(y) * margin; double absZ = Math.abs(z) * margin; diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/edgeInteraction/EdgeInteractionRenderer.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/edgeInteraction/EdgeInteractionRenderer.java new file mode 100644 index 000000000..39b55ea7c --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/edgeInteraction/EdgeInteractionRenderer.java @@ -0,0 +1,120 @@ +package com.simibubi.create.foundation.blockEntity.behaviour.edgeInteraction; + +import java.util.ArrayList; +import java.util.List; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.CreateClient; +import com.simibubi.create.content.kinetics.crafter.CrafterHelper; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBox; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; +import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.Vec3; + +public class EdgeInteractionRenderer { + + public static void tick() { + Minecraft mc = Minecraft.getInstance(); + HitResult target = mc.hitResult; + if (target == null || !(target instanceof BlockHitResult)) + return; + + BlockHitResult result = (BlockHitResult) target; + ClientLevel world = mc.level; + BlockPos pos = result.getBlockPos(); + Player player = mc.player; + ItemStack heldItem = player.getMainHandItem(); + + if (player.isShiftKeyDown()) + return; + EdgeInteractionBehaviour behaviour = BlockEntityBehaviour.get(world, pos, EdgeInteractionBehaviour.TYPE); + if (behaviour == null) + return; + if (behaviour.requiredItem.orElse(heldItem.getItem()) != heldItem.getItem()) + return; + + Direction face = result.getDirection(); + List connectiveSides = EdgeInteractionHandler.getConnectiveSides(world, pos, face, behaviour); + if (connectiveSides.isEmpty()) + return; + + Direction closestEdge = connectiveSides.get(0); + double bestDistance = Double.MAX_VALUE; + Vec3 center = VecHelper.getCenterOf(pos); + for (Direction direction : connectiveSides) { + double distance = Vec3.atLowerCornerOf(direction.getNormal()) + .subtract(target.getLocation() + .subtract(center)) + .length(); + if (distance > bestDistance) + continue; + bestDistance = distance; + closestEdge = direction; + } + + AABB bb = EdgeInteractionHandler.getBB(pos, closestEdge); + boolean hit = bb.contains(target.getLocation()); + Vec3 offset = Vec3.atLowerCornerOf(closestEdge.getNormal()) + .scale(.5) + .add(Vec3.atLowerCornerOf(face.getNormal()) + .scale(.469)) + .add(VecHelper.CENTER_OF_ORIGIN); + + ValueBox box = new ValueBox(Components.immutableEmpty(), bb, pos).passive(!hit) + .transform(new EdgeValueBoxTransform(offset)) + .wideOutline(); + CreateClient.OUTLINER.showValueBox("edge", box) + .highlightFace(face); + + if (!hit) + return; + + List tip = new ArrayList<>(); + tip.add(Lang.translateDirect("logistics.crafter.connected")); + tip.add(Lang.translateDirect(CrafterHelper.areCraftersConnected(world, pos, pos.relative(closestEdge)) + ? "logistics.crafter.click_to_separate" + : "logistics.crafter.click_to_merge")); + CreateClient.VALUE_SETTINGS_HANDLER.showHoverTip(tip); + } + + static class EdgeValueBoxTransform extends ValueBoxTransform.Sided { + + private Vec3 add; + + public EdgeValueBoxTransform(Vec3 add) { + this.add = add; + } + + @Override + protected Vec3 getSouthLocation() { + return Vec3.ZERO; + } + + @Override + public Vec3 getLocalOffset(BlockState state) { + return add; + } + + @Override + public void rotate(BlockState state, PoseStack ms) { + super.rotate(state, ms); + } + + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/filtering/FilteringBehaviour.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/filtering/FilteringBehaviour.java new file mode 100644 index 000000000..01db2b804 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/filtering/FilteringBehaviour.java @@ -0,0 +1,386 @@ +package com.simibubi.create.foundation.blockEntity.behaviour.filtering; + +import java.util.function.Consumer; +import java.util.function.Predicate; +import java.util.function.Supplier; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllItems; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.content.logistics.filter.FilterItem; +import com.simibubi.create.content.schematics.requirement.ItemRequirement; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsBoard; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsFormatter; +import com.simibubi.create.foundation.item.ItemHelper; +import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.ChatFormatting; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.util.Mth; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.player.Player; +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 net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.items.ItemHandlerHelper; +import net.minecraftforge.items.wrapper.InvWrapper; + +public class FilteringBehaviour extends BlockEntityBehaviour implements ValueSettingsBehaviour { + + public static final BehaviourType TYPE = new BehaviourType<>(); + + public MutableComponent customLabel; + ValueBoxTransform slotPositioning; + boolean showCount; + + private ItemStack filter; + public int count; + public boolean upTo; + private Predicate predicate; + private Consumer callback; + private Supplier isActive; + private Supplier showCountPredicate; + + boolean recipeFilter; + boolean fluidFilter; + + public FilteringBehaviour(SmartBlockEntity be, ValueBoxTransform slot) { + super(be); + filter = ItemStack.EMPTY; + slotPositioning = slot; + showCount = false; + callback = stack -> { + }; + predicate = stack -> true; + isActive = () -> true; + count = 64; + showCountPredicate = () -> showCount; + recipeFilter = false; + fluidFilter = false; + upTo = true; + } + + @Override + public boolean isSafeNBT() { + return true; + } + + @Override + public void write(CompoundTag nbt, boolean clientPacket) { + nbt.put("Filter", getFilter().serializeNBT()); + nbt.putInt("FilterAmount", count); + nbt.putBoolean("UpTo", upTo); + super.write(nbt, clientPacket); + } + + @Override + public void read(CompoundTag nbt, boolean clientPacket) { + filter = ItemStack.of(nbt.getCompound("Filter")); + count = nbt.getInt("FilterAmount"); + upTo = nbt.getBoolean("UpTo"); + + // Migrate from previous behaviour + if (count == 0) { + upTo = true; + count = filter.getMaxStackSize(); + } + + super.read(nbt, clientPacket); + } + + public FilteringBehaviour withCallback(Consumer filterCallback) { + callback = filterCallback; + return this; + } + + public FilteringBehaviour withPredicate(Predicate filterPredicate) { + predicate = filterPredicate; + return this; + } + + public FilteringBehaviour forRecipes() { + recipeFilter = true; + return this; + } + + public FilteringBehaviour forFluids() { + fluidFilter = true; + return this; + } + + public FilteringBehaviour onlyActiveWhen(Supplier condition) { + isActive = condition; + return this; + } + + public FilteringBehaviour showCountWhen(Supplier condition) { + showCountPredicate = condition; + return this; + } + + public FilteringBehaviour showCount() { + showCount = true; + return this; + } + + public boolean setFilter(Direction face, ItemStack stack) { + return setFilter(stack); + } + + public void setLabel(MutableComponent label) { + this.customLabel = label; + } + + public boolean setFilter(ItemStack stack) { + ItemStack filter = stack.copy(); + if (!filter.isEmpty() && !predicate.test(filter)) + return false; + this.filter = filter; + if (!upTo) + count = Math.min(count, stack.getMaxStackSize()); + callback.accept(filter); + blockEntity.setChanged(); + blockEntity.sendData(); + return true; + } + + @Override + public void setValueSettings(Player player, ValueSettings settings, boolean ctrlDown) { + if (getValueSettings().equals(settings)) + return; + count = Mth.clamp(settings.value(), 1, filter.getMaxStackSize()); + upTo = settings.row() == 0; + blockEntity.setChanged(); + blockEntity.sendData(); + playFeedbackSound(this); + } + + @Override + public ValueSettings getValueSettings() { + return new ValueSettings(upTo ? 0 : 1, count == 0 ? filter.getMaxStackSize() : count); + } + + @Override + public void destroy() { + if (filter.getItem() instanceof FilterItem) { + Vec3 pos = VecHelper.getCenterOf(getPos()); + Level world = getWorld(); + world.addFreshEntity(new ItemEntity(world, pos.x, pos.y, pos.z, filter.copy())); + } + super.destroy(); + } + + @Override + public ItemRequirement getRequiredItems() { + Item filterItem = filter.getItem(); + if (filterItem instanceof FilterItem) + return new ItemRequirement(ItemRequirement.ItemUseType.CONSUME, filterItem); + + return ItemRequirement.NONE; + } + + public ItemStack getFilter(Direction side) { + return getFilter(); + } + + public ItemStack getFilter() { + return filter.copy(); + } + + public boolean isCountVisible() { + return showCountPredicate.get() && filter.getMaxStackSize() > 1; + } + + public boolean test(ItemStack stack) { + return !isActive() || filter.isEmpty() || FilterItem.test(blockEntity.getLevel(), stack, filter); + } + + public boolean test(FluidStack stack) { + return !isActive() || filter.isEmpty() || FilterItem.test(blockEntity.getLevel(), stack, filter); + } + + @Override + public BehaviourType getType() { + return TYPE; + } + + @Override + public boolean testHit(Vec3 hit) { + BlockState state = blockEntity.getBlockState(); + Vec3 localHit = hit.subtract(Vec3.atLowerCornerOf(blockEntity.getBlockPos())); + return slotPositioning.testHit(state, localHit); + } + + public int getAmount() { + return count; + } + + public boolean anyAmount() { + return count == 0; + } + + @Override + public boolean acceptsValueSettings() { + return isCountVisible(); + } + + @Override + public boolean isActive() { + return isActive.get(); + } + + @Override + public ValueBoxTransform getSlotPositioning() { + return slotPositioning; + } + + @Override + public ValueSettingsBoard createBoard(Player player, BlockHitResult hitResult) { + ItemStack filter = getFilter(hitResult.getDirection()); + int maxAmount = (filter.getItem() instanceof FilterItem) ? 64 : filter.getMaxStackSize(); + return new ValueSettingsBoard(Lang.translateDirect("logistics.filter.extracted_amount"), maxAmount, 16, + Lang.translatedOptions("logistics.filter", "up_to", "exactly"), + new ValueSettingsFormatter(this::formatValue)); + } + + public MutableComponent formatValue(ValueSettings value) { + if (value.row() == 0 && value.value() == filter.getMaxStackSize()) + return Lang.translateDirect("logistics.filter.any_amount_short"); + return Components.literal(((value.row() == 0) ? "\u2264" : "=") + Math.max(1, value.value())); + } + + @Override + public void onShortInteract(Player player, InteractionHand hand, Direction side) { + Level level = getWorld(); + BlockPos pos = getPos(); + ItemStack toApply = player.getItemInHand(hand) + .copy(); + + if (AllItems.WRENCH.isIn(toApply)) + return; + if (AllBlocks.MECHANICAL_ARM.isIn(toApply)) + return; + if (level.isClientSide()) + return; + + if (!player.isCreative()) { + if (toApply.getItem() instanceof FilterItem) { + if (toApply.getCount() == 1) + player.setItemInHand(hand, ItemStack.EMPTY); + else + player.getItemInHand(hand) + .shrink(1); + } + } + + if (getFilter().getItem() instanceof FilterItem) { + if (!player.isCreative() || ItemHelper + .extract(new InvWrapper(player.getInventory()), + stack -> ItemHandlerHelper.canItemStacksStack(stack, getFilter()), true) + .isEmpty()) + player.getInventory() + .placeItemBackInInventory(getFilter()); + } + + if (toApply.getItem() instanceof FilterItem) + toApply.setCount(1); + + if (!setFilter(side, toApply)) { + player.displayClientMessage(Lang.translateDirect("logistics.filter.invalid_item"), true); + AllSoundEvents.DENY.playOnServer(player.level, player.blockPosition(), 1, 1); + return; + } + + level.playSound(null, pos, SoundEvents.ITEM_FRAME_ADD_ITEM, SoundSource.BLOCKS, .25f, .1f); + } + + public MutableComponent getLabel() { + if (customLabel != null) + return customLabel; + return Lang.translateDirect( + recipeFilter ? "logistics.recipe_filter" : fluidFilter ? "logistics.fluid_filter" : "logistics.filter"); + } + + @Override + public String getClipboardKey() { + return "Filtering"; + } + + @Override + public boolean writeToClipboard(CompoundTag tag, Direction side) { + ValueSettingsBehaviour.super.writeToClipboard(tag, side); + ItemStack filter = getFilter(side); + tag.put("Filter", filter.serializeNBT()); + return true; + } + + @Override + public boolean readFromClipboard(CompoundTag tag, Player player, Direction side, boolean simulate) { + boolean upstreamResult = ValueSettingsBehaviour.super.readFromClipboard(tag, player, side, simulate); + if (!tag.contains("Filter")) + return upstreamResult; + if (simulate) + return true; + if (getWorld().isClientSide) + return true; + + ItemStack refund = ItemStack.EMPTY; + if (getFilter(side).getItem() instanceof FilterItem && !player.isCreative()) + refund = getFilter(side).copy(); + + ItemStack copied = ItemStack.of(tag.getCompound("Filter")); + + if (copied.getItem() instanceof FilterItem filterType && !player.isCreative()) { + InvWrapper inv = new InvWrapper(player.getInventory()); + + for (boolean preferStacksWithoutData : Iterate.trueAndFalse) { + if (refund.getItem() != filterType && ItemHelper + .extract(inv, stack -> stack.getItem() == filterType && preferStacksWithoutData != stack.hasTag(), + 1, false) + .isEmpty()) + continue; + + if (!refund.isEmpty() && refund.getItem() != filterType) + player.getInventory() + .placeItemBackInInventory(refund); + + setFilter(side, copied); + return true; + } + + player.displayClientMessage(Lang + .translate("logistics.filter.requires_item_in_inventory", copied.getHoverName() + .copy() + .withStyle(ChatFormatting.WHITE)) + .style(ChatFormatting.RED) + .component(), true); + AllSoundEvents.DENY.playOnServer(player.level, player.blockPosition(), 1, 1); + return false; + } + + if (!refund.isEmpty()) + player.getInventory() + .placeItemBackInInventory(refund); + + return setFilter(side, copied); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/filtering/FilteringRenderer.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/filtering/FilteringRenderer.java new file mode 100644 index 000000000..4a6c25756 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/filtering/FilteringRenderer.java @@ -0,0 +1,162 @@ +package com.simibubi.create.foundation.blockEntity.behaviour.filtering; + +import java.util.ArrayList; +import java.util.List; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllSpecialTextures; +import com.simibubi.create.CreateClient; +import com.simibubi.create.content.logistics.filter.FilterItem; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBox; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBox.ItemValueBox; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxRenderer; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform.Sided; +import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.Pair; +import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.Vec3; + +public class FilteringRenderer { + + public static void tick() { + Minecraft mc = Minecraft.getInstance(); + HitResult target = mc.hitResult; + if (target == null || !(target instanceof BlockHitResult)) + return; + + BlockHitResult result = (BlockHitResult) target; + ClientLevel world = mc.level; + BlockPos pos = result.getBlockPos(); + BlockState state = world.getBlockState(pos); + + FilteringBehaviour behaviour = BlockEntityBehaviour.get(world, pos, FilteringBehaviour.TYPE); + if (mc.player.isShiftKeyDown()) + return; + + ItemStack mainhandItem = mc.player.getItemInHand(InteractionHand.MAIN_HAND); + if (behaviour == null) + return; + if (behaviour instanceof SidedFilteringBehaviour) { + behaviour = ((SidedFilteringBehaviour) behaviour).get(result.getDirection()); + if (behaviour == null) + return; + } + if (!behaviour.isActive()) + return; + if (behaviour.slotPositioning instanceof ValueBoxTransform.Sided) + ((Sided) behaviour.slotPositioning).fromSide(result.getDirection()); + if (!behaviour.slotPositioning.shouldRender(state)) + return; + + ItemStack filter = behaviour.getFilter(); + boolean isFilterSlotted = filter.getItem() instanceof FilterItem; + boolean showCount = behaviour.isCountVisible(); + Component label = behaviour.getLabel(); + boolean hit = behaviour.slotPositioning.testHit(state, target.getLocation() + .subtract(Vec3.atLowerCornerOf(pos))); + + AABB emptyBB = new AABB(Vec3.ZERO, Vec3.ZERO); + AABB bb = isFilterSlotted ? emptyBB.inflate(.45f, .31f, .2f) : emptyBB.inflate(.25f); + + ValueBox box = new ItemValueBox(label, bb, pos, filter, showCount ? behaviour.count : -1, behaviour.upTo); + box.passive(!hit || AllBlocks.CLIPBOARD.isIn(mainhandItem)); + + CreateClient.OUTLINER.showValueBox(Pair.of("filter", pos), box.transform(behaviour.slotPositioning)) + .lineWidth(1 / 64f) + .withFaceTexture(hit ? AllSpecialTextures.THIN_CHECKERED : null) + .highlightFace(result.getDirection()); + + if (!hit) + return; + + List tip = new ArrayList<>(); + tip.add(label.copy()); + tip.add(Lang + .translateDirect(filter.isEmpty() ? "logistics.filter.click_to_set" : "logistics.filter.click_to_replace")); + if (showCount) + tip.add(Lang.translateDirect("logistics.filter.hold_to_set_amount")); + + CreateClient.VALUE_SETTINGS_HANDLER.showHoverTip(tip); + } + + public static void renderOnBlockEntity(SmartBlockEntity be, float partialTicks, PoseStack ms, + MultiBufferSource buffer, int light, int overlay) { + + if (be == null || be.isRemoved()) + return; + + if (!be.isVirtual()) { + Entity cameraEntity = Minecraft.getInstance().cameraEntity; + if (cameraEntity != null && be.getLevel() == cameraEntity.getLevel()) { + float max = AllConfigs.client().filterItemRenderDistance.getF(); + if (cameraEntity.position() + .distanceToSqr(VecHelper.getCenterOf(be.getBlockPos())) > (max * max)) { + return; + } + } + } + + FilteringBehaviour behaviour = be.getBehaviour(FilteringBehaviour.TYPE); + if (behaviour == null) + return; + if (!behaviour.isActive()) + return; + if (behaviour.getFilter() + .isEmpty() && !(behaviour instanceof SidedFilteringBehaviour)) + return; + + ValueBoxTransform slotPositioning = behaviour.slotPositioning; + BlockState blockState = be.getBlockState(); + + if (slotPositioning instanceof ValueBoxTransform.Sided) { + ValueBoxTransform.Sided sided = (ValueBoxTransform.Sided) slotPositioning; + Direction side = sided.getSide(); + for (Direction d : Iterate.directions) { + ItemStack filter = behaviour.getFilter(d); + if (filter.isEmpty()) + continue; + + sided.fromSide(d); + if (!slotPositioning.shouldRender(blockState)) + continue; + + ms.pushPose(); + slotPositioning.transform(blockState, ms); + if (AllBlocks.CONTRAPTION_CONTROLS.has(blockState)) + ValueBoxRenderer.renderFlatItemIntoValueBox(filter, ms, buffer, light, overlay); + else + ValueBoxRenderer.renderItemIntoValueBox(filter, ms, buffer, light, overlay); + ms.popPose(); + } + sided.fromSide(side); + return; + } else if (slotPositioning.shouldRender(blockState)) { + ms.pushPose(); + slotPositioning.transform(blockState, ms); + ValueBoxRenderer.renderItemIntoValueBox(behaviour.getFilter(), ms, buffer, light, overlay); + ms.popPose(); + } + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/filtering/SidedFilteringBehaviour.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/filtering/SidedFilteringBehaviour.java similarity index 82% rename from src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/filtering/SidedFilteringBehaviour.java rename to src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/filtering/SidedFilteringBehaviour.java index 87753bc80..d770f8b36 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/filtering/SidedFilteringBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/filtering/SidedFilteringBehaviour.java @@ -1,4 +1,4 @@ -package com.simibubi.create.foundation.tileEntity.behaviour.filtering; +package com.simibubi.create.foundation.blockEntity.behaviour.filtering; import java.util.HashSet; import java.util.IdentityHashMap; @@ -7,10 +7,10 @@ import java.util.Set; import java.util.function.BiFunction; import java.util.function.Predicate; -import com.simibubi.create.content.schematics.ItemRequirement; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform; -import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform.Sided; +import com.simibubi.create.content.schematics.requirement.ItemRequirement; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform.Sided; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.NBTHelper; @@ -27,10 +27,10 @@ public class SidedFilteringBehaviour extends FilteringBehaviour { private BiFunction filterFactory; private Predicate validDirections; - public SidedFilteringBehaviour(SmartTileEntity te, ValueBoxTransform.Sided sidedSlot, + public SidedFilteringBehaviour(SmartBlockEntity be, ValueBoxTransform.Sided sidedSlot, BiFunction filterFactory, Predicate validDirections) { - super(te, sidedSlot); + super(be, sidedSlot); this.filterFactory = filterFactory; this.validDirections = validDirections; sidedFilters = new IdentityHashMap<>(); @@ -54,7 +54,7 @@ public class SidedFilteringBehaviour extends FilteringBehaviour { for (Direction d : Iterate.directions) if (valid.contains(d)) { if (!sidedFilters.containsKey(d)) - sidedFilters.put(d, filterFactory.apply(d, new FilteringBehaviour(tileEntity, slotPositioning))); + sidedFilters.put(d, filterFactory.apply(d, new FilteringBehaviour(blockEntity, slotPositioning))); } else if (sidedFilters.containsKey(d)) removeFilter(d); } @@ -91,11 +91,12 @@ public class SidedFilteringBehaviour extends FilteringBehaviour { } @Override - public void setFilter(Direction side, ItemStack stack) { + public boolean setFilter(Direction side, ItemStack stack) { if (!sidedFilters.containsKey(side)) - return; + return true; sidedFilters.get(side) .setFilter(stack); + return true; } @Override @@ -138,8 +139,8 @@ public class SidedFilteringBehaviour extends FilteringBehaviour { public boolean testHit(Direction direction, Vec3 hit) { ValueBoxTransform.Sided sidedPositioning = (Sided) slotPositioning; - BlockState state = tileEntity.getBlockState(); - Vec3 localHit = hit.subtract(Vec3.atLowerCornerOf(tileEntity.getBlockPos())); + BlockState state = blockEntity.getBlockState(); + Vec3 localHit = hit.subtract(Vec3.atLowerCornerOf(blockEntity.getBlockPos())); return sidedPositioning.fromSide(direction) .testHit(state, localHit); } diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/fluid/SmartFluidTankBehaviour.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/fluid/SmartFluidTankBehaviour.java similarity index 90% rename from src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/fluid/SmartFluidTankBehaviour.java rename to src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/fluid/SmartFluidTankBehaviour.java index 72410381a..4b10c7fd1 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/fluid/SmartFluidTankBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/fluid/SmartFluidTankBehaviour.java @@ -1,14 +1,14 @@ -package com.simibubi.create.foundation.tileEntity.behaviour.fluid; +package com.simibubi.create.foundation.blockEntity.behaviour.fluid; import java.util.function.Consumer; import org.apache.commons.lang3.mutable.MutableInt; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.fluid.CombinedTankWrapper; import com.simibubi.create.foundation.fluid.SmartFluidTank; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType; import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.animation.LerpedFloat; import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; @@ -20,7 +20,7 @@ import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler; -public class SmartFluidTankBehaviour extends TileEntityBehaviour { +public class SmartFluidTankBehaviour extends BlockEntityBehaviour { public static final BehaviourType @@ -38,13 +38,13 @@ public class SmartFluidTankBehaviour extends TileEntityBehaviour { private BehaviourType behaviourType; - public static SmartFluidTankBehaviour single(SmartTileEntity te, int capacity) { - return new SmartFluidTankBehaviour(TYPE, te, 1, capacity, false); + public static SmartFluidTankBehaviour single(SmartBlockEntity be, int capacity) { + return new SmartFluidTankBehaviour(TYPE, be, 1, capacity, false); } - public SmartFluidTankBehaviour(BehaviourType type, SmartTileEntity te, int tanks, + public SmartFluidTankBehaviour(BehaviourType type, SmartBlockEntity be, int tanks, int tankCapacity, boolean enforceVariety) { - super(te); + super(be); insertionAllowed = true; extractionAllowed = true; behaviourType = type; @@ -106,8 +106,8 @@ public class SmartFluidTankBehaviour extends TileEntityBehaviour { updateFluids(); } - forEach(te -> { - LerpedFloat fluidLevel = te.getFluidLevel(); + forEach(be -> { + LerpedFloat fluidLevel = be.getFluidLevel(); if (fluidLevel != null) fluidLevel.tickChaser(); }); @@ -131,8 +131,8 @@ public class SmartFluidTankBehaviour extends TileEntityBehaviour { protected void updateFluids() { fluidUpdateCallback.run(); - tileEntity.sendData(); - tileEntity.setChanged(); + blockEntity.sendData(); + blockEntity.setChanged(); } @Override @@ -239,12 +239,12 @@ public class SmartFluidTankBehaviour extends TileEntityBehaviour { } public void onFluidStackChanged() { - if (!tileEntity.hasLevel()) + if (!blockEntity.hasLevel()) return; fluidLevel.chase(tank.getFluidAmount() / (float) tank.getCapacity(), .25, Chaser.EXP); if (!getWorld().isClientSide) sendDataLazily(); - if (tileEntity.isVirtual() && !tank.getFluid() + if (blockEntity.isVirtual() && !tank.getFluid() .isEmpty()) renderedFluid = tank.getFluid(); } diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/inventory/CapManipulationBehaviourBase.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/inventory/CapManipulationBehaviourBase.java new file mode 100644 index 000000000..79953f71f --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/inventory/CapManipulationBehaviourBase.java @@ -0,0 +1,152 @@ +package com.simibubi.create.foundation.blockEntity.behaviour.inventory; + +import javax.annotation.Nullable; + +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.item.ItemHelper.ExtractionCountMode; +import com.simibubi.create.foundation.utility.BlockFace; + +import net.minecraft.core.BlockPos; +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.BlockStateProperties; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; + +public abstract class CapManipulationBehaviourBase> + extends BlockEntityBehaviour { + + protected InterfaceProvider target; + protected LazyOptional targetCapability; + protected boolean simulateNext; + protected boolean bypassSided; + private boolean findNewNextTick; + + public CapManipulationBehaviourBase(SmartBlockEntity be, InterfaceProvider target) { + super(be); + setLazyTickRate(5); + this.target = target; + targetCapability = LazyOptional.empty(); + simulateNext = false; + bypassSided = false; + } + + protected abstract Capability capability(); + + @Override + public void initialize() { + super.initialize(); + findNewNextTick = true; + } + + @Override + public void onNeighborChanged(BlockPos neighborPos) { + BlockFace targetBlockFace = target.getTarget(getWorld(), blockEntity.getBlockPos(), blockEntity.getBlockState()); + if (targetBlockFace.getConnectedPos() + .equals(neighborPos)) + onHandlerInvalidated(targetCapability); + } + + @SuppressWarnings("unchecked") + public S bypassSidedness() { + bypassSided = true; + return (S) this; + } + + /** + * Only simulate the upcoming operation + */ + @SuppressWarnings("unchecked") + public S simulate() { + simulateNext = true; + return (S) this; + } + + public boolean hasInventory() { + return targetCapability.isPresent(); + } + + @Nullable + public T getInventory() { + return targetCapability.orElse(null); + } + + protected void onHandlerInvalidated(LazyOptional handler) { + findNewNextTick = true; + targetCapability = LazyOptional.empty(); + } + + @Override + public void lazyTick() { + super.lazyTick(); + if (!targetCapability.isPresent()) + findNewCapability(); + } + + @Override + public void tick() { + super.tick(); + if (findNewNextTick || getWorld().getGameTime() % 64 == 0) { + findNewNextTick = false; + findNewCapability(); + } + } + + public int getAmountFromFilter() { + int amount = -1; + FilteringBehaviour filter = blockEntity.getBehaviour(FilteringBehaviour.TYPE); + if (filter != null && !filter.anyAmount()) + amount = filter.getAmount(); + return amount; + } + + public ExtractionCountMode getModeFromFilter() { + ExtractionCountMode mode = ExtractionCountMode.UPTO; + FilteringBehaviour filter = blockEntity.getBehaviour(FilteringBehaviour.TYPE); + if (filter != null && !filter.upTo) + mode = ExtractionCountMode.EXACTLY; + return mode; + } + + public void findNewCapability() { + Level world = getWorld(); + BlockFace targetBlockFace = target.getTarget(world, blockEntity.getBlockPos(), blockEntity.getBlockState()) + .getOpposite(); + BlockPos pos = targetBlockFace.getPos(); + + targetCapability = LazyOptional.empty(); + + if (!world.isLoaded(pos)) + return; + BlockEntity invBE = world.getBlockEntity(pos); + if (invBE == null) + return; + Capability capability = capability(); + targetCapability = + bypassSided ? invBE.getCapability(capability) : invBE.getCapability(capability, targetBlockFace.getFace()); + if (targetCapability.isPresent()) + targetCapability.addListener(this::onHandlerInvalidated); + } + + @FunctionalInterface + public interface InterfaceProvider { + + public static InterfaceProvider towardBlockFacing() { + return (w, p, s) -> new BlockFace(p, + s.hasProperty(BlockStateProperties.FACING) ? s.getValue(BlockStateProperties.FACING) + : s.getValue(BlockStateProperties.HORIZONTAL_FACING)); + } + + public static InterfaceProvider oppositeOfBlockFacing() { + return (w, p, s) -> new BlockFace(p, + (s.hasProperty(BlockStateProperties.FACING) ? s.getValue(BlockStateProperties.FACING) + : s.getValue(BlockStateProperties.HORIZONTAL_FACING)).getOpposite()); + } + + public BlockFace getTarget(Level world, BlockPos pos, BlockState blockState); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/inventory/InvManipulationBehaviour.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/inventory/InvManipulationBehaviour.java new file mode 100644 index 000000000..f1083ba1f --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/inventory/InvManipulationBehaviour.java @@ -0,0 +1,97 @@ +package com.simibubi.create.foundation.blockEntity.behaviour.inventory; + +import java.util.function.Predicate; + +import com.google.common.base.Predicates; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.item.ItemHelper; +import com.simibubi.create.foundation.item.ItemHelper.ExtractionCountMode; + +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemHandlerHelper; + +public class InvManipulationBehaviour extends CapManipulationBehaviourBase { + + // Extra types available for multibehaviour + public static final BehaviourType + + TYPE = new BehaviourType<>(), EXTRACT = new BehaviourType<>(), INSERT = new BehaviourType<>(); + + private BehaviourType behaviourType; + + public static InvManipulationBehaviour forExtraction(SmartBlockEntity be, InterfaceProvider target) { + return new InvManipulationBehaviour(EXTRACT, be, target); + } + + public static InvManipulationBehaviour forInsertion(SmartBlockEntity be, InterfaceProvider target) { + return new InvManipulationBehaviour(INSERT, be, target); + } + + public InvManipulationBehaviour(SmartBlockEntity be, InterfaceProvider target) { + this(TYPE, be, target); + } + + private InvManipulationBehaviour(BehaviourType type, SmartBlockEntity be, + InterfaceProvider target) { + super(be, target); + behaviourType = type; + } + + @Override + protected Capability capability() { + return CapabilityItemHandler.ITEM_HANDLER_CAPABILITY; + } + + public ItemStack extract() { + return extract(getModeFromFilter(), getAmountFromFilter()); + } + + public ItemStack extract(ExtractionCountMode mode, int amount) { + return extract(mode, amount, Predicates.alwaysTrue()); + } + + public ItemStack extract(ExtractionCountMode mode, int amount, Predicate filter) { + boolean shouldSimulate = simulateNext; + simulateNext = false; + + if (getWorld().isClientSide) + return ItemStack.EMPTY; + IItemHandler inventory = targetCapability.orElse(null); + if (inventory == null) + return ItemStack.EMPTY; + + Predicate test = getFilterTest(filter); + ItemStack simulatedItems = ItemHelper.extract(inventory, test, mode, amount, true); + if (shouldSimulate || simulatedItems.isEmpty()) + return simulatedItems; + return ItemHelper.extract(inventory, test, mode, amount, false); + } + + public ItemStack insert(ItemStack stack) { + boolean shouldSimulate = simulateNext; + simulateNext = false; + IItemHandler inventory = targetCapability.orElse(null); + if (inventory == null) + return stack; + return ItemHandlerHelper.insertItemStacked(inventory, stack, shouldSimulate); + } + + protected Predicate getFilterTest(Predicate customFilter) { + Predicate test = customFilter; + FilteringBehaviour filter = blockEntity.getBehaviour(FilteringBehaviour.TYPE); + if (filter != null) + test = customFilter.and(filter::test); + return test; + } + + @Override + public BehaviourType getType() { + return behaviourType; + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/inventory/TankManipulationBehaviour.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/inventory/TankManipulationBehaviour.java similarity index 76% rename from src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/inventory/TankManipulationBehaviour.java rename to src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/inventory/TankManipulationBehaviour.java index 42a77735f..aab7b1261 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/inventory/TankManipulationBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/inventory/TankManipulationBehaviour.java @@ -1,11 +1,11 @@ -package com.simibubi.create.foundation.tileEntity.behaviour.inventory; +package com.simibubi.create.foundation.blockEntity.behaviour.inventory; import java.util.function.Predicate; import com.google.common.base.Predicates; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; -import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType; -import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.fluids.FluidStack; @@ -18,13 +18,13 @@ public class TankManipulationBehaviour extends CapManipulationBehaviourBase OBSERVE = new BehaviourType<>(); private BehaviourType behaviourType; - public TankManipulationBehaviour(SmartTileEntity te, InterfaceProvider target) { - this(OBSERVE, te, target); + public TankManipulationBehaviour(SmartBlockEntity be, InterfaceProvider target) { + this(OBSERVE, be, target); } - private TankManipulationBehaviour(BehaviourType type, SmartTileEntity te, + private TankManipulationBehaviour(BehaviourType type, SmartBlockEntity be, InterfaceProvider target) { - super(te, target); + super(be, target); behaviourType = type; } @@ -50,7 +50,7 @@ public class TankManipulationBehaviour extends CapManipulationBehaviourBase getFilterTest(Predicate customFilter) { Predicate test = customFilter; - FilteringBehaviour filter = tileEntity.getBehaviour(FilteringBehaviour.TYPE); + FilteringBehaviour filter = blockEntity.getBehaviour(FilteringBehaviour.TYPE); if (filter != null) test = customFilter.and(filter::test); return test; diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/scrollValue/BulkScrollValueBehaviour.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/scrollValue/BulkScrollValueBehaviour.java new file mode 100644 index 000000000..685c24bed --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/scrollValue/BulkScrollValueBehaviour.java @@ -0,0 +1,41 @@ +package com.simibubi.create.foundation.blockEntity.behaviour.scrollValue; + +import java.util.List; +import java.util.function.Function; + +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; + +import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.player.Player; + +public class BulkScrollValueBehaviour extends ScrollValueBehaviour { + + Function> groupGetter; + + public BulkScrollValueBehaviour(Component label, SmartBlockEntity be, ValueBoxTransform slot, + Function> groupGetter) { + super(label, be, slot); + this.groupGetter = groupGetter; + } + + @Override + public void setValueSettings(Player player, ValueSettings valueSetting, boolean ctrlDown) { + if (!ctrlDown) { + super.setValueSettings(player, valueSetting, ctrlDown); + return; + } + if (!valueSetting.equals(getValueSettings())) + playFeedbackSound(this); + for (SmartBlockEntity be : getBulk()) { + ScrollValueBehaviour other = be.getBehaviour(ScrollValueBehaviour.TYPE); + if (other != null) + other.setValue(valueSetting.value()); + } + } + + public List getBulk() { + return groupGetter.apply(blockEntity); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/scrollValue/INamedIconOptions.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/scrollValue/INamedIconOptions.java new file mode 100644 index 000000000..821d3ec2a --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/scrollValue/INamedIconOptions.java @@ -0,0 +1,8 @@ +package com.simibubi.create.foundation.blockEntity.behaviour.scrollValue; + +import com.simibubi.create.foundation.gui.AllIcons; + +public interface INamedIconOptions { + AllIcons getIcon(); + String getTranslationKey(); +} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/scrollValue/ScrollOptionBehaviour.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/scrollValue/ScrollOptionBehaviour.java new file mode 100644 index 000000000..262ff9673 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/scrollValue/ScrollOptionBehaviour.java @@ -0,0 +1,43 @@ +package com.simibubi.create.foundation.blockEntity.behaviour.scrollValue; + +import com.google.common.collect.ImmutableList; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsBoard; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsFormatter.ScrollOptionSettingsFormatter; +import com.simibubi.create.foundation.utility.Components; + +import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.phys.BlockHitResult; + +public class ScrollOptionBehaviour & INamedIconOptions> extends ScrollValueBehaviour { + + private E[] options; + + public ScrollOptionBehaviour(Class enum_, Component label, SmartBlockEntity be, ValueBoxTransform slot) { + super(label, be, slot); + options = enum_.getEnumConstants(); + between(0, options.length - 1); + } + + INamedIconOptions getIconForSelected() { + return get(); + } + + public E get() { + return options[value]; + } + + @Override + public ValueSettingsBoard createBoard(Player player, BlockHitResult hitResult) { + return new ValueSettingsBoard(label, max, 1, ImmutableList.of(Components.literal("Select")), + new ScrollOptionSettingsFormatter(options)); + } + + @Override + public String getClipboardKey() { + return options[0].getClass().getSimpleName(); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/scrollValue/ScrollValueBehaviour.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/scrollValue/ScrollValueBehaviour.java new file mode 100644 index 000000000..4af38bb16 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/scrollValue/ScrollValueBehaviour.java @@ -0,0 +1,190 @@ +package com.simibubi.create.foundation.blockEntity.behaviour.scrollValue; + +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; + +import com.google.common.collect.ImmutableList; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBoxTransform; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsBoard; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsFormatter; +import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.util.Mth; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.common.util.FakePlayer; + +public class ScrollValueBehaviour extends BlockEntityBehaviour implements ValueSettingsBehaviour { + + public static final BehaviourType TYPE = new BehaviourType<>(); + + ValueBoxTransform slotPositioning; + Vec3 textShift; + + int min = 0; + protected int max = 1; + public int value; + public Component label; + Consumer callback; + Consumer clientCallback; + Function formatter; + private Supplier isActive; + boolean needsWrench; + + public ScrollValueBehaviour(Component label, SmartBlockEntity be, ValueBoxTransform slot) { + super(be); + this.setLabel(label); + slotPositioning = slot; + callback = i -> { + }; + clientCallback = i -> { + }; + formatter = i -> Integer.toString(i); + value = 0; + isActive = () -> true; + } + + @Override + public boolean isSafeNBT() { + return true; + } + + @Override + public void write(CompoundTag nbt, boolean clientPacket) { + nbt.putInt("ScrollValue", value); + super.write(nbt, clientPacket); + } + + @Override + public void read(CompoundTag nbt, boolean clientPacket) { + value = nbt.getInt("ScrollValue"); + super.read(nbt, clientPacket); + } + + public ScrollValueBehaviour withClientCallback(Consumer valueCallback) { + clientCallback = valueCallback; + return this; + } + + public ScrollValueBehaviour withCallback(Consumer valueCallback) { + callback = valueCallback; + return this; + } + + public ScrollValueBehaviour between(int min, int max) { + this.min = min; + this.max = max; + return this; + } + + public ScrollValueBehaviour requiresWrench() { + this.needsWrench = true; + return this; + } + + public ScrollValueBehaviour withFormatter(Function formatter) { + this.formatter = formatter; + return this; + } + + public ScrollValueBehaviour onlyActiveWhen(Supplier condition) { + isActive = condition; + return this; + } + + public void setValue(int value) { + value = Mth.clamp(value, min, max); + if (value == this.value) + return; + this.value = value; + callback.accept(value); + blockEntity.setChanged(); + blockEntity.sendData(); + } + + public int getValue() { + return value; + } + + public String formatValue() { + return formatter.apply(value); + } + + @Override + public BehaviourType getType() { + return TYPE; + } + + @Override + public boolean isActive() { + return isActive.get(); + } + + @Override + public boolean testHit(Vec3 hit) { + BlockState state = blockEntity.getBlockState(); + Vec3 localHit = hit.subtract(Vec3.atLowerCornerOf(blockEntity.getBlockPos())); + return slotPositioning.testHit(state, localHit); + } + + public void setLabel(Component label) { + this.label = label; + } + + public static class StepContext { + public int currentValue; + public boolean forward; + public boolean shift; + public boolean control; + } + + @Override + public ValueBoxTransform getSlotPositioning() { + return slotPositioning; + } + + @Override + public ValueSettingsBoard createBoard(Player player, BlockHitResult hitResult) { + return new ValueSettingsBoard(label, max, 10, ImmutableList.of(Components.literal("Value")), + new ValueSettingsFormatter(ValueSettings::format)); + } + + @Override + public void setValueSettings(Player player, ValueSettings valueSetting, boolean ctrlDown) { + if (valueSetting.equals(getValueSettings())) + return; + setValue(valueSetting.value()); + playFeedbackSound(this); + } + + @Override + public ValueSettings getValueSettings() { + return new ValueSettings(0, value); + } + + @Override + public boolean onlyVisibleWithWrench() { + return needsWrench; + } + + @Override + public void onShortInteract(Player player, InteractionHand hand, Direction side) { + if (player instanceof FakePlayer) + blockEntity.getBlockState() + .use(getWorld(), player, hand, + new BlockHitResult(VecHelper.getCenterOf(getPos()), side, getPos(), true)); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/scrollValue/ScrollValueHandler.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/scrollValue/ScrollValueHandler.java new file mode 100644 index 000000000..11b820c1d --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/scrollValue/ScrollValueHandler.java @@ -0,0 +1,32 @@ +package com.simibubi.create.foundation.blockEntity.behaviour.scrollValue; + +import com.simibubi.create.foundation.utility.animation.PhysicalFloat; + +import net.minecraft.client.Minecraft; +import net.minecraft.util.Mth; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public class ScrollValueHandler { + + private static float lastPassiveScroll = 0.0f; + private static float passiveScroll = 0.0f; + private static float passiveScrollDirection = 1f; + public static final PhysicalFloat wrenchCog = PhysicalFloat.create() + .withDrag(0.3); + + public static float getScroll(float partialTicks) { + return wrenchCog.getValue(partialTicks) + Mth.lerp(partialTicks, lastPassiveScroll, passiveScroll); + } + + @OnlyIn(Dist.CLIENT) + public static void tick() { + if (!Minecraft.getInstance() + .isPaused()) { + lastPassiveScroll = passiveScroll; + wrenchCog.tick(); + passiveScroll += passiveScrollDirection * 0.5; + } + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/scrollValue/ScrollValueRenderer.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/scrollValue/ScrollValueRenderer.java new file mode 100644 index 000000000..e4878b173 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/scrollValue/ScrollValueRenderer.java @@ -0,0 +1,97 @@ +package com.simibubi.create.foundation.blockEntity.behaviour.scrollValue; + +import java.util.ArrayList; +import java.util.List; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllItems; +import com.simibubi.create.AllKeys; +import com.simibubi.create.CreateClient; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBox; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBox.IconValueBox; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueBox.TextValueBox; +import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.Vec3; + +public class ScrollValueRenderer { + + public static void tick() { + Minecraft mc = Minecraft.getInstance(); + HitResult target = mc.hitResult; + if (target == null || !(target instanceof BlockHitResult)) + return; + + BlockHitResult result = (BlockHitResult) target; + ClientLevel world = mc.level; + BlockPos pos = result.getBlockPos(); + Direction face = result.getDirection(); + + ScrollValueBehaviour behaviour = BlockEntityBehaviour.get(world, pos, ScrollValueBehaviour.TYPE); + if (behaviour == null) + return; + if (!behaviour.isActive()) { + CreateClient.OUTLINER.remove(pos); + return; + } + ItemStack mainhandItem = mc.player.getItemInHand(InteractionHand.MAIN_HAND); + boolean clipboard = AllBlocks.CLIPBOARD.isIn(mainhandItem); + if (behaviour.needsWrench && !AllItems.WRENCH.isIn(mainhandItem) && !clipboard) + return; + boolean highlight = behaviour.testHit(target.getLocation()) && !clipboard; + + if (behaviour instanceof BulkScrollValueBehaviour && AllKeys.ctrlDown()) { + BulkScrollValueBehaviour bulkScrolling = (BulkScrollValueBehaviour) behaviour; + for (SmartBlockEntity smartBlockEntity : bulkScrolling.getBulk()) { + ScrollValueBehaviour other = smartBlockEntity.getBehaviour(ScrollValueBehaviour.TYPE); + if (other != null) + addBox(world, smartBlockEntity.getBlockPos(), face, other, highlight); + } + } else + addBox(world, pos, face, behaviour, highlight); + + if (!highlight) + return; + + List tip = new ArrayList<>(); + tip.add(behaviour.label.copy()); + tip.add(Lang.translateDirect("gui.value_settings.hold_to_edit")); + CreateClient.VALUE_SETTINGS_HANDLER.showHoverTip(tip); + } + + protected static void addBox(ClientLevel world, BlockPos pos, Direction face, ScrollValueBehaviour behaviour, + boolean highlight) { + AABB bb = new AABB(Vec3.ZERO, Vec3.ZERO).inflate(.5f) + .contract(0, 0, -.5f) + .move(0, 0, -.125f); + Component label = behaviour.label; + ValueBox box; + + if (behaviour instanceof ScrollOptionBehaviour) { + box = new IconValueBox(label, ((ScrollOptionBehaviour) behaviour).getIconForSelected(), bb, pos); + } else { + box = new TextValueBox(label, bb, pos, Components.literal(behaviour.formatValue())); + } + + box.passive(!highlight) + .wideOutline(); + + CreateClient.OUTLINER.showValueBox(pos, box.transform(behaviour.slotPositioning)) + .highlightFace(face); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/simple/DeferralBehaviour.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/simple/DeferralBehaviour.java new file mode 100644 index 000000000..3e23d96e1 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/simple/DeferralBehaviour.java @@ -0,0 +1,54 @@ +package com.simibubi.create.foundation.blockEntity.behaviour.simple; + +import java.util.function.Supplier; + +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; + +import net.minecraft.nbt.CompoundTag; + +public class DeferralBehaviour extends BlockEntityBehaviour { + + public static final BehaviourType TYPE = new BehaviourType<>(); + + private boolean needsUpdate; + private Supplier callback; + + public DeferralBehaviour(SmartBlockEntity be, Supplier callback) { + super(be); + this.callback = callback; + } + + @Override + public boolean isSafeNBT() { return true; } + + @Override + public void write(CompoundTag nbt, boolean clientPacket) { + nbt.putBoolean("NeedsUpdate", needsUpdate); + super.write(nbt, clientPacket); + } + + @Override + public void read(CompoundTag nbt, boolean clientPacket) { + needsUpdate = nbt.getBoolean("NeedsUpdate"); + super.read(nbt, clientPacket); + } + + @Override + public void tick() { + super.tick(); + if (needsUpdate && callback.get()) + needsUpdate = false; + } + + public void scheduleUpdate() { + needsUpdate = true; + } + + @Override + public BehaviourType getType() { + return TYPE; + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/renderer/ColoredOverlayBlockEntityRenderer.java b/src/main/java/com/simibubi/create/foundation/blockEntity/renderer/ColoredOverlayBlockEntityRenderer.java new file mode 100644 index 000000000..d45608e71 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/renderer/ColoredOverlayBlockEntityRenderer.java @@ -0,0 +1,35 @@ +package com.simibubi.create.foundation.blockEntity.renderer; + +import com.jozufozu.flywheel.backend.Backend; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.foundation.render.SuperByteBuffer; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.world.level.block.entity.BlockEntity; + +public abstract class ColoredOverlayBlockEntityRenderer extends SafeBlockEntityRenderer { + + public ColoredOverlayBlockEntityRenderer(BlockEntityRendererProvider.Context context) { + } + + @Override + protected void renderSafe(T be, float partialTicks, PoseStack ms, MultiBufferSource buffer, + int light, int overlay) { + + if (Backend.canUseInstancing(be.getLevel())) return; + + SuperByteBuffer render = render(getOverlayBuffer(be), getColor(be, partialTicks), light); + render.renderInto(ms, buffer.getBuffer(RenderType.solid())); + } + + protected abstract int getColor(T be, float partialTicks); + + protected abstract SuperByteBuffer getOverlayBuffer(T be); + + public static SuperByteBuffer render(SuperByteBuffer buffer, int color, int light) { + return buffer.color(color).light(light); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/renderer/SafeBlockEntityRenderer.java b/src/main/java/com/simibubi/create/foundation/blockEntity/renderer/SafeBlockEntityRenderer.java new file mode 100644 index 000000000..1ecb77e29 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/renderer/SafeBlockEntityRenderer.java @@ -0,0 +1,26 @@ +package com.simibubi.create.foundation.blockEntity.renderer; + +import com.mojang.blaze3d.vertex.PoseStack; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.entity.BlockEntity; + +public abstract class SafeBlockEntityRenderer implements BlockEntityRenderer { + @Override + public final void render(T be, float partialTicks, PoseStack ms, MultiBufferSource bufferSource, int light, + int overlay) { + if (isInvalid(be)) + return; + renderSafe(be, partialTicks, ms, bufferSource, light, overlay); + } + + protected abstract void renderSafe(T be, float partialTicks, PoseStack ms, MultiBufferSource bufferSource, int light, + int overlay); + + public boolean isInvalid(T be) { + return !be.hasLevel() || be.getBlockState() + .getBlock() == Blocks.AIR; + } +} diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/renderer/SmartBlockEntityRenderer.java b/src/main/java/com/simibubi/create/foundation/blockEntity/renderer/SmartBlockEntityRenderer.java new file mode 100644 index 000000000..041c97d17 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/renderer/SmartBlockEntityRenderer.java @@ -0,0 +1,23 @@ +package com.simibubi.create.foundation.blockEntity.renderer; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.content.redstone.link.LinkRenderer; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringRenderer; + +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; + +public class SmartBlockEntityRenderer extends SafeBlockEntityRenderer { + + public SmartBlockEntityRenderer(BlockEntityRendererProvider.Context context) { + } + + @Override + protected void renderSafe(T blockEntity, float partialTicks, PoseStack ms, MultiBufferSource buffer, int light, + int overlay) { + FilteringRenderer.renderOnBlockEntity(blockEntity, partialTicks, ms, buffer, light, overlay); + LinkRenderer.renderOnBlockEntity(blockEntity, partialTicks, ms, buffer, light, overlay); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/config/AllConfigs.java b/src/main/java/com/simibubi/create/foundation/config/AllConfigs.java deleted file mode 100644 index 756383840..000000000 --- a/src/main/java/com/simibubi/create/foundation/config/AllConfigs.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.simibubi.create.foundation.config; - -import java.util.EnumMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.function.Supplier; - -import org.apache.commons.lang3.tuple.Pair; - -import com.simibubi.create.foundation.block.BlockStressValues; - -import net.minecraftforge.common.ForgeConfigSpec; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.ModLoadingContext; -import net.minecraftforge.fml.common.Mod.EventBusSubscriber; -import net.minecraftforge.fml.config.ModConfig; -import net.minecraftforge.fml.event.config.ModConfigEvent; - -@EventBusSubscriber(bus = EventBusSubscriber.Bus.MOD) -public class AllConfigs { - - private static final Map CONFIGS = new EnumMap<>(ModConfig.Type.class); - - public static CClient CLIENT; - public static CCommon COMMON; - public static CServer SERVER; - - public static ConfigBase byType(ModConfig.Type type) { - return CONFIGS.get(type); - } - - private static T register(Supplier factory, ModConfig.Type side) { - Pair specPair = new ForgeConfigSpec.Builder().configure(builder -> { - T config = factory.get(); - config.registerAll(builder); - return config; - }); - - T config = specPair.getLeft(); - config.specification = specPair.getRight(); - CONFIGS.put(side, config); - return config; - } - - public static void register(ModLoadingContext context) { - CLIENT = register(CClient::new, ModConfig.Type.CLIENT); - COMMON = register(CCommon::new, ModConfig.Type.COMMON); - SERVER = register(CServer::new, ModConfig.Type.SERVER); - - for (Entry pair : CONFIGS.entrySet()) - context.registerConfig(pair.getKey(), pair.getValue().specification); - - BlockStressValues.registerProvider(context.getActiveNamespace(), SERVER.kinetics.stressValues); - } - - @SubscribeEvent - public static void onLoad(ModConfigEvent.Loading event) { - for (ConfigBase config : CONFIGS.values()) - if (config.specification == event.getConfig() - .getSpec()) - config.onLoad(); - } - - @SubscribeEvent - public static void onReload(ModConfigEvent.Reloading event) { - for (ConfigBase config : CONFIGS.values()) - if (config.specification == event.getConfig() - .getSpec()) - config.onReload(); - } - -} diff --git a/src/main/java/com/simibubi/create/foundation/config/CCommon.java b/src/main/java/com/simibubi/create/foundation/config/CCommon.java deleted file mode 100644 index 13847bc11..000000000 --- a/src/main/java/com/simibubi/create/foundation/config/CCommon.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.simibubi.create.foundation.config; - -public class CCommon extends ConfigBase { - - public final CWorldGen worldGen = nested(0, CWorldGen::new, Comments.worldGen); - - @Override - public String getName() { - return "common"; - } - - private static class Comments { - static String worldGen = "Modify Create's impact on your terrain"; - } - -} diff --git a/src/main/java/com/simibubi/create/foundation/config/CCuriosities.java b/src/main/java/com/simibubi/create/foundation/config/CCuriosities.java deleted file mode 100644 index 14ddacd56..000000000 --- a/src/main/java/com/simibubi/create/foundation/config/CCuriosities.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.simibubi.create.foundation.config; - -public class CCuriosities extends ConfigBase { - - public final ConfigInt maxSymmetryWandRange = i(50, 10, "maxSymmetryWandRange", Comments.symmetryRange); - public final ConfigInt placementAssistRange = i(12, 3, "placementAssistRange", Comments.placementRange); - public final ConfigInt toolboxRange = i(10, 1, "toolboxRange", Comments.toolboxRange); - public final ConfigInt airInBacktank = i(900, 1, "airInBacktank", Comments.maxAirInBacktank); - public final ConfigInt enchantedBacktankCapacity = i(300, 1, "enchantedBacktankCapacity", Comments.enchantedBacktankCapacity); - - public final ConfigInt maxExtendoGripActions = i(1000, 0, "maxExtendoGripActions", Comments.maxExtendoGripActions); - public final ConfigInt maxPotatoCannonShots = i(200, 0, "maxPotatoCannonShots", Comments.maxPotatoCannonShots); - -// public ConfigInt zapperUndoLogLength = i(10, 0, "zapperUndoLogLength", Comments.zapperUndoLogLength); NYI - - @Override - public String getName() { - return "curiosities"; - } - - private static class Comments { - static String symmetryRange = "The Maximum Distance to an active mirror for the symmetry wand to trigger."; - static String maxAirInBacktank = - "The Maximum volume of Air that can be stored in a backtank = Seconds of underwater breathing"; - static String enchantedBacktankCapacity = - "The volume of Air added by each level of the backtanks Capacity Enchantment"; - static String placementRange = - "The Maximum Distance a Block placed by Create's placement assist will have to its interaction point."; - static String toolboxRange = - "The Maximum Distance at which a Toolbox can interact with Players' Inventories."; - static String maxExtendoGripActions = - "Amount of free Extendo Grip actions provided by one filled Copper Backtank. Set to 0 makes Extendo Grips unbreakable"; - static String maxPotatoCannonShots = - "Amount of free Potato Cannon shots provided by one filled Copper Backtank. Set to 0 makes Potato Cannons unbreakable"; -// static String zapperUndoLogLength = "The maximum amount of operations a blockzapper can remember for undoing. (0 to disable undo)"; - } - -} diff --git a/src/main/java/com/simibubi/create/foundation/config/CWorldGen.java b/src/main/java/com/simibubi/create/foundation/config/CWorldGen.java deleted file mode 100644 index 3b8a19a2f..000000000 --- a/src/main/java/com/simibubi/create/foundation/config/CWorldGen.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.simibubi.create.foundation.config; - -public class CWorldGen extends ConfigBase { - - public final ConfigBool disable = b(false, "disableWorldGen", Comments.disable); - - @Override - public String getName() { - return "worldgen"; - } - - private static class Comments { - static String disable = "Prevents all worldgen added by Create from taking effect"; - } - -} diff --git a/src/main/java/com/simibubi/create/foundation/config/ConfigBase.java b/src/main/java/com/simibubi/create/foundation/config/ConfigBase.java index 5559a8db4..e8921fbf7 100644 --- a/src/main/java/com/simibubi/create/foundation/config/ConfigBase.java +++ b/src/main/java/com/simibubi/create/foundation/config/ConfigBase.java @@ -21,7 +21,7 @@ public abstract class ConfigBase { protected List> allValues; protected List children; - protected void registerAll(final ForgeConfigSpec.Builder builder) { + public void registerAll(final ForgeConfigSpec.Builder builder) { for (CValue cValue : allValues) cValue.register(builder); } diff --git a/src/main/java/com/simibubi/create/foundation/config/ContraptionMovementSetting.java b/src/main/java/com/simibubi/create/foundation/config/ContraptionMovementSetting.java deleted file mode 100644 index eefabc5ea..000000000 --- a/src/main/java/com/simibubi/create/foundation/config/ContraptionMovementSetting.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.simibubi.create.foundation.config; - -import java.util.Collection; -import java.util.function.Supplier; - -import javax.annotation.Nullable; - -import com.simibubi.create.foundation.utility.CreateRegistry; - -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; -import net.minecraftforge.common.extensions.IForgeBlock; -import net.minecraftforge.registries.ForgeRegistries; - -public enum ContraptionMovementSetting { - MOVABLE, NO_PICKUP, UNMOVABLE; - - private static final CreateRegistry> SETTING_SUPPLIERS = new CreateRegistry<>(ForgeRegistries.BLOCKS); - - public static void register(ResourceLocation block, Supplier settingSupplier) { - SETTING_SUPPLIERS.register(block, settingSupplier); - } - - public static void register(Block block, Supplier settingSupplier) { - SETTING_SUPPLIERS.register(block, settingSupplier); - } - - @Nullable - public static ContraptionMovementSetting get(Block block) { - if (block instanceof IMovementSettingProvider provider) - return provider.getContraptionMovementSetting(); - Supplier supplier = SETTING_SUPPLIERS.get(block); - if (supplier == null) - return null; - return supplier.get(); - } - - public static boolean allAre(Collection blocks, ContraptionMovementSetting are) { - return blocks.stream().anyMatch(b -> get(b.state.getBlock()) == are); - } - - public static boolean isNoPickup(Collection blocks) { - return allAre(blocks, ContraptionMovementSetting.NO_PICKUP); - } - - public static void registerDefaults() { - register(Blocks.SPAWNER, () -> AllConfigs.SERVER.kinetics.spawnerMovement.get()); - register(Blocks.BUDDING_AMETHYST, () -> AllConfigs.SERVER.kinetics.amethystMovement.get()); - register(Blocks.OBSIDIAN, () -> AllConfigs.SERVER.kinetics.obsidianMovement.get()); - register(Blocks.CRYING_OBSIDIAN, () -> AllConfigs.SERVER.kinetics.obsidianMovement.get()); - register(Blocks.RESPAWN_ANCHOR, () -> AllConfigs.SERVER.kinetics.obsidianMovement.get()); - register(Blocks.REINFORCED_DEEPSLATE, () -> AllConfigs.SERVER.kinetics.reinforcedDeepslateMovement.get()); - } - - public interface IMovementSettingProvider extends IForgeBlock { - ContraptionMovementSetting getContraptionMovementSetting(); - } -} diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/BaseConfigScreen.java b/src/main/java/com/simibubi/create/foundation/config/ui/BaseConfigScreen.java index a80623f38..af135847f 100644 --- a/src/main/java/com/simibubi/create/foundation/config/ui/BaseConfigScreen.java +++ b/src/main/java/com/simibubi/create/foundation/config/ui/BaseConfigScreen.java @@ -12,7 +12,6 @@ import org.lwjgl.glfw.GLFW; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.Create; -import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.gui.ScreenOpener; import com.simibubi.create.foundation.gui.Theme; @@ -21,9 +20,10 @@ import com.simibubi.create.foundation.gui.element.DelegatedStencilElement; import com.simibubi.create.foundation.gui.element.TextStencilElement; import com.simibubi.create.foundation.gui.widget.BoxWidget; import com.simibubi.create.foundation.item.TooltipHelper; +import com.simibubi.create.foundation.item.TooltipHelper.Palette; import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.infrastructure.config.AllConfigs; -import net.minecraft.ChatFormatting; import net.minecraft.client.gui.screens.Screen; import net.minecraftforge.common.ForgeConfigSpec; import net.minecraftforge.fml.config.ModConfig; @@ -36,7 +36,7 @@ public class BaseConfigScreen extends ConfigScreen { static { DEFAULTS.put(Create.ID, (base) -> base .withTitles("Client Settings", "World Generation Settings", "Gameplay Settings") - .withSpecs(AllConfigs.CLIENT.specification, AllConfigs.COMMON.specification, AllConfigs.SERVER.specification) + .withSpecs(AllConfigs.client().specification, AllConfigs.common().specification, AllConfigs.server().specification) ); } @@ -70,9 +70,9 @@ public class BaseConfigScreen extends ConfigScreen { ForgeConfigSpec clientSpec; ForgeConfigSpec commonSpec; ForgeConfigSpec serverSpec; - String clientTile = "Client Config"; - String commonTile = "Common Config"; - String serverTile = "Server Config"; + String clientTitle = "Client Config"; + String commonTitle = "Common Config"; + String serverTitle = "Server Config"; String modID; protected boolean returnOnClose; @@ -130,13 +130,13 @@ public class BaseConfigScreen extends ConfigScreen { public BaseConfigScreen withTitles(@Nullable String client, @Nullable String common, @Nullable String server) { if (client != null) - clientTile = client; + clientTitle = client; if (common != null) - commonTile = common; + commonTitle = common; if (server != null) - serverTile = server; + serverTitle = server; return this; } @@ -146,7 +146,7 @@ public class BaseConfigScreen extends ConfigScreen { super.init(); returnOnClose = true; - TextStencilElement clientText = new TextStencilElement(font, Components.literal(clientTile)).centered(true, true); + TextStencilElement clientText = new TextStencilElement(font, Components.literal(clientTitle)).centered(true, true); addRenderableWidget(clientConfigWidget = new BoxWidget(width / 2 - 100, height / 2 - 15 - 30, 200, 16).showingElement(clientText)); if (clientSpec != null) { @@ -158,7 +158,7 @@ public class BaseConfigScreen extends ConfigScreen { clientText.withElementRenderer(DISABLED_RENDERER); } - TextStencilElement commonText = new TextStencilElement(font, Components.literal(commonTile)).centered(true, true); + TextStencilElement commonText = new TextStencilElement(font, Components.literal(commonTitle)).centered(true, true); addRenderableWidget(commonConfigWidget = new BoxWidget(width / 2 - 100, height / 2 - 15, 200, 16).showingElement(commonText)); if (commonSpec != null) { @@ -170,7 +170,7 @@ public class BaseConfigScreen extends ConfigScreen { commonText.withElementRenderer(DISABLED_RENDERER); } - TextStencilElement serverText = new TextStencilElement(font, Components.literal(serverTile)).centered(true, true); + TextStencilElement serverText = new TextStencilElement(font, Components.literal(serverTitle)).centered(true, true); addRenderableWidget(serverConfigWidget = new BoxWidget(width / 2 - 100, height / 2 - 15 + 30, 200, 16).showingElement(serverText)); if (serverSpec == null) { @@ -185,7 +185,7 @@ public class BaseConfigScreen extends ConfigScreen { .addAll(TooltipHelper.cutTextComponent( Components.literal( "Gameplay settings can only be accessed from the in-game menu after joining a World or Server."), - ChatFormatting.GRAY, ChatFormatting.GRAY)); + Palette.ALL_GRAY)); } else { serverConfigWidget.withCallback(() -> linkTo(new SubMenuConfigScreen(this, ModConfig.Type.SERVER, serverSpec))); serverText.withElementRenderer(BoxWidget.gradientFactory.apply(serverConfigWidget)); diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/CConfigureConfigPacket.java b/src/main/java/com/simibubi/create/foundation/config/ui/CConfigureConfigPacket.java index 6e1a12224..33e715d9c 100644 --- a/src/main/java/com/simibubi/create/foundation/config/ui/CConfigureConfigPacket.java +++ b/src/main/java/com/simibubi/create/foundation/config/ui/CConfigureConfigPacket.java @@ -1,7 +1,6 @@ package com.simibubi.create.foundation.config.ui; import java.util.Objects; -import java.util.function.Supplier; import com.simibubi.create.Create; import com.simibubi.create.foundation.networking.SimplePacketBase; @@ -38,10 +37,10 @@ public class CConfigureConfigPacket extends SimplePacketBase { } @Override - public void handle(Supplier context) { - context.get().enqueueWork(() -> { + public boolean handle(NetworkEvent.Context context) { + context.enqueueWork(() -> { try { - ServerPlayer sender = context.get().getSender(); + ServerPlayer sender = context.getSender(); if (sender == null || !sender.hasPermissions(2)) return; @@ -60,8 +59,7 @@ public class CConfigureConfigPacket extends SimplePacketBase { Create.LOGGER.warn("Unable to handle ConfigureConfig Packet. ", e); } }); - - context.get().setPacketHandled(true); + return true; } public String serialize(T value) { diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/ConfigHelper.java b/src/main/java/com/simibubi/create/foundation/config/ui/ConfigHelper.java index af0e38450..2a9cc509a 100644 --- a/src/main/java/com/simibubi/create/foundation/config/ui/ConfigHelper.java +++ b/src/main/java/com/simibubi/create/foundation/config/ui/ConfigHelper.java @@ -19,8 +19,8 @@ import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.simibubi.create.Create; -import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.utility.Pair; +import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraftforge.common.ForgeConfigSpec; import net.minecraftforge.fml.ModContainer; diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/ConfigModListScreen.java b/src/main/java/com/simibubi/create/foundation/config/ui/ConfigModListScreen.java index 9723124ce..bcc59626d 100644 --- a/src/main/java/com/simibubi/create/foundation/config/ui/ConfigModListScreen.java +++ b/src/main/java/com/simibubi/create/foundation/config/ui/ConfigModListScreen.java @@ -13,9 +13,9 @@ import com.simibubi.create.foundation.gui.Theme; import com.simibubi.create.foundation.gui.element.DelegatedStencilElement; import com.simibubi.create.foundation.gui.widget.BoxWidget; import com.simibubi.create.foundation.item.TooltipHelper; +import com.simibubi.create.foundation.item.TooltipHelper.Palette; import com.simibubi.create.foundation.utility.Components; -import net.minecraft.ChatFormatting; import net.minecraft.client.gui.screens.Screen; import net.minecraftforge.fml.ModList; import net.minecraftforge.forgespi.language.IModInfo; @@ -113,7 +113,7 @@ public class ConfigModListScreen extends ConfigScreen { button.updateColorsFromState(); button.modifyElement(e -> ((DelegatedStencilElement) e).withElementRenderer(BaseConfigScreen.DISABLED_RENDERER)); labelTooltip.add(Components.literal(toHumanReadable(id))); - labelTooltip.addAll(TooltipHelper.cutTextComponent(Components.literal("This Mod does not have any configs registered or is not using Forge's config system"), ChatFormatting.GRAY, ChatFormatting.GRAY)); + labelTooltip.addAll(TooltipHelper.cutStringTextComponent("This Mod does not have any configs registered or is not using Forge's config system", Palette.ALL_GRAY)); } listeners.add(button); diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/ConfigScreen.java b/src/main/java/com/simibubi/create/foundation/config/ui/ConfigScreen.java index fa0f94bfb..585c2a03d 100644 --- a/src/main/java/com/simibubi/create/foundation/config/ui/ConfigScreen.java +++ b/src/main/java/com/simibubi/create/foundation/config/ui/ConfigScreen.java @@ -15,14 +15,14 @@ import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock; +import com.simibubi.create.content.kinetics.simpleRelays.CogWheelBlock; import com.simibubi.create.foundation.gui.AbstractSimiScreen; -import com.simibubi.create.foundation.gui.CreateMainMenuScreen; import com.simibubi.create.foundation.gui.UIRenderHelper; import com.simibubi.create.foundation.gui.element.GuiGameElement; import com.simibubi.create.foundation.gui.element.StencilElement; import com.simibubi.create.foundation.utility.animation.Force; import com.simibubi.create.foundation.utility.animation.PhysicalFloat; +import com.simibubi.create.infrastructure.gui.CreateMainMenuScreen; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.Screen; diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/SubMenuConfigScreen.java b/src/main/java/com/simibubi/create/foundation/config/ui/SubMenuConfigScreen.java index ee3b31657..aefc192d0 100644 --- a/src/main/java/com/simibubi/create/foundation/config/ui/SubMenuConfigScreen.java +++ b/src/main/java/com/simibubi/create/foundation/config/ui/SubMenuConfigScreen.java @@ -20,6 +20,7 @@ import com.electronwill.nightconfig.core.AbstractConfig; import com.electronwill.nightconfig.core.UnmodifiableConfig; import com.google.common.collect.Lists; import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllPackets; import com.simibubi.create.foundation.config.ui.ConfigScreenList.LabeledEntry; import com.simibubi.create.foundation.config.ui.entries.BooleanEntry; import com.simibubi.create.foundation.config.ui.entries.EnumEntry; @@ -35,7 +36,7 @@ import com.simibubi.create.foundation.gui.UIRenderHelper; import com.simibubi.create.foundation.gui.element.DelegatedStencilElement; import com.simibubi.create.foundation.gui.widget.BoxWidget; import com.simibubi.create.foundation.item.TooltipHelper; -import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.foundation.item.TooltipHelper.Palette; import com.simibubi.create.foundation.utility.Color; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Couple; @@ -131,7 +132,7 @@ public class SubMenuConfigScreen extends ConfigScreen { configValue.set(change.value); if (type == ModConfig.Type.SERVER) { - AllPackets.channel.sendToServer(new CConfigureConfigPacket<>(ConfigScreen.modID, path, change.value)); + AllPackets.getChannel().sendToServer(new CConfigureConfigPacket<>(ConfigScreen.modID, path, change.value)); } String command = change.annotations.get("Execute"); @@ -192,7 +193,7 @@ public class SubMenuConfigScreen extends ConfigScreen { resetAll.showingElement(AllIcons.I_CONFIG_RESET.asStencil().withElementRenderer(BoxWidget.gradientFactory.apply(resetAll))); resetAll.getToolTip().add(Components.literal("Reset All")); - resetAll.getToolTip().addAll(TooltipHelper.cutStringTextComponent("Click here to reset all settings to their default value.", ChatFormatting.GRAY, ChatFormatting.GRAY)); + resetAll.getToolTip().addAll(TooltipHelper.cutStringTextComponent("Click here to reset all settings to their default value.", Palette.ALL_GRAY)); saveChanges = new BoxWidget(listL - 30, yCenter - 25, 20, 20) .withPadding(2, 2) @@ -212,7 +213,7 @@ public class SubMenuConfigScreen extends ConfigScreen { }); saveChanges.showingElement(AllIcons.I_CONFIG_SAVE.asStencil().withElementRenderer(BoxWidget.gradientFactory.apply(saveChanges))); saveChanges.getToolTip().add(Components.literal("Save Changes")); - saveChanges.getToolTip().addAll(TooltipHelper.cutStringTextComponent("Click here to save your current changes.", ChatFormatting.GRAY, ChatFormatting.GRAY)); + saveChanges.getToolTip().addAll(TooltipHelper.cutStringTextComponent("Click here to save your current changes.", Palette.ALL_GRAY)); discardChanges = new BoxWidget(listL - 30, yCenter + 5, 20, 20) .withPadding(2, 2) @@ -231,7 +232,7 @@ public class SubMenuConfigScreen extends ConfigScreen { }); discardChanges.showingElement(AllIcons.I_CONFIG_DISCARD.asStencil().withElementRenderer(BoxWidget.gradientFactory.apply(discardChanges))); discardChanges.getToolTip().add(Components.literal("Discard Changes")); - discardChanges.getToolTip().addAll(TooltipHelper.cutStringTextComponent("Click here to discard all the changes you made.", ChatFormatting.GRAY, ChatFormatting.GRAY)); + discardChanges.getToolTip().addAll(TooltipHelper.cutStringTextComponent("Click here to discard all the changes you made.", Palette.ALL_GRAY)); goBack = new BoxWidget(listL - 30, yCenter + 65, 20, 20) .withPadding(2, 2) @@ -331,13 +332,13 @@ public class SubMenuConfigScreen extends ConfigScreen { stencil.withElementRenderer((ms, w, h, alpha) -> UIRenderHelper.angledGradient(ms, 90, 8, 0, 16, 16, red)); serverLocked.withBorderColors(red); serverLocked.getToolTip().add(Components.literal("Locked").withStyle(ChatFormatting.BOLD)); - serverLocked.getToolTip().addAll(TooltipHelper.cutStringTextComponent("You do not have enough permissions to edit the server config. You can still look at the current values here though.", ChatFormatting.GRAY, ChatFormatting.GRAY)); + serverLocked.getToolTip().addAll(TooltipHelper.cutStringTextComponent("You do not have enough permissions to edit the server config. You can still look at the current values here though.", Palette.ALL_GRAY)); } else { stencil.withStencilRenderer((ms, w, h, alpha) -> AllIcons.I_CONFIG_UNLOCKED.render(ms, 0, 0)); stencil.withElementRenderer((ms, w, h, alpha) -> UIRenderHelper.angledGradient(ms, 90, 8, 0, 16, 16, green)); serverLocked.withBorderColors(green); serverLocked.getToolTip().add(Components.literal("Unlocked").withStyle(ChatFormatting.BOLD)); - serverLocked.getToolTip().addAll(TooltipHelper.cutStringTextComponent("You have enough permissions to edit the server config. Changes you make here will be synced with the server when you save them.", ChatFormatting.GRAY, ChatFormatting.GRAY)); + serverLocked.getToolTip().addAll(TooltipHelper.cutStringTextComponent("You have enough permissions to edit the server config. Changes you make here will be synced with the server when you save them.", Palette.ALL_GRAY)); } addRenderableWidget(serverLocked); diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/entries/ValueEntry.java b/src/main/java/com/simibubi/create/foundation/config/ui/entries/ValueEntry.java index 1992a4a8c..d892972b9 100644 --- a/src/main/java/com/simibubi/create/foundation/config/ui/entries/ValueEntry.java +++ b/src/main/java/com/simibubi/create/foundation/config/ui/entries/ValueEntry.java @@ -18,6 +18,7 @@ import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.gui.element.DelegatedStencilElement; import com.simibubi.create.foundation.gui.widget.BoxWidget; import com.simibubi.create.foundation.item.TooltipHelper; +import com.simibubi.create.foundation.item.TooltipHelper.Palette; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Pair; @@ -70,15 +71,15 @@ public class ValueEntry extends ConfigScreenList.LabeledEntry { .filter(Predicates.not(s -> s.startsWith("Range"))) .filter(s -> !s.equals(".")) .map(Components::literal) - .flatMap(stc -> TooltipHelper.cutTextComponent(stc, ChatFormatting.GRAY, ChatFormatting.GRAY) + .flatMap(stc -> TooltipHelper.cutTextComponent(stc, Palette.ALL_GRAY) .stream()) .collect(Collectors.toList())); if (annotations.containsKey(ConfigAnnotations.RequiresRelog.TRUE.getName())) - labelTooltip.addAll(TooltipHelper.cutTextComponent(Components.literal("Changing this value will require a _relog_ to take full effect"), ChatFormatting.GRAY, ChatFormatting.GOLD)); + labelTooltip.addAll(TooltipHelper.cutStringTextComponent("Changing this value will require a _relog_ to take full effect", Palette.GRAY_AND_GOLD)); if (annotations.containsKey(ConfigAnnotations.RequiresRestart.CLIENT.getName())) - labelTooltip.addAll(TooltipHelper.cutTextComponent(Components.literal("Changing this value will require a _restart_ to take full effect"), ChatFormatting.GRAY, ChatFormatting.RED)); + labelTooltip.addAll(TooltipHelper.cutStringTextComponent("Changing this value will require a _restart_ to take full effect", Palette.GRAY_AND_RED)); labelTooltip.add(Components.literal(ConfigScreen.modID + ":" + path.get(path.size() - 1)).withStyle(ChatFormatting.DARK_GRAY)); } diff --git a/src/main/java/com/simibubi/create/foundation/data/BlockStateGen.java b/src/main/java/com/simibubi/create/foundation/data/BlockStateGen.java index e11bb2a02..e29e0dbeb 100644 --- a/src/main/java/com/simibubi/create/foundation/data/BlockStateGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/BlockStateGen.java @@ -14,22 +14,23 @@ import org.apache.commons.lang3.tuple.Pair; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.simibubi.create.Create; -import com.simibubi.create.content.contraptions.base.DirectionalAxisKineticBlock; -import com.simibubi.create.content.contraptions.components.steam.whistle.WhistleBlock.WhistleSize; -import com.simibubi.create.content.contraptions.components.steam.whistle.WhistleExtenderBlock; -import com.simibubi.create.content.contraptions.components.steam.whistle.WhistleExtenderBlock.WhistleExtenderShape; -import com.simibubi.create.content.contraptions.components.structureMovement.chassis.LinearChassisBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.chassis.RadialChassisBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssembleRailType; -import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerBlock; -import com.simibubi.create.content.contraptions.fluids.pipes.EncasedPipeBlock; -import com.simibubi.create.content.contraptions.fluids.pipes.FluidPipeBlock; -import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock; +import com.simibubi.create.content.contraptions.chassis.LinearChassisBlock; +import com.simibubi.create.content.contraptions.chassis.RadialChassisBlock; +import com.simibubi.create.content.contraptions.mounted.CartAssembleRailType; +import com.simibubi.create.content.contraptions.mounted.CartAssemblerBlock; +import com.simibubi.create.content.decoration.steamWhistle.WhistleBlock.WhistleSize; +import com.simibubi.create.content.decoration.steamWhistle.WhistleExtenderBlock; +import com.simibubi.create.content.decoration.steamWhistle.WhistleExtenderBlock.WhistleExtenderShape; +import com.simibubi.create.content.fluids.pipes.EncasedPipeBlock; +import com.simibubi.create.content.fluids.pipes.FluidPipeBlock; +import com.simibubi.create.content.kinetics.base.DirectionalAxisKineticBlock; +import com.simibubi.create.content.processing.burner.BlazeBurnerBlock; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Pointing; import com.tterrag.registrate.providers.DataGenContext; import com.tterrag.registrate.providers.RegistrateBlockstateProvider; import com.tterrag.registrate.util.nullness.NonNullBiConsumer; +import com.tterrag.registrate.util.nullness.NonnullType; import net.minecraft.core.Direction; import net.minecraft.core.Direction.Axis; @@ -333,6 +334,21 @@ public class BlockStateGen { }; } + public static

NonNullBiConsumer, RegistrateBlockstateProvider> naturalStoneTypeBlock( + String type) { + return (c, p) -> { + ConfiguredModel[] variants = new ConfiguredModel[4]; + for (int i = 0; i < variants.length; i++) + variants[i] = ConfiguredModel.builder() + .modelFile(p.models() + .cubeAll(type + "_natural_" + i, p.modLoc("block/palettes/stone_types/natural/" + type + "_" + i))) + .buildLast(); + p.getVariantBuilder(c.get()) + .partialState() + .setModels(variants); + }; + } + public static

NonNullBiConsumer, RegistrateBlockstateProvider> encasedPipe() { return (c, p) -> { ModelFile open = AssetLookup.partialBaseModel(c, p, "open"); @@ -522,4 +538,11 @@ public class BlockStateGen { .end(); } + public static Function mapToAir(@NonnullType RegistrateBlockstateProvider p) { + return state -> ConfiguredModel.builder() + .modelFile(p.models() + .getExistingFile(p.mcLoc("block/air"))) + .build(); + } + } diff --git a/src/main/java/com/simibubi/create/foundation/data/BuilderTransformers.java b/src/main/java/com/simibubi/create/foundation/data/BuilderTransformers.java index d33a34abb..34f51e760 100644 --- a/src/main/java/com/simibubi/create/foundation/data/BuilderTransformers.java +++ b/src/main/java/com/simibubi/create/foundation/data/BuilderTransformers.java @@ -18,24 +18,28 @@ import com.simibubi.create.AllBlocks; import com.simibubi.create.AllTags.AllBlockTags; import com.simibubi.create.AllTags.AllItemTags; import com.simibubi.create.Create; -import com.simibubi.create.content.contraptions.base.CasingBlock; -import com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock; -import com.simibubi.create.content.contraptions.components.crank.ValveHandleBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.interaction.DoorMovingInteraction; -import com.simibubi.create.content.contraptions.components.structureMovement.interaction.TrapdoorMovingInteraction; -import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonGenerator; -import com.simibubi.create.content.contraptions.relays.encased.EncasedCTBehaviour; -import com.simibubi.create.content.contraptions.relays.encased.EncasedCogCTBehaviour; -import com.simibubi.create.content.contraptions.relays.encased.EncasedCogwheelBlock; -import com.simibubi.create.content.contraptions.relays.encased.EncasedShaftBlock; -import com.simibubi.create.content.curiosities.deco.SlidingDoorBlock; -import com.simibubi.create.content.curiosities.deco.SlidingDoorMovementBehaviour; -import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelBlock; -import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelBlock.Shape; -import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelItem; -import com.simibubi.create.content.logistics.trains.IBogeyBlock; -import com.simibubi.create.content.logistics.trains.track.StandardBogeyBlock; -import com.simibubi.create.foundation.block.BlockStressDefaults; +import com.simibubi.create.content.contraptions.behaviour.DoorMovingInteraction; +import com.simibubi.create.content.contraptions.behaviour.TrapdoorMovingInteraction; +import com.simibubi.create.content.contraptions.piston.MechanicalPistonGenerator; +import com.simibubi.create.content.decoration.MetalScaffoldingBlock; +import com.simibubi.create.content.decoration.MetalScaffoldingBlockItem; +import com.simibubi.create.content.decoration.MetalScaffoldingCTBehaviour; +import com.simibubi.create.content.decoration.copycat.CopycatBlock; +import com.simibubi.create.content.decoration.encasing.CasingBlock; +import com.simibubi.create.content.decoration.encasing.EncasedCTBehaviour; +import com.simibubi.create.content.decoration.slidingDoor.SlidingDoorBlock; +import com.simibubi.create.content.decoration.slidingDoor.SlidingDoorMovementBehaviour; +import com.simibubi.create.content.kinetics.BlockStressDefaults; +import com.simibubi.create.content.kinetics.base.RotatedPillarKineticBlock; +import com.simibubi.create.content.kinetics.crank.ValveHandleBlock; +import com.simibubi.create.content.kinetics.simpleRelays.encased.EncasedCogCTBehaviour; +import com.simibubi.create.content.kinetics.simpleRelays.encased.EncasedCogwheelBlock; +import com.simibubi.create.content.kinetics.simpleRelays.encased.EncasedShaftBlock; +import com.simibubi.create.content.logistics.tunnel.BeltTunnelBlock; +import com.simibubi.create.content.logistics.tunnel.BeltTunnelBlock.Shape; +import com.simibubi.create.content.logistics.tunnel.BeltTunnelItem; +import com.simibubi.create.content.trains.bogey.AbstractBogeyBlock; +import com.simibubi.create.content.trains.bogey.StandardBogeyBlock; import com.simibubi.create.foundation.block.ItemUseOverrides; import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry; import com.simibubi.create.foundation.block.connected.HorizontalCTBehaviour; @@ -62,6 +66,17 @@ import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.PistonType; import net.minecraft.world.level.material.Material; +import net.minecraft.world.level.material.MaterialColor; +import net.minecraft.world.level.storage.loot.LootPool; +import net.minecraft.world.level.storage.loot.LootTable; +import net.minecraft.world.level.storage.loot.LootTable.Builder; +import net.minecraft.world.level.storage.loot.entries.LootItem; +import net.minecraft.world.level.storage.loot.functions.CopyNameFunction; +import net.minecraft.world.level.storage.loot.functions.CopyNbtFunction; +import net.minecraft.world.level.storage.loot.predicates.ExplosionCondition; +import net.minecraft.world.level.storage.loot.predicates.LootItemCondition; +import net.minecraft.world.level.storage.loot.providers.nbt.ContextNbtProvider; +import net.minecraft.world.level.storage.loot.providers.number.ConstantValue; import net.minecraftforge.client.model.generators.ConfiguredModel; import net.minecraftforge.client.model.generators.ModelFile; @@ -80,6 +95,7 @@ public class BuilderTransformers { .build(); } + @SuppressWarnings("deprecation") public static NonNullUnaryOperator> bogey() { return b -> b.initialProperties(SharedProperties::softMetal) .properties(p -> p.sound(SoundType.NETHERITE_BLOCK)) @@ -88,7 +104,22 @@ public class BuilderTransformers { .blockstate((c, p) -> BlockStateGen.horizontalAxisBlock(c, p, s -> p.models() .getExistingFile(p.modLoc("block/track/bogey/top")))) .loot((p, l) -> p.dropOther(l, AllBlocks.RAILWAY_CASING.get())) - .onRegister(block -> IBogeyBlock.register(RegisteredObjects.getKeyOrThrow(block))); + .onRegister(block -> AbstractBogeyBlock.registerStandardBogey(RegisteredObjects.getKeyOrThrow(block))); + } + + public static NonNullUnaryOperator> copycat() { + return b -> b.initialProperties(SharedProperties::softMetal) + .blockstate((c, p) -> p.simpleBlock(c.get(), p.models() + .getExistingFile(p.mcLoc("air")))) + .initialProperties(SharedProperties::softMetal) + .properties(p -> p.noOcclusion() + .color(MaterialColor.NONE)) + .addLayer(() -> RenderType::solid) + .addLayer(() -> RenderType::cutout) + .addLayer(() -> RenderType::cutoutMipped) + .addLayer(() -> RenderType::translucent) + .color(() -> CopycatBlock::wrappedColor) + .transform(TagGen.axeOrPickaxe()); } public static NonNullUnaryOperator> trapdoor(boolean orientable) { @@ -129,6 +160,7 @@ public class BuilderTransformers { .loot((lr, block) -> lr.add(block, lr.createDoorTable(block))) .item() .tag(ItemTags.DOORS) + .tag(AllItemTags.CONTRAPTION_CONTROLLED.tag) .model((c, p) -> p.blockSprite(c, p.modLoc("item/" + type + "_door"))) .build(); } @@ -149,6 +181,7 @@ public class BuilderTransformers { String encasedSuffix = "_encased_cogwheel_side" + (large ? "_connected" : ""); String blockFolder = large ? "encased_large_cogwheel" : "encased_cogwheel"; String wood = casing.equals("brass") ? "dark_oak" : "spruce"; + String gearbox = casing.equals("brass") ? "brass_gearbox" : "gearbox"; return encasedBase(b, drop).addLayer(() -> RenderType::cutoutMipped) .onRegister(CreateRegistrate.casingConnectivity((block, cc) -> cc.make(block, casingShift.get(), (s, f) -> f.getAxis() == s.getValue(EncasedCogwheelBlock.AXIS) @@ -161,12 +194,15 @@ public class BuilderTransformers { return p.models() .withExistingParent(modelName, p.modLoc("block/" + blockFolder + "/block" + suffix)) .texture("casing", Create.asResource("block/" + casing + "_casing")) + .texture("particle", Create.asResource("block/" + casing + "_casing")) + .texture("4", Create.asResource("block/" + gearbox)) .texture("1", new ResourceLocation("block/stripped_" + wood + "_log_top")) .texture("side", Create.asResource("block/" + casing + encasedSuffix)); }, false)) .item() .model((c, p) -> p.withExistingParent(c.getName(), p.modLoc("block/" + blockFolder + "/item")) .texture("casing", Create.asResource("block/" + casing + "_casing")) + .texture("particle", Create.asResource("block/" + casing + "_casing")) .texture("1", new ResourceLocation("block/stripped_" + wood + "_log_top")) .texture("side", Create.asResource("block/" + casing + encasedSuffix))) .build(); @@ -191,8 +227,9 @@ public class BuilderTransformers { } public static NonNullUnaryOperator> ladder(String name, - Supplier ingredient) { + Supplier ingredient, MaterialColor color) { return b -> b.initialProperties(() -> Blocks.LADDER) + .properties(p -> p.color(color)) .addLayer(() -> RenderType::cutout) .blockstate((c, p) -> p.horizontalBlock(c.get(), p.models() .withExistingParent(c.getName(), p.modLoc("block/ladder")) @@ -203,15 +240,41 @@ public class BuilderTransformers { .transform(pickaxeOnly()) .tag(BlockTags.CLIMBABLE) .item() - .recipe((c, p) -> { - if (name.equals("andesite")) - return; - p.stonecutting(ingredient.get(), RecipeCategory.DECORATIONS, c::get, 2); - }) + .recipe((c, p) -> p.stonecutting(ingredient.get(), RecipeCategory.DECORATIONS, c::get, 2)) .model((c, p) -> p.blockSprite(c::get, p.modLoc("block/ladder_" + name))) .build(); } + public static NonNullUnaryOperator> scaffold(String name, + Supplier ingredient, MaterialColor color, CTSpriteShiftEntry scaffoldShift, + CTSpriteShiftEntry scaffoldInsideShift, CTSpriteShiftEntry casingShift) { + return b -> b.initialProperties(() -> Blocks.SCAFFOLDING) + .properties(p -> p.sound(SoundType.COPPER) + .color(color)) + .addLayer(() -> RenderType::cutout) + .blockstate((c, p) -> p.getVariantBuilder(c.get()) + .forAllStatesExcept(s -> { + String suffix = s.getValue(MetalScaffoldingBlock.BOTTOM) ? "_horizontal" : ""; + return ConfiguredModel.builder() + .modelFile(p.models() + .withExistingParent(c.getName() + suffix, p.modLoc("block/scaffold/block" + suffix)) + .texture("top", p.modLoc("block/funnel/" + name + "_funnel_frame")) + .texture("inside", p.modLoc("block/scaffold/" + name + "_scaffold_inside")) + .texture("side", p.modLoc("block/scaffold/" + name + "_scaffold")) + .texture("casing", p.modLoc("block/" + name + "_casing")) + .texture("particle", p.modLoc("block/scaffold/" + name + "_scaffold"))) + .build(); + }, MetalScaffoldingBlock.WATERLOGGED, MetalScaffoldingBlock.DISTANCE)) + .onRegister(connectedTextures( + () -> new MetalScaffoldingCTBehaviour(scaffoldShift, scaffoldInsideShift, casingShift))) + .transform(pickaxeOnly()) + .tag(BlockTags.CLIMBABLE) + .item(MetalScaffoldingBlockItem::new) + .recipe((c, p) -> p.stonecutting(ingredient.get(), RecipeCategory.DECORATIONS, c::get, 2)) + .model((c, p) -> p.withExistingParent(c.getName(), p.modLoc("block/" + c.getName()))) + .build(); + } + public static NonNullUnaryOperator> valveHandle( @Nullable DyeColor color) { return b -> b.initialProperties(SharedProperties::copperMetal) @@ -222,7 +285,6 @@ public class BuilderTransformers { .texture("3", p.modLoc("block/valve_handle/valve_handle_" + variant))); }) .tag(AllBlockTags.BRITTLE.tag, AllBlockTags.VALVE_HANDLES.tag) - .transform(BlockStressDefaults.setCapacity(8.0)) .transform(BlockStressDefaults.setGeneratorSpeed(ValveHandleBlock::getSpeedRange)) .onRegister(ItemUseOverrides::addBlock) .item() @@ -263,33 +325,37 @@ public class BuilderTransformers { public static NonNullUnaryOperator> beltTunnel( String type, ResourceLocation particleTexture) { + String prefix = "block/tunnel/" + type + "_tunnel"; + String funnel_prefix = "block/funnel/" + type + "_funnel"; return b -> b.initialProperties(SharedProperties::stone) .addLayer(() -> RenderType::cutoutMipped) .properties(BlockBehaviour.Properties::noOcclusion) .transform(pickaxeOnly()) .blockstate((c, p) -> p.getVariantBuilder(c.get()) .forAllStates(state -> { - String id = "block/" + type + "_tunnel"; Shape shape = state.getValue(BeltTunnelBlock.SHAPE); + String window = shape == Shape.WINDOW ? "_window" : ""; if (shape == BeltTunnelBlock.Shape.CLOSED) shape = BeltTunnelBlock.Shape.STRAIGHT; String shapeName = shape.getSerializedName(); return ConfiguredModel.builder() .modelFile(p.models() - .withExistingParent(id + "/" + shapeName, p.modLoc("block/belt_tunnel/" + shapeName)) - .texture("1", p.modLoc(id + "_top")) - .texture("2", p.modLoc(id)) - .texture("3", p.modLoc(id + "_top_window")) + .withExistingParent(prefix + "/" + shapeName, p.modLoc("block/belt_tunnel/" + shapeName)) + .texture("top", p.modLoc(prefix + "_top" + window)) + .texture("tunnel", p.modLoc(prefix)) + .texture("direction", p.modLoc(funnel_prefix + "_neutral")) + .texture("frame", p.modLoc(funnel_prefix + "_frame")) .texture("particle", particleTexture)) .rotationY(state.getValue(BeltTunnelBlock.HORIZONTAL_AXIS) == Axis.X ? 0 : 90) .build(); })) .item(BeltTunnelItem::new) .model((c, p) -> { - String id = type + "_tunnel"; - p.withExistingParent("item/" + id, p.modLoc("block/belt_tunnel/item")) - .texture("1", p.modLoc("block/" + id + "_top")) - .texture("2", p.modLoc("block/" + id)) + p.withExistingParent("item/" + type + "_tunnel", p.modLoc("block/belt_tunnel/item")) + .texture("top", p.modLoc(prefix + "_top")) + .texture("tunnel", p.modLoc(prefix)) + .texture("direction", p.modLoc(funnel_prefix + "_neutral")) + .texture("frame", p.modLoc(funnel_prefix + "_frame")) .texture("particle", particleTexture); }) .build(); @@ -306,12 +372,10 @@ public class BuilderTransformers { } public static NonNullUnaryOperator> bearing(String prefix, - String backTexture, boolean woodenTop) { + String backTexture) { ResourceLocation baseBlockModelLocation = Create.asResource("block/bearing/block"); ResourceLocation baseItemModelLocation = Create.asResource("block/bearing/item"); - ResourceLocation topTextureLocation = Create.asResource("block/bearing_top" + (woodenTop ? "_wooden" : "")); - ResourceLocation nookTextureLocation = - Create.asResource("block/" + (woodenTop ? "andesite" : "brass") + "_casing"); + ResourceLocation topTextureLocation = Create.asResource("block/bearing_top"); ResourceLocation sideTextureLocation = Create.asResource("block/" + prefix + "_bearing_side"); ResourceLocation backTextureLocation = Create.asResource("block/" + backTexture); return b -> b.initialProperties(SharedProperties::stone) @@ -319,7 +383,6 @@ public class BuilderTransformers { .blockstate((c, p) -> p.directionalBlock(c.get(), p.models() .withExistingParent(c.getName(), baseBlockModelLocation) .texture("side", sideTextureLocation) - .texture("nook", nookTextureLocation) .texture("back", backTextureLocation))) .item() .model((c, p) -> p.withExistingParent(c.getName(), baseItemModelLocation) @@ -360,6 +423,26 @@ public class BuilderTransformers { .transform(ModelGen.customItemModel("crate", type, "single")); } + public static NonNullUnaryOperator> backtank(Supplier drop) { + return b -> b.blockstate((c, p) -> p.horizontalBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p))) + .transform(pickaxeOnly()) + .addLayer(() -> RenderType::cutoutMipped) + .transform(BlockStressDefaults.setImpact(4.0)) + .loot((lt, block) -> { + Builder builder = LootTable.lootTable(); + LootItemCondition.Builder survivesExplosion = ExplosionCondition.survivesExplosion(); + lt.add(block, builder.withPool(LootPool.lootPool() + .when(survivesExplosion) + .setRolls(ConstantValue.exactly(1)) + .add(LootItem.lootTableItem(drop.get()) + .apply(CopyNameFunction.copyName(CopyNameFunction.NameSource.BLOCK_ENTITY)) + .apply(CopyNbtFunction.copyData(ContextNbtProvider.BLOCK_ENTITY) + .copy("Air", "Air")) + .apply(CopyNbtFunction.copyData(ContextNbtProvider.BLOCK_ENTITY) + .copy("Enchantments", "Enchantments"))))); + }); + } + public static NonNullUnaryOperator> bell() { return b -> b.initialProperties(SharedProperties::softMetal) .properties(p -> p.noOcclusion() @@ -375,6 +458,7 @@ public class BuilderTransformers { })) .item() .model((c, p) -> p.withExistingParent(c.getName(), p.modLoc("block/" + c.getName()))) + .tag(AllItemTags.CONTRAPTION_CONTROLLED.tag) .build(); } diff --git a/src/main/java/com/simibubi/create/foundation/data/CreateBlockEntityBuilder.java b/src/main/java/com/simibubi/create/foundation/data/CreateBlockEntityBuilder.java new file mode 100644 index 000000000..cdf40b42d --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/data/CreateBlockEntityBuilder.java @@ -0,0 +1,98 @@ +package com.simibubi.create.foundation.data; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.function.BiFunction; +import java.util.function.Supplier; + +import javax.annotation.Nullable; + +import com.jozufozu.flywheel.api.MaterialManager; +import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry; +import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance; +import com.tterrag.registrate.AbstractRegistrate; +import com.tterrag.registrate.builders.BlockEntityBuilder; +import com.tterrag.registrate.builders.BuilderCallback; +import com.tterrag.registrate.util.OneTimeEventReceiver; +import com.tterrag.registrate.util.nullness.NonNullSupplier; + +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.common.util.NonNullPredicate; +import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; + +public class CreateBlockEntityBuilder extends BlockEntityBuilder { + + @Nullable + private NonNullSupplier>> instanceFactory; + private NonNullPredicate renderNormally; + + private Collection>>> deferredValidBlocks = + new ArrayList<>(); + + public static BlockEntityBuilder create(AbstractRegistrate owner, P parent, + String name, BuilderCallback callback, BlockEntityFactory factory) { + return new CreateBlockEntityBuilder<>(owner, parent, name, callback, factory); + } + + protected CreateBlockEntityBuilder(AbstractRegistrate owner, P parent, String name, BuilderCallback callback, + BlockEntityFactory factory) { + super(owner, parent, name, callback, factory); + } + + public CreateBlockEntityBuilder validBlocksDeferred( + NonNullSupplier>> blocks) { + deferredValidBlocks.add(blocks); + return this; + } + + @Override + protected BlockEntityType createEntry() { + deferredValidBlocks.stream() + .map(Supplier::get) + .flatMap(Collection::stream) + .forEach(this::validBlock); + return super.createEntry(); + } + + public CreateBlockEntityBuilder instance( + NonNullSupplier>> instanceFactory) { + return instance(instanceFactory, true); + } + + public CreateBlockEntityBuilder instance( + NonNullSupplier>> instanceFactory, + boolean renderNormally) { + return instance(instanceFactory, be -> renderNormally); + } + + public CreateBlockEntityBuilder instance( + NonNullSupplier>> instanceFactory, + NonNullPredicate renderNormally) { + if (this.instanceFactory == null) { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> this::registerInstance); + } + + this.instanceFactory = instanceFactory; + this.renderNormally = renderNormally; + + return this; + } + + protected void registerInstance() { + OneTimeEventReceiver.addModListener(FMLClientSetupEvent.class, $ -> { + NonNullSupplier>> instanceFactory = + this.instanceFactory; + if (instanceFactory != null) { + NonNullPredicate renderNormally = this.renderNormally; + InstancedRenderRegistry.configure(getEntry()) + .factory(instanceFactory.get()) + .skipRender(be -> !renderNormally.test(be)) + .apply(); + } + }); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/data/CreateRegistrate.java b/src/main/java/com/simibubi/create/foundation/data/CreateRegistrate.java index 4b5181d54..9751857cc 100644 --- a/src/main/java/com/simibubi/create/foundation/data/CreateRegistrate.java +++ b/src/main/java/com/simibubi/create/foundation/data/CreateRegistrate.java @@ -2,22 +2,20 @@ package com.simibubi.create.foundation.data; import static com.simibubi.create.foundation.data.TagGen.pickaxeOnly; -import java.util.Collection; -import java.util.IdentityHashMap; -import java.util.Map; -import java.util.Map.Entry; import java.util.function.BiConsumer; import java.util.function.Consumer; +import java.util.function.Function; import java.util.function.Supplier; -import java.util.stream.Collectors; + +import org.jetbrains.annotations.Nullable; import com.simibubi.create.Create; import com.simibubi.create.CreateClient; -import com.simibubi.create.content.AllSections; -import com.simibubi.create.content.contraptions.fluids.VirtualFluid; -import com.simibubi.create.content.contraptions.relays.encased.CasingConnectivity; +import com.simibubi.create.content.decoration.encasing.CasingConnectivity; +import com.simibubi.create.content.fluids.VirtualFluid; import com.simibubi.create.foundation.block.connected.CTModel; import com.simibubi.create.foundation.block.connected.ConnectedTextureBehaviour; +import com.simibubi.create.foundation.item.TooltipModifier; import com.simibubi.create.foundation.utility.RegisteredObjects; import com.tterrag.registrate.AbstractRegistrate; import com.tterrag.registrate.builders.BlockBuilder; @@ -31,6 +29,7 @@ import com.tterrag.registrate.util.nullness.NonNullSupplier; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.core.Registry; +import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.BlockTags; @@ -48,10 +47,12 @@ import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.fluids.FluidType; import net.minecraftforge.fluids.ForgeFlowingFluid; import net.minecraftforge.fml.DistExecutor; -import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.registries.RegistryObject; public class CreateRegistrate extends AbstractRegistrate { + @Nullable + protected Function currentTooltipModifierFactory; + protected CreateRegistrate(String modid) { super(modid); } @@ -60,11 +61,14 @@ public class CreateRegistrate extends AbstractRegistrate { return new CreateRegistrate(modid); } - @Deprecated(forRemoval = true) - public static NonNullSupplier lazy(String modid) { - return NonNullSupplier - .lazy(() -> new CreateRegistrate(modid).registerEventListeners(FMLJavaModLoadingContext.get() - .getModEventBus())); + public CreateRegistrate setTooltipModifierFactory(@Nullable Function factory) { + currentTooltipModifierFactory = factory; + return self(); + } + + @Nullable + public Function getTooltipModifierFactory() { + return currentTooltipModifierFactory; } @Override @@ -72,63 +76,30 @@ public class CreateRegistrate extends AbstractRegistrate { return super.registerEventListeners(bus); } - /* Section Tracking */ - - protected static final Map, AllSections> SECTION_LOOKUP = new IdentityHashMap<>(); - protected AllSections currentSection; - - public CreateRegistrate startSection(AllSections section) { - this.currentSection = section; - return this; - } - - public AllSections currentSection() { - return currentSection; - } - @Override protected RegistryEntry accept(String name, ResourceKey> type, Builder builder, NonNullSupplier creator, NonNullFunction, ? extends RegistryEntry> entryFactory) { - RegistryEntry ret = super.accept(name, type, builder, creator, entryFactory); - SECTION_LOOKUP.put(ret, currentSection()); - return ret; - } - - public void addToSection(RegistryEntry entry, AllSections section) { - SECTION_LOOKUP.put(entry, section); - } - - public AllSections getSection(RegistryEntry entry) { - return SECTION_LOOKUP.getOrDefault(entry, AllSections.UNASSIGNED); - } - - public AllSections getSection(Object entry) { - for (Entry, AllSections> mapEntry : SECTION_LOOKUP.entrySet()) { - if (mapEntry.getKey().get() == entry) { - return mapEntry.getValue(); + RegistryEntry entry = super.accept(name, type, builder, creator, entryFactory); + if (type.equals(Registries.ITEM)) { + if (currentTooltipModifierFactory != null) { + TooltipModifier.REGISTRY.registerDeferred(entry.getId(), currentTooltipModifierFactory); } } - return AllSections.UNASSIGNED; + return entry; } - public Collection> getAll(AllSections section, - ResourceKey> registryType) { - return this.getAll(registryType) - .stream() - .filter(e -> getSection(e) == section) - .collect(Collectors.toList()); - } - - public CreateTileEntityBuilder tileEntity(String name, + @Override + public CreateBlockEntityBuilder blockEntity(String name, BlockEntityFactory factory) { - return this.tileEntity(this.self(), name, factory); + return blockEntity(self(), name, factory); } - public CreateTileEntityBuilder tileEntity(P parent, String name, + @Override + public CreateBlockEntityBuilder blockEntity(P parent, String name, BlockEntityFactory factory) { - return (CreateTileEntityBuilder) this.entry(name, - (callback) -> CreateTileEntityBuilder.create(this, parent, name, callback, factory)); + return (CreateBlockEntityBuilder) entry(name, + (callback) -> CreateBlockEntityBuilder.create(this, parent, name, callback, factory)); } @Override @@ -148,10 +119,11 @@ public class CreateRegistrate extends AbstractRegistrate { /* Palettes */ public BlockBuilder paletteStoneBlock(String name, - NonNullFunction factory, NonNullSupplier propertiesFrom, boolean worldGenStone) { + NonNullFunction factory, NonNullSupplier propertiesFrom, boolean worldGenStone, + boolean hasNaturalVariants) { BlockBuilder builder = super.block(name, factory).initialProperties(propertiesFrom) .transform(pickaxeOnly()) - .blockstate((c, p) -> { + .blockstate(hasNaturalVariants ? BlockStateGen.naturalStoneTypeBlock(name) : (c, p) -> { final String location = "block/palettes/stone_types/" + c.getName(); p.simpleBlock(c.get(), p.models() .cubeAll(c.getName(), p.modLoc(location))); @@ -161,13 +133,16 @@ public class CreateRegistrate extends AbstractRegistrate { .tag(BlockTags.MOSS_REPLACEABLE) .tag(BlockTags.LUSH_GROUND_REPLACEABLE) .item() + .model((c, p) -> p.cubeAll(c.getName(), + p.modLoc(hasNaturalVariants ? "block/palettes/stone_types/natural/" + name + "_1" + : "block/palettes/stone_types/" + c.getName()))) .build(); return builder; } public BlockBuilder paletteStoneBlock(String name, NonNullSupplier propertiesFrom, - boolean worldGenStone) { - return paletteStoneBlock(name, Block::new, propertiesFrom, worldGenStone); + boolean worldGenStone, boolean hasNaturalVariants) { + return paletteStoneBlock(name, Block::new, propertiesFrom, worldGenStone, hasNaturalVariants); } /* Fluids */ diff --git a/src/main/java/com/simibubi/create/foundation/data/CreateTileEntityBuilder.java b/src/main/java/com/simibubi/create/foundation/data/CreateTileEntityBuilder.java deleted file mode 100644 index d336936a8..000000000 --- a/src/main/java/com/simibubi/create/foundation/data/CreateTileEntityBuilder.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.simibubi.create.foundation.data; - -import java.util.function.BiFunction; - -import javax.annotation.Nullable; - -import com.jozufozu.flywheel.api.MaterialManager; -import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry; -import com.jozufozu.flywheel.backend.instancing.blockentity.BlockEntityInstance; -import com.tterrag.registrate.AbstractRegistrate; -import com.tterrag.registrate.builders.BlockEntityBuilder; -import com.tterrag.registrate.builders.BuilderCallback; -import com.tterrag.registrate.util.OneTimeEventReceiver; -import com.tterrag.registrate.util.nullness.NonNullSupplier; - -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.common.util.NonNullPredicate; -import net.minecraftforge.fml.DistExecutor; -import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; - -public class CreateTileEntityBuilder extends BlockEntityBuilder { - - @Nullable - private NonNullSupplier>> instanceFactory; - private NonNullPredicate renderNormally; - - public static BlockEntityBuilder create(AbstractRegistrate owner, P parent, - String name, BuilderCallback callback, BlockEntityFactory factory) { - return new CreateTileEntityBuilder<>(owner, parent, name, callback, factory); - } - - protected CreateTileEntityBuilder(AbstractRegistrate owner, P parent, String name, BuilderCallback callback, - BlockEntityFactory factory) { - super(owner, parent, name, callback, factory); - } - - public CreateTileEntityBuilder instance(NonNullSupplier>> instanceFactory) { - return instance(instanceFactory, true); - } - - public CreateTileEntityBuilder instance(NonNullSupplier>> instanceFactory, boolean renderNormally) { - return instance(instanceFactory, be -> renderNormally); - } - - public CreateTileEntityBuilder instance(NonNullSupplier>> instanceFactory, NonNullPredicate renderNormally) { - if (this.instanceFactory == null) { - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> this::registerInstance); - } - - this.instanceFactory = instanceFactory; - this.renderNormally = renderNormally; - - return this; - } - - protected void registerInstance() { - OneTimeEventReceiver.addModListener(FMLClientSetupEvent.class, $ -> { - NonNullSupplier>> instanceFactory = this.instanceFactory; - if (instanceFactory != null) { - NonNullPredicate renderNormally = this.renderNormally; - InstancedRenderRegistry.configure(getEntry()) - .factory(instanceFactory.get()) - .skipRender(be -> !renderNormally.test(be)) - .apply(); - } - }); - } -} diff --git a/src/main/java/com/simibubi/create/foundation/data/DirectionalAxisBlockStateGen.java b/src/main/java/com/simibubi/create/foundation/data/DirectionalAxisBlockStateGen.java index 0905608cc..3103cf4d5 100644 --- a/src/main/java/com/simibubi/create/foundation/data/DirectionalAxisBlockStateGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/DirectionalAxisBlockStateGen.java @@ -1,6 +1,6 @@ package com.simibubi.create.foundation.data; -import com.simibubi.create.content.contraptions.relays.gauge.GaugeBlock; +import com.simibubi.create.content.kinetics.gauge.GaugeBlock; import com.tterrag.registrate.providers.DataGenContext; import com.tterrag.registrate.providers.RegistrateBlockstateProvider; diff --git a/src/main/java/com/simibubi/create/foundation/data/LangEntry.java b/src/main/java/com/simibubi/create/foundation/data/LangEntry.java new file mode 100644 index 000000000..87f4f1f32 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/data/LangEntry.java @@ -0,0 +1,19 @@ +package com.simibubi.create.foundation.data; + +public class LangEntry { + static final String ENTRY_FORMAT = "\t\"%s\": %s,\n"; + + private String key; + private String value; + + LangEntry(String key, String value) { + this.key = key; + this.value = value; + } + + @Override + public String toString() { + return String.format(ENTRY_FORMAT, key, LangMerger.GSON.toJson(value, String.class)); + } + +} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/foundation/data/LangMerger.java b/src/main/java/com/simibubi/create/foundation/data/LangMerger.java index 556312134..a16a9135f 100644 --- a/src/main/java/com/simibubi/create/foundation/data/LangMerger.java +++ b/src/main/java/com/simibubi/create/foundation/data/LangMerger.java @@ -35,7 +35,7 @@ import net.minecraftforge.fml.LogicalSide; public class LangMerger implements RegistrateProvider { - private static final Gson GSON = new GsonBuilder().setPrettyPrinting() + static final Gson GSON = new GsonBuilder().setPrettyPrinting() .disableHtmlEscaping() .create(); private static final String CATEGORY_HEADER = @@ -218,24 +218,6 @@ public class LangMerger implements RegistrateProvider { return builder.toString(); } - private class LangEntry { - static final String ENTRY_FORMAT = "\t\"%s\": %s,\n"; - - private String key; - private String value; - - LangEntry(String key, String value) { - this.key = key; - this.value = value; - } - - @Override - public String toString() { - return String.format(ENTRY_FORMAT, key, GSON.toJson(value, String.class)); - } - - } - @Override public LogicalSide getSide() { return LogicalSide.CLIENT; diff --git a/src/main/java/com/simibubi/create/foundation/data/MetalBarsGen.java b/src/main/java/com/simibubi/create/foundation/data/MetalBarsGen.java new file mode 100644 index 000000000..c6505edac --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/data/MetalBarsGen.java @@ -0,0 +1,148 @@ +package com.simibubi.create.foundation.data; + +import static com.simibubi.create.Create.REGISTRATE; +import static net.minecraft.world.level.block.state.properties.BlockStateProperties.EAST; +import static net.minecraft.world.level.block.state.properties.BlockStateProperties.NORTH; +import static net.minecraft.world.level.block.state.properties.BlockStateProperties.SOUTH; +import static net.minecraft.world.level.block.state.properties.BlockStateProperties.WEST; + +import java.util.function.Supplier; + +import com.simibubi.create.AllTags.AllBlockTags; +import com.simibubi.create.Create; +import com.tterrag.registrate.providers.DataGenContext; +import com.tterrag.registrate.providers.RegistrateBlockstateProvider; +import com.tterrag.registrate.util.DataIngredient; +import com.tterrag.registrate.util.entry.BlockEntry; +import com.tterrag.registrate.util.nullness.NonNullBiConsumer; + +import net.minecraft.client.renderer.RenderType; +import net.minecraft.data.recipes.RecipeCategory; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.IronBarsBlock; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.material.MaterialColor; +import net.minecraftforge.client.model.generators.ModelFile; + +public class MetalBarsGen { + + public static

NonNullBiConsumer, RegistrateBlockstateProvider> barsBlockState( + String name, boolean specialEdge) { + return (c, p) -> { + + ModelFile post_ends = barsSubModel(p, name, "post_ends", specialEdge); + ModelFile post = barsSubModel(p, name, "post", specialEdge); + ModelFile cap = barsSubModel(p, name, "cap", specialEdge); + ModelFile cap_alt = barsSubModel(p, name, "cap_alt", specialEdge); + ModelFile side = barsSubModel(p, name, "side", specialEdge); + ModelFile side_alt = barsSubModel(p, name, "side_alt", specialEdge); + + p.getMultipartBuilder(c.get()) + .part() + .modelFile(post_ends) + .addModel() + .end() + .part() + .modelFile(post) + .addModel() + .condition(NORTH, false) + .condition(EAST, false) + .condition(SOUTH, false) + .condition(WEST, false) + .end() + .part() + .modelFile(cap) + .addModel() + .condition(NORTH, true) + .condition(EAST, false) + .condition(SOUTH, false) + .condition(WEST, false) + .end() + .part() + .modelFile(cap) + .rotationY(90) + .addModel() + .condition(NORTH, false) + .condition(EAST, true) + .condition(SOUTH, false) + .condition(WEST, false) + .end() + .part() + .modelFile(cap_alt) + .addModel() + .condition(NORTH, false) + .condition(EAST, false) + .condition(SOUTH, true) + .condition(WEST, false) + .end() + .part() + .modelFile(cap_alt) + .rotationY(90) + .addModel() + .condition(NORTH, false) + .condition(EAST, false) + .condition(SOUTH, false) + .condition(WEST, true) + .end() + .part() + .modelFile(side) + .addModel() + .condition(NORTH, true) + .end() + .part() + .modelFile(side) + .rotationY(90) + .addModel() + .condition(EAST, true) + .end() + .part() + .modelFile(side_alt) + .addModel() + .condition(SOUTH, true) + .end() + .part() + .modelFile(side_alt) + .rotationY(90) + .addModel() + .condition(WEST, true) + .end(); + }; + } + + private static ModelFile barsSubModel(RegistrateBlockstateProvider p, String name, String suffix, + boolean specialEdge) { + ResourceLocation barsTexture = p.modLoc("block/bars/" + name + "_bars"); + ResourceLocation edgeTexture = specialEdge ? p.modLoc("block/bars/" + name + "_bars_edge") : barsTexture; + return p.models() + .withExistingParent(name + "_" + suffix, p.modLoc("block/bars/" + suffix)) + .texture("bars", barsTexture) + .texture("particle", barsTexture) + .texture("edge", edgeTexture); + } + + public static BlockEntry createBars(String name, boolean specialEdge, + Supplier ingredient, MaterialColor color) { + return REGISTRATE.block(name + "_bars", IronBarsBlock::new) + .addLayer(() -> RenderType::cutoutMipped) + .initialProperties(() -> Blocks.IRON_BARS) + .properties(p -> p.sound(SoundType.COPPER) + .color(color)) + .tag(AllBlockTags.WRENCH_PICKUP.tag) + .tag(AllBlockTags.FAN_TRANSPARENT.tag) + .transform(TagGen.pickaxeOnly()) + .blockstate(barsBlockState(name, specialEdge)) + .item() + .model((c, p) -> { + ResourceLocation barsTexture = p.modLoc("block/bars/" + name + "_bars"); + p.withExistingParent(c.getName(), Create.asResource("item/bars")) + .texture("bars", barsTexture) + .texture("edge", specialEdge ? p.modLoc("block/bars/" + name + "_bars_edge") : barsTexture); + }) + .recipe((c, p) -> p.stonecutting(ingredient.get(), RecipeCategory.DECORATIONS, c::get, 4)) + .build() + .register(); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/data/SharedProperties.java b/src/main/java/com/simibubi/create/foundation/data/SharedProperties.java index f1838c470..256aafed4 100644 --- a/src/main/java/com/simibubi/create/foundation/data/SharedProperties.java +++ b/src/main/java/com/simibubi/create/foundation/data/SharedProperties.java @@ -15,6 +15,10 @@ public class SharedProperties { public static final Material CRUSHING_WHEEL_CONTROLLER_MATERIAL = new Material(MaterialColor.NONE, false, false, true, true, false, false, PushReaction.BLOCK); + public static Block wooden() { + return Blocks.STRIPPED_SPRUCE_WOOD; + } + public static Block stone() { return Blocks.ANDESITE; } @@ -22,12 +26,12 @@ public class SharedProperties { public static Block softMetal() { return Blocks.GOLD_BLOCK; } - + public static Block copperMetal() { return Blocks.COPPER_BLOCK; } - public static Block wooden() { - return Blocks.STRIPPED_SPRUCE_WOOD; + public static Block netheriteMetal() { + return Blocks.NETHERITE_BLOCK; } } diff --git a/src/main/java/com/simibubi/create/foundation/data/TagGen.java b/src/main/java/com/simibubi/create/foundation/data/TagGen.java index e1824a776..a49e66378 100644 --- a/src/main/java/com/simibubi/create/foundation/data/TagGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/TagGen.java @@ -83,9 +83,9 @@ public class TagGen { .add(Blocks.BELL, Blocks.COCOA, Blocks.FLOWER_POT) .addTag(BlockTags.BEDS) .addTag(BlockTags.DOORS); - + prov.tag(AllBlockTags.MOVABLE_EMPTY_COLLIDER.tag) - .add(Blocks.COBWEB, Blocks.POWDER_SNOW) + .add(Blocks.COBWEB, Blocks.POWDER_SNOW, Blocks.TRIPWIRE, Blocks.TRIPWIRE_HOOK) .addTag(BlockTags.FENCE_GATES); prov.tag(AllBlockTags.FAN_TRANSPARENT.tag) @@ -121,6 +121,13 @@ public class TagGen { .addTag(BlockTags.PRESSURE_PLATES) .addTag(BlockTags.RAILS); + prov.tag(AllBlockTags.COPYCAT_ALLOW.tag) + .add(Blocks.BARREL); + prov.tag(AllBlockTags.COPYCAT_DENY.tag) + .addTag(BlockTags.CAULDRONS) + .addTag(BlockTags.SAPLINGS) + .addTag(BlockTags.CLIMBABLE); + // COMPAT addOptional(prov.tag(AllBlockTags.NON_MOVABLE.tag), Mods.IE, @@ -158,6 +165,9 @@ public class TagGen { .add(Items.GLASS_BOTTLE, Items.POTION, Items.SPLASH_POTION, Items.LINGERING_POTION, Items.HONEY_BOTTLE, Items.CAKE); + prov.tag(AllItemTags.CONTRAPTION_CONTROLLED.tag) + .add(Items.BELL, Items.CAMPFIRE, Items.SOUL_CAMPFIRE, Items.DISPENSER, Items.DROPPER); + prov.tag(AllItemTags.VANILLA_STRIPPED_LOGS.tag) .add(Items.STRIPPED_ACACIA_LOG, Items.STRIPPED_BIRCH_LOG, Items.STRIPPED_CRIMSON_STEM, Items.STRIPPED_DARK_OAK_LOG, Items.STRIPPED_JUNGLE_LOG, Items.STRIPPED_MANGROVE_LOG, diff --git a/src/main/java/com/simibubi/create/foundation/data/WindowGen.java b/src/main/java/com/simibubi/create/foundation/data/WindowGen.java index f6ad3fbf8..dacf2e104 100644 --- a/src/main/java/com/simibubi/create/foundation/data/WindowGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/WindowGen.java @@ -8,10 +8,10 @@ import java.util.function.Supplier; import com.simibubi.create.AllSpriteShifts; import com.simibubi.create.Create; -import com.simibubi.create.content.palettes.ConnectedGlassBlock; -import com.simibubi.create.content.palettes.ConnectedGlassPaneBlock; -import com.simibubi.create.content.palettes.GlassPaneBlock; -import com.simibubi.create.content.palettes.WindowBlock; +import com.simibubi.create.content.decoration.palettes.ConnectedGlassBlock; +import com.simibubi.create.content.decoration.palettes.ConnectedGlassPaneBlock; +import com.simibubi.create.content.decoration.palettes.GlassPaneBlock; +import com.simibubi.create.content.decoration.palettes.WindowBlock; import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry; import com.simibubi.create.foundation.block.connected.ConnectedTextureBehaviour; import com.simibubi.create.foundation.block.connected.GlassPaneCTBehaviour; diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/CreateRecipeProvider.java b/src/main/java/com/simibubi/create/foundation/data/recipe/CreateRecipeProvider.java index 6d3a27a7d..cb8f4a83b 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/CreateRecipeProvider.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/CreateRecipeProvider.java @@ -16,6 +16,7 @@ import net.minecraft.tags.ItemTags; import net.minecraft.tags.TagKey; import net.minecraft.world.item.Item; import net.minecraft.world.item.Items; +import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.level.ItemLike; import net.minecraftforge.common.Tags; @@ -184,5 +185,9 @@ public abstract class CreateRecipeProvider extends RecipeProvider { return AllItems.SHADOW_STEEL.get(); } + static Ingredient netherite() { + return Ingredient.of(AllTags.forgeItemTag("ingots/netherite")); + } + } } diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/CrushingRecipeGen.java b/src/main/java/com/simibubi/create/foundation/data/recipe/CrushingRecipeGen.java index 4eed3f4f0..80e9cbd95 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/CrushingRecipeGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/CrushingRecipeGen.java @@ -17,9 +17,9 @@ import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; import com.simibubi.create.AllRecipeTypes; import com.simibubi.create.AllTags; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipe; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder; -import com.simibubi.create.content.palettes.AllPaletteStoneTypes; +import com.simibubi.create.content.decoration.palettes.AllPaletteStoneTypes; +import com.simibubi.create.content.processing.recipe.ProcessingRecipe; +import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder; import com.simibubi.create.foundation.utility.Lang; import net.minecraft.data.PackOutput; @@ -225,7 +225,7 @@ public class CrushingRecipeGen extends ProcessingRecipeGen { float extra = expectedAmount - Mth.floor(expectedAmount); if (extra > 0) builder.output(extra, raw.get(), 1); - builder.output(.75f, AllItems.EXP_NUGGET.get(), 1); + builder.output(.75f, AllItems.EXP_NUGGET.get(), raw.get() == AllItems.CRUSHED_GOLD.get() ? 2 : 1); return builder.output(.125f, stoneType); }); } @@ -233,7 +233,7 @@ public class CrushingRecipeGen extends ProcessingRecipeGen { protected GeneratedRecipe rawOre(Supplier input, Supplier result, int amount) { return create(input, b -> b.duration(400) .output(result.get(), amount) - .output(.75f, AllItems.EXP_NUGGET.get(), amount)); + .output(.75f, AllItems.EXP_NUGGET.get(), (result.get() == AllItems.CRUSHED_GOLD.get() ? 2 : 1) * amount)); } protected GeneratedRecipe moddedRawOre(CompatMetals metal, Supplier result, int amount) { diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/CuttingRecipeGen.java b/src/main/java/com/simibubi/create/foundation/data/recipe/CuttingRecipeGen.java index ed89d1de0..a7f62c78d 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/CuttingRecipeGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/CuttingRecipeGen.java @@ -64,7 +64,7 @@ public class CuttingRecipeGen extends ProcessingRecipeGen { // Oh The Biomes You'll Go BYG = cuttingCompat(Mods.BYG, "aspen", "baobab", "blue_enchanted", "cherry", "cika", "cypress", "ebony", "ether", - "fir", "green_enchanted", "holly", "jacaranda", "lament", "mahogany", "mangrove", "maple", "nightshade", + "fir", "green_enchanted", "holly", "jacaranda", "lament", "mahogany", "maple", "nightshade", "palm", "pine", "rainbow_eucalyptus", "redwood", "skyris", "willow", "witch_hazel", "zelkova"), BYG_2 = stripAndMakePlanks(Mods.BYG, "bulbis_stem", "stripped_bulbis_stem", "bulbis_planks"), BYG_3 = stripAndMakePlanks(Mods.BYG, "bulbis_wood", "stripped_bulbis_wood", "bulbis_planks"), diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/FillingRecipeGen.java b/src/main/java/com/simibubi/create/foundation/data/recipe/FillingRecipeGen.java index 75cdb024a..aba7ea3d1 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/FillingRecipeGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/FillingRecipeGen.java @@ -4,7 +4,7 @@ import com.simibubi.create.AllFluids; import com.simibubi.create.AllItems; import com.simibubi.create.AllRecipeTypes; import com.simibubi.create.AllTags.AllFluidTags; -import com.simibubi.create.content.contraptions.fluids.potion.PotionFluidHandler; +import com.simibubi.create.content.fluids.potion.PotionFluidHandler; import net.minecraft.data.PackOutput; import net.minecraft.world.item.Items; diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/LogStrippingFakeRecipes.java b/src/main/java/com/simibubi/create/foundation/data/recipe/LogStrippingFakeRecipes.java index 4dbb1fdc0..0c5525676 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/LogStrippingFakeRecipes.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/LogStrippingFakeRecipes.java @@ -3,11 +3,11 @@ package com.simibubi.create.foundation.data.recipe; import java.util.ArrayList; import java.util.List; -import com.simibubi.create.content.contraptions.components.deployer.ManualApplicationRecipe; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder; -import com.simibubi.create.foundation.config.AllConfigs; +import com.simibubi.create.content.kinetics.deployer.ManualApplicationRecipe; +import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.RegisteredObjects; +import com.simibubi.create.infrastructure.config.AllConfigs; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.ItemTags; @@ -29,7 +29,7 @@ public class LogStrippingFakeRecipes { public static List createRecipes() { List recipes = new ArrayList<>(); - if (!AllConfigs.SERVER.recipes.displayLogStrippingRecipes.get()) + if (!AllConfigs.server().recipes.displayLogStrippingRecipes.get()) return recipes; ItemStack axe = new ItemStack(Items.IRON_AXE); diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/MixingRecipeGen.java b/src/main/java/com/simibubi/create/foundation/data/recipe/MixingRecipeGen.java index 9f8d05819..3a5268469 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/MixingRecipeGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/MixingRecipeGen.java @@ -3,8 +3,8 @@ package com.simibubi.create.foundation.data.recipe; import com.simibubi.create.AllFluids; import com.simibubi.create.AllItems; import com.simibubi.create.AllRecipeTypes; -import com.simibubi.create.content.contraptions.processing.HeatCondition; -import com.simibubi.create.foundation.utility.recipe.BlockTagIngredient; +import com.simibubi.create.content.processing.recipe.HeatCondition; +import com.simibubi.create.foundation.recipe.BlockTagIngredient; import net.minecraft.data.PackOutput; import net.minecraft.tags.BlockTags; diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/ProcessingRecipeGen.java b/src/main/java/com/simibubi/create/foundation/data/recipe/ProcessingRecipeGen.java index 897d6afbd..47022ed60 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/ProcessingRecipeGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/ProcessingRecipeGen.java @@ -7,11 +7,11 @@ import java.util.function.Supplier; import java.util.function.UnaryOperator; import com.simibubi.create.Create; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipe; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipeSerializer; +import com.simibubi.create.content.processing.recipe.ProcessingRecipe; +import com.simibubi.create.content.processing.recipe.ProcessingRecipeBuilder; +import com.simibubi.create.content.processing.recipe.ProcessingRecipeSerializer; +import com.simibubi.create.foundation.recipe.IRecipeTypeInfo; import com.simibubi.create.foundation.utility.RegisteredObjects; -import com.simibubi.create.foundation.utility.recipe.IRecipeTypeInfo; import net.minecraft.data.CachedOutput; import net.minecraft.data.DataGenerator; @@ -71,11 +71,11 @@ public abstract class ProcessingRecipeGen extends CreateRecipeProvider { Supplier singleIngredient, UnaryOperator> transform) { ProcessingRecipeSerializer serializer = getSerializer(); GeneratedRecipe generatedRecipe = c -> { - ItemLike iItemProvider = singleIngredient.get(); + ItemLike itemLike = singleIngredient.get(); transform .apply(new ProcessingRecipeBuilder<>(serializer.getFactory(), - new ResourceLocation(namespace, RegisteredObjects.getKeyOrThrow(iItemProvider.asItem()) - .getPath())).withItemIngredients(Ingredient.of(iItemProvider))) + new ResourceLocation(namespace, RegisteredObjects.getKeyOrThrow(itemLike.asItem()) + .getPath())).withItemIngredients(Ingredient.of(itemLike))) .build(c); }; all.add(generatedRecipe); diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/SequencedAssemblyRecipeGen.java b/src/main/java/com/simibubi/create/foundation/data/recipe/SequencedAssemblyRecipeGen.java index 8ada736da..fc0b03976 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/SequencedAssemblyRecipeGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/SequencedAssemblyRecipeGen.java @@ -7,10 +7,10 @@ import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; import com.simibubi.create.AllTags.AllItemTags; import com.simibubi.create.Create; -import com.simibubi.create.content.contraptions.components.deployer.DeployerApplicationRecipe; -import com.simibubi.create.content.contraptions.components.press.PressingRecipe; -import com.simibubi.create.content.contraptions.fluids.actors.FillingRecipe; -import com.simibubi.create.content.contraptions.itemAssembly.SequencedAssemblyRecipeBuilder; +import com.simibubi.create.content.fluids.transfer.FillingRecipe; +import com.simibubi.create.content.kinetics.deployer.DeployerApplicationRecipe; +import com.simibubi.create.content.kinetics.press.PressingRecipe; +import com.simibubi.create.content.processing.sequenced.SequencedAssemblyRecipeBuilder; import net.minecraft.data.PackOutput; import net.minecraft.world.item.Items; diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/StandardRecipeGen.java b/src/main/java/com/simibubi/create/foundation/data/recipe/StandardRecipeGen.java index 22d6a931d..5368f2013 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/StandardRecipeGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/StandardRecipeGen.java @@ -24,10 +24,8 @@ import com.simibubi.create.AllRecipeTypes; import com.simibubi.create.AllTags; import com.simibubi.create.AllTags.AllItemTags; import com.simibubi.create.Create; -import com.simibubi.create.content.AllSections; -import com.simibubi.create.content.palettes.AllPaletteBlocks; -import com.simibubi.create.content.palettes.AllPaletteStoneTypes; -import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.content.decoration.palettes.AllPaletteBlocks; +import com.simibubi.create.content.decoration.palettes.AllPaletteStoneTypes; import com.simibubi.create.foundation.utility.RegisteredObjects; import com.tterrag.registrate.util.entry.BlockEntry; import com.tterrag.registrate.util.entry.ItemEntry; @@ -41,6 +39,7 @@ import net.minecraft.data.recipes.ShapedRecipeBuilder; import net.minecraft.data.recipes.ShapelessRecipeBuilder; import net.minecraft.data.recipes.SimpleCookingRecipeBuilder; import net.minecraft.data.recipes.SpecialRecipeBuilder; +import net.minecraft.data.recipes.UpgradeRecipeBuilder; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.ItemTags; import net.minecraft.tags.TagKey; @@ -69,7 +68,7 @@ public class StandardRecipeGen extends CreateRecipeProvider { * (Ctrl-o) in Eclipse */ - private Marker MATERIALS = enterSection(AllSections.MATERIALS); + private Marker MATERIALS = enterFolder("materials"); GeneratedRecipe @@ -93,6 +92,28 @@ public class StandardRecipeGen extends CreateRecipeProvider { .pattern("CCC") .pattern("CCC")), + ANDESITE_ALLOY_FROM_BLOCK = create(AllItems.ANDESITE_ALLOY).withSuffix("_from_block") + .returns(9) + .unlockedBy(I::andesite) + .viaShapeless(b -> b.requires(AllBlocks.ANDESITE_ALLOY_BLOCK.get())), + + ANDESITE_ALLOY_BLOCK = create(AllBlocks.ANDESITE_ALLOY_BLOCK).unlockedBy(I::andesite) + .viaShaped(b -> b.define('C', I.andesite()) + .pattern("CCC") + .pattern("CCC") + .pattern("CCC")), + + EXPERIENCE_FROM_BLOCK = create(AllItems.EXP_NUGGET).withSuffix("_from_block") + .returns(9) + .unlockedBy(AllItems.EXP_NUGGET::get) + .viaShapeless(b -> b.requires(AllBlocks.EXPERIENCE_BLOCK.get())), + + EXPERIENCE_BLOCK = create(AllBlocks.EXPERIENCE_BLOCK).unlockedBy(AllItems.EXP_NUGGET::get) + .viaShaped(b -> b.define('C', AllItems.EXP_NUGGET.get()) + .pattern("CCC") + .pattern("CCC") + .pattern("CCC")), + BRASS_COMPACTING = metalCompacting(ImmutableList.of(AllItems.BRASS_NUGGET, AllItems.BRASS_INGOT, AllBlocks.BRASS_BLOCK), ImmutableList.of(I::brassNugget, I::brass, I::brassBlock)), @@ -137,7 +158,7 @@ public class StandardRecipeGen extends CreateRecipeProvider { ; - private Marker CURIOSITIES = enterSection(AllSections.CURIOSITIES); + private Marker CURIOSITIES = enterFolder("curiosities"); GeneratedRecipe @@ -176,19 +197,12 @@ public class StandardRecipeGen extends CreateRecipeProvider { ; - private Marker KINETICS = enterSection(AllSections.KINETICS); + private Marker KINETICS = enterFolder("kinetics"); - GeneratedRecipe ANDESITE_LADDER = create(AllBlocks.ANDESITE_LADDER).returns(4) - .unlockedBy(I::andesite) + GeneratedRecipe BASIN = create(AllBlocks.BASIN).unlockedBy(I::andesite) .viaShaped(b -> b.define('A', I.andesite()) .pattern("A A") - .pattern("AAA") - .pattern("A A")), - - BASIN = create(AllBlocks.BASIN).unlockedBy(I::andesite) - .viaShaped(b -> b.define('A', I.andesite()) - .pattern("A A") - .pattern("AAA")), + .pattern("AAA")), GOGGLES = create(AllItems.GOGGLES).unlockedBy(I::andesite) .viaShaped(b -> b.define('G', Tags.Items.GLASS) @@ -242,14 +256,21 @@ public class StandardRecipeGen extends CreateRecipeProvider { .requires(I.planks()) .requires(I.planks())), - LARGE_COGWHEEL_FROM_LITTLE = create(AllBlocks.LARGE_COGWHEEL).withSuffix("from_little") + LARGE_COGWHEEL_FROM_LITTLE = create(AllBlocks.LARGE_COGWHEEL).withSuffix("_from_little") .unlockedBy(I::andesite) .viaShapeless(b -> b.requires(I.cog()) .requires(I.planks())), WATER_WHEEL = create(AllBlocks.WATER_WHEEL).unlockedBy(I::andesite) - .viaShaped(b -> b.define('S', ItemTags.WOODEN_SLABS) - .define('C', AllBlocks.LARGE_COGWHEEL.get()) + .viaShaped(b -> b.define('S', I.planks()) + .define('C', I.shaft()) + .pattern("SSS") + .pattern("SCS") + .pattern("SSS")), + + LARGE_WATER_WHEEL = create(AllBlocks.LARGE_WATER_WHEEL).unlockedBy(AllBlocks.WATER_WHEEL::get) + .viaShaped(b -> b.define('S', I.planks()) + .define('C', AllBlocks.WATER_WHEEL.get()) .pattern("SSS") .pattern("SCS") .pattern("SSS")), @@ -326,14 +347,29 @@ public class StandardRecipeGen extends CreateRecipeProvider { .requires(I.brassSheet())), TRAIN_DOOR = create(AllBlocks.TRAIN_DOOR).returns(1) - .unlockedByTag(() -> I.brass()) + .unlockedBy(() -> I.railwayCasing()) .viaShapeless(b -> b.requires(ItemTags.WOODEN_DOORS) - .requires(I.brassSheet())), + .requires(I.railwayCasing())), + + ANDESITE_DOOR = create(AllBlocks.ANDESITE_DOOR).returns(1) + .unlockedBy(() -> I.andesiteCasing()) + .viaShapeless(b -> b.requires(ItemTags.WOODEN_DOORS) + .requires(I.andesiteCasing())), + + BRASS_DOOR = create(AllBlocks.BRASS_DOOR).returns(1) + .unlockedBy(() -> I.brassCasing()) + .viaShapeless(b -> b.requires(ItemTags.WOODEN_DOORS) + .requires(I.brassCasing())), + + COPPER_DOOR = create(AllBlocks.COPPER_DOOR).returns(1) + .unlockedBy(() -> I.copperCasing()) + .viaShapeless(b -> b.requires(ItemTags.WOODEN_DOORS) + .requires(I.copperCasing())), TRAIN_TRAPDOOR = create(AllBlocks.TRAIN_TRAPDOOR).returns(1) - .unlockedByTag(() -> I.brass()) + .unlockedBy(() -> I.railwayCasing()) .viaShapeless(b -> b.requires(ItemTags.WOODEN_TRAPDOORS) - .requires(I.brassSheet())), + .requires(I.railwayCasing())), FRAMED_GLASS_DOOR = create(AllBlocks.FRAMED_GLASS_DOOR).returns(1) .unlockedBy(AllPaletteBlocks.FRAMED_GLASS::get) @@ -594,7 +630,7 @@ public class StandardRecipeGen extends CreateRecipeProvider { .viaShapeless(b -> b.requires(I.railwayCasing()) .requires(Items.COMPASS)), - TRAIN_CONTROLS = create(AllBlocks.CONTROLS).unlockedBy(I::railwayCasing) + TRAIN_CONTROLS = create(AllBlocks.TRAIN_CONTROLS).unlockedBy(I::railwayCasing) .viaShaped(b -> b.define('I', I.precisionMechanism()) .define('B', Items.LEVER) .define('C', I.railwayCasing()) @@ -634,6 +670,22 @@ public class StandardRecipeGen extends CreateRecipeProvider { .pattern("C") .pattern("I")), + ELEVATOR_PULLEY = create(AllBlocks.ELEVATOR_PULLEY).unlockedByTag(I::brass) + .viaShaped(b -> b.define('B', I.brassCasing()) + .define('C', Items.DRIED_KELP_BLOCK) + .define('I', I.ironSheet()) + .pattern("B") + .pattern("C") + .pattern("I")), + + CONTRAPTION_CONTROLS = create(AllBlocks.CONTRAPTION_CONTROLS).unlockedBy(I::andesite) + .viaShaped(b -> b.define('B', ItemTags.BUTTONS) + .define('C', I.andesiteCasing()) + .define('I', I.electronTube()) + .pattern("B") + .pattern("C") + .pattern("I")), + EMPTY_BLAZE_BURNER = create(AllItems.EMPTY_BLAZE_BURNER).unlockedByTag(I::iron) .viaShaped(b -> b.define('A', Tags.Items.NETHERRACK) .define('I', I.ironSheet()) @@ -815,6 +867,14 @@ public class StandardRecipeGen extends CreateRecipeProvider { .pattern("AAA") .pattern(" C ")), + MECHANICAL_ROLLER = create(AllBlocks.MECHANICAL_ROLLER).unlockedBy(I::andesiteCasing) + .viaShaped(b -> b.define('C', I.andesiteCasing()) + .define('A', I.electronTube()) + .define('I', AllBlocks.CRUSHING_WHEEL.get()) + .pattern("A") + .pattern("C") + .pattern("I")), + MECHANICAL_DRILL = create(AllBlocks.MECHANICAL_DRILL).unlockedBy(I::andesiteCasing) .viaShaped(b -> b.define('C', I.andesiteCasing()) .define('A', I.andesite()) @@ -830,7 +890,7 @@ public class StandardRecipeGen extends CreateRecipeProvider { ; - private Marker LOGISTICS = enterSection(AllSections.LOGISTICS); + private Marker LOGISTICS = enterFolder("logistics"); GeneratedRecipe @@ -875,15 +935,21 @@ public class StandardRecipeGen extends CreateRecipeProvider { .pattern("AA") .pattern("KK")), - CONTENT_OBSERVER = create(AllBlocks.CONTENT_OBSERVER).unlockedBy(AllItems.BELT_CONNECTOR::get) + SMART_OBSERVER = create(AllBlocks.SMART_OBSERVER).unlockedBy(I::brassCasing) + .viaShaped(b -> b.define('B', I.brassCasing()) + .define('R', I.electronTube()) + .define('I', Blocks.OBSERVER) + .pattern("R") + .pattern("B") + .pattern("I")), + + THRESHOLD_SWITCH = create(AllBlocks.THRESHOLD_SWITCH).unlockedBy(I::brassCasing) .viaShaped(b -> b.define('B', I.brassCasing()) .define('R', I.electronTube()) .define('I', Blocks.COMPARATOR) - .pattern("I") + .pattern("R") .pattern("B") - .pattern("R")), - - OBSERVER_CYCLE = conversionCycle(ImmutableList.of(AllBlocks.CONTENT_OBSERVER, AllBlocks.STOCKPILE_SWITCH)), + .pattern("I")), PULSE_EXTENDER = create(AllBlocks.PULSE_EXTENDER).unlockedByTag(I::redstone) .viaShaped(b -> b.define('T', Blocks.REDSTONE_TORCH) @@ -936,7 +1002,7 @@ public class StandardRecipeGen extends CreateRecipeProvider { ; - private Marker SCHEMATICS = enterSection(AllSections.SCHEMATICS); + private Marker SCHEMATICS = enterFolder("schematics"); GeneratedRecipe @@ -966,7 +1032,7 @@ public class StandardRecipeGen extends CreateRecipeProvider { ; - private Marker PALETTES = enterSection(AllSections.PALETTES); + private Marker PALETTES = enterFolder("palettes"); GeneratedRecipe @@ -989,7 +1055,18 @@ public class StandardRecipeGen extends CreateRecipeProvider { .viaShapeless(b -> b.requires(I.wheatFlour()) .requires(Items.WATER_BUCKET)), - DIVING_HELMET = create(AllItems.DIVING_HELMET).unlockedBy(I::copper) + CLIPBOARD = create(AllBlocks.CLIPBOARD).unlockedBy(I::andesite) + .viaShaped(b -> b.define('G', I.planks()) + .define('P', Items.PAPER) + .define('A', I.andesite()) + .pattern("A") + .pattern("P") + .pattern("G")), + + CLIPBOARD_CLEAR = clearData(AllBlocks.CLIPBOARD), SCHEDULE_CLEAR = clearData(AllItems.SCHEDULE), + FILTER_CLEAR = clearData(AllItems.FILTER), ATTRIBUTE_FILTER_CLEAR = clearData(AllItems.ATTRIBUTE_FILTER), + + DIVING_HELMET = create(AllItems.COPPER_DIVING_HELMET).unlockedBy(I::copper) .viaShaped(b -> b.define('G', Tags.Items.GLASS) .define('P', I.copper()) .pattern("PPP") @@ -1004,7 +1081,7 @@ public class StandardRecipeGen extends CreateRecipeProvider { .pattern("PBP") .pattern(" P ")), - DIVING_BOOTS = create(AllItems.DIVING_BOOTS).unlockedBy(I::copper) + DIVING_BOOTS = create(AllItems.COPPER_DIVING_BOOTS).unlockedBy(I::copper) .viaShaped(b -> b.define('G', I.andesite()) .define('P', I.copper()) .pattern("P P") @@ -1031,7 +1108,21 @@ public class StandardRecipeGen extends CreateRecipeProvider { .viaShapeless(b -> b.requires(Ingredient.of(ItemTags.SMALL_FLOWERS), 2) .requires(Ingredient.of(Items.HORN_CORAL, Items.BRAIN_CORAL, Items.TUBE_CORAL, Items.BUBBLE_CORAL, Items.FIRE_CORAL)) - .requires(Items.BONE_MEAL)) + .requires(Items.BONE_MEAL)), + + NETHERITE_DIVING_HELMET = + create(AllItems.NETHERITE_DIVING_HELMET).viaSmithing(AllItems.COPPER_DIVING_HELMET::get, I::netherite), + NETHERITE_BACKTANK = + create(AllItems.NETHERITE_BACKTANK).viaSmithing(AllItems.COPPER_BACKTANK::get, I::netherite), + NETHERITE_DIVING_BOOTS = + create(AllItems.NETHERITE_DIVING_BOOTS).viaSmithing(AllItems.COPPER_DIVING_BOOTS::get, I::netherite), + + NETHERITE_DIVING_HELMET_2 = create(AllItems.NETHERITE_DIVING_HELMET).withSuffix("_from_netherite") + .viaSmithing(() -> Items.NETHERITE_HELMET, () -> Ingredient.of(AllItems.COPPER_DIVING_HELMET.get())), + NETHERITE_BACKTANK_2 = create(AllItems.NETHERITE_BACKTANK).withSuffix("_from_netherite") + .viaSmithing(() -> Items.NETHERITE_CHESTPLATE, () -> Ingredient.of(AllItems.COPPER_BACKTANK.get())), + NETHERITE_DIVING_BOOTS_2 = create(AllItems.NETHERITE_DIVING_BOOTS).withSuffix("_from_netherite") + .viaSmithing(() -> Items.NETHERITE_BOOTS, () -> Ingredient.of(AllItems.COPPER_DIVING_BOOTS.get())) ; @@ -1087,11 +1178,6 @@ public class StandardRecipeGen extends CreateRecipeProvider { String currentFolder = ""; - Marker enterSection(AllSections section) { - currentFolder = Lang.asId(section.name()); - return new Marker(); - } - Marker enterFolder(String folder) { currentFolder = folder; return new Marker(); @@ -1191,6 +1277,12 @@ public class StandardRecipeGen extends CreateRecipeProvider { return result; } + GeneratedRecipe clearData(ItemProviderEntry item) { + return create(item).withSuffix("_clear") + .unlockedBy(item::get) + .viaShapeless(b -> b.requires(item.get())); + } + class GeneratedRecipeBuilder { private String path; @@ -1275,6 +1367,18 @@ public class StandardRecipeGen extends CreateRecipeProvider { }); } + GeneratedRecipe viaSmithing(Supplier base, Supplier upgradeMaterial) { + return register(consumer -> { + UpgradeRecipeBuilder b = UpgradeRecipeBuilder.smithing(Ingredient.of(base.get()), upgradeMaterial.get(), + RecipeCategory.COMBAT, result.get() + .asItem()); + b.unlocks("has_item", inventoryTrigger(ItemPredicate.Builder.item() + .of(base.get()) + .build())); + b.save(consumer, createLocation("crafting")); + }); + } + private ResourceLocation createSimpleLocation(String recipeType) { return Create.asResource(recipeType + "/" + getRegistryName().getPath() + suffix); } diff --git a/src/main/java/com/simibubi/create/foundation/events/ClientEvents.java b/src/main/java/com/simibubi/create/foundation/events/ClientEvents.java new file mode 100644 index 000000000..45f480a03 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/events/ClientEvents.java @@ -0,0 +1,411 @@ +package com.simibubi.create.foundation.events; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllFluids; +import com.simibubi.create.AllItems; +import com.simibubi.create.AllPackets; +import com.simibubi.create.Create; +import com.simibubi.create.CreateClient; +import com.simibubi.create.content.contraptions.ContraptionHandler; +import com.simibubi.create.content.contraptions.actors.trainControls.ControlsHandler; +import com.simibubi.create.content.contraptions.chassis.ChassisRangeDisplay; +import com.simibubi.create.content.contraptions.minecart.CouplingHandlerClient; +import com.simibubi.create.content.contraptions.minecart.CouplingPhysics; +import com.simibubi.create.content.contraptions.minecart.CouplingRenderer; +import com.simibubi.create.content.contraptions.minecart.capability.CapabilityMinecartController; +import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher; +import com.simibubi.create.content.decoration.girder.GirderWrenchBehavior; +import com.simibubi.create.content.equipment.armor.BacktankArmorLayer; +import com.simibubi.create.content.equipment.armor.DivingHelmetItem; +import com.simibubi.create.content.equipment.armor.NetheriteBacktankFirstPersonRenderer; +import com.simibubi.create.content.equipment.armor.RemainingAirOverlay; +import com.simibubi.create.content.equipment.blueprint.BlueprintOverlayRenderer; +import com.simibubi.create.content.equipment.clipboard.ClipboardValueSettingsHandler; +import com.simibubi.create.content.equipment.extendoGrip.ExtendoGripRenderHandler; +import com.simibubi.create.content.equipment.goggles.GoggleOverlayRenderer; +import com.simibubi.create.content.equipment.toolbox.ToolboxHandlerClient; +import com.simibubi.create.content.equipment.zapper.ZapperItem; +import com.simibubi.create.content.equipment.zapper.terrainzapper.WorldshaperRenderHandler; +import com.simibubi.create.content.kinetics.KineticDebugger; +import com.simibubi.create.content.kinetics.belt.item.BeltConnectorHandler; +import com.simibubi.create.content.kinetics.fan.AirCurrent; +import com.simibubi.create.content.kinetics.mechanicalArm.ArmInteractionPointHandler; +import com.simibubi.create.content.kinetics.turntable.TurntableHandler; +import com.simibubi.create.content.logistics.depot.EjectorTargetHandler; +import com.simibubi.create.content.processing.sequenced.SequencedAssemblyRecipe; +import com.simibubi.create.content.redstone.displayLink.DisplayLinkBlockItem; +import com.simibubi.create.content.redstone.link.LinkRenderer; +import com.simibubi.create.content.redstone.link.controller.LinkedControllerClientHandler; +import com.simibubi.create.content.trains.CameraDistanceModifier; +import com.simibubi.create.content.trains.TrainHUD; +import com.simibubi.create.content.trains.entity.CarriageContraptionEntity; +import com.simibubi.create.content.trains.entity.CarriageCouplingRenderer; +import com.simibubi.create.content.trains.entity.TrainRelocator; +import com.simibubi.create.content.trains.schedule.TrainHatArmorLayer; +import com.simibubi.create.content.trains.track.CurvedTrackInteraction; +import com.simibubi.create.content.trains.track.TrackBlockOutline; +import com.simibubi.create.content.trains.track.TrackPlacement; +import com.simibubi.create.content.trains.track.TrackPlacementOverlay; +import com.simibubi.create.content.trains.track.TrackTargetingClient; +import com.simibubi.create.foundation.blockEntity.behaviour.edgeInteraction.EdgeInteractionRenderer; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringRenderer; +import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollValueHandler; +import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollValueRenderer; +import com.simibubi.create.foundation.config.ui.BaseConfigScreen; +import com.simibubi.create.foundation.fluid.FluidHelper; +import com.simibubi.create.foundation.item.TooltipModifier; +import com.simibubi.create.foundation.networking.LeftClickPacket; +import com.simibubi.create.foundation.placement.PlacementHelpers; +import com.simibubi.create.foundation.ponder.PonderTooltipHandler; +import com.simibubi.create.foundation.render.SuperRenderTypeBuffer; +import com.simibubi.create.foundation.sound.SoundScapes; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.CameraAngleAnimationService; +import com.simibubi.create.foundation.utility.ServerSpeedProvider; +import com.simibubi.create.foundation.utility.worldWrappers.WrappedClientWorld; +import com.simibubi.create.infrastructure.config.AllConfigs; + +import net.minecraft.client.Camera; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.renderer.entity.EntityRenderDispatcher; +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.client.ConfigScreenHandler; +import net.minecraftforge.client.event.ClientPlayerNetworkEvent; +import net.minecraftforge.client.event.EntityRenderersEvent; +import net.minecraftforge.client.event.RegisterClientReloadListenersEvent; +import net.minecraftforge.client.event.RegisterGuiOverlaysEvent; +import net.minecraftforge.client.event.RenderLevelLastEvent; +import net.minecraftforge.client.event.RenderTooltipEvent; +import net.minecraftforge.client.event.ViewportEvent; +import net.minecraftforge.client.gui.overlay.VanillaGuiOverlay; +import net.minecraftforge.event.TickEvent.ClientTickEvent; +import net.minecraftforge.event.TickEvent.Phase; +import net.minecraftforge.event.TickEvent.RenderTickEvent; +import net.minecraftforge.event.entity.EntityMountEvent; +import net.minecraftforge.event.entity.player.ItemTooltipEvent; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import net.minecraftforge.event.level.LevelEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.ModContainer; +import net.minecraftforge.fml.ModList; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; +import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent; + +@EventBusSubscriber(Dist.CLIENT) +public class ClientEvents { + + @SubscribeEvent + public static void onTick(ClientTickEvent event) { + if (!isGameActive()) + return; + + Level world = Minecraft.getInstance().level; + if (event.phase == Phase.START) { + LinkedControllerClientHandler.tick(); + ControlsHandler.tick(); + AirCurrent.tickClientPlayerSounds(); + return; + } + + SoundScapes.tick(); + AnimationTickHolder.tick(); + + CreateClient.SCHEMATIC_SENDER.tick(); + CreateClient.SCHEMATIC_AND_QUILL_HANDLER.tick(); + CreateClient.GLUE_HANDLER.tick(); + CreateClient.SCHEMATIC_HANDLER.tick(); + CreateClient.ZAPPER_RENDER_HANDLER.tick(); + CreateClient.POTATO_CANNON_RENDER_HANDLER.tick(); + CreateClient.SOUL_PULSE_EFFECT_HANDLER.tick(world); + CreateClient.RAILWAYS.clientTick(); + + ContraptionHandler.tick(world); + CapabilityMinecartController.tick(world); + CouplingPhysics.tick(world); + + PonderTooltipHandler.tick(); + // ScreenOpener.tick(); + ServerSpeedProvider.clientTick(); + BeltConnectorHandler.tick(); +// BeltSlicer.tickHoveringInformation(); + FilteringRenderer.tick(); + LinkRenderer.tick(); + ScrollValueRenderer.tick(); + ChassisRangeDisplay.tick(); + EdgeInteractionRenderer.tick(); + GirderWrenchBehavior.tick(); + WorldshaperRenderHandler.tick(); + CouplingHandlerClient.tick(); + CouplingRenderer.tickDebugModeRenders(); + KineticDebugger.tick(); + ExtendoGripRenderHandler.tick(); + // CollisionDebugger.tick(); + ArmInteractionPointHandler.tick(); + EjectorTargetHandler.tick(); + PlacementHelpers.tick(); + CreateClient.OUTLINER.tickOutlines(); + CreateClient.GHOST_BLOCKS.tickGhosts(); + ContraptionRenderDispatcher.tick(world); + BlueprintOverlayRenderer.tick(); + ToolboxHandlerClient.clientTick(); + TrackTargetingClient.clientTick(); + TrackPlacement.clientTick(); + TrainRelocator.clientTick(); + DisplayLinkBlockItem.clientTick(); + CurvedTrackInteraction.clientTick(); + CameraDistanceModifier.tick(); + CameraAngleAnimationService.tick(); + TrainHUD.tick(); + ClipboardValueSettingsHandler.clientTick(); + CreateClient.VALUE_SETTINGS_HANDLER.tick(); + ScrollValueHandler.tick(); + NetheriteBacktankFirstPersonRenderer.clientTick(); + } + + @SubscribeEvent + public static void onJoin(ClientPlayerNetworkEvent.LoggingIn event) { + CreateClient.checkGraphicsFanciness(); + } + + @SubscribeEvent + public static void onLeave(ClientPlayerNetworkEvent.LoggingOut event) { + CreateClient.RAILWAYS.cleanUp(); + } + + @SubscribeEvent + public static void onLoadWorld(LevelEvent.Load event) { + LevelAccessor world = event.getLevel(); + if (world.isClientSide() && world instanceof ClientLevel && !(world instanceof WrappedClientWorld)) { + CreateClient.invalidateRenderers(); + AnimationTickHolder.reset(); + } + } + + @SubscribeEvent + public static void onUnloadWorld(LevelEvent.Unload event) { + if (!event.getLevel() + .isClientSide()) + return; + CreateClient.invalidateRenderers(); + CreateClient.SOUL_PULSE_EFFECT_HANDLER.refresh(); + AnimationTickHolder.reset(); + ControlsHandler.levelUnloaded(event.getLevel()); + } + + @SubscribeEvent + public static void onRenderWorld(RenderLevelLastEvent event) { + PoseStack ms = event.getPoseStack(); + ms.pushPose(); + SuperRenderTypeBuffer buffer = SuperRenderTypeBuffer.getInstance(); + float partialTicks = AnimationTickHolder.getPartialTicks(); + Vec3 camera = Minecraft.getInstance().gameRenderer.getMainCamera() + .getPosition(); + + TrackBlockOutline.drawCurveSelection(ms, buffer, camera); + TrackTargetingClient.render(ms, buffer, camera); + CouplingRenderer.renderAll(ms, buffer, camera); + CarriageCouplingRenderer.renderAll(ms, buffer, camera); + CreateClient.SCHEMATIC_HANDLER.render(ms, buffer, camera); + CreateClient.GHOST_BLOCKS.renderAll(ms, buffer, camera); + CreateClient.OUTLINER.renderOutlines(ms, buffer, camera, partialTicks); + + buffer.draw(); + RenderSystem.enableCull(); + ms.popPose(); + } + + @SubscribeEvent + public static void onCameraSetup(ViewportEvent.ComputeCameraAngles event) { + float partialTicks = AnimationTickHolder.getPartialTicks(); + + if (CameraAngleAnimationService.isYawAnimating()) + event.setYaw(CameraAngleAnimationService.getYaw(partialTicks)); + + if (CameraAngleAnimationService.isPitchAnimating()) + event.setPitch(CameraAngleAnimationService.getPitch(partialTicks)); + } + + @SubscribeEvent + public static void getItemTooltipColor(RenderTooltipEvent.Color event) { + PonderTooltipHandler.handleTooltipColor(event); + } + + @SubscribeEvent + public static void addToItemTooltip(ItemTooltipEvent event) { + if (!AllConfigs.client().tooltips.get()) + return; + if (event.getEntity() == null) + return; + + Item item = event.getItemStack().getItem(); + TooltipModifier modifier = TooltipModifier.REGISTRY.get(item); + if (modifier != null && modifier != TooltipModifier.EMPTY) { + modifier.modify(event); + } + + PonderTooltipHandler.addToTooltip(event); + SequencedAssemblyRecipe.addToTooltip(event); + } + + @SubscribeEvent + public static void onRenderTick(RenderTickEvent event) { + if (!isGameActive()) + return; + TurntableHandler.gameRenderTick(); + } + + @SubscribeEvent + public static void onMount(EntityMountEvent event) { + if (event.getEntityMounting() != Minecraft.getInstance().player) + return; + + if (event.isDismounting()) { + CameraDistanceModifier.reset(); + return; + } + + if (!event.isMounting() || !(event.getEntityBeingMounted() instanceof CarriageContraptionEntity carriage)) { + return; + } + + CameraDistanceModifier.zoomOut(); + } + + protected static boolean isGameActive() { + return !(Minecraft.getInstance().level == null || Minecraft.getInstance().player == null); + } + + @SubscribeEvent + public static void getFogDensity(ViewportEvent.RenderFog event) { + Camera camera = event.getCamera(); + Level level = Minecraft.getInstance().level; + BlockPos blockPos = camera.getBlockPosition(); + FluidState fluidState = level.getFluidState(blockPos); + if (camera.getPosition().y >= blockPos.getY() + fluidState.getHeight(level, blockPos)) + return; + + Fluid fluid = fluidState.getType(); + Entity entity = camera.getEntity(); + + if (AllFluids.CHOCOLATE.get() + .isSame(fluid)) { + event.scaleFarPlaneDistance(1f / 32f * AllConfigs.client().chocolateTransparencyMultiplier.getF()); + event.setCanceled(true); + return; + } + + if (AllFluids.HONEY.get() + .isSame(fluid)) { + event.scaleFarPlaneDistance(1f / 8f * AllConfigs.client().honeyTransparencyMultiplier.getF()); + event.setCanceled(true); + return; + } + + if (entity.isSpectator()) + return; + + ItemStack divingHelmet = DivingHelmetItem.getWornItem(entity); + if (divingHelmet != null) { + if (FluidHelper.isWater(fluid)) { + event.scaleFarPlaneDistance(6.25f); + event.setCanceled(true); + return; + } else if (FluidHelper.isLava(fluid) && AllItems.NETHERITE_DIVING_HELMET.isIn(divingHelmet)) { + event.setNearPlaneDistance(-4.0f); + event.setFarPlaneDistance(20.0f); + event.setCanceled(true); + return; + } + } + } + + @SubscribeEvent + public static void getFogColor(ViewportEvent.ComputeFogColor event) { + Camera info = event.getCamera(); + Level level = Minecraft.getInstance().level; + BlockPos blockPos = info.getBlockPosition(); + FluidState fluidState = level.getFluidState(blockPos); + if (info.getPosition().y > blockPos.getY() + fluidState.getHeight(level, blockPos)) + return; + + Fluid fluid = fluidState.getType(); + + if (AllFluids.CHOCOLATE.get() + .isSame(fluid)) { + event.setRed(98 / 255f); + event.setGreen(32 / 255f); + event.setBlue(32 / 255f); + return; + } + + if (AllFluids.HONEY.get() + .isSame(fluid)) { + event.setRed(234 / 255f); + event.setGreen(174 / 255f); + event.setBlue(47 / 255f); + return; + } + } + + @SubscribeEvent + public static void leftClickEmpty(PlayerInteractEvent.LeftClickEmpty event) { + ItemStack stack = event.getItemStack(); + if (stack.getItem() instanceof ZapperItem) { + AllPackets.getChannel().sendToServer(new LeftClickPacket()); + } + } + + @EventBusSubscriber(value = Dist.CLIENT, bus = EventBusSubscriber.Bus.MOD) + public static class ModBusEvents { + + @SubscribeEvent + public static void registerClientReloadListeners(RegisterClientReloadListenersEvent event) { + event.registerReloadListener(CreateClient.RESOURCE_RELOAD_LISTENER); + } + + @SubscribeEvent + public static void addEntityRendererLayers(EntityRenderersEvent.AddLayers event) { + EntityRenderDispatcher dispatcher = Minecraft.getInstance() + .getEntityRenderDispatcher(); + BacktankArmorLayer.registerOnAll(dispatcher); + TrainHatArmorLayer.registerOnAll(dispatcher); + } + + @SubscribeEvent + public static void registerGuiOverlays(RegisterGuiOverlaysEvent event) { + // Register overlays in reverse order + event.registerAbove(VanillaGuiOverlay.AIR_LEVEL.id(), "remaining_air", RemainingAirOverlay.INSTANCE); + event.registerAbove(VanillaGuiOverlay.EXPERIENCE_BAR.id(), "train_hud", TrainHUD.OVERLAY); + event.registerAbove(VanillaGuiOverlay.HOTBAR.id(), "value_settings", CreateClient.VALUE_SETTINGS_HANDLER); + event.registerAbove(VanillaGuiOverlay.HOTBAR.id(), "track_placement", TrackPlacementOverlay.INSTANCE); + event.registerAbove(VanillaGuiOverlay.HOTBAR.id(), "goggle_info", GoggleOverlayRenderer.OVERLAY); + event.registerAbove(VanillaGuiOverlay.HOTBAR.id(), "blueprint", BlueprintOverlayRenderer.OVERLAY); + event.registerAbove(VanillaGuiOverlay.HOTBAR.id(), "linked_controller", LinkedControllerClientHandler.OVERLAY); + event.registerAbove(VanillaGuiOverlay.HOTBAR.id(), "schematic", CreateClient.SCHEMATIC_HANDLER); + event.registerAbove(VanillaGuiOverlay.HOTBAR.id(), "toolbox", ToolboxHandlerClient.OVERLAY); + } + + @SubscribeEvent + public static void onLoadComplete(FMLLoadCompleteEvent event) { + ModContainer createContainer = ModList.get() + .getModContainerById(Create.ID) + .orElseThrow(() -> new IllegalStateException("Create mod container missing on LoadComplete")); + createContainer.registerExtensionPoint(ConfigScreenHandler.ConfigScreenFactory.class, + () -> new ConfigScreenHandler.ConfigScreenFactory( + (mc, previousScreen) -> BaseConfigScreen.forCreate(previousScreen))); + } + + } + +} diff --git a/src/main/java/com/simibubi/create/events/CommonEvents.java b/src/main/java/com/simibubi/create/foundation/events/CommonEvents.java similarity index 86% rename from src/main/java/com/simibubi/create/events/CommonEvents.java rename to src/main/java/com/simibubi/create/foundation/events/CommonEvents.java index 11512be1d..b7f71d373 100644 --- a/src/main/java/com/simibubi/create/events/CommonEvents.java +++ b/src/main/java/com/simibubi/create/foundation/events/CommonEvents.java @@ -1,23 +1,23 @@ -package com.simibubi.create.events; +package com.simibubi.create.foundation.events; import com.simibubi.create.Create; -import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionHandler; -import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsServerHandler; -import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingPhysics; -import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.CapabilityMinecartController; -import com.simibubi.create.content.contraptions.wrench.WrenchItem; -import com.simibubi.create.content.curiosities.toolbox.ToolboxHandler; -import com.simibubi.create.content.curiosities.weapons.PotatoProjectileTypeManager; -import com.simibubi.create.content.curiosities.zapper.ZapperInteractionHandler; -import com.simibubi.create.content.curiosities.zapper.ZapperItem; -import com.simibubi.create.content.logistics.item.LinkedControllerServerHandler; -import com.simibubi.create.content.logistics.trains.entity.CarriageEntityHandler; +import com.simibubi.create.content.contraptions.ContraptionHandler; +import com.simibubi.create.content.contraptions.actors.trainControls.ControlsServerHandler; +import com.simibubi.create.content.contraptions.minecart.CouplingPhysics; +import com.simibubi.create.content.contraptions.minecart.capability.CapabilityMinecartController; +import com.simibubi.create.content.equipment.potatoCannon.PotatoProjectileTypeManager; +import com.simibubi.create.content.equipment.toolbox.ToolboxHandler; +import com.simibubi.create.content.equipment.wrench.WrenchItem; +import com.simibubi.create.content.equipment.zapper.ZapperInteractionHandler; +import com.simibubi.create.content.equipment.zapper.ZapperItem; +import com.simibubi.create.content.redstone.link.controller.LinkedControllerServerHandler; +import com.simibubi.create.content.trains.entity.CarriageEntityHandler; import com.simibubi.create.foundation.ModFilePackResources; -import com.simibubi.create.foundation.command.AllCommands; +import com.simibubi.create.foundation.recipe.RecipeFinder; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.ServerSpeedProvider; import com.simibubi.create.foundation.utility.WorldAttached; -import com.simibubi.create.foundation.utility.recipe.RecipeFinder; +import com.simibubi.create.infrastructure.command.AllCommands; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.packs.PackType; @@ -79,7 +79,7 @@ public class CommonEvents { ToolboxHandler.playerLogin(player); Create.RAILWAYS.playerLogin(player); } - + @SubscribeEvent public static void playerLoggedOut(PlayerLoggedOutEvent event) { Player player = event.getEntity(); @@ -132,7 +132,7 @@ public class CommonEvents { public static void onEntityEnterSection(EntityEvent.EnteringSection event) { CarriageEntityHandler.onEntityEnterSection(event); } - + @SubscribeEvent public static void addReloadListeners(AddReloadListenerEvent event) { event.addListener(RecipeFinder.LISTENER); @@ -212,7 +212,5 @@ public class CommonEvents { }); } } - } - } diff --git a/src/main/java/com/simibubi/create/events/InputEvents.java b/src/main/java/com/simibubi/create/foundation/events/InputEvents.java similarity index 75% rename from src/main/java/com/simibubi/create/events/InputEvents.java rename to src/main/java/com/simibubi/create/foundation/events/InputEvents.java index ada1a3eb0..f5a524fcb 100644 --- a/src/main/java/com/simibubi/create/events/InputEvents.java +++ b/src/main/java/com/simibubi/create/foundation/events/InputEvents.java @@ -1,13 +1,12 @@ -package com.simibubi.create.events; +package com.simibubi.create.foundation.events; import com.simibubi.create.CreateClient; -import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.TrainHUD; -import com.simibubi.create.content.curiosities.toolbox.ToolboxHandlerClient; -import com.simibubi.create.content.logistics.item.LinkedControllerClientHandler; -import com.simibubi.create.content.logistics.trains.entity.TrainRelocator; -import com.simibubi.create.content.logistics.trains.track.CurvedTrackInteraction; -import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringHandler; -import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueHandler; +import com.simibubi.create.content.contraptions.elevator.ElevatorControlsHandler; +import com.simibubi.create.content.equipment.toolbox.ToolboxHandlerClient; +import com.simibubi.create.content.redstone.link.controller.LinkedControllerClientHandler; +import com.simibubi.create.content.trains.TrainHUD; +import com.simibubi.create.content.trains.entity.TrainRelocator; +import com.simibubi.create.content.trains.track.CurvedTrackInteraction; import net.minecraft.client.KeyMapping; import net.minecraft.client.Minecraft; @@ -39,8 +38,8 @@ public class InputEvents { double delta = event.getScrollDelta(); // CollisionDebugger.onScroll(delta); boolean cancelled = CreateClient.SCHEMATIC_HANDLER.mouseScrolled(delta) - || CreateClient.SCHEMATIC_AND_QUILL_HANDLER.mouseScrolled(delta) || FilteringHandler.onScroll(delta) - || ScrollValueHandler.onScroll(delta) || TrainHUD.onScroll(delta); + || CreateClient.SCHEMATIC_AND_QUILL_HANDLER.mouseScrolled(delta) || TrainHUD.onScroll(delta) + || ElevatorControlsHandler.onScroll(delta); event.setCanceled(cancelled); } diff --git a/src/main/java/com/simibubi/create/foundation/fluid/FluidHelper.java b/src/main/java/com/simibubi/create/foundation/fluid/FluidHelper.java index 1e1d9ddcf..850a87893 100644 --- a/src/main/java/com/simibubi/create/foundation/fluid/FluidHelper.java +++ b/src/main/java/com/simibubi/create/foundation/fluid/FluidHelper.java @@ -7,10 +7,10 @@ import com.google.gson.JsonObject; import com.google.gson.JsonSyntaxException; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.simibubi.create.Create; -import com.simibubi.create.content.contraptions.fluids.actors.GenericItemFilling; -import com.simibubi.create.content.contraptions.fluids.tank.CreativeFluidTankTileEntity; -import com.simibubi.create.content.contraptions.processing.EmptyingByBasin; -import com.simibubi.create.foundation.tileEntity.SmartTileEntity; +import com.simibubi.create.content.fluids.tank.CreativeFluidTankBlockEntity; +import com.simibubi.create.content.fluids.transfer.GenericItemEmptying; +import com.simibubi.create.content.fluids.transfer.GenericItemFilling; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.utility.Pair; import com.simibubi.create.foundation.utility.RegisteredObjects; @@ -157,13 +157,13 @@ public class FluidHelper { return stack; } - public static boolean tryEmptyItemIntoTE(Level worldIn, Player player, InteractionHand handIn, ItemStack heldItem, - SmartTileEntity te) { - if (!EmptyingByBasin.canItemBeEmptied(worldIn, heldItem)) + public static boolean tryEmptyItemIntoBE(Level worldIn, Player player, InteractionHand handIn, ItemStack heldItem, + SmartBlockEntity be) { + if (!GenericItemEmptying.canItemBeEmptied(worldIn, heldItem)) return false; - Pair emptyingResult = EmptyingByBasin.emptyItem(worldIn, heldItem, true); - LazyOptional capability = te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY); + Pair emptyingResult = GenericItemEmptying.emptyItem(worldIn, heldItem, true); + LazyOptional capability = be.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY); IFluidHandler tank = capability.orElse(null); FluidStack fluidStack = emptyingResult.getFirst(); @@ -173,10 +173,10 @@ public class FluidHelper { return true; ItemStack copyOfHeld = heldItem.copy(); - emptyingResult = EmptyingByBasin.emptyItem(worldIn, copyOfHeld, false); + emptyingResult = GenericItemEmptying.emptyItem(worldIn, copyOfHeld, false); tank.fill(fluidStack, FluidAction.EXECUTE); - if (!player.isCreative() && !(te instanceof CreativeFluidTankTileEntity)) { + if (!player.isCreative() && !(be instanceof CreativeFluidTankBlockEntity)) { if (copyOfHeld.isEmpty()) player.setItemInHand(handIn, emptyingResult.getSecond()); else { @@ -188,12 +188,12 @@ public class FluidHelper { return true; } - public static boolean tryFillItemFromTE(Level world, Player player, InteractionHand handIn, ItemStack heldItem, - SmartTileEntity te) { + public static boolean tryFillItemFromBE(Level world, Player player, InteractionHand handIn, ItemStack heldItem, + SmartBlockEntity be) { if (!GenericItemFilling.canItemBeFilled(world, heldItem)) return false; - LazyOptional capability = te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY); + LazyOptional capability = be.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY); IFluidHandler tank = capability.orElse(null); if (tank == null) @@ -212,7 +212,7 @@ public class FluidHelper { if (world.isClientSide) return true; - if (player.isCreative() || te instanceof CreativeFluidTankTileEntity) + if (player.isCreative() || be instanceof CreativeFluidTankBlockEntity) heldItem = heldItem.copy(); ItemStack out = GenericItemFilling.fillItem(world, requiredAmountForItem, heldItem, fluid.copy()); @@ -223,7 +223,7 @@ public class FluidHelper { if (!player.isCreative()) player.getInventory() .placeItemBackInInventory(out); - te.notifyUpdate(); + be.notifyUpdate(); return true; } diff --git a/src/main/java/com/simibubi/create/foundation/gui/AllGuiTextures.java b/src/main/java/com/simibubi/create/foundation/gui/AllGuiTextures.java index 53f9571e8..2333dd062 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/AllGuiTextures.java +++ b/src/main/java/com/simibubi/create/foundation/gui/AllGuiTextures.java @@ -40,20 +40,16 @@ public enum AllGuiTextures implements ScreenElement { SCHEMATICANNON_FUEL("schematics_2", 28, 222, 47, 16), SCHEMATICANNON_FUEL_CREATIVE("schematics_2", 28, 239, 47, 16), - STOCKSWITCH("logistics", 182, 93), + STOCKSWITCH("logistics", 182, 95), STOCKSWITCH_ARROW_UP("logistics", 191, 0, 7, 24), STOCKSWITCH_ARROW_DOWN("logistics", 198, 0, 7, 24), STOCKSWITCH_CURSOR("logistics", 206, 0, 7, 16), - STOCKSWITCH_INTERVAL("logistics", 0, 93, 100, 18), - STOCKSWITCH_UNPOWERED_LANE("logistics", 36, 18, 102, 18), - STOCKSWITCH_POWERED_LANE("logistics", 36, 40, 102, 18), + STOCKSWITCH_INTERVAL("logistics", 0, 95, 100, 18), + STOCKSWITCH_UNPOWERED_LANE("logistics", 37, 20, 100, 18), + STOCKSWITCH_POWERED_LANE("logistics", 37, 42, 100, 18), - ADJUSTABLE_CRATE("logistics_2", 124, 127), - ADJUSTABLE_DOUBLE_CRATE("logistics_2", 0, 127, 196, 127), - ADJUSTABLE_CRATE_LOCKED_SLOT("logistics_2", 125, 109, 18, 18), - - FILTER("filters", 214, 97), - ATTRIBUTE_FILTER("filters", 0, 97, 241, 83), + FILTER("filters", 214, 99), + ATTRIBUTE_FILTER("filters", 0, 99, 241, 85), TOOLBOX("toolbox", 188, 171), TOOLBELT_SLOT("minecraft", "widgets", 24, 23, 22, 22), @@ -67,21 +63,17 @@ public enum AllGuiTextures implements ScreenElement { TOOLBELT_SELECTED_OFF("widgets", 0, 155, 22, 22), TOOLBELT_SELECTED_ON("widgets", 22, 155, 22, 22), - SEQUENCER("sequencer", 173, 159), - SEQUENCER_INSTRUCTION("sequencer", 0, 14, 162, 22), - SEQUENCER_DELAY("sequencer", 0, 58, 162, 22), - SEQUENCER_END("sequencer", 0, 80, 162, 22), - SEQUENCER_EMPTY("sequencer", 0, 102, 162, 22), - SEQUENCER_AWAIT("sequencer", 0, 160, 162, 22), + SEQUENCER("sequencer", 173, 161), + SEQUENCER_INSTRUCTION("sequencer", 0, 16, 162, 22), + SEQUENCER_DELAY("sequencer", 0, 60, 162, 22), + SEQUENCER_END("sequencer", 0, 82, 162, 22), + SEQUENCER_EMPTY("sequencer", 0, 104, 162, 22), + SEQUENCER_AWAIT("sequencer", 0, 162, 162, 22), LINKED_CONTROLLER("curiosities_2", 179, 109), BLUEPRINT("curiosities_2", 0, 109, 179, 109), - - PROJECTOR("projector", 235, 185), - PROJECTOR_FILTER_STRENGTH("projector", 0, 14, 162, 22), - PROJECTOR_FILTER("projector", 0, 36, 162, 22), - PROJECTOR_END("projector", 0, 58, 162, 22), - PROJECTOR_EMPTY("projector", 0, 80, 162, 22), + + CLIPBOARD("clipboard", 0, 0, 256, 256), DATA_GATHERER("display_link", 235, 162), DATA_AREA_START("display_link", 0, 163, 2, 18), @@ -131,7 +123,29 @@ public enum AllGuiTextures implements ScreenElement { I_NEW_TRAIN("schedule_2", 14, 239, 24, 16), I_DISASSEMBLE_TRAIN("schedule_2", 39, 239, 24, 16), I_ASSEMBLE_TRAIN("schedule_2", 64, 239, 24, 16), + + ELEVATOR_CONTACT("display_link", 20, 172, 233, 82), + BRASS_FRAME_TL("value_settings", 65, 9, 4, 4), + BRASS_FRAME_TR("value_settings", 70, 9, 4, 4), + BRASS_FRAME_BL("value_settings", 65, 19, 4, 4), + BRASS_FRAME_BR("value_settings", 70, 19, 4, 4), + BRASS_FRAME_LEFT("value_settings", 65, 14, 3, 4), + BRASS_FRAME_RIGHT("value_settings", 71, 14, 3, 4), + BRASS_FRAME_TOP("value_settings", 0, 24, 256, 3), + BRASS_FRAME_BOTTOM("value_settings", 0, 27, 256, 3), + + VALUE_SETTINGS_MILESTONE("value_settings", 0, 0, 7, 8), + VALUE_SETTINGS_WIDE_MILESTONE("value_settings", 75, 14, 13, 8), + VALUE_SETTINGS_BAR("value_settings", 7, 0, 249, 8), + VALUE_SETTINGS_BAR_BG("value_settings", 75, 9, 1, 1), + VALUE_SETTINGS_OUTER_BG("value_settings", 80, 9, 1, 1), + VALUE_SETTINGS_CURSOR_LEFT("value_settings", 0, 9, 3, 14), + VALUE_SETTINGS_CURSOR("value_settings", 4, 9, 56, 14), + VALUE_SETTINGS_CURSOR_RIGHT("value_settings", 61, 9, 3, 14), + VALUE_SETTINGS_CURSOR_ICON("value_settings", 0, 44, 22, 20), + VALUE_SETTINGS_LABEL_BG("value_settings", 0, 31, 81, 11), + // JEI JEI_SLOT("jei/widgets", 18, 18), JEI_CHANCE_SLOT("jei/widgets", 20, 156, 18, 18), @@ -163,7 +177,7 @@ public enum AllGuiTextures implements ScreenElement { SPEECH_TOOLTIP_BACKGROUND("widgets", 0, 24, 8, 8), SPEECH_TOOLTIP_COLOR("widgets", 8, 24, 8, 8), - + TRAIN_HUD_SPEED_BG("widgets", 0, 190, 182, 5), TRAIN_HUD_SPEED("widgets", 0, 185, 182, 5), TRAIN_HUD_THROTTLE("widgets", 0, 195, 182, 5), @@ -175,7 +189,10 @@ public enum AllGuiTextures implements ScreenElement { TRAIN_PROMPT("widgets", 0, 230, 256, 16), // PlacementIndicator - PLACEMENT_INDICATOR_SHEET("placement_indicator", 0, 0, 16, 256); + PLACEMENT_INDICATOR_SHEET("placement_indicator", 0, 0, 16, 256), + + // ComputerCraft + COMPUTER("computer", 200, 102); ; diff --git a/src/main/java/com/simibubi/create/foundation/gui/AllIcons.java b/src/main/java/com/simibubi/create/foundation/gui/AllIcons.java index cef90136e..c0b7dae9a 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/AllIcons.java +++ b/src/main/java/com/simibubi/create/foundation/gui/AllIcons.java @@ -83,7 +83,7 @@ public class AllIcons implements ScreenElement { public static final AllIcons I_TOOL_DEPLOY = newRow(), I_SKIP_MISSING = next(), - I_SKIP_TILES = next(), + I_SKIP_BLOCK_ENTITIES = next(), I_DICE = next(), I_TUNNEL_SPLIT = next(), I_TUNNEL_FORCED_SPLIT = next(), @@ -105,6 +105,10 @@ public class AllIcons implements ScreenElement { I_ADD_INVERTED_ATTRIBUTE = next(), I_FLIP = next(), + + I_ROLLER_PAVE = next(), + I_ROLLER_FILL = next(), + I_ROLLER_WIDE_FILL = next(), I_PLAY = newRow(), I_PAUSE = next(), @@ -124,9 +128,14 @@ public class AllIcons implements ScreenElement { I_PATTERN_CHANCE_75 = next(), I_FOLLOW_DIAGONAL = next(), I_FOLLOW_MATERIAL = next(), + + I_CLEAR_CHECKED = next(), I_SCHEMATIC = newRow(), I_SEQ_REPEAT = next(), + VALUE_BOX_HOVER_6PX = next(), + VALUE_BOX_HOVER_4PX = next(), + VALUE_BOX_HOVER_8PX = next(), I_MTD_LEFT = newRow(), I_MTD_CLOSE = next(), @@ -188,7 +197,7 @@ public class AllIcons implements ScreenElement { @OnlyIn(Dist.CLIENT) public void render(PoseStack ms, MultiBufferSource buffer, int color) { - VertexConsumer builder = buffer.getBuffer(RenderType.textSeeThrough(ICON_ATLAS)); + VertexConsumer builder = buffer.getBuffer(RenderType.text(ICON_ATLAS)); Matrix4f matrix = ms.last().pose(); Color rgb = new Color(color); int light = LightTexture.FULL_BRIGHT; diff --git a/src/main/java/com/simibubi/create/foundation/gui/UIRenderHelper.java b/src/main/java/com/simibubi/create/foundation/gui/UIRenderHelper.java index 8d8e67fcd..18d5fa813 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/UIRenderHelper.java +++ b/src/main/java/com/simibubi/create/foundation/gui/UIRenderHelper.java @@ -252,6 +252,13 @@ public class UIRenderHelper { tex.startY / 256f, (tex.startY + tex.height) / 256f); } + public static void drawCropped(PoseStack ms, int left, int top, int w, int h, int z, AllGuiTextures tex) { + tex.bind(); + drawTexturedQuad(ms.last() + .pose(), Color.WHITE, left, left + w, top, top + h, z, tex.startX / 256f, (tex.startX + w) / 256f, + tex.startY / 256f, (tex.startY + h) / 256f); + } + private static void drawColoredTexture(PoseStack ms, Color c, int left, int right, int top, int bot, int z, int tex_width, int tex_height, float tex_left, float tex_top, int sheet_width, int sheet_height) { drawTexturedQuad(ms.last().pose(), c, left, right, top, bot, z, (tex_left + 0.0F) / (float) sheet_width, (tex_left + (float) tex_width) / (float) sheet_width, (tex_top + 0.0F) / (float) sheet_height, (tex_top + (float) tex_height) / (float) sheet_height); } diff --git a/src/main/java/com/simibubi/create/foundation/gui/container/ClearContainerPacket.java b/src/main/java/com/simibubi/create/foundation/gui/container/ClearContainerPacket.java deleted file mode 100644 index 1fb21351c..000000000 --- a/src/main/java/com/simibubi/create/foundation/gui/container/ClearContainerPacket.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.simibubi.create.foundation.gui.container; - -import java.util.function.Supplier; - -import com.simibubi.create.foundation.networking.SimplePacketBase; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.server.level.ServerPlayer; -import net.minecraftforge.network.NetworkEvent.Context; - -public class ClearContainerPacket extends SimplePacketBase { - - public ClearContainerPacket() {} - - public ClearContainerPacket(FriendlyByteBuf buffer) {} - - @Override - public void write(FriendlyByteBuf buffer) {} - - @Override - public void handle(Supplier context) { - context.get() - .enqueueWork(() -> { - ServerPlayer player = context.get() - .getSender(); - if (player == null) - return; - if (!(player.containerMenu instanceof IClearableContainer)) - return; - ((IClearableContainer) player.containerMenu).clearContents(); - }); - context.get() - .setPacketHandled(true); - } - -} diff --git a/src/main/java/com/simibubi/create/foundation/gui/container/ContainerBase.java b/src/main/java/com/simibubi/create/foundation/gui/container/ContainerBase.java deleted file mode 100644 index f3632f10e..000000000 --- a/src/main/java/com/simibubi/create/foundation/gui/container/ContainerBase.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.simibubi.create.foundation.gui.container; - -import com.simibubi.create.foundation.utility.IInteractionChecker; - -import net.minecraft.network.FriendlyByteBuf; -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 net.minecraft.world.inventory.Slot; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -public abstract class ContainerBase extends AbstractContainerMenu { - - public Player player; - public Inventory playerInventory; - public T contentHolder; - - protected ContainerBase(MenuType type, int id, Inventory inv, FriendlyByteBuf extraData) { - super(type, id); - init(inv, createOnClient(extraData)); - } - - protected ContainerBase(MenuType type, int id, Inventory inv, T contentHolder) { - super(type, id); - init(inv, contentHolder); - } - - protected void init(Inventory inv, T contentHolderIn) { - player = inv.player; - playerInventory = inv; - contentHolder = contentHolderIn; - initAndReadInventory(contentHolder); - addSlots(); - broadcastChanges(); - } - - @OnlyIn(Dist.CLIENT) - protected abstract T createOnClient(FriendlyByteBuf extraData); - - protected abstract void initAndReadInventory(T contentHolder); - - protected abstract void addSlots(); - - protected abstract void saveData(T contentHolder); - - protected void addPlayerSlots(int x, int y) { - for (int hotbarSlot = 0; hotbarSlot < 9; ++hotbarSlot) - this.addSlot(new Slot(playerInventory, hotbarSlot, x + hotbarSlot * 18, y + 58)); - for (int row = 0; row < 3; ++row) - for (int col = 0; col < 9; ++col) - this.addSlot(new Slot(playerInventory, col + row * 9 + 9, x + col * 18, y + row * 18)); - } - - @Override - public void removed(Player playerIn) { - super.removed(playerIn); - saveData(contentHolder); - } - - @Override - public boolean stillValid(Player player) { - if (contentHolder == null) - return false; - if (contentHolder instanceof IInteractionChecker) - return ((IInteractionChecker) contentHolder).canPlayerUse(player); - return true; - } - -} diff --git a/src/main/java/com/simibubi/create/foundation/gui/container/GhostItemContainer.java b/src/main/java/com/simibubi/create/foundation/gui/container/GhostItemContainer.java deleted file mode 100644 index bb42dfd2a..000000000 --- a/src/main/java/com/simibubi/create/foundation/gui/container/GhostItemContainer.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.simibubi.create.foundation.gui.container; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.entity.player.Player; -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.minecraftforge.items.ItemHandlerHelper; -import net.minecraftforge.items.ItemStackHandler; - -public abstract class GhostItemContainer extends ContainerBase implements IClearableContainer { - - public ItemStackHandler ghostInventory; - - protected GhostItemContainer(MenuType type, int id, Inventory inv, FriendlyByteBuf extraData) { - super(type, id, inv, extraData); - } - - protected GhostItemContainer(MenuType type, int id, Inventory inv, T contentHolder) { - super(type, id, inv, contentHolder); - } - - protected abstract ItemStackHandler createGhostInventory(); - - protected abstract boolean allowRepeats(); - - @Override - protected void initAndReadInventory(T contentHolder) { - ghostInventory = createGhostInventory(); - } - - @Override - public void clearContents() { - for (int i = 0; i < ghostInventory.getSlots(); i++) - ghostInventory.setStackInSlot(i, ItemStack.EMPTY); - } - - @Override - public boolean canTakeItemForPickAll(ItemStack stack, Slot slotIn) { - return slotIn.container == playerInventory; - } - - @Override - public boolean canDragTo(Slot slotIn) { - if (allowRepeats()) - return true; - return slotIn.container == playerInventory; - } - - @Override - public void clicked(int slotId, int dragType, ClickType clickTypeIn, Player player) { - if (slotId < 36) { - super.clicked(slotId, dragType, clickTypeIn, player); - return; - } - if (clickTypeIn == ClickType.THROW) - return; - - ItemStack held = getCarried(); - int slot = slotId - 36; - if (clickTypeIn == ClickType.CLONE) { - if (player.isCreative() && held.isEmpty()) { - ItemStack stackInSlot = ghostInventory.getStackInSlot(slot) - .copy(); - stackInSlot.setCount(stackInSlot.getMaxStackSize()); - setCarried(stackInSlot); - return; - } - return; - } - - ItemStack insert; - if (held.isEmpty()) { - insert = ItemStack.EMPTY; - } else { - insert = held.copy(); - insert.setCount(1); - } - ghostInventory.setStackInSlot(slot, insert); - getSlot(slotId).setChanged(); - } - - @Override - public ItemStack quickMoveStack(Player playerIn, int index) { - if (index < 36) { - ItemStack stackToInsert = playerInventory.getItem(index); - for (int i = 0; i < ghostInventory.getSlots(); i++) { - ItemStack stack = ghostInventory.getStackInSlot(i); - if (!allowRepeats() && ItemHandlerHelper.canItemStacksStack(stack, stackToInsert)) - break; - if (stack.isEmpty()) { - ItemStack copy = stackToInsert.copy(); - copy.setCount(1); - ghostInventory.insertItem(i, copy, false); - getSlot(i + 36).setChanged(); - break; - } - } - } else { - ghostInventory.extractItem(index - 36, 1, false); - getSlot(index).setChanged(); - } - return ItemStack.EMPTY; - } - -} diff --git a/src/main/java/com/simibubi/create/foundation/gui/container/GhostItemSubmitPacket.java b/src/main/java/com/simibubi/create/foundation/gui/container/GhostItemSubmitPacket.java deleted file mode 100644 index eb1813703..000000000 --- a/src/main/java/com/simibubi/create/foundation/gui/container/GhostItemSubmitPacket.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.simibubi.create.foundation.gui.container; - -import java.util.function.Supplier; - -import com.simibubi.create.foundation.networking.SimplePacketBase; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.network.NetworkEvent.Context; - -public class GhostItemSubmitPacket extends SimplePacketBase { - - private final ItemStack item; - private final int slot; - - public GhostItemSubmitPacket(ItemStack item, int slot) { - this.item = item; - this.slot = slot; - } - - public GhostItemSubmitPacket(FriendlyByteBuf buffer) { - item = buffer.readItem(); - slot = buffer.readInt(); - } - - @Override - public void write(FriendlyByteBuf buffer) { - buffer.writeItem(item); - buffer.writeInt(slot); - } - - @Override - public void handle(Supplier context) { - context.get() - .enqueueWork(() -> { - ServerPlayer player = context.get() - .getSender(); - if (player == null) - return; - - if (player.containerMenu instanceof GhostItemContainer) { - GhostItemContainer c = (GhostItemContainer) player.containerMenu; - c.ghostInventory.setStackInSlot(slot, item); - c.getSlot(36 + slot).setChanged(); - } - - }); - context.get() - .setPacketHandled(true); - } - -} diff --git a/src/main/java/com/simibubi/create/foundation/gui/container/IClearableContainer.java b/src/main/java/com/simibubi/create/foundation/gui/container/IClearableContainer.java deleted file mode 100644 index d0d0da14e..000000000 --- a/src/main/java/com/simibubi/create/foundation/gui/container/IClearableContainer.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.simibubi.create.foundation.gui.container; - -import com.simibubi.create.foundation.networking.AllPackets; - -public interface IClearableContainer { - - default void sendClearPacket() { - AllPackets.channel.sendToServer(new ClearContainerPacket()); - } - - public void clearContents(); - -} diff --git a/src/main/java/com/simibubi/create/foundation/gui/container/AbstractSimiContainerScreen.java b/src/main/java/com/simibubi/create/foundation/gui/menu/AbstractSimiContainerScreen.java similarity index 99% rename from src/main/java/com/simibubi/create/foundation/gui/container/AbstractSimiContainerScreen.java rename to src/main/java/com/simibubi/create/foundation/gui/menu/AbstractSimiContainerScreen.java index cf88a60dc..c701abc4a 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/container/AbstractSimiContainerScreen.java +++ b/src/main/java/com/simibubi/create/foundation/gui/menu/AbstractSimiContainerScreen.java @@ -1,4 +1,4 @@ -package com.simibubi.create.foundation.gui.container; +package com.simibubi.create.foundation.gui.menu; import java.util.Collection; import java.util.Collections; diff --git a/src/main/java/com/simibubi/create/foundation/gui/menu/ClearMenuPacket.java b/src/main/java/com/simibubi/create/foundation/gui/menu/ClearMenuPacket.java new file mode 100644 index 000000000..ba0a12eeb --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/gui/menu/ClearMenuPacket.java @@ -0,0 +1,31 @@ +package com.simibubi.create.foundation.gui.menu; + +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraftforge.network.NetworkEvent.Context; + +public class ClearMenuPacket extends SimplePacketBase { + + public ClearMenuPacket() {} + + public ClearMenuPacket(FriendlyByteBuf buffer) {} + + @Override + public void write(FriendlyByteBuf buffer) {} + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> { + ServerPlayer player = context.getSender(); + if (player == null) + return; + if (!(player.containerMenu instanceof IClearableMenu)) + return; + ((IClearableMenu) player.containerMenu).clearContents(); + }); + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/gui/menu/GhostItemMenu.java b/src/main/java/com/simibubi/create/foundation/gui/menu/GhostItemMenu.java new file mode 100644 index 000000000..b7d619cb8 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/gui/menu/GhostItemMenu.java @@ -0,0 +1,108 @@ +package com.simibubi.create.foundation.gui.menu; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +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.minecraftforge.items.ItemHandlerHelper; +import net.minecraftforge.items.ItemStackHandler; + +public abstract class GhostItemMenu extends MenuBase implements IClearableMenu { + + public ItemStackHandler ghostInventory; + + protected GhostItemMenu(MenuType type, int id, Inventory inv, FriendlyByteBuf extraData) { + super(type, id, inv, extraData); + } + + protected GhostItemMenu(MenuType type, int id, Inventory inv, T contentHolder) { + super(type, id, inv, contentHolder); + } + + protected abstract ItemStackHandler createGhostInventory(); + + protected abstract boolean allowRepeats(); + + @Override + protected void initAndReadInventory(T contentHolder) { + ghostInventory = createGhostInventory(); + } + + @Override + public void clearContents() { + for (int i = 0; i < ghostInventory.getSlots(); i++) + ghostInventory.setStackInSlot(i, ItemStack.EMPTY); + } + + @Override + public boolean canTakeItemForPickAll(ItemStack stack, Slot slotIn) { + return slotIn.container == playerInventory; + } + + @Override + public boolean canDragTo(Slot slotIn) { + if (allowRepeats()) + return true; + return slotIn.container == playerInventory; + } + + @Override + public void clicked(int slotId, int dragType, ClickType clickTypeIn, Player player) { + if (slotId < 36) { + super.clicked(slotId, dragType, clickTypeIn, player); + return; + } + if (clickTypeIn == ClickType.THROW) + return; + + ItemStack held = getCarried(); + int slot = slotId - 36; + if (clickTypeIn == ClickType.CLONE) { + if (player.isCreative() && held.isEmpty()) { + ItemStack stackInSlot = ghostInventory.getStackInSlot(slot) + .copy(); + stackInSlot.setCount(stackInSlot.getMaxStackSize()); + setCarried(stackInSlot); + return; + } + return; + } + + ItemStack insert; + if (held.isEmpty()) { + insert = ItemStack.EMPTY; + } else { + insert = held.copy(); + insert.setCount(1); + } + ghostInventory.setStackInSlot(slot, insert); + getSlot(slotId).setChanged(); + } + + @Override + public ItemStack quickMoveStack(Player playerIn, int index) { + if (index < 36) { + ItemStack stackToInsert = playerInventory.getItem(index); + for (int i = 0; i < ghostInventory.getSlots(); i++) { + ItemStack stack = ghostInventory.getStackInSlot(i); + if (!allowRepeats() && ItemHandlerHelper.canItemStacksStack(stack, stackToInsert)) + break; + if (stack.isEmpty()) { + ItemStack copy = stackToInsert.copy(); + copy.setCount(1); + ghostInventory.insertItem(i, copy, false); + getSlot(i + 36).setChanged(); + break; + } + } + } else { + ghostInventory.extractItem(index - 36, 1, false); + getSlot(index).setChanged(); + } + return ItemStack.EMPTY; + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/gui/menu/GhostItemSubmitPacket.java b/src/main/java/com/simibubi/create/foundation/gui/menu/GhostItemSubmitPacket.java new file mode 100644 index 000000000..234b87d4b --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/gui/menu/GhostItemSubmitPacket.java @@ -0,0 +1,46 @@ +package com.simibubi.create.foundation.gui.menu; + +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.network.NetworkEvent.Context; + +public class GhostItemSubmitPacket extends SimplePacketBase { + + private final ItemStack item; + private final int slot; + + public GhostItemSubmitPacket(ItemStack item, int slot) { + this.item = item; + this.slot = slot; + } + + public GhostItemSubmitPacket(FriendlyByteBuf buffer) { + item = buffer.readItem(); + slot = buffer.readInt(); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeItem(item); + buffer.writeInt(slot); + } + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> { + ServerPlayer player = context.getSender(); + if (player == null) + return; + + if (player.containerMenu instanceof GhostItemMenu menu) { + menu.ghostInventory.setStackInSlot(slot, item); + menu.getSlot(36 + slot).setChanged(); + } + }); + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/gui/menu/IClearableMenu.java b/src/main/java/com/simibubi/create/foundation/gui/menu/IClearableMenu.java new file mode 100644 index 000000000..b9d8431be --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/gui/menu/IClearableMenu.java @@ -0,0 +1,13 @@ +package com.simibubi.create.foundation.gui.menu; + +import com.simibubi.create.AllPackets; + +public interface IClearableMenu { + + default void sendClearPacket() { + AllPackets.getChannel().sendToServer(new ClearMenuPacket()); + } + + public void clearContents(); + +} diff --git a/src/main/java/com/simibubi/create/foundation/gui/menu/MenuBase.java b/src/main/java/com/simibubi/create/foundation/gui/menu/MenuBase.java new file mode 100644 index 000000000..9781f17d7 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/gui/menu/MenuBase.java @@ -0,0 +1,71 @@ +package com.simibubi.create.foundation.gui.menu; + +import com.simibubi.create.foundation.utility.IInteractionChecker; + +import net.minecraft.network.FriendlyByteBuf; +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 net.minecraft.world.inventory.Slot; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public abstract class MenuBase extends AbstractContainerMenu { + + public Player player; + public Inventory playerInventory; + public T contentHolder; + + protected MenuBase(MenuType type, int id, Inventory inv, FriendlyByteBuf extraData) { + super(type, id); + init(inv, createOnClient(extraData)); + } + + protected MenuBase(MenuType type, int id, Inventory inv, T contentHolder) { + super(type, id); + init(inv, contentHolder); + } + + protected void init(Inventory inv, T contentHolderIn) { + player = inv.player; + playerInventory = inv; + contentHolder = contentHolderIn; + initAndReadInventory(contentHolder); + addSlots(); + broadcastChanges(); + } + + @OnlyIn(Dist.CLIENT) + protected abstract T createOnClient(FriendlyByteBuf extraData); + + protected abstract void initAndReadInventory(T contentHolder); + + protected abstract void addSlots(); + + protected abstract void saveData(T contentHolder); + + protected void addPlayerSlots(int x, int y) { + for (int hotbarSlot = 0; hotbarSlot < 9; ++hotbarSlot) + this.addSlot(new Slot(playerInventory, hotbarSlot, x + hotbarSlot * 18, y + 58)); + for (int row = 0; row < 3; ++row) + for (int col = 0; col < 9; ++col) + this.addSlot(new Slot(playerInventory, col + row * 9 + 9, x + col * 18, y + row * 18)); + } + + @Override + public void removed(Player playerIn) { + super.removed(playerIn); + saveData(contentHolder); + } + + @Override + public boolean stillValid(Player player) { + if (contentHolder == null) + return false; + if (contentHolder instanceof IInteractionChecker) + return ((IInteractionChecker) contentHolder).canPlayerUse(player); + return true; + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/gui/widget/AbstractSimiWidget.java b/src/main/java/com/simibubi/create/foundation/gui/widget/AbstractSimiWidget.java index 46a873fa6..0c20fcee6 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/widget/AbstractSimiWidget.java +++ b/src/main/java/com/simibubi/create/foundation/gui/widget/AbstractSimiWidget.java @@ -17,6 +17,7 @@ import net.minecraft.network.chat.Component; public abstract class AbstractSimiWidget extends AbstractWidget implements TickableGuiEventListener { public static final int HEADER_RGB = 0x5391E1; + public static final int HINT_RGB = 0x96B7E0; protected float z; protected boolean wasHovered = false; diff --git a/src/main/java/com/simibubi/create/foundation/gui/widget/ScrollInput.java b/src/main/java/com/simibubi/create/foundation/gui/widget/ScrollInput.java index 02589aa85..ab9641132 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/widget/ScrollInput.java +++ b/src/main/java/com/simibubi/create/foundation/gui/widget/ScrollInput.java @@ -5,7 +5,7 @@ import java.util.function.Function; import com.simibubi.create.AllKeys; import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueBehaviour.StepContext; +import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollValueBehaviour.StepContext; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Lang; @@ -22,8 +22,10 @@ public class ScrollInput extends AbstractSimiWidget { protected Component title = Lang.translateDirect("gui.scrollInput.defaultTitle"); protected final Component scrollToModify = Lang.translateDirect("gui.scrollInput.scrollToModify"); protected final Component shiftScrollsFaster = Lang.translateDirect("gui.scrollInput.shiftScrollsFaster"); + protected Component hint = null; protected Label displayLabel; protected boolean inverted; + protected boolean soundPlayed; protected Function formatter; protected int min, max; @@ -38,6 +40,7 @@ public class ScrollInput extends AbstractSimiWidget { shiftStep = 5; step = standardStep(); formatter = i -> Components.literal(String.valueOf(i)); + soundPlayed = false; } public Function standardStep() { @@ -76,6 +79,12 @@ public class ScrollInput extends AbstractSimiWidget { return this; } + public ScrollInput addHint(MutableComponent hint) { + this.hint = hint; + updateTooltip(); + return this; + } + public ScrollInput withStepFunction(Function step) { this.step = step; return this; @@ -87,6 +96,12 @@ public class ScrollInput extends AbstractSimiWidget { writeToLabel(); return this; } + + @Override + public void tick() { + super.tick(); + soundPlayed = false; + } public int getState() { return state; @@ -128,7 +143,12 @@ public class ScrollInput extends AbstractSimiWidget { clampState(); if (priorState != state) { - Minecraft.getInstance().getSoundManager().play(SimpleSoundInstance.forUI(AllSoundEvents.SCROLL_VALUE.getMainEvent(), 1.5f + 0.1f * (state-min)/(max-min))); + if (!soundPlayed) + Minecraft.getInstance() + .getSoundManager() + .play(SimpleSoundInstance.forUI(AllSoundEvents.SCROLL_VALUE.getMainEvent(), + 1.5f + 0.1f * (state - min) / (max - min))); + soundPlayed = true; onChanged(); } @@ -160,6 +180,9 @@ public class ScrollInput extends AbstractSimiWidget { return; toolTip.add(title.plainCopy() .withStyle(s -> s.withColor(HEADER_RGB))); + if (hint != null) + toolTip.add(hint.plainCopy() + .withStyle(s -> s.withColor(HINT_RGB))); toolTip.add(scrollToModify.plainCopy() .withStyle(ChatFormatting.ITALIC, ChatFormatting.DARK_GRAY)); toolTip.add(shiftScrollsFaster.plainCopy() diff --git a/src/main/java/com/simibubi/create/foundation/gui/widget/SelectionScrollInput.java b/src/main/java/com/simibubi/create/foundation/gui/widget/SelectionScrollInput.java index 097f21b32..158175120 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/widget/SelectionScrollInput.java +++ b/src/main/java/com/simibubi/create/foundation/gui/widget/SelectionScrollInput.java @@ -43,7 +43,8 @@ public class SelectionScrollInput extends ScrollInput { if (this.min + 1 == min) min--; if (min > this.min) - toolTip.add(Components.literal("> ...").withStyle(ChatFormatting.GRAY)); + toolTip.add(Components.literal("> ...") + .withStyle(ChatFormatting.GRAY)); if (this.max - 1 == max) max++; for (int i = min; i < max; i++) { @@ -59,8 +60,12 @@ public class SelectionScrollInput extends ScrollInput { .withStyle(ChatFormatting.GRAY)); } if (max < this.max) - toolTip.add(Components.literal("> ...").withStyle(ChatFormatting.GRAY)); + toolTip.add(Components.literal("> ...") + .withStyle(ChatFormatting.GRAY)); + if (hint != null) + toolTip.add(hint.plainCopy() + .withStyle(s -> s.withColor(HINT_RGB))); toolTip.add(scrollToSelect.plainCopy() .withStyle(ChatFormatting.DARK_GRAY, ChatFormatting.ITALIC)); } diff --git a/src/main/java/com/simibubi/create/content/curiosities/CombustibleItem.java b/src/main/java/com/simibubi/create/foundation/item/CombustibleItem.java similarity index 90% rename from src/main/java/com/simibubi/create/content/curiosities/CombustibleItem.java rename to src/main/java/com/simibubi/create/foundation/item/CombustibleItem.java index 0ec268443..95330e609 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/CombustibleItem.java +++ b/src/main/java/com/simibubi/create/foundation/item/CombustibleItem.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.curiosities; +package com.simibubi.create.foundation.item; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; diff --git a/src/main/java/com/simibubi/create/foundation/item/CountedItemStackList.java b/src/main/java/com/simibubi/create/foundation/item/CountedItemStackList.java index 2b964a7c6..224f6a0fc 100644 --- a/src/main/java/com/simibubi/create/foundation/item/CountedItemStackList.java +++ b/src/main/java/com/simibubi/create/foundation/item/CountedItemStackList.java @@ -7,7 +7,7 @@ import java.util.Map; import java.util.Set; import java.util.stream.Stream; -import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; +import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringBehaviour; import com.simibubi.create.foundation.utility.IntAttached; import net.minecraft.network.chat.MutableComponent; diff --git a/src/main/java/com/simibubi/create/foundation/item/CustomRenderedArmorItem.java b/src/main/java/com/simibubi/create/foundation/item/CustomRenderedArmorItem.java new file mode 100644 index 000000000..3f8744044 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/item/CustomRenderedArmorItem.java @@ -0,0 +1,17 @@ +package com.simibubi.create.foundation.item; + +import com.mojang.blaze3d.vertex.PoseStack; + +import net.minecraft.client.model.HumanoidModel; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.entity.layers.HumanoidArmorLayer; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public interface CustomRenderedArmorItem { + @OnlyIn(Dist.CLIENT) + void renderArmorPiece(HumanoidArmorLayer layer, PoseStack poseStack, MultiBufferSource bufferSource, LivingEntity entity, EquipmentSlot slot, int light, HumanoidModel originalModel, ItemStack stack); +} diff --git a/src/main/java/com/simibubi/create/foundation/item/IItemHandlerModifiableIntermediate.java b/src/main/java/com/simibubi/create/foundation/item/IItemHandlerModifiableIntermediate.java deleted file mode 100644 index 8b5545a48..000000000 --- a/src/main/java/com/simibubi/create/foundation/item/IItemHandlerModifiableIntermediate.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.simibubi.create.foundation.item; - -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.items.IItemHandlerModifiable; - -interface IItemHandlerModifiableIntermediate extends IItemHandlerModifiable { - - @Override - public default ItemStack getStackInSlot(int slot) { - return getStackInSlotIntermediate(slot); - } - - public ItemStack getStackInSlotIntermediate(int slot); - -} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/foundation/item/ItemDescription.java b/src/main/java/com/simibubi/create/foundation/item/ItemDescription.java index b8b85e2f6..cb8adeed1 100644 --- a/src/main/java/com/simibubi/create/foundation/item/ItemDescription.java +++ b/src/main/java/com/simibubi/create/foundation/item/ItemDescription.java @@ -1,289 +1,254 @@ package com.simibubi.create.foundation.item; -import static com.simibubi.create.foundation.item.TooltipHelper.cutStringTextComponent; -import static com.simibubi.create.foundation.item.TooltipHelper.cutTextComponent; -import static net.minecraft.ChatFormatting.AQUA; -import static net.minecraft.ChatFormatting.BLUE; import static net.minecraft.ChatFormatting.DARK_GRAY; -import static net.minecraft.ChatFormatting.DARK_GREEN; -import static net.minecraft.ChatFormatting.DARK_PURPLE; -import static net.minecraft.ChatFormatting.DARK_RED; -import static net.minecraft.ChatFormatting.GOLD; import static net.minecraft.ChatFormatting.GRAY; -import static net.minecraft.ChatFormatting.GREEN; -import static net.minecraft.ChatFormatting.LIGHT_PURPLE; -import static net.minecraft.ChatFormatting.RED; -import static net.minecraft.ChatFormatting.STRIKETHROUGH; import static net.minecraft.ChatFormatting.WHITE; -import static net.minecraft.ChatFormatting.YELLOW; import java.util.ArrayList; import java.util.Arrays; +import java.util.IdentityHashMap; import java.util.List; +import java.util.Map; +import java.util.function.Supplier; -import com.simibubi.create.content.contraptions.base.IRotate; -import com.simibubi.create.content.contraptions.base.IRotate.StressImpact; -import com.simibubi.create.content.contraptions.goggles.GogglesItem; -import com.simibubi.create.foundation.block.BlockStressValues; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.config.CKinetics; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.Nullable; + +import com.google.common.collect.ImmutableList; +import com.mojang.bridge.game.Language; +import com.simibubi.create.foundation.item.TooltipHelper.Palette; import com.simibubi.create.foundation.utility.Components; -import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Lang; -import com.simibubi.create.foundation.utility.LangBuilder; -import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.level.block.Block; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.ItemLike; +import net.minecraftforge.event.entity.player.ItemTooltipEvent; -public class ItemDescription { +public record ItemDescription(ImmutableList lines, ImmutableList linesOnShift, ImmutableList linesOnCtrl) { + private static final Map> CUSTOM_TOOLTIP_KEYS = new IdentityHashMap<>(); - public static final ItemDescription MISSING = new ItemDescription(null); - public static Component trim = Components.literal(" ").withStyle(WHITE, STRIKETHROUGH); + @Nullable + public static ItemDescription create(Item item, Palette palette) { + return create(getTooltipTranslationKey(item), palette); + } - public enum Palette { - - Blue(BLUE, AQUA), - Green(DARK_GREEN, GREEN), - Yellow(GOLD, YELLOW), - Red(DARK_RED, RED), - Purple(DARK_PURPLE, LIGHT_PURPLE), - Gray(DARK_GRAY, GRAY), - - ; - - private Palette(ChatFormatting primary, ChatFormatting highlight) { - color = primary; - hColor = highlight; + @Nullable + public static ItemDescription create(String translationKey, Palette palette) { + if (!canFillBuilder(translationKey)) { + return null; } - public ChatFormatting color; - public ChatFormatting hColor; + Builder builder = new Builder(palette); + fillBuilder(builder, translationKey); + return builder.build(); } - private List lines; - private List linesOnShift; - private List linesOnCtrl; - private Palette palette; - - public ItemDescription(Palette palette) { - this.palette = palette; - lines = new ArrayList<>(); - linesOnShift = new ArrayList<>(); - linesOnCtrl = new ArrayList<>(); + public static boolean canFillBuilder(String translationKey) { + return I18n.exists(translationKey); } - public ItemDescription withSummary(Component summary) { - addStrings(linesOnShift, cutTextComponent(summary, palette.color, palette.hColor)); - return this; - } - - public static List getKineticStats(Block block) { - List list = new ArrayList<>(); - - CKinetics config = AllConfigs.SERVER.kinetics; - LangBuilder rpmUnit = Lang.translate("generic.unit.rpm"); - LangBuilder suUnit = Lang.translate("generic.unit.stress"); - - boolean hasGoggles = GogglesItem.isWearingGoggles(Minecraft.getInstance().player); - - boolean showStressImpact; - if (!(block instanceof IRotate)) { - showStressImpact = true; - } else { - showStressImpact = !((IRotate) block).hideStressImpact(); + public static void fillBuilder(Builder builder, String translationKey) { + // Summary + String summaryKey = translationKey + ".summary"; + if (I18n.exists(summaryKey)) { + builder.addSummary(I18n.get(summaryKey)); } - boolean hasStressImpact = - StressImpact.isEnabled() && showStressImpact && BlockStressValues.getImpact(block) > 0; - boolean hasStressCapacity = StressImpact.isEnabled() && BlockStressValues.hasCapacity(block); - - if (hasStressImpact) { - Lang.translate("tooltip.stressImpact") - .style(GRAY) - .addTo(list); - - double impact = BlockStressValues.getImpact(block); - StressImpact impactId = impact >= config.highStressImpact.get() ? StressImpact.HIGH - : (impact >= config.mediumStressImpact.get() ? StressImpact.MEDIUM : StressImpact.LOW); - LangBuilder builder = Lang.builder() - .add(Lang.text(makeProgressBar(3, impactId.ordinal() + 1)) - .style(impactId.getAbsoluteColor())); - - if (hasGoggles) { - builder.add(Lang.number(impact)) - .text("x ") - .add(rpmUnit) - .addTo(list); - } else - builder.translate("tooltip.stressImpact." + Lang.asId(impactId.name())) - .addTo(list); + // Behaviours + for (int i = 1; i < 100; i++) { + String conditionKey = translationKey + ".condition" + i; + String behaviourKey = translationKey + ".behaviour" + i; + if (!I18n.exists(conditionKey)) + break; + builder.addBehaviour(I18n.get(conditionKey), I18n.get(behaviourKey)); } - if (hasStressCapacity) { - Lang.translate("tooltip.capacityProvided") - .style(GRAY) - .addTo(list); - - double capacity = BlockStressValues.getCapacity(block); - BlockStressValues.IStressValueProvider stressProvider = BlockStressValues.getProvider(block); - Couple generatedRPM = stressProvider != null ? - stressProvider.getGeneratedRPM(block) - : null; - - StressImpact impactId = capacity >= config.highCapacity.get() ? StressImpact.HIGH - : (capacity >= config.mediumCapacity.get() ? StressImpact.MEDIUM : StressImpact.LOW); - StressImpact opposite = StressImpact.values()[StressImpact.values().length - 2 - impactId.ordinal()]; - LangBuilder builder = Lang.builder() - .add(Lang.text(makeProgressBar(3, impactId.ordinal() + 1)) - .style(opposite.getAbsoluteColor())); - - if (hasGoggles) { - builder.add(Lang.number(capacity)) - .text("x ") - .add(rpmUnit) - .addTo(list); - - if (generatedRPM != null) { - LangBuilder amount = Lang.number(capacity * generatedRPM.getSecond()) - .add(suUnit); - Lang.text(" -> ") - .add(!generatedRPM.getFirst() - .equals(generatedRPM.getSecond()) ? Lang.translate("tooltip.up_to", amount) : amount) - .style(DARK_GRAY) - .addTo(list); - } - } else - builder.translate("tooltip.capacityProvided." + Lang.asId(impactId.name())) - .addTo(list); + // Actions + for (int i = 1; i < 100; i++) { + String controlKey = translationKey + ".control" + i; + String actionKey = translationKey + ".action" + i; + if (!I18n.exists(controlKey)) + break; + builder.addAction(I18n.get(controlKey), I18n.get(actionKey)); } - - return list; } - public static String makeProgressBar(int length, int filledLength) { - String bar = " "; - int emptySpaces = length - filledLength; - for (int i = 0; i < filledLength; i++) - bar += "\u2588"; - for (int i = 0; i < emptySpaces; i++) - bar += "\u2592"; - return bar + " "; + public static void useKey(Item item, Supplier supplier) { + CUSTOM_TOOLTIP_KEYS.put(item, supplier); } - public ItemDescription withBehaviour(String condition, String behaviour) { - add(linesOnShift, Components.literal(condition).withStyle(GRAY)); - addStrings(linesOnShift, cutStringTextComponent(behaviour, palette.color, palette.hColor, 1)); - return this; + public static void useKey(ItemLike item, String string) { + useKey(item.asItem(), () -> string); } - public ItemDescription withControl(String condition, String action) { - add(linesOnCtrl, Components.literal(condition).withStyle(GRAY)); - addStrings(linesOnCtrl, cutStringTextComponent(action, palette.color, palette.hColor, 1)); - return this; + public static void referKey(ItemLike item, Supplier otherItem) { + useKey(item.asItem(), () -> otherItem.get() + .asItem() + .getDescriptionId()); } - public ItemDescription createTabs() { - boolean hasDescription = !linesOnShift.isEmpty(); - boolean hasControls = !linesOnCtrl.isEmpty(); - - if (hasDescription || hasControls) { - String[] holdDesc = Lang.translateDirect("tooltip.holdForDescription", "$") - .getString() - .split("\\$"); - String[] holdCtrl = Lang.translateDirect("tooltip.holdForControls", "$") - .getString() - .split("\\$"); - MutableComponent keyShift = Lang.translateDirect("tooltip.keyShift"); - MutableComponent keyCtrl = Lang.translateDirect("tooltip.keyCtrl"); - for (List list : Arrays.asList(lines, linesOnShift, linesOnCtrl)) { - boolean shift = list == linesOnShift; - boolean ctrl = list == linesOnCtrl; - - if (holdDesc.length != 2 || holdCtrl.length != 2) { - list.add(0, Components.literal("Invalid lang formatting!")); - continue; - } - - if (hasControls) { - MutableComponent tabBuilder = Components.empty(); - tabBuilder.append(Components.literal(holdCtrl[0]).withStyle(DARK_GRAY)); - tabBuilder.append(keyCtrl.plainCopy() - .withStyle(ctrl ? WHITE : GRAY)); - tabBuilder.append(Components.literal(holdCtrl[1]).withStyle(DARK_GRAY)); - list.add(0, tabBuilder); - } - - if (hasDescription) { - MutableComponent tabBuilder = Components.empty(); - tabBuilder.append(Components.literal(holdDesc[0]).withStyle(DARK_GRAY)); - tabBuilder.append(keyShift.plainCopy() - .withStyle(shift ? WHITE : GRAY)); - tabBuilder.append(Components.literal(holdDesc[1]).withStyle(DARK_GRAY)); - list.add(0, tabBuilder); - } - - if (shift || ctrl) - list.add(hasDescription && hasControls ? 2 : 1, Components.immutableEmpty()); - } + public static String getTooltipTranslationKey(Item item) { + if (CUSTOM_TOOLTIP_KEYS.containsKey(item)) { + return CUSTOM_TOOLTIP_KEYS.get(item).get() + ".tooltip"; } - - if (!hasDescription) - linesOnShift = lines; - if (!hasControls) - linesOnCtrl = lines; - - return this; + return item.getDescriptionId() + ".tooltip"; } - public static String hightlight(String s, Palette palette) { - return palette.hColor + s + palette.color; - } - - public static void addStrings(List infoList, List textLines) { - textLines.forEach(s -> add(infoList, s)); - } - - public static void add(List infoList, List textLines) { - infoList.addAll(textLines); - } - - public static void add(List infoList, Component line) { - infoList.add(line); - } - - public Palette getPalette() { - return palette; - } - - public List addInformation(List tooltip) { + public ImmutableList getCurrentLines() { if (Screen.hasShiftDown()) { - tooltip.addAll(linesOnShift); - return tooltip; + return linesOnShift; + } else if (Screen.hasControlDown()) { + return linesOnCtrl; + } else { + return lines; + } + } + + public static class Builder { + protected final Palette palette; + protected final List summary = new ArrayList<>(); + protected final List> behaviours = new ArrayList<>(); + protected final List> actions = new ArrayList<>(); + + public Builder(Palette palette) { + this.palette = palette; } - if (Screen.hasControlDown()) { - tooltip.addAll(linesOnCtrl); - return tooltip; + public Builder addSummary(String summaryLine) { + summary.add(summaryLine); + return this; } - tooltip.addAll(lines); - return tooltip; + public Builder addBehaviour(String condition, String behaviour) { + behaviours.add(Pair.of(condition, behaviour)); + return this; + } + + public Builder addAction(String condition, String action) { + actions.add(Pair.of(condition, action)); + return this; + } + + public ItemDescription build() { + List lines = new ArrayList<>(); + List linesOnShift = new ArrayList<>(); + List linesOnCtrl = new ArrayList<>(); + + for (String summaryLine : summary) { + linesOnShift.addAll(TooltipHelper.cutStringTextComponent(summaryLine, palette)); + } + + if (!behaviours.isEmpty()) { + linesOnShift.add(Components.immutableEmpty()); + } + + for (Pair behaviourPair : behaviours) { + String condition = behaviourPair.getLeft(); + String behaviour = behaviourPair.getRight(); + linesOnShift.add(Components.literal(condition).withStyle(GRAY)); + linesOnShift.addAll(TooltipHelper.cutStringTextComponent(behaviour, palette.primary(), palette.highlight(), 1)); + } + + for (Pair actionPair : actions) { + String condition = actionPair.getLeft(); + String action = actionPair.getRight(); + linesOnCtrl.add(Components.literal(condition).withStyle(GRAY)); + linesOnCtrl.addAll(TooltipHelper.cutStringTextComponent(action, palette.primary(), palette.highlight(), 1)); + } + + boolean hasDescription = !linesOnShift.isEmpty(); + boolean hasControls = !linesOnCtrl.isEmpty(); + + if (hasDescription || hasControls) { + String[] holdDesc = Lang.translateDirect("tooltip.holdForDescription", "$") + .getString() + .split("\\$"); + String[] holdCtrl = Lang.translateDirect("tooltip.holdForControls", "$") + .getString() + .split("\\$"); + MutableComponent keyShift = Lang.translateDirect("tooltip.keyShift"); + MutableComponent keyCtrl = Lang.translateDirect("tooltip.keyCtrl"); + for (List list : Arrays.asList(lines, linesOnShift, linesOnCtrl)) { + boolean shift = list == linesOnShift; + boolean ctrl = list == linesOnCtrl; + + if (holdDesc.length != 2 || holdCtrl.length != 2) { + list.add(0, Components.literal("Invalid lang formatting!")); + continue; + } + + if (hasControls) { + MutableComponent tabBuilder = Components.empty(); + tabBuilder.append(Components.literal(holdCtrl[0]).withStyle(DARK_GRAY)); + tabBuilder.append(keyCtrl.plainCopy() + .withStyle(ctrl ? WHITE : GRAY)); + tabBuilder.append(Components.literal(holdCtrl[1]).withStyle(DARK_GRAY)); + list.add(0, tabBuilder); + } + + if (hasDescription) { + MutableComponent tabBuilder = Components.empty(); + tabBuilder.append(Components.literal(holdDesc[0]).withStyle(DARK_GRAY)); + tabBuilder.append(keyShift.plainCopy() + .withStyle(shift ? WHITE : GRAY)); + tabBuilder.append(Components.literal(holdDesc[1]).withStyle(DARK_GRAY)); + list.add(0, tabBuilder); + } + + if (shift || ctrl) + list.add(hasDescription && hasControls ? 2 : 1, Components.immutableEmpty()); + } + } + + if (!hasDescription) { + linesOnCtrl.clear(); + linesOnShift.addAll(lines); + } + if (!hasControls) { + linesOnCtrl.clear(); + linesOnCtrl.addAll(lines); + } + + return new ItemDescription(ImmutableList.copyOf(lines), ImmutableList.copyOf(linesOnShift), ImmutableList.copyOf(linesOnCtrl)); + } } - public List getLines() { - return lines; - } + public static class Modifier implements TooltipModifier { + protected final Item item; + protected final Palette palette; + protected Language cachedLanguage; + protected ItemDescription description; - public List getLinesOnCtrl() { - return linesOnCtrl; - } + public Modifier(Item item, Palette palette) { + this.item = item; + this.palette = palette; + } - public List getLinesOnShift() { - return linesOnShift; - } + @Override + public void modify(ItemTooltipEvent context) { + if (checkLocale()) { + description = create(item, palette); + } + if (description == null) { + return; + } + context.getToolTip().addAll(1, description.getCurrentLines()); + } + protected boolean checkLocale() { + Language currentLanguage = Minecraft.getInstance() + .getLanguageManager() + .getSelected(); + if (cachedLanguage != currentLanguage) { + cachedLanguage = currentLanguage; + return true; + } + return false; + } + } } diff --git a/src/main/java/com/simibubi/create/foundation/item/ItemHelper.java b/src/main/java/com/simibubi/create/foundation/item/ItemHelper.java index b2a454fb8..1f4e09d18 100644 --- a/src/main/java/com/simibubi/create/foundation/item/ItemHelper.java +++ b/src/main/java/com/simibubi/create/foundation/item/ItemHelper.java @@ -9,7 +9,6 @@ import javax.annotation.Nullable; import org.apache.commons.lang3.mutable.MutableInt; -import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.utility.Pair; import net.minecraft.core.BlockPos; @@ -148,8 +147,7 @@ public class ItemHelper { } public static ItemStack extract(IItemHandler inv, Predicate test, boolean simulate) { - return extract(inv, test, ExtractionCountMode.UPTO, AllConfigs.SERVER.logistics.defaultExtractionLimit.get(), - simulate); + return extract(inv, test, ExtractionCountMode.UPTO, 64, simulate); } public static ItemStack extract(IItemHandler inv, Predicate test, int exactAmount, boolean simulate) { @@ -224,7 +222,7 @@ public class ItemHelper { public static ItemStack extract(IItemHandler inv, Predicate test, Function amountFunction, boolean simulate) { ItemStack extracting = ItemStack.EMPTY; - int maxExtractionCount = AllConfigs.SERVER.logistics.defaultExtractionLimit.get(); + int maxExtractionCount = 64; for (int slot = 0; slot < inv.getSlots(); slot++) { if (extracting.isEmpty()) { diff --git a/src/main/java/com/simibubi/create/foundation/item/KineticStats.java b/src/main/java/com/simibubi/create/foundation/item/KineticStats.java new file mode 100644 index 000000000..5cf6656c4 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/item/KineticStats.java @@ -0,0 +1,142 @@ +package com.simibubi.create.foundation.item; + +import static net.minecraft.ChatFormatting.DARK_GRAY; +import static net.minecraft.ChatFormatting.GRAY; + +import java.util.ArrayList; +import java.util.List; + +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.equipment.goggles.GogglesItem; +import com.simibubi.create.content.kinetics.BlockStressValues; +import com.simibubi.create.content.kinetics.base.IRotate; +import com.simibubi.create.content.kinetics.base.IRotate.StressImpact; +import com.simibubi.create.content.kinetics.crank.ValveHandleBlock; +import com.simibubi.create.content.kinetics.steamEngine.SteamEngineBlock; +import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.Couple; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.LangBuilder; +import com.simibubi.create.infrastructure.config.AllConfigs; +import com.simibubi.create.infrastructure.config.CKinetics; + +import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.block.Block; +import net.minecraftforge.event.entity.player.ItemTooltipEvent; + +public class KineticStats implements TooltipModifier { + protected final Block block; + + public KineticStats(Block block) { + this.block = block; + } + + @Nullable + public static KineticStats create(Item item) { + if (item instanceof BlockItem blockItem) { + Block block = blockItem.getBlock(); + if (block instanceof IRotate || block instanceof SteamEngineBlock) { + return new KineticStats(block); + } + } + return null; + } + + @Override + public void modify(ItemTooltipEvent context) { + List kineticStats = getKineticStats(block, context.getEntity()); + if (!kineticStats.isEmpty()) { + List tooltip = context.getToolTip(); + tooltip.add(Components.immutableEmpty()); + tooltip.addAll(kineticStats); + } + } + + public static List getKineticStats(Block block, Player player) { + List list = new ArrayList<>(); + + CKinetics config = AllConfigs.server().kinetics; + LangBuilder rpmUnit = Lang.translate("generic.unit.rpm"); + LangBuilder suUnit = Lang.translate("generic.unit.stress"); + + boolean hasGoggles = GogglesItem.isWearingGoggles(player); + + boolean showStressImpact; + if (block instanceof IRotate) { + showStressImpact = !((IRotate) block).hideStressImpact(); + } else { + showStressImpact = true; + } + + if (block instanceof ValveHandleBlock) + block = AllBlocks.COPPER_VALVE_HANDLE.get(); + + boolean hasStressImpact = + StressImpact.isEnabled() && showStressImpact && BlockStressValues.getImpact(block) > 0; + boolean hasStressCapacity = StressImpact.isEnabled() && BlockStressValues.hasCapacity(block); + + if (hasStressImpact) { + Lang.translate("tooltip.stressImpact") + .style(GRAY) + .addTo(list); + + double impact = BlockStressValues.getImpact(block); + StressImpact impactId = impact >= config.highStressImpact.get() ? StressImpact.HIGH + : (impact >= config.mediumStressImpact.get() ? StressImpact.MEDIUM : StressImpact.LOW); + LangBuilder builder = Lang.builder() + .add(Lang.text(TooltipHelper.makeProgressBar(3, impactId.ordinal() + 1)) + .style(impactId.getAbsoluteColor())); + + if (hasGoggles) { + builder.add(Lang.number(impact)) + .text("x ") + .add(rpmUnit) + .addTo(list); + } else + builder.translate("tooltip.stressImpact." + Lang.asId(impactId.name())) + .addTo(list); + } + + if (hasStressCapacity) { + Lang.translate("tooltip.capacityProvided") + .style(GRAY) + .addTo(list); + + double capacity = BlockStressValues.getCapacity(block); + Couple generatedRPM = BlockStressValues.getGeneratedRPM(block); + + StressImpact impactId = capacity >= config.highCapacity.get() ? StressImpact.HIGH + : (capacity >= config.mediumCapacity.get() ? StressImpact.MEDIUM : StressImpact.LOW); + StressImpact opposite = StressImpact.values()[StressImpact.values().length - 2 - impactId.ordinal()]; + LangBuilder builder = Lang.builder() + .add(Lang.text(TooltipHelper.makeProgressBar(3, impactId.ordinal() + 1)) + .style(opposite.getAbsoluteColor())); + + if (hasGoggles) { + builder.add(Lang.number(capacity)) + .text("x ") + .add(rpmUnit) + .addTo(list); + + if (generatedRPM != null) { + LangBuilder amount = Lang.number(capacity * generatedRPM.getSecond()) + .add(suUnit); + Lang.text(" -> ") + .add(!generatedRPM.getFirst() + .equals(generatedRPM.getSecond()) ? Lang.translate("tooltip.up_to", amount) : amount) + .style(DARK_GRAY) + .addTo(list); + } + } else + builder.translate("tooltip.capacityProvided." + Lang.asId(impactId.name())) + .addTo(list); + } + + return list; + } +} diff --git a/src/main/java/com/simibubi/create/foundation/item/LayeredArmorItem.java b/src/main/java/com/simibubi/create/foundation/item/LayeredArmorItem.java new file mode 100644 index 000000000..487a147d1 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/item/LayeredArmorItem.java @@ -0,0 +1,53 @@ +package com.simibubi.create.foundation.item; + +import java.util.Map; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.foundation.mixin.accessor.HumanoidArmorLayerAccessor; + +import net.minecraft.client.model.HumanoidModel; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.entity.layers.HumanoidArmorLayer; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ArmorItem; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +public interface LayeredArmorItem extends CustomRenderedArmorItem { + @OnlyIn(Dist.CLIENT) + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Override + default void renderArmorPiece(HumanoidArmorLayer layer, PoseStack poseStack, + MultiBufferSource bufferSource, LivingEntity entity, EquipmentSlot slot, int light, + HumanoidModel originalModel, ItemStack stack) { + if (!(stack.getItem() instanceof ArmorItem item)) { + return; + } + if (item.getSlot() != slot) { + return; + } + + HumanoidArmorLayerAccessor accessor = (HumanoidArmorLayerAccessor) layer; + Map locationCache = HumanoidArmorLayerAccessor.create$getArmorLocationCache(); + boolean glint = stack.hasFoil(); + + HumanoidModel innerModel = accessor.create$getInnerModel(); + layer.getParentModel().copyPropertiesTo((HumanoidModel) innerModel); + accessor.create$callSetPartVisibility(innerModel, slot); + String locationStr2 = getArmorTextureLocation(entity, slot, stack, 2); + ResourceLocation location2 = locationCache.computeIfAbsent(locationStr2, ResourceLocation::new); + accessor.create$callRenderModel(poseStack, bufferSource, light, glint, innerModel, 1.0F, 1.0F, 1.0F, location2); + + HumanoidModel outerModel = accessor.create$getOuterModel(); + layer.getParentModel().copyPropertiesTo((HumanoidModel) outerModel); + accessor.create$callSetPartVisibility(outerModel, slot); + String locationStr1 = getArmorTextureLocation(entity, slot, stack, 1); + ResourceLocation location1 = locationCache.computeIfAbsent(locationStr1, ResourceLocation::new); + accessor.create$callRenderModel(poseStack, bufferSource, light, glint, outerModel, 1.0F, 1.0F, 1.0F, location1); + } + + String getArmorTextureLocation(LivingEntity entity, EquipmentSlot slot, ItemStack stack, int layer); +} diff --git a/src/main/java/com/simibubi/create/foundation/item/SmartInventory.java b/src/main/java/com/simibubi/create/foundation/item/SmartInventory.java index 1fcd6d697..d9d5a3b44 100644 --- a/src/main/java/com/simibubi/create/foundation/item/SmartInventory.java +++ b/src/main/java/com/simibubi/create/foundation/item/SmartInventory.java @@ -4,16 +4,17 @@ import java.util.function.Consumer; import javax.annotation.Nonnull; -import com.simibubi.create.foundation.tileEntity.SyncedTileEntity; +import com.simibubi.create.foundation.blockEntity.SyncedBlockEntity; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.ItemStack; import net.minecraftforge.common.util.INBTSerializable; +import net.minecraftforge.items.IItemHandlerModifiable; import net.minecraftforge.items.ItemStackHandler; import net.minecraftforge.items.wrapper.RecipeWrapper; public class SmartInventory extends RecipeWrapper - implements IItemHandlerModifiableIntermediate, INBTSerializable { + implements IItemHandlerModifiable, INBTSerializable { protected boolean extractionAllowed; protected boolean insertionAllowed; @@ -21,12 +22,12 @@ public class SmartInventory extends RecipeWrapper protected SyncedStackHandler wrapped; protected int stackSize; - public SmartInventory(int slots, SyncedTileEntity te) { - this(slots, te, 64, false); + public SmartInventory(int slots, SyncedBlockEntity be) { + this(slots, be, 64, false); } - public SmartInventory(int slots, SyncedTileEntity te, int stackSize, boolean stackNonStackables) { - super(new SyncedStackHandler(slots, te, stackNonStackables, stackSize)); + public SmartInventory(int slots, SyncedBlockEntity be, int stackSize, boolean stackNonStackables) { + super(new SyncedStackHandler(slots, be, stackNonStackables, stackSize)); this.stackNonStackables = stackNonStackables; insertionAllowed = true; extractionAllowed = true; @@ -100,13 +101,13 @@ public class SmartInventory extends RecipeWrapper } @Override - public void setStackInSlot(int slot, ItemStack stack) { - inv.setStackInSlot(slot, stack); + public ItemStack getStackInSlot(int slot) { + return inv.getStackInSlot(slot); } @Override - public ItemStack getItem(int slot) { - return super.getItem(slot); + public void setStackInSlot(int slot, ItemStack stack) { + inv.setStackInSlot(slot, stack); } public int getStackLimit(int slot, @Nonnull ItemStack stack) { @@ -129,14 +130,14 @@ public class SmartInventory extends RecipeWrapper private static class SyncedStackHandler extends ItemStackHandler { - private SyncedTileEntity te; + private SyncedBlockEntity blockEntity; private boolean stackNonStackables; private int stackSize; private Consumer updateCallback; - public SyncedStackHandler(int slots, SyncedTileEntity te, boolean stackNonStackables, int stackSize) { + public SyncedStackHandler(int slots, SyncedBlockEntity be, boolean stackNonStackables, int stackSize) { super(slots); - this.te = te; + this.blockEntity = be; this.stackNonStackables = stackNonStackables; this.stackSize = stackSize; } @@ -146,7 +147,7 @@ public class SmartInventory extends RecipeWrapper super.onContentsChanged(slot); if (updateCallback != null) updateCallback.accept(slot); - te.notifyUpdate(); + blockEntity.notifyUpdate(); } @Override @@ -160,9 +161,4 @@ public class SmartInventory extends RecipeWrapper } - @Override - public ItemStack getStackInSlotIntermediate(int slot) { - return getItem(slot); - } - } diff --git a/src/main/java/com/simibubi/create/foundation/item/TooltipHelper.java b/src/main/java/com/simibubi/create/foundation/item/TooltipHelper.java index 2daa2b82c..e8611df71 100644 --- a/src/main/java/com/simibubi/create/foundation/item/TooltipHelper.java +++ b/src/main/java/com/simibubi/create/foundation/item/TooltipHelper.java @@ -2,43 +2,27 @@ package com.simibubi.create.foundation.item; import java.text.BreakIterator; import java.util.ArrayList; -import java.util.HashMap; import java.util.LinkedList; import java.util.List; -import java.util.Map; -import java.util.function.Supplier; import com.google.common.base.Strings; -import com.mojang.bridge.game.Language; -import com.simibubi.create.content.AllSections; -import com.simibubi.create.content.contraptions.goggles.GogglesItem; -import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation; -import com.simibubi.create.foundation.item.ItemDescription.Palette; +import com.simibubi.create.content.equipment.goggles.IHaveGoggleInformation; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.FontHelper; import com.simibubi.create.foundation.utility.Lang; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; -import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.ItemLike; +import net.minecraft.network.chat.Style; public class TooltipHelper { - public static final int maxWidthPerLine = 200; - public static final Map cachedTooltips = new HashMap<>(); - public static Language cachedLanguage; - private static boolean gogglesMode; - private static final Map> tooltipReferrals = new HashMap<>(); + public static final int MAX_WIDTH_PER_LINE = 200; - public static MutableComponent holdShift(Palette color, boolean highlighted) { + public static MutableComponent holdShift(Palette palette, boolean highlighted) { return Lang.translateDirect("tooltip.holdForDescription", Lang.translateDirect("tooltip.keyShift") .withStyle(ChatFormatting.GRAY)) .withStyle(ChatFormatting.DARK_GRAY); @@ -50,87 +34,64 @@ public class TooltipHelper { .append(Lang.translateDirect(hintKey + ".title")) .withStyle(ChatFormatting.GOLD)); Component hint = Lang.translateDirect(hintKey); - List cutComponent = TooltipHelper.cutTextComponent(hint, ChatFormatting.GRAY, ChatFormatting.WHITE); + List cutComponent = cutTextComponent(hint, Palette.GRAY_AND_WHITE); for (Component component : cutComponent) tooltip.add(spacing.plainCopy() .append(component)); } - public static void referTo(ItemLike item, Supplier itemWithTooltip) { - tooltipReferrals.put(item.asItem(), () -> itemWithTooltip.get() - .asItem() - .getDescriptionId()); + public static String makeProgressBar(int length, int filledLength) { + String bar = " "; + int emptySpaces = length - filledLength; + for (int i = 0; i < filledLength; i++) + bar += "\u2588"; + for (int i = 0; i < emptySpaces; i++) + bar += "\u2592"; + return bar + " "; } - public static void referTo(ItemLike item, String string) { - tooltipReferrals.put(item.asItem(), () -> string); + public static Style styleFromColor(ChatFormatting color) { + return Style.EMPTY.applyFormat(color); + } + + public static Style styleFromColor(int hex) { + return Style.EMPTY.withColor(hex); } - @Deprecated - public static List cutString(Component s, ChatFormatting defaultColor, ChatFormatting highlightColor) { - return cutString(s.getString(), defaultColor, highlightColor, 0); + public static List cutStringTextComponent(String s, Palette palette) { + return cutTextComponent(Components.literal(s), palette); } - @Deprecated - public static List cutString(String s, ChatFormatting defaultColor, ChatFormatting highlightColor, - int indent) { - // Apply markup - String markedUp = s.replaceAll("_([^_]+)_", highlightColor + "$1" + defaultColor); - - // Split words - List words = new LinkedList<>(); - BreakIterator iterator = BreakIterator.getLineInstance(Minecraft.getInstance().getLocale()); - iterator.setText(markedUp); - int start = iterator.first(); - for (int end = iterator.next(); end != BreakIterator.DONE; start = end, end = iterator.next()) { - String word = markedUp.substring(start, end); - words.add(word); - } - - Font font = Minecraft.getInstance().font; - List lines = FontHelper.cutString(font, markedUp, maxWidthPerLine); - - // Format - String lineStart = Strings.repeat(" ", indent); - List formattedLines = new ArrayList<>(lines.size()); - String format = defaultColor.toString(); - for (String line : lines) { - String formattedLine = format + lineStart + line; - formattedLines.add(formattedLine); -// format = TextFormatting.getFormatString(formattedLine); - } - return formattedLines; + public static List cutTextComponent(Component c, Palette palette) { + return cutTextComponent(c, palette.primary(), palette.highlight()); } - public static List cutStringTextComponent(String c, ChatFormatting defaultColor, - ChatFormatting highlightColor) { - return cutTextComponent(Components.literal(c), defaultColor, highlightColor, 0); + public static List cutStringTextComponent(String s, Style primaryStyle, + Style highlightStyle) { + return cutTextComponent(Components.literal(s), primaryStyle, highlightStyle); } - public static List cutTextComponent(Component c, ChatFormatting defaultColor, - ChatFormatting highlightColor) { - return cutTextComponent(c, defaultColor, highlightColor, 0); + public static List cutTextComponent(Component c, Style primaryStyle, + Style highlightStyle) { + return cutTextComponent(c, primaryStyle, highlightStyle, 0); } - public static List cutStringTextComponent(String c, ChatFormatting defaultColor, - ChatFormatting highlightColor, int indent) { - return cutTextComponent(Components.literal(c), defaultColor, highlightColor, indent); + public static List cutStringTextComponent(String c, Style primaryStyle, + Style highlightStyle, int indent) { + return cutTextComponent(Components.literal(c), primaryStyle, highlightStyle, indent); } - public static List cutTextComponent(Component c, ChatFormatting defaultColor, - ChatFormatting highlightColor, int indent) { + public static List cutTextComponent(Component c, Style primaryStyle, + Style highlightStyle, int indent) { String s = c.getString(); - // Apply markup - String markedUp = s;// .replaceAll("_([^_]+)_", highlightColor + "$1" + defaultColor); - // Split words List words = new LinkedList<>(); BreakIterator iterator = BreakIterator.getLineInstance(Minecraft.getInstance().getLocale()); - iterator.setText(markedUp); + iterator.setText(s); int start = iterator.first(); for (int end = iterator.next(); end != BreakIterator.DONE; start = end, end = iterator.next()) { - String word = markedUp.substring(start, end); + String word = s.substring(start, end); words.add(word); } @@ -141,7 +102,7 @@ public class TooltipHelper { int width = 0; for (String word : words) { int newWidth = font.width(word.replaceAll("_", "")); - if (width + newWidth > maxWidthPerLine) { + if (width + newWidth > MAX_WIDTH_PER_LINE) { if (width > 0) { String line = currentLine.toString(); lines.add(line); @@ -161,16 +122,16 @@ public class TooltipHelper { // Format MutableComponent lineStart = Components.literal(Strings.repeat(" ", indent)); - lineStart.withStyle(defaultColor); + lineStart.withStyle(primaryStyle); List formattedLines = new ArrayList<>(lines.size()); - Couple f = Couple.create(highlightColor, defaultColor); + Couple