merge changes from 1.20.1/feature-dev

This commit is contained in:
zelophed 2023-11-17 16:37:37 +01:00
commit 0e69448d0a
205 changed files with 73724 additions and 67918 deletions

View file

@ -49,6 +49,8 @@ body:
label: Mod Version label: Mod Version
description: The version of the mod you were using when the bug occured description: The version of the mod you were using when the bug occured
options: options:
- "0.5.1f"
- "0.5.1e"
- "0.5.1d" - "0.5.1d"
- "0.5.1c" - "0.5.1c"
- "0.5.1b" - "0.5.1b"

View file

@ -258,6 +258,8 @@ dependencies {
// runtimeOnly fg.deobf("slimeknights.tconstruct:TConstruct:1.16.5-3.1.1.252") // runtimeOnly fg.deobf("slimeknights.tconstruct:TConstruct:1.16.5-3.1.1.252")
// runtimeOnly fg.deobf("maven.modrinth:rubidium:0.5.3") // 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 } // implementation fg.deobf("com.railwayteam.railways:railways-1.18.2-1.1.1:all") { transitive = false }
// runtimeOnly fg.deobf("maven.modrinth:aether:1.19.2-1.0.0-beta.1.1-forge")
// runtimeOnly fg.deobf("maven.modrinth:spark:1.10.38-forge")
// https://discord.com/channels/313125603924639766/725850371834118214/910619168821354497 // https://discord.com/channels/313125603924639766/725850371834118214/910619168821354497
// Prevent Mixin annotation processor from getting into IntelliJ's annotation processor settings // Prevent Mixin annotation processor from getting into IntelliJ's annotation processor settings

View file

@ -10,6 +10,7 @@
"translation": "src/main/resources/assets/create/lang/%locale_with_underscore%.json", "translation": "src/main/resources/assets/create/lang/%locale_with_underscore%.json",
"languages_mapping": { "languages_mapping": {
"locale_with_underscore": { "locale_with_underscore": {
"be": "be_by",
"cs": "cs_cz", "cs": "cs_cz",
"cy": "cy_gb", "cy": "cy_gb",
"da": "da_dk", "da": "da_dk",
@ -18,6 +19,7 @@
"es-CL": "es_cl", "es-CL": "es_cl",
"es-ES": "es_es", "es-ES": "es_es",
"es-MX": "es_mx", "es-MX": "es_mx",
"et": "et_ee",
"fa": "fa_ir", "fa": "fa_ir",
"fi": "fi_fi", "fi": "fi_fi",
"fr": "fr_fr", "fr": "fr_fr",
@ -41,6 +43,7 @@
"tok": "tok", "tok": "tok",
"tr": "tr_tr", "tr": "tr_tr",
"uk": "uk_ua", "uk": "uk_ua",
"vi": "vi_vn",
"zh-CN": "zh_cn", "zh-CN": "zh_cn",
"zh-TW": "zh_tw", "zh-TW": "zh_tw",
} }

View file

@ -4,7 +4,7 @@ org.gradle.jvmargs = -Xmx3G
org.gradle.daemon = false org.gradle.daemon = false
# mod version info # mod version info
mod_version = 0.5.1.e mod_version = 0.6.0
artifact_minecraft_version = 1.20.1 artifact_minecraft_version = 1.20.1
minecraft_version = 1.20.1 minecraft_version = 1.20.1
@ -23,13 +23,13 @@ use_parchment = true
# dependency versions # dependency versions
registrate_version = MC1.20-1.3.3 registrate_version = MC1.20-1.3.3
flywheel_minecraft_version = 1.20.1 flywheel_minecraft_version = 1.20.1
flywheel_version = 0.6.10-6 flywheel_version = 0.6.10-7
jei_minecraft_version = 1.20.1 jei_minecraft_version = 1.20.1
jei_version = 15.2.0.22 jei_version = 15.2.0.22
curios_minecraft_version = 1.20.1 curios_minecraft_version = 1.20.1
curios_version = 5.2.0-beta.3 curios_version = 5.3.1
catnip_version = 0.7.4 catnip_version = 0.7.5
ponder_version = 0.7.4 ponder_version = 0.7.5
cc_tweaked_enable = true cc_tweaked_enable = true
cc_tweaked_minecraft_version = 1.20.1 cc_tweaked_minecraft_version = 1.20.1

View file

@ -1,4 +1,4 @@
// 1.20.1 2023-07-04T18:31:12.3951444 Create's Sequenced Assembly Recipes // 1.20.1 2023-09-20T19:40:25.4471912 Create's Sequenced Assembly Recipes
dbaca5a5aa312f3bc7b826e51e665d32e798a5d7 data/create/recipes/sequenced_assembly/precision_mechanism.json dbaca5a5aa312f3bc7b826e51e665d32e798a5d7 data/create/recipes/sequenced_assembly/precision_mechanism.json
0cdbd4f583aa0a2aa8f3ca2827199bede1732722 data/create/recipes/sequenced_assembly/sturdy_sheet.json 0cdbd4f583aa0a2aa8f3ca2827199bede1732722 data/create/recipes/sequenced_assembly/sturdy_sheet.json
1274315b5c570722d6f5b2ed7f5e53fe01b6288a data/create/recipes/sequenced_assembly/track.json 1274315b5c570722d6f5b2ed7f5e53fe01b6288a data/create/recipes/sequenced_assembly/track.json

View file

@ -1,4 +1,4 @@
// 1.20.1 2023-08-22T15:37:03.5601186 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)] // 1.20.1 2023-11-17T16:06:13.2756739 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)]
60bbdf92d2ac9824ea6144955c74043a6005f79d assets/create/blockstates/acacia_window.json 60bbdf92d2ac9824ea6144955c74043a6005f79d assets/create/blockstates/acacia_window.json
6a67703c2697d81b7dc83e9d72a66f9c9ff08383 assets/create/blockstates/acacia_window_pane.json 6a67703c2697d81b7dc83e9d72a66f9c9ff08383 assets/create/blockstates/acacia_window_pane.json
c3ae87b62e81d8e9476eccd793bb1548d74c66a1 assets/create/blockstates/adjustable_chain_gearshift.json c3ae87b62e81d8e9476eccd793bb1548d74c66a1 assets/create/blockstates/adjustable_chain_gearshift.json
@ -585,8 +585,8 @@ b0d8f08968763a5f74e5cd5644377a76a9f39753 assets/create/blockstates/yellow_toolbo
fe8c497aacc641c2f01cec90bba9f19e59cc2ed2 assets/create/blockstates/yellow_valve_handle.json fe8c497aacc641c2f01cec90bba9f19e59cc2ed2 assets/create/blockstates/yellow_valve_handle.json
e819e93fdcbe9fd9c050a052d2718ff3b3539365 assets/create/blockstates/zinc_block.json e819e93fdcbe9fd9c050a052d2718ff3b3539365 assets/create/blockstates/zinc_block.json
64121dcb216381c83b4fe28aa361ea07c24c9ad0 assets/create/blockstates/zinc_ore.json 64121dcb216381c83b4fe28aa361ea07c24c9ad0 assets/create/blockstates/zinc_ore.json
3a1e0c68a9f1d6a252f47b3f7311278711f2aae0 assets/create/lang/en_ud.json 807ea2be63882ed9e2d14267abf902a4c9313027 assets/create/lang/en_ud.json
a0c0e4f23540bef4b1796ad9f4e4ace609d2919b assets/create/lang/en_us.json 50e19fb11134116092d9f05811ff63bc116a997c assets/create/lang/en_us.json
a97e1060e00ae701a02e39cd4ef8054cf345fac4 assets/create/models/block/acacia_window.json a97e1060e00ae701a02e39cd4ef8054cf345fac4 assets/create/models/block/acacia_window.json
103e032c0b1a0a6a27c67da8c91179a564bd281c assets/create/models/block/acacia_window_pane_noside.json 103e032c0b1a0a6a27c67da8c91179a564bd281c assets/create/models/block/acacia_window_pane_noside.json
fb00b627abda76ad4fea867ca57dbfadd24fffa3 assets/create/models/block/acacia_window_pane_noside_alt.json fb00b627abda76ad4fea867ca57dbfadd24fffa3 assets/create/models/block/acacia_window_pane_noside_alt.json
@ -4171,6 +4171,10 @@ f1a03ac86925e26cbec6aeeada2eafb40008fc8e data/create/recipes/weathered_copper_ti
35133e95f1c8fdd7a1c21afcc231fc0bffefb9a8 data/create/tags/blocks/contraption_inventory_deny.json 35133e95f1c8fdd7a1c21afcc231fc0bffefb9a8 data/create/tags/blocks/contraption_inventory_deny.json
c7ec0dbc18e9c1b58e568ed925287b89df11a136 data/create/tags/blocks/copycat_allow.json c7ec0dbc18e9c1b58e568ed925287b89df11a136 data/create/tags/blocks/copycat_allow.json
876eb9210f4a14898a2fe6d225699c66b5bdfeef data/create/tags/blocks/copycat_deny.json 876eb9210f4a14898a2fe6d225699c66b5bdfeef data/create/tags/blocks/copycat_deny.json
f675c20350ed60da4878b5d6301f02c8c05624bd data/create/tags/blocks/fan_processing_catalysts/blasting.json
0592b99f657415f6546564ed8efa1fcbef07ba15 data/create/tags/blocks/fan_processing_catalysts/haunting.json
9386dd9a1d234813f9b8ae4ec88866d396aa1d37 data/create/tags/blocks/fan_processing_catalysts/smoking.json
35133e95f1c8fdd7a1c21afcc231fc0bffefb9a8 data/create/tags/blocks/fan_processing_catalysts/splashing.json
6858173c670bb593664ac3c62ded726d57d581f1 data/create/tags/blocks/fan_transparent.json 6858173c670bb593664ac3c62ded726d57d581f1 data/create/tags/blocks/fan_transparent.json
2589b135c0e96ad29076569e144528fe32ea5b39 data/create/tags/blocks/girdable_tracks.json 2589b135c0e96ad29076569e144528fe32ea5b39 data/create/tags/blocks/girdable_tracks.json
a1e21c22f32354fd1a82a1b0a59dd786c0deaba0 data/create/tags/blocks/movable_empty_collider.json a1e21c22f32354fd1a82a1b0a59dd786c0deaba0 data/create/tags/blocks/movable_empty_collider.json
@ -4185,9 +4189,14 @@ a5874f73c7dc0a3ae12999e6ae8abf45bc7fb9be data/create/tags/blocks/passive_boiler_
da739ad2160e7df4e0e5cc89587670ce5e9450c3 data/create/tags/blocks/valve_handles.json da739ad2160e7df4e0e5cc89587670ce5e9450c3 data/create/tags/blocks/valve_handles.json
72143286fb5cb372a0696550e2eac76ca50e6fbc data/create/tags/blocks/windmill_sails.json 72143286fb5cb372a0696550e2eac76ca50e6fbc data/create/tags/blocks/windmill_sails.json
58987ea71d488cc48192ceb00c00aa2903e51304 data/create/tags/blocks/wrench_pickup.json 58987ea71d488cc48192ceb00c00aa2903e51304 data/create/tags/blocks/wrench_pickup.json
76c0522664726c09461ad4565b6fba80b4f816b2 data/create/tags/entity_types/blaze_burner_capturable.json
35133e95f1c8fdd7a1c21afcc231fc0bffefb9a8 data/create/tags/entity_types/ignore_seat.json 35133e95f1c8fdd7a1c21afcc231fc0bffefb9a8 data/create/tags/entity_types/ignore_seat.json
894e1e4fd1e32712abdda18ec64ab13750d3c039 data/create/tags/fluids/bottomless/allow.json 894e1e4fd1e32712abdda18ec64ab13750d3c039 data/create/tags/fluids/bottomless/allow.json
35133e95f1c8fdd7a1c21afcc231fc0bffefb9a8 data/create/tags/fluids/bottomless/deny.json 35133e95f1c8fdd7a1c21afcc231fc0bffefb9a8 data/create/tags/fluids/bottomless/deny.json
e191d5f912e05091b3a0b1df17f4c4181e04d96f data/create/tags/fluids/fan_processing_catalysts/blasting.json
35133e95f1c8fdd7a1c21afcc231fc0bffefb9a8 data/create/tags/fluids/fan_processing_catalysts/haunting.json
35133e95f1c8fdd7a1c21afcc231fc0bffefb9a8 data/create/tags/fluids/fan_processing_catalysts/smoking.json
c9ae54a7510073b17edf82f7591e14bdb2c51837 data/create/tags/fluids/fan_processing_catalysts/splashing.json
35133e95f1c8fdd7a1c21afcc231fc0bffefb9a8 data/create/tags/items/blaze_burner_fuel/regular.json 35133e95f1c8fdd7a1c21afcc231fc0bffefb9a8 data/create/tags/items/blaze_burner_fuel/regular.json
8ba98bf390a326abeebfd5d84be5f740c935a8b6 data/create/tags/items/blaze_burner_fuel/special.json 8ba98bf390a326abeebfd5d84be5f740c935a8b6 data/create/tags/items/blaze_burner_fuel/special.json
8b6c0b444b15f7fb2d55b9cbcb68537c1269f877 data/create/tags/items/casing.json 8b6c0b444b15f7fb2d55b9cbcb68537c1269f877 data/create/tags/items/casing.json
@ -4195,8 +4204,8 @@ f43cac8216e2a9347e48cf93a43de95dd810ca20 data/create/tags/items/contraption_cont
d371dfd35e49a7bef19f59c03e7f4ae20992f03d data/create/tags/items/create_ingots.json d371dfd35e49a7bef19f59c03e7f4ae20992f03d data/create/tags/items/create_ingots.json
910d0f5ccbc4c84b224eca1f1588b1695f41447b data/create/tags/items/crushed_raw_materials.json 910d0f5ccbc4c84b224eca1f1588b1695f41447b data/create/tags/items/crushed_raw_materials.json
0fa526e7e742573b603ad26b09526cf724efa1dc data/create/tags/items/deployable_drink.json 0fa526e7e742573b603ad26b09526cf724efa1dc data/create/tags/items/deployable_drink.json
99d3f12c67bd4c1f14fa9e6cbc1de5ed209ef402 data/create/tags/items/modded_stripped_logs.json ab45dc78be188d430c71904015b2b034908db64e data/create/tags/items/modded_stripped_logs.json
b49ad07e47fbb4b12c1d95d72f752e6e6839a815 data/create/tags/items/modded_stripped_wood.json 864fb582620b267894ad4016af8f0fd793bac5e8 data/create/tags/items/modded_stripped_wood.json
695d75b352fd190b303c724d1aaee9bb786a903b data/create/tags/items/pressurized_air_sources.json 695d75b352fd190b303c724d1aaee9bb786a903b data/create/tags/items/pressurized_air_sources.json
2cd3adffd8b151354df137a990dcb97996a665bb data/create/tags/items/sandpaper.json 2cd3adffd8b151354df137a990dcb97996a665bb data/create/tags/items/sandpaper.json
79418bd729cef417b322cef9b491e7ae83317d61 data/create/tags/items/seats.json 79418bd729cef417b322cef9b491e7ae83317d61 data/create/tags/items/seats.json

View file

@ -1,4 +1,4 @@
// 1.20.1 2023-07-04T18:31:12.3303171 Create's Advancements // 1.20.1 2023-09-20T19:40:25.3622264 Create's Advancements
2661a689fdcf729494f46e3c719f71c62e31582e data/create/advancements/andesite_alloy.json 2661a689fdcf729494f46e3c719f71c62e31582e data/create/advancements/andesite_alloy.json
fa16c4afe0496edc3f157858a6e0ff177a1622ff data/create/advancements/andesite_casing.json fa16c4afe0496edc3f157858a6e0ff177a1622ff data/create/advancements/andesite_casing.json
5a694002d0a663bc869b09d15924a10c43dc522f data/create/advancements/anvil_plough.json 5a694002d0a663bc869b09d15924a10c43dc522f data/create/advancements/anvil_plough.json
@ -29,7 +29,7 @@ ac78707d112458c7f771260cf65f0e9bc928d1b6 data/create/advancements/deployer.json
48c3af4499797cfb695a235e4527c52c608d40ad data/create/advancements/display_board_0.json 48c3af4499797cfb695a235e4527c52c608d40ad data/create/advancements/display_board_0.json
24be041d833017d7e7e02a5a92fd04060ea62594 data/create/advancements/display_link.json 24be041d833017d7e7e02a5a92fd04060ea62594 data/create/advancements/display_link.json
cc2c729cf82a0c80b4966ac6382984da08429b9d data/create/advancements/diving_suit.json cc2c729cf82a0c80b4966ac6382984da08429b9d data/create/advancements/diving_suit.json
7418171d223567cb52b22f5facef648af04cbae6 data/create/advancements/diving_suit_lava.json e1af547fd148cf9e60c1725ab03545fe3010eac7 data/create/advancements/diving_suit_lava.json
4d91e6a7bbf08191d8d1e11943650dfc1dc170e6 data/create/advancements/drain.json 4d91e6a7bbf08191d8d1e11943650dfc1dc170e6 data/create/advancements/drain.json
dee06f0f78a97a6358b67459d05fb479e5318fe9 data/create/advancements/ejector_maxed.json dee06f0f78a97a6358b67459d05fb479e5318fe9 data/create/advancements/ejector_maxed.json
3300ee54dc1e9d04fd13a11c971e046d9db24e10 data/create/advancements/encased_fan.json 3300ee54dc1e9d04fd13a11c971e046d9db24e10 data/create/advancements/encased_fan.json

View file

@ -1,4 +1,4 @@
// 1.20.1 2023-07-04T18:31:12.4130959 Create's Mechanical Crafting Recipes // 1.20.1 2023-09-20T19:40:25.4511802 Create's Mechanical Crafting Recipes
f076d64d9f30709bed34775136c9241097b28aa9 data/create/recipes/mechanical_crafting/crushing_wheel.json f076d64d9f30709bed34775136c9241097b28aa9 data/create/recipes/mechanical_crafting/crushing_wheel.json
694dca9dcff246bb7f560b3304fcc244c53217d5 data/create/recipes/mechanical_crafting/extendo_grip.json 694dca9dcff246bb7f560b3304fcc244c53217d5 data/create/recipes/mechanical_crafting/extendo_grip.json
3b2837b08607c1ca466fa3eb418209b2e55da6ba data/create/recipes/mechanical_crafting/potato_cannon.json 3b2837b08607c1ca466fa3eb418209b2e55da6ba data/create/recipes/mechanical_crafting/potato_cannon.json

View file

@ -1,4 +1,4 @@
// 1.20.1 2023-07-04T18:31:12.4081093 Create's Standard Recipes // 1.20.1 2023-09-20T19:40:25.4471912 Create's Standard Recipes
a8cc4af26f6c7c45a9eef12e92af1452fe042454 data/create/advancements/recipes/combat/crafting/appliances/netherite_backtank.json a8cc4af26f6c7c45a9eef12e92af1452fe042454 data/create/advancements/recipes/combat/crafting/appliances/netherite_backtank.json
2c2639c7b307ee7c7a4e97e5efebf496788998ad data/create/advancements/recipes/combat/crafting/appliances/netherite_backtank_from_netherite.json 2c2639c7b307ee7c7a4e97e5efebf496788998ad data/create/advancements/recipes/combat/crafting/appliances/netherite_backtank_from_netherite.json
81dcf0cb1aa99e39bc7d1a386e07cad4cee7d8b9 data/create/advancements/recipes/combat/crafting/appliances/netherite_diving_boots.json 81dcf0cb1aa99e39bc7d1a386e07cad4cee7d8b9 data/create/advancements/recipes/combat/crafting/appliances/netherite_diving_boots.json

View file

@ -1,4 +1,4 @@
// 1.20.1 2023-08-25T18:36:29.7642425 Create's Damage Type Tags // 1.20.1 2023-09-20T19:47:44.9018689 Create's Damage Type Tags
7884716b2f4bb1330ff215366bb4bab06e4728c2 data/minecraft/tags/damage_type/bypasses_armor.json 7884716b2f4bb1330ff215366bb4bab06e4728c2 data/minecraft/tags/damage_type/bypasses_armor.json
1fcad1f89265fba8bdb05b03a1dfcc88d7b7a550 data/minecraft/tags/damage_type/is_explosion.json 1fcad1f89265fba8bdb05b03a1dfcc88d7b7a550 data/minecraft/tags/damage_type/is_explosion.json
08324c61115b72bb8a6370d7f34d84d9a31afd16 data/minecraft/tags/damage_type/is_fire.json 08324c61115b72bb8a6370d7f34d84d9a31afd16 data/minecraft/tags/damage_type/is_fire.json

View file

@ -1,4 +1,4 @@
// 1.20.1 2023-08-23T16:29:07.6573146 Create's Processing Recipes // 1.20.1 2023-09-20T19:40:25.3652491 Create's Processing Recipes
3c94326fb730f68c1e44fe1e2ef09c9db6ffd92b data/create/recipes/compacting/andesite_from_flint.json 3c94326fb730f68c1e44fe1e2ef09c9db6ffd92b data/create/recipes/compacting/andesite_from_flint.json
8d3d5b31f3601b9f681ff710e0545a483a1494c6 data/create/recipes/compacting/blaze_cake.json 8d3d5b31f3601b9f681ff710e0545a483a1494c6 data/create/recipes/compacting/blaze_cake.json
8bd7f4e3a686ab520b2d55594d2018d0e9a50c91 data/create/recipes/compacting/chocolate.json 8bd7f4e3a686ab520b2d55594d2018d0e9a50c91 data/create/recipes/compacting/chocolate.json

View file

@ -1,2 +1,2 @@
// 1.20.1 2023-07-04T18:31:12.3492665 Create's Custom Sounds // 1.20.1 2023-09-20T19:40:25.3732177 Create's Custom Sounds
043955db25ffe58e7debb9a4f11e41a9571376e6 assets/create/sounds.json 043955db25ffe58e7debb9a4f11e41a9571376e6 assets/create/sounds.json

View file

@ -1,2 +1,2 @@
// 1.20.1 2023-08-24T21:57:44.7330415 Create's Recipe Serializer Tags // 1.20.1 2023-09-20T19:40:25.4461939 Create's Recipe Serializer Tags
0d8718f7383761bc5d7bc45306ed266ebf25dc1d data/create/tags/recipe_serializer/automation_ignore.json 0d8718f7383761bc5d7bc45306ed266ebf25dc1d data/create/tags/recipe_serializer/automation_ignore.json

View file

@ -1,4 +1,4 @@
// 1.20.1 2023-08-25T18:36:29.766244 Create's Generated Registry Entries // 1.20.1 2023-09-20T19:47:44.9028659 Create's Generated Registry Entries
030ede1044384c4117ac1e491bf5c78bbd2842f5 data/create/damage_type/crush.json 030ede1044384c4117ac1e491bf5c78bbd2842f5 data/create/damage_type/crush.json
92b0416950ffeb3ba68811e587177c2f8811c2c5 data/create/damage_type/cuckoo_surprise.json 92b0416950ffeb3ba68811e587177c2f8811c2c5 data/create/damage_type/cuckoo_surprise.json
d2a4fdb64f4ba817e13a7b20c73fd1ca34b825fc data/create/damage_type/fan_fire.json d2a4fdb64f4ba817e13a7b20c73fd1ca34b825fc data/create/damage_type/fan_fire.json

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
{ {
"parent": "create:backtank", "parent": "create:foods",
"criteria": { "criteria": {
"0": { "0": {
"conditions": {}, "conditions": {},
@ -13,9 +13,9 @@
"translate": "advancement.create.diving_suit_lava.desc" "translate": "advancement.create.diving_suit_lava.desc"
}, },
"frame": "goal", "frame": "goal",
"hidden": true, "hidden": false,
"icon": { "icon": {
"item": "create:copper_diving_helmet", "item": "create:netherite_diving_helmet",
"nbt": "{Damage:0}" "nbt": "{Damage:0}"
}, },
"show_toast": true, "show_toast": true,

View file

@ -0,0 +1,5 @@
{
"values": [
"create:blaze_burner"
]
}

View file

@ -0,0 +1,7 @@
{
"values": [
"create:lit_blaze_burner",
"minecraft:soul_fire",
"minecraft:soul_campfire"
]
}

View file

@ -0,0 +1,8 @@
{
"values": [
"create:blaze_burner",
"create:lit_blaze_burner",
"minecraft:fire",
"minecraft:campfire"
]
}

View file

@ -0,0 +1,3 @@
{
"values": []
}

View file

@ -0,0 +1,5 @@
{
"values": [
"minecraft:blaze"
]
}

View file

@ -0,0 +1,6 @@
{
"values": [
"minecraft:lava",
"minecraft:flowing_lava"
]
}

View file

@ -0,0 +1,3 @@
{
"values": []
}

View file

@ -0,0 +1,3 @@
{
"values": []
}

View file

@ -0,0 +1,6 @@
{
"values": [
"minecraft:water",
"minecraft:flowing_water"
]
}

View file

@ -288,6 +288,70 @@
"id": "blue_skies:stripped_cherry_log", "id": "blue_skies:stripped_cherry_log",
"required": false "required": false
}, },
{
"id": "environmental:stripped_cherry_log",
"required": false
},
{
"id": "environmental:stripped_willow_log",
"required": false
},
{
"id": "environmental:stripped_wisteria_log",
"required": false
},
{
"id": "atmospheric:stripped_aspen_log",
"required": false
},
{
"id": "atmospheric:stripped_kousa_log",
"required": false
},
{
"id": "atmospheric:stripped_yucca_log",
"required": false
},
{
"id": "atmospheric:stripped_morado_log",
"required": false
},
{
"id": "atmospheric:stripped_rosewood_log",
"required": false
},
{
"id": "atmospheric:stripped_grimwood_log",
"required": false
},
{
"id": "goodending:stripped_muddy_oak_log",
"required": false
},
{
"id": "goodending:stripped_cypress_log",
"required": false
},
{
"id": "biomemakeover:stripped_blighted_balsa_log",
"required": false
},
{
"id": "biomemakeover:stripped_willow_log",
"required": false
},
{
"id": "biomemakeover:stripped_swamp_cypress_log",
"required": false
},
{
"id": "biomemakeover:stripped_ancient_oak_log",
"required": false
},
{
"id": "infernalexp:stripped_luminous_stem",
"required": false
},
{ {
"id": "byg:stripped_bulbis_stem", "id": "byg:stripped_bulbis_stem",
"required": false "required": false

View file

@ -288,6 +288,70 @@
"id": "blue_skies:stripped_cherry_wood", "id": "blue_skies:stripped_cherry_wood",
"required": false "required": false
}, },
{
"id": "environmental:stripped_cherry_wood",
"required": false
},
{
"id": "environmental:stripped_willow_wood",
"required": false
},
{
"id": "environmental:stripped_wisteria_wood",
"required": false
},
{
"id": "atmospheric:stripped_aspen_wood",
"required": false
},
{
"id": "atmospheric:stripped_kousa_wood",
"required": false
},
{
"id": "atmospheric:stripped_yucca_wood",
"required": false
},
{
"id": "atmospheric:stripped_morado_wood",
"required": false
},
{
"id": "atmospheric:stripped_rosewood",
"required": false
},
{
"id": "atmospheric:stripped_grimwood",
"required": false
},
{
"id": "goodending:stripped_muddy_oak_wood",
"required": false
},
{
"id": "goodending:stripped_cypress_wood",
"required": false
},
{
"id": "biomemakeover:stripped_blighted_balsa_wood",
"required": false
},
{
"id": "biomemakeover:stripped_willow_wood",
"required": false
},
{
"id": "biomemakeover:stripped_swamp_cypress_wood",
"required": false
},
{
"id": "biomemakeover:stripped_ancient_oak_wood",
"required": false
},
{
"id": "infernalexp:stripped_luminous_hyphae",
"required": false
},
{ {
"id": "byg:stripped_bulbis_wood", "id": "byg:stripped_bulbis_wood",
"required": false "required": false

View file

@ -310,8 +310,10 @@ import net.minecraftforge.common.Tags;
import net.minecraftforge.common.util.ForgeSoundType; import net.minecraftforge.common.util.ForgeSoundType;
public class AllBlocks { public class AllBlocks {
static { REGISTRATE.useCreativeTab(AllCreativeModeTabs.MAIN_TAB); } static {
REGISTRATE.setCreativeTab(AllCreativeModeTabs.BASE_CREATIVE_TAB);
}
// Schematics // Schematics
@ -339,7 +341,7 @@ public class AllBlocks {
public static final BlockEntry<SchematicTableBlock> SCHEMATIC_TABLE = public static final BlockEntry<SchematicTableBlock> SCHEMATIC_TABLE =
REGISTRATE.block("schematic_table", SchematicTableBlock::new) REGISTRATE.block("schematic_table", SchematicTableBlock::new)
.initialProperties(() -> Blocks.LECTERN) .initialProperties(() -> Blocks.LECTERN)
.properties(p -> p.mapColor(MapColor.PODZOL)) .properties(p -> p.mapColor(MapColor.PODZOL).forceSolidOn())
.transform(axeOrPickaxe()) .transform(axeOrPickaxe())
.blockstate((ctx, prov) -> prov.horizontalBlock(ctx.getEntry(), prov.models() .blockstate((ctx, prov) -> prov.horizontalBlock(ctx.getEntry(), prov.models()
.getExistingFile(ctx.getId()), 0)) .getExistingFile(ctx.getId()), 0))
@ -350,7 +352,7 @@ public class AllBlocks {
public static final BlockEntry<ShaftBlock> SHAFT = REGISTRATE.block("shaft", ShaftBlock::new) public static final BlockEntry<ShaftBlock> SHAFT = REGISTRATE.block("shaft", ShaftBlock::new)
.initialProperties(SharedProperties::stone) .initialProperties(SharedProperties::stone)
.properties(p -> p.mapColor(MapColor.METAL)) .properties(p -> p.mapColor(MapColor.METAL).forceSolidOn())
.transform(BlockStressDefaults.setNoImpact()) .transform(BlockStressDefaults.setNoImpact())
.transform(pickaxeOnly()) .transform(pickaxeOnly())
.blockstate(BlockStateGen.axisBlockProvider(false)) .blockstate(BlockStateGen.axisBlockProvider(false))
@ -360,8 +362,7 @@ public class AllBlocks {
public static final BlockEntry<CogWheelBlock> COGWHEEL = REGISTRATE.block("cogwheel", CogWheelBlock::small) public static final BlockEntry<CogWheelBlock> COGWHEEL = REGISTRATE.block("cogwheel", CogWheelBlock::small)
.initialProperties(SharedProperties::stone) .initialProperties(SharedProperties::stone)
.properties(p -> p.sound(SoundType.WOOD)) .properties(p -> p.sound(SoundType.WOOD).mapColor(MapColor.DIRT))
.properties(p -> p.mapColor(MapColor.DIRT))
.transform(BlockStressDefaults.setNoImpact()) .transform(BlockStressDefaults.setNoImpact())
.transform(axeOrPickaxe()) .transform(axeOrPickaxe())
.blockstate(BlockStateGen.axisBlockProvider(false)) .blockstate(BlockStateGen.axisBlockProvider(false))
@ -373,8 +374,7 @@ public class AllBlocks {
public static final BlockEntry<CogWheelBlock> LARGE_COGWHEEL = public static final BlockEntry<CogWheelBlock> LARGE_COGWHEEL =
REGISTRATE.block("large_cogwheel", CogWheelBlock::large) REGISTRATE.block("large_cogwheel", CogWheelBlock::large)
.initialProperties(SharedProperties::stone) .initialProperties(SharedProperties::stone)
.properties(p -> p.sound(SoundType.WOOD)) .properties(p -> p.sound(SoundType.WOOD).mapColor(MapColor.DIRT))
.properties(p -> p.mapColor(MapColor.DIRT))
.transform(axeOrPickaxe()) .transform(axeOrPickaxe())
.transform(BlockStressDefaults.setNoImpact()) .transform(BlockStressDefaults.setNoImpact())
.blockstate(BlockStateGen.axisBlockProvider(false)) .blockstate(BlockStateGen.axisBlockProvider(false))
@ -440,8 +440,7 @@ public class AllBlocks {
public static final BlockEntry<GearboxBlock> GEARBOX = REGISTRATE.block("gearbox", GearboxBlock::new) public static final BlockEntry<GearboxBlock> GEARBOX = REGISTRATE.block("gearbox", GearboxBlock::new)
.initialProperties(SharedProperties::stone) .initialProperties(SharedProperties::stone)
.properties(BlockBehaviour.Properties::noOcclusion) .properties(p -> p.noOcclusion().mapColor(MapColor.PODZOL))
.properties(p -> p.mapColor(MapColor.PODZOL))
.transform(BlockStressDefaults.setNoImpact()) .transform(BlockStressDefaults.setNoImpact())
.transform(axeOrPickaxe()) .transform(axeOrPickaxe())
.onRegister(CreateRegistrate.connectedTextures(() -> new EncasedCTBehaviour(AllSpriteShifts.ANDESITE_CASING))) .onRegister(CreateRegistrate.connectedTextures(() -> new EncasedCTBehaviour(AllSpriteShifts.ANDESITE_CASING)))
@ -454,8 +453,7 @@ public class AllBlocks {
public static final BlockEntry<ClutchBlock> CLUTCH = REGISTRATE.block("clutch", ClutchBlock::new) public static final BlockEntry<ClutchBlock> CLUTCH = REGISTRATE.block("clutch", ClutchBlock::new)
.initialProperties(SharedProperties::stone) .initialProperties(SharedProperties::stone)
.properties(BlockBehaviour.Properties::noOcclusion) .properties(p -> p.noOcclusion().mapColor(MapColor.PODZOL))
.properties(p -> p.mapColor(MapColor.PODZOL))
.addLayer(() -> RenderType::cutoutMipped) .addLayer(() -> RenderType::cutoutMipped)
.transform(BlockStressDefaults.setNoImpact()) .transform(BlockStressDefaults.setNoImpact())
.transform(axeOrPickaxe()) .transform(axeOrPickaxe())
@ -466,8 +464,7 @@ public class AllBlocks {
public static final BlockEntry<GearshiftBlock> GEARSHIFT = REGISTRATE.block("gearshift", GearshiftBlock::new) public static final BlockEntry<GearshiftBlock> GEARSHIFT = REGISTRATE.block("gearshift", GearshiftBlock::new)
.initialProperties(SharedProperties::stone) .initialProperties(SharedProperties::stone)
.properties(BlockBehaviour.Properties::noOcclusion) .properties(p -> p.noOcclusion().mapColor(MapColor.PODZOL))
.properties(p -> p.mapColor(MapColor.PODZOL))
.addLayer(() -> RenderType::cutoutMipped) .addLayer(() -> RenderType::cutoutMipped)
.transform(BlockStressDefaults.setNoImpact()) .transform(BlockStressDefaults.setNoImpact())
.transform(axeOrPickaxe()) .transform(axeOrPickaxe())
@ -479,8 +476,7 @@ public class AllBlocks {
public static final BlockEntry<ChainDriveBlock> ENCASED_CHAIN_DRIVE = public static final BlockEntry<ChainDriveBlock> ENCASED_CHAIN_DRIVE =
REGISTRATE.block("encased_chain_drive", ChainDriveBlock::new) REGISTRATE.block("encased_chain_drive", ChainDriveBlock::new)
.initialProperties(SharedProperties::stone) .initialProperties(SharedProperties::stone)
.properties(BlockBehaviour.Properties::noOcclusion) .properties(p -> p.noOcclusion().mapColor(MapColor.PODZOL))
.properties(p -> p.mapColor(MapColor.PODZOL))
.transform(BlockStressDefaults.setNoImpact()) .transform(BlockStressDefaults.setNoImpact())
.transform(axeOrPickaxe()) .transform(axeOrPickaxe())
.blockstate((c, p) -> new ChainDriveGenerator((state, suffix) -> p.models() .blockstate((c, p) -> new ChainDriveGenerator((state, suffix) -> p.models()
@ -492,8 +488,7 @@ public class AllBlocks {
public static final BlockEntry<ChainGearshiftBlock> ADJUSTABLE_CHAIN_GEARSHIFT = public static final BlockEntry<ChainGearshiftBlock> ADJUSTABLE_CHAIN_GEARSHIFT =
REGISTRATE.block("adjustable_chain_gearshift", ChainGearshiftBlock::new) REGISTRATE.block("adjustable_chain_gearshift", ChainGearshiftBlock::new)
.initialProperties(SharedProperties::stone) .initialProperties(SharedProperties::stone)
.properties(BlockBehaviour.Properties::noOcclusion) .properties(p -> p.noOcclusion().mapColor(MapColor.NETHER))
.properties(p -> p.mapColor(MapColor.NETHER))
.transform(BlockStressDefaults.setNoImpact()) .transform(BlockStressDefaults.setNoImpact())
.transform(axeOrPickaxe()) .transform(axeOrPickaxe())
.blockstate((c, p) -> new ChainDriveGenerator((state, suffix) -> { .blockstate((c, p) -> new ChainDriveGenerator((state, suffix) -> {
@ -524,7 +519,7 @@ public class AllBlocks {
public static final BlockEntry<CreativeMotorBlock> CREATIVE_MOTOR = public static final BlockEntry<CreativeMotorBlock> CREATIVE_MOTOR =
REGISTRATE.block("creative_motor", CreativeMotorBlock::new) REGISTRATE.block("creative_motor", CreativeMotorBlock::new)
.initialProperties(SharedProperties::stone) .initialProperties(SharedProperties::stone)
.properties(p -> p.mapColor(MapColor.COLOR_PURPLE)) .properties(p -> p.mapColor(MapColor.COLOR_PURPLE).forceSolidOn())
.tag(AllBlockTags.SAFE_NBT.tag) .tag(AllBlockTags.SAFE_NBT.tag)
.transform(pickaxeOnly()) .transform(pickaxeOnly())
.blockstate(new CreativeMotorGenerator()::generate) .blockstate(new CreativeMotorGenerator()::generate)
@ -537,8 +532,7 @@ public class AllBlocks {
public static final BlockEntry<WaterWheelBlock> WATER_WHEEL = REGISTRATE.block("water_wheel", WaterWheelBlock::new) public static final BlockEntry<WaterWheelBlock> WATER_WHEEL = REGISTRATE.block("water_wheel", WaterWheelBlock::new)
.initialProperties(SharedProperties::wooden) .initialProperties(SharedProperties::wooden)
.properties(p -> p.mapColor(MapColor.DIRT)) .properties(p -> p.noOcclusion().mapColor(MapColor.DIRT))
.properties(BlockBehaviour.Properties::noOcclusion)
.transform(axeOrPickaxe()) .transform(axeOrPickaxe())
.blockstate( .blockstate(
(c, p) -> BlockStateGen.directionalBlockIgnoresWaterlogged(c, p, s -> AssetLookup.partialBaseModel(c, p))) (c, p) -> BlockStateGen.directionalBlockIgnoresWaterlogged(c, p, s -> AssetLookup.partialBaseModel(c, p)))
@ -552,8 +546,7 @@ public class AllBlocks {
public static final BlockEntry<LargeWaterWheelBlock> LARGE_WATER_WHEEL = public static final BlockEntry<LargeWaterWheelBlock> LARGE_WATER_WHEEL =
REGISTRATE.block("large_water_wheel", LargeWaterWheelBlock::new) REGISTRATE.block("large_water_wheel", LargeWaterWheelBlock::new)
.initialProperties(SharedProperties::wooden) .initialProperties(SharedProperties::wooden)
.properties(p -> p.mapColor(MapColor.DIRT)) .properties(p -> p.noOcclusion().mapColor(MapColor.DIRT))
.properties(BlockBehaviour.Properties::noOcclusion)
.transform(axeOrPickaxe()) .transform(axeOrPickaxe())
.blockstate((c, p) -> axisBlock(c, p, .blockstate((c, p) -> axisBlock(c, p,
s -> s.getValue(LargeWaterWheelBlock.EXTENSION) ? AssetLookup.partialBaseModel(c, p, "extension") s -> s.getValue(LargeWaterWheelBlock.EXTENSION) ? AssetLookup.partialBaseModel(c, p, "extension")
@ -569,8 +562,7 @@ public class AllBlocks {
.initialProperties(SharedProperties::wooden) .initialProperties(SharedProperties::wooden)
.blockstate((c, p) -> p.getVariantBuilder(c.get()) .blockstate((c, p) -> p.getVariantBuilder(c.get())
.forAllStatesExcept(BlockStateGen.mapToAir(p), WaterWheelStructuralBlock.FACING)) .forAllStatesExcept(BlockStateGen.mapToAir(p), WaterWheelStructuralBlock.FACING))
.properties(p -> p.mapColor(MapColor.DIRT)) .properties(p -> p.noOcclusion().mapColor(MapColor.DIRT))
.properties(BlockBehaviour.Properties::noOcclusion)
.transform(axeOrPickaxe()) .transform(axeOrPickaxe())
.lang("Large Water Wheel") .lang("Large Water Wheel")
.register(); .register();
@ -675,8 +667,7 @@ public class AllBlocks {
public static final BlockEntry<MechanicalPressBlock> MECHANICAL_PRESS = public static final BlockEntry<MechanicalPressBlock> MECHANICAL_PRESS =
REGISTRATE.block("mechanical_press", MechanicalPressBlock::new) REGISTRATE.block("mechanical_press", MechanicalPressBlock::new)
.initialProperties(SharedProperties::stone) .initialProperties(SharedProperties::stone)
.properties(p -> p.mapColor(MapColor.PODZOL)) .properties(p -> p.noOcclusion().mapColor(MapColor.PODZOL))
.properties(BlockBehaviour.Properties::noOcclusion)
.transform(axeOrPickaxe()) .transform(axeOrPickaxe())
.blockstate(BlockStateGen.horizontalBlockProvider(true)) .blockstate(BlockStateGen.horizontalBlockProvider(true))
.transform(BlockStressDefaults.setImpact(8.0)) .transform(BlockStressDefaults.setImpact(8.0))
@ -687,8 +678,7 @@ public class AllBlocks {
public static final BlockEntry<MechanicalMixerBlock> MECHANICAL_MIXER = public static final BlockEntry<MechanicalMixerBlock> MECHANICAL_MIXER =
REGISTRATE.block("mechanical_mixer", MechanicalMixerBlock::new) REGISTRATE.block("mechanical_mixer", MechanicalMixerBlock::new)
.initialProperties(SharedProperties::stone) .initialProperties(SharedProperties::stone)
.properties(p -> p.mapColor(MapColor.STONE)) .properties(p -> p.noOcclusion().mapColor(MapColor.STONE))
.properties(BlockBehaviour.Properties::noOcclusion)
.transform(axeOrPickaxe()) .transform(axeOrPickaxe())
.blockstate((c, p) -> p.simpleBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p))) .blockstate((c, p) -> p.simpleBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p)))
.addLayer(() -> RenderType::cutoutMipped) .addLayer(() -> RenderType::cutoutMipped)
@ -699,8 +689,7 @@ public class AllBlocks {
public static final BlockEntry<BasinBlock> BASIN = REGISTRATE.block("basin", BasinBlock::new) public static final BlockEntry<BasinBlock> BASIN = REGISTRATE.block("basin", BasinBlock::new)
.initialProperties(SharedProperties::stone) .initialProperties(SharedProperties::stone)
.properties(p -> p.mapColor(MapColor.COLOR_GRAY)) .properties(p -> p.mapColor(MapColor.COLOR_GRAY).sound(SoundType.NETHERITE_BLOCK))
.properties(p -> p.sound(SoundType.NETHERITE_BLOCK))
.transform(pickaxeOnly()) .transform(pickaxeOnly())
.blockstate(new BasinGenerator()::generate) .blockstate(new BasinGenerator()::generate)
.addLayer(() -> RenderType::cutoutMipped) .addLayer(() -> RenderType::cutoutMipped)
@ -712,11 +701,10 @@ public class AllBlocks {
public static final BlockEntry<BlazeBurnerBlock> BLAZE_BURNER = public static final BlockEntry<BlazeBurnerBlock> BLAZE_BURNER =
REGISTRATE.block("blaze_burner", BlazeBurnerBlock::new) REGISTRATE.block("blaze_burner", BlazeBurnerBlock::new)
.initialProperties(SharedProperties::softMetal) .initialProperties(SharedProperties::softMetal)
.properties(p -> p.mapColor(MapColor.COLOR_GRAY)) .properties(p -> p.mapColor(MapColor.COLOR_GRAY).lightLevel(BlazeBurnerBlock::getLight))
.properties(p -> p.lightLevel(BlazeBurnerBlock::getLight))
.transform(pickaxeOnly()) .transform(pickaxeOnly())
.addLayer(() -> RenderType::cutoutMipped) .addLayer(() -> RenderType::cutoutMipped)
.tag(AllBlockTags.FAN_TRANSPARENT.tag, AllBlockTags.PASSIVE_BOILER_HEATERS.tag) .tag(AllBlockTags.FAN_PROCESSING_CATALYSTS_BLASTING.tag, AllBlockTags.FAN_PROCESSING_CATALYSTS_SMOKING.tag, AllBlockTags.FAN_TRANSPARENT.tag, AllBlockTags.PASSIVE_BOILER_HEATERS.tag)
.loot((lt, block) -> lt.add(block, BlazeBurnerBlock.buildLootTable())) .loot((lt, block) -> lt.add(block, BlazeBurnerBlock.buildLootTable()))
.blockstate((c, p) -> p.simpleBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p))) .blockstate((c, p) -> p.simpleBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p)))
.onRegister(movementBehaviour(new BlazeBurnerMovementBehaviour())) .onRegister(movementBehaviour(new BlazeBurnerMovementBehaviour()))
@ -729,11 +717,10 @@ public class AllBlocks {
public static final BlockEntry<LitBlazeBurnerBlock> LIT_BLAZE_BURNER = public static final BlockEntry<LitBlazeBurnerBlock> LIT_BLAZE_BURNER =
REGISTRATE.block("lit_blaze_burner", LitBlazeBurnerBlock::new) REGISTRATE.block("lit_blaze_burner", LitBlazeBurnerBlock::new)
.initialProperties(SharedProperties::softMetal) .initialProperties(SharedProperties::softMetal)
.properties(p -> p.mapColor(MapColor.COLOR_LIGHT_GRAY)) .properties(p -> p.mapColor(MapColor.COLOR_LIGHT_GRAY).lightLevel(LitBlazeBurnerBlock::getLight))
.properties(p -> p.lightLevel(LitBlazeBurnerBlock::getLight))
.transform(pickaxeOnly()) .transform(pickaxeOnly())
.addLayer(() -> RenderType::cutoutMipped) .addLayer(() -> RenderType::cutoutMipped)
.tag(AllBlockTags.FAN_TRANSPARENT.tag, AllBlockTags.PASSIVE_BOILER_HEATERS.tag) .tag(AllBlockTags.FAN_PROCESSING_CATALYSTS_HAUNTING.tag, AllBlockTags.FAN_PROCESSING_CATALYSTS_SMOKING.tag, AllBlockTags.FAN_TRANSPARENT.tag, AllBlockTags.PASSIVE_BOILER_HEATERS.tag)
.loot((lt, block) -> lt.dropOther(block, AllItems.EMPTY_BLAZE_BURNER.get())) .loot((lt, block) -> lt.dropOther(block, AllItems.EMPTY_BLAZE_BURNER.get()))
.blockstate((c, p) -> p.getVariantBuilder(c.get()) .blockstate((c, p) -> p.getVariantBuilder(c.get())
.forAllStates(state -> ConfiguredModel.builder() .forAllStates(state -> ConfiguredModel.builder()
@ -758,8 +745,7 @@ public class AllBlocks {
public static final BlockEntry<EjectorBlock> WEIGHTED_EJECTOR = public static final BlockEntry<EjectorBlock> WEIGHTED_EJECTOR =
REGISTRATE.block("weighted_ejector", EjectorBlock::new) REGISTRATE.block("weighted_ejector", EjectorBlock::new)
.initialProperties(SharedProperties::stone) .initialProperties(SharedProperties::stone)
.properties(p -> p.mapColor(MapColor.COLOR_GRAY)) .properties(p -> p.noOcclusion().mapColor(MapColor.COLOR_GRAY))
.properties(BlockBehaviour.Properties::noOcclusion)
.transform(axeOrPickaxe()) .transform(axeOrPickaxe())
.blockstate((c, p) -> p.horizontalBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p), 180)) .blockstate((c, p) -> p.horizontalBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p), 180))
.transform(BlockStressDefaults.setImpact(2.0)) .transform(BlockStressDefaults.setImpact(2.0))
@ -769,10 +755,8 @@ public class AllBlocks {
.register(); .register();
public static final BlockEntry<ChuteBlock> CHUTE = REGISTRATE.block("chute", ChuteBlock::new) public static final BlockEntry<ChuteBlock> CHUTE = REGISTRATE.block("chute", ChuteBlock::new)
.addLayer(() -> RenderType::cutoutMipped)
.initialProperties(SharedProperties::softMetal) .initialProperties(SharedProperties::softMetal)
.properties(p -> p.mapColor(MapColor.COLOR_GRAY)) .properties(p -> p.mapColor(MapColor.COLOR_GRAY).sound(SoundType.NETHERITE_BLOCK))
.properties(p -> p.sound(SoundType.NETHERITE_BLOCK))
.transform(pickaxeOnly()) .transform(pickaxeOnly())
.addLayer(() -> RenderType::cutoutMipped) .addLayer(() -> RenderType::cutoutMipped)
.blockstate(new ChuteGenerator()::generate) .blockstate(new ChuteGenerator()::generate)
@ -781,12 +765,12 @@ public class AllBlocks {
.register(); .register();
public static final BlockEntry<SmartChuteBlock> SMART_CHUTE = REGISTRATE.block("smart_chute", SmartChuteBlock::new) public static final BlockEntry<SmartChuteBlock> SMART_CHUTE = REGISTRATE.block("smart_chute", SmartChuteBlock::new)
.addLayer(() -> RenderType::cutoutMipped)
.initialProperties(SharedProperties::softMetal) .initialProperties(SharedProperties::softMetal)
.properties(p -> p.mapColor(MapColor.COLOR_GRAY)) .properties(p -> p.mapColor(MapColor.COLOR_GRAY)
.properties(p -> p.sound(SoundType.NETHERITE_BLOCK)) .sound(SoundType.NETHERITE_BLOCK)
.properties(p -> p.noOcclusion()) .noOcclusion()
.properties(p -> p.isRedstoneConductor((level, pos, state) -> false)) .isRedstoneConductor((level, pos, state) -> false))
.addLayer(() -> RenderType::cutoutMipped)
.transform(pickaxeOnly()) .transform(pickaxeOnly())
.blockstate((c, p) -> BlockStateGen.simpleBlock(c, p, AssetLookup.forPowered(c, p))) .blockstate((c, p) -> BlockStateGen.simpleBlock(c, p, AssetLookup.forPowered(c, p)))
.item() .item()
@ -835,6 +819,7 @@ public class AllBlocks {
public static final BlockEntry<FluidPipeBlock> FLUID_PIPE = REGISTRATE.block("fluid_pipe", FluidPipeBlock::new) public static final BlockEntry<FluidPipeBlock> FLUID_PIPE = REGISTRATE.block("fluid_pipe", FluidPipeBlock::new)
.initialProperties(SharedProperties::copperMetal) .initialProperties(SharedProperties::copperMetal)
.properties(p -> p.forceSolidOn())
.transform(pickaxeOnly()) .transform(pickaxeOnly())
.blockstate(BlockStateGen.pipe()) .blockstate(BlockStateGen.pipe())
.onRegister(CreateRegistrate.blockModel(() -> PipeAttachmentModel::new)) .onRegister(CreateRegistrate.blockModel(() -> PipeAttachmentModel::new))
@ -845,8 +830,7 @@ public class AllBlocks {
public static final BlockEntry<EncasedPipeBlock> ENCASED_FLUID_PIPE = public static final BlockEntry<EncasedPipeBlock> ENCASED_FLUID_PIPE =
REGISTRATE.block("encased_fluid_pipe", p -> new EncasedPipeBlock(p, AllBlocks.COPPER_CASING::get)) REGISTRATE.block("encased_fluid_pipe", p -> new EncasedPipeBlock(p, AllBlocks.COPPER_CASING::get))
.initialProperties(SharedProperties::copperMetal) .initialProperties(SharedProperties::copperMetal)
.properties(p -> p.mapColor(MapColor.TERRACOTTA_LIGHT_GRAY)) .properties(p -> p.noOcclusion().mapColor(MapColor.TERRACOTTA_LIGHT_GRAY))
.properties(BlockBehaviour.Properties::noOcclusion)
.transform(axeOrPickaxe()) .transform(axeOrPickaxe())
.blockstate(BlockStateGen.encasedPipe()) .blockstate(BlockStateGen.encasedPipe())
.onRegister(CreateRegistrate.connectedTextures(() -> new EncasedCTBehaviour(AllSpriteShifts.COPPER_CASING))) .onRegister(CreateRegistrate.connectedTextures(() -> new EncasedCTBehaviour(AllSpriteShifts.COPPER_CASING)))
@ -860,6 +844,7 @@ public class AllBlocks {
public static final BlockEntry<GlassFluidPipeBlock> GLASS_FLUID_PIPE = public static final BlockEntry<GlassFluidPipeBlock> GLASS_FLUID_PIPE =
REGISTRATE.block("glass_fluid_pipe", GlassFluidPipeBlock::new) REGISTRATE.block("glass_fluid_pipe", GlassFluidPipeBlock::new)
.initialProperties(SharedProperties::copperMetal) .initialProperties(SharedProperties::copperMetal)
.properties(p -> p.forceSolidOn())
.addLayer(() -> RenderType::cutoutMipped) .addLayer(() -> RenderType::cutoutMipped)
.transform(pickaxeOnly()) .transform(pickaxeOnly())
.blockstate((c, p) -> { .blockstate((c, p) -> {
@ -935,8 +920,7 @@ public class AllBlocks {
public static final BlockEntry<FluidTankBlock> FLUID_TANK = REGISTRATE.block("fluid_tank", FluidTankBlock::regular) public static final BlockEntry<FluidTankBlock> FLUID_TANK = REGISTRATE.block("fluid_tank", FluidTankBlock::regular)
.initialProperties(SharedProperties::copperMetal) .initialProperties(SharedProperties::copperMetal)
.properties(BlockBehaviour.Properties::noOcclusion) .properties(p -> p.noOcclusion().isRedstoneConductor((p1, p2, p3) -> true))
.properties(p -> p.isRedstoneConductor((p1, p2, p3) -> true))
.transform(pickaxeOnly()) .transform(pickaxeOnly())
.blockstate(new FluidTankGenerator()::generate) .blockstate(new FluidTankGenerator()::generate)
.onRegister(CreateRegistrate.blockModel(() -> FluidTankModel::standard)) .onRegister(CreateRegistrate.blockModel(() -> FluidTankModel::standard))
@ -950,8 +934,7 @@ public class AllBlocks {
public static final BlockEntry<FluidTankBlock> CREATIVE_FLUID_TANK = public static final BlockEntry<FluidTankBlock> CREATIVE_FLUID_TANK =
REGISTRATE.block("creative_fluid_tank", FluidTankBlock::creative) REGISTRATE.block("creative_fluid_tank", FluidTankBlock::creative)
.initialProperties(SharedProperties::copperMetal) .initialProperties(SharedProperties::copperMetal)
.properties(BlockBehaviour.Properties::noOcclusion) .properties(p -> p.noOcclusion().mapColor(MapColor.COLOR_PURPLE))
.properties(p -> p.mapColor(MapColor.COLOR_PURPLE))
.transform(pickaxeOnly()) .transform(pickaxeOnly())
.tag(AllBlockTags.SAFE_NBT.tag) .tag(AllBlockTags.SAFE_NBT.tag)
.blockstate(new FluidTankGenerator("creative_")::generate) .blockstate(new FluidTankGenerator("creative_")::generate)
@ -1030,7 +1013,7 @@ public class AllBlocks {
public static final BlockEntry<WhistleExtenderBlock> STEAM_WHISTLE_EXTENSION = public static final BlockEntry<WhistleExtenderBlock> STEAM_WHISTLE_EXTENSION =
REGISTRATE.block("steam_whistle_extension", WhistleExtenderBlock::new) REGISTRATE.block("steam_whistle_extension", WhistleExtenderBlock::new)
.initialProperties(SharedProperties::copperMetal) .initialProperties(SharedProperties::copperMetal)
.properties(p -> p.mapColor(MapColor.GOLD)) .properties(p -> p.mapColor(MapColor.GOLD).forceSolidOn())
.transform(pickaxeOnly()) .transform(pickaxeOnly())
.blockstate(BlockStateGen.whistleExtender()) .blockstate(BlockStateGen.whistleExtender())
.register(); .register();
@ -1038,7 +1021,7 @@ public class AllBlocks {
public static final BlockEntry<PoweredShaftBlock> POWERED_SHAFT = public static final BlockEntry<PoweredShaftBlock> POWERED_SHAFT =
REGISTRATE.block("powered_shaft", PoweredShaftBlock::new) REGISTRATE.block("powered_shaft", PoweredShaftBlock::new)
.initialProperties(SharedProperties::stone) .initialProperties(SharedProperties::stone)
.properties(p -> p.mapColor(MapColor.METAL)) .properties(p -> p.mapColor(MapColor.METAL).forceSolidOn())
.transform(pickaxeOnly()) .transform(pickaxeOnly())
.blockstate(BlockStateGen.axisBlockProvider(false)) .blockstate(BlockStateGen.axisBlockProvider(false))
.loot((lt, block) -> lt.dropOther(block, AllBlocks.SHAFT.get())) .loot((lt, block) -> lt.dropOther(block, AllBlocks.SHAFT.get()))
@ -1065,8 +1048,7 @@ public class AllBlocks {
public static final BlockEntry<PistonExtensionPoleBlock> PISTON_EXTENSION_POLE = public static final BlockEntry<PistonExtensionPoleBlock> PISTON_EXTENSION_POLE =
REGISTRATE.block("piston_extension_pole", PistonExtensionPoleBlock::new) REGISTRATE.block("piston_extension_pole", PistonExtensionPoleBlock::new)
.initialProperties(() -> Blocks.PISTON_HEAD) .initialProperties(() -> Blocks.PISTON_HEAD)
.properties(p -> p.sound(SoundType.SCAFFOLDING)) .properties(p -> p.sound(SoundType.SCAFFOLDING).mapColor(MapColor.DIRT).forceSolidOn())
.properties(p -> p.mapColor(MapColor.DIRT))
.transform(axeOrPickaxe()) .transform(axeOrPickaxe())
.blockstate(BlockStateGen.directionalBlockProviderIgnoresWaterlogged(false)) .blockstate(BlockStateGen.directionalBlockProviderIgnoresWaterlogged(false))
.simpleItem() .simpleItem()
@ -1086,8 +1068,7 @@ public class AllBlocks {
public static final BlockEntry<GantryCarriageBlock> GANTRY_CARRIAGE = public static final BlockEntry<GantryCarriageBlock> GANTRY_CARRIAGE =
REGISTRATE.block("gantry_carriage", GantryCarriageBlock::new) REGISTRATE.block("gantry_carriage", GantryCarriageBlock::new)
.initialProperties(SharedProperties::stone) .initialProperties(SharedProperties::stone)
.properties(p -> p.mapColor(MapColor.PODZOL)) .properties(p -> p.noOcclusion().mapColor(MapColor.PODZOL))
.properties(BlockBehaviour.Properties::noOcclusion)
.transform(axeOrPickaxe()) .transform(axeOrPickaxe())
.blockstate(BlockStateGen.directionalAxisBlockProvider()) .blockstate(BlockStateGen.directionalAxisBlockProvider())
.item() .item()
@ -1097,7 +1078,7 @@ public class AllBlocks {
public static final BlockEntry<GantryShaftBlock> GANTRY_SHAFT = public static final BlockEntry<GantryShaftBlock> GANTRY_SHAFT =
REGISTRATE.block("gantry_shaft", GantryShaftBlock::new) REGISTRATE.block("gantry_shaft", GantryShaftBlock::new)
.initialProperties(SharedProperties::stone) .initialProperties(SharedProperties::stone)
.properties(p -> p.mapColor(MapColor.NETHER)) .properties(p -> p.mapColor(MapColor.NETHER).forceSolidOn())
.transform(axeOrPickaxe()) .transform(axeOrPickaxe())
.blockstate((c, p) -> p.directionalBlock(c.get(), s -> { .blockstate((c, p) -> p.directionalBlock(c.get(), s -> {
boolean isPowered = s.getValue(GantryShaftBlock.POWERED); boolean isPowered = s.getValue(GantryShaftBlock.POWERED);
@ -1192,8 +1173,7 @@ public class AllBlocks {
public static final BlockEntry<CartAssemblerBlock> CART_ASSEMBLER = public static final BlockEntry<CartAssemblerBlock> CART_ASSEMBLER =
REGISTRATE.block("cart_assembler", CartAssemblerBlock::new) REGISTRATE.block("cart_assembler", CartAssemblerBlock::new)
.initialProperties(SharedProperties::stone) .initialProperties(SharedProperties::stone)
.properties(p -> p.mapColor(MapColor.COLOR_GRAY)) .properties(p -> p.noOcclusion().mapColor(MapColor.COLOR_GRAY))
.properties(BlockBehaviour.Properties::noOcclusion)
.transform(axeOrPickaxe()) .transform(axeOrPickaxe())
.blockstate(BlockStateGen.cartAssembler()) .blockstate(BlockStateGen.cartAssembler())
.addLayer(() -> RenderType::cutoutMipped) .addLayer(() -> RenderType::cutoutMipped)
@ -1349,8 +1329,7 @@ public class AllBlocks {
public static final BlockEntry<ElevatorContactBlock> ELEVATOR_CONTACT = public static final BlockEntry<ElevatorContactBlock> ELEVATOR_CONTACT =
REGISTRATE.block("elevator_contact", ElevatorContactBlock::new) REGISTRATE.block("elevator_contact", ElevatorContactBlock::new)
.initialProperties(SharedProperties::softMetal) .initialProperties(SharedProperties::softMetal)
.properties(p -> p.mapColor(MapColor.TERRACOTTA_YELLOW)) .properties(p -> p.mapColor(MapColor.TERRACOTTA_YELLOW).lightLevel(ElevatorContactBlock::getLight))
.properties(p -> p.lightLevel(ElevatorContactBlock::getLight))
.transform(axeOrPickaxe()) .transform(axeOrPickaxe())
.blockstate((c, p) -> p.directionalBlock(c.get(), state -> { .blockstate((c, p) -> p.directionalBlock(c.get(), state -> {
Boolean calling = state.getValue(ElevatorContactBlock.CALLING); Boolean calling = state.getValue(ElevatorContactBlock.CALLING);
@ -1367,7 +1346,7 @@ public class AllBlocks {
public static final BlockEntry<HarvesterBlock> MECHANICAL_HARVESTER = public static final BlockEntry<HarvesterBlock> MECHANICAL_HARVESTER =
REGISTRATE.block("mechanical_harvester", HarvesterBlock::new) REGISTRATE.block("mechanical_harvester", HarvesterBlock::new)
.initialProperties(SharedProperties::stone) .initialProperties(SharedProperties::stone)
.properties(p -> p.mapColor(MapColor.METAL)) .properties(p -> p.mapColor(MapColor.METAL).forceSolidOn())
.transform(axeOrPickaxe()) .transform(axeOrPickaxe())
.onRegister(movementBehaviour(new HarvesterMovementBehaviour())) .onRegister(movementBehaviour(new HarvesterMovementBehaviour()))
.blockstate(BlockStateGen.horizontalBlockProvider(true)) .blockstate(BlockStateGen.horizontalBlockProvider(true))
@ -1380,7 +1359,7 @@ public class AllBlocks {
public static final BlockEntry<PloughBlock> MECHANICAL_PLOUGH = public static final BlockEntry<PloughBlock> MECHANICAL_PLOUGH =
REGISTRATE.block("mechanical_plough", PloughBlock::new) REGISTRATE.block("mechanical_plough", PloughBlock::new)
.initialProperties(SharedProperties::stone) .initialProperties(SharedProperties::stone)
.properties(p -> p.mapColor(MapColor.COLOR_GRAY)) .properties(p -> p.mapColor(MapColor.COLOR_GRAY).forceSolidOn())
.transform(axeOrPickaxe()) .transform(axeOrPickaxe())
.onRegister(movementBehaviour(new PloughMovementBehaviour())) .onRegister(movementBehaviour(new PloughMovementBehaviour()))
.blockstate(BlockStateGen.horizontalBlockProvider(false)) .blockstate(BlockStateGen.horizontalBlockProvider(false))
@ -1405,8 +1384,8 @@ public class AllBlocks {
public static final BlockEntry<SailBlock> SAIL_FRAME = REGISTRATE.block("sail_frame", p -> SailBlock.frame(p)) public static final BlockEntry<SailBlock> SAIL_FRAME = REGISTRATE.block("sail_frame", p -> SailBlock.frame(p))
.initialProperties(SharedProperties::wooden) .initialProperties(SharedProperties::wooden)
.properties(p -> p.mapColor(MapColor.DIRT)) .properties(p -> p.mapColor(MapColor.DIRT)
.properties(p -> p.sound(SoundType.SCAFFOLDING) .sound(SoundType.SCAFFOLDING)
.noOcclusion()) .noOcclusion())
.transform(axeOnly()) .transform(axeOnly())
.blockstate(BlockStateGen.directionalBlockProvider(false)) .blockstate(BlockStateGen.directionalBlockProvider(false))
@ -1419,8 +1398,8 @@ public class AllBlocks {
public static final BlockEntry<SailBlock> SAIL = public static final BlockEntry<SailBlock> SAIL =
REGISTRATE.block("white_sail", p -> SailBlock.withCanvas(p, DyeColor.WHITE)) REGISTRATE.block("white_sail", p -> SailBlock.withCanvas(p, DyeColor.WHITE))
.initialProperties(SharedProperties::wooden) .initialProperties(SharedProperties::wooden)
.properties(p -> p.mapColor(MapColor.SNOW)) .properties(p -> p.mapColor(MapColor.SNOW)
.properties(p -> p.sound(SoundType.SCAFFOLDING) .sound(SoundType.SCAFFOLDING)
.noOcclusion()) .noOcclusion())
.transform(axeOnly()) .transform(axeOnly())
.blockstate(BlockStateGen.directionalBlockProvider(false)) .blockstate(BlockStateGen.directionalBlockProvider(false))
@ -1437,8 +1416,8 @@ public class AllBlocks {
String colourName = colour.getSerializedName(); String colourName = colour.getSerializedName();
return REGISTRATE.block(colourName + "_sail", p -> SailBlock.withCanvas(p, colour)) return REGISTRATE.block(colourName + "_sail", p -> SailBlock.withCanvas(p, colour))
.initialProperties(SharedProperties::wooden) .initialProperties(SharedProperties::wooden)
.properties(p -> p.mapColor(colour.getMapColor())) .properties(p -> p.mapColor(colour.getMapColor())
.properties(p -> p.sound(SoundType.SCAFFOLDING) .sound(SoundType.SCAFFOLDING)
.noOcclusion()) .noOcclusion())
.transform(axeOnly()) .transform(axeOnly())
.blockstate((c, p) -> p.directionalBlock(c.get(), p.models() .blockstate((c, p) -> p.directionalBlock(c.get(), p.models()
@ -1460,8 +1439,7 @@ public class AllBlocks {
.register(); .register();
public static final BlockEntry<CasingBlock> COPPER_CASING = REGISTRATE.block("copper_casing", CasingBlock::new) public static final BlockEntry<CasingBlock> COPPER_CASING = REGISTRATE.block("copper_casing", CasingBlock::new)
.properties(p -> p.mapColor(MapColor.TERRACOTTA_LIGHT_GRAY)) .properties(p -> p.mapColor(MapColor.TERRACOTTA_LIGHT_GRAY).sound(SoundType.COPPER))
.properties(p -> p.sound(SoundType.COPPER))
.transform(BuilderTransformers.casing(() -> AllSpriteShifts.COPPER_CASING)) .transform(BuilderTransformers.casing(() -> AllSpriteShifts.COPPER_CASING))
.register(); .register();
@ -1483,8 +1461,7 @@ public class AllBlocks {
public static final BlockEntry<MechanicalCrafterBlock> MECHANICAL_CRAFTER = public static final BlockEntry<MechanicalCrafterBlock> MECHANICAL_CRAFTER =
REGISTRATE.block("mechanical_crafter", MechanicalCrafterBlock::new) REGISTRATE.block("mechanical_crafter", MechanicalCrafterBlock::new)
.initialProperties(SharedProperties::softMetal) .initialProperties(SharedProperties::softMetal)
.properties(p -> p.mapColor(MapColor.TERRACOTTA_YELLOW)) .properties(p -> p.noOcclusion().mapColor(MapColor.TERRACOTTA_YELLOW))
.properties(BlockBehaviour.Properties::noOcclusion)
.transform(axeOrPickaxe()) .transform(axeOrPickaxe())
.blockstate(BlockStateGen.horizontalBlockProvider(true)) .blockstate(BlockStateGen.horizontalBlockProvider(true))
.transform(BlockStressDefaults.setImpact(2.0)) .transform(BlockStressDefaults.setImpact(2.0))
@ -1509,8 +1486,7 @@ public class AllBlocks {
public static final BlockEntry<FlywheelBlock> FLYWHEEL = REGISTRATE.block("flywheel", FlywheelBlock::new) public static final BlockEntry<FlywheelBlock> FLYWHEEL = REGISTRATE.block("flywheel", FlywheelBlock::new)
.initialProperties(SharedProperties::softMetal) .initialProperties(SharedProperties::softMetal)
.properties(p -> p.mapColor(MapColor.TERRACOTTA_YELLOW)) .properties(p -> p.noOcclusion().mapColor(MapColor.TERRACOTTA_YELLOW))
.properties(BlockBehaviour.Properties::noOcclusion)
.transform(axeOrPickaxe()) .transform(axeOrPickaxe())
.transform(BlockStressDefaults.setNoImpact()) .transform(BlockStressDefaults.setNoImpact())
.blockstate(BlockStateGen.axisBlockProvider(true)) .blockstate(BlockStateGen.axisBlockProvider(true))
@ -1551,7 +1527,8 @@ public class AllBlocks {
.properties(p -> p.mapColor(MapColor.METAL) .properties(p -> p.mapColor(MapColor.METAL)
.strength(0.8F) .strength(0.8F)
.sound(SoundType.METAL) .sound(SoundType.METAL)
.noOcclusion()) .noOcclusion()
.forceSolidOn())
.addLayer(() -> RenderType::cutoutMipped) .addLayer(() -> RenderType::cutoutMipped)
.transform(pickaxeOnly()) .transform(pickaxeOnly())
.onRegister(CreateRegistrate.blockModel(() -> TrackModel::new)) .onRegister(CreateRegistrate.blockModel(() -> TrackModel::new))
@ -1578,15 +1555,13 @@ public class AllBlocks {
public static final BlockEntry<CasingBlock> RAILWAY_CASING = REGISTRATE.block("railway_casing", CasingBlock::new) public static final BlockEntry<CasingBlock> RAILWAY_CASING = REGISTRATE.block("railway_casing", CasingBlock::new)
.transform(BuilderTransformers.layeredCasing(() -> AllSpriteShifts.RAILWAY_CASING_SIDE, .transform(BuilderTransformers.layeredCasing(() -> AllSpriteShifts.RAILWAY_CASING_SIDE,
() -> AllSpriteShifts.RAILWAY_CASING)) () -> AllSpriteShifts.RAILWAY_CASING))
.properties(p -> p.mapColor(MapColor.TERRACOTTA_CYAN)) .properties(p -> p.mapColor(MapColor.TERRACOTTA_CYAN).sound(SoundType.NETHERITE_BLOCK))
.properties(p -> p.sound(SoundType.NETHERITE_BLOCK))
.lang("Train Casing") .lang("Train Casing")
.register(); .register();
public static final BlockEntry<StationBlock> TRACK_STATION = REGISTRATE.block("track_station", StationBlock::new) public static final BlockEntry<StationBlock> TRACK_STATION = REGISTRATE.block("track_station", StationBlock::new)
.initialProperties(SharedProperties::softMetal) .initialProperties(SharedProperties::softMetal)
.properties(p -> p.mapColor(MapColor.PODZOL)) .properties(p -> p.mapColor(MapColor.PODZOL).sound(SoundType.NETHERITE_BLOCK))
.properties(p -> p.sound(SoundType.NETHERITE_BLOCK))
.transform(pickaxeOnly()) .transform(pickaxeOnly())
.blockstate((c, p) -> p.simpleBlock(c.get(), AssetLookup.partialBaseModel(c, p))) .blockstate((c, p) -> p.simpleBlock(c.get(), AssetLookup.partialBaseModel(c, p)))
.onRegister(assignDataBehaviour(new StationSummaryDisplaySource(), "station_summary")) .onRegister(assignDataBehaviour(new StationSummaryDisplaySource(), "station_summary"))
@ -1598,9 +1573,9 @@ public class AllBlocks {
public static final BlockEntry<SignalBlock> TRACK_SIGNAL = REGISTRATE.block("track_signal", SignalBlock::new) public static final BlockEntry<SignalBlock> TRACK_SIGNAL = REGISTRATE.block("track_signal", SignalBlock::new)
.initialProperties(SharedProperties::softMetal) .initialProperties(SharedProperties::softMetal)
.properties(p -> p.mapColor(MapColor.PODZOL)) .properties(p -> p.mapColor(MapColor.PODZOL)
.properties(p -> p.noOcclusion()) .noOcclusion()
.properties(p -> p.sound(SoundType.NETHERITE_BLOCK)) .sound(SoundType.NETHERITE_BLOCK))
.transform(pickaxeOnly()) .transform(pickaxeOnly())
.blockstate((c, p) -> p.getVariantBuilder(c.get()) .blockstate((c, p) -> p.getVariantBuilder(c.get())
.forAllStates(state -> ConfiguredModel.builder() .forAllStates(state -> ConfiguredModel.builder()
@ -1615,9 +1590,9 @@ public class AllBlocks {
public static final BlockEntry<TrackObserverBlock> TRACK_OBSERVER = public static final BlockEntry<TrackObserverBlock> TRACK_OBSERVER =
REGISTRATE.block("track_observer", TrackObserverBlock::new) REGISTRATE.block("track_observer", TrackObserverBlock::new)
.initialProperties(SharedProperties::softMetal) .initialProperties(SharedProperties::softMetal)
.properties(p -> p.mapColor(MapColor.PODZOL)) .properties(p -> p.mapColor(MapColor.PODZOL)
.properties(p -> p.noOcclusion()) .noOcclusion()
.properties(p -> p.sound(SoundType.NETHERITE_BLOCK)) .sound(SoundType.NETHERITE_BLOCK))
.blockstate((c, p) -> BlockStateGen.simpleBlock(c, p, AssetLookup.forPowered(c, p))) .blockstate((c, p) -> BlockStateGen.simpleBlock(c, p, AssetLookup.forPowered(c, p)))
.transform(pickaxeOnly()) .transform(pickaxeOnly())
.onRegister(assignDataBehaviour(new ObservedTrainNameSource(), "observed_train_name")) .onRegister(assignDataBehaviour(new ObservedTrainNameSource(), "observed_train_name"))
@ -1640,8 +1615,7 @@ public class AllBlocks {
public static final BlockEntry<ControlsBlock> TRAIN_CONTROLS = REGISTRATE.block("controls", ControlsBlock::new) public static final BlockEntry<ControlsBlock> TRAIN_CONTROLS = REGISTRATE.block("controls", ControlsBlock::new)
.initialProperties(SharedProperties::softMetal) .initialProperties(SharedProperties::softMetal)
.properties(p -> p.mapColor(MapColor.TERRACOTTA_BROWN)) .properties(p -> p.mapColor(MapColor.TERRACOTTA_BROWN).sound(SoundType.NETHERITE_BLOCK))
.properties(p -> p.sound(SoundType.NETHERITE_BLOCK))
.addLayer(() -> RenderType::cutoutMipped) .addLayer(() -> RenderType::cutoutMipped)
.transform(pickaxeOnly()) .transform(pickaxeOnly())
.blockstate((c, p) -> p.horizontalBlock(c.get(), .blockstate((c, p) -> p.horizontalBlock(c.get(),
@ -1656,8 +1630,7 @@ public class AllBlocks {
public static final BlockEntry<ItemVaultBlock> ITEM_VAULT = REGISTRATE.block("item_vault", ItemVaultBlock::new) public static final BlockEntry<ItemVaultBlock> ITEM_VAULT = REGISTRATE.block("item_vault", ItemVaultBlock::new)
.initialProperties(SharedProperties::softMetal) .initialProperties(SharedProperties::softMetal)
.properties(p -> p.mapColor(MapColor.TERRACOTTA_BLUE)) .properties(p -> p.mapColor(MapColor.TERRACOTTA_BLUE).sound(SoundType.NETHERITE_BLOCK)
.properties(p -> p.sound(SoundType.NETHERITE_BLOCK)
.explosionResistance(1200)) .explosionResistance(1200))
.transform(pickaxeOnly()) .transform(pickaxeOnly())
.blockstate((c, p) -> p.getVariantBuilder(c.get()) .blockstate((c, p) -> p.getVariantBuilder(c.get())
@ -1742,8 +1715,7 @@ public class AllBlocks {
public static final BlockEntry<SmartObserverBlock> SMART_OBSERVER = public static final BlockEntry<SmartObserverBlock> SMART_OBSERVER =
REGISTRATE.block("content_observer", SmartObserverBlock::new) REGISTRATE.block("content_observer", SmartObserverBlock::new)
.initialProperties(SharedProperties::stone) .initialProperties(SharedProperties::stone)
.properties(p -> p.mapColor(MapColor.TERRACOTTA_BROWN)) .properties(p -> p.mapColor(MapColor.TERRACOTTA_BROWN).noOcclusion())
.properties(p -> p.noOcclusion())
.transform(axeOrPickaxe()) .transform(axeOrPickaxe())
.blockstate(new SmartObserverGenerator()::generate) .blockstate(new SmartObserverGenerator()::generate)
.onRegister(assignDataBehaviour(new ItemCountDisplaySource(), "count_items")) .onRegister(assignDataBehaviour(new ItemCountDisplaySource(), "count_items"))
@ -1758,8 +1730,7 @@ public class AllBlocks {
public static final BlockEntry<ThresholdSwitchBlock> THRESHOLD_SWITCH = public static final BlockEntry<ThresholdSwitchBlock> THRESHOLD_SWITCH =
REGISTRATE.block("stockpile_switch", ThresholdSwitchBlock::new) REGISTRATE.block("stockpile_switch", ThresholdSwitchBlock::new)
.initialProperties(SharedProperties::stone) .initialProperties(SharedProperties::stone)
.properties(p -> p.mapColor(MapColor.TERRACOTTA_BROWN)) .properties(p -> p.mapColor(MapColor.TERRACOTTA_BROWN).noOcclusion())
.properties(p -> p.noOcclusion())
.transform(axeOrPickaxe()) .transform(axeOrPickaxe())
.blockstate(new ThresholdSwitchGenerator()::generate) .blockstate(new ThresholdSwitchGenerator()::generate)
.onRegister(assignDataBehaviour(new FillLevelDisplaySource(), "fill_level")) .onRegister(assignDataBehaviour(new FillLevelDisplaySource(), "fill_level"))
@ -1802,8 +1773,7 @@ public class AllBlocks {
public static final BlockEntry<NixieTubeBlock> ORANGE_NIXIE_TUBE = public static final BlockEntry<NixieTubeBlock> ORANGE_NIXIE_TUBE =
REGISTRATE.block("nixie_tube", p -> new NixieTubeBlock(p, DyeColor.ORANGE)) REGISTRATE.block("nixie_tube", p -> new NixieTubeBlock(p, DyeColor.ORANGE))
.initialProperties(SharedProperties::softMetal) .initialProperties(SharedProperties::softMetal)
.properties(p -> p.lightLevel($ -> 5)) .properties(p -> p.lightLevel($ -> 5).mapColor(DyeColor.ORANGE).forceSolidOn())
.properties(p -> p.mapColor(DyeColor.ORANGE))
.transform(pickaxeOnly()) .transform(pickaxeOnly())
.blockstate(new NixieTubeGenerator()::generate) .blockstate(new NixieTubeGenerator()::generate)
.addLayer(() -> RenderType::translucent) .addLayer(() -> RenderType::translucent)
@ -1817,8 +1787,7 @@ public class AllBlocks {
String colourName = colour.getSerializedName(); String colourName = colour.getSerializedName();
return REGISTRATE.block(colourName + "_nixie_tube", p -> new NixieTubeBlock(p, colour)) return REGISTRATE.block(colourName + "_nixie_tube", p -> new NixieTubeBlock(p, colour))
.initialProperties(SharedProperties::softMetal) .initialProperties(SharedProperties::softMetal)
.properties(p -> p.mapColor(colour)) .properties(p -> p.lightLevel($ -> 5).mapColor(colour).forceSolidOn())
.properties(p -> p.lightLevel($ -> 5))
.transform(pickaxeOnly()) .transform(pickaxeOnly())
.blockstate(new NixieTubeGenerator()::generate) .blockstate(new NixieTubeGenerator()::generate)
.loot((p, b) -> p.dropOther(b, ORANGE_NIXIE_TUBE.get())) .loot((p, b) -> p.dropOther(b, ORANGE_NIXIE_TUBE.get()))
@ -1844,7 +1813,7 @@ public class AllBlocks {
public static final BlockEntry<RedstoneLinkBlock> REDSTONE_LINK = public static final BlockEntry<RedstoneLinkBlock> REDSTONE_LINK =
REGISTRATE.block("redstone_link", RedstoneLinkBlock::new) REGISTRATE.block("redstone_link", RedstoneLinkBlock::new)
.initialProperties(SharedProperties::wooden) .initialProperties(SharedProperties::wooden)
.properties(p -> p.mapColor(MapColor.TERRACOTTA_BROWN)) .properties(p -> p.mapColor(MapColor.TERRACOTTA_BROWN).forceSolidOn())
.transform(axeOrPickaxe()) .transform(axeOrPickaxe())
.tag(AllBlockTags.BRITTLE.tag, AllBlockTags.SAFE_NBT.tag) .tag(AllBlockTags.BRITTLE.tag, AllBlockTags.SAFE_NBT.tag)
.blockstate(new RedstoneLinkGenerator()::generate) .blockstate(new RedstoneLinkGenerator()::generate)
@ -1866,6 +1835,7 @@ public class AllBlocks {
public static final BlockEntry<PlacardBlock> PLACARD = REGISTRATE.block("placard", PlacardBlock::new) public static final BlockEntry<PlacardBlock> PLACARD = REGISTRATE.block("placard", PlacardBlock::new)
.initialProperties(SharedProperties::copperMetal) .initialProperties(SharedProperties::copperMetal)
.properties(p -> p.forceSolidOn())
.transform(pickaxeOnly()) .transform(pickaxeOnly())
.blockstate((c, p) -> p.horizontalFaceBlock(c.get(), AssetLookup.standardModel(c, p))) .blockstate((c, p) -> p.horizontalFaceBlock(c.get(), AssetLookup.standardModel(c, p)))
.simpleItem() .simpleItem()
@ -1935,14 +1905,14 @@ public class AllBlocks {
public static final BlockEntry<PeculiarBellBlock> PECULIAR_BELL = public static final BlockEntry<PeculiarBellBlock> PECULIAR_BELL =
REGISTRATE.block("peculiar_bell", PeculiarBellBlock::new) REGISTRATE.block("peculiar_bell", PeculiarBellBlock::new)
.properties(p -> p.mapColor(MapColor.GOLD)) .properties(p -> p.mapColor(MapColor.GOLD).forceSolidOn())
.transform(BuilderTransformers.bell()) .transform(BuilderTransformers.bell())
.onRegister(movementBehaviour(new BellMovementBehaviour())) .onRegister(movementBehaviour(new BellMovementBehaviour()))
.register(); .register();
public static final BlockEntry<HauntedBellBlock> HAUNTED_BELL = public static final BlockEntry<HauntedBellBlock> HAUNTED_BELL =
REGISTRATE.block("haunted_bell", HauntedBellBlock::new) REGISTRATE.block("haunted_bell", HauntedBellBlock::new)
.properties(p -> p.mapColor(MapColor.SAND)) .properties(p -> p.mapColor(MapColor.SAND).forceSolidOn())
.transform(BuilderTransformers.bell()) .transform(BuilderTransformers.bell())
.onRegister(movementBehaviour(new HauntedBellMovementBehaviour())) .onRegister(movementBehaviour(new HauntedBellMovementBehaviour()))
.register(); .register();
@ -1951,8 +1921,7 @@ public class AllBlocks {
String colourName = colour.getSerializedName(); String colourName = colour.getSerializedName();
return REGISTRATE.block(colourName + "_toolbox", p -> new ToolboxBlock(p, colour)) return REGISTRATE.block(colourName + "_toolbox", p -> new ToolboxBlock(p, colour))
.initialProperties(SharedProperties::wooden) .initialProperties(SharedProperties::wooden)
.properties(p -> p.sound(SoundType.WOOD)) .properties(p -> p.sound(SoundType.WOOD).mapColor(colour).forceSolidOn())
.properties(p -> p.mapColor(colour))
.addLayer(() -> RenderType::cutoutMipped) .addLayer(() -> RenderType::cutoutMipped)
.loot((lt, block) -> { .loot((lt, block) -> {
Builder builder = LootTable.lootTable(); Builder builder = LootTable.lootTable();
@ -1984,6 +1953,7 @@ public class AllBlocks {
public static final BlockEntry<ClipboardBlock> CLIPBOARD = REGISTRATE.block("clipboard", ClipboardBlock::new) public static final BlockEntry<ClipboardBlock> CLIPBOARD = REGISTRATE.block("clipboard", ClipboardBlock::new)
.initialProperties(SharedProperties::wooden) .initialProperties(SharedProperties::wooden)
.properties(p -> p.forceSolidOn())
.transform(axeOrPickaxe()) .transform(axeOrPickaxe())
.tag(AllBlockTags.SAFE_NBT.tag) .tag(AllBlockTags.SAFE_NBT.tag)
.blockstate((c, p) -> p.horizontalFaceBlock(c.get(), .blockstate((c, p) -> p.horizontalFaceBlock(c.get(),
@ -1996,8 +1966,10 @@ public class AllBlocks {
.register(); .register();
// Materials // Materials
static { REGISTRATE.useCreativeTab(AllCreativeModeTabs.BUILDING_BLOCKS_TAB); } static {
REGISTRATE.setCreativeTab(AllCreativeModeTabs.PALETTES_CREATIVE_TAB);
}
public static final BlockEntry<MetalLadderBlock> ANDESITE_LADDER = public static final BlockEntry<MetalLadderBlock> ANDESITE_LADDER =
REGISTRATE.block("andesite_ladder", MetalLadderBlock::new) REGISTRATE.block("andesite_ladder", MetalLadderBlock::new)
@ -2047,10 +2019,9 @@ public class AllBlocks {
public static final BlockEntry<GirderBlock> METAL_GIRDER = REGISTRATE.block("metal_girder", GirderBlock::new) public static final BlockEntry<GirderBlock> METAL_GIRDER = REGISTRATE.block("metal_girder", GirderBlock::new)
.initialProperties(SharedProperties::softMetal) .initialProperties(SharedProperties::softMetal)
.blockstate(GirderBlockStateGenerator::blockState) .properties(p -> p.mapColor(MapColor.COLOR_GRAY).sound(SoundType.NETHERITE_BLOCK))
.properties(p -> p.mapColor(MapColor.COLOR_GRAY))
.properties(p -> p.sound(SoundType.NETHERITE_BLOCK))
.transform(pickaxeOnly()) .transform(pickaxeOnly())
.blockstate(GirderBlockStateGenerator::blockState)
.onRegister(CreateRegistrate.blockModel(() -> ConnectedGirderModel::new)) .onRegister(CreateRegistrate.blockModel(() -> ConnectedGirderModel::new))
.item() .item()
.transform(customItemModel()) .transform(customItemModel())
@ -2059,10 +2030,9 @@ public class AllBlocks {
public static final BlockEntry<GirderEncasedShaftBlock> METAL_GIRDER_ENCASED_SHAFT = public static final BlockEntry<GirderEncasedShaftBlock> METAL_GIRDER_ENCASED_SHAFT =
REGISTRATE.block("metal_girder_encased_shaft", GirderEncasedShaftBlock::new) REGISTRATE.block("metal_girder_encased_shaft", GirderEncasedShaftBlock::new)
.initialProperties(SharedProperties::softMetal) .initialProperties(SharedProperties::softMetal)
.blockstate(GirderBlockStateGenerator::blockStateWithShaft) .properties(p -> p.mapColor(MapColor.COLOR_GRAY).sound(SoundType.NETHERITE_BLOCK))
.properties(p -> p.mapColor(MapColor.COLOR_GRAY))
.properties(p -> p.sound(SoundType.NETHERITE_BLOCK))
.transform(pickaxeOnly()) .transform(pickaxeOnly())
.blockstate(GirderBlockStateGenerator::blockStateWithShaft)
.loot((p, b) -> p.add(b, p.createSingleItemTable(METAL_GIRDER.get()) .loot((p, b) -> p.add(b, p.createSingleItemTable(METAL_GIRDER.get())
.withPool(p.applyExplosionCondition(SHAFT.get(), LootPool.lootPool() .withPool(p.applyExplosionCondition(SHAFT.get(), LootPool.lootPool()
.setRolls(ConstantValue.exactly(1.0F)) .setRolls(ConstantValue.exactly(1.0F))
@ -2081,6 +2051,7 @@ public class AllBlocks {
public static final BlockEntry<CopycatStepBlock> COPYCAT_STEP = public static final BlockEntry<CopycatStepBlock> COPYCAT_STEP =
REGISTRATE.block("copycat_step", CopycatStepBlock::new) REGISTRATE.block("copycat_step", CopycatStepBlock::new)
.properties(p -> p.forceSolidOn())
.transform(BuilderTransformers.copycat()) .transform(BuilderTransformers.copycat())
.onRegister(CreateRegistrate.blockModel(() -> CopycatStepModel::new)) .onRegister(CreateRegistrate.blockModel(() -> CopycatStepModel::new))
.item() .item()
@ -2203,8 +2174,8 @@ public class AllBlocks {
public static final BlockEntry<Block> ZINC_ORE = REGISTRATE.block("zinc_ore", Block::new) public static final BlockEntry<Block> ZINC_ORE = REGISTRATE.block("zinc_ore", Block::new)
.initialProperties(() -> Blocks.GOLD_ORE) .initialProperties(() -> Blocks.GOLD_ORE)
.properties(p -> p.mapColor(MapColor.METAL)) .properties(p -> p.mapColor(MapColor.METAL)
.properties(p -> p.requiresCorrectToolForDrops() .requiresCorrectToolForDrops()
.sound(SoundType.STONE)) .sound(SoundType.STONE))
.transform(pickaxeOnly()) .transform(pickaxeOnly())
.loot((lt, b) -> lt.add(b, .loot((lt, b) -> lt.add(b,
@ -2220,8 +2191,8 @@ public class AllBlocks {
public static final BlockEntry<Block> DEEPSLATE_ZINC_ORE = REGISTRATE.block("deepslate_zinc_ore", Block::new) public static final BlockEntry<Block> DEEPSLATE_ZINC_ORE = REGISTRATE.block("deepslate_zinc_ore", Block::new)
.initialProperties(() -> Blocks.DEEPSLATE_GOLD_ORE) .initialProperties(() -> Blocks.DEEPSLATE_GOLD_ORE)
.properties(p -> p.mapColor(MapColor.STONE)) .properties(p -> p.mapColor(MapColor.STONE)
.properties(p -> p.requiresCorrectToolForDrops() .requiresCorrectToolForDrops()
.sound(SoundType.DEEPSLATE)) .sound(SoundType.DEEPSLATE))
.transform(pickaxeOnly()) .transform(pickaxeOnly())
.loot((lt, b) -> lt.add(b, .loot((lt, b) -> lt.add(b,
@ -2237,8 +2208,7 @@ public class AllBlocks {
public static final BlockEntry<Block> RAW_ZINC_BLOCK = REGISTRATE.block("raw_zinc_block", Block::new) public static final BlockEntry<Block> RAW_ZINC_BLOCK = REGISTRATE.block("raw_zinc_block", Block::new)
.initialProperties(() -> Blocks.RAW_GOLD_BLOCK) .initialProperties(() -> Blocks.RAW_GOLD_BLOCK)
.properties(p -> p.mapColor(MapColor.GLOW_LICHEN)) .properties(p -> p.mapColor(MapColor.GLOW_LICHEN).requiresCorrectToolForDrops())
.properties(p -> p.requiresCorrectToolForDrops())
.transform(pickaxeOnly()) .transform(pickaxeOnly())
.tag(Tags.Blocks.STORAGE_BLOCKS) .tag(Tags.Blocks.STORAGE_BLOCKS)
.tag(BlockTags.NEEDS_IRON_TOOL) .tag(BlockTags.NEEDS_IRON_TOOL)
@ -2250,8 +2220,7 @@ public class AllBlocks {
public static final BlockEntry<Block> ZINC_BLOCK = REGISTRATE.block("zinc_block", Block::new) public static final BlockEntry<Block> ZINC_BLOCK = REGISTRATE.block("zinc_block", Block::new)
.initialProperties(() -> Blocks.IRON_BLOCK) .initialProperties(() -> Blocks.IRON_BLOCK)
.properties(p -> p.mapColor(MapColor.GLOW_LICHEN)) .properties(p -> p.mapColor(MapColor.GLOW_LICHEN).requiresCorrectToolForDrops())
.properties(p -> p.requiresCorrectToolForDrops())
.transform(pickaxeOnly()) .transform(pickaxeOnly())
.tag(BlockTags.NEEDS_IRON_TOOL) .tag(BlockTags.NEEDS_IRON_TOOL)
.tag(Tags.Blocks.STORAGE_BLOCKS) .tag(Tags.Blocks.STORAGE_BLOCKS)
@ -2264,8 +2233,7 @@ public class AllBlocks {
public static final BlockEntry<Block> ANDESITE_ALLOY_BLOCK = REGISTRATE.block("andesite_alloy_block", Block::new) public static final BlockEntry<Block> ANDESITE_ALLOY_BLOCK = REGISTRATE.block("andesite_alloy_block", Block::new)
.initialProperties(() -> Blocks.ANDESITE) .initialProperties(() -> Blocks.ANDESITE)
.properties(p -> p.mapColor(MapColor.STONE)) .properties(p -> p.mapColor(MapColor.STONE).requiresCorrectToolForDrops())
.properties(p -> p.requiresCorrectToolForDrops())
.transform(pickaxeOnly()) .transform(pickaxeOnly())
.blockstate(simpleCubeAll("andesite_block")) .blockstate(simpleCubeAll("andesite_block"))
.tag(Tags.Blocks.STORAGE_BLOCKS) .tag(Tags.Blocks.STORAGE_BLOCKS)
@ -2277,9 +2245,9 @@ public class AllBlocks {
public static final BlockEntry<Block> INDUSTRIAL_IRON_BLOCK = REGISTRATE.block("industrial_iron_block", Block::new) public static final BlockEntry<Block> INDUSTRIAL_IRON_BLOCK = REGISTRATE.block("industrial_iron_block", Block::new)
.initialProperties(SharedProperties::softMetal) .initialProperties(SharedProperties::softMetal)
.properties(p -> p.mapColor(MapColor.COLOR_GRAY)) .properties(p -> p.mapColor(MapColor.COLOR_GRAY)
.properties(p -> p.sound(SoundType.NETHERITE_BLOCK)) .sound(SoundType.NETHERITE_BLOCK)
.properties(p -> p.requiresCorrectToolForDrops()) .requiresCorrectToolForDrops())
.transform(pickaxeOnly()) .transform(pickaxeOnly())
.blockstate((c, p) -> p.simpleBlock(c.get(), p.models() .blockstate((c, p) -> p.simpleBlock(c.get(), p.models()
.cubeColumn(c.getName(), p.modLoc("block/industrial_iron_block"), .cubeColumn(c.getName(), p.modLoc("block/industrial_iron_block"),
@ -2293,8 +2261,7 @@ public class AllBlocks {
public static final BlockEntry<Block> BRASS_BLOCK = REGISTRATE.block("brass_block", Block::new) public static final BlockEntry<Block> BRASS_BLOCK = REGISTRATE.block("brass_block", Block::new)
.initialProperties(() -> Blocks.IRON_BLOCK) .initialProperties(() -> Blocks.IRON_BLOCK)
.properties(p -> p.mapColor(MapColor.TERRACOTTA_YELLOW)) .properties(p -> p.mapColor(MapColor.TERRACOTTA_YELLOW).requiresCorrectToolForDrops())
.properties(p -> p.requiresCorrectToolForDrops())
.transform(pickaxeOnly()) .transform(pickaxeOnly())
.blockstate(simpleCubeAll("brass_block")) .blockstate(simpleCubeAll("brass_block"))
.tag(BlockTags.NEEDS_IRON_TOOL) .tag(BlockTags.NEEDS_IRON_TOOL)
@ -2309,12 +2276,12 @@ public class AllBlocks {
public static final BlockEntry<ExperienceBlock> EXPERIENCE_BLOCK = public static final BlockEntry<ExperienceBlock> EXPERIENCE_BLOCK =
REGISTRATE.block("experience_block", ExperienceBlock::new) REGISTRATE.block("experience_block", ExperienceBlock::new)
.initialProperties(SharedProperties::softMetal) .initialProperties(SharedProperties::softMetal)
.properties(p -> p.mapColor(MapColor.PLANT)) .properties(p -> p.mapColor(MapColor.PLANT)
.properties(p -> p.sound(new ForgeSoundType(1, .5f, () -> SoundEvents.AMETHYST_BLOCK_BREAK, .sound(new ForgeSoundType(1, .5f, () -> SoundEvents.AMETHYST_BLOCK_BREAK,
() -> SoundEvents.AMETHYST_BLOCK_STEP, () -> SoundEvents.AMETHYST_BLOCK_PLACE, () -> SoundEvents.AMETHYST_BLOCK_STEP, () -> SoundEvents.AMETHYST_BLOCK_PLACE,
() -> SoundEvents.AMETHYST_BLOCK_HIT, () -> SoundEvents.AMETHYST_BLOCK_FALL))) () -> SoundEvents.AMETHYST_BLOCK_HIT, () -> SoundEvents.AMETHYST_BLOCK_FALL))
.properties(p -> p.requiresCorrectToolForDrops()) .requiresCorrectToolForDrops()
.properties(p -> p.lightLevel(s -> 15)) .lightLevel(s -> 15))
.blockstate((c, p) -> p.simpleBlock(c.get(), AssetLookup.standardModel(c, p))) .blockstate((c, p) -> p.simpleBlock(c.get(), AssetLookup.standardModel(c, p)))
.transform(pickaxeOnly()) .transform(pickaxeOnly())
.lang("Block of Experience") .lang("Block of Experience")
@ -2343,8 +2310,7 @@ public class AllBlocks {
public static final BlockEntry<Block> ROSE_QUARTZ_TILES = REGISTRATE.block("rose_quartz_tiles", Block::new) public static final BlockEntry<Block> ROSE_QUARTZ_TILES = REGISTRATE.block("rose_quartz_tiles", Block::new)
.initialProperties(() -> Blocks.DEEPSLATE) .initialProperties(() -> Blocks.DEEPSLATE)
.properties(p -> p.mapColor(MapColor.TERRACOTTA_PINK)) .properties(p -> p.mapColor(MapColor.TERRACOTTA_PINK).requiresCorrectToolForDrops())
.properties(p -> p.requiresCorrectToolForDrops())
.transform(pickaxeOnly()) .transform(pickaxeOnly())
.blockstate(simpleCubeAll("palettes/rose_quartz_tiles")) .blockstate(simpleCubeAll("palettes/rose_quartz_tiles"))
.recipe((c, p) -> p.stonecutting(DataIngredient.items(AllItems.POLISHED_ROSE_QUARTZ.get()), .recipe((c, p) -> p.stonecutting(DataIngredient.items(AllItems.POLISHED_ROSE_QUARTZ.get()),
@ -2355,8 +2321,7 @@ public class AllBlocks {
public static final BlockEntry<Block> SMALL_ROSE_QUARTZ_TILES = public static final BlockEntry<Block> SMALL_ROSE_QUARTZ_TILES =
REGISTRATE.block("small_rose_quartz_tiles", Block::new) REGISTRATE.block("small_rose_quartz_tiles", Block::new)
.initialProperties(() -> Blocks.DEEPSLATE) .initialProperties(() -> Blocks.DEEPSLATE)
.properties(p -> p.mapColor(MapColor.TERRACOTTA_PINK)) .properties(p -> p.mapColor(MapColor.TERRACOTTA_PINK).requiresCorrectToolForDrops())
.properties(p -> p.requiresCorrectToolForDrops())
.transform(pickaxeOnly()) .transform(pickaxeOnly())
.blockstate(simpleCubeAll("palettes/small_rose_quartz_tiles")) .blockstate(simpleCubeAll("palettes/small_rose_quartz_tiles"))
.recipe((c, p) -> p.stonecutting(DataIngredient.items(AllItems.POLISHED_ROSE_QUARTZ.get()), .recipe((c, p) -> p.stonecutting(DataIngredient.items(AllItems.POLISHED_ROSE_QUARTZ.get()),

View file

@ -7,13 +7,14 @@ import java.util.Set;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Predicate; import java.util.function.Predicate;
import org.apache.commons.lang3.mutable.MutableBoolean; import org.apache.commons.lang3.mutable.MutableObject;
import com.simibubi.create.content.contraptions.actors.seat.SeatBlock; import com.simibubi.create.content.contraptions.actors.seat.SeatBlock;
import com.simibubi.create.content.decoration.palettes.AllPaletteBlocks; import com.simibubi.create.content.decoration.palettes.AllPaletteBlocks;
import com.simibubi.create.content.equipment.armor.BacktankUtil; import com.simibubi.create.content.equipment.armor.BacktankUtil;
import com.simibubi.create.content.equipment.toolbox.ToolboxBlock; import com.simibubi.create.content.equipment.toolbox.ToolboxBlock;
import com.simibubi.create.content.kinetics.crank.ValveHandleBlock; import com.simibubi.create.content.kinetics.crank.ValveHandleBlock;
import com.simibubi.create.foundation.data.CreateRegistrate;
import com.simibubi.create.foundation.item.TagDependentIngredientItem; import com.simibubi.create.foundation.item.TagDependentIngredientItem;
import com.tterrag.registrate.util.entry.BlockEntry; import com.tterrag.registrate.util.entry.BlockEntry;
import com.tterrag.registrate.util.entry.ItemEntry; import com.tterrag.registrate.util.entry.ItemEntry;
@ -25,11 +26,11 @@ import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap;
import it.unimi.dsi.fastutil.objects.ReferenceArrayList; import it.unimi.dsi.fastutil.objects.ReferenceArrayList;
import it.unimi.dsi.fastutil.objects.ReferenceLinkedOpenHashSet; import it.unimi.dsi.fastutil.objects.ReferenceLinkedOpenHashSet;
import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet;
import net.createmod.catnip.utility.lang.Components;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.entity.ItemRenderer; import net.minecraft.client.renderer.entity.ItemRenderer;
import net.minecraft.client.resources.model.BakedModel; import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.core.registries.Registries; import net.minecraft.core.registries.Registries;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.CreativeModeTab.DisplayItemsGenerator; import net.minecraft.world.item.CreativeModeTab.DisplayItemsGenerator;
@ -53,45 +54,63 @@ import net.minecraftforge.registries.RegistryObject;
@EventBusSubscriber(bus = Bus.MOD) @EventBusSubscriber(bus = Bus.MOD)
public class AllCreativeModeTabs { public class AllCreativeModeTabs {
private static final DeferredRegister<CreativeModeTab> REGISTER =
private static final DeferredRegister<CreativeModeTab> TAB_REGISTER =
DeferredRegister.create(Registries.CREATIVE_MODE_TAB, Create.ID); DeferredRegister.create(Registries.CREATIVE_MODE_TAB, Create.ID);
public static final RegistryObject<CreativeModeTab> MAIN_TAB = TAB_REGISTER.register("base", public static final RegistryObject<CreativeModeTab> BASE_CREATIVE_TAB = REGISTER.register("base",
() -> CreativeModeTab.builder() () -> CreativeModeTab.builder()
.title(Component.translatable("itemGroup.create.base")) .title(Components.translatable("itemGroup.create.base"))
.withTabsBefore(CreativeModeTabs.SPAWN_EGGS) .withTabsBefore(CreativeModeTabs.SPAWN_EGGS)
.icon(() -> AllBlocks.COGWHEEL.asStack()) .icon(() -> AllBlocks.COGWHEEL.asStack())
.displayItems(new RegistrateDisplayItemsGenerator(true)) .displayItems(new RegistrateDisplayItemsGenerator(true, AllCreativeModeTabs.BASE_CREATIVE_TAB))
.build()); .build());
public static final RegistryObject<CreativeModeTab> BUILDING_BLOCKS_TAB = TAB_REGISTER.register("palettes", public static final RegistryObject<CreativeModeTab> PALETTES_CREATIVE_TAB = REGISTER.register("palettes",
() -> CreativeModeTab.builder() () -> CreativeModeTab.builder()
.title(Component.translatable("itemGroup.create.palettes")) .title(Components.translatable("itemGroup.create.palettes"))
.withTabsBefore(MAIN_TAB.getKey()) .withTabsBefore(BASE_CREATIVE_TAB.getKey())
.icon(() -> AllPaletteBlocks.ORNATE_IRON_WINDOW.asStack()) .icon(() -> AllPaletteBlocks.ORNATE_IRON_WINDOW.asStack())
.displayItems(new RegistrateDisplayItemsGenerator(false)) .displayItems(new RegistrateDisplayItemsGenerator(false, AllCreativeModeTabs.PALETTES_CREATIVE_TAB))
.build()); .build());
public static void register(IEventBus modEventBus) { public static void register(IEventBus modEventBus) {
TAB_REGISTER.register(modEventBus); REGISTER.register(modEventBus);
} }
public static CreativeModeTab getBaseTab() { private static class RegistrateDisplayItemsGenerator implements DisplayItemsGenerator {
return MAIN_TAB.get(); private static final Predicate<Item> IS_ITEM_3D_PREDICATE;
}
public static CreativeModeTab getPalettesTab() { static {
return BUILDING_BLOCKS_TAB.get(); MutableObject<Predicate<Item>> isItem3d = new MutableObject<>(item -> false);
} DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> {
isItem3d.setValue(item -> {
public static class RegistrateDisplayItemsGenerator implements DisplayItemsGenerator { ItemRenderer itemRenderer = Minecraft.getInstance()
.getItemRenderer();
private final boolean mainTab; BakedModel model = itemRenderer.getModel(new ItemStack(item), null, null, 0);
return model.isGui3d();
public RegistrateDisplayItemsGenerator(boolean mainTab) { });
this.mainTab = mainTab; });
IS_ITEM_3D_PREDICATE = isItem3d.getValue();
} }
@OnlyIn(Dist.CLIENT)
private static Predicate<Item> makeClient3dItemPredicate() {
return item -> {
ItemRenderer itemRenderer = Minecraft.getInstance()
.getItemRenderer();
BakedModel model = itemRenderer.getModel(new ItemStack(item), null, null, 0);
return model.isGui3d();
};
}
private final boolean addItems;
private final RegistryObject<CreativeModeTab> tabFilter;
public RegistrateDisplayItemsGenerator(boolean addItems, RegistryObject<CreativeModeTab> tabFilter) {
this.addItems = addItems;
this.tabFilter = tabFilter;
}
private static Predicate<Item> makeExclusionPredicate() { private static Predicate<Item> makeExclusionPredicate() {
Set<Item> exclusions = new ReferenceOpenHashSet<>(); Set<Item> exclusions = new ReferenceOpenHashSet<>();
@ -145,22 +164,6 @@ public class AllCreativeModeTabs {
return exclusions::contains; return exclusions::contains;
} }
private static Predicate<Item> make3DPredicate(boolean model3d) {
return item -> {
MutableBoolean result = new MutableBoolean(false);
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> result.setValue(isItem3d(item) == model3d));
return result.getValue();
};
}
@OnlyIn(Dist.CLIENT)
private static boolean isItem3d(Item item) {
ItemRenderer itemRenderer = Minecraft.getInstance()
.getItemRenderer();
BakedModel model = itemRenderer.getModel(new ItemStack(item), null, null, 0);
return model.isGui3d();
}
private static List<ItemOrdering> makeOrderings() { private static List<ItemOrdering> makeOrderings() {
List<ItemOrdering> orderings = new ReferenceArrayList<>(); List<ItemOrdering> orderings = new ReferenceArrayList<>();
@ -253,26 +256,29 @@ public class AllCreativeModeTabs {
} }
@Override @Override
public void accept(ItemDisplayParameters pParameters, Output output) { public void accept(ItemDisplayParameters parameters, Output output) {
Predicate<Item> exclusionPredicate = makeExclusionPredicate(); Predicate<Item> exclusionPredicate = makeExclusionPredicate();
List<ItemOrdering> orderings = makeOrderings(); List<ItemOrdering> orderings = makeOrderings();
Function<Item, ItemStack> stackFunc = makeStackFunc(); Function<Item, ItemStack> stackFunc = makeStackFunc();
Function<Item, TabVisibility> visibilityFunc = makeVisibilityFunc(); Function<Item, TabVisibility> visibilityFunc = makeVisibilityFunc();
RegistryObject<CreativeModeTab> tab = mainTab ? MAIN_TAB : BUILDING_BLOCKS_TAB;
List<Item> items = new LinkedList<>(); List<Item> items = new LinkedList<>();
items.addAll(collectItems(tab, exclusionPredicate.or(make3DPredicate(false)))); if (addItems) {
items.addAll(collectBlocks(tab, exclusionPredicate)); items.addAll(collectItems(exclusionPredicate.or(IS_ITEM_3D_PREDICATE.negate())));
items.addAll(collectItems(tab, exclusionPredicate.or(make3DPredicate(true)))); }
items.addAll(collectBlocks(exclusionPredicate));
if (addItems) {
items.addAll(collectItems(exclusionPredicate.or(IS_ITEM_3D_PREDICATE)));
}
applyOrderings(items, orderings); applyOrderings(items, orderings);
outputAll(output, items, stackFunc, visibilityFunc); outputAll(output, items, stackFunc, visibilityFunc);
} }
private List<Item> collectBlocks(RegistryObject<CreativeModeTab> tab, Predicate<Item> exclusionPredicate) { private List<Item> collectBlocks(Predicate<Item> exclusionPredicate) {
List<Item> items = new ReferenceArrayList<>(); List<Item> items = new ReferenceArrayList<>();
for (RegistryEntry<Block> entry : Create.REGISTRATE.getAll(Registries.BLOCK)) { for (RegistryEntry<Block> entry : Create.REGISTRATE.getAll(Registries.BLOCK)) {
if (!Create.REGISTRATE.isInCreativeTab(entry, tab)) if (!CreateRegistrate.isInCreativeTab(entry, tabFilter))
continue; continue;
Item item = entry.get() Item item = entry.get()
.asItem(); .asItem();
@ -285,14 +291,10 @@ public class AllCreativeModeTabs {
return items; return items;
} }
private List<Item> collectItems(RegistryObject<CreativeModeTab> tab, Predicate<Item> exclusionPredicate) { private List<Item> collectItems(Predicate<Item> exclusionPredicate) {
List<Item> items = new ReferenceArrayList<>(); List<Item> items = new ReferenceArrayList<>();
if (!mainTab)
return items;
for (RegistryEntry<Item> entry : Create.REGISTRATE.getAll(Registries.ITEM)) { for (RegistryEntry<Item> entry : Create.REGISTRATE.getAll(Registries.ITEM)) {
if (!Create.REGISTRATE.isInCreativeTab(entry, tab)) if (!CreateRegistrate.isInCreativeTab(entry, tabFilter))
continue; continue;
Item item = entry.get(); Item item = entry.get();
if (item instanceof BlockItem) if (item instanceof BlockItem)
@ -345,4 +347,4 @@ public class AllCreativeModeTabs {
} }
} }
} }
} }

View file

@ -66,8 +66,10 @@ import net.minecraft.world.item.Rarity;
import net.minecraftforge.common.Tags; import net.minecraftforge.common.Tags;
public class AllItems { public class AllItems {
static { REGISTRATE.useCreativeTab(AllCreativeModeTabs.MAIN_TAB); } static {
REGISTRATE.setCreativeTab(AllCreativeModeTabs.BASE_CREATIVE_TAB);
}
public static final ItemEntry<Item> WHEAT_FLOUR = public static final ItemEntry<Item> WHEAT_FLOUR =
taggedIngredient("wheat_flour", forgeItemTag("flour/wheat"), forgeItemTag("flour")), taggedIngredient("wheat_flour", forgeItemTag("flour/wheat"), forgeItemTag("flour")),

View file

@ -91,6 +91,7 @@ import com.simibubi.create.foundation.networking.SimplePacketBase;
import com.simibubi.create.foundation.utility.ServerSpeedProvider; import com.simibubi.create.foundation.utility.ServerSpeedProvider;
import com.simibubi.create.infrastructure.command.HighlightPacket; import com.simibubi.create.infrastructure.command.HighlightPacket;
import com.simibubi.create.infrastructure.command.SimpleCreateActions; import com.simibubi.create.infrastructure.command.SimpleCreateActions;
import com.simibubi.create.infrastructure.debugInfo.ServerDebugInfoPacket;
import net.createmod.catnip.net.ClientboundSimpleActionPacket; import net.createmod.catnip.net.ClientboundSimpleActionPacket;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@ -205,7 +206,7 @@ public enum AllPackets {
CONTRAPTION_ACTOR_TOGGLE(ContraptionDisableActorPacket.class, ContraptionDisableActorPacket::new, PLAY_TO_CLIENT), CONTRAPTION_ACTOR_TOGGLE(ContraptionDisableActorPacket.class, ContraptionDisableActorPacket::new, PLAY_TO_CLIENT),
CONTRAPTION_COLLIDER_LOCK(ContraptionColliderLockPacket.class, ContraptionColliderLockPacket::new, PLAY_TO_CLIENT), CONTRAPTION_COLLIDER_LOCK(ContraptionColliderLockPacket.class, ContraptionColliderLockPacket::new, PLAY_TO_CLIENT),
ATTACHED_COMPUTER(AttachedComputerPacket.class, AttachedComputerPacket::new, PLAY_TO_CLIENT), ATTACHED_COMPUTER(AttachedComputerPacket.class, AttachedComputerPacket::new, PLAY_TO_CLIENT),
SERVER_DEBUG_INFO(ServerDebugInfoPacket.class, ServerDebugInfoPacket::new, PLAY_TO_CLIENT)
; ;
static { static {

View file

@ -6,6 +6,7 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.function.BiConsumer;
import java.util.function.Supplier; import java.util.function.Supplier;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
@ -319,12 +320,10 @@ public class AllSoundEvents {
}); });
} }
public static JsonObject provideLangEntries() { public static void provideLang(BiConsumer<String, String> consumer) {
JsonObject object = new JsonObject();
for (SoundEntry entry : ALL.values()) for (SoundEntry entry : ALL.values())
if (entry.hasSubtitle()) if (entry.hasSubtitle())
object.addProperty(entry.getSubtitleKey(), entry.getSubtitle()); consumer.accept(entry.getSubtitleKey(), entry.getSubtitle());
return object;
} }
public static SoundEntryProvider provider(DataGenerator generator) { public static SoundEntryProvider provider(DataGenerator generator) {

View file

@ -78,23 +78,27 @@ public class AllTags {
BRITTLE, BRITTLE,
CASING, CASING,
CONTRAPTION_INVENTORY_DENY,
COPYCAT_ALLOW,
COPYCAT_DENY,
FAN_PROCESSING_CATALYSTS_BLASTING(MOD, "fan_processing_catalysts/blasting"),
FAN_PROCESSING_CATALYSTS_HAUNTING(MOD, "fan_processing_catalysts/haunting"),
FAN_PROCESSING_CATALYSTS_SMOKING(MOD, "fan_processing_catalysts/smoking"),
FAN_PROCESSING_CATALYSTS_SPLASHING(MOD, "fan_processing_catalysts/splashing"),
FAN_TRANSPARENT, FAN_TRANSPARENT,
NON_MOVABLE, GIRDABLE_TRACKS,
MOVABLE_EMPTY_COLLIDER, MOVABLE_EMPTY_COLLIDER,
NON_MOVABLE,
ORE_OVERRIDE_STONE, ORE_OVERRIDE_STONE,
PASSIVE_BOILER_HEATERS, PASSIVE_BOILER_HEATERS,
SAFE_NBT, SAFE_NBT,
SEATS, SEATS,
TOOLBOXES, TOOLBOXES,
TRACKS, TRACKS,
GIRDABLE_TRACKS,
TREE_ATTACHMENTS, TREE_ATTACHMENTS,
VALVE_HANDLES, VALVE_HANDLES,
WINDMILL_SAILS, WINDMILL_SAILS,
WRENCH_PICKUP, WRENCH_PICKUP,
COPYCAT_ALLOW,
COPYCAT_DENY,
CONTRAPTION_INVENTORY_DENY,
RELOCATION_NOT_SUPPORTED(FORGE), RELOCATION_NOT_SUPPORTED(FORGE),
WG_STONE(FORGE), WG_STONE(FORGE),
@ -156,8 +160,10 @@ public class AllTags {
BLAZE_BURNER_FUEL_REGULAR(MOD, "blaze_burner_fuel/regular"), BLAZE_BURNER_FUEL_REGULAR(MOD, "blaze_burner_fuel/regular"),
BLAZE_BURNER_FUEL_SPECIAL(MOD, "blaze_burner_fuel/special"), BLAZE_BURNER_FUEL_SPECIAL(MOD, "blaze_burner_fuel/special"),
CASING, CASING,
CONTRAPTION_CONTROLLED,
CREATE_INGOTS, CREATE_INGOTS,
CRUSHED_RAW_MATERIALS, CRUSHED_RAW_MATERIALS,
DEPLOYABLE_DRINK,
MODDED_STRIPPED_LOGS, MODDED_STRIPPED_LOGS,
MODDED_STRIPPED_WOOD, MODDED_STRIPPED_WOOD,
PRESSURIZED_AIR_SOURCES, PRESSURIZED_AIR_SOURCES,
@ -169,8 +175,6 @@ public class AllTags {
VALVE_HANDLES, VALVE_HANDLES,
VANILLA_STRIPPED_LOGS, VANILLA_STRIPPED_LOGS,
VANILLA_STRIPPED_WOOD, VANILLA_STRIPPED_WOOD,
DEPLOYABLE_DRINK,
CONTRAPTION_CONTROLLED,
STRIPPED_LOGS(FORGE), STRIPPED_LOGS(FORGE),
STRIPPED_WOOD(FORGE), STRIPPED_WOOD(FORGE),
@ -226,6 +230,10 @@ public class AllTags {
BOTTOMLESS_ALLOW(MOD, "bottomless/allow"), BOTTOMLESS_ALLOW(MOD, "bottomless/allow"),
BOTTOMLESS_DENY(MOD, "bottomless/deny"), BOTTOMLESS_DENY(MOD, "bottomless/deny"),
FAN_PROCESSING_CATALYSTS_BLASTING(MOD, "fan_processing_catalysts/blasting"),
FAN_PROCESSING_CATALYSTS_HAUNTING(MOD, "fan_processing_catalysts/haunting"),
FAN_PROCESSING_CATALYSTS_SMOKING(MOD, "fan_processing_catalysts/smoking"),
FAN_PROCESSING_CATALYSTS_SPLASHING(MOD, "fan_processing_catalysts/splashing"),
HONEY(FORGE) HONEY(FORGE)
@ -275,6 +283,7 @@ public class AllTags {
public enum AllEntityTags { public enum AllEntityTags {
BLAZE_BURNER_CAPTURABLE,
IGNORE_SEAT, IGNORE_SEAT,
; ;
@ -308,9 +317,12 @@ public class AllTags {
this.alwaysDatagen = alwaysDatagen; this.alwaysDatagen = alwaysDatagen;
} }
public boolean matches(EntityType<?> type) {
return type.is(tag);
}
public boolean matches(Entity entity) { public boolean matches(Entity entity) {
return entity.getType() return matches(entity.getType());
.is(tag);
} }
private static void init() {} private static void init() {}

View file

@ -1,7 +1,6 @@
package com.simibubi.create; package com.simibubi.create;
import java.util.Random; import java.util.Random;
import java.util.concurrent.CompletableFuture;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -24,43 +23,30 @@ import com.simibubi.create.content.redstone.link.RedstoneLinkNetworkHandler;
import com.simibubi.create.content.schematics.ServerSchematicLoader; import com.simibubi.create.content.schematics.ServerSchematicLoader;
import com.simibubi.create.content.trains.GlobalRailwayManager; import com.simibubi.create.content.trains.GlobalRailwayManager;
import com.simibubi.create.content.trains.bogey.BogeySizes; import com.simibubi.create.content.trains.bogey.BogeySizes;
import com.simibubi.create.content.trains.track.AllPortalTracks;
import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.advancement.AllAdvancements;
import com.simibubi.create.foundation.advancement.AllTriggers; import com.simibubi.create.foundation.advancement.AllTriggers;
import com.simibubi.create.foundation.block.CopperRegistries; import com.simibubi.create.foundation.block.CopperRegistries;
import com.simibubi.create.foundation.data.CreateRegistrate; import com.simibubi.create.foundation.data.CreateRegistrate;
import com.simibubi.create.foundation.data.DamageTypeTagGen;
import com.simibubi.create.foundation.data.GeneratedEntriesProvider;
import com.simibubi.create.foundation.data.LangMerger;
import com.simibubi.create.foundation.data.RecipeSerializerTagGen;
import com.simibubi.create.foundation.data.TagGen;
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.gui.CreateTheme; import com.simibubi.create.foundation.gui.CreateTheme;
import com.simibubi.create.foundation.item.ItemDescription; import com.simibubi.create.foundation.item.ItemDescription;
import com.simibubi.create.foundation.item.KineticStats; import com.simibubi.create.foundation.item.KineticStats;
import com.simibubi.create.foundation.item.TooltipModifier; import com.simibubi.create.foundation.item.TooltipModifier;
import com.simibubi.create.foundation.ponder.CreatePonderPlugin;
import com.simibubi.create.foundation.utility.AttachedRegistry; import com.simibubi.create.foundation.utility.AttachedRegistry;
import com.simibubi.create.foundation.utility.CreateNBTProcessors; import com.simibubi.create.foundation.utility.CreateNBTProcessors;
import com.simibubi.create.infrastructure.command.ServerLagger; import com.simibubi.create.infrastructure.command.ServerLagger;
import com.simibubi.create.infrastructure.config.AllConfigs; import com.simibubi.create.infrastructure.config.AllConfigs;
import com.simibubi.create.infrastructure.data.CreateDatagen;
import com.simibubi.create.infrastructure.worldgen.AllFeatures; import com.simibubi.create.infrastructure.worldgen.AllFeatures;
import com.simibubi.create.infrastructure.worldgen.AllPlacementModifiers; import com.simibubi.create.infrastructure.worldgen.AllPlacementModifiers;
import net.minecraft.core.HolderLookup;
import net.createmod.catnip.utility.lang.LangBuilder; import net.createmod.catnip.utility.lang.LangBuilder;
import net.createmod.ponder.foundation.PonderIndex;
import net.minecraft.data.DataGenerator;
import net.minecraft.data.PackOutput;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.common.ForgeMod; import net.minecraftforge.common.ForgeMod;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.data.event.GatherDataEvent;
import net.minecraftforge.eventbus.api.EventPriority; import net.minecraftforge.eventbus.api.EventPriority;
import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.fml.DistExecutor;
@ -74,7 +60,7 @@ public class Create {
public static final String ID = "create"; public static final String ID = "create";
public static final String NAME = "Create"; public static final String NAME = "Create";
public static final String VERSION = "0.5.1e"; public static final String VERSION = "0.6-experimental";
public static final Logger LOGGER = LogUtils.getLogger(); public static final Logger LOGGER = LogUtils.getLogger();
@ -86,6 +72,10 @@ public class Create {
@Deprecated @Deprecated
public static final Random RANDOM = new Random(); public static final Random RANDOM = new Random();
/**
* <b>Other mods should not use this field!</b> If you are an addon developer, create your own instance of
* {@link CreateRegistrate}.
*/
public static final CreateRegistrate REGISTRATE = CreateRegistrate.create(ID); public static final CreateRegistrate REGISTRATE = CreateRegistrate.create(ID);
static { static {
@ -138,6 +128,7 @@ public class Create {
// FIXME: some of these registrations are not thread-safe // FIXME: some of these registrations are not thread-safe
AllMovementBehaviours.registerDefaults(); AllMovementBehaviours.registerDefaults();
AllInteractionBehaviours.registerDefaults(); AllInteractionBehaviours.registerDefaults();
AllPortalTracks.registerDefaults();
AllDisplayBehaviours.registerDefaults(); AllDisplayBehaviours.registerDefaults();
ContraptionMovementSetting.registerDefaults(); ContraptionMovementSetting.registerDefaults();
AllArmInteractionPointTypes.register(); AllArmInteractionPointTypes.register();
@ -153,7 +144,7 @@ public class Create {
CopperRegistries.inject(); CopperRegistries.inject();
modEventBus.addListener(Create::init); modEventBus.addListener(Create::init);
modEventBus.addListener(EventPriority.LOW, Create::gatherData); modEventBus.addListener(EventPriority.LOWEST, CreateDatagen::gatherData);
modEventBus.addListener(AllSoundEvents::register); modEventBus.addListener(AllSoundEvents::register);
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> CreateClient.onCtorClient(modEventBus, forgeEventBus)); DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> CreateClient.onCtorClient(modEventBus, forgeEventBus));
@ -180,36 +171,6 @@ public class Create {
}); });
} }
public static void gatherData(GatherDataEvent event) {
TagGen.datagen();
DataGenerator gen = event.getGenerator();
PackOutput output = gen.getPackOutput();
CompletableFuture<HolderLookup.Provider> lookupProvider = event.getLookupProvider();
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> PonderIndex.addPlugin(new CreatePonderPlugin()));
gen.addProvider(event.includeClient(), AllSoundEvents.provider(gen));
GeneratedEntriesProvider generatedEntriesProvider = new GeneratedEntriesProvider(output, lookupProvider);
lookupProvider = generatedEntriesProvider.getRegistryProvider();
gen.addProvider(event.includeServer(), generatedEntriesProvider);
gen.addProvider(event.includeServer(), new RecipeSerializerTagGen(output, lookupProvider, event.getExistingFileHelper()));
gen.addProvider(event.includeServer(), new DamageTypeTagGen(output, lookupProvider, event.getExistingFileHelper()));
gen.addProvider(event.includeServer(), new AllAdvancements(output));
gen.addProvider(event.includeServer(), new StandardRecipeGen(output));
gen.addProvider(event.includeServer(), new MechanicalCraftingRecipeGen(output));
gen.addProvider(event.includeServer(), new SequencedAssemblyRecipeGen(output));
if (event.includeClient()) {
LangMerger.attachToRegistrateProvider(gen, output);
}
if (event.includeServer()) {
ProcessingRecipeGen.registerAll(gen, output);
}
}
public static LangBuilder lang() { public static LangBuilder lang() {
return new LangBuilder(ID); return new LangBuilder(ID);
} }

View file

@ -0,0 +1,83 @@
package com.simibubi.create.api.event;
import org.jetbrains.annotations.Nullable;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.Fluid;
import net.minecraftforge.eventbus.api.Event;
/**
* This Event is fired when two fluids meet in a pipe ({@link Flow})<br>
* or when a fluid in a pipe meets with a fluid in the world
* ({@link Spill}).<br>
* <br>
* If it is not null, the event's BlockState will be placed in world after
* firing.
*/
public class PipeCollisionEvent extends Event {
private final Level level;
private final BlockPos pos;
protected final Fluid firstFluid, secondFluid;
@Nullable
private BlockState state;
protected PipeCollisionEvent(Level level, BlockPos pos, Fluid firstFluid, Fluid secondFluid,
@Nullable BlockState defaultState) {
this.level = level;
this.pos = pos;
this.firstFluid = firstFluid;
this.secondFluid = secondFluid;
this.state = defaultState;
}
public Level getLevel() {
return level;
}
public BlockPos getPos() {
return pos;
}
@Nullable
public BlockState getState() {
return state;
}
public void setState(@Nullable BlockState state) {
this.state = state;
}
public static class Flow extends PipeCollisionEvent {
public Flow(Level level, BlockPos pos, Fluid firstFluid, Fluid secondFluid, @Nullable BlockState defaultState) {
super(level, pos, firstFluid, secondFluid, defaultState);
}
public Fluid getFirstFluid() {
return firstFluid;
}
public Fluid getSecondFluid() {
return secondFluid;
}
}
public static class Spill extends PipeCollisionEvent {
public Spill(Level level, BlockPos pos, Fluid worldFluid, Fluid pipeFluid, @Nullable BlockState defaultState) {
super(level, pos, worldFluid, pipeFluid, defaultState);
}
public Fluid getWorldFluid() {
return firstFluid;
}
public Fluid getPipeFluid() {
return secondFluid;
}
}
}

View file

@ -13,6 +13,7 @@ import net.minecraftforge.registries.ForgeRegistries;
* For compatibility with and without another mod present, we have to define load conditions of the specific code * For compatibility with and without another mod present, we have to define load conditions of the specific code
*/ */
public enum Mods { public enum Mods {
AETHER,
COMPUTERCRAFT, COMPUTERCRAFT,
CONNECTIVITY, CONNECTIVITY,
CURIOS, CURIOS,

View file

@ -1,5 +1,18 @@
package com.simibubi.create.content.contraptions; package com.simibubi.create.content.contraptions;
import java.util.Collection;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.UUID;
import javax.annotation.Nullable;
import org.apache.commons.lang3.mutable.MutableInt;
import org.apache.commons.lang3.tuple.MutablePair;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.AllMovementBehaviours; import com.simibubi.create.AllMovementBehaviours;
@ -24,6 +37,7 @@ import com.simibubi.create.content.trains.entity.Train;
import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.advancement.AllAdvancements;
import com.simibubi.create.foundation.collision.Matrix3d; import com.simibubi.create.foundation.collision.Matrix3d;
import com.simibubi.create.foundation.mixin.accessor.ServerLevelAccessor; import com.simibubi.create.foundation.mixin.accessor.ServerLevelAccessor;
import net.createmod.catnip.utility.VecHelper; import net.createmod.catnip.utility.VecHelper;
import net.createmod.catnip.utility.math.AngleHelper; import net.createmod.catnip.utility.math.AngleHelper;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
@ -64,17 +78,6 @@ import net.minecraftforge.entity.IEntityAdditionalSpawnData;
import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.network.NetworkHooks; import net.minecraftforge.network.NetworkHooks;
import net.minecraftforge.network.PacketDistributor; import net.minecraftforge.network.PacketDistributor;
import org.apache.commons.lang3.mutable.MutableInt;
import org.apache.commons.lang3.tuple.MutablePair;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.UUID;
public abstract class AbstractContraptionEntity extends Entity implements IEntityAdditionalSpawnData { public abstract class AbstractContraptionEntity extends Entity implements IEntityAdditionalSpawnData {
@ -215,6 +218,9 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
} }
public Vec3 getPassengerPosition(Entity passenger, float partialTicks) { public Vec3 getPassengerPosition(Entity passenger, float partialTicks) {
if (contraption == null)
return null;
UUID id = passenger.getUUID(); UUID id = passenger.getUUID();
if (passenger instanceof OrientedContraptionEntity) { if (passenger instanceof OrientedContraptionEntity) {
BlockPos localPos = contraption.getBearingPosOf(id); BlockPos localPos = contraption.getBearingPosOf(id);
@ -229,6 +235,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
BlockPos seat = contraption.getSeatOf(id); BlockPos seat = contraption.getSeatOf(id);
if (seat == null) if (seat == null)
return null; return null;
Vec3 transformedVector = toGlobalVector(Vec3.atLowerCornerOf(seat) Vec3 transformedVector = toGlobalVector(Vec3.atLowerCornerOf(seat)
.add(.5, passenger.getMyRidingOffset() + ySize - .15f, .5), partialTicks) .add(.5, passenger.getMyRidingOffset() + ySize - .15f, .5), partialTicks)
.add(VecHelper.getCenterOf(BlockPos.ZERO)) .add(VecHelper.getCenterOf(BlockPos.ZERO))

View file

@ -1,5 +1,12 @@
package com.simibubi.create.content.contraptions; package com.simibubi.create.content.contraptions;
import static net.createmod.catnip.utility.math.AngleHelper.angleLerp;
import java.util.Optional;
import java.util.UUID;
import javax.annotation.Nullable;
import com.jozufozu.flywheel.util.transform.TransformStack; import com.jozufozu.flywheel.util.transform.TransformStack;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllEntityTypes; import com.simibubi.create.AllEntityTypes;
@ -10,6 +17,7 @@ import com.simibubi.create.content.contraptions.minecart.capability.MinecartCont
import com.simibubi.create.content.contraptions.mounted.CartAssemblerBlockEntity.CartMovementMode; import com.simibubi.create.content.contraptions.mounted.CartAssemblerBlockEntity.CartMovementMode;
import com.simibubi.create.content.contraptions.mounted.MountedContraption; import com.simibubi.create.content.contraptions.mounted.MountedContraption;
import com.simibubi.create.foundation.item.ItemHelper; import com.simibubi.create.foundation.item.ItemHelper;
import net.createmod.catnip.utility.Couple; import net.createmod.catnip.utility.Couple;
import net.createmod.catnip.utility.NBTHelper; import net.createmod.catnip.utility.NBTHelper;
import net.createmod.catnip.utility.VecHelper; import net.createmod.catnip.utility.VecHelper;
@ -41,12 +49,6 @@ import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.common.util.LazyOptional;
import javax.annotation.Nullable;
import java.util.Optional;
import java.util.UUID;
import static net.createmod.catnip.utility.math.AngleHelper.angleLerp;
/** /**
* Ex: Minecarts, Couplings <br> * Ex: Minecarts, Couplings <br>
* Oriented Contraption Entities can rotate freely around two axes * Oriented Contraption Entities can rotate freely around two axes
@ -567,6 +569,9 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity {
private Vec3 getContraptionOffset(float partialTicks, Entity ridingEntity) { private Vec3 getContraptionOffset(float partialTicks, Entity ridingEntity) {
AbstractContraptionEntity parent = (AbstractContraptionEntity) ridingEntity; AbstractContraptionEntity parent = (AbstractContraptionEntity) ridingEntity;
Vec3 passengerPosition = parent.getPassengerPosition(this, partialTicks); Vec3 passengerPosition = parent.getPassengerPosition(this, partialTicks);
if (passengerPosition == null)
return Vec3.ZERO;
double x = passengerPosition.x - Mth.lerp(partialTicks, this.xOld, this.getX()); double x = passengerPosition.x - Mth.lerp(partialTicks, this.xOld, this.getX());
double y = passengerPosition.y - Mth.lerp(partialTicks, this.yOld, this.getY()); double y = passengerPosition.y - Mth.lerp(partialTicks, this.yOld, this.getY());
double z = passengerPosition.z - Mth.lerp(partialTicks, this.zOld, this.getZ()); double z = passengerPosition.z - Mth.lerp(partialTicks, this.zOld, this.getZ());

View file

@ -58,7 +58,7 @@ public class PortableStorageInterfaceBlock extends WrenchableDirectionalBlock
public BlockState getStateForPlacement(BlockPlaceContext context) { public BlockState getStateForPlacement(BlockPlaceContext context) {
Direction direction = context.getNearestLookingDirection(); Direction direction = context.getNearestLookingDirection();
if (context.getPlayer() != null && context.getPlayer() if (context.getPlayer() != null && context.getPlayer()
.isSteppingCarefully()) .isShiftKeyDown())
direction = direction.getOpposite(); direction = direction.getOpposite();
return defaultBlockState().setValue(FACING, direction.getOpposite()); return defaultBlockState().setValue(FACING, direction.getOpposite());
} }

View file

@ -118,7 +118,7 @@ public class RollerBlockEntity extends SmartBlockEntity {
protected void acceptSharedValues(int mode, ItemStack filter) { protected void acceptSharedValues(int mode, ItemStack filter) {
dontPropagate = true; dontPropagate = true;
this.filtering.setFilter(filter); this.filtering.setFilter(filter.copy());
this.mode.setValue(mode); this.mode.setValue(mode);
dontPropagate = false; dontPropagate = false;
notifyUpdate(); notifyUpdate();

View file

@ -19,7 +19,7 @@ import com.simibubi.create.content.contraptions.render.ActorInstance;
import com.simibubi.create.content.contraptions.render.ContraptionMatrices; import com.simibubi.create.content.contraptions.render.ContraptionMatrices;
import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher; import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher;
import com.simibubi.create.content.kinetics.base.BlockBreakingMovementBehaviour; import com.simibubi.create.content.kinetics.base.BlockBreakingMovementBehaviour;
import com.simibubi.create.content.logistics.filter.FilterItem; import com.simibubi.create.content.logistics.filter.FilterItemStack;
import com.simibubi.create.content.trains.bogey.StandardBogeyBlock; import com.simibubi.create.content.trains.bogey.StandardBogeyBlock;
import com.simibubi.create.content.trains.entity.Carriage; import com.simibubi.create.content.trains.entity.Carriage;
import com.simibubi.create.content.trains.entity.CarriageBogey; import com.simibubi.create.content.trains.entity.CarriageBogey;
@ -36,6 +36,7 @@ import com.simibubi.create.foundation.utility.BlockHelper;
import com.simibubi.create.infrastructure.config.AllConfigs; import com.simibubi.create.infrastructure.config.AllConfigs;
import net.createmod.catnip.utility.Couple; import net.createmod.catnip.utility.Couple;
import net.createmod.catnip.utility.Iterate;
import net.createmod.catnip.utility.Pair; import net.createmod.catnip.utility.Pair;
import net.createmod.catnip.utility.VecHelper; import net.createmod.catnip.utility.VecHelper;
import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.MultiBufferSource;
@ -102,6 +103,11 @@ public class RollerMovementBehaviour extends BlockBreakingMovementBehaviour {
@Override @Override
public boolean canBreak(Level world, BlockPos breakingPos, BlockState state) { public boolean canBreak(Level world, BlockPos breakingPos, BlockState state) {
for (Direction side : Iterate.directions)
if (world.getBlockState(breakingPos.relative(side))
.is(BlockTags.PORTALS))
return false;
return super.canBreak(world, breakingPos, state) && !state.getCollisionShape(world, breakingPos) return super.canBreak(world, breakingPos, state) && !state.getCollisionShape(world, breakingPos)
.isEmpty() && !AllBlocks.TRACK.has(state); .isEmpty() && !AllBlocks.TRACK.has(state);
} }
@ -188,10 +194,10 @@ public class RollerMovementBehaviour extends BlockBreakingMovementBehaviour {
int startingY = 1; int startingY = 1;
if (!getStateToPaveWith(context).isAir()) { if (!getStateToPaveWith(context).isAir()) {
ItemStack filter = ItemStack.of(context.blockEntityData.getCompound("Filter")); FilterItemStack filter = context.getFilterFromBE();
if (!ItemHelper if (!ItemHelper
.extract(context.contraption.getSharedInventory(), .extract(context.contraption.getSharedInventory(),
stack -> FilterItem.test(context.world, stack, filter), 1, true) stack -> filter.test(context.world, stack), 1, true)
.isEmpty()) .isEmpty())
startingY = 0; startingY = 0;
} }
@ -279,8 +285,15 @@ public class RollerMovementBehaviour extends BlockBreakingMovementBehaviour {
}; };
rollerScout.travel(train.graph, lengthWiseOffset + 1, steering); rollerScout.travel(train.graph, lengthWiseOffset + 1, steering);
rollerScout.traversalCallback = (edge, coords) -> TrackPaverV2.pave(heightProfile, train.graph, edge, rollerScout.traversalCallback = (edge, coords) -> {
coords.getFirst(), coords.getSecond()); if (edge == null)
return;
if (edge.isInterDimensional())
return;
if (edge.node1.getLocation().dimension != context.world.dimension())
return;
TrackPaverV2.pave(heightProfile, train.graph, edge, coords.getFirst(), coords.getSecond());
};
rollerScout.travel(train.graph, distanceToTravel, steering); rollerScout.travel(train.graph, distanceToTravel, steering);
for (Couple<Integer> entry : heightProfile.keys()) for (Couple<Integer> entry : heightProfile.keys())
@ -294,6 +307,9 @@ public class RollerMovementBehaviour extends BlockBreakingMovementBehaviour {
BlockState stateToPaveWithAsSlab = getStateToPaveWithAsSlab(context); BlockState stateToPaveWithAsSlab = getStateToPaveWithAsSlab(context);
RollingMode mode = getMode(context); RollingMode mode = getMode(context);
if (mode != RollingMode.TUNNEL_PAVE && stateToPaveWith.isAir())
return;
Vec3 directionVec = Vec3.atLowerCornerOf(context.state.getValue(RollerBlock.FACING) Vec3 directionVec = Vec3.atLowerCornerOf(context.state.getValue(RollerBlock.FACING)
.getClockWise() .getClockWise()
.getNormal()); .getNormal());
@ -457,9 +473,9 @@ public class RollerMovementBehaviour extends BlockBreakingMovementBehaviour {
.isEmpty()) .isEmpty())
return PaveResult.FAIL; return PaveResult.FAIL;
ItemStack filter = ItemStack.of(context.blockEntityData.getCompound("Filter")); FilterItemStack filter = context.getFilterFromBE();
ItemStack held = ItemHelper.extract(context.contraption.getSharedInventory(), ItemStack held = ItemHelper.extract(context.contraption.getSharedInventory(),
stack -> FilterItem.test(context.world, stack, filter), 1, false); stack -> filter.test(context.world, stack), 1, false);
if (held.isEmpty()) if (held.isEmpty())
return PaveResult.FAIL; return PaveResult.FAIL;

View file

@ -56,7 +56,7 @@ public class ControlsBlock extends HorizontalDirectionalBlock implements IWrench
Player player = pContext.getPlayer(); Player player = pContext.getPlayer();
state = state.setValue(FACING, horizontalDirection.getOpposite()); state = state.setValue(FACING, horizontalDirection.getOpposite());
if (player != null && player.isSteppingCarefully()) if (player != null && player.isShiftKeyDown())
state = state.setValue(FACING, horizontalDirection); state = state.setValue(FACING, horizontalDirection);
return state; return state;

View file

@ -3,6 +3,7 @@ package com.simibubi.create.content.contraptions.behaviour;
import java.util.function.UnaryOperator; import java.util.function.UnaryOperator;
import com.simibubi.create.content.contraptions.Contraption; import com.simibubi.create.content.contraptions.Contraption;
import com.simibubi.create.content.logistics.filter.FilterItemStack;
import net.createmod.catnip.utility.VecHelper; import net.createmod.catnip.utility.VecHelper;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@ -32,6 +33,8 @@ public class MovementContext {
public Contraption contraption; public Contraption contraption;
public Object temporaryData; public Object temporaryData;
private FilterItemStack filter;
public MovementContext(Level world, StructureBlockInfo info, Contraption contraption) { public MovementContext(Level world, StructureBlockInfo info, Contraption contraption) {
this.world = world; this.world = world;
this.state = info.state(); this.state = info.state();
@ -47,6 +50,7 @@ public class MovementContext {
position = null; position = null;
data = new CompoundTag(); data = new CompoundTag();
stall = false; stall = false;
filter = null;
} }
public float getAnimationSpeed() { public float getAnimationSpeed() {
@ -84,4 +88,10 @@ public class MovementContext {
return nbt; return nbt;
} }
public FilterItemStack getFilterFromBE() {
if (filter != null)
return filter;
return filter = FilterItemStack.of(blockEntityData.getCompound("Filter"));
}
} }

View file

@ -1,5 +1,7 @@
package com.simibubi.create.content.contraptions.elevator; package com.simibubi.create.content.contraptions.elevator;
import java.util.List;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllPackets; import com.simibubi.create.AllPackets;
import com.simibubi.create.AllSoundEvents; import com.simibubi.create.AllSoundEvents;
@ -10,6 +12,7 @@ import com.simibubi.create.content.contraptions.pulley.PulleyBlockEntity;
import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.advancement.AllAdvancements;
import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour;
import com.simibubi.create.infrastructure.config.AllConfigs; import com.simibubi.create.infrastructure.config.AllConfigs;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
@ -17,8 +20,6 @@ import net.minecraft.util.Mth;
import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import java.util.List;
public class ElevatorPulleyBlockEntity extends PulleyBlockEntity { public class ElevatorPulleyBlockEntity extends PulleyBlockEntity {
private float prevSpeed; private float prevSpeed;
@ -88,7 +89,7 @@ public class ElevatorPulleyBlockEntity extends PulleyBlockEntity {
if (level.isClientSide()) if (level.isClientSide())
targetLevel = ec.clientYTarget; targetLevel = ec.clientYTarget;
if (!wasArrived && !level.isClientSide()) { if (!wasArrived && !level.isClientSide()) {
triggerContact(ec, targetLevel); triggerContact(ec, targetLevel - ec.contactYOffset);
AllSoundEvents.CONTRAPTION_DISASSEMBLE.play(level, null, worldPosition.below((int) offset), 0.75f, 0.8f); AllSoundEvents.CONTRAPTION_DISASSEMBLE.play(level, null, worldPosition.below((int) offset), 0.75f, 0.8f);
} }

View file

@ -1,5 +1,9 @@
package com.simibubi.create.content.contraptions.glue; package com.simibubi.create.content.contraptions.glue;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllEntityTypes; import com.simibubi.create.AllEntityTypes;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
@ -11,6 +15,7 @@ import com.simibubi.create.content.kinetics.base.DirectionalKineticBlock;
import com.simibubi.create.content.schematics.requirement.ISpecialEntityItemRequirement; import com.simibubi.create.content.schematics.requirement.ISpecialEntityItemRequirement;
import com.simibubi.create.content.schematics.requirement.ItemRequirement; import com.simibubi.create.content.schematics.requirement.ItemRequirement;
import com.simibubi.create.content.schematics.requirement.ItemRequirement.ItemUseType; import com.simibubi.create.content.schematics.requirement.ItemRequirement.ItemUseType;
import net.createmod.catnip.utility.Iterate; import net.createmod.catnip.utility.Iterate;
import net.createmod.catnip.utility.VecHelper; import net.createmod.catnip.utility.VecHelper;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@ -50,10 +55,6 @@ import net.minecraft.world.phys.Vec3;
import net.minecraftforge.entity.IEntityAdditionalSpawnData; import net.minecraftforge.entity.IEntityAdditionalSpawnData;
import net.minecraftforge.network.NetworkHooks; import net.minecraftforge.network.NetworkHooks;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnData, ISpecialEntityItemRequirement { public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnData, ISpecialEntityItemRequirement {
public static AABB span(BlockPos startPos, BlockPos endPos) { public static AABB span(BlockPos startPos, BlockPos endPos) {
@ -295,9 +296,12 @@ public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnDat
return PushReaction.IGNORE; return PushReaction.IGNORE;
} }
public void setPortalEntrancePos() {
portalEntrancePos = blockPosition();
}
@Override @Override
public PortalInfo findDimensionEntryPoint(ServerLevel pDestination) { public PortalInfo findDimensionEntryPoint(ServerLevel pDestination) {
portalEntrancePos = blockPosition();
return super.findDimensionEntryPoint(pDestination); return super.findDimensionEntryPoint(pDestination);
} }

View file

@ -1,5 +1,9 @@
package com.simibubi.create.content.contraptions.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.google.common.base.Objects;
import com.simibubi.create.AllPackets; import com.simibubi.create.AllPackets;
import com.simibubi.create.AllSoundEvents; import com.simibubi.create.AllSoundEvents;
@ -7,6 +11,7 @@ import com.simibubi.create.AllSpecialTextures;
import com.simibubi.create.content.contraptions.chassis.AbstractChassisBlock; import com.simibubi.create.content.contraptions.chassis.AbstractChassisBlock;
import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.foundation.utility.CreateLang;
import com.simibubi.create.foundation.utility.RaycastHelper; import com.simibubi.create.foundation.utility.RaycastHelper;
import net.createmod.catnip.CatnipClient; import net.createmod.catnip.CatnipClient;
import net.createmod.catnip.utility.lang.Components; import net.createmod.catnip.utility.lang.Components;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
@ -25,10 +30,6 @@ import net.minecraft.world.phys.HitResult.Type;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import net.minecraftforge.common.ForgeMod; import net.minecraftforge.common.ForgeMod;
import java.util.List;
import java.util.Optional;
import java.util.Set;
public class SuperGlueSelectionHandler { public class SuperGlueSelectionHandler {
private static final int PASSIVE = 0x4D9162; private static final int PASSIVE = 0x4D9162;
@ -120,7 +121,7 @@ public class SuperGlueSelectionHandler {
return; return;
} }
boolean cancel = player.isSteppingCarefully(); boolean cancel = player.isShiftKeyDown();
if (cancel && firstPos == null) if (cancel && firstPos == null)
return; return;
@ -188,6 +189,8 @@ public class SuperGlueSelectionHandler {
if (!isGlue(player.getMainHandItem())) if (!isGlue(player.getMainHandItem()))
return false; return false;
if (!player.mayBuild())
return false;
if (attack) { if (attack) {
if (selected == null) if (selected == null)
@ -198,7 +201,7 @@ public class SuperGlueSelectionHandler {
return true; return true;
} }
if (player.isSteppingCarefully()) { if (player.isShiftKeyDown()) {
if (firstPos != null) { if (firstPos != null) {
discard(); discard();
return true; return true;

View file

@ -316,7 +316,7 @@ public abstract class CopycatBlock extends Block implements IBE<CopycatBlockEnti
public ItemStack getCloneItemStack(BlockState state, HitResult target, BlockGetter level, BlockPos pos, public ItemStack getCloneItemStack(BlockState state, HitResult target, BlockGetter level, BlockPos pos,
Player player) { Player player) {
BlockState material = getMaterial(level, pos); BlockState material = getMaterial(level, pos);
if (AllBlocks.COPYCAT_BASE.has(material) || player != null && player.isSteppingCarefully()) if (AllBlocks.COPYCAT_BASE.has(material) || player != null && player.isShiftKeyDown())
return new ItemStack(this); return new ItemStack(this);
return material.getCloneItemStack(target, level, pos, player); return material.getCloneItemStack(target, level, pos, player);
} }

View file

@ -1,5 +1,8 @@
package com.simibubi.create.content.decoration.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;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.AllShapes; import com.simibubi.create.AllShapes;
@ -15,6 +18,7 @@ import com.simibubi.create.content.trains.display.FlapDisplayBlock;
import com.simibubi.create.content.trains.track.TrackBlock; import com.simibubi.create.content.trains.track.TrackBlock;
import com.simibubi.create.content.trains.track.TrackShape; import com.simibubi.create.content.trains.track.TrackShape;
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
import net.createmod.catnip.utility.Iterate; import net.createmod.catnip.utility.Iterate;
import net.createmod.catnip.utility.placement.IPlacementHelper; import net.createmod.catnip.utility.placement.IPlacementHelper;
import net.createmod.catnip.utility.placement.PlacementHelpers; import net.createmod.catnip.utility.placement.PlacementHelpers;
@ -60,9 +64,6 @@ import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.phys.shapes.VoxelShape;
import static net.minecraft.world.level.block.FaceAttachedHorizontalDirectionalBlock.FACE;
import static net.minecraft.world.level.block.state.properties.BlockStateProperties.WATERLOGGED;
public class GirderBlock extends Block implements SimpleWaterloggedBlock, IWrenchable { public class GirderBlock extends Block implements SimpleWaterloggedBlock, IWrenchable {
private static final int placementHelperId = PlacementHelpers.register(new GirderPlacementHelper()); private static final int placementHelperId = PlacementHelpers.register(new GirderPlacementHelper());
@ -119,7 +120,7 @@ public class GirderBlock extends Block implements SimpleWaterloggedBlock, IWrenc
return InteractionResult.SUCCESS; return InteractionResult.SUCCESS;
} }
if (AllItems.WRENCH.isIn(itemInHand) && !pPlayer.isSteppingCarefully()) { if (AllItems.WRENCH.isIn(itemInHand) && !pPlayer.isShiftKeyDown()) {
if (GirderWrenchBehavior.handleClick(pLevel, pPos, pState, pHit)) if (GirderWrenchBehavior.handleClick(pLevel, pPos, pState, pHit))
return InteractionResult.sidedSuccess(pLevel.isClientSide); return InteractionResult.sidedSuccess(pLevel.isClientSide);
return InteractionResult.FAIL; return InteractionResult.FAIL;

View file

@ -44,7 +44,7 @@ public class GirderWrenchBehavior {
Player player = mc.player; Player player = mc.player;
ItemStack heldItem = player.getMainHandItem(); ItemStack heldItem = player.getMainHandItem();
if (player.isSteppingCarefully()) if (player.isShiftKeyDown())
return; return;
if (!AllBlocks.METAL_GIRDER.has(world.getBlockState(pos))) if (!AllBlocks.METAL_GIRDER.has(world.getBlockState(pos)))

View file

@ -1,5 +1,13 @@
package com.simibubi.create.content.decoration.palettes; package com.simibubi.create.content.decoration.palettes;
import static com.simibubi.create.Create.REGISTRATE;
import static com.simibubi.create.foundation.data.WindowGen.customWindowBlock;
import static com.simibubi.create.foundation.data.WindowGen.customWindowPane;
import static com.simibubi.create.foundation.data.WindowGen.framedGlass;
import static com.simibubi.create.foundation.data.WindowGen.framedGlassPane;
import static com.simibubi.create.foundation.data.WindowGen.woodenWindowBlock;
import static com.simibubi.create.foundation.data.WindowGen.woodenWindowPane;
import com.simibubi.create.AllCreativeModeTabs; import com.simibubi.create.AllCreativeModeTabs;
import com.simibubi.create.AllSpriteShifts; import com.simibubi.create.AllSpriteShifts;
import com.simibubi.create.Create; import com.simibubi.create.Create;
@ -9,6 +17,7 @@ import com.simibubi.create.foundation.data.BlockStateGen;
import com.simibubi.create.foundation.data.WindowGen; import com.simibubi.create.foundation.data.WindowGen;
import com.tterrag.registrate.util.DataIngredient; import com.tterrag.registrate.util.DataIngredient;
import com.tterrag.registrate.util.entry.BlockEntry; import com.tterrag.registrate.util.entry.BlockEntry;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
import net.minecraft.data.recipes.RecipeCategory; import net.minecraft.data.recipes.RecipeCategory;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
@ -20,17 +29,11 @@ import net.minecraft.world.level.block.state.properties.WoodType;
import net.minecraft.world.level.material.MapColor; import net.minecraft.world.level.material.MapColor;
import net.minecraftforge.common.Tags; import net.minecraftforge.common.Tags;
import static com.simibubi.create.Create.REGISTRATE;
import static com.simibubi.create.foundation.data.WindowGen.customWindowBlock;
import static com.simibubi.create.foundation.data.WindowGen.customWindowPane;
import static com.simibubi.create.foundation.data.WindowGen.framedGlass;
import static com.simibubi.create.foundation.data.WindowGen.framedGlassPane;
import static com.simibubi.create.foundation.data.WindowGen.woodenWindowBlock;
import static com.simibubi.create.foundation.data.WindowGen.woodenWindowPane;
public class AllPaletteBlocks { public class AllPaletteBlocks {
static { REGISTRATE.useCreativeTab(AllCreativeModeTabs.BUILDING_BLOCKS_TAB); } static {
REGISTRATE.setCreativeTab(AllCreativeModeTabs.PALETTES_CREATIVE_TAB);
}
// Windows and Glass // Windows and Glass

View file

@ -18,7 +18,7 @@ public class LayeredBlock extends RotatedPillarBlock {
.relative(pContext.getClickedFace() .relative(pContext.getClickedFace()
.getOpposite())); .getOpposite()));
if (placedOn.getBlock() == this && (pContext.getPlayer() == null || !pContext.getPlayer() if (placedOn.getBlock() == this && (pContext.getPlayer() == null || !pContext.getPlayer()
.isSteppingCarefully())) .isShiftKeyDown()))
stateForPlacement = stateForPlacement.setValue(AXIS, placedOn.getValue(AXIS)); stateForPlacement = stateForPlacement.setValue(AXIS, placedOn.getValue(AXIS));
return stateForPlacement; return stateForPlacement;
} }

View file

@ -1,5 +1,10 @@
package com.simibubi.create.content.decoration.palettes; package com.simibubi.create.content.decoration.palettes;
import static com.simibubi.create.foundation.data.TagGen.pickaxeOnly;
import java.util.Arrays;
import java.util.function.Supplier;
import com.simibubi.create.Create; import com.simibubi.create.Create;
import com.simibubi.create.foundation.data.CreateRegistrate; import com.simibubi.create.foundation.data.CreateRegistrate;
import com.tterrag.registrate.builders.BlockBuilder; import com.tterrag.registrate.builders.BlockBuilder;
@ -10,6 +15,7 @@ import com.tterrag.registrate.providers.RegistrateRecipeProvider;
import com.tterrag.registrate.util.DataIngredient; import com.tterrag.registrate.util.DataIngredient;
import com.tterrag.registrate.util.entry.BlockEntry; import com.tterrag.registrate.util.entry.BlockEntry;
import com.tterrag.registrate.util.nullness.NonnullType; import com.tterrag.registrate.util.nullness.NonnullType;
import net.createmod.catnip.utility.lang.Lang; import net.createmod.catnip.utility.lang.Lang;
import net.minecraft.data.recipes.RecipeCategory; import net.minecraft.data.recipes.RecipeCategory;
import net.minecraft.data.recipes.ShapedRecipeBuilder; import net.minecraft.data.recipes.ShapedRecipeBuilder;
@ -27,11 +33,6 @@ import net.minecraft.world.level.block.WallBlock;
import net.minecraft.world.level.block.state.BlockBehaviour.Properties; import net.minecraft.world.level.block.state.BlockBehaviour.Properties;
import net.minecraftforge.client.model.generators.ModelFile; import net.minecraftforge.client.model.generators.ModelFile;
import java.util.Arrays;
import java.util.function.Supplier;
import static com.simibubi.create.foundation.data.TagGen.pickaxeOnly;
public abstract class PaletteBlockPartial<B extends Block> { public abstract class PaletteBlockPartial<B extends Block> {
public static final PaletteBlockPartial<StairBlock> STAIR = new Stairs(); public static final PaletteBlockPartial<StairBlock> STAIR = new Stairs();
@ -223,7 +224,7 @@ public abstract class PaletteBlockPartial<B extends Block> {
@Override @Override
protected WallBlock createBlock(Supplier<? extends Block> block) { protected WallBlock createBlock(Supplier<? extends Block> block) {
return new WallBlock(Properties.copy(block.get())); return new WallBlock(Properties.copy(block.get()).forceSolidOn());
} }
@Override @Override

View file

@ -8,6 +8,7 @@ import com.simibubi.create.AllShapes;
import com.simibubi.create.AllSoundEvents; import com.simibubi.create.AllSoundEvents;
import com.simibubi.create.content.equipment.wrench.IWrenchable; import com.simibubi.create.content.equipment.wrench.IWrenchable;
import com.simibubi.create.content.logistics.filter.FilterItem; import com.simibubi.create.content.logistics.filter.FilterItem;
import com.simibubi.create.content.logistics.filter.FilterItemStack;
import com.simibubi.create.content.schematics.requirement.ISpecialBlockItemRequirement; import com.simibubi.create.content.schematics.requirement.ISpecialBlockItemRequirement;
import com.simibubi.create.content.schematics.requirement.ItemRequirement; import com.simibubi.create.content.schematics.requirement.ItemRequirement;
import com.simibubi.create.content.schematics.requirement.ItemRequirement.ItemUseType; import com.simibubi.create.content.schematics.requirement.ItemRequirement.ItemUseType;
@ -132,9 +133,9 @@ public class PlacardBlock extends FaceAttachedHorizontalDirectionalBlock
return InteractionResult.FAIL; return InteractionResult.FAIL;
if (pState.getValue(POWERED)) if (pState.getValue(POWERED))
return InteractionResult.FAIL; return InteractionResult.FAIL;
boolean test = inBlock.getItem() instanceof FilterItem ? FilterItem.test(pLevel, inHand, inBlock) boolean test = inBlock.getItem() instanceof FilterItem ? FilterItemStack.of(inBlock)
: ItemHandlerHelper.canItemStacksStack(inHand, inBlock); .test(pLevel, inHand) : ItemHandlerHelper.canItemStacksStack(inHand, inBlock);
if (!test) { if (!test) {
AllSoundEvents.DENY.play(pLevel, null, pPos, 1, 1); AllSoundEvents.DENY.play(pLevel, null, pPos, 1, 1);
return InteractionResult.SUCCESS; return InteractionResult.SUCCESS;

View file

@ -1,6 +1,6 @@
package com.simibubi.create.content.equipment.armor; package com.simibubi.create.content.equipment.armor;
import com.simibubi.create.AllItems; import com.simibubi.create.AllTags.AllItemTags;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.EquipmentSlot;
@ -28,13 +28,13 @@ public final class NetheriteDivingHandler {
ItemStack to = event.getTo(); ItemStack to = event.getTo();
if (slot == EquipmentSlot.HEAD) { if (slot == EquipmentSlot.HEAD) {
if (AllItems.NETHERITE_DIVING_HELMET.isIn(to)) { if (isNetheriteDivingHelmet(to)) {
setBit(entity, slot); setBit(entity, slot);
} else { } else {
clearBit(entity, slot); clearBit(entity, slot);
} }
} else if (slot == EquipmentSlot.CHEST) { } else if (slot == EquipmentSlot.CHEST) {
if (AllItems.NETHERITE_BACKTANK.isIn(to) && BacktankUtil.hasAirRemaining(to)) { if (isNetheriteBacktank(to) && BacktankUtil.hasAirRemaining(to)) {
setBit(entity, slot); setBit(entity, slot);
} else { } else {
clearBit(entity, slot); clearBit(entity, slot);
@ -48,6 +48,14 @@ public final class NetheriteDivingHandler {
} }
} }
public static boolean isNetheriteDivingHelmet(ItemStack stack) {
return stack.getItem() instanceof DivingHelmetItem && isNetheriteArmor(stack);
}
public static boolean isNetheriteBacktank(ItemStack stack) {
return stack.is(AllItemTags.PRESSURIZED_AIR_SOURCES.tag) && isNetheriteArmor(stack);
}
public static boolean isNetheriteArmor(ItemStack stack) { public static boolean isNetheriteArmor(ItemStack stack) {
return stack.getItem() instanceof ArmorItem armorItem && armorItem.getMaterial() == ArmorMaterials.NETHERITE; return stack.getItem() instanceof ArmorItem armorItem && armorItem.getMaterial() == ArmorMaterials.NETHERITE;
} }

View file

@ -1,14 +1,24 @@
package com.simibubi.create.content.equipment.blueprint; package com.simibubi.create.content.equipment.blueprint;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import javax.annotation.Nullable;
import org.apache.commons.lang3.Validate;
import com.simibubi.create.AllEntityTypes; import com.simibubi.create.AllEntityTypes;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.Create; import com.simibubi.create.Create;
import com.simibubi.create.content.logistics.filter.FilterItem; import com.simibubi.create.content.logistics.filter.FilterItemStack;
import com.simibubi.create.content.schematics.requirement.ISpecialEntityItemRequirement; import com.simibubi.create.content.schematics.requirement.ISpecialEntityItemRequirement;
import com.simibubi.create.content.schematics.requirement.ItemRequirement; import com.simibubi.create.content.schematics.requirement.ItemRequirement;
import com.simibubi.create.content.schematics.requirement.ItemRequirement.ItemUseType; import com.simibubi.create.content.schematics.requirement.ItemRequirement.ItemUseType;
import com.simibubi.create.foundation.networking.ISyncPersistentData; import com.simibubi.create.foundation.networking.ISyncPersistentData;
import com.simibubi.create.foundation.utility.IInteractionChecker; import com.simibubi.create.foundation.utility.IInteractionChecker;
import net.createmod.catnip.utility.Couple; import net.createmod.catnip.utility.Couple;
import net.createmod.catnip.utility.VecHelper; import net.createmod.catnip.utility.VecHelper;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@ -60,13 +70,6 @@ import net.minecraftforge.items.IItemHandlerModifiable;
import net.minecraftforge.items.ItemStackHandler; import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.items.wrapper.InvWrapper; import net.minecraftforge.items.wrapper.InvWrapper;
import net.minecraftforge.network.NetworkHooks; import net.minecraftforge.network.NetworkHooks;
import org.apache.commons.lang3.Validate;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
public class BlueprintEntity extends HangingEntity public class BlueprintEntity extends HangingEntity
implements IEntityAdditionalSpawnData, ISpecialEntityItemRequirement, ISyncPersistentData, IInteractionChecker { implements IEntityAdditionalSpawnData, ISpecialEntityItemRequirement, ISyncPersistentData, IInteractionChecker {
@ -363,14 +366,14 @@ public class BlueprintEntity extends HangingEntity
boolean success = true; boolean success = true;
Search: for (int i = 0; i < 9; i++) { Search: for (int i = 0; i < 9; i++) {
ItemStack requestedItem = items.getStackInSlot(i); FilterItemStack requestedItem = FilterItemStack.of(items.getStackInSlot(i));
if (requestedItem.isEmpty()) { if (requestedItem.isEmpty()) {
craftingGrid.put(i, ItemStack.EMPTY); craftingGrid.put(i, ItemStack.EMPTY);
continue; continue;
} }
for (int slot = 0; slot < playerInv.getSlots(); slot++) { for (int slot = 0; slot < playerInv.getSlots(); slot++) {
if (!FilterItem.test(level(), playerInv.getStackInSlot(slot), requestedItem)) if (!requestedItem.test(level(), playerInv.getStackInSlot(slot)))
continue; continue;
ItemStack currentItem = playerInv.extractItem(slot, 1, false); ItemStack currentItem = playerInv.extractItem(slot, 1, false);
if (stacksTaken.containsKey(slot)) if (stacksTaken.containsKey(slot))

View file

@ -1,14 +1,23 @@
package com.simibubi.create.content.equipment.blueprint; package com.simibubi.create.content.equipment.blueprint;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.content.equipment.blueprint.BlueprintEntity.BlueprintCraftingInventory; import com.simibubi.create.content.equipment.blueprint.BlueprintEntity.BlueprintCraftingInventory;
import com.simibubi.create.content.equipment.blueprint.BlueprintEntity.BlueprintSection; 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.AttributeFilterMenu.WhitelistMode;
import com.simibubi.create.content.logistics.filter.FilterItem; import com.simibubi.create.content.logistics.filter.FilterItem;
import com.simibubi.create.content.logistics.filter.FilterItemStack;
import com.simibubi.create.content.logistics.filter.ItemAttribute; import com.simibubi.create.content.logistics.filter.ItemAttribute;
import com.simibubi.create.content.trains.track.TrackPlacement.PlacementInfo; import com.simibubi.create.content.trains.track.TrackPlacement.PlacementInfo;
import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllGuiTextures;
import net.createmod.catnip.gui.element.GuiGameElement; import net.createmod.catnip.gui.element.GuiGameElement;
import net.createmod.catnip.utility.AnimationTickHolder; import net.createmod.catnip.utility.AnimationTickHolder;
import net.createmod.catnip.utility.Pair; import net.createmod.catnip.utility.Pair;
@ -36,13 +45,6 @@ import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.tags.ITag; import net.minecraftforge.registries.tags.ITag;
import net.minecraftforge.registries.tags.ITagManager; import net.minecraftforge.registries.tags.ITagManager;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
public class BlueprintOverlayRenderer { public class BlueprintOverlayRenderer {
public static final IGuiOverlay OVERLAY = BlueprintOverlayRenderer::renderOverlay; public static final IGuiOverlay OVERLAY = BlueprintOverlayRenderer::renderOverlay;
@ -161,14 +163,14 @@ public class BlueprintOverlayRenderer {
newlyMissing.clear(); newlyMissing.clear();
Search: for (int i = 0; i < 9; i++) { Search: for (int i = 0; i < 9; i++) {
ItemStack requestedItem = items.getStackInSlot(i); FilterItemStack requestedItem = FilterItemStack.of(items.getStackInSlot(i));
if (requestedItem.isEmpty()) { if (requestedItem.isEmpty()) {
craftingGrid.put(i, ItemStack.EMPTY); craftingGrid.put(i, ItemStack.EMPTY);
continue; continue;
} }
for (int slot = 0; slot < playerInv.getSlots(); slot++) { for (int slot = 0; slot < playerInv.getSlots(); slot++) {
if (!FilterItem.test(mc.level, playerInv.getStackInSlot(slot), requestedItem)) if (!requestedItem.test(mc.level, playerInv.getStackInSlot(slot)))
continue; continue;
ItemStack currentItem = playerInv.extractItem(slot, 1, false); ItemStack currentItem = playerInv.extractItem(slot, 1, false);
craftingGrid.put(i, currentItem); craftingGrid.put(i, currentItem);
@ -177,7 +179,7 @@ public class BlueprintOverlayRenderer {
} }
success = false; success = false;
newlyMissing.add(requestedItem); newlyMissing.add(requestedItem.item());
} }
if (success) { if (success) {

View file

@ -1,11 +1,14 @@
package com.simibubi.create.content.equipment.clipboard; package com.simibubi.create.content.equipment.clipboard;
import java.util.List;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.simibubi.create.AllBlockEntityTypes; import com.simibubi.create.AllBlockEntityTypes;
import com.simibubi.create.AllShapes; import com.simibubi.create.AllShapes;
import com.simibubi.create.content.equipment.wrench.IWrenchable; import com.simibubi.create.content.equipment.wrench.IWrenchable;
import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.block.IBE;
import com.simibubi.create.foundation.block.ProperWaterloggedBlock; import com.simibubi.create.foundation.block.ProperWaterloggedBlock;
import net.createmod.catnip.gui.ScreenOpener; import net.createmod.catnip.gui.ScreenOpener;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@ -38,8 +41,6 @@ import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.util.FakePlayer; import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.fml.DistExecutor;
import java.util.List;
public class ClipboardBlock extends FaceAttachedHorizontalDirectionalBlock public class ClipboardBlock extends FaceAttachedHorizontalDirectionalBlock
implements IBE<ClipboardBlockEntity>, IWrenchable, ProperWaterloggedBlock { implements IBE<ClipboardBlockEntity>, IWrenchable, ProperWaterloggedBlock {
@ -85,7 +86,7 @@ public class ClipboardBlock extends FaceAttachedHorizontalDirectionalBlock
@Override @Override
public InteractionResult use(BlockState pState, Level pLevel, BlockPos pPos, Player pPlayer, InteractionHand pHand, public InteractionResult use(BlockState pState, Level pLevel, BlockPos pPos, Player pPlayer, InteractionHand pHand,
BlockHitResult pHit) { BlockHitResult pHit) {
if (pPlayer.isSteppingCarefully()) { if (pPlayer.isShiftKeyDown()) {
breakAndCollect(pState, pLevel, pPos, pPlayer); breakAndCollect(pState, pLevel, pPos, pPlayer);
return InteractionResult.SUCCESS; return InteractionResult.SUCCESS;
} }

View file

@ -33,7 +33,7 @@ public class ClipboardBlockItem extends BlockItem {
Player player = context.getPlayer(); Player player = context.getPlayer();
if (player == null) if (player == null)
return InteractionResult.PASS; return InteractionResult.PASS;
if (player.isSteppingCarefully()) if (player.isShiftKeyDown())
return super.useOn(context); return super.useOn(context);
return use(context.getLevel(), player, context.getHand()).getResult(); return use(context.getLevel(), player, context.getHand()).getResult();
} }

View file

@ -141,7 +141,7 @@ public class ClipboardValueSettingsHandler {
Player player = event.getEntity(); Player player = event.getEntity();
if (player != null && player.isSpectator()) if (player != null && player.isSpectator())
return; return;
if (player.isSteppingCarefully()) if (player.isShiftKeyDown())
return; return;
if (!(world.getBlockEntity(pos) instanceof SmartBlockEntity smartBE)) if (!(world.getBlockEntity(pos) instanceof SmartBlockEntity smartBE))
return; return;

View file

@ -45,7 +45,7 @@ public class WrenchItem extends Item {
Block block = state.getBlock(); Block block = state.getBlock();
if (!(block instanceof IWrenchable)) { if (!(block instanceof IWrenchable)) {
if (canWrenchPickup(state)) if (player.isShiftKeyDown() && canWrenchPickup(state))
return onItemUseOnOther(context); return onItemUseOnOther(context);
return super.useOn(context); return super.useOn(context);
} }

View file

@ -1,6 +1,7 @@
package com.simibubi.create.content.fluids; package com.simibubi.create.content.fluids;
import com.simibubi.create.AllFluids; import com.simibubi.create.AllFluids;
import com.simibubi.create.api.event.PipeCollisionEvent;
import com.simibubi.create.foundation.advancement.AdvancementBehaviour; import com.simibubi.create.foundation.advancement.AdvancementBehaviour;
import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.advancement.AllAdvancements;
import com.simibubi.create.foundation.fluid.FluidHelper; import com.simibubi.create.foundation.fluid.FluidHelper;
@ -14,53 +15,84 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.Fluid; import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.FluidState; import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids; import net.minecraft.world.level.material.Fluids;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.eventbus.api.EventPriority;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
@EventBusSubscriber
public class FluidReactions { public class FluidReactions {
public static void handlePipeFlowCollision(Level world, BlockPos pos, FluidStack fluid, FluidStack fluid2) { public static void handlePipeFlowCollision(Level level, BlockPos pos, FluidStack fluid, FluidStack fluid2) {
Fluid f1 = fluid.getFluid(); Fluid f1 = fluid.getFluid();
Fluid f2 = fluid2.getFluid(); Fluid f2 = fluid2.getFluid();
AdvancementBehaviour.tryAward(world, pos, AllAdvancements.CROSS_STREAMS); AdvancementBehaviour.tryAward(level, pos, AllAdvancements.CROSS_STREAMS);
BlockHelper.destroyBlock(world, pos, 1); BlockHelper.destroyBlock(level, pos, 1);
if (f1 == Fluids.WATER && f2 == Fluids.LAVA || f2 == Fluids.WATER && f1 == Fluids.LAVA) PipeCollisionEvent.Flow event = new PipeCollisionEvent.Flow(level, pos, f1, f2, null);
world.setBlockAndUpdate(pos, Blocks.COBBLESTONE.defaultBlockState()); MinecraftForge.EVENT_BUS.post(event);
else if (f1 == Fluids.LAVA && FluidHelper.hasBlockState(f2)) { if (event.getState() != null)
BlockState lavaInteraction = AllFluids.getLavaInteraction(FluidHelper.convertToFlowing(f2) level.setBlockAndUpdate(pos, event.getState());
.defaultFluidState()); }
if (lavaInteraction != null)
world.setBlockAndUpdate(pos, lavaInteraction); @SubscribeEvent(priority = EventPriority.HIGH)
public static void handlePipeFlowCollisionFallback(PipeCollisionEvent.Flow event) {
Fluid f1 = event.getFirstFluid();
Fluid f2 = event.getSecondFluid();
if (f1 == Fluids.WATER && f2 == Fluids.LAVA || f2 == Fluids.WATER && f1 == Fluids.LAVA) {
event.setState(Blocks.COBBLESTONE.defaultBlockState());
} else if (f1 == Fluids.LAVA && FluidHelper.hasBlockState(f2)) {
BlockState lavaInteraction = AllFluids.getLavaInteraction(FluidHelper.convertToFlowing(f2).defaultFluidState());
if (lavaInteraction != null) {
event.setState(lavaInteraction);
}
} else if (f2 == Fluids.LAVA && FluidHelper.hasBlockState(f1)) { } else if (f2 == Fluids.LAVA && FluidHelper.hasBlockState(f1)) {
BlockState lavaInteraction = AllFluids.getLavaInteraction(FluidHelper.convertToFlowing(f1) BlockState lavaInteraction = AllFluids.getLavaInteraction(FluidHelper.convertToFlowing(f1).defaultFluidState());
.defaultFluidState()); if (lavaInteraction != null) {
if (lavaInteraction != null) event.setState(lavaInteraction);
world.setBlockAndUpdate(pos, lavaInteraction); }
} }
} }
public static void handlePipeSpillCollision(Level world, BlockPos pos, Fluid pipeFluid, FluidState worldFluid) { public static void handlePipeSpillCollision(Level level, BlockPos pos, Fluid pipeFluid, FluidState worldFluid) {
Fluid pf = FluidHelper.convertToStill(pipeFluid); Fluid pf = FluidHelper.convertToStill(pipeFluid);
Fluid wf = worldFluid.getType(); Fluid wf = worldFluid.getType();
if (FluidHelper.isTag(pf, FluidTags.WATER) && wf == Fluids.LAVA)
world.setBlockAndUpdate(pos, Blocks.OBSIDIAN.defaultBlockState()); PipeCollisionEvent.Spill event = new PipeCollisionEvent.Spill(level, pos, wf, pf, null);
else if (pf == Fluids.WATER && wf == Fluids.FLOWING_LAVA) MinecraftForge.EVENT_BUS.post(event);
world.setBlockAndUpdate(pos, Blocks.COBBLESTONE.defaultBlockState()); if (event.getState() != null) {
else if (pf == Fluids.LAVA && wf == Fluids.WATER) level.setBlockAndUpdate(pos, event.getState());
world.setBlockAndUpdate(pos, Blocks.STONE.defaultBlockState()); }
else if (pf == Fluids.LAVA && wf == Fluids.FLOWING_WATER) }
world.setBlockAndUpdate(pos, Blocks.COBBLESTONE.defaultBlockState());
@SubscribeEvent(priority = EventPriority.HIGH)
public static void handlePipeSpillCollisionFallback(PipeCollisionEvent.Spill event) {
Fluid pf = event.getPipeFluid();
Fluid wf = event.getWorldFluid();
if (FluidHelper.isTag(pf, FluidTags.WATER) && wf == Fluids.LAVA) {
event.setState(Blocks.OBSIDIAN.defaultBlockState());
} else if (pf == Fluids.WATER && wf == Fluids.FLOWING_LAVA) {
event.setState(Blocks.COBBLESTONE.defaultBlockState());
} else if (pf == Fluids.LAVA && wf == Fluids.WATER) {
event.setState(Blocks.STONE.defaultBlockState());
} else if (pf == Fluids.LAVA && wf == Fluids.FLOWING_WATER) {
event.setState(Blocks.COBBLESTONE.defaultBlockState());
}
if (pf == Fluids.LAVA) { if (pf == Fluids.LAVA) {
BlockState lavaInteraction = AllFluids.getLavaInteraction(worldFluid); BlockState lavaInteraction = AllFluids.getLavaInteraction(wf.defaultFluidState());
if (lavaInteraction != null) if (lavaInteraction != null) {
world.setBlockAndUpdate(pos, lavaInteraction); event.setState(lavaInteraction);
}
} else if (wf == Fluids.FLOWING_LAVA && FluidHelper.hasBlockState(pf)) { } else if (wf == Fluids.FLOWING_LAVA && FluidHelper.hasBlockState(pf)) {
BlockState lavaInteraction = AllFluids.getLavaInteraction(FluidHelper.convertToFlowing(pf) BlockState lavaInteraction = AllFluids.getLavaInteraction(FluidHelper.convertToFlowing(pf).defaultFluidState());
.defaultFluidState()); if (lavaInteraction != null) {
if (lavaInteraction != null) event.setState(lavaInteraction);
world.setBlockAndUpdate(pos, lavaInteraction); }
} }
} }

View file

@ -131,7 +131,7 @@ public class PumpBlock extends DirectionalKineticBlock
return toPlace; return toPlace;
if (bestConnectedDirection.getAxis() == targetDirection.getAxis()) if (bestConnectedDirection.getAxis() == targetDirection.getAxis())
return toPlace; return toPlace;
if (player.isSteppingCarefully() && bestConnectedDirection.getAxis() != targetDirection.getAxis()) if (player.isShiftKeyDown() && bestConnectedDirection.getAxis() != targetDirection.getAxis())
return toPlace; return toPlace;
return toPlace.setValue(FACING, bestConnectedDirection); return toPlace.setValue(FACING, bestConnectedDirection);

View file

@ -10,6 +10,7 @@ import com.simibubi.create.AllTags.AllBlockTags;
import com.simibubi.create.content.processing.burner.BlazeBurnerBlock; import com.simibubi.create.content.processing.burner.BlazeBurnerBlock;
import com.simibubi.create.content.processing.burner.BlazeBurnerBlock.HeatLevel; import com.simibubi.create.content.processing.burner.BlazeBurnerBlock.HeatLevel;
import com.simibubi.create.foundation.utility.AttachedRegistry; import com.simibubi.create.foundation.utility.AttachedRegistry;
import com.simibubi.create.foundation.utility.BlockHelper;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
@ -71,7 +72,7 @@ public class BoilerHeaters {
}); });
registerHeaterProvider((level, pos, state) -> { registerHeaterProvider((level, pos, state) -> {
if (AllBlockTags.PASSIVE_BOILER_HEATERS.matches(state)) { if (AllBlockTags.PASSIVE_BOILER_HEATERS.matches(state) && BlockHelper.isNotUnheated(state)) {
return (level1, pos1, state1) -> 0; return (level1, pos1, state1) -> 0;
} }
return null; return null;

View file

@ -94,7 +94,7 @@ public class BeltBlockEntity extends KineticBlockEntity {
public void addBehaviours(List<BlockEntityBehaviour> behaviours) { public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
super.addBehaviours(behaviours); super.addBehaviours(behaviours);
behaviours.add(new DirectBeltInputBehaviour(this).onlyInsertWhen(this::canInsertFrom) behaviours.add(new DirectBeltInputBehaviour(this).onlyInsertWhen(this::canInsertFrom)
.setInsertionHandler(this::tryInsertingFromSide)); .setInsertionHandler(this::tryInsertingFromSide).considerOccupiedWhen(this::isOccupied));
behaviours.add(new TransportedItemStackHandlerBehaviour(this, this::applyToAllItems) behaviours.add(new TransportedItemStackHandlerBehaviour(this, this::applyToAllItems)
.withStackPlacement(this::getWorldPositionOf)); .withStackPlacement(this::getWorldPositionOf));
} }
@ -463,6 +463,22 @@ public class BeltBlockEntity extends KineticBlockEntity {
return false; return false;
return getMovementFacing() != side.getOpposite(); return getMovementFacing() != side.getOpposite();
} }
private boolean isOccupied(Direction side) {
BeltBlockEntity nextBeltController = getControllerBE();
if (nextBeltController == null)
return true;
BeltInventory nextInventory = nextBeltController.getInventory();
if (nextInventory == null)
return true;
if (getSpeed() == 0)
return true;
if (getMovementFacing() == side.getOpposite())
return true;
if (!nextInventory.canInsertAtFromSide(index, side))
return true;
return false;
}
private ItemStack tryInsertingFromSide(TransportedItemStack transportedStack, Direction side, boolean simulate) { private ItemStack tryInsertingFromSide(TransportedItemStack transportedStack, Direction side, boolean simulate) {
BeltBlockEntity nextBeltController = getControllerBE(); BeltBlockEntity nextBeltController = getControllerBE();
@ -492,11 +508,7 @@ public class BeltBlockEntity extends KineticBlockEntity {
} }
} }
if (getSpeed() == 0) if (isOccupied(side))
return inserted;
if (getMovementFacing() == side.getOpposite())
return inserted;
if (!nextInventory.canInsertAtFromSide(index, side))
return inserted; return inserted;
if (simulate) if (simulate)
return empty; return empty;

View file

@ -1,11 +1,16 @@
package com.simibubi.create.content.kinetics.belt; package com.simibubi.create.content.kinetics.belt;
import java.util.Map;
import com.simibubi.create.AllTags.AllItemTags; import com.simibubi.create.AllTags.AllItemTags;
import it.unimi.dsi.fastutil.objects.Object2BooleanOpenHashMap;
import net.createmod.catnip.utility.VecHelper; import net.createmod.catnip.utility.VecHelper;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Vec3i; import net.minecraft.core.Vec3i;
import net.minecraft.server.packs.resources.ResourceManagerReloadListener;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.LevelAccessor;
@ -16,9 +21,13 @@ import net.minecraftforge.common.capabilities.ForgeCapabilities;
public class BeltHelper { public class BeltHelper {
public static Map<Item, Boolean> uprightCache = new Object2BooleanOpenHashMap<>();
public static final ResourceManagerReloadListener LISTENER = resourceManager -> uprightCache.clear();
public static boolean isItemUpright(ItemStack stack) { public static boolean isItemUpright(ItemStack stack) {
return stack.getCapability(ForgeCapabilities.FLUID_HANDLER_ITEM) return uprightCache.computeIfAbsent(stack.getItem(),
.isPresent() || AllItemTags.UPRIGHT_ON_BELT.matches(stack); item -> stack.getCapability(ForgeCapabilities.FLUID_HANDLER_ITEM)
.isPresent() || AllItemTags.UPRIGHT_ON_BELT.matches(stack));
} }
public static BeltBlockEntity getSegmentBE(LevelAccessor world, BlockPos pos) { public static BeltBlockEntity getSegmentBE(LevelAccessor world, BlockPos pos) {

View file

@ -33,6 +33,7 @@ public class DirectBeltInputBehaviour extends BlockEntityBehaviour {
public static final BehaviourType<DirectBeltInputBehaviour> TYPE = new BehaviourType<>(); public static final BehaviourType<DirectBeltInputBehaviour> TYPE = new BehaviourType<>();
private InsertionCallback tryInsert; private InsertionCallback tryInsert;
private OccupiedPredicate isOccupied;
private AvailabilityPredicate canInsert; private AvailabilityPredicate canInsert;
private Supplier<Boolean> supportsBeltFunnels; private Supplier<Boolean> supportsBeltFunnels;
@ -40,6 +41,7 @@ public class DirectBeltInputBehaviour extends BlockEntityBehaviour {
super(be); super(be);
tryInsert = this::defaultInsertionCallback; tryInsert = this::defaultInsertionCallback;
canInsert = d -> true; canInsert = d -> true;
isOccupied = d -> false;
supportsBeltFunnels = () -> false; supportsBeltFunnels = () -> false;
} }
@ -57,6 +59,11 @@ public class DirectBeltInputBehaviour extends BlockEntityBehaviour {
canInsert = pred; canInsert = pred;
return this; return this;
} }
public DirectBeltInputBehaviour considerOccupiedWhen(OccupiedPredicate pred) {
isOccupied = pred;
return this;
}
public DirectBeltInputBehaviour setInsertionHandler(InsertionCallback callback) { public DirectBeltInputBehaviour setInsertionHandler(InsertionCallback callback) {
tryInsert = callback; tryInsert = callback;
@ -75,6 +82,10 @@ public class DirectBeltInputBehaviour extends BlockEntityBehaviour {
return canInsert.test(side); return canInsert.test(side);
} }
public boolean isOccupied(Direction side) {
return isOccupied.test(side);
}
public ItemStack handleInsertion(ItemStack stack, Direction side, boolean simulate) { public ItemStack handleInsertion(ItemStack stack, Direction side, boolean simulate) {
return handleInsertion(new TransportedItemStack(stack), side, simulate); return handleInsertion(new TransportedItemStack(stack), side, simulate);
} }
@ -93,6 +104,11 @@ public class DirectBeltInputBehaviour extends BlockEntityBehaviour {
public ItemStack apply(TransportedItemStack stack, Direction side, boolean simulate); public ItemStack apply(TransportedItemStack stack, Direction side, boolean simulate);
} }
@FunctionalInterface
public interface OccupiedPredicate {
public boolean test(Direction side);
}
@FunctionalInterface @FunctionalInterface
public interface AvailabilityPredicate { public interface AvailabilityPredicate {
public boolean test(Direction side); public boolean test(Direction side);

View file

@ -62,7 +62,9 @@ public class ValveHandleBlock extends HandCrankBlock {
if (!(blockState.getBlock() instanceof ValveHandleBlock vhb)) if (!(blockState.getBlock() instanceof ValveHandleBlock vhb))
return; return;
if (AllItems.WRENCH.isIn(player.getItemInHand(event.getHand())) && player.isSteppingCarefully()) if (!player.mayBuild())
return;
if (AllItems.WRENCH.isIn(player.getItemInHand(event.getHand())) && player.isShiftKeyDown())
return; return;
if (vhb.clicked(level, pos, blockState, player, event.getHand())) { if (vhb.clicked(level, pos, blockState, player, event.getHand())) {
@ -90,7 +92,7 @@ public class ValveHandleBlock extends HandCrankBlock {
} }
onBlockEntityUse(level, pos, onBlockEntityUse(level, pos,
hcbe -> (hcbe instanceof ValveHandleBlockEntity vhbe) && vhbe.activate(player.isSteppingCarefully()) hcbe -> (hcbe instanceof ValveHandleBlockEntity vhbe) && vhbe.activate(player.isShiftKeyDown())
? InteractionResult.SUCCESS ? InteractionResult.SUCCESS
: InteractionResult.PASS); : InteractionResult.PASS);
return true; return true;

View file

@ -299,9 +299,6 @@ public class DeployerHandler {
return; return;
if (useItem == DENY) if (useItem == DENY)
return; return;
if (item instanceof BlockItem && !(item instanceof CartAssemblerBlockItem)
&& !clickedState.canBeReplaced(new BlockPlaceContext(itemusecontext)))
return;
// Reposition fire placement for convenience // Reposition fire placement for convenience
if (item == Items.FLINT_AND_STEEL) { if (item == Items.FLINT_AND_STEEL) {
@ -323,6 +320,10 @@ public class DeployerHandler {
player.placedTracks = true; player.placedTracks = true;
return; return;
} }
if (item instanceof BlockItem && !(item instanceof CartAssemblerBlockItem)
&& !clickedState.canBeReplaced(new BlockPlaceContext(itemusecontext)))
return;
if (item == Items.ENDER_PEARL) if (item == Items.ENDER_PEARL)
return; return;
if (AllItemTags.DEPLOYABLE_DRINK.matches(item)) if (AllItemTags.DEPLOYABLE_DRINK.matches(item))

View file

@ -21,7 +21,7 @@ import com.simibubi.create.content.contraptions.render.ActorInstance;
import com.simibubi.create.content.contraptions.render.ContraptionMatrices; import com.simibubi.create.content.contraptions.render.ContraptionMatrices;
import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher; import com.simibubi.create.content.contraptions.render.ContraptionRenderDispatcher;
import com.simibubi.create.content.kinetics.deployer.DeployerBlockEntity.Mode; import com.simibubi.create.content.kinetics.deployer.DeployerBlockEntity.Mode;
import com.simibubi.create.content.logistics.filter.FilterItem; import com.simibubi.create.content.logistics.filter.FilterItemStack;
import com.simibubi.create.content.schematics.SchematicInstances; import com.simibubi.create.content.schematics.SchematicInstances;
import com.simibubi.create.content.schematics.requirement.ItemRequirement; import com.simibubi.create.content.schematics.requirement.ItemRequirement;
import com.simibubi.create.content.trains.entity.CarriageContraption; import com.simibubi.create.content.trains.entity.CarriageContraption;
@ -80,9 +80,9 @@ public class DeployerMovementBehaviour implements MovementBehaviour {
public void activate(MovementContext context, BlockPos pos, DeployerFakePlayer player, Mode mode) { public void activate(MovementContext context, BlockPos pos, DeployerFakePlayer player, Mode mode) {
Level world = context.world; Level world = context.world;
ItemStack filter = getFilter(context); FilterItemStack filter = context.getFilterFromBE();
if (AllItems.SCHEMATIC.isIn(filter)) if (AllItems.SCHEMATIC.isIn(filter.item()))
activateAsSchematicPrinter(context, pos, player, world, filter); activateAsSchematicPrinter(context, pos, player, world, filter.item());
Vec3 facingVec = Vec3.atLowerCornerOf(context.state.getValue(DeployerBlock.FACING) Vec3 facingVec = Vec3.atLowerCornerOf(context.state.getValue(DeployerBlock.FACING)
.getNormal()); .getNormal());
@ -221,11 +221,11 @@ public class DeployerMovementBehaviour implements MovementBehaviour {
return; return;
if (player.getMainHandItem() if (player.getMainHandItem()
.isEmpty()) { .isEmpty()) {
ItemStack filter = getFilter(context); FilterItemStack filter = context.getFilterFromBE();
if (AllItems.SCHEMATIC.isIn(filter)) if (AllItems.SCHEMATIC.isIn(filter.item()))
return; return;
ItemStack held = ItemHelper.extract(context.contraption.getSharedInventory(), ItemStack held = ItemHelper.extract(context.contraption.getSharedInventory(),
stack -> FilterItem.test(context.world, stack, filter), 1, false); stack -> filter.test(context.world, stack), 1, false);
player.setItemInHand(InteractionHand.MAIN_HAND, held); player.setItemInHand(InteractionHand.MAIN_HAND, held);
} }
} }
@ -235,7 +235,7 @@ public class DeployerMovementBehaviour implements MovementBehaviour {
if (player == null) if (player == null)
return; return;
Inventory inv = player.getInventory(); Inventory inv = player.getInventory();
ItemStack filter = getFilter(context); FilterItemStack filter = context.getFilterFromBE();
for (List<ItemStack> list : Arrays.asList(inv.armor, inv.offhand, inv.items)) { for (List<ItemStack> list : Arrays.asList(inv.armor, inv.offhand, inv.items)) {
for (int i = 0; i < list.size(); ++i) { for (int i = 0; i < list.size(); ++i) {
@ -243,7 +243,7 @@ public class DeployerMovementBehaviour implements MovementBehaviour {
if (itemstack.isEmpty()) if (itemstack.isEmpty())
continue; continue;
if (list == inv.items && i == inv.selected && FilterItem.test(context.world, itemstack, filter)) if (list == inv.items && i == inv.selected && filter.test(context.world, itemstack))
continue; continue;
dropItem(context, itemstack); dropItem(context, itemstack);
@ -277,10 +277,6 @@ public class DeployerMovementBehaviour implements MovementBehaviour {
return (DeployerFakePlayer) context.temporaryData; return (DeployerFakePlayer) context.temporaryData;
} }
private ItemStack getFilter(MovementContext context) {
return ItemStack.of(context.blockEntityData.getCompound("Filter"));
}
private Mode getMode(MovementContext context) { private Mode getMode(MovementContext context) {
return NBTHelper.readEnum(context.blockEntityData, "Mode", Mode.class); return NBTHelper.readEnum(context.blockEntityData, "Mode", Mode.class);
} }

View file

@ -32,9 +32,7 @@ import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
@ -54,8 +52,6 @@ public class AirCurrent {
new ArrayList<>(); new ArrayList<>();
protected List<Entity> caughtEntities = new ArrayList<>(); protected List<Entity> caughtEntities = new ArrayList<>();
static boolean isClientPlayerInAirCurrent;
public AirCurrent(IAirCurrentSource source) { public AirCurrent(IAirCurrentSource source) {
this.source = source; this.source = source;
} }
@ -64,21 +60,20 @@ public class AirCurrent {
if (direction == null) if (direction == null)
rebuild(); rebuild();
Level world = source.getAirCurrentWorld(); Level world = source.getAirCurrentWorld();
Direction facing = direction;
if (world != null && world.isClientSide) { if (world != null && world.isClientSide) {
float offset = pushing ? 0.5f : maxDistance + .5f; float offset = pushing ? 0.5f : maxDistance + .5f;
Vec3 pos = VecHelper.getCenterOf(source.getAirCurrentPos()) Vec3 pos = VecHelper.getCenterOf(source.getAirCurrentPos())
.add(Vec3.atLowerCornerOf(facing.getNormal()) .add(Vec3.atLowerCornerOf(direction.getNormal())
.scale(offset)); .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); world.addParticle(new AirFlowParticleData(source.getAirCurrentPos()), pos.x, pos.y, pos.z, 0, 0, 0);
} }
tickAffectedEntities(world, facing); tickAffectedEntities(world);
tickAffectedHandlers(); tickAffectedHandlers();
} }
protected void tickAffectedEntities(Level world, Direction facing) { protected void tickAffectedEntities(Level world) {
for (Iterator<Entity> iterator = caughtEntities.iterator(); iterator.hasNext();) { for (Iterator<Entity> iterator = caughtEntities.iterator(); iterator.hasNext();) {
Entity entity = iterator.next(); Entity entity = iterator.next();
if (!entity.isAlive() || !entity.getBoundingBox() if (!entity.isAlive() || !entity.getBoundingBox()
@ -87,14 +82,14 @@ public class AirCurrent {
continue; continue;
} }
Vec3 center = VecHelper.getCenterOf(source.getAirCurrentPos()); Vec3i flow = (pushing ? direction : direction.getOpposite()).getNormal();
Vec3i flow = (pushing ? facing : facing.getOpposite()).getNormal();
float sneakModifier = entity.isShiftKeyDown() ? 4096f : 512f;
float speed = Math.abs(source.getSpeed()); float speed = Math.abs(source.getSpeed());
double entityDistance = entity.position() float sneakModifier = entity.isShiftKeyDown() ? 4096f : 512f;
.distanceTo(center); double entityDistance = VecHelper.alignedDistanceToFace(entity.position(), source.getAirCurrentPos(), direction);
float acceleration = (float) (speed / sneakModifier / (entityDistance / maxDistance)); // entityDistanceOld should be removed eventually. Remember that entityDistanceOld cannot be 0 while entityDistance can,
// so division by 0 must be avoided.
double entityDistanceOld = entity.position().distanceTo(VecHelper.getCenterOf(source.getAirCurrentPos()));
float acceleration = (float) (speed / sneakModifier / (entityDistanceOld / maxDistance));
Vec3 previousMotion = entity.getDeltaMovement(); Vec3 previousMotion = entity.getDeltaMovement();
float maxAcceleration = 5; float maxAcceleration = 5;
@ -110,8 +105,7 @@ public class AirCurrent {
if (entity instanceof ServerPlayer) if (entity instanceof ServerPlayer)
((ServerPlayer) entity).connection.aboveGroundTickCount = 0; ((ServerPlayer) entity).connection.aboveGroundTickCount = 0;
entityDistance -= .5f; FanProcessingType processingType = getTypeAt((float) entityDistance);
FanProcessingType processingType = getSegmentAt((float) entityDistance);
if (processingType == AllFanProcessingTypes.NONE) if (processingType == AllFanProcessingTypes.NONE)
continue; continue;
@ -131,7 +125,33 @@ public class AirCurrent {
if (world != null) if (world != null)
processingType.affectEntity(entity, world); processingType.affectEntity(entity, world);
} }
}
public static boolean isPlayerCreativeFlying(Entity entity) {
if (entity instanceof Player) {
Player player = (Player) entity;
return player.isCreative() && player.getAbilities().flying;
}
return false;
}
public void tickAffectedHandlers() {
for (Pair<TransportedItemStackHandlerBehaviour, FanProcessingType> pair : affectedItemHandlers) {
TransportedItemStackHandlerBehaviour handler = pair.getKey();
Level world = handler.getWorld();
FanProcessingType processingType = pair.getRight();
handler.handleProcessingOnAllItems(transported -> {
if (world.isClientSide) {
processingType.spawnProcessingParticles(world, handler.getWorldPositionOf(transported));
return TransportedResult.doNothing();
}
TransportedResult applyProcessing = FanProcessing.applyProcessing(transported, world, processingType);
if (!applyProcessing.doesNothing() && source instanceof EncasedFanBlockEntity fan)
fan.award(AllAdvancements.FAN_PROCESSING);
return applyProcessing;
});
}
} }
public void rebuild() { public void rebuild() {
@ -154,32 +174,38 @@ public class AirCurrent {
maxDistance = getFlowLimit(world, start, max, facing); maxDistance = getFlowLimit(world, start, max, facing);
// Determine segments with transported fluids/gases // Determine segments with transported fluids/gases
AirCurrentSegment currentSegment = new AirCurrentSegment();
segments.clear(); segments.clear();
currentSegment.startOffset = 0; AirCurrentSegment currentSegment = null;
FanProcessingType type = AllFanProcessingTypes.NONE; FanProcessingType type = AllFanProcessingTypes.NONE;
int limit = (int) (maxDistance + .5f); int limit = getLimit();
int searchStart = pushing ? 0 : limit; int searchStart = pushing ? 1 : limit;
int searchEnd = pushing ? limit : 0; int searchEnd = pushing ? limit : 1;
int searchStep = pushing ? 1 : -1; int searchStep = pushing ? 1 : -1;
int toOffset = pushing ? -1 : 0;
for (int i = searchStart; i * searchStep <= searchEnd * searchStep; i += searchStep) { for (int i = searchStart; i * searchStep <= searchEnd * searchStep; i += searchStep) {
BlockPos currentPos = start.relative(direction, i); BlockPos currentPos = start.relative(direction, i);
FanProcessingType newType = FanProcessingType.getAt(world, currentPos); FanProcessingType newType = FanProcessingType.getAt(world, currentPos);
if (newType != AllFanProcessingTypes.NONE) if (newType != AllFanProcessingTypes.NONE) {
type = newType; type = newType;
if (currentSegment.type != type || currentSegment.startOffset == 0) { }
currentSegment.endOffset = i; if (currentSegment == null) {
if (currentSegment.startOffset != 0)
segments.add(currentSegment);
currentSegment = new AirCurrentSegment(); currentSegment = new AirCurrentSegment();
currentSegment.startOffset = i; currentSegment.startOffset = i + toOffset;
currentSegment.type = type;
} else if (currentSegment.type != type) {
currentSegment.endOffset = i + toOffset;
segments.add(currentSegment);
currentSegment = new AirCurrentSegment();
currentSegment.startOffset = i + toOffset;
currentSegment.type = type; currentSegment.type = type;
} }
} }
currentSegment.endOffset = searchEnd + searchStep; if (currentSegment != null) {
segments.add(currentSegment); currentSegment.endOffset = searchEnd + searchStep + toOffset;
segments.add(currentSegment);
}
// Build Bounding Box // Build Bounding Box
if (maxDistance < 0.25f) if (maxDistance < 0.25f)
@ -194,133 +220,152 @@ public class AirCurrent {
.move(scale); .move(scale);
} }
} }
findAffectedHandlers(); findAffectedHandlers();
} }
public static float getFlowLimit(Level world, BlockPos start, float max, Direction facing) { public static float getFlowLimit(Level world, BlockPos start, float max, Direction facing) {
Vec3 directionVec = Vec3.atLowerCornerOf(facing.getNormal()); for (int i = 0; i < max; i++) {
Vec3 planeVec = VecHelper.axisAlingedPlaneOf(directionVec); BlockPos currentPos = start.relative(facing, i + 1);
if (!world.isLoaded(currentPos)) {
return i;
}
// 4 Rays test for holes in the shapes blocking the flow
float offsetDistance = .25f;
Vec3[] offsets = new Vec3[] { planeVec.multiply(offsetDistance, offsetDistance, offsetDistance),
planeVec.multiply(-offsetDistance, -offsetDistance, offsetDistance),
planeVec.multiply(offsetDistance, -offsetDistance, -offsetDistance),
planeVec.multiply(-offsetDistance, offsetDistance, -offsetDistance), };
float limitedDistance = 0;
// Determine the distance of the air flow
Outer: for (int i = 1; i <= max; i++) {
BlockPos currentPos = start.relative(facing, i);
if (!world.isLoaded(currentPos))
break;
BlockState state = world.getBlockState(currentPos); BlockState state = world.getBlockState(currentPos);
BlockState copycatState = CopycatBlock.getMaterial(world, currentPos); BlockState copycatState = CopycatBlock.getMaterial(world, currentPos);
if (shouldAlwaysPass(copycatState.isAir() ? state : copycatState)) if (shouldAlwaysPass(copycatState.isAir() ? state : copycatState)) {
continue; continue;
VoxelShape voxelshape = state.getCollisionShape(world, currentPos, CollisionContext.empty());
if (voxelshape.isEmpty())
continue;
if (voxelshape == Shapes.block()) {
max = i - 1;
break;
} }
for (Vec3 offset : offsets) { VoxelShape shape = state.getCollisionShape(world, currentPos);
Vec3 rayStart = VecHelper.getCenterOf(currentPos) if (shape.isEmpty()) {
.subtract(directionVec.scale(.5f + 1 / 32f)) continue;
.add(offset);
Vec3 rayEnd = rayStart.add(directionVec.scale(1 + 1 / 32f));
BlockHitResult blockraytraceresult =
world.clipWithInteractionOverride(rayStart, rayEnd, currentPos, voxelshape, state);
if (blockraytraceresult == null)
continue Outer;
double distance = i - 1 + blockraytraceresult.getLocation()
.distanceTo(rayStart);
if (limitedDistance < distance)
limitedDistance = (float) distance;
} }
if (shape == Shapes.block()) {
max = limitedDistance; return i;
break; }
double shapeDepth = findMaxDepth(shape, facing);
if (shapeDepth == Double.POSITIVE_INFINITY) {
continue;
}
return Math.min((float) (i + shapeDepth + 1/32d), max);
} }
return max; return max;
} }
private static final double[][] DEPTH_TEST_COORDINATES = {
{ 0.25, 0.25 },
{ 0.25, 0.75 },
{ 0.5, 0.5 },
{ 0.75, 0.25 },
{ 0.75, 0.75 }
};
// Finds the maximum depth of the shape when traveling in the given direction.
// The result is always positive.
// If there is a hole, the result will be Double.POSITIVE_INFINITY.
private static double findMaxDepth(VoxelShape shape, Direction direction) {
Direction.Axis axis = direction.getAxis();
Direction.AxisDirection axisDirection = direction.getAxisDirection();
double maxDepth = 0;
for (double[] coordinates : DEPTH_TEST_COORDINATES) {
double depth;
if (axisDirection == Direction.AxisDirection.POSITIVE) {
double min = shape.min(axis, coordinates[0], coordinates[1]);
if (min == Double.POSITIVE_INFINITY) {
return Double.POSITIVE_INFINITY;
}
depth = min;
} else {
double max = shape.max(axis, coordinates[0], coordinates[1]);
if (max == Double.NEGATIVE_INFINITY) {
return Double.POSITIVE_INFINITY;
}
depth = 1 - max;
}
if (depth > maxDepth) {
maxDepth = depth;
}
}
return maxDepth;
}
private static boolean shouldAlwaysPass(BlockState state) {
return AllTags.AllBlockTags.FAN_TRANSPARENT.matches(state);
}
private int getLimit() {
if ((float) (int) maxDistance == maxDistance) {
return (int) maxDistance;
} else {
return (int) maxDistance + 1;
}
}
public void findAffectedHandlers() {
Level world = source.getAirCurrentWorld();
BlockPos start = source.getAirCurrentPos();
affectedItemHandlers.clear();
int limit = getLimit();
for (int i = 1; i <= limit; i++) {
FanProcessingType segmentType = getTypeAt(i - 1);
for (int offset : Iterate.zeroAndOne) {
BlockPos pos = start.relative(direction, i)
.below(offset);
TransportedItemStackHandlerBehaviour behaviour =
BlockEntityBehaviour.get(world, pos, TransportedItemStackHandlerBehaviour.TYPE);
if (behaviour != null) {
FanProcessingType type = FanProcessingType.getAt(world, pos);
if (type == AllFanProcessingTypes.NONE)
type = segmentType;
affectedItemHandlers.add(Pair.of(behaviour, type));
}
if (direction.getAxis()
.isVertical())
break;
}
}
}
public void findEntities() { public void findEntities() {
caughtEntities.clear(); caughtEntities.clear();
caughtEntities = source.getAirCurrentWorld() caughtEntities = source.getAirCurrentWorld()
.getEntities(null, bounds); .getEntities(null, bounds);
} }
public void findAffectedHandlers() { public FanProcessingType getTypeAt(float offset) {
Level world = source.getAirCurrentWorld(); if (offset >= 0 && offset <= maxDistance) {
BlockPos start = source.getAirCurrentPos(); if (pushing) {
affectedItemHandlers.clear(); for (AirCurrentSegment airCurrentSegment : segments) {
for (int i = 0; i < maxDistance + 1; i++) { if (offset <= airCurrentSegment.endOffset) {
FanProcessingType segmentType = getSegmentAt(i); return airCurrentSegment.type;
for (int offset : Iterate.zeroAndOne) { }
BlockPos pos = start.relative(direction, i)
.below(offset);
TransportedItemStackHandlerBehaviour behaviour =
BlockEntityBehaviour.get(world, pos, TransportedItemStackHandlerBehaviour.TYPE);
if (behaviour == null)
continue;
FanProcessingType type = FanProcessingType.getAt(world, pos);
if (type == AllFanProcessingTypes.NONE)
type = segmentType;
affectedItemHandlers.add(Pair.of(behaviour, type));
if (direction.getAxis()
.isVertical())
break;
}
}
}
public void tickAffectedHandlers() {
for (Pair<TransportedItemStackHandlerBehaviour, FanProcessingType> pair : affectedItemHandlers) {
TransportedItemStackHandlerBehaviour handler = pair.getKey();
Level world = handler.getWorld();
FanProcessingType processingType = pair.getRight();
handler.handleProcessingOnAllItems(transported -> {
if (world.isClientSide) {
processingType.spawnProcessingParticles(world, handler.getWorldPositionOf(transported));
return TransportedResult.doNothing();
} }
TransportedResult applyProcessing = FanProcessing.applyProcessing(transported, world, processingType); } else {
if (!applyProcessing.doesNothing() && source instanceof EncasedFanBlockEntity fan) for (AirCurrentSegment airCurrentSegment : segments) {
fan.award(AllAdvancements.FAN_PROCESSING); if (offset >= airCurrentSegment.endOffset) {
return applyProcessing; return airCurrentSegment.type;
}); }
} }
} }
private static boolean shouldAlwaysPass(BlockState state) {
return AllTags.AllBlockTags.FAN_TRANSPARENT.matches(state);
}
public FanProcessingType getSegmentAt(float offset) {
for (AirCurrentSegment airCurrentSegment : segments) {
if (offset > airCurrentSegment.endOffset && pushing)
continue;
if (offset < airCurrentSegment.endOffset && !pushing)
continue;
return airCurrentSegment.type;
} }
return AllFanProcessingTypes.NONE; return AllFanProcessingTypes.NONE;
} }
public static class AirCurrentSegment { private static class AirCurrentSegment {
FanProcessingType type; private FanProcessingType type;
int startOffset; private int startOffset;
int endOffset; private int endOffset;
} }
private static boolean isClientPlayerInAirCurrent;
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
static AirCurrentSound flyingSound; private static AirCurrentSound flyingSound;
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
private static void enableClientPlayerSound(Entity e, float maxVolume) { private static void enableClientPlayerSound(Entity e, float maxVolume) {
@ -345,7 +390,7 @@ public class AirCurrent {
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public static void tickClientPlayerSounds() { public static void tickClientPlayerSounds() {
if (!AirCurrent.isClientPlayerInAirCurrent && flyingSound != null) if (!isClientPlayerInAirCurrent && flyingSound != null)
if (flyingSound.isFaded()) if (flyingSound.isFaded())
flyingSound.stopSound(); flyingSound.stopSound();
else else
@ -353,12 +398,4 @@ public class AirCurrent {
isClientPlayerInAirCurrent = false; isClientPlayerInAirCurrent = false;
} }
public static boolean isPlayerCreativeFlying(Entity entity) {
if (entity instanceof Player) {
Player player = (Player) entity;
return player.isCreative() && player.getAbilities().flying;
}
return false;
}
} }

View file

@ -34,9 +34,9 @@ public class AirFlowParticle extends SimpleAnimatedParticle {
selectSprite(7); selectSprite(7);
Vec3 offset = VecHelper.offsetRandomly(Vec3.ZERO, random, .25f); Vec3 offset = VecHelper.offsetRandomly(Vec3.ZERO, random, .25f);
this.setPos(x + offset.x, y + offset.y, z + offset.z); this.setPos(x + offset.x, y + offset.y, z + offset.z);
this.xo = x; this.xo = this.x;
this.yo = y; this.yo = this.y;
this.zo = z; this.zo = this.z;
setColor(0xEEEEEE); setColor(0xEEEEEE);
setAlpha(.25f); setAlpha(.25f);
} }
@ -97,15 +97,13 @@ public class AirFlowParticle extends SimpleAnimatedParticle {
this.zd *= 0.7; this.zd *= 0.7;
} }
this.move(this.xd, this.yd, this.zd); this.move(this.xd, this.yd, this.zd);
} }
} }
private FanProcessingType getType(double distance) { private FanProcessingType getType(double distance) {
if (source.getAirCurrent() == null) if (source.getAirCurrent() == null)
return AllFanProcessingTypes.NONE; return AllFanProcessingTypes.NONE;
return source.getAirCurrent().getSegmentAt((float) distance); return source.getAirCurrent().getTypeAt((float) distance);
} }
public int getLightColor(float partialTick) { public int getLightColor(float partialTick) {
@ -124,6 +122,7 @@ public class AirFlowParticle extends SimpleAnimatedParticle {
this.spriteSet = animatedSprite; this.spriteSet = animatedSprite;
} }
@Override
public Particle createParticle(AirFlowParticleData data, ClientLevel worldIn, double x, double y, double z, public Particle createParticle(AirFlowParticleData data, ClientLevel worldIn, double x, double y, double z,
double xSpeed, double ySpeed, double zSpeed) { double xSpeed, double ySpeed, double zSpeed) {
BlockEntity be = worldIn.getBlockEntity(new BlockPos(data.posX, data.posY, data.posZ)); BlockEntity be = worldIn.getBlockEntity(new BlockPos(data.posX, data.posY, data.posZ));

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.kinetics.fan.processing; package com.simibubi.create.content.kinetics.fan.processing;
import static com.simibubi.create.content.processing.burner.BlazeBurnerBlock.getHeatLevelOf;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -10,8 +8,9 @@ import java.util.Optional;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.joml.Vector3f; import org.joml.Vector3f;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllRecipeTypes; import com.simibubi.create.AllRecipeTypes;
import com.simibubi.create.AllTags.AllBlockTags;
import com.simibubi.create.AllTags.AllFluidTags;
import com.simibubi.create.Create; import com.simibubi.create.Create;
import com.simibubi.create.content.kinetics.fan.processing.HauntingRecipe.HauntingWrapper; import com.simibubi.create.content.kinetics.fan.processing.HauntingRecipe.HauntingWrapper;
import com.simibubi.create.content.kinetics.fan.processing.SplashingRecipe.SplashingWrapper; import com.simibubi.create.content.kinetics.fan.processing.SplashingRecipe.SplashingWrapper;
@ -48,13 +47,10 @@ import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.item.crafting.SmeltingRecipe; import net.minecraft.world.item.crafting.SmeltingRecipe;
import net.minecraft.world.item.crafting.SmokingRecipe; import net.minecraft.world.item.crafting.SmokingRecipe;
import net.minecraft.world.level.Level; 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.Blocks;
import net.minecraft.world.level.block.CampfireBlock; import net.minecraft.world.level.block.CampfireBlock;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.FluidState; import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import net.minecraftforge.items.ItemStackHandler; import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.items.wrapper.RecipeWrapper; import net.minecraftforge.items.wrapper.RecipeWrapper;
@ -140,9 +136,18 @@ public class AllFanProcessingTypes {
@Override @Override
public boolean isValidAt(Level level, BlockPos pos) { public boolean isValidAt(Level level, BlockPos pos) {
FluidState fluidState = level.getFluidState(pos);
if (AllFluidTags.FAN_PROCESSING_CATALYSTS_BLASTING.matches(fluidState)) {
return true;
}
BlockState blockState = level.getBlockState(pos); BlockState blockState = level.getBlockState(pos);
Block block = blockState.getBlock(); if (AllBlockTags.FAN_PROCESSING_CATALYSTS_BLASTING.matches(blockState)) {
return block == Blocks.LAVA || getHeatLevelOf(blockState).isAtLeast(BlazeBurnerBlock.HeatLevel.FADING); if (blockState.hasProperty(BlazeBurnerBlock.HEAT_LEVEL) && !blockState.getValue(BlazeBurnerBlock.HEAT_LEVEL).isAtLeast(BlazeBurnerBlock.HeatLevel.FADING)) {
return false;
}
return true;
}
return false;
} }
@Override @Override
@ -233,15 +238,21 @@ public class AllFanProcessingTypes {
@Override @Override
public boolean isValidAt(Level level, BlockPos pos) { public boolean isValidAt(Level level, BlockPos pos) {
FluidState fluidState = level.getFluidState(pos);
if (AllFluidTags.FAN_PROCESSING_CATALYSTS_HAUNTING.matches(fluidState)) {
return true;
}
BlockState blockState = level.getBlockState(pos); BlockState blockState = level.getBlockState(pos);
Block block = blockState.getBlock(); if (AllBlockTags.FAN_PROCESSING_CATALYSTS_HAUNTING.matches(blockState)) {
return block == Blocks.SOUL_FIRE if (blockState.is(BlockTags.CAMPFIRES) && blockState.hasProperty(CampfireBlock.LIT) && !blockState.getValue(CampfireBlock.LIT)) {
|| block == Blocks.SOUL_CAMPFIRE && blockState.getOptionalValue(CampfireBlock.LIT) return false;
.orElse(false) }
|| AllBlocks.LIT_BLAZE_BURNER.has(blockState) if (blockState.hasProperty(LitBlazeBurnerBlock.FLAME_TYPE) && blockState.getValue(LitBlazeBurnerBlock.FLAME_TYPE) != LitBlazeBurnerBlock.FlameType.SOUL) {
&& blockState.getOptionalValue(LitBlazeBurnerBlock.FLAME_TYPE) return false;
.map(flame -> flame == LitBlazeBurnerBlock.FlameType.SOUL) }
.orElse(false); return true;
}
return false;
} }
@Override @Override
@ -347,16 +358,24 @@ public class AllFanProcessingTypes {
@Override @Override
public boolean isValidAt(Level level, BlockPos pos) { public boolean isValidAt(Level level, BlockPos pos) {
FluidState fluidState = level.getFluidState(pos);
if (AllFluidTags.FAN_PROCESSING_CATALYSTS_SMOKING.matches(fluidState)) {
return true;
}
BlockState blockState = level.getBlockState(pos); BlockState blockState = level.getBlockState(pos);
Block block = blockState.getBlock(); if (AllBlockTags.FAN_PROCESSING_CATALYSTS_SMOKING.matches(blockState)) {
return block == Blocks.FIRE if (blockState.is(BlockTags.CAMPFIRES) && blockState.hasProperty(CampfireBlock.LIT) && !blockState.getValue(CampfireBlock.LIT)) {
|| blockState.is(BlockTags.CAMPFIRES) && blockState.getOptionalValue(CampfireBlock.LIT) return false;
.orElse(false) }
|| AllBlocks.LIT_BLAZE_BURNER.has(blockState) if (blockState.hasProperty(LitBlazeBurnerBlock.FLAME_TYPE) && blockState.getValue(LitBlazeBurnerBlock.FLAME_TYPE) != LitBlazeBurnerBlock.FlameType.REGULAR) {
&& blockState.getOptionalValue(LitBlazeBurnerBlock.FLAME_TYPE) return false;
.map(flame -> flame == LitBlazeBurnerBlock.FlameType.REGULAR) }
.orElse(false) if (blockState.hasProperty(BlazeBurnerBlock.HEAT_LEVEL) && blockState.getValue(BlazeBurnerBlock.HEAT_LEVEL) != BlazeBurnerBlock.HeatLevel.SMOULDERING) {
|| getHeatLevelOf(blockState) == BlazeBurnerBlock.HeatLevel.SMOULDERING; return false;
}
return true;
}
return false;
} }
@Override @Override
@ -420,8 +439,14 @@ public class AllFanProcessingTypes {
@Override @Override
public boolean isValidAt(Level level, BlockPos pos) { public boolean isValidAt(Level level, BlockPos pos) {
FluidState fluidState = level.getFluidState(pos); FluidState fluidState = level.getFluidState(pos);
Fluid fluid = fluidState.getType(); if (AllFluidTags.FAN_PROCESSING_CATALYSTS_SPLASHING.matches(fluidState)) {
return fluid == Fluids.WATER || fluid == Fluids.FLOWING_WATER; return true;
}
BlockState blockState = level.getBlockState(pos);
if (AllBlockTags.FAN_PROCESSING_CATALYSTS_SPLASHING.matches(blockState)) {
return true;
}
return false;
} }
@Override @Override

View file

@ -16,6 +16,8 @@ public class TurntableHandler {
Minecraft mc = Minecraft.getInstance(); Minecraft mc = Minecraft.getInstance();
BlockPos pos = mc.player.blockPosition(); BlockPos pos = mc.player.blockPosition();
if (mc.gameMode == null)
return;
if (!AllBlocks.TURNTABLE.has(mc.level.getBlockState(pos))) if (!AllBlocks.TURNTABLE.has(mc.level.getBlockState(pos)))
return; return;
if (!mc.player.onGround()) if (!mc.player.onGround())

View file

@ -20,6 +20,7 @@ import com.simibubi.create.content.logistics.funnel.FunnelBlock;
import com.simibubi.create.foundation.advancement.AllAdvancements; import com.simibubi.create.foundation.advancement.AllAdvancements;
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour;
import com.simibubi.create.foundation.blockEntity.behaviour.inventory.VersionedInventoryTrackerBehaviour;
import com.simibubi.create.foundation.item.ItemHelper; import com.simibubi.create.foundation.item.ItemHelper;
import com.simibubi.create.foundation.item.ItemHelper.ExtractionCountMode; import com.simibubi.create.foundation.item.ItemHelper.ExtractionCountMode;
import com.simibubi.create.foundation.particle.AirParticleData; import com.simibubi.create.foundation.particle.AirParticleData;
@ -81,6 +82,8 @@ public class ChuteBlockEntity extends SmartBlockEntity implements IHaveGoggleInf
int airCurrentUpdateCooldown; int airCurrentUpdateCooldown;
int entitySearchCooldown; int entitySearchCooldown;
VersionedInventoryTrackerBehaviour invVersionTracker;
LazyOptional<IItemHandler> capAbove; LazyOptional<IItemHandler> capAbove;
LazyOptional<IItemHandler> capBelow; LazyOptional<IItemHandler> capBelow;
@ -101,6 +104,7 @@ public class ChuteBlockEntity extends SmartBlockEntity implements IHaveGoggleInf
@Override @Override
public void addBehaviours(List<BlockEntityBehaviour> behaviours) { public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
behaviours.add(new DirectBeltInputBehaviour(this).onlyInsertWhen((d) -> canDirectlyInsertCached())); behaviours.add(new DirectBeltInputBehaviour(this).onlyInsertWhen((d) -> canDirectlyInsertCached()));
behaviours.add(invVersionTracker = new VersionedInventoryTrackerBehaviour(this));
registerAwardables(behaviours, AllAdvancements.CHUTE); registerAwardables(behaviours, AllAdvancements.CHUTE);
} }
@ -336,15 +340,20 @@ public class ChuteBlockEntity extends SmartBlockEntity implements IHaveGoggleInf
private void handleInput(IItemHandler inv, float startLocation) { private void handleInput(IItemHandler inv, float startLocation) {
if (inv == null) if (inv == null)
return; return;
if (invVersionTracker.stillWaiting(inv))
return;
Predicate<ItemStack> canAccept = this::canAcceptItem; Predicate<ItemStack> canAccept = this::canAcceptItem;
int count = getExtractionAmount(); int count = getExtractionAmount();
ExtractionCountMode mode = getExtractionMode(); ExtractionCountMode mode = getExtractionMode();
if (mode == ExtractionCountMode.UPTO || !ItemHelper.extract(inv, canAccept, mode, count, true) if (mode == ExtractionCountMode.UPTO || !ItemHelper.extract(inv, canAccept, mode, count, true)
.isEmpty()) { .isEmpty()) {
ItemStack extracted = ItemHelper.extract(inv, canAccept, mode, count, false); ItemStack extracted = ItemHelper.extract(inv, canAccept, mode, count, false);
if (!extracted.isEmpty()) if (!extracted.isEmpty()) {
setItem(extracted, startLocation); setItem(extracted, startLocation);
return;
}
} }
invVersionTracker.awaitNewVersion(inv);
} }
private boolean handleDownwardOutput(boolean simulate) { private boolean handleDownwardOutput(boolean simulate) {
@ -359,12 +368,16 @@ public class ChuteBlockEntity extends SmartBlockEntity implements IHaveGoggleInf
if (capBelow.isPresent()) { if (capBelow.isPresent()) {
if (level.isClientSide && !isVirtual()) if (level.isClientSide && !isVirtual())
return false; return false;
ItemStack remainder = ItemHandlerHelper.insertItemStacked(capBelow.orElse(null), item, simulate); IItemHandler inv = capBelow.orElse(null);
if (invVersionTracker.stillWaiting(inv))
return false;
ItemStack remainder = ItemHandlerHelper.insertItemStacked(inv, item, simulate);
ItemStack held = getItem(); ItemStack held = getItem();
if (!simulate) if (!simulate)
setItem(remainder, itemPosition.getValue(0)); setItem(remainder, itemPosition.getValue(0));
if (remainder.getCount() != held.getCount()) if (remainder.getCount() != held.getCount())
return true; return true;
invVersionTracker.awaitNewVersion(inv);
if (direction == Direction.DOWN) if (direction == Direction.DOWN)
return false; return false;
} }
@ -414,10 +427,16 @@ public class ChuteBlockEntity extends SmartBlockEntity implements IHaveGoggleInf
if (level.isClientSide && !isVirtual() && !ChuteBlock.isChute(stateAbove)) if (level.isClientSide && !isVirtual() && !ChuteBlock.isChute(stateAbove))
return false; return false;
int countBefore = item.getCount(); int countBefore = item.getCount();
ItemStack remainder = ItemHandlerHelper.insertItemStacked(capAbove.orElse(null), item, simulate); IItemHandler inv = capAbove.orElse(null);
if (invVersionTracker.stillWaiting(inv))
return false;
ItemStack remainder = ItemHandlerHelper.insertItemStacked(inv, item, simulate);
if (!simulate) if (!simulate)
item = remainder; item = remainder;
return countBefore != remainder.getCount(); if (countBefore != remainder.getCount())
return true;
invVersionTracker.awaitNewVersion(inv);
return false;
} }
} }
@ -502,6 +521,7 @@ public class ChuteBlockEntity extends SmartBlockEntity implements IHaveGoggleInf
public void setItem(ItemStack stack, float insertionPos) { public void setItem(ItemStack stack, float insertionPos) {
item = stack; item = stack;
itemPosition.startWithValue(insertionPos); itemPosition.startWithValue(insertionPos);
invVersionTracker.reset();
if (!level.isClientSide) { if (!level.isClientSide) {
notifyUpdate(); notifyUpdate();
award(AllAdvancements.CHUTE); award(AllAdvancements.CHUTE);

View file

@ -51,7 +51,8 @@ public class SmartChuteBlockEntity extends ChuteBlockEntity {
@Override @Override
public void addBehaviours(List<BlockEntityBehaviour> behaviours) { public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
behaviours.add(filtering = behaviours.add(filtering =
new FilteringBehaviour(this, new SmartChuteFilterSlotPositioning()).showCountWhen(this::isExtracting)); new FilteringBehaviour(this, new SmartChuteFilterSlotPositioning()).showCountWhen(this::isExtracting)
.withCallback($ -> invVersionTracker.reset()));
super.addBehaviours(behaviours); super.addBehaviours(behaviours);
} }

View file

@ -240,7 +240,7 @@ public class DepotBehaviour extends BlockEntityBehaviour {
public void addSubBehaviours(List<BlockEntityBehaviour> behaviours) { public void addSubBehaviours(List<BlockEntityBehaviour> behaviours) {
behaviours.add(new DirectBeltInputBehaviour(blockEntity).allowingBeltFunnels() behaviours.add(new DirectBeltInputBehaviour(blockEntity).allowingBeltFunnels()
.setInsertionHandler(this::tryInsertingFromSide)); .setInsertionHandler(this::tryInsertingFromSide).considerOccupiedWhen(this::isOccupied));
transportedHandler = new TransportedItemStackHandlerBehaviour(blockEntity, this::applyToAllItems) transportedHandler = new TransportedItemStackHandlerBehaviour(blockEntity, this::applyToAllItems)
.withStackPlacement(this::getWorldPositionOf); .withStackPlacement(this::getWorldPositionOf);
behaviours.add(transportedHandler); behaviours.add(transportedHandler);
@ -339,14 +339,20 @@ public class DepotBehaviour extends BlockEntityBehaviour {
return lazyItemHandler.cast(); return lazyItemHandler.cast();
} }
private boolean isOccupied(Direction side) {
if (!getHeldItemStack().isEmpty() && !canMergeItems())
return true;
if (!isOutputEmpty() && !canMergeItems())
return true;
if (!canAcceptItems.get())
return true;
return false;
}
private ItemStack tryInsertingFromSide(TransportedItemStack transportedStack, Direction side, boolean simulate) { private ItemStack tryInsertingFromSide(TransportedItemStack transportedStack, Direction side, boolean simulate) {
ItemStack inserted = transportedStack.stack; ItemStack inserted = transportedStack.stack;
if (!getHeldItemStack().isEmpty() && !canMergeItems()) if (isOccupied(side))
return inserted;
if (!isOutputEmpty() && !canMergeItems())
return inserted;
if (!canAcceptItems.get())
return inserted; return inserted;
int size = transportedStack.stack.getCount(); int size = transportedStack.stack.getCount();

View file

@ -8,7 +8,6 @@ import javax.annotation.Nonnull;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.AllKeys; import com.simibubi.create.AllKeys;
import com.simibubi.create.content.fluids.transfer.GenericItemEmptying;
import com.simibubi.create.content.logistics.filter.AttributeFilterMenu.WhitelistMode; import com.simibubi.create.content.logistics.filter.AttributeFilterMenu.WhitelistMode;
import com.simibubi.create.foundation.item.ItemHelper; import com.simibubi.create.foundation.item.ItemHelper;
import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.foundation.utility.CreateLang;
@ -34,7 +33,6 @@ import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraftforge.items.ItemStackHandler; import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.network.NetworkHooks; import net.minecraftforge.network.NetworkHooks;
@ -189,146 +187,7 @@ public class FilterItem extends Item implements MenuProvider {
return newInv; return newInv;
} }
public static boolean test(Level world, ItemStack stack, ItemStack filter) { public static boolean testDirect(ItemStack filter, ItemStack stack, boolean matchNBT) {
return test(world, stack, filter, false);
}
public static boolean test(Level world, FluidStack stack, ItemStack filter) {
return test(world, stack, filter, true);
}
public static boolean test(Level world, ItemStack stack, ItemStack filter, boolean matchNBT) {
if (filter.isEmpty())
return true;
if (!(filter.getItem() instanceof FilterItem))
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 = 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()) {
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);
if (attribute == null)
continue;
boolean matches = attribute.appliesTo(stack, world) != compound.getBoolean("Inverted");
if (matches) {
switch (whitelistMode) {
case BLACKLIST:
return false;
case WHITELIST_CONJ:
continue;
case WHITELIST_DISJ:
return true;
}
} else {
switch (whitelistMode) {
case BLACKLIST:
continue;
case WHITELIST_CONJ:
return false;
case WHITELIST_DISJ:
continue;
}
}
}
switch (whitelistMode) {
case BLACKLIST:
return true;
case WHITELIST_CONJ:
return true;
case WHITELIST_DISJ:
return false;
}
}
return false;
}
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 (!GenericItemEmptying.canItemBeEmptied(world, filter))
return false;
FluidStack fluidInFilter = GenericItemEmptying.emptyItem(world, filter, true)
.getFirst();
if (fluidInFilter == null)
return false;
if (!matchNBT)
return fluidInFilter.getFluid()
.isSame(stack.getFluid());
boolean fluidEqual = fluidInFilter.isFluidEqual(stack);
return fluidEqual;
}
boolean defaults = !filter.hasTag();
if (AllItems.FILTER.get() == filter.getItem()) {
ItemStackHandler filterItems = getFilterItems(filter);
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())
continue;
boolean matches = test(world, stack, stackInSlot, respectNBT);
if (matches)
return !blacklist;
}
return blacklist;
}
return false;
}
private static boolean testDirect(ItemStack filter, ItemStack stack, boolean matchNBT) {
if (matchNBT) { if (matchNBT) {
return ItemHandlerHelper.canItemStacksStack(filter, stack); return ItemHandlerHelper.canItemStacksStack(filter, stack);
} else { } else {

View file

@ -0,0 +1,235 @@
package com.simibubi.create.content.logistics.filter;
import java.util.ArrayList;
import java.util.List;
import com.simibubi.create.AllItems;
import com.simibubi.create.content.fluids.transfer.GenericItemEmptying;
import net.createmod.catnip.utility.Pair;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.Tag;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.items.ItemStackHandler;
public class FilterItemStack {
private ItemStack filterItemStack;
private boolean fluidExtracted;
private FluidStack filterFluidStack;
public static FilterItemStack of(ItemStack filter) {
if (filter.hasTag()) {
if (AllItems.FILTER.isIn(filter))
return new ListFilterItemStack(filter);
if (AllItems.ATTRIBUTE_FILTER.isIn(filter))
return new AttributeFilterItemStack(filter);
}
return new FilterItemStack(filter);
}
public static FilterItemStack of(CompoundTag tag) {
return of(ItemStack.of(tag));
}
public static FilterItemStack empty() {
return of(ItemStack.EMPTY);
}
public boolean isEmpty() {
return filterItemStack.isEmpty();
}
public CompoundTag serializeNBT() {
return filterItemStack.serializeNBT();
}
public ItemStack item() {
return filterItemStack;
}
public FluidStack fluid(Level level) {
resolveFluid(level);
return filterFluidStack;
}
public boolean isFilterItem() {
return filterItemStack.getItem() instanceof FilterItem;
}
//
public boolean test(Level world, ItemStack stack) {
return test(world, stack, false);
}
public boolean test(Level world, FluidStack stack) {
return test(world, stack, true);
}
public boolean test(Level world, ItemStack stack, boolean matchNBT) {
if (isEmpty())
return true;
return FilterItem.testDirect(filterItemStack, stack, matchNBT);
}
public boolean test(Level world, FluidStack stack, boolean matchNBT) {
if (isEmpty())
return true;
if (stack.isEmpty())
return false;
resolveFluid(world);
if (filterFluidStack.isEmpty())
return false;
if (!matchNBT)
return filterFluidStack.getFluid()
.isSame(stack.getFluid());
return filterFluidStack.isFluidEqual(stack);
}
//
private void resolveFluid(Level world) {
if (!fluidExtracted) {
fluidExtracted = true;
if (GenericItemEmptying.canItemBeEmptied(world, filterItemStack))
filterFluidStack = GenericItemEmptying.emptyItem(world, filterItemStack, true)
.getFirst();
}
}
protected FilterItemStack(ItemStack filter) {
filterItemStack = filter;
filterFluidStack = FluidStack.EMPTY;
fluidExtracted = false;
}
public static class ListFilterItemStack extends FilterItemStack {
public List<FilterItemStack> containedItems;
public boolean shouldRespectNBT;
public boolean isBlacklist;
protected ListFilterItemStack(ItemStack filter) {
super(filter);
boolean defaults = !filter.hasTag();
containedItems = new ArrayList<>();
ItemStackHandler items = FilterItem.getFilterItems(filter);
for (int i = 0; i < items.getSlots(); i++) {
ItemStack stackInSlot = items.getStackInSlot(i);
if (!stackInSlot.isEmpty())
containedItems.add(FilterItemStack.of(stackInSlot));
}
shouldRespectNBT = !defaults ? false
: filter.getTag()
.getBoolean("RespectNBT");
isBlacklist = defaults ? false
: filter.getTag()
.getBoolean("Blacklist");
}
@Override
public boolean test(Level world, ItemStack stack, boolean matchNBT) {
if (containedItems.isEmpty())
return super.test(world, stack, matchNBT);
for (FilterItemStack filterItemStack : containedItems)
if (filterItemStack.test(world, stack, shouldRespectNBT))
return !isBlacklist;
return isBlacklist;
}
@Override
public boolean test(Level world, FluidStack stack, boolean matchNBT) {
for (FilterItemStack filterItemStack : containedItems)
if (filterItemStack.test(world, stack, shouldRespectNBT))
return !isBlacklist;
return isBlacklist;
}
}
public static class AttributeFilterItemStack extends FilterItemStack {
public enum WhitelistMode {
WHITELIST_DISJ, WHITELIST_CONJ, BLACKLIST;
}
public WhitelistMode whitelistMode;
public List<Pair<ItemAttribute, Boolean>> attributeTests;
protected AttributeFilterItemStack(ItemStack filter) {
super(filter);
boolean defaults = !filter.hasTag();
attributeTests = new ArrayList<>();
whitelistMode = WhitelistMode.values()[defaults ? 0
: filter.getTag()
.getInt("WhitelistMode")];
ListTag attributes = defaults ? new ListTag()
: filter.getTag()
.getList("MatchedAttributes", Tag.TAG_COMPOUND);
for (Tag inbt : attributes) {
CompoundTag compound = (CompoundTag) inbt;
ItemAttribute attribute = ItemAttribute.fromNBT(compound);
if (attribute != null)
attributeTests.add(Pair.of(attribute, compound.getBoolean("Inverted")));
}
}
@Override
public boolean test(Level world, FluidStack stack, boolean matchNBT) {
return false;
}
@Override
public boolean test(Level world, ItemStack stack, boolean matchNBT) {
if (attributeTests.isEmpty())
return super.test(world, stack, matchNBT);
for (Pair<ItemAttribute, Boolean> test : attributeTests) {
ItemAttribute attribute = test.getFirst();
boolean inverted = test.getSecond();
boolean matches = attribute.appliesTo(stack, world) != inverted;
if (matches) {
switch (whitelistMode) {
case BLACKLIST -> {
return false;
}
case WHITELIST_CONJ -> {
continue;
}
case WHITELIST_DISJ -> {
return true;
}
}
} else {
switch (whitelistMode) {
case BLACKLIST, WHITELIST_DISJ -> {
continue;
}
case WHITELIST_CONJ -> {
return false;
}
}
}
}
return switch (whitelistMode) {
case BLACKLIST, WHITELIST_CONJ -> true;
case WHITELIST_DISJ -> false;
};
}
}
}

View file

@ -3,6 +3,8 @@ package com.simibubi.create.content.logistics.funnel;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.List; import java.util.List;
import org.apache.commons.lang3.mutable.MutableBoolean;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllPackets; import com.simibubi.create.AllPackets;
@ -18,6 +20,7 @@ import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; 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.FilteringBehaviour;
import com.simibubi.create.foundation.blockEntity.behaviour.inventory.InvManipulationBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.inventory.InvManipulationBehaviour;
import com.simibubi.create.foundation.blockEntity.behaviour.inventory.VersionedInventoryTrackerBehaviour;
import com.simibubi.create.foundation.item.ItemHelper.ExtractionCountMode; import com.simibubi.create.foundation.item.ItemHelper.ExtractionCountMode;
import com.simibubi.create.infrastructure.config.AllConfigs; import com.simibubi.create.infrastructure.config.AllConfigs;
@ -42,6 +45,7 @@ public class FunnelBlockEntity extends SmartBlockEntity implements IHaveHovering
private FilteringBehaviour filtering; private FilteringBehaviour filtering;
private InvManipulationBehaviour invManipulation; private InvManipulationBehaviour invManipulation;
private VersionedInventoryTrackerBehaviour invVersionTracker;
private int extractionCooldown; private int extractionCooldown;
private WeakReference<ItemEntity> lastObserved; // In-world Extractors only private WeakReference<ItemEntity> lastObserved; // In-world Extractors only
@ -111,6 +115,9 @@ public class FunnelBlockEntity extends SmartBlockEntity implements IHaveHovering
} }
private void activateExtractor() { private void activateExtractor() {
if (invVersionTracker.stillWaiting(invManipulation))
return;
BlockState blockState = getBlockState(); BlockState blockState = getBlockState();
Direction facing = AbstractFunnelBlock.getFunnelFacing(blockState); Direction facing = AbstractFunnelBlock.getFunnelFacing(blockState);
@ -140,8 +147,10 @@ public class FunnelBlockEntity extends SmartBlockEntity implements IHaveHovering
ExtractionCountMode mode = getModeToExtract(); ExtractionCountMode mode = getModeToExtract();
ItemStack stack = invManipulation.simulate() ItemStack stack = invManipulation.simulate()
.extract(mode, amountToExtract); .extract(mode, amountToExtract);
if (stack.isEmpty()) if (stack.isEmpty()) {
invVersionTracker.awaitNewVersion(invManipulation);
return; return;
}
for (ItemEntity itemEntity : level.getEntitiesOfClass(ItemEntity.class, area)) { for (ItemEntity itemEntity : level.getEntitiesOfClass(ItemEntity.class, area)) {
lastObserved = new WeakReference<>(itemEntity); lastObserved = new WeakReference<>(itemEntity);
return; return;
@ -189,6 +198,9 @@ public class FunnelBlockEntity extends SmartBlockEntity implements IHaveHovering
} }
private void activateExtractingBeltFunnel() { private void activateExtractingBeltFunnel() {
if (invVersionTracker.stillWaiting(invManipulation))
return;
BlockState blockState = getBlockState(); BlockState blockState = getBlockState();
Direction facing = blockState.getValue(BeltFunnelBlock.HORIZONTAL_FACING); Direction facing = blockState.getValue(BeltFunnelBlock.HORIZONTAL_FACING);
DirectBeltInputBehaviour inputBehaviour = DirectBeltInputBehaviour inputBehaviour =
@ -198,14 +210,24 @@ public class FunnelBlockEntity extends SmartBlockEntity implements IHaveHovering
return; return;
if (!inputBehaviour.canInsertFromSide(facing)) if (!inputBehaviour.canInsertFromSide(facing))
return; return;
if (inputBehaviour.isOccupied(facing))
return;
int amountToExtract = getAmountToExtract(); int amountToExtract = getAmountToExtract();
ExtractionCountMode mode = getModeToExtract(); ExtractionCountMode mode = getModeToExtract();
ItemStack stack = MutableBoolean deniedByInsertion = new MutableBoolean(false);
invManipulation.extract(mode, amountToExtract, s -> inputBehaviour.handleInsertion(s, facing, true) ItemStack stack = invManipulation.extract(mode, amountToExtract, s -> {
.isEmpty()); ItemStack handleInsertion = inputBehaviour.handleInsertion(s, facing, true);
if (stack.isEmpty()) if (handleInsertion.isEmpty())
return true;
deniedByInsertion.setTrue();
return false;
});
if (stack.isEmpty()) {
if (deniedByInsertion.isFalse())
invVersionTracker.awaitNewVersion(invManipulation.getInventory());
return; return;
}
flap(false); flap(false);
onTransfer(stack); onTransfer(stack);
inputBehaviour.handleInsertion(stack, facing, false); inputBehaviour.handleInsertion(stack, facing, false);
@ -237,12 +259,15 @@ public class FunnelBlockEntity extends SmartBlockEntity implements IHaveHovering
new InvManipulationBehaviour(this, (w, p, s) -> new BlockFace(p, AbstractFunnelBlock.getFunnelFacing(s) new InvManipulationBehaviour(this, (w, p, s) -> new BlockFace(p, AbstractFunnelBlock.getFunnelFacing(s)
.getOpposite())); .getOpposite()));
behaviours.add(invManipulation); behaviours.add(invManipulation);
behaviours.add(invVersionTracker = new VersionedInventoryTrackerBehaviour(this));
filtering = new FilteringBehaviour(this, new FunnelFilterSlotPositioning()); filtering = new FilteringBehaviour(this, new FunnelFilterSlotPositioning());
filtering.showCountWhen(this::supportsAmountOnFilter); filtering.showCountWhen(this::supportsAmountOnFilter);
filtering.onlyActiveWhen(this::supportsFiltering); filtering.onlyActiveWhen(this::supportsFiltering);
filtering.withCallback($ -> invVersionTracker.reset());
behaviours.add(filtering); behaviours.add(filtering);
behaviours.add(new DirectBeltInputBehaviour(this).onlyInsertWhen(this::supportsDirectBeltInput) behaviours.add(new DirectBeltInputBehaviour(this).onlyInsertWhen(this::supportsDirectBeltInput)
.setInsertionHandler(this::handleDirectBeltInput)); .setInsertionHandler(this::handleDirectBeltInput));
registerAwardables(behaviours, AllAdvancements.FUNNEL); registerAwardables(behaviours, AllAdvancements.FUNNEL);

View file

@ -4,7 +4,7 @@ import java.util.List;
import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour;
import com.simibubi.create.content.contraptions.behaviour.MovementContext; import com.simibubi.create.content.contraptions.behaviour.MovementContext;
import com.simibubi.create.content.logistics.filter.FilterItem; import com.simibubi.create.content.logistics.filter.FilterItemStack;
import com.simibubi.create.foundation.item.ItemHelper; import com.simibubi.create.foundation.item.ItemHelper;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@ -71,14 +71,14 @@ public class FunnelMovementBehaviour implements MovementBehaviour {
.isEmpty()) .isEmpty())
return; return;
ItemStack filter = getFilter(context); FilterItemStack filter = context.getFilterFromBE();
int filterAmount = context.blockEntityData.getInt("FilterAmount"); int filterAmount = context.blockEntityData.getInt("FilterAmount");
boolean upTo = context.blockEntityData.getBoolean("UpTo"); boolean upTo = context.blockEntityData.getBoolean("UpTo");
if (filterAmount <= 0) if (filterAmount <= 0)
filterAmount = hasFilter ? 64 : 1; filterAmount = hasFilter ? 64 : 1;
ItemStack extract = ItemHelper.extract(context.contraption.getSharedInventory(), ItemStack extract = ItemHelper.extract(context.contraption.getSharedInventory(),
s -> FilterItem.test(world, s, filter), s -> filter.test(world, s),
upTo ? ItemHelper.ExtractionCountMode.UPTO : ItemHelper.ExtractionCountMode.EXACTLY, filterAmount, false); upTo ? ItemHelper.ExtractionCountMode.UPTO : ItemHelper.ExtractionCountMode.EXACTLY, filterAmount, false);
if (extract.isEmpty()) if (extract.isEmpty())
@ -97,13 +97,13 @@ public class FunnelMovementBehaviour implements MovementBehaviour {
private void succ(MovementContext context, BlockPos pos) { private void succ(MovementContext context, BlockPos pos) {
Level world = context.world; Level world = context.world;
List<ItemEntity> items = world.getEntitiesOfClass(ItemEntity.class, new AABB(pos)); List<ItemEntity> items = world.getEntitiesOfClass(ItemEntity.class, new AABB(pos));
ItemStack filter = getFilter(context); FilterItemStack filter = context.getFilterFromBE();
for (ItemEntity item : items) { for (ItemEntity item : items) {
if (!item.isAlive()) if (!item.isAlive())
continue; continue;
ItemStack toInsert = item.getItem(); ItemStack toInsert = item.getItem();
if (!filter.isEmpty() && !FilterItem.test(context.world, toInsert, filter)) if (!filter.test(context.world, toInsert))
continue; continue;
ItemStack remainder = ItemStack remainder =
ItemHandlerHelper.insertItemStacked(context.contraption.getSharedInventory(), toInsert, false); ItemHandlerHelper.insertItemStacked(context.contraption.getSharedInventory(), toInsert, false);
@ -124,8 +124,4 @@ public class FunnelMovementBehaviour implements MovementBehaviour {
return true; return true;
} }
private ItemStack getFilter(MovementContext context) {
return hasFilter ? ItemStack.of(context.blockEntityData.getCompound("Filter")) : ItemStack.EMPTY;
}
} }

View file

@ -53,7 +53,7 @@ public class ItemVaultBlock extends Block implements IWrenchable, IBE<ItemVaultB
@Override @Override
public BlockState getStateForPlacement(BlockPlaceContext pContext) { public BlockState getStateForPlacement(BlockPlaceContext pContext) {
if (pContext.getPlayer() == null || !pContext.getPlayer() if (pContext.getPlayer() == null || !pContext.getPlayer()
.isSteppingCarefully()) { .isShiftKeyDown()) {
BlockState placedOn = pContext.getLevel() BlockState placedOn = pContext.getLevel()
.getBlockState(pContext.getClickedPos() .getBlockState(pContext.getClickedPos()
.relative(pContext.getClickedFace() .relative(pContext.getClickedFace()

View file

@ -7,6 +7,7 @@ import com.simibubi.create.api.connectivity.ConnectivityHandler;
import com.simibubi.create.foundation.blockEntity.IMultiBlockEntityContainer; import com.simibubi.create.foundation.blockEntity.IMultiBlockEntityContainer;
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour;
import com.simibubi.create.foundation.blockEntity.behaviour.inventory.VersionedInventoryWrapper;
import com.simibubi.create.infrastructure.config.AllConfigs; import com.simibubi.create.infrastructure.config.AllConfigs;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@ -260,8 +261,8 @@ public class ItemVaultBlockEntity extends SmartBlockEntity implements IMultiBloc
} }
} }
CombinedInvWrapper combinedInvWrapper = new CombinedInvWrapper(invs); IItemHandler itemHandler = new VersionedInventoryWrapper(new CombinedInvWrapper(invs));
itemCapability = LazyOptional.of(() -> combinedInvWrapper); itemCapability = LazyOptional.of(() -> itemHandler);
} }
public static int getMaxLength(int radius) { public static int getMaxLength(int radius) {

View file

@ -54,7 +54,7 @@ public class ItemVaultItem extends BlockItem {
Player player = ctx.getPlayer(); Player player = ctx.getPlayer();
if (player == null) if (player == null)
return; return;
if (player.isSteppingCarefully()) if (player.isShiftKeyDown())
return; return;
Direction face = ctx.getClickedFace(); Direction face = ctx.getClickedFace();
ItemStack stack = ctx.getItemInHand(); ItemStack stack = ctx.getItemInHand();

View file

@ -34,7 +34,7 @@ public class ExperienceNuggetItem extends Item {
return InteractionResultHolder.consume(itemInHand); return InteractionResultHolder.consume(itemInHand);
} }
int amountUsed = pPlayer.isSteppingCarefully() ? 1 : itemInHand.getCount(); int amountUsed = pPlayer.isShiftKeyDown() ? 1 : itemInHand.getCount();
int total = Mth.ceil(3f * amountUsed); int total = Mth.ceil(3f * amountUsed);
int maxOrbs = amountUsed == 1 ? 1 : 5; int maxOrbs = amountUsed == 1 ? 1 : 5;
int valuePer = Math.max(1, 1 + total / maxOrbs); int valuePer = Math.max(1, 1 + total / maxOrbs);

View file

@ -28,6 +28,7 @@ import com.simibubi.create.foundation.blockEntity.behaviour.inventory.InvManipul
import com.simibubi.create.foundation.fluid.CombinedTankWrapper; import com.simibubi.create.foundation.fluid.CombinedTankWrapper;
import com.simibubi.create.foundation.item.ItemHelper; import com.simibubi.create.foundation.item.ItemHelper;
import com.simibubi.create.foundation.item.SmartInventory; import com.simibubi.create.foundation.item.SmartInventory;
import com.simibubi.create.foundation.utility.BlockHelper;
import com.simibubi.create.foundation.utility.CreateLang; import com.simibubi.create.foundation.utility.CreateLang;
import net.createmod.catnip.utility.AnimationTickHolder; import net.createmod.catnip.utility.AnimationTickHolder;
@ -602,7 +603,7 @@ public class BasinBlockEntity extends SmartBlockEntity implements IHaveGoggleInf
public static HeatLevel getHeatLevelOf(BlockState state) { public static HeatLevel getHeatLevelOf(BlockState state) {
if (state.hasProperty(BlazeBurnerBlock.HEAT_LEVEL)) if (state.hasProperty(BlazeBurnerBlock.HEAT_LEVEL))
return state.getValue(BlazeBurnerBlock.HEAT_LEVEL); return state.getValue(BlazeBurnerBlock.HEAT_LEVEL);
return AllTags.AllBlockTags.PASSIVE_BOILER_HEATERS.matches(state) ? HeatLevel.SMOULDERING : HeatLevel.NONE; return AllTags.AllBlockTags.PASSIVE_BOILER_HEATERS.matches(state) && BlockHelper.isNotUnheated(state) ? HeatLevel.SMOULDERING : HeatLevel.NONE;
} }
public Couple<SmartFluidTankBehaviour> getTanks() { public Couple<SmartFluidTankBehaviour> getTanks() {

View file

@ -3,17 +3,18 @@ package com.simibubi.create.content.processing.burner;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import javax.annotation.ParametersAreNonnullByDefault; import javax.annotation.ParametersAreNonnullByDefault;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllTags.AllEntityTags;
import net.createmod.catnip.platform.CatnipServices; import net.createmod.catnip.platform.CatnipServices;
import net.createmod.catnip.utility.VecHelper; import net.createmod.catnip.utility.VecHelper;
import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.particles.ParticleTypes; import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource; import net.minecraft.sounds.SoundSource;
import net.minecraft.util.random.WeightedEntry.Wrapper; import net.minecraft.util.random.WeightedEntry.Wrapper;
@ -21,7 +22,6 @@ import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.monster.Blaze;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.Item; import net.minecraft.world.item.Item;
@ -91,11 +91,9 @@ public class BlazeBurnerBlockItem extends BlockItem {
possibleSpawns.add(spawner.nextSpawnData); possibleSpawns.add(spawner.nextSpawnData);
} }
ResourceLocation blazeId = CatnipServices.REGISTRIES.getKeyOrThrow(EntityType.BLAZE);
for (SpawnData e : possibleSpawns) { for (SpawnData e : possibleSpawns) {
ResourceLocation spawnerEntityId = new ResourceLocation(e.entityToSpawn() Optional<EntityType<?>> optionalEntity = EntityType.by(e.entityToSpawn());
.getString("id")); if (optionalEntity.isEmpty() || !AllEntityTags.BLAZE_BURNER_CAPTURABLE.matches(optionalEntity.get()))
if (!spawnerEntityId.equals(blazeId))
continue; continue;
spawnCaptureEffects(world, VecHelper.getCenterOf(pos)); spawnCaptureEffects(world, VecHelper.getCenterOf(pos));
@ -114,7 +112,7 @@ public class BlazeBurnerBlockItem extends BlockItem {
InteractionHand hand) { InteractionHand hand) {
if (hasCapturedBlaze()) if (hasCapturedBlaze())
return InteractionResult.PASS; return InteractionResult.PASS;
if (!(entity instanceof Blaze)) if (!AllEntityTags.BLAZE_BURNER_CAPTURABLE.matches(entity))
return InteractionResult.PASS; return InteractionResult.PASS;
Level world = player.level(); Level world = player.level();

View file

@ -33,12 +33,11 @@ public class AnalogLeverInstance extends BlockEntityInstance<AnalogLeverBlockEnt
indicator = mat.getModel(AllPartialModels.ANALOG_LEVER_INDICATOR, blockState) indicator = mat.getModel(AllPartialModels.ANALOG_LEVER_INDICATOR, blockState)
.createInstance(); .createInstance();
transform(indicator);
AttachFace face = blockState.getValue(AnalogLeverBlock.FACE); AttachFace face = blockState.getValue(AnalogLeverBlock.FACE);
rX = face == AttachFace.FLOOR ? 0 : face == AttachFace.WALL ? 90 : 180; rX = face == AttachFace.FLOOR ? 0 : face == AttachFace.WALL ? 90 : 180;
rY = AngleHelper.horizontalAngle(blockState.getValue(AnalogLeverBlock.FACING)); rY = AngleHelper.horizontalAngle(blockState.getValue(AnalogLeverBlock.FACING));
transform(indicator.loadIdentity());
animateLever(); animateLever();
} }

View file

@ -139,7 +139,7 @@ public class DisplayLinkBlock extends WrenchableDirectionalBlock implements IBE<
BlockHitResult pHit) { BlockHitResult pHit) {
if (pPlayer == null) if (pPlayer == null)
return InteractionResult.PASS; return InteractionResult.PASS;
if (pPlayer.isSteppingCarefully()) if (pPlayer.isShiftKeyDown())
return InteractionResult.PASS; return InteractionResult.PASS;
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, DistExecutor.unsafeRunWhenOn(Dist.CLIENT,
() -> () -> withBlockEntityDo(pLevel, pPos, be -> this.displayScreen(be, pPlayer))); () -> () -> withBlockEntityDo(pLevel, pPos, be -> this.displayScreen(be, pPlayer)));

View file

@ -57,7 +57,7 @@ public class DisplayLinkBlockItem extends BlockItem {
if (player == null) if (player == null)
return InteractionResult.FAIL; return InteractionResult.FAIL;
if (player.isSteppingCarefully() && stack.hasTag()) { if (player.isShiftKeyDown() && stack.hasTag()) {
if (level.isClientSide) if (level.isClientSide)
return InteractionResult.SUCCESS; return InteractionResult.SUCCESS;
player.displayClientMessage(CreateLang.translateDirect("display_link.clear"), true); player.displayClientMessage(CreateLang.translateDirect("display_link.clear"), true);

View file

@ -83,7 +83,7 @@ public class SmartObserverBlock extends DirectedDirectionalBlock implements IBE<
if (preferredFacing == null) { if (preferredFacing == null) {
Direction facing = context.getNearestLookingDirection(); Direction facing = context.getNearestLookingDirection();
preferredFacing = context.getPlayer() != null && context.getPlayer() preferredFacing = context.getPlayer() != null && context.getPlayer()
.isSteppingCarefully() ? facing : facing.getOpposite(); .isShiftKeyDown() ? facing : facing.getOpposite();
} }
if (preferredFacing.getAxis() == Axis.Y) { if (preferredFacing.getAxis() == Axis.Y) {
@ -101,7 +101,7 @@ public class SmartObserverBlock extends DirectedDirectionalBlock implements IBE<
@Override @Override
public int getSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { public int getSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) {
return isSignalSource(blockState) && (side == null || side != blockState.getValue(FACING) return isSignalSource(blockState) && (side == null || side != getTargetDirection(blockState)
.getOpposite()) ? 15 : 0; .getOpposite()) ? 15 : 0;
} }

View file

@ -14,6 +14,7 @@ import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringB
import com.simibubi.create.foundation.blockEntity.behaviour.inventory.CapManipulationBehaviourBase.InterfaceProvider; 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.InvManipulationBehaviour;
import com.simibubi.create.foundation.blockEntity.behaviour.inventory.TankManipulationBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.inventory.TankManipulationBehaviour;
import com.simibubi.create.foundation.blockEntity.behaviour.inventory.VersionedInventoryTrackerBehaviour;
import net.createmod.catnip.utility.BlockFace; import net.createmod.catnip.utility.BlockFace;
import net.createmod.catnip.utility.Iterate; import net.createmod.catnip.utility.Iterate;
@ -31,6 +32,10 @@ public class SmartObserverBlockEntity extends SmartBlockEntity {
private FilteringBehaviour filtering; private FilteringBehaviour filtering;
private InvManipulationBehaviour observedInventory; private InvManipulationBehaviour observedInventory;
private TankManipulationBehaviour observedTank; private TankManipulationBehaviour observedTank;
private VersionedInventoryTrackerBehaviour invVersionTracker;
private boolean sustainSignal;
public int turnOffTicks = 0; public int turnOffTicks = 0;
public SmartObserverBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) { public SmartObserverBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
@ -40,7 +45,9 @@ public class SmartObserverBlockEntity extends SmartBlockEntity {
@Override @Override
public void addBehaviours(List<BlockEntityBehaviour> behaviours) { public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
behaviours.add(filtering = new FilteringBehaviour(this, new FilteredDetectorFilterSlot(false))); behaviours.add(filtering = new FilteringBehaviour(this, new FilteredDetectorFilterSlot(false))
.withCallback($ -> invVersionTracker.reset()));
behaviours.add(invVersionTracker = new VersionedInventoryTrackerBehaviour(this));
InterfaceProvider towardBlockFacing = InterfaceProvider towardBlockFacing =
(w, p, s) -> new BlockFace(p, DirectedDirectionalBlock.getTargetDirection(s)); (w, p, s) -> new BlockFace(p, DirectedDirectionalBlock.getTargetDirection(s));
@ -105,11 +112,23 @@ public class SmartObserverBlockEntity extends SmartBlockEntity {
return; return;
} }
if (!observedInventory.simulate() if (observedInventory.hasInventory()) {
.extract() boolean skipInv = invVersionTracker.stillWaiting(observedInventory);
.isEmpty()) { invVersionTracker.awaitNewVersion(observedInventory);
activate();
return; if (skipInv && sustainSignal)
turnOffTicks = DEFAULT_DELAY;
if (!skipInv) {
sustainSignal = false;
if (!observedInventory.simulate()
.extract()
.isEmpty()) {
sustainSignal = true;
activate();
return;
}
}
} }
if (!observedTank.simulate() if (!observedTank.simulate()

View file

@ -54,7 +54,7 @@ public class ThresholdSwitchBlock extends DirectedDirectionalBlock implements IB
@Override @Override
public boolean canConnectRedstone(BlockState state, BlockGetter world, BlockPos pos, Direction side) { public boolean canConnectRedstone(BlockState state, BlockGetter world, BlockPos pos, Direction side) {
return side != null && side.getOpposite() != state.getValue(FACING); return side != null && side.getOpposite() != getTargetDirection(state);
} }
@Override @Override
@ -64,7 +64,7 @@ public class ThresholdSwitchBlock extends DirectedDirectionalBlock implements IB
@Override @Override
public int getSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) { public int getSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) {
if (side == blockState.getValue(FACING) if (side == getTargetDirection(blockState)
.getOpposite()) .getOpposite())
return 0; return 0;
return getBlockEntityOptional(blockAccess, pos).filter(ThresholdSwitchBlockEntity::isPowered) return getBlockEntityOptional(blockAccess, pos).filter(ThresholdSwitchBlockEntity::isPowered)
@ -121,7 +121,7 @@ public class ThresholdSwitchBlock extends DirectedDirectionalBlock implements IB
if (preferredFacing == null) { if (preferredFacing == null) {
Direction facing = context.getNearestLookingDirection(); Direction facing = context.getNearestLookingDirection();
preferredFacing = context.getPlayer() != null && context.getPlayer() preferredFacing = context.getPlayer() != null && context.getPlayer()
.isSteppingCarefully() ? facing : facing.getOpposite(); .isShiftKeyDown() ? facing : facing.getOpposite();
} }
if (preferredFacing.getAxis() == Axis.Y) { if (preferredFacing.getAxis() == Axis.Y) {

View file

@ -12,6 +12,7 @@ import com.simibubi.create.foundation.blockEntity.behaviour.filtering.FilteringB
import com.simibubi.create.foundation.blockEntity.behaviour.inventory.CapManipulationBehaviourBase.InterfaceProvider; 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.InvManipulationBehaviour;
import com.simibubi.create.foundation.blockEntity.behaviour.inventory.TankManipulationBehaviour; import com.simibubi.create.foundation.blockEntity.behaviour.inventory.TankManipulationBehaviour;
import com.simibubi.create.foundation.blockEntity.behaviour.inventory.VersionedInventoryTrackerBehaviour;
import net.createmod.catnip.utility.BlockFace; import net.createmod.catnip.utility.BlockFace;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@ -39,6 +40,7 @@ public class ThresholdSwitchBlockEntity extends SmartBlockEntity {
private FilteringBehaviour filtering; private FilteringBehaviour filtering;
private InvManipulationBehaviour observedInventory; private InvManipulationBehaviour observedInventory;
private TankManipulationBehaviour observedTank; private TankManipulationBehaviour observedTank;
private VersionedInventoryTrackerBehaviour invVersionTracker;
public ThresholdSwitchBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) { public ThresholdSwitchBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state); super(type, pos, state);
@ -107,18 +109,26 @@ public class ThresholdSwitchBlockEntity extends SmartBlockEntity {
} else if (observedInventory.hasInventory() || observedTank.hasInventory()) { } else if (observedInventory.hasInventory() || observedTank.hasInventory()) {
if (observedInventory.hasInventory()) { if (observedInventory.hasInventory()) {
// Item inventory // Item inventory
IItemHandler inv = observedInventory.getInventory(); IItemHandler inv = observedInventory.getInventory();
for (int slot = 0; slot < inv.getSlots(); slot++) { if (invVersionTracker.stillWaiting(inv)) {
ItemStack stackInSlot = inv.getStackInSlot(slot); occupied = prevLevel;
int space = Math.min(stackInSlot.getMaxStackSize(), inv.getSlotLimit(slot)); totalSpace = 1f;
int count = stackInSlot.getCount();
if (space == 0)
continue;
totalSpace += 1; } else {
if (filtering.test(stackInSlot)) invVersionTracker.awaitNewVersion(inv);
occupied += count * (1f / space); 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);
}
} }
} }
@ -195,7 +205,12 @@ public class ThresholdSwitchBlockEntity extends SmartBlockEntity {
@Override @Override
public void addBehaviours(List<BlockEntityBehaviour> behaviours) { public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
behaviours.add(filtering = new FilteringBehaviour(this, new FilteredDetectorFilterSlot(true)) behaviours.add(filtering = new FilteringBehaviour(this, new FilteredDetectorFilterSlot(true))
.withCallback($ -> this.updateCurrentLevel())); .withCallback($ -> {
this.updateCurrentLevel();
invVersionTracker.reset();
}));
behaviours.add(invVersionTracker = new VersionedInventoryTrackerBehaviour(this));
InterfaceProvider towardBlockFacing = InterfaceProvider towardBlockFacing =
(w, p, s) -> new BlockFace(p, DirectedDirectionalBlock.getTargetDirection(s)); (w, p, s) -> new BlockFace(p, DirectedDirectionalBlock.getTargetDirection(s));

View file

@ -188,20 +188,19 @@ public class GlobalRailwayManager {
if (level.dimension() != Level.OVERWORLD) if (level.dimension() != Level.OVERWORLD)
return; return;
for (SignalEdgeGroup group : signalEdgeGroups.values()) { signalEdgeGroups.forEach((id, group) -> {
group.trains.clear(); group.trains.clear();
group.reserved = null; group.reserved = null;
} });
for (TrackGraph graph : trackNetworks.values()) { trackNetworks.forEach((id, graph) -> {
graph.tickPoints(true); graph.tickPoints(true);
graph.resolveIntersectingEdgeGroups(level); graph.resolveIntersectingEdgeGroups(level);
} });
tickTrains(level); tickTrains(level);
for (TrackGraph graph : trackNetworks.values()) trackNetworks.forEach((id, graph) -> graph.tickPoints(false));
graph.tickPoints(false);
GlobalTrainDisplayData.updateTick = level.getGameTime() % 100 == 0; GlobalTrainDisplayData.updateTick = level.getGameTime() % 100 == 0;
if (GlobalTrainDisplayData.updateTick) if (GlobalTrainDisplayData.updateTick)

View file

@ -25,6 +25,7 @@ import com.simibubi.create.content.schematics.requirement.ItemRequirement;
import com.simibubi.create.content.trains.entity.Carriage; import com.simibubi.create.content.trains.entity.Carriage;
import com.simibubi.create.content.trains.entity.CarriageBogey; import com.simibubi.create.content.trains.entity.CarriageBogey;
import com.simibubi.create.content.trains.entity.TravellingPoint; import com.simibubi.create.content.trains.entity.TravellingPoint;
import com.simibubi.create.content.trains.graph.TrackEdge;
import com.simibubi.create.content.trains.track.TrackMaterial; import com.simibubi.create.content.trains.track.TrackMaterial;
import com.simibubi.create.foundation.block.IBE; import com.simibubi.create.foundation.block.IBE;
import com.simibubi.create.foundation.block.ProperWaterloggedBlock; import com.simibubi.create.foundation.block.ProperWaterloggedBlock;
@ -75,7 +76,10 @@ public abstract class AbstractBogeyBlock<T extends AbstractBogeyBlockEntity> ext
public boolean isOnIncompatibleTrack(Carriage carriage, boolean leading) { public boolean isOnIncompatibleTrack(Carriage carriage, boolean leading) {
TravellingPoint point = leading ? carriage.getLeadingPoint() : carriage.getTrailingPoint(); TravellingPoint point = leading ? carriage.getLeadingPoint() : carriage.getTrailingPoint();
CarriageBogey bogey = leading ? carriage.leadingBogey() : carriage.trailingBogey(); CarriageBogey bogey = leading ? carriage.leadingBogey() : carriage.trailingBogey();
return point.edge.getTrackMaterial().trackType != getTrackType(bogey.getStyle()); TrackEdge currentEdge = point.edge;
if (currentEdge == null)
return false;
return currentEdge.getTrackMaterial().trackType != getTrackType(bogey.getStyle());
} }
public Set<TrackMaterial.TrackType> getValidPathfindingTypes(BogeyStyle style) { public Set<TrackMaterial.TrackType> getValidPathfindingTypes(BogeyStyle style) {

View file

@ -641,7 +641,7 @@ public class CarriageContraptionEntity extends OrientedContraptionEntity {
if (lookAhead != null) { if (lookAhead != null) {
if (spaceDown) { if (spaceDown) {
carriage.train.manualTick = true; carriage.train.manualTick = true;
nav.startNavigation(lookAhead, -1, false); nav.startNavigation(nav.findPathTo(lookAhead, -1));
carriage.train.manualTick = false; carriage.train.manualTick = false;
navDistanceTotal = nav.distanceToDestination; navDistanceTotal = nav.distanceToDestination;
return true; return true;

View file

@ -304,9 +304,12 @@ public class CarriageSyncData {
TrackNode initialNode1 = forward ? current.node1 : current.node2; TrackNode initialNode1 = forward ? current.node1 : current.node2;
TrackNode initialNode2 = forward ? current.node2 : current.node1; TrackNode initialNode2 = forward ? current.node2 : current.node1;
TrackEdge initialEdge = graph.getConnectionsFrom(initialNode1)
.get(initialNode2); Map<TrackNode, TrackEdge> connectionsFromInitial = graph.getConnectionsFrom(initialNode1);
if (connectionsFromInitial == null)
return -1;
TrackEdge initialEdge = connectionsFromInitial.get(initialNode2);
if (initialEdge == null) if (initialEdge == null)
return -1; // graph changed return -1; // graph changed

View file

@ -21,6 +21,7 @@ import org.apache.commons.lang3.mutable.MutableObject;
import com.simibubi.create.Create; import com.simibubi.create.Create;
import com.simibubi.create.content.trains.entity.TravellingPoint.ITrackSelector; import com.simibubi.create.content.trains.entity.TravellingPoint.ITrackSelector;
import com.simibubi.create.content.trains.graph.DimensionPalette; import com.simibubi.create.content.trains.graph.DimensionPalette;
import com.simibubi.create.content.trains.graph.DiscoveredPath;
import com.simibubi.create.content.trains.graph.EdgeData; import com.simibubi.create.content.trains.graph.EdgeData;
import com.simibubi.create.content.trains.graph.EdgePointType; import com.simibubi.create.content.trains.graph.EdgePointType;
import com.simibubi.create.content.trains.graph.TrackEdge; import com.simibubi.create.content.trains.graph.TrackEdge;
@ -380,15 +381,11 @@ public class Navigation {
train.reservedSignalBlocks.clear(); train.reservedSignalBlocks.clear();
} }
public double startNavigation(GlobalStation destination, double maxCost, boolean simulate) { public double startNavigation(DiscoveredPath pathTo) {
DiscoveredPath pathTo = findPathTo(destination, maxCost);
boolean noneFound = pathTo == null; boolean noneFound = pathTo == null;
double distance = noneFound ? -1 : Math.abs(pathTo.distance); double distance = noneFound ? -1 : Math.abs(pathTo.distance);
double cost = noneFound ? -1 : pathTo.cost; double cost = noneFound ? -1 : pathTo.cost;
if (simulate)
return cost;
distanceToDestination = distance; distanceToDestination = distance;
if (noneFound) { if (noneFound) {
@ -407,10 +404,10 @@ public class Navigation {
train.reservedSignalBlocks.clear(); train.reservedSignalBlocks.clear();
train.navigation.waitingForSignal = null; train.navigation.waitingForSignal = null;
if (this.destination == null && !simulate) if (this.destination == null)
distanceStartedAt = distance; distanceStartedAt = distance;
if (this.destination == destination) if (this.destination == pathTo.destination)
return 0; return 0;
if (!train.runtime.paused) { if (!train.runtime.paused) {
@ -435,12 +432,19 @@ public class Navigation {
train.status.foundConductor(); train.status.foundConductor();
} }
this.destination = destination; this.destination = pathTo.destination;
return cost; return cost;
} }
@Nullable @Nullable
private DiscoveredPath findPathTo(GlobalStation destination, double maxCost) { public DiscoveredPath findPathTo(GlobalStation destination, double maxCost) {
ArrayList<GlobalStation> destinations = new ArrayList<>();
destinations.add(destination);
return findPathTo(destinations, maxCost);
}
@Nullable
public DiscoveredPath findPathTo(ArrayList<GlobalStation> destinations, double maxCost) {
TrackGraph graph = train.graph; TrackGraph graph = train.graph;
if (graph == null) if (graph == null)
return null; return null;
@ -460,34 +464,36 @@ public class Navigation {
: graph.getConnectionsFrom(initialPoint.node2) : graph.getConnectionsFrom(initialPoint.node2)
.get(initialPoint.node1); .get(initialPoint.node1);
search(Double.MAX_VALUE, maxCost, forward, (distance, cost, reachedVia, currentEntry, globalStation) -> { search(Double.MAX_VALUE, maxCost, forward, destinations, (distance, cost, reachedVia, currentEntry, globalStation) -> {
if (globalStation != destination) for (GlobalStation destination : destinations){
return false; if (globalStation == destination) {
TrackEdge edge = currentEntry.getSecond();
TrackNode node1 = currentEntry.getFirst()
.getFirst();
TrackNode node2 = currentEntry.getFirst()
.getSecond();
TrackEdge edge = currentEntry.getSecond(); List<Couple<TrackNode>> currentPath = new ArrayList<>();
TrackNode node1 = currentEntry.getFirst() Pair<Boolean, Couple<TrackNode>> backTrack = reachedVia.get(edge);
.getFirst(); Couple<TrackNode> toReach = Couple.create(node1, node2);
TrackNode node2 = currentEntry.getFirst() TrackEdge edgeReached = edge;
.getSecond(); while (backTrack != null) {
if (edgeReached == initialEdge)
break;
if (backTrack.getFirst())
currentPath.add(0, toReach);
toReach = backTrack.getSecond();
edgeReached = graph.getConnection(toReach);
backTrack = reachedVia.get(edgeReached);
}
List<Couple<TrackNode>> currentPath = new ArrayList<>(); double position = edge.getLength() - destination.getLocationOn(edge);
Pair<Boolean, Couple<TrackNode>> backTrack = reachedVia.get(edge); double distanceToDestination = distance - position;
Couple<TrackNode> toReach = Couple.create(node1, node2); results.set(forward, new DiscoveredPath((forward ? 1 : -1) * distanceToDestination, cost, currentPath, destination));
TrackEdge edgeReached = edge; return true;
while (backTrack != null) { }
if (edgeReached == initialEdge)
break;
if (backTrack.getFirst())
currentPath.add(0, toReach);
toReach = backTrack.getSecond();
edgeReached = graph.getConnection(toReach);
backTrack = reachedVia.get(edgeReached);
} }
return false;
double position = edge.getLength() - destination.getLocationOn(edge);
double distanceToDestination = distance - position;
results.set(forward, new DiscoveredPath((forward ? 1 : -1) * distanceToDestination, cost, currentPath));
return true;
}); });
} }
@ -508,18 +514,6 @@ public class Navigation {
return frontBetter ? front : back; return frontBetter ? front : back;
} }
public class DiscoveredPath {
List<Couple<TrackNode>> path;
double distance;
double cost;
public DiscoveredPath(double distance, double cost, List<Couple<TrackNode>> path) {
this.distance = distance;
this.cost = cost;
this.path = path;
}
}
public GlobalStation findNearestApproachable(boolean forward) { public GlobalStation findNearestApproachable(boolean forward) {
TrackGraph graph = train.graph; TrackGraph graph = train.graph;
if (graph == null) if (graph == null)
@ -530,7 +524,7 @@ public class Navigation {
double minDistance = .75f * (train.speed * train.speed) / (2 * acceleration); double minDistance = .75f * (train.speed * train.speed) / (2 * acceleration);
double maxDistance = Math.max(32, 1.5f * (train.speed * train.speed) / (2 * acceleration)); double maxDistance = Math.max(32, 1.5f * (train.speed * train.speed) / (2 * acceleration));
search(maxDistance, forward, (distance, cost, reachedVia, currentEntry, globalStation) -> { search(maxDistance, forward, null, (distance, cost, reachedVia, currentEntry, globalStation) -> {
if (distance < minDistance) if (distance < minDistance)
return false; return false;
@ -548,11 +542,11 @@ public class Navigation {
return result.getValue(); return result.getValue();
} }
public void search(double maxDistance, boolean forward, StationTest stationTest) { public void search(double maxDistance, boolean forward, ArrayList<GlobalStation> destinations, StationTest stationTest) {
search(maxDistance, -1, forward, stationTest); search(maxDistance, -1, forward, destinations, stationTest);
} }
public void search(double maxDistance, double maxCost, boolean forward, StationTest stationTest) { public void search(double maxDistance, double maxCost, boolean forward, ArrayList<GlobalStation> destinations, StationTest stationTest) {
TrackGraph graph = train.graph; TrackGraph graph = train.graph;
if (graph == null) if (graph == null)
return; return;
@ -614,10 +608,58 @@ public class Navigation {
double distanceToNode2 = forward ? initialEdge.getLength() - startingPoint.position : startingPoint.position; double distanceToNode2 = forward ? initialEdge.getLength() - startingPoint.position : startingPoint.position;
frontier.add(new FrontierEntry(distanceToNode2, 0, initialNode1, initialNode2, initialEdge));
int signalWeight = Mth.clamp(ticksWaitingForSignal * 2, Train.Penalties.RED_SIGNAL, 200); int signalWeight = Mth.clamp(ticksWaitingForSignal * 2, Train.Penalties.RED_SIGNAL, 200);
Search: while (!frontier.isEmpty()) { // Apply penalties to initial edge
int initialPenalty = 0;
if (costRelevant)
initialPenalty += penalties.getOrDefault(initialEdge, 0);
EdgeData initialSignalData = initialEdge.getEdgeData();
if (initialSignalData.hasPoints()) {
for (TrackEdgePoint point : initialSignalData.getPoints()) {
if (point.getLocationOn(initialEdge) < initialEdge.getLength() - distanceToNode2)
continue;
if (costRelevant && distanceToNode2 + initialPenalty > maxCost)
return;
if (!point.canNavigateVia(initialNode2))
return;
if (point instanceof SignalBoundary signal) {
if (signal.isForcedRed(initialNode2)) {
initialPenalty += Train.Penalties.REDSTONE_RED_SIGNAL;
continue;
}
UUID group = signal.getGroup(initialNode2);
if (group == null)
continue;
SignalEdgeGroup signalEdgeGroup = Create.RAILWAYS.signalEdgeGroups.get(group);
if (signalEdgeGroup == null)
continue;
if (signalEdgeGroup.isOccupiedUnless(signal)) {
initialPenalty += signalWeight;
signalWeight /= 2;
}
}
if (point instanceof GlobalStation station) {
Train presentTrain = station.getPresentTrain();
boolean isOwnStation = presentTrain == train;
if (presentTrain != null && !isOwnStation)
initialPenalty += Train.Penalties.STATION_WITH_TRAIN;
if (station.canApproachFrom(initialNode2) && stationTest.test(distanceToNode2, distanceToNode2 + initialPenalty, reachedVia,
Pair.of(Couple.create(initialNode1, initialNode2), initialEdge), station))
return;
if (!isOwnStation)
initialPenalty += Train.Penalties.STATION;
}
}
}
if (costRelevant && distanceToNode2 + initialPenalty > maxCost)
return;
frontier.add(new FrontierEntry(distanceToNode2, initialPenalty, initialNode1, initialNode2, initialEdge));
while (!frontier.isEmpty()) {
FrontierEntry entry = frontier.poll(); FrontierEntry entry = frontier.poll();
if (!visited.add(entry.edge)) if (!visited.add(entry.edge))
continue; continue;
@ -632,51 +674,19 @@ public class Navigation {
TrackNode node1 = entry.node1; TrackNode node1 = entry.node1;
TrackNode node2 = entry.node2; TrackNode node2 = entry.node2;
if (costRelevant) if (entry.hasDestination) {
penalty += penalties.getOrDefault(edge, 0); EdgeData signalData = edge.getEdgeData();
if (signalData.hasPoints()) {
EdgeData signalData = edge.getEdgeData(); for (TrackEdgePoint point : signalData.getPoints()) {
if (signalData.hasPoints()) { if (point instanceof GlobalStation station) {
for (TrackEdgePoint point : signalData.getPoints()) { if (station.canApproachFrom(node2) && stationTest.test(distance, penalty, reachedVia,
if (node1 == initialNode1 && point.getLocationOn(edge) < edge.getLength() - distanceToNode2) Pair.of(Couple.create(node1, node2), edge), station))
continue; return;
if (costRelevant && distance + penalty > maxCost)
continue Search;
if (!point.canNavigateVia(node2))
continue Search;
if (point instanceof SignalBoundary signal) {
if (signal.isForcedRed(node2)) {
penalty += Train.Penalties.REDSTONE_RED_SIGNAL;
continue;
} }
UUID group = signal.getGroup(node2);
if (group == null)
continue;
SignalEdgeGroup signalEdgeGroup = Create.RAILWAYS.signalEdgeGroups.get(group);
if (signalEdgeGroup == null)
continue;
if (signalEdgeGroup.isOccupiedUnless(signal)) {
penalty += signalWeight;
signalWeight /= 2;
}
}
if (point instanceof GlobalStation station) {
Train presentTrain = station.getPresentTrain();
boolean isOwnStation = presentTrain == train;
if (presentTrain != null && !isOwnStation)
penalty += Train.Penalties.STATION_WITH_TRAIN;
if (station.canApproachFrom(node2) && stationTest.test(distance, distance + penalty, reachedVia,
Pair.of(Couple.create(node1, node2), edge), station))
return;
if (!isOwnStation)
penalty += Train.Penalties.STATION;
} }
} }
} }
if (costRelevant && distance + penalty > maxCost)
continue;
List<Entry<TrackNode, TrackEdge>> validTargets = new ArrayList<>(); List<Entry<TrackNode, TrackEdge>> validTargets = new ArrayList<>();
Map<TrackNode, TrackEdge> connectionsFrom = graph.getConnectionsFrom(node2); Map<TrackNode, TrackEdge> connectionsFrom = graph.getConnectionsFrom(node2);
for (Entry<TrackNode, TrackEdge> connection : connectionsFrom.entrySet()) { for (Entry<TrackNode, TrackEdge> connection : connectionsFrom.entrySet()) {
@ -690,15 +700,101 @@ public class Navigation {
if (validTargets.isEmpty()) if (validTargets.isEmpty())
continue; continue;
for (Entry<TrackNode, TrackEdge> target : validTargets) { Search: for (Entry<TrackNode, TrackEdge> target : validTargets) {
if (!validTypes.contains(target.getValue().getTrackMaterial().trackType)) if (!validTypes.contains(target.getValue().getTrackMaterial().trackType))
continue; continue;
TrackNode newNode = target.getKey(); TrackNode newNode = target.getKey();
TrackEdge newEdge = target.getValue(); TrackEdge newEdge = target.getValue();
double newDistance = newEdge.getLength() + distance;
int newPenalty = penalty; int newPenalty = penalty;
double edgeLength = newEdge.getLength();
double newDistance = distance + edgeLength;
if (costRelevant)
newPenalty += penalties.getOrDefault(newEdge, 0);
// Apply penalty to next connected edge
boolean hasDestination = false;
EdgeData signalData = newEdge.getEdgeData();
if (signalData.hasPoints()) {
for (TrackEdgePoint point : signalData.getPoints()) {
if (node2 == initialNode1 && point.getLocationOn(newEdge) < edgeLength - distanceToNode2)
continue;
if (costRelevant && newDistance + newPenalty > maxCost)
continue Search;
if (!point.canNavigateVia(newNode))
continue Search;
if (point instanceof SignalBoundary signal) {
if (signal.isForcedRed(newNode)) {
newPenalty += Train.Penalties.REDSTONE_RED_SIGNAL;
continue;
}
UUID group = signal.getGroup(newNode);
if (group == null)
continue;
SignalEdgeGroup signalEdgeGroup = Create.RAILWAYS.signalEdgeGroups.get(group);
if (signalEdgeGroup == null)
continue;
if (signalEdgeGroup.isOccupiedUnless(signal)) {
newPenalty += signalWeight;
signalWeight /= 2;
}
}
if (point instanceof GlobalStation station) {
Train presentTrain = station.getPresentTrain();
boolean isOwnStation = presentTrain == train;
if (presentTrain != null && !isOwnStation)
newPenalty += Train.Penalties.STATION_WITH_TRAIN;
if (station.canApproachFrom(newNode) && stationTest.test(newDistance, newDistance + newPenalty, reachedVia,
Pair.of(Couple.create(node2, newNode), newEdge), station)) {
hasDestination = true;
continue;
}
if (!isOwnStation)
newPenalty += Train.Penalties.STATION;
}
}
}
if (costRelevant && newDistance + newPenalty > maxCost)
continue;
double remainingDist = 0;
// Calculate remaining distance estimator for next connected edge
if (destinations != null && !destinations.isEmpty()) {
remainingDist = Double.MAX_VALUE;
Vec3 newNodePosition = newNode.getLocation().getLocation();
for (GlobalStation destination : destinations) {
TrackNodeLocation destinationNode = destination.edgeLocation.getFirst();
double dMin = Math.abs(newNodePosition.x - destinationNode.getLocation().x);
double dMid = Math.abs(newNodePosition.y - destinationNode.getLocation().y);
double dMax = Math.abs(newNodePosition.z - destinationNode.getLocation().z);
// Sort distance vector in ascending order
double temp;
if (dMin > dMid) {
temp = dMid;
dMid = dMin;
dMin = temp;
}
if (dMin > dMax) {
temp = dMax;
dMax = dMin;
dMin = temp;
}
if (dMid > dMax) {
temp = dMax;
dMax = dMid;
dMid = temp;
}
// Octile distance from newNode to station node
double currentRemaining = 0.317837245195782 * dMin + 0.414213562373095 * dMid + dMax + destination.position;
if (node2.getLocation().equals(destinationNode))
currentRemaining -= newEdge.getLength() * 2; // Correct the distance estimator for station edge
remainingDist = Math.min(remainingDist, currentRemaining);
}
}
reachedVia.putIfAbsent(newEdge, Pair.of(validTargets.size() > 1, Couple.create(node1, node2))); reachedVia.putIfAbsent(newEdge, Pair.of(validTargets.size() > 1, Couple.create(node1, node2)));
frontier.add(new FrontierEntry(newDistance, newPenalty, node2, newNode, newEdge)); frontier.add(new FrontierEntry(newDistance, newPenalty, remainingDist, hasDestination, node2, newNode, newEdge));
} }
} }
} }
@ -707,6 +803,8 @@ public class Navigation {
double distance; double distance;
int penalty; int penalty;
double remaining;
boolean hasDestination;
TrackNode node1; TrackNode node1;
TrackNode node2; TrackNode node2;
TrackEdge edge; TrackEdge edge;
@ -714,6 +812,17 @@ public class Navigation {
public FrontierEntry(double distance, int penalty, TrackNode node1, TrackNode node2, TrackEdge edge) { public FrontierEntry(double distance, int penalty, TrackNode node1, TrackNode node2, TrackEdge edge) {
this.distance = distance; this.distance = distance;
this.penalty = penalty; this.penalty = penalty;
this.remaining = 0;
this.hasDestination = false;
this.node1 = node1;
this.node2 = node2;
this.edge = edge;
}
public FrontierEntry(double distance, int penalty, double remaining, boolean hasDestination, TrackNode node1, TrackNode node2, TrackEdge edge) {
this.distance = distance;
this.penalty = penalty;
this.remaining = remaining;
this.hasDestination = hasDestination;
this.node1 = node1; this.node1 = node1;
this.node2 = node2; this.node2 = node2;
this.edge = edge; this.edge = edge;
@ -721,7 +830,7 @@ public class Navigation {
@Override @Override
public int compareTo(FrontierEntry o) { public int compareTo(FrontierEntry o) {
return Double.compare(distance + penalty, o.distance + o.penalty); return Double.compare(distance + penalty + remaining, o.distance + o.penalty + o.remaining);
} }
} }

View file

@ -24,12 +24,13 @@ import com.simibubi.create.AllMovementBehaviours;
import com.simibubi.create.AllPackets; import com.simibubi.create.AllPackets;
import com.simibubi.create.Create; import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour;
import com.simibubi.create.content.logistics.filter.FilterItem; import com.simibubi.create.content.logistics.filter.FilterItemStack;
import com.simibubi.create.content.trains.bogey.AbstractBogeyBlockEntity; import com.simibubi.create.content.trains.bogey.AbstractBogeyBlockEntity;
import com.simibubi.create.content.trains.entity.Carriage.DimensionalCarriageEntity; 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.IEdgePointListener;
import com.simibubi.create.content.trains.entity.TravellingPoint.SteerDirection; import com.simibubi.create.content.trains.entity.TravellingPoint.SteerDirection;
import com.simibubi.create.content.trains.graph.DimensionPalette; import com.simibubi.create.content.trains.graph.DimensionPalette;
import com.simibubi.create.content.trains.graph.DiscoveredPath;
import com.simibubi.create.content.trains.graph.EdgeData; import com.simibubi.create.content.trains.graph.EdgeData;
import com.simibubi.create.content.trains.graph.EdgePointType; import com.simibubi.create.content.trains.graph.EdgePointType;
import com.simibubi.create.content.trains.graph.TrackEdge; import com.simibubi.create.content.trains.graph.TrackEdge;
@ -195,7 +196,7 @@ public class Train {
if (observer == null) if (observer == null)
continue; continue;
ItemStack filter = observer.getFilter(); FilterItemStack filter = observer.getFilter();
if (filter.isEmpty()) { if (filter.isEmpty()) {
observer.keepAlive(this); observer.keepAlive(this);
continue; continue;
@ -223,7 +224,7 @@ public class Train {
ItemStack extractItem = inv.extractItem(slot, 1, true); ItemStack extractItem = inv.extractItem(slot, 1, true);
if (extractItem.isEmpty()) if (extractItem.isEmpty())
continue; continue;
shouldActivate |= FilterItem.test(level, extractItem, filter); shouldActivate |= filter.test(level, extractItem);
} }
} }
@ -235,7 +236,7 @@ public class Train {
FluidStack drain = tank.drain(1, FluidAction.SIMULATE); FluidStack drain = tank.drain(1, FluidAction.SIMULATE);
if (drain.isEmpty()) if (drain.isEmpty())
continue; continue;
shouldActivate |= FilterItem.test(level, drain, filter); shouldActivate |= filter.test(level, drain);
} }
} }
} }
@ -539,14 +540,12 @@ public class Train {
if (!reservedSignalBlocks.isEmpty()) if (!reservedSignalBlocks.isEmpty())
return; return;
GlobalStation destination = navigation.destination;
if (!navigatingManually && fullRefresh) { if (!navigatingManually && fullRefresh) {
GlobalStation preferredDestination = runtime.startCurrentInstruction(); DiscoveredPath preferredPath = runtime.startCurrentInstruction();
if (preferredDestination != null) if (preferredPath != null){
destination = preferredDestination; navigation.startNavigation(preferredPath);
}
} }
navigation.startNavigation(destination, navigatingManually ? -1 : Double.MAX_VALUE, false);
} }
private void tickDerailedSlowdown() { private void tickDerailedSlowdown() {
@ -601,7 +600,7 @@ public class Train {
Vec3 start = (speed < 0 ? trailingPoint : leadingPoint).getPosition(graph); Vec3 start = (speed < 0 ? trailingPoint : leadingPoint).getPosition(graph);
Vec3 end = (speed < 0 ? leadingPoint : trailingPoint).getPosition(graph); Vec3 end = (speed < 0 ? leadingPoint : trailingPoint).getPosition(graph);
Pair<Train, Vec3> collision = findCollidingTrain(level, start, end, this, dimension); Pair<Train, Vec3> collision = findCollidingTrain(level, start, end, dimension);
if (collision == null) if (collision == null)
return; return;
@ -617,13 +616,16 @@ public class Train {
train.crash(); train.crash();
} }
public static Pair<Train, Vec3> findCollidingTrain(Level level, Vec3 start, Vec3 end, Train ignore, public Pair<Train, Vec3> findCollidingTrain(Level level, Vec3 start, Vec3 end, ResourceKey<Level> dimension) {
ResourceKey<Level> dimension) { Vec3 diff = end.subtract(start);
for (Train train : Create.RAILWAYS.sided(level).trains.values()) { double maxDistanceSqr = Math.pow(AllConfigs.server().trains.maxAssemblyLength.get(), 2.0);
if (train == ignore)
Trains: for (Train train : Create.RAILWAYS.sided(level).trains.values()) {
if (train == this)
continue;
if (train.graph != null && train.graph != graph)
continue; continue;
Vec3 diff = end.subtract(start);
Vec3 lastPoint = null; Vec3 lastPoint = null;
for (Carriage otherCarriage : train.carriages) { for (Carriage otherCarriage : train.carriages) {
@ -643,6 +645,10 @@ public class Train {
Vec3 start2 = otherLeading.getPosition(train.graph); Vec3 start2 = otherLeading.getPosition(train.graph);
Vec3 end2 = otherTrailing.getPosition(train.graph); Vec3 end2 = otherTrailing.getPosition(train.graph);
if (Math.min(start2.distanceToSqr(start), end2.distanceToSqr(start)) > maxDistanceSqr)
continue Trains;
if (betweenBits) { if (betweenBits) {
end2 = start2; end2 = start2;
start2 = lastPoint; start2 = lastPoint;
@ -1040,7 +1046,7 @@ public class Train {
} }
public static class Penalties { public static class Penalties {
static final int STATION = 200, STATION_WITH_TRAIN = 300; static final int STATION = 50, STATION_WITH_TRAIN = 300;
static final int MANUAL_TRAIN = 200, IDLE_TRAIN = 700, ARRIVING_TRAIN = 50, WAITING_TRAIN = 50, ANY_TRAIN = 25, static final int MANUAL_TRAIN = 200, IDLE_TRAIN = 700, ARRIVING_TRAIN = 50, WAITING_TRAIN = 50, ANY_TRAIN = 25,
RED_SIGNAL = 25, REDSTONE_RED_SIGNAL = 400; RED_SIGNAL = 25, REDSTONE_RED_SIGNAL = 400;
} }

Some files were not shown because too many files have changed in this diff Show more