diff --git a/src/generated/resources/.cache/2d64935085b86659cb7857bad9701dbf9bab6e4c b/src/generated/resources/.cache/2d64935085b86659cb7857bad9701dbf9bab6e4c index 21f3cd15d3..2d76c03235 100644 --- a/src/generated/resources/.cache/2d64935085b86659cb7857bad9701dbf9bab6e4c +++ b/src/generated/resources/.cache/2d64935085b86659cb7857bad9701dbf9bab6e4c @@ -1,4 +1,4 @@ -// 1.20.1 2025-01-24T23:36:27.3459617 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 2025-01-25T07:57:37.109242956 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 6a67703c2697d81b7dc83e9d72a66f9c9ff08383 assets/create/blockstates/acacia_window_pane.json c3ae87b62e81d8e9476eccd793bb1548d74c66a1 assets/create/blockstates/adjustable_chain_gearshift.json @@ -83,13 +83,13 @@ b5170d754ce5f07ea2b4646eb07c099c50bae249 assets/create/blockstates/clipboard.jso f7254f20f91e2f1295e36d2e70390d43f3952d07 assets/create/blockstates/copper_door.json 736777de0eb038ff1ef9e8fe9d04c23d80239eda assets/create/blockstates/copper_ladder.json df3103dfc1c3ba7a9573229d009cb0de4925df16 assets/create/blockstates/copper_scaffolding.json -4d3d29e8a74bf103da39e76a1466b03eb5dcf916 assets/create/blockstates/copper_shingles.json 1ea8fdb990f8cda1762ab69ac38ea3161a835227 assets/create/blockstates/copper_shingle_slab.json 7c35bb802099d6bb5d92eafd8cbb7ea146979a2e assets/create/blockstates/copper_shingle_stairs.json +4d3d29e8a74bf103da39e76a1466b03eb5dcf916 assets/create/blockstates/copper_shingles.json 5c5ba06bf5b0a2c57d0aa42e85880f36d9694a78 assets/create/blockstates/copper_table_cloth.json -9a9f03140a57a7a8903d3e1b159bdc052566a6ec assets/create/blockstates/copper_tiles.json 7db7a0d81887091ca889f40bb8a508d3098c5164 assets/create/blockstates/copper_tile_slab.json c0b7eca017242913d156e4623147add0d03574f6 assets/create/blockstates/copper_tile_stairs.json +9a9f03140a57a7a8903d3e1b159bdc052566a6ec assets/create/blockstates/copper_tiles.json ef3ccb2d8b03f5a972b053a15bb037f8db6af17c assets/create/blockstates/copper_valve_handle.json 4758bed22fb6fe18213f463bc055775c1909e858 assets/create/blockstates/copycat_bars.json 4789c857508452aede1cb7389187b99ce2d7bf62 assets/create/blockstates/copycat_base.json @@ -106,114 +106,114 @@ c9a2c3a7971c46957d0f07c6d94d76f59da54a0b assets/create/blockstates/crushing_whee 4b0e51a1c10685f7d432467339afc9c2e24793b0 assets/create/blockstates/crushing_wheel_controller.json ba9c3ecfacbd398048440d247decffeaefc714b5 assets/create/blockstates/cuckoo_clock.json 1f6d84cba69062a1989d671c9c97317e2c2455b6 assets/create/blockstates/cut_andesite.json -cc62a6499ce8dcfc5e8695f0e8bb3c3d67f41efc assets/create/blockstates/cut_andesite_bricks.json 50d88f806122818af2ffecbd514d13ebbd21e4c9 assets/create/blockstates/cut_andesite_brick_slab.json 32d801225ea18209792921fa91618ed41794dbd0 assets/create/blockstates/cut_andesite_brick_stairs.json 3bf8204bf8c7c5b7b3c388fbc3478bb2d7c47129 assets/create/blockstates/cut_andesite_brick_wall.json +cc62a6499ce8dcfc5e8695f0e8bb3c3d67f41efc assets/create/blockstates/cut_andesite_bricks.json 34e89a828f14383c6115954a235b19851b74f277 assets/create/blockstates/cut_andesite_slab.json 49d58ae14544d89305ddc707cf7f6a81998200fa assets/create/blockstates/cut_andesite_stairs.json 1cc235cb6c388324793ac40f7bf89df8b048faac assets/create/blockstates/cut_andesite_wall.json 13ea54a4b9b89e576879a6e23a029c6341b7c098 assets/create/blockstates/cut_asurine.json -51c22c0547ab8ed2564890afb8733bbe356899f5 assets/create/blockstates/cut_asurine_bricks.json cf09de38f826fe000c5efe5afe56cf746125691d assets/create/blockstates/cut_asurine_brick_slab.json 1835482d5e9a59f2214336a63b12c7132ad815b4 assets/create/blockstates/cut_asurine_brick_stairs.json c48ab37bf7a2aba676af281d29cb6a2103c72fba assets/create/blockstates/cut_asurine_brick_wall.json +51c22c0547ab8ed2564890afb8733bbe356899f5 assets/create/blockstates/cut_asurine_bricks.json 1523a57124239a99da0b12a6b435c09d3d4276a5 assets/create/blockstates/cut_asurine_slab.json cc1acf5e118f1b1e78c5bb291176008960794d59 assets/create/blockstates/cut_asurine_stairs.json 139640bf41070e8eeb48647319eee54bb6804692 assets/create/blockstates/cut_asurine_wall.json 06b8c5cf98366608c480a37e6944d0d668bc8983 assets/create/blockstates/cut_calcite.json -979c70e35d806f1f63fe3381f27d881a17f9f6be assets/create/blockstates/cut_calcite_bricks.json a8f83cb8e1eae587f4e11e37c4cd3d0a1bbef377 assets/create/blockstates/cut_calcite_brick_slab.json 1eabb2e485aa323d317fa9648be02c12556593b7 assets/create/blockstates/cut_calcite_brick_stairs.json a0a33df71c5d26344a7bb0dd7a4622c30cc7825f assets/create/blockstates/cut_calcite_brick_wall.json +979c70e35d806f1f63fe3381f27d881a17f9f6be assets/create/blockstates/cut_calcite_bricks.json e3ddaae92b52cc3ea230088ff23260b5c5c93017 assets/create/blockstates/cut_calcite_slab.json 80c5249eaf9504c743c427fdd1a2c7bfa0f3d48f assets/create/blockstates/cut_calcite_stairs.json b4bbdb08d8114b6741546a0418cb54d645481c02 assets/create/blockstates/cut_calcite_wall.json 449f5180c72a028393afdac55a34e59862728224 assets/create/blockstates/cut_crimsite.json -25d731077a131d03347296c38c76b547194a6320 assets/create/blockstates/cut_crimsite_bricks.json d2c8a3580d3578c8afe44b94d4448be3680dbdeb assets/create/blockstates/cut_crimsite_brick_slab.json a3d9d2190a23b881dd3a7538ab248e0b0a3efa8e assets/create/blockstates/cut_crimsite_brick_stairs.json 3791c00ed477c0aaf7c5a20803a89dfc0e20f013 assets/create/blockstates/cut_crimsite_brick_wall.json +25d731077a131d03347296c38c76b547194a6320 assets/create/blockstates/cut_crimsite_bricks.json c9f19e7a976a7428b3dd58f45d734700ca1a18cd assets/create/blockstates/cut_crimsite_slab.json 1b8d4ac53dc5823083c2af605165a05b73c9ff79 assets/create/blockstates/cut_crimsite_stairs.json 484f9253ed92e963f398973a99fbeacb67ba1188 assets/create/blockstates/cut_crimsite_wall.json c4e95ceb7914da09ebe42d539bf5d976a3d70972 assets/create/blockstates/cut_deepslate.json -75d4ef863cd85d8f3df78226177966954e02ee2b assets/create/blockstates/cut_deepslate_bricks.json e1dc99a48b9066732fc5c62071c5ead16f34f438 assets/create/blockstates/cut_deepslate_brick_slab.json dbb2eddaf1d4ae3e687beb611552ea4283a1e7d8 assets/create/blockstates/cut_deepslate_brick_stairs.json 91c1f3da848503067c64b966ddda22ab91ff8fd5 assets/create/blockstates/cut_deepslate_brick_wall.json +75d4ef863cd85d8f3df78226177966954e02ee2b assets/create/blockstates/cut_deepslate_bricks.json 593198ffd37eae124a8366ae1d4a40b682788f92 assets/create/blockstates/cut_deepslate_slab.json f8cd1f9002ed8593ab71af9cfb7f962625994108 assets/create/blockstates/cut_deepslate_stairs.json c2d8060a0c830e5b8bbb084457083324b5b6f4c9 assets/create/blockstates/cut_deepslate_wall.json aaa6ac5f4fc399c4b03a7f8de856fa7aae97e049 assets/create/blockstates/cut_diorite.json -08b6289ca8b4193c87324ca23ca081e8773fb223 assets/create/blockstates/cut_diorite_bricks.json 423f809f06fa3fd96643f068ba0d3520269b3844 assets/create/blockstates/cut_diorite_brick_slab.json 9011fb92f57e7695c4484c923dd40ecd749ff307 assets/create/blockstates/cut_diorite_brick_stairs.json 41bad89777a33737bc0365ce2c7ffc20720f9620 assets/create/blockstates/cut_diorite_brick_wall.json +08b6289ca8b4193c87324ca23ca081e8773fb223 assets/create/blockstates/cut_diorite_bricks.json b03e7cf494c53c6f24ba93d0ef531e839026932b assets/create/blockstates/cut_diorite_slab.json 95c8094204979acfb0e59c2826003e0274a02fe5 assets/create/blockstates/cut_diorite_stairs.json e2f163d36dd5d03c0741dd2e87d8f77a0c86ae00 assets/create/blockstates/cut_diorite_wall.json f42ca2ce8e8f657c64376759413ec611f8045531 assets/create/blockstates/cut_dripstone.json -2d696162b2085c3d5723308a8d1ccafb29660f01 assets/create/blockstates/cut_dripstone_bricks.json 9310a800fb091014e7c0a220f5f2511c1de379ad assets/create/blockstates/cut_dripstone_brick_slab.json 3ff2f65dafcb4654b99e0d65b7e851760f9a4075 assets/create/blockstates/cut_dripstone_brick_stairs.json cafc956d8dc2053e5a0e8437c4ccde7fa24fc17e assets/create/blockstates/cut_dripstone_brick_wall.json +2d696162b2085c3d5723308a8d1ccafb29660f01 assets/create/blockstates/cut_dripstone_bricks.json 9cb32af3b952b841e9da94789da17cd274c3cfb9 assets/create/blockstates/cut_dripstone_slab.json da0300f54bdfcc705beb8d84f26406be660de5de assets/create/blockstates/cut_dripstone_stairs.json 83ff3eaeb481202c77e6dbdc442b4dd195ca568c assets/create/blockstates/cut_dripstone_wall.json bf501250fd2226838afe0baf68db08cd832e3c4f assets/create/blockstates/cut_granite.json -5c029d7ec837b3239d17ab91a70f025df1bfb124 assets/create/blockstates/cut_granite_bricks.json 773717bd5c140cf025f463c99c67efb9d27bd696 assets/create/blockstates/cut_granite_brick_slab.json 97d20b21e5b7f329c1b21b436fd0bdcaa8d173d0 assets/create/blockstates/cut_granite_brick_stairs.json 5e4175b6c89039ded48937ad1cd13d3bb2d2992a assets/create/blockstates/cut_granite_brick_wall.json +5c029d7ec837b3239d17ab91a70f025df1bfb124 assets/create/blockstates/cut_granite_bricks.json 42549436ce26ad7b44f2e1cba54357b3f25bcb18 assets/create/blockstates/cut_granite_slab.json e9d8fd028d8092e5fa0fd13cd638516f57a22d53 assets/create/blockstates/cut_granite_stairs.json 2daab523202dd2e31daeaf3b9a04cde2a7da4ca5 assets/create/blockstates/cut_granite_wall.json 0652c8b9c41acc1a8da901bd7b8b6018b3581d5b assets/create/blockstates/cut_limestone.json -508ee569f313b7e804f6268ca86f5a61851563ec assets/create/blockstates/cut_limestone_bricks.json 4efbeb34c96918e9b48dc484a82b1ef4811ed39d assets/create/blockstates/cut_limestone_brick_slab.json 11b99cf9b33d7f8de9d11cc1e405e2681682ba32 assets/create/blockstates/cut_limestone_brick_stairs.json b6c02a9e9e47a8e521a54ef9488259267068f032 assets/create/blockstates/cut_limestone_brick_wall.json +508ee569f313b7e804f6268ca86f5a61851563ec assets/create/blockstates/cut_limestone_bricks.json fb63a2581211fe62344985a06feec9dcec4b1888 assets/create/blockstates/cut_limestone_slab.json ffcca1e66718f3e78e544b5fa9954a852c095e91 assets/create/blockstates/cut_limestone_stairs.json a1a90f84b47f96b4384fc2d60bfc48ddbb5ed179 assets/create/blockstates/cut_limestone_wall.json 1b7a133518780d4f49474a70e7f6263d6e88ff51 assets/create/blockstates/cut_ochrum.json -6f37e5e2dca3b443951131cb82c15a981a4e2005 assets/create/blockstates/cut_ochrum_bricks.json f1e9d54a6f9f41b968f117a7be711011effa71a5 assets/create/blockstates/cut_ochrum_brick_slab.json 8d334e026e94b304a1ff1ee96097f434b50175f2 assets/create/blockstates/cut_ochrum_brick_stairs.json e92c026ee7ab2aa35003ad475bef3d6c0e29818c assets/create/blockstates/cut_ochrum_brick_wall.json +6f37e5e2dca3b443951131cb82c15a981a4e2005 assets/create/blockstates/cut_ochrum_bricks.json 5a61edb7d146e83d951795fae33dc306e71b2cb6 assets/create/blockstates/cut_ochrum_slab.json b31944bf6297685acd37631083dde0889c08ede7 assets/create/blockstates/cut_ochrum_stairs.json df33a8af1dc8cb08ddcfd22a50a305499479a4dd assets/create/blockstates/cut_ochrum_wall.json 1606d7481e56755f07e9331cf85a8d7cc9aace9a assets/create/blockstates/cut_scorchia.json -bc2a0e7f11400b8c2a03071be87dadb5edc097de assets/create/blockstates/cut_scorchia_bricks.json 43db25ebac2f5bcaa7ca9cfb6da8fcb20fad8269 assets/create/blockstates/cut_scorchia_brick_slab.json 7a80620590ba5e61967c5168f5c67ecabf09dc00 assets/create/blockstates/cut_scorchia_brick_stairs.json e4eb79360a41bb1a7ca835d61446ea5166e4cda8 assets/create/blockstates/cut_scorchia_brick_wall.json +bc2a0e7f11400b8c2a03071be87dadb5edc097de assets/create/blockstates/cut_scorchia_bricks.json c0d262f54e3b2fce8bc941a2a6df71db5f0229ea assets/create/blockstates/cut_scorchia_slab.json de2e918058e9dd7eafd085a8dec634f6a2832c21 assets/create/blockstates/cut_scorchia_stairs.json 5d2d06799b82449754f62b1d80b9ee9a24c65bad assets/create/blockstates/cut_scorchia_wall.json 76ea4f3438a3effedfc93d2bbabac0899610cd28 assets/create/blockstates/cut_scoria.json -6d9c79e1b71656a73bb69e2a9b100be59084dd2e assets/create/blockstates/cut_scoria_bricks.json 7c7dcd1fe82f3673910620c2eefebad5d0029cdf assets/create/blockstates/cut_scoria_brick_slab.json d535b387bf0a6f9e124eed8b76d899e13699bca9 assets/create/blockstates/cut_scoria_brick_stairs.json c426e1b5e4c77c25cd0d16d10fba0e0731673dd1 assets/create/blockstates/cut_scoria_brick_wall.json +6d9c79e1b71656a73bb69e2a9b100be59084dd2e assets/create/blockstates/cut_scoria_bricks.json fb692494c88358d4d8e687b216f729d6b6bd7174 assets/create/blockstates/cut_scoria_slab.json 950f43bae8f4e3220103ce0c62f444856129ca12 assets/create/blockstates/cut_scoria_stairs.json 01350030831c5b9edef0dc2c778b92f1ebc2b2fc assets/create/blockstates/cut_scoria_wall.json c0c1c4d44eba5babe9703eca31f0279ebd11ed8e assets/create/blockstates/cut_tuff.json -9bddef4a2b4a338c15f03e2397c4cd4c3ae9e5d9 assets/create/blockstates/cut_tuff_bricks.json 11306e83915e0106d48f890df3212c3a47443a08 assets/create/blockstates/cut_tuff_brick_slab.json e8951d94e0d3228700bcb56819928f1c179c3973 assets/create/blockstates/cut_tuff_brick_stairs.json 619340b7cf014cfb72a4b5440b90881535f16108 assets/create/blockstates/cut_tuff_brick_wall.json +9bddef4a2b4a338c15f03e2397c4cd4c3ae9e5d9 assets/create/blockstates/cut_tuff_bricks.json 3577e3f4933ea8cb7464c28e80867ce84917898d assets/create/blockstates/cut_tuff_slab.json 5673fdb02439d622c56dc0ff47a0dca98dc6d027 assets/create/blockstates/cut_tuff_stairs.json 12a46ee82536665400ec2f3befed3be58325d5c6 assets/create/blockstates/cut_tuff_wall.json beb9e47f8d811c2146f68daf992fb805342a65cb assets/create/blockstates/cut_veridium.json -04d07986eb86ffd66baaaf9b65e02d00022e98e2 assets/create/blockstates/cut_veridium_bricks.json 952543c03e730443d85059ec43642efb089485e7 assets/create/blockstates/cut_veridium_brick_slab.json 6a033e7b5a0b26cce5956c6c7c1eff558f866cb5 assets/create/blockstates/cut_veridium_brick_stairs.json 43689138c8018b3ee9f35a11870887e9df3c8fe5 assets/create/blockstates/cut_veridium_brick_wall.json +04d07986eb86ffd66baaaf9b65e02d00022e98e2 assets/create/blockstates/cut_veridium_bricks.json 212d8ee5dfa78802b9539640cf8b263fd5880b87 assets/create/blockstates/cut_veridium_slab.json c11f09df4a23e951bdf9a345515183f4fac7cde3 assets/create/blockstates/cut_veridium_stairs.json 3aa6f5e613ff73952e3de00408051f92316e7f81 assets/create/blockstates/cut_veridium_wall.json @@ -241,12 +241,12 @@ f7f5df9086c71688cbdb5d05c394dc5acb8fb338 assets/create/blockstates/elevator_cont d47bc65703e9582cc710e6408fb565e16d3514a6 assets/create/blockstates/encased_fan.json 651f9fdb11f56d887d131be8f936f508d0b2fc1d assets/create/blockstates/encased_fluid_pipe.json 489ad4daeaed702d231a3f175f7b66846f5789a6 assets/create/blockstates/experience_block.json -5f6c60a30889b043709066707e80a21081d98155 assets/create/blockstates/exposed_copper_shingles.json 74c8a72db3dd3fa919e29baaa8c5865f13490461 assets/create/blockstates/exposed_copper_shingle_slab.json 4e0b5a9be15f0c2861f5f6bd71bd9c2a4db2a21d assets/create/blockstates/exposed_copper_shingle_stairs.json -5299b4f7b9b3490872e8c26a6b212e14dd05fd9a assets/create/blockstates/exposed_copper_tiles.json +5f6c60a30889b043709066707e80a21081d98155 assets/create/blockstates/exposed_copper_shingles.json 6ee73ff3608d51fdad6e9810feee66ed1773b81c assets/create/blockstates/exposed_copper_tile_slab.json f93e4059876bfc6d70b9fa2bc24d8e3d6943d56f assets/create/blockstates/exposed_copper_tile_stairs.json +5299b4f7b9b3490872e8c26a6b212e14dd05fd9a assets/create/blockstates/exposed_copper_tiles.json 4b30365ed77db9c5754eeda5fee81d47b568b946 assets/create/blockstates/factory_gauge.json f1a03ede031d8c4e33a4d07c529e71936da9dc6d assets/create/blockstates/fake_track.json 21fa4a1bf4ee851e090a21c97c9a38d18cfddf0d assets/create/blockstates/fluid_pipe.json @@ -323,8 +323,6 @@ fa5fb2be73c7c54b70e927b66adf3f4d64c5cb6b assets/create/blockstates/light_gray_ni f1901887cd166296e465133c3b0d7ad0d664a614 assets/create/blockstates/light_gray_table_cloth.json 35b151db396069b146d223fbe46be5b0c3dda8a9 assets/create/blockstates/light_gray_toolbox.json 894827ffd176bc733abecf18d96888e9ed5a3eb4 assets/create/blockstates/light_gray_valve_handle.json -a6f319c803c03e34bbf841ea52d82f0f7ec7a413 assets/create/blockstates/limestone.json -7ff65e1c4c8e48a0b694cd17506a192e6a7e6e44 assets/create/blockstates/limestone_pillar.json 7f20b548dd535942b2d6f41c39de7ad4fafe637e assets/create/blockstates/lime_nixie_tube.json c6ac740bf37477ad170576983230b130ac01f355 assets/create/blockstates/lime_postbox.json ad1ec304729fd6d336c0d4d0c27c9345af636695 assets/create/blockstates/lime_sail.json @@ -332,6 +330,8 @@ b9934a558e1b495403dc2c71ffb43cce7d396013 assets/create/blockstates/lime_seat.jso 7c5dc2ffd0bd44ba8785b6a788030714a009bcbc assets/create/blockstates/lime_table_cloth.json 49a02f7fc16697ba1cf16cee7e45ab6bfd8b06ce assets/create/blockstates/lime_toolbox.json ba181485f219d3ae23509a7edf28e25d9edb10f4 assets/create/blockstates/lime_valve_handle.json +a6f319c803c03e34bbf841ea52d82f0f7ec7a413 assets/create/blockstates/limestone.json +7ff65e1c4c8e48a0b694cd17506a192e6a7e6e44 assets/create/blockstates/limestone_pillar.json 654e845cebed82b7afbcf81380921e0a475b01e9 assets/create/blockstates/linear_chassis.json e195e82e4d0c1fc20474535bc9068cbb77a5e175 assets/create/blockstates/lit_blaze_burner.json 296186b196af94e1ab3f7e8a3254f6d31ae47a5c assets/create/blockstates/magenta_nixie_tube.json @@ -377,14 +377,14 @@ aab812cecf7d10d4e7587f4dead8a98238a15f41 assets/create/blockstates/orange_seat.j 2af63a4768f84fc93c7e7d67fa9a64438433e59f assets/create/blockstates/orange_valve_handle.json 515ed7dae09b052f289419ba09998a23e0d7083d assets/create/blockstates/ornate_iron_window.json 8118444f37536b9104ef4818d374b0c8a7c987bf assets/create/blockstates/ornate_iron_window_pane.json -97cd78453af94f44cef1187988966626574b29d5 assets/create/blockstates/oxidized_copper_shingles.json 2ddc762b8d8558e69a2f81c028702f3a25b5e978 assets/create/blockstates/oxidized_copper_shingle_slab.json ac536ae742c12e97bfd0b2483c87ff29f3935eaf assets/create/blockstates/oxidized_copper_shingle_stairs.json -110a6c19bcc9f044e5e982ac6e4b295b03ec0145 assets/create/blockstates/oxidized_copper_tiles.json +97cd78453af94f44cef1187988966626574b29d5 assets/create/blockstates/oxidized_copper_shingles.json 3f3924f0f0e368edfa04f4fdd6d6c2319276ddfe assets/create/blockstates/oxidized_copper_tile_slab.json 5e634cfb9abb06d8b29f39d751fc56b28ea5a9cd assets/create/blockstates/oxidized_copper_tile_stairs.json -65f3fa5a068189c1c2971af1a1052f69c0e26005 assets/create/blockstates/packager.json +110a6c19bcc9f044e5e982ac6e4b295b03ec0145 assets/create/blockstates/oxidized_copper_tiles.json 887565a0f89f089d6be888c87394dde4878afda7 assets/create/blockstates/package_frogport.json +65f3fa5a068189c1c2971af1a1052f69c0e26005 assets/create/blockstates/packager.json 36742cc6ce052ead143366d31b11e828a525c1b8 assets/create/blockstates/peculiar_bell.json 53d102e706d53cb2c0dbc0bc11da828084a43519 assets/create/blockstates/pink_nixie_tube.json db7ef5acb1ce2d3b8f881f34b5d9f40633c3973d assets/create/blockstates/pink_postbox.json @@ -470,9 +470,6 @@ a4b6bd4e55cd292abf752efeda93cf8d23162657 assets/create/blockstates/purple_table_ 3aca01f2eddb22adb1b25735b98a990bfc7220d2 assets/create/blockstates/radial_chassis.json 72faac9777be540f95f8b662a833856e0e1b8f35 assets/create/blockstates/railway_casing.json 7ce346fa18702f6fe6e2a939efcfa26eda63fe38 assets/create/blockstates/raw_zinc_block.json -ec546afd3ec8036e4393b97d535f05a86f57dbc1 assets/create/blockstates/redstone_contact.json -ff205f032b36486753dddb1f2029ef8d53e9c86f assets/create/blockstates/redstone_link.json -e4c645b199a2d7e89c91065071a0a91df5ca8e3c assets/create/blockstates/redstone_requester.json e3fd62e466e3e6e7bd6fc8661f764ba972a466fc assets/create/blockstates/red_nixie_tube.json d14d6437a6727da13cea5f7eeb815720c80dde6f assets/create/blockstates/red_postbox.json 4c36b562da58ef2af57009da7cf2426059249228 assets/create/blockstates/red_sail.json @@ -480,6 +477,9 @@ d14d6437a6727da13cea5f7eeb815720c80dde6f assets/create/blockstates/red_postbox.j 90bf31515faa2e7e6d73414a6c5498911910710e assets/create/blockstates/red_table_cloth.json 380f46b7cb72b13c0f16fd4a4287a1a33adeff41 assets/create/blockstates/red_toolbox.json b689d87a27ed0cb2cab190a2ad2b599818bff56c assets/create/blockstates/red_valve_handle.json +ec546afd3ec8036e4393b97d535f05a86f57dbc1 assets/create/blockstates/redstone_contact.json +ff205f032b36486753dddb1f2029ef8d53e9c86f assets/create/blockstates/redstone_link.json +e4c645b199a2d7e89c91065071a0a91df5ca8e3c assets/create/blockstates/redstone_requester.json 87ab7ca62ecf24d60d7e5c61bd5af97714dad0ad assets/create/blockstates/refined_radiance_casing.json 64a5b256e5af2dc8cb7ed77f0feadcf5134f7335 assets/create/blockstates/repackager.json 3807bcc6ccc3dad0dbfcc8fcf260a361aa488659 assets/create/blockstates/rope.json @@ -489,8 +489,8 @@ dd63fd8443a2be507281548df838d878b0c3c8c8 assets/create/blockstates/rose_quartz_l dfe69ee57f832a2e4c576ee01bdde1617c81e46a assets/create/blockstates/rose_quartz_tiles.json b9cbbc7c4e1d9abd312263a9a270315bd5f0106b assets/create/blockstates/rotation_speed_controller.json 5a25ecb95b7978cc487491cb24478e4d6a73e977 assets/create/blockstates/sail_frame.json -bff758cc56bece375b40c32067b903b675065328 assets/create/blockstates/schematicannon.json 505510656c77d93ecd3691e7111615193275f29e assets/create/blockstates/schematic_table.json +bff758cc56bece375b40c32067b903b675065328 assets/create/blockstates/schematicannon.json 82c9ceb19cfc4e247fbb62a9605630ba08423efe assets/create/blockstates/scorchia.json 6fa99d5f1ff05153660f9917286d4b157eaa1b40 assets/create/blockstates/scorchia_pillar.json 8c34743564aa0473745ecec304a19e15e9e87cf2 assets/create/blockstates/scoria.json @@ -499,64 +499,64 @@ e5aff9dc8fa5e98b060232974194afb06d497d09 assets/create/blockstates/scoria_pillar 3343224d6da4e75f0bc7a7634ba010a4ba54ad70 assets/create/blockstates/sequenced_gearshift.json 4c261d54117ee295b307f6ea3e56a09437631f73 assets/create/blockstates/shadow_steel_casing.json 4c67d2a1a1faea5be2a81ebc0722c32d8e2e84d6 assets/create/blockstates/shaft.json -c606f103619088e8a5afe969ba54929af480a3d2 assets/create/blockstates/small_andesite_bricks.json c5469de5957d77fc11febaa658ee2bfb0d11b0bc assets/create/blockstates/small_andesite_brick_slab.json ed0bcfd07959aa208085910bd3780756979c985d assets/create/blockstates/small_andesite_brick_stairs.json 78e30e63adedf1ca95261eb4010a1db45aecfe9e assets/create/blockstates/small_andesite_brick_wall.json -b9fedc13dc8cb53a8bb16ce2257ea65f0ac94a6b assets/create/blockstates/small_asurine_bricks.json +c606f103619088e8a5afe969ba54929af480a3d2 assets/create/blockstates/small_andesite_bricks.json 653fa70f0aa7fc319d50f72692d507ff7c59c0f4 assets/create/blockstates/small_asurine_brick_slab.json e61a0b891729565434d6ab34aa3aeada7d189f9d assets/create/blockstates/small_asurine_brick_stairs.json 02556b916c198c683279eb4392ebaa31fb41e182 assets/create/blockstates/small_asurine_brick_wall.json +b9fedc13dc8cb53a8bb16ce2257ea65f0ac94a6b assets/create/blockstates/small_asurine_bricks.json e986248237013eea755bccd300f745e44d0a183f assets/create/blockstates/small_bogey.json -031d9492dbcc5de77431e8f54b9b04db412b5690 assets/create/blockstates/small_calcite_bricks.json 898bca10ff6e5402c4b8b84e1b9ba9036b32b8bc assets/create/blockstates/small_calcite_brick_slab.json ecc2276bdb2b24f54e31372bf207171a348e55d3 assets/create/blockstates/small_calcite_brick_stairs.json d9dd243b5b754a487755b53609d404ac1b3fde99 assets/create/blockstates/small_calcite_brick_wall.json -3d4e0b54ffda83f7f6e08b6a745db81049d95f3b assets/create/blockstates/small_crimsite_bricks.json +031d9492dbcc5de77431e8f54b9b04db412b5690 assets/create/blockstates/small_calcite_bricks.json 4094bf00cad8dea2dd234866b482c07175802c4c assets/create/blockstates/small_crimsite_brick_slab.json 7f73a2505e2a3a98a7749fa98f4623aa2d216edd assets/create/blockstates/small_crimsite_brick_stairs.json b477c7f1855c9eb2ef1bf672376e972678dc563f assets/create/blockstates/small_crimsite_brick_wall.json -17359d1b87399bb066cfc23002bcf0d8f71d8ccd assets/create/blockstates/small_deepslate_bricks.json +3d4e0b54ffda83f7f6e08b6a745db81049d95f3b assets/create/blockstates/small_crimsite_bricks.json c67f32adc49f0b24b34f098a390a398813365260 assets/create/blockstates/small_deepslate_brick_slab.json d05aed31d45ed12f8f117a9c64312b1abff8bd2f assets/create/blockstates/small_deepslate_brick_stairs.json 6952b02d8c5adf3d0d1a243221b637c50edaa287 assets/create/blockstates/small_deepslate_brick_wall.json -6c0ac59e09feb76afc078a88431442a2a6381c6c assets/create/blockstates/small_diorite_bricks.json +17359d1b87399bb066cfc23002bcf0d8f71d8ccd assets/create/blockstates/small_deepslate_bricks.json ee39994b434a17ec7497b271a6e0a006cf6311cb assets/create/blockstates/small_diorite_brick_slab.json eb335cf0a857299b9cd0c4f60e00bc8e4ca7efe8 assets/create/blockstates/small_diorite_brick_stairs.json b6f7c563c30483c749849899b96d4f0030b71df1 assets/create/blockstates/small_diorite_brick_wall.json -d51095bfb9d5758f8b3972a973fbe282569b0234 assets/create/blockstates/small_dripstone_bricks.json +6c0ac59e09feb76afc078a88431442a2a6381c6c assets/create/blockstates/small_diorite_bricks.json 3d8109d327099c65ca0fafcb5651051059cad1df assets/create/blockstates/small_dripstone_brick_slab.json 3931e24229db79115ffe2a9f3a069202b9b8dcab assets/create/blockstates/small_dripstone_brick_stairs.json 0d16cefcb8e619bc81ef65111d16d331db58d0aa assets/create/blockstates/small_dripstone_brick_wall.json -11dcaf8a6da96d178024b4c3ee76b9c373e5d082 assets/create/blockstates/small_granite_bricks.json +d51095bfb9d5758f8b3972a973fbe282569b0234 assets/create/blockstates/small_dripstone_bricks.json 096b064f28fbe381e1b637d4668550851cbbb2c2 assets/create/blockstates/small_granite_brick_slab.json e99cc3251937fbf9fc858623d5ea525ed5b79704 assets/create/blockstates/small_granite_brick_stairs.json 62f2b570ac6073c8a98369523095d2c18a353eed assets/create/blockstates/small_granite_brick_wall.json -346dbff9a84b988bd9c9af670b486b6af5e18179 assets/create/blockstates/small_limestone_bricks.json +11dcaf8a6da96d178024b4c3ee76b9c373e5d082 assets/create/blockstates/small_granite_bricks.json d640eed81abaa013ed1c53d68a552f639168ae8b assets/create/blockstates/small_limestone_brick_slab.json d470967200aa6ca618421cf375140b352c45cc90 assets/create/blockstates/small_limestone_brick_stairs.json 8d4a1eff66a3f45d595ff8371c0d1ebaa0ba1773 assets/create/blockstates/small_limestone_brick_wall.json -1464b01d4c8bd9ec56460c1250fd4bb07e936e22 assets/create/blockstates/small_ochrum_bricks.json +346dbff9a84b988bd9c9af670b486b6af5e18179 assets/create/blockstates/small_limestone_bricks.json ddee92141e00898e8d70145cf00c0d64f56b4f48 assets/create/blockstates/small_ochrum_brick_slab.json bad9a5820c64c125494c0eba4f6c7ebebe93341c assets/create/blockstates/small_ochrum_brick_stairs.json ed899a18522adc70ae46185c308904c8de5b5834 assets/create/blockstates/small_ochrum_brick_wall.json +1464b01d4c8bd9ec56460c1250fd4bb07e936e22 assets/create/blockstates/small_ochrum_bricks.json c520e9ba54ff6dfb96f7863bb093cdf15cc95ce4 assets/create/blockstates/small_rose_quartz_tiles.json -371ff795eb4e7cb1220d307abf8cb003f455cbec assets/create/blockstates/small_scorchia_bricks.json 384a1331b92b7beba988f729bb7cda42abec0172 assets/create/blockstates/small_scorchia_brick_slab.json 046a84030a23f5a40f4deac13f2e60ced436cadf assets/create/blockstates/small_scorchia_brick_stairs.json 58bc6e3bb10ed72b8cb5813a88cab300d1183b7d assets/create/blockstates/small_scorchia_brick_wall.json -0aa51dbfda8349b878e2f6c9bb3314fcfc1a9c39 assets/create/blockstates/small_scoria_bricks.json +371ff795eb4e7cb1220d307abf8cb003f455cbec assets/create/blockstates/small_scorchia_bricks.json 5b227400e588abae33c1682196f098adc8006d13 assets/create/blockstates/small_scoria_brick_slab.json 51420bb12b757d3888fd1ceb5c21d83b42bd2266 assets/create/blockstates/small_scoria_brick_stairs.json 36e9bd161fa4ffe18f07153b2945cfeae55e7c0b assets/create/blockstates/small_scoria_brick_wall.json -c1f9f986dd0bfdbdee210c6c7d71981b251c27db assets/create/blockstates/small_tuff_bricks.json +0aa51dbfda8349b878e2f6c9bb3314fcfc1a9c39 assets/create/blockstates/small_scoria_bricks.json 8d1af444031291fe58d850ae344aaf7e97b8bd87 assets/create/blockstates/small_tuff_brick_slab.json 26879e6cadf0035c3eed4b54b3a1fdc0c080a485 assets/create/blockstates/small_tuff_brick_stairs.json 5d58ca7b81ae537454c3cdbb5fc8aacca83cff3f assets/create/blockstates/small_tuff_brick_wall.json -ad79aa8ff306695f65386fdeb44c5285547934b6 assets/create/blockstates/small_veridium_bricks.json +c1f9f986dd0bfdbdee210c6c7d71981b251c27db assets/create/blockstates/small_tuff_bricks.json 6226471fdcadbbf0e02704bb0e7de607e99302a8 assets/create/blockstates/small_veridium_brick_slab.json b54200ebe65c4ad2e5661c81ba5bf939039277ca assets/create/blockstates/small_veridium_brick_stairs.json 0237d58443ca9dc2a9186c2387dd6633702a7598 assets/create/blockstates/small_veridium_brick_wall.json +ad79aa8ff306695f65386fdeb44c5285547934b6 assets/create/blockstates/small_veridium_bricks.json 4d987859e5f5a930c20e955919304088fb6fc6d1 assets/create/blockstates/smart_chute.json 57fc35b2e0ae9ab16c011abd95f507910c70a234 assets/create/blockstates/smart_fluid_pipe.json a70c025de5d85180f371ff05bbdc531d8bdfaab1 assets/create/blockstates/speedometer.json @@ -568,9 +568,9 @@ a60c9c8241e40c2e28f5760c0ca6e80cfe9d59f3 assets/create/blockstates/steam_whistle 636ec6c7e1ef3b737edc716200f138bc63681d78 assets/create/blockstates/steam_whistle_extension.json 8865500bcd2e4d467e74edb3509850fa92a5809f assets/create/blockstates/sticker.json bed0534e618105184bc877b104230403ca85bb58 assets/create/blockstates/sticky_mechanical_piston.json -c7c17ff17b98ce85d355f2f9b4509271bc283843 assets/create/blockstates/stockpile_switch.json d17e6ac368278bd60442e2f19eb064a31c4106d2 assets/create/blockstates/stock_link.json 9989bda294fbffc5f659d2e608e01dea424c7694 assets/create/blockstates/stock_ticker.json +c7c17ff17b98ce85d355f2f9b4509271bc283843 assets/create/blockstates/stockpile_switch.json a70c025de5d85180f371ff05bbdc531d8bdfaab1 assets/create/blockstates/stressometer.json 8086f80c532fad42b37fcdc590b890ed7e8c3fe9 assets/create/blockstates/tiled_glass.json 1143ab7223c655764a81ed72ac385ea179664072 assets/create/blockstates/tiled_glass_pane.json @@ -590,36 +590,36 @@ bfb2b7eabba2e7aef4d783328c8a5a1558e7e493 assets/create/blockstates/turntable.jso 116d0a8fb72bcc00bd511db7893ea3e96efda297 assets/create/blockstates/warped_window_pane.json fa3d300520e3bedb926696d9980cbeeb54cfdc68 assets/create/blockstates/water_wheel.json 3dff9e1ec59415779195d2abfa9f07bc17b428a1 assets/create/blockstates/water_wheel_structure.json -2ae175c489b86b78b4646306250ca2dba66b0a5e assets/create/blockstates/waxed_copper_shingles.json 85ed36dcb0a3542e0638601116360202a9670d53 assets/create/blockstates/waxed_copper_shingle_slab.json aaf49f1b6785e2195c5dc2e8792c99c960745f89 assets/create/blockstates/waxed_copper_shingle_stairs.json -835bfe0d2137ad60e5f8322fa4449d5c7a02187f assets/create/blockstates/waxed_copper_tiles.json +2ae175c489b86b78b4646306250ca2dba66b0a5e assets/create/blockstates/waxed_copper_shingles.json b52eda74c9000507a4f34e10fbd1a7846b66c16d assets/create/blockstates/waxed_copper_tile_slab.json 5428969f6f27213d0ec5140d911b3844b5332006 assets/create/blockstates/waxed_copper_tile_stairs.json -306b9cd1efe3abd1fcca11bc464560837fb8fdfa assets/create/blockstates/waxed_exposed_copper_shingles.json +835bfe0d2137ad60e5f8322fa4449d5c7a02187f assets/create/blockstates/waxed_copper_tiles.json bc8f3bb75bdb094c8372d61a68927270d3347437 assets/create/blockstates/waxed_exposed_copper_shingle_slab.json 32382e5f524b50393080fdbd2415a98ddb700c9c assets/create/blockstates/waxed_exposed_copper_shingle_stairs.json -ae92a9051f1603e7ad4f93cb668706ccffc7a85b assets/create/blockstates/waxed_exposed_copper_tiles.json +306b9cd1efe3abd1fcca11bc464560837fb8fdfa assets/create/blockstates/waxed_exposed_copper_shingles.json ca37c3e54d5c78a77fcb4a4aca004a34e271f246 assets/create/blockstates/waxed_exposed_copper_tile_slab.json a864f82ccd6b3e0fa181c800da886ebd3239fb82 assets/create/blockstates/waxed_exposed_copper_tile_stairs.json -729ca65a140b3d7571a2072f7406cc5f4a2e27c5 assets/create/blockstates/waxed_oxidized_copper_shingles.json +ae92a9051f1603e7ad4f93cb668706ccffc7a85b assets/create/blockstates/waxed_exposed_copper_tiles.json ef99e849f9dd6ad53ddf04625c81750f11eaae1c assets/create/blockstates/waxed_oxidized_copper_shingle_slab.json 9386068220f9bb5d2f6d3cc408dc4f78f26b4eeb assets/create/blockstates/waxed_oxidized_copper_shingle_stairs.json -17acf3486e92aabc3efbe99fa1e5d7d664e6ec97 assets/create/blockstates/waxed_oxidized_copper_tiles.json +729ca65a140b3d7571a2072f7406cc5f4a2e27c5 assets/create/blockstates/waxed_oxidized_copper_shingles.json fe79f7eab017d714c0331664a3a2b5579104194e assets/create/blockstates/waxed_oxidized_copper_tile_slab.json 10bbe77a0334b5578b1ec40b398a45cf7d2bb534 assets/create/blockstates/waxed_oxidized_copper_tile_stairs.json -079acbfd6a9375899687b581f95bbe74940afce2 assets/create/blockstates/waxed_weathered_copper_shingles.json +17acf3486e92aabc3efbe99fa1e5d7d664e6ec97 assets/create/blockstates/waxed_oxidized_copper_tiles.json 73572bbe16957e63853ee425d8f34d98e14e4a10 assets/create/blockstates/waxed_weathered_copper_shingle_slab.json ab05925d5bb70e53fec9c149982304f31acd2b1a assets/create/blockstates/waxed_weathered_copper_shingle_stairs.json -202b0f2e6fca9eab949f47eaa1f4ddee249a633a assets/create/blockstates/waxed_weathered_copper_tiles.json +079acbfd6a9375899687b581f95bbe74940afce2 assets/create/blockstates/waxed_weathered_copper_shingles.json fc1b53d3b2b1f0977069abec3c376f3f5c4cd7c8 assets/create/blockstates/waxed_weathered_copper_tile_slab.json 6cd93476a45c3b77f5eda66f68425bae486cfba8 assets/create/blockstates/waxed_weathered_copper_tile_stairs.json -c11562afd9a5f85945e521dcea5f911d1b6d13c6 assets/create/blockstates/weathered_copper_shingles.json +202b0f2e6fca9eab949f47eaa1f4ddee249a633a assets/create/blockstates/waxed_weathered_copper_tiles.json 5a5a1e95988edb7a2b6dc6c6ba5677c2d896a5ae assets/create/blockstates/weathered_copper_shingle_slab.json 07019fc8890cb5e966a42ca636a0ab9cf71cc881 assets/create/blockstates/weathered_copper_shingle_stairs.json -236e072d9056c0dbffdf5d7d973a85a56c2c8de1 assets/create/blockstates/weathered_copper_tiles.json +c11562afd9a5f85945e521dcea5f911d1b6d13c6 assets/create/blockstates/weathered_copper_shingles.json fee668eb9a45dca0d287fee5811219d69f9ec3e2 assets/create/blockstates/weathered_copper_tile_slab.json da110f382368257e15431c77164aef82e014e3f8 assets/create/blockstates/weathered_copper_tile_stairs.json +236e072d9056c0dbffdf5d7d973a85a56c2c8de1 assets/create/blockstates/weathered_copper_tiles.json 64fb3e569da401635b64e71e01ea0b3ff6360611 assets/create/blockstates/weathered_iron_block.json 6fd81f1eb48fbfc44df9db8eedc613690c9b8ef5 assets/create/blockstates/weathered_iron_window.json 1aed351050d73989c4553bf49ce03b3a8fdd210e assets/create/blockstates/weathered_iron_window_pane.json @@ -806,21 +806,21 @@ d063df8e9b974c11fc7810ce176b02d7d924e15b assets/create/models/block/copper_post. 2b5aed4a917694beb33d9b0ecbc800dcbc143ee9 assets/create/models/block/copper_post_ends.json bac7566a726b0fe6d537c744aec4afb383dc165c assets/create/models/block/copper_scaffolding.json dbee65c129740f3b99c07e754b3224d3f9f8c242 assets/create/models/block/copper_scaffolding_horizontal.json -32fdb85b5b62d5a0fb41732874c854788cdd2ba1 assets/create/models/block/copper_shingles.json fb7fb6deebd502946ab57f1b8a9f4a6b5dd48da3 assets/create/models/block/copper_shingle_slab.json 660f61112b8e46dec5050cb0ed4ee936965a7c58 assets/create/models/block/copper_shingle_slab_top.json 5d74be967bbe9feba4b630751f13af817a733d1d assets/create/models/block/copper_shingle_stairs.json 35cb89f29ce3f8d8af13602c08ecd7afbb7cf56a assets/create/models/block/copper_shingle_stairs_inner.json fcb9295f4f388e6d439ec9a3906ca326b6d69077 assets/create/models/block/copper_shingle_stairs_outer.json +32fdb85b5b62d5a0fb41732874c854788cdd2ba1 assets/create/models/block/copper_shingles.json cb218a725f82db34ffe58a5208266e1c768cfc05 assets/create/models/block/copper_side.json d9b4652ca8f1e65007f42d946ecfb38acc3f168f assets/create/models/block/copper_side_alt.json 03a6c5b8bc3041a2be001092f7abd014d6f852a2 assets/create/models/block/copper_table_cloth.json -32f06f39d0b34e4431795aa6e64f87e58dc1597b assets/create/models/block/copper_tiles.json 298c6100de02ed9f813397d8ba38c46f35035c69 assets/create/models/block/copper_tile_slab.json d4422c2d96fb329087d1be70d8b983a8cf6c7f01 assets/create/models/block/copper_tile_slab_top.json fca72048f916d3a3e567b385c948cc1b59711ef4 assets/create/models/block/copper_tile_stairs.json 997479b62ed3d81ab633279ecc2fabd9588a3bf3 assets/create/models/block/copper_tile_stairs_inner.json d5c5bbfb9aaa282e11ad6e6309b1880b172ee653 assets/create/models/block/copper_tile_stairs_outer.json +32f06f39d0b34e4431795aa6e64f87e58dc1597b assets/create/models/block/copper_tiles.json fa2fa91e674eb4de440617049dae34064fd6fa39 assets/create/models/block/copper_valve_handle.json 52ae02c17509e483e35a1b6055296c3a663f85d7 assets/create/models/block/crate/creative/bottom.json 689989ecbd4d59d5836deb8adf7af1d473a377c0 assets/create/models/block/crate/creative/left.json @@ -864,15 +864,15 @@ b3f403f77e3b1b44c56450e387136bca12a84a99 assets/create/models/block/crimson_wind 117d14a1f25cc8ac633bb4cc8a81830a1c016096 assets/create/models/block/crimson_window_pane_side.json ee13522aadfca40f856499d5c29bd86d8f4dda57 assets/create/models/block/crimson_window_pane_side_alt.json 40042ce15d51445ec71b73da34477fa735f3fdd4 assets/create/models/block/cut_andesite.json -5be7d431ac56e2ceb9e3d95589d687f757d5257c assets/create/models/block/cut_andesite_bricks.json -c78e2acf9b54d7370f12e34dcca5c71743f47d55 assets/create/models/block/cut_andesite_bricks_wall_post.json -88e3c8eadf97f772fbafe3b71c8dd27c91c0c0e3 assets/create/models/block/cut_andesite_bricks_wall_side.json -bc264e09c506418b01c6032dcab8ca28080cb70b assets/create/models/block/cut_andesite_bricks_wall_side_tall.json fcbe246aca067dcfeef7afb4e6068b8932da8792 assets/create/models/block/cut_andesite_brick_slab.json e384a98b54ed7317b6ad0e86cf87500491eea824 assets/create/models/block/cut_andesite_brick_slab_top.json 91699e60e29e7524271a2f87200951ee8bfeb8ef assets/create/models/block/cut_andesite_brick_stairs.json e314e0837aed319cdf34a1aaa60f0be6ca169636 assets/create/models/block/cut_andesite_brick_stairs_inner.json aba679c4c6a8d5afc2924d2c9c84af5a2208fde3 assets/create/models/block/cut_andesite_brick_stairs_outer.json +5be7d431ac56e2ceb9e3d95589d687f757d5257c assets/create/models/block/cut_andesite_bricks.json +c78e2acf9b54d7370f12e34dcca5c71743f47d55 assets/create/models/block/cut_andesite_bricks_wall_post.json +88e3c8eadf97f772fbafe3b71c8dd27c91c0c0e3 assets/create/models/block/cut_andesite_bricks_wall_side.json +bc264e09c506418b01c6032dcab8ca28080cb70b assets/create/models/block/cut_andesite_bricks_wall_side_tall.json 8c17ba39e50a440497af089f5fd85649f05bdf8c assets/create/models/block/cut_andesite_slab.json b95ab966cf8c177c799e228759d0cd28c1cfa71f assets/create/models/block/cut_andesite_slab_top.json 81a407a5ff4393b66f784ba4ceee971c3c62de7f assets/create/models/block/cut_andesite_stairs.json @@ -882,15 +882,15 @@ f06abcb3ce691fd30db81b40ea0430462fc972cf assets/create/models/block/cut_andesite 81cef9548137aaff5b6e77d417f387796f2608b2 assets/create/models/block/cut_andesite_wall_side.json dbb99ac37333ee12b7d3859207409aa2599f28eb assets/create/models/block/cut_andesite_wall_side_tall.json a48f77e90c1d02d5b4e6540db723f748118788e9 assets/create/models/block/cut_asurine.json -3b0b7bd63870ac19b9444ce9add9930ec9120821 assets/create/models/block/cut_asurine_bricks.json -89142424e1d702a0f2bc27829304520e48ee1eb3 assets/create/models/block/cut_asurine_bricks_wall_post.json -1f1fcf92e91b1f0d15ba389d6d25e1fba3ad8e5b assets/create/models/block/cut_asurine_bricks_wall_side.json -858d15aff53fe938304bafb52ef32e54e3d44a44 assets/create/models/block/cut_asurine_bricks_wall_side_tall.json 4107317f71d07fb1c113e056c832e963f57b41d7 assets/create/models/block/cut_asurine_brick_slab.json fba2e8dc513184eaa9c4449471b32f206dfe425a assets/create/models/block/cut_asurine_brick_slab_top.json 72bb7b2df330f8d5981f4c12b23429d8d874362d assets/create/models/block/cut_asurine_brick_stairs.json e753ba3830c51539565abbd9b49df9a34f97f2ff assets/create/models/block/cut_asurine_brick_stairs_inner.json ec9182d14517ffc71749e3e016e6546db79e6800 assets/create/models/block/cut_asurine_brick_stairs_outer.json +3b0b7bd63870ac19b9444ce9add9930ec9120821 assets/create/models/block/cut_asurine_bricks.json +89142424e1d702a0f2bc27829304520e48ee1eb3 assets/create/models/block/cut_asurine_bricks_wall_post.json +1f1fcf92e91b1f0d15ba389d6d25e1fba3ad8e5b assets/create/models/block/cut_asurine_bricks_wall_side.json +858d15aff53fe938304bafb52ef32e54e3d44a44 assets/create/models/block/cut_asurine_bricks_wall_side_tall.json b4512f7cef7cef0bc5f85cb955c2dec6de2cbb56 assets/create/models/block/cut_asurine_slab.json 7c1befdd97b1556e9658e968e705c9edbf1ed667 assets/create/models/block/cut_asurine_slab_top.json d04b8a8cf9a50aa7e0b068ceb9a5a2970abc81a7 assets/create/models/block/cut_asurine_stairs.json @@ -900,15 +900,15 @@ ac544a8f948119945aa21362ad26ed8b1c922b0d assets/create/models/block/cut_asurine_ a253210cba60f58e720598323bd0d9ed4c209b4d assets/create/models/block/cut_asurine_wall_side.json c0c2cc13288771699a80c5c80e8e35d352cea684 assets/create/models/block/cut_asurine_wall_side_tall.json a6b10dc7984d22cac7aa314d46ac0928a00e667b assets/create/models/block/cut_calcite.json -6230a499321b175fc441bb662e0655662b3597de assets/create/models/block/cut_calcite_bricks.json -be1462847e9001a062091162802fab2fe6737693 assets/create/models/block/cut_calcite_bricks_wall_post.json -6e6b34468a7a0786efe5f4ebd917a4640b4be6ae assets/create/models/block/cut_calcite_bricks_wall_side.json -8b10c0f4f17f3844cee6d514cc22ddc6cb056c8a assets/create/models/block/cut_calcite_bricks_wall_side_tall.json f046be4f44936946bd3cc2ad5549d112b2e60d97 assets/create/models/block/cut_calcite_brick_slab.json 64953ca8a302ecab9311c617f69e5dcf8c138718 assets/create/models/block/cut_calcite_brick_slab_top.json 19e1b342d05d3cd69c410952dc22507c3c988c15 assets/create/models/block/cut_calcite_brick_stairs.json 18317b0a8bab345abd779f5d43f9620b73df0e67 assets/create/models/block/cut_calcite_brick_stairs_inner.json 0631d4e1bdaf724752f2e55401eb7a54af705b56 assets/create/models/block/cut_calcite_brick_stairs_outer.json +6230a499321b175fc441bb662e0655662b3597de assets/create/models/block/cut_calcite_bricks.json +be1462847e9001a062091162802fab2fe6737693 assets/create/models/block/cut_calcite_bricks_wall_post.json +6e6b34468a7a0786efe5f4ebd917a4640b4be6ae assets/create/models/block/cut_calcite_bricks_wall_side.json +8b10c0f4f17f3844cee6d514cc22ddc6cb056c8a assets/create/models/block/cut_calcite_bricks_wall_side_tall.json 6b35e0f9e6a7e247bf38d8d6d911a2bcc53c2517 assets/create/models/block/cut_calcite_slab.json 0eec7692ee8e119c1258bdb7e852204771c2232d assets/create/models/block/cut_calcite_slab_top.json d07ebf8982e4947852da8b2b0052f6b6000d334f assets/create/models/block/cut_calcite_stairs.json @@ -918,15 +918,15 @@ e8b7b983168ad9f4f4fa1642ca20ff56621935db assets/create/models/block/cut_calcite_ 421e128177bb4dd51391e360f11ba83c5d891cd1 assets/create/models/block/cut_calcite_wall_side.json 5add4bde51bbdd7c229b05f4fabd8a769414fb79 assets/create/models/block/cut_calcite_wall_side_tall.json 2e93da554ea72b90a576bbc9230aea373d3aed0f assets/create/models/block/cut_crimsite.json -39d1a3cdd978c761bc0d67baaba82d11953fc2a0 assets/create/models/block/cut_crimsite_bricks.json -8614cb38c52447fea5245fcf295a951a977071c0 assets/create/models/block/cut_crimsite_bricks_wall_post.json -b0b16f4a2f6dd3f77ec4f65f05e9edb70a196316 assets/create/models/block/cut_crimsite_bricks_wall_side.json -ac41e5b092c6ed81d14004f9427b6151b88dc924 assets/create/models/block/cut_crimsite_bricks_wall_side_tall.json c2474a10109d0476a46d2a509fc1cd37cd52822d assets/create/models/block/cut_crimsite_brick_slab.json efeb149835a389409b7f94bc35765b0871ad7342 assets/create/models/block/cut_crimsite_brick_slab_top.json e5096a1bae43341bae5706f02cd6d564b5a82502 assets/create/models/block/cut_crimsite_brick_stairs.json af3c0018e5e12bbe0f118bc0174b6ca513ae58ae assets/create/models/block/cut_crimsite_brick_stairs_inner.json ed30baef426f2ccf158d87111c7b53f3600bc32a assets/create/models/block/cut_crimsite_brick_stairs_outer.json +39d1a3cdd978c761bc0d67baaba82d11953fc2a0 assets/create/models/block/cut_crimsite_bricks.json +8614cb38c52447fea5245fcf295a951a977071c0 assets/create/models/block/cut_crimsite_bricks_wall_post.json +b0b16f4a2f6dd3f77ec4f65f05e9edb70a196316 assets/create/models/block/cut_crimsite_bricks_wall_side.json +ac41e5b092c6ed81d14004f9427b6151b88dc924 assets/create/models/block/cut_crimsite_bricks_wall_side_tall.json a6cdd4b227210b7487b8431b8d76bbe490636b81 assets/create/models/block/cut_crimsite_slab.json 5c585dba4dbfa9ff0a22a84aa726260cffdeebeb assets/create/models/block/cut_crimsite_slab_top.json 91f60b4277ca48dabfb5d3eebb1ed64a2681a083 assets/create/models/block/cut_crimsite_stairs.json @@ -936,15 +936,15 @@ e6b39a0b1dbab462479fc60fab2efc6a9ceb6a55 assets/create/models/block/cut_crimsite 5b3783862e50fde6ffffc92068900afcc066002f assets/create/models/block/cut_crimsite_wall_side.json b59fbbfe9c6738b1f93f03d59a747f5610164c34 assets/create/models/block/cut_crimsite_wall_side_tall.json 144ec3864fb0a7981e74d357200a96033c75a2d6 assets/create/models/block/cut_deepslate.json -0d599ae1b4e9309f2a7b3362e86061e2150ba3ec assets/create/models/block/cut_deepslate_bricks.json -601894e096edbcd3d96ce0160f06e17a4efca819 assets/create/models/block/cut_deepslate_bricks_wall_post.json -42db46cb5c9c02d684c86f3a518feb3348d83fa0 assets/create/models/block/cut_deepslate_bricks_wall_side.json -c046436d59c350c6beb6b395675513c12184ffe2 assets/create/models/block/cut_deepslate_bricks_wall_side_tall.json af8c7c652e75bf904093bbafc1cf805f842a39c9 assets/create/models/block/cut_deepslate_brick_slab.json 2a01dd0244b07f28454c061a565d1028ca7e3066 assets/create/models/block/cut_deepslate_brick_slab_top.json 62d39eec3621204de82377e74936b9cd338e8004 assets/create/models/block/cut_deepslate_brick_stairs.json 5f90dfbb45b57bd894bf03fcc6c347cb525e3a73 assets/create/models/block/cut_deepslate_brick_stairs_inner.json 512d588c77bdf5a7232826e2f4ce4b3cb991d0ce assets/create/models/block/cut_deepslate_brick_stairs_outer.json +0d599ae1b4e9309f2a7b3362e86061e2150ba3ec assets/create/models/block/cut_deepslate_bricks.json +601894e096edbcd3d96ce0160f06e17a4efca819 assets/create/models/block/cut_deepslate_bricks_wall_post.json +42db46cb5c9c02d684c86f3a518feb3348d83fa0 assets/create/models/block/cut_deepslate_bricks_wall_side.json +c046436d59c350c6beb6b395675513c12184ffe2 assets/create/models/block/cut_deepslate_bricks_wall_side_tall.json c79ae6e97e94d36f2586865ea63f3fab43f8ccbc assets/create/models/block/cut_deepslate_slab.json 5978b93805ccf0bdd953938b34a8dd0ffdcf5565 assets/create/models/block/cut_deepslate_slab_top.json 06a508b2395c3f738d2c5651f366792ee9b9c5ec assets/create/models/block/cut_deepslate_stairs.json @@ -954,15 +954,15 @@ c2850e9f223c459ba53d575a1ef8231589c48c0b assets/create/models/block/cut_deepslat e901746d3e50fe7d9b79d268f4d02251d5cf95f4 assets/create/models/block/cut_deepslate_wall_side.json 1ef794aab31a10bf150a0015cd46e5b5f3c70042 assets/create/models/block/cut_deepslate_wall_side_tall.json 4abb502ea3f6764797641f55a2c48f4858be1ba6 assets/create/models/block/cut_diorite.json -e97babf115a4f81f8555994aba435cf76bebf7a3 assets/create/models/block/cut_diorite_bricks.json -4f7cf44e4d6431587266a4fac78c0812e99d780c assets/create/models/block/cut_diorite_bricks_wall_post.json -1f96f9e190d8e28496ce2db5712f33e449215985 assets/create/models/block/cut_diorite_bricks_wall_side.json -45246192d9cd39837b426e425fc5082422642b65 assets/create/models/block/cut_diorite_bricks_wall_side_tall.json ab61b1b94946f315006a29113f594c234d796bee assets/create/models/block/cut_diorite_brick_slab.json 73597772386c6bbd38907cbea8db816f174a9f8f assets/create/models/block/cut_diorite_brick_slab_top.json c9fbd953ef0789a0e9a915d5f283fd09a76784d6 assets/create/models/block/cut_diorite_brick_stairs.json 5d721f1b3f4376a91707b56950a1f9635adbe603 assets/create/models/block/cut_diorite_brick_stairs_inner.json 9a446bf02732e1873fa96d7745fced0fa04d48d6 assets/create/models/block/cut_diorite_brick_stairs_outer.json +e97babf115a4f81f8555994aba435cf76bebf7a3 assets/create/models/block/cut_diorite_bricks.json +4f7cf44e4d6431587266a4fac78c0812e99d780c assets/create/models/block/cut_diorite_bricks_wall_post.json +1f96f9e190d8e28496ce2db5712f33e449215985 assets/create/models/block/cut_diorite_bricks_wall_side.json +45246192d9cd39837b426e425fc5082422642b65 assets/create/models/block/cut_diorite_bricks_wall_side_tall.json 15195975e7e0ffb7010591b957a657f492e6d59d assets/create/models/block/cut_diorite_slab.json 01c320637843dc0d8b74b48b8d6946cd663d51f6 assets/create/models/block/cut_diorite_slab_top.json 7dcbfe4dc2ec62345da660ecc6ca44056fcd64e7 assets/create/models/block/cut_diorite_stairs.json @@ -972,15 +972,15 @@ c9fbd953ef0789a0e9a915d5f283fd09a76784d6 assets/create/models/block/cut_diorite_ 29075eaaba51ba158f030c2a9583ed5ba52379c8 assets/create/models/block/cut_diorite_wall_side.json 1fb50473359147c7147ea85bc1907e6015ce06bc assets/create/models/block/cut_diorite_wall_side_tall.json 59ee053a884bc9731b4d1b01ae22e0e2b5916cfb assets/create/models/block/cut_dripstone.json -6a4b26a117f58d0187b2cc0c5b117ef71d03d4e9 assets/create/models/block/cut_dripstone_bricks.json -0bb1fa8fb9698dae61096483a01b41bf829666b0 assets/create/models/block/cut_dripstone_bricks_wall_post.json -2019fdc38b401bac72e8344d118d85049ec3efb9 assets/create/models/block/cut_dripstone_bricks_wall_side.json -ebb790b2b6f47d40c92c9bba680e82cb8f054fa9 assets/create/models/block/cut_dripstone_bricks_wall_side_tall.json 84d714b29dcb7eb95a82de8d48491413e26d5fa8 assets/create/models/block/cut_dripstone_brick_slab.json 28b0b1a641d11f8ade57c444e4c1bfd9d617f66a assets/create/models/block/cut_dripstone_brick_slab_top.json 05900c156a6341c12b366790c7e8d15e59a873f0 assets/create/models/block/cut_dripstone_brick_stairs.json 35fb2c83dc89b96951c69253f7502f78c903a9b8 assets/create/models/block/cut_dripstone_brick_stairs_inner.json f69244c1706c95aaadd32d45a24c91ce0848509f assets/create/models/block/cut_dripstone_brick_stairs_outer.json +6a4b26a117f58d0187b2cc0c5b117ef71d03d4e9 assets/create/models/block/cut_dripstone_bricks.json +0bb1fa8fb9698dae61096483a01b41bf829666b0 assets/create/models/block/cut_dripstone_bricks_wall_post.json +2019fdc38b401bac72e8344d118d85049ec3efb9 assets/create/models/block/cut_dripstone_bricks_wall_side.json +ebb790b2b6f47d40c92c9bba680e82cb8f054fa9 assets/create/models/block/cut_dripstone_bricks_wall_side_tall.json 9e42cf588f57de5166f2a2ccdae656743c8b9481 assets/create/models/block/cut_dripstone_slab.json 0da2f782d8ad8fecd81b98c72db182b817bf19eb assets/create/models/block/cut_dripstone_slab_top.json b3c903a1edcd1786ea51a2ccdad5734a1d04ea98 assets/create/models/block/cut_dripstone_stairs.json @@ -990,15 +990,15 @@ b3c903a1edcd1786ea51a2ccdad5734a1d04ea98 assets/create/models/block/cut_dripston 7fab5102d7fa4cd824b9393425639d05727b2ad2 assets/create/models/block/cut_dripstone_wall_side.json c41514cda1c9f5d942d222cbc5f6e620e367afc6 assets/create/models/block/cut_dripstone_wall_side_tall.json dff602c8d2fcd1ceca79f90ae15dbdfbd6cb157d assets/create/models/block/cut_granite.json -31c5299a42f82992e50f711e1e33549c373bd034 assets/create/models/block/cut_granite_bricks.json -ef5a851e57cc4b9c0e625176b1256441e1c17c66 assets/create/models/block/cut_granite_bricks_wall_post.json -815e8dc551c3e813b0b2af29df23a28860de0b53 assets/create/models/block/cut_granite_bricks_wall_side.json -ba241f9c82e27dd98ba6f4e4180922388ab5d1a3 assets/create/models/block/cut_granite_bricks_wall_side_tall.json 9e00dc8fcee23548c0cebda6eadbcfc559e4c20b assets/create/models/block/cut_granite_brick_slab.json 5ad061096451f74e773c3030f96d59424aa93314 assets/create/models/block/cut_granite_brick_slab_top.json 94f8ce607aae5c04ccf9e56f177f9d69203ae879 assets/create/models/block/cut_granite_brick_stairs.json 11d511844fec3bfd05cac8b788332f2decd53021 assets/create/models/block/cut_granite_brick_stairs_inner.json 418eb6a2b52e748a26c2d1914c6c1de94106589f assets/create/models/block/cut_granite_brick_stairs_outer.json +31c5299a42f82992e50f711e1e33549c373bd034 assets/create/models/block/cut_granite_bricks.json +ef5a851e57cc4b9c0e625176b1256441e1c17c66 assets/create/models/block/cut_granite_bricks_wall_post.json +815e8dc551c3e813b0b2af29df23a28860de0b53 assets/create/models/block/cut_granite_bricks_wall_side.json +ba241f9c82e27dd98ba6f4e4180922388ab5d1a3 assets/create/models/block/cut_granite_bricks_wall_side_tall.json 81be5e86cbdaec4945d3ccaf6d376f69c49f40d6 assets/create/models/block/cut_granite_slab.json f72a14e7cf3dd7d93b4462a3bee49683353dfb57 assets/create/models/block/cut_granite_slab_top.json 33bf924f01aae3a7720475f4b32b3a637e69ee36 assets/create/models/block/cut_granite_stairs.json @@ -1008,15 +1008,15 @@ fb4969e562ad2039d3bad2dc57a6845d3243d453 assets/create/models/block/cut_granite_ 2972b40134bcb15950a0118306f0251ff5e377b7 assets/create/models/block/cut_granite_wall_side.json abbe71fd17dbb5f176553db2f6edf2f1f7d8974a assets/create/models/block/cut_granite_wall_side_tall.json 019d3c4ffb39e328b5458aee44fee90e0ecbd829 assets/create/models/block/cut_limestone.json -7eae0f9766506f713933bde9f301d2f7f2bbef13 assets/create/models/block/cut_limestone_bricks.json -817e8cf8956af36c70e4b4e30b5d141086d006dd assets/create/models/block/cut_limestone_bricks_wall_post.json -1291cacff1b0980e58b5702a84c9b87ac5ef835d assets/create/models/block/cut_limestone_bricks_wall_side.json -6c9bc8803fe17ac623bde56f85683dd2ff13c33e assets/create/models/block/cut_limestone_bricks_wall_side_tall.json c93f33ba39c62b10dfb94c6e1c339cd4fbebffae assets/create/models/block/cut_limestone_brick_slab.json b12a340897ba98ed732a91dbd4129db7a7188e68 assets/create/models/block/cut_limestone_brick_slab_top.json 3e90b32d95ad1cf7b8a16dae3c16724510d41490 assets/create/models/block/cut_limestone_brick_stairs.json b2e7311667d14b2aa8c00e207f69f76207226567 assets/create/models/block/cut_limestone_brick_stairs_inner.json aac619ec1fb8aa56f1752ad3f354f9cb128771f8 assets/create/models/block/cut_limestone_brick_stairs_outer.json +7eae0f9766506f713933bde9f301d2f7f2bbef13 assets/create/models/block/cut_limestone_bricks.json +817e8cf8956af36c70e4b4e30b5d141086d006dd assets/create/models/block/cut_limestone_bricks_wall_post.json +1291cacff1b0980e58b5702a84c9b87ac5ef835d assets/create/models/block/cut_limestone_bricks_wall_side.json +6c9bc8803fe17ac623bde56f85683dd2ff13c33e assets/create/models/block/cut_limestone_bricks_wall_side_tall.json adc21af1c07edaf0573cfd2c95ebe38e50f7282c assets/create/models/block/cut_limestone_slab.json 2d1ea8fc5c8ce5549c7f7888371b6612bf0f5301 assets/create/models/block/cut_limestone_slab_top.json c1416808a2178996be75e0a9c1cd45849fcd6646 assets/create/models/block/cut_limestone_stairs.json @@ -1026,15 +1026,15 @@ c1416808a2178996be75e0a9c1cd45849fcd6646 assets/create/models/block/cut_limeston 2b5e65e662069a5c59e702224778dd407f5d11dd assets/create/models/block/cut_limestone_wall_side.json 052f130fef646242acccbbed2b510add21e18921 assets/create/models/block/cut_limestone_wall_side_tall.json 66cb6054821d45a60ae4d4d1d904dbef0b9f7c0f assets/create/models/block/cut_ochrum.json -0a7e38e3ac32352c5b3ec56a8c26212dbbb637a3 assets/create/models/block/cut_ochrum_bricks.json -47d0c58dd190f1ea894a5ca40ea7efd54a845d3e assets/create/models/block/cut_ochrum_bricks_wall_post.json -b502b5b213996bce0a626d86414045c80921511e assets/create/models/block/cut_ochrum_bricks_wall_side.json -c3f27545b3b7654c3e7a2df6b482d1a9895ccae9 assets/create/models/block/cut_ochrum_bricks_wall_side_tall.json ce16ec490ae8a33671502804e0b45fc42b6f228f assets/create/models/block/cut_ochrum_brick_slab.json fcbee94fdbd96b0b3d4aa245c6c87443abd1de90 assets/create/models/block/cut_ochrum_brick_slab_top.json 827349ed3eb05f5fe700e8f5816bcd82d0347612 assets/create/models/block/cut_ochrum_brick_stairs.json aa81d4135400eb40f891f8c41fcf7fa516ef64f1 assets/create/models/block/cut_ochrum_brick_stairs_inner.json ecd7e1cb9cae717e35eeb58dbe482833e98f5ac0 assets/create/models/block/cut_ochrum_brick_stairs_outer.json +0a7e38e3ac32352c5b3ec56a8c26212dbbb637a3 assets/create/models/block/cut_ochrum_bricks.json +47d0c58dd190f1ea894a5ca40ea7efd54a845d3e assets/create/models/block/cut_ochrum_bricks_wall_post.json +b502b5b213996bce0a626d86414045c80921511e assets/create/models/block/cut_ochrum_bricks_wall_side.json +c3f27545b3b7654c3e7a2df6b482d1a9895ccae9 assets/create/models/block/cut_ochrum_bricks_wall_side_tall.json e23998f88eb77826f5e4d58f3f4bb41a2e09ea97 assets/create/models/block/cut_ochrum_slab.json cd14f1abe3d0c65fbdd052f4a8e0b8fc2a15ad0e assets/create/models/block/cut_ochrum_slab_top.json a751feb4b609df141f971e341b204e76379dcda7 assets/create/models/block/cut_ochrum_stairs.json @@ -1044,15 +1044,15 @@ bed6843e39e7e771f6de151dfab0586d3ebad58c assets/create/models/block/cut_ochrum_s df267fb690642cac139aaabefa9eab802f13ddc1 assets/create/models/block/cut_ochrum_wall_side.json ed363b80cc61cb4d0b6fad9da855a0543ecaccc9 assets/create/models/block/cut_ochrum_wall_side_tall.json a65a54a08d9cc3b45e2320482dc2d9e317dd4f3d assets/create/models/block/cut_scorchia.json -9c93a554ab680d7c98c648c16472b52cc2646c50 assets/create/models/block/cut_scorchia_bricks.json -615dc444bb677caa774a4e95686ac24ebe4ec6dc assets/create/models/block/cut_scorchia_bricks_wall_post.json -758a2ad6677f857fbe955c26853eadc7150c105a assets/create/models/block/cut_scorchia_bricks_wall_side.json -f918dfa0751589d18a3eb054c290f669b5c61308 assets/create/models/block/cut_scorchia_bricks_wall_side_tall.json a032cf0a77e4f416ed153b1ffa834c065a73b2ae assets/create/models/block/cut_scorchia_brick_slab.json 716fc6ef58c240b3e6b45acf08d6e1472fe38e7c assets/create/models/block/cut_scorchia_brick_slab_top.json b2870e5ba7c5d5053b3639bf0aa1771ee050810b assets/create/models/block/cut_scorchia_brick_stairs.json 3e8a815eabd1991039a8ad18cedc9c57f46cd097 assets/create/models/block/cut_scorchia_brick_stairs_inner.json 0a9dc3149e7219a70642c242cd86dce5ba5cf4cc assets/create/models/block/cut_scorchia_brick_stairs_outer.json +9c93a554ab680d7c98c648c16472b52cc2646c50 assets/create/models/block/cut_scorchia_bricks.json +615dc444bb677caa774a4e95686ac24ebe4ec6dc assets/create/models/block/cut_scorchia_bricks_wall_post.json +758a2ad6677f857fbe955c26853eadc7150c105a assets/create/models/block/cut_scorchia_bricks_wall_side.json +f918dfa0751589d18a3eb054c290f669b5c61308 assets/create/models/block/cut_scorchia_bricks_wall_side_tall.json a85c4d0467c6746a8ef9c6ac0167d3e16f307d4e assets/create/models/block/cut_scorchia_slab.json 23fd6c65ea83f7ca7ef67dd7faf902c4fa662d70 assets/create/models/block/cut_scorchia_slab_top.json e42329f6fa3aeb958d2349a5442856e9473dc6b5 assets/create/models/block/cut_scorchia_stairs.json @@ -1062,15 +1062,15 @@ b9a911675861fee414f82c745399a7707c258f77 assets/create/models/block/cut_scorchia e61af066960897d50dc7f7bc17f95baa962829bd assets/create/models/block/cut_scorchia_wall_side.json 846f84efddca7d51b58ebe5e3bbed78312fb052d assets/create/models/block/cut_scorchia_wall_side_tall.json ce9dcf5b7fe58a97fab832fb98b4f5b6d3778255 assets/create/models/block/cut_scoria.json -fa3ef2bb65299c985b70f6959421e243a9ebc6d8 assets/create/models/block/cut_scoria_bricks.json -24ea1a30f68a918e6737dc8d9babe4528af5716a assets/create/models/block/cut_scoria_bricks_wall_post.json -ba7ae110d51fe510566ab42f5ead299b4409f2b7 assets/create/models/block/cut_scoria_bricks_wall_side.json -f04d12bc4e0b939bb443abcc6eb808e66c352c66 assets/create/models/block/cut_scoria_bricks_wall_side_tall.json edf04cbfb19b6ce99c1b74a71d40cd40c8120551 assets/create/models/block/cut_scoria_brick_slab.json f05725fd6d2764b277f01985d0e2fcbd3bf4a41e assets/create/models/block/cut_scoria_brick_slab_top.json 4bccbaef9dd9a8322087d3feb973e14d740ff27a assets/create/models/block/cut_scoria_brick_stairs.json 13f3b55dfdd97e68a6d525166618477e5bcb336d assets/create/models/block/cut_scoria_brick_stairs_inner.json 465862fb20542cae723fd72818be73aec05dad60 assets/create/models/block/cut_scoria_brick_stairs_outer.json +fa3ef2bb65299c985b70f6959421e243a9ebc6d8 assets/create/models/block/cut_scoria_bricks.json +24ea1a30f68a918e6737dc8d9babe4528af5716a assets/create/models/block/cut_scoria_bricks_wall_post.json +ba7ae110d51fe510566ab42f5ead299b4409f2b7 assets/create/models/block/cut_scoria_bricks_wall_side.json +f04d12bc4e0b939bb443abcc6eb808e66c352c66 assets/create/models/block/cut_scoria_bricks_wall_side_tall.json aeef239ca6b0eee527f75091d11d4a947740416d assets/create/models/block/cut_scoria_slab.json 5dfda9fa8117d35ebc324a5c9cb026e206e3b936 assets/create/models/block/cut_scoria_slab_top.json dfe8dbdb6deca69d847ee46fedfefe2da98dc329 assets/create/models/block/cut_scoria_stairs.json @@ -1080,15 +1080,15 @@ e0b2a94ff4b3f1c1e4282c9c8eecf2583bd7c68e assets/create/models/block/cut_scoria_w cf18e3fde94e3ba611f430fe527a9042a57e6936 assets/create/models/block/cut_scoria_wall_side.json 92475d7758b2bf582c585c2aafa6510f330c6f45 assets/create/models/block/cut_scoria_wall_side_tall.json 9f6543d21d9c24a429aae00511e6dbf61caf8030 assets/create/models/block/cut_tuff.json -8b3d9fe37ab7fda79ea4d90f674c525350883ba0 assets/create/models/block/cut_tuff_bricks.json -6b80481e15ff3d6eb40a42128da883c2027e0074 assets/create/models/block/cut_tuff_bricks_wall_post.json -057a34015b49565cb9858a2eea995a446ac0cfd4 assets/create/models/block/cut_tuff_bricks_wall_side.json -9f20bd04ef163076db9a8bf83c20cc802b57ae60 assets/create/models/block/cut_tuff_bricks_wall_side_tall.json 8c16599fda76c38978a2faa14f842a68fbbe4b9c assets/create/models/block/cut_tuff_brick_slab.json 696036e5900bdbb366dd49f5df71a1e701fd8ee3 assets/create/models/block/cut_tuff_brick_slab_top.json 54d4603e36be86e88d9302d61eab81e76cac1bbc assets/create/models/block/cut_tuff_brick_stairs.json 0ebb41a1ce5bf4ca86cbaf95e83cd2edf8f309ea assets/create/models/block/cut_tuff_brick_stairs_inner.json 5d5ed291db4b4bca464717c7fcde682b33d71c3f assets/create/models/block/cut_tuff_brick_stairs_outer.json +8b3d9fe37ab7fda79ea4d90f674c525350883ba0 assets/create/models/block/cut_tuff_bricks.json +6b80481e15ff3d6eb40a42128da883c2027e0074 assets/create/models/block/cut_tuff_bricks_wall_post.json +057a34015b49565cb9858a2eea995a446ac0cfd4 assets/create/models/block/cut_tuff_bricks_wall_side.json +9f20bd04ef163076db9a8bf83c20cc802b57ae60 assets/create/models/block/cut_tuff_bricks_wall_side_tall.json f2a904b7943555e8ec9dcc07513ca1ad9af809c3 assets/create/models/block/cut_tuff_slab.json ea74bb8a69f6acbd520ac8922e147495e5f99f6f assets/create/models/block/cut_tuff_slab_top.json 0262700e59de947907a04fdea9974f9d7e5a22f2 assets/create/models/block/cut_tuff_stairs.json @@ -1098,15 +1098,15 @@ ea74bb8a69f6acbd520ac8922e147495e5f99f6f assets/create/models/block/cut_tuff_sla 8c6492dc9e09359e5bac67ae4d473cffc8f93dbb assets/create/models/block/cut_tuff_wall_side.json f5f24066b6281303f52e25745881d5bca8c49c54 assets/create/models/block/cut_tuff_wall_side_tall.json 167e9a084987bcf7f67f655d0de88ae8ca2fcebb assets/create/models/block/cut_veridium.json -f8ab87c34f211a63525f6d386397face67460f8c assets/create/models/block/cut_veridium_bricks.json -e4e717fa8412032e184aebd1186470f41a2089c0 assets/create/models/block/cut_veridium_bricks_wall_post.json -8c40ccb8f10ef8dcda1bef46ad3490f697d178d2 assets/create/models/block/cut_veridium_bricks_wall_side.json -2c4671c66d904e15883ec3a14681b97ac537135c assets/create/models/block/cut_veridium_bricks_wall_side_tall.json 07c330c501375d5c316677edee80fb040c0fc237 assets/create/models/block/cut_veridium_brick_slab.json 4c8c660afe72e8ce9eaef53a37fdc63eb0c69513 assets/create/models/block/cut_veridium_brick_slab_top.json f802e4ae758e2c37c3129594ce4f5d9ffcfe173d assets/create/models/block/cut_veridium_brick_stairs.json 0d60d5cd0269e05816d28fcbbd2c680fe60cd316 assets/create/models/block/cut_veridium_brick_stairs_inner.json 22656f90b55aeaeeffa448b5f061fb26b5de7b0f assets/create/models/block/cut_veridium_brick_stairs_outer.json +f8ab87c34f211a63525f6d386397face67460f8c assets/create/models/block/cut_veridium_bricks.json +e4e717fa8412032e184aebd1186470f41a2089c0 assets/create/models/block/cut_veridium_bricks_wall_post.json +8c40ccb8f10ef8dcda1bef46ad3490f697d178d2 assets/create/models/block/cut_veridium_bricks_wall_side.json +2c4671c66d904e15883ec3a14681b97ac537135c assets/create/models/block/cut_veridium_bricks_wall_side_tall.json d736230e9b49a9fd40bc8f31df4d5144cdb429c8 assets/create/models/block/cut_veridium_slab.json 750e536c7b71dfb3a005d9b7a128ac435461e57f assets/create/models/block/cut_veridium_slab_top.json 8b05c19560e97ce15a66202717e3d32f6ee153a9 assets/create/models/block/cut_veridium_stairs.json @@ -1136,22 +1136,25 @@ db89bc32d0e466bc5008aa7091c682ba3aeec611 assets/create/models/block/diorite_pill a21387ab955f2b91e402b2189145f5fd6623592d assets/create/models/block/diorite_pillar_horizontal.json 44af455badc2b35a763007bba3537bda7d0ac289 assets/create/models/block/dripstone_pillar.json 1e23e3758e3311d0063c83742abb750a05021075 assets/create/models/block/dripstone_pillar_horizontal.json -19a773f91c58c49301f35965bac02d0c05fb2764 assets/create/models/block/exposed_copper_shingles.json a3420b91fdebec40e508a5eebb145c0201bd80c8 assets/create/models/block/exposed_copper_shingle_slab.json 4178ea5e50ee17b3c15f4a59efd019c4a19bb892 assets/create/models/block/exposed_copper_shingle_slab_top.json dd2d747774abc86e428a883e299db66cded78e11 assets/create/models/block/exposed_copper_shingle_stairs.json b6845da62d96a33cee624bb70360e256b26eda83 assets/create/models/block/exposed_copper_shingle_stairs_inner.json 3d8b758e50e75c5adc26ab6f39f9d73f00866673 assets/create/models/block/exposed_copper_shingle_stairs_outer.json -9cb20c9d41629d8b9426cb65829365d10966338f assets/create/models/block/exposed_copper_tiles.json +19a773f91c58c49301f35965bac02d0c05fb2764 assets/create/models/block/exposed_copper_shingles.json cd21d9d2935b6d0103502e2731c11ea27ff64ecf assets/create/models/block/exposed_copper_tile_slab.json 0ec039ba59fb0028183433e52131ff355ace5bff assets/create/models/block/exposed_copper_tile_slab_top.json c51dbd34996ac4513234800e427ac308067d5e1d assets/create/models/block/exposed_copper_tile_stairs.json 68772d4352dc7ade995dfa57ba41a38ef819e855 assets/create/models/block/exposed_copper_tile_stairs_inner.json d932671822ba93b71a9c8b50e7207803a1c4dbab assets/create/models/block/exposed_copper_tile_stairs_outer.json +9cb20c9d41629d8b9426cb65829365d10966338f assets/create/models/block/exposed_copper_tiles.json 2d1ade82820569936fd3021a877283474ced09d0 assets/create/models/block/fake_track.json 9e41f0b90dd1e71766c9d07bdb75d1e553f3392f assets/create/models/block/fluid_pipe/d_x.json 13507730f6ca6462c4cfeddc46e5b21e93fb1287 assets/create/models/block/fluid_pipe/d_y.json 84c09934d3537343a1226389993dabfa850b745e assets/create/models/block/fluid_pipe/d_z.json +b8fd54e514bd50fb287c6b758647818c6b08ef75 assets/create/models/block/fluid_pipe/l_x.json +e985ff9dbe7324cf69ab38e6e9e85c9b554af56c assets/create/models/block/fluid_pipe/l_y.json +e24957d63bac1e754fcc1647a4a86337a67f6298 assets/create/models/block/fluid_pipe/l_z.json eacc5ee5f164ccc7c13cfbbd37a92b401222debe assets/create/models/block/fluid_pipe/ld_x.json 33fc0ecce85fae051c54d5a538793d7081238894 assets/create/models/block/fluid_pipe/ld_y.json 638f1a259cabed1f8d63c6fdaa6d4d4dff539e7d assets/create/models/block/fluid_pipe/ld_z.json @@ -1161,24 +1164,21 @@ c52521cd566294c797312104284ddd343fad9c2e assets/create/models/block/fluid_pipe/l 99637310d3ca1ccfbe62b03aa9b0d82a0cf6f724 assets/create/models/block/fluid_pipe/lu_x.json 986800d441e95553464d1869d39baf456f5d70dc assets/create/models/block/fluid_pipe/lu_y.json 11dcf7d2dcd0df9b043035cb072deee96ab9e6da assets/create/models/block/fluid_pipe/lu_z.json -b8fd54e514bd50fb287c6b758647818c6b08ef75 assets/create/models/block/fluid_pipe/l_x.json -e985ff9dbe7324cf69ab38e6e9e85c9b554af56c assets/create/models/block/fluid_pipe/l_y.json -e24957d63bac1e754fcc1647a4a86337a67f6298 assets/create/models/block/fluid_pipe/l_z.json +d44ff2aed71039a7d0ff913d0d9e8398e1318f39 assets/create/models/block/fluid_pipe/r_x.json +92d4044b51a90da0b2277b0613c7ca0bb80c66fe assets/create/models/block/fluid_pipe/r_y.json +fb9a23de00ef4edb4f7e24fb60de345cd12e513f assets/create/models/block/fluid_pipe/r_z.json bde9ec36b86113a6ca7a51a4f405994460a2eb56 assets/create/models/block/fluid_pipe/rd_x.json bd325f5b37ff08328ddddeeceac1a41be586d20a assets/create/models/block/fluid_pipe/rd_y.json 28f351fd215af3a991ccd9aa05c57b9cd9e6f58d assets/create/models/block/fluid_pipe/rd_z.json 1ff3ea321aeacca70709eb76370c11c7f13163b6 assets/create/models/block/fluid_pipe/ru_x.json 95bc5342fd3909981430c2e13ef98cdbd8f02709 assets/create/models/block/fluid_pipe/ru_y.json e1fc0d1297a83749ac55f51c9cf33ff2ecc9fdc2 assets/create/models/block/fluid_pipe/ru_z.json -d44ff2aed71039a7d0ff913d0d9e8398e1318f39 assets/create/models/block/fluid_pipe/r_x.json -92d4044b51a90da0b2277b0613c7ca0bb80c66fe assets/create/models/block/fluid_pipe/r_y.json -fb9a23de00ef4edb4f7e24fb60de345cd12e513f assets/create/models/block/fluid_pipe/r_z.json -65a41f4b680af197776e03cae6f1815b6d04def2 assets/create/models/block/fluid_pipe/ud_x.json -26398801d89889ffe17b6513b786d27707f6a480 assets/create/models/block/fluid_pipe/ud_y.json -07747cc2b936e1b326bae7ac32a8a5ba77fdffa9 assets/create/models/block/fluid_pipe/ud_z.json 4e3debb2ba60398a0730866f781e0455f4316610 assets/create/models/block/fluid_pipe/u_x.json 0f98b30ba09706b8a5ee09aeef912b39acea0216 assets/create/models/block/fluid_pipe/u_y.json 83bf9b1af633c319c051055170debff4cc3508c0 assets/create/models/block/fluid_pipe/u_z.json +65a41f4b680af197776e03cae6f1815b6d04def2 assets/create/models/block/fluid_pipe/ud_x.json +26398801d89889ffe17b6513b786d27707f6a480 assets/create/models/block/fluid_pipe/ud_y.json +07747cc2b936e1b326bae7ac32a8a5ba77fdffa9 assets/create/models/block/fluid_pipe/ud_z.json 5f70af15ec2569c68a17d31024c7a37cb5c68c7e assets/create/models/block/framed_glass.json f0100e1d44146b256998fbd2af05da80d147e8d9 assets/create/models/block/framed_glass_pane_noside.json 4a032c6ae3f459e3349c2a2218da186170c31e03 assets/create/models/block/framed_glass_pane_noside_alt.json @@ -1269,9 +1269,6 @@ d1813d0f548fcddb361df7cc3b5d97582842b10f assets/create/models/block/light_gray_s debf78f20659bc3c637299a40b649cbe4aa30ebf assets/create/models/block/light_gray_table_cloth.json 4ec5d701dd8b2d8c3dc44d05f527a3d737002cd4 assets/create/models/block/light_gray_toolbox.json adb8dbed70419e0310e7a20f3656bf325b348434 assets/create/models/block/light_gray_valve_handle.json -8f53caad3899a30be5087a0ba155080834418cc0 assets/create/models/block/limestone.json -2b80f9421c2fe902d55d9bd95183ad4bae46c315 assets/create/models/block/limestone_pillar.json -fb18280a2a708f60b00cc7c675804c219784871a assets/create/models/block/limestone_pillar_horizontal.json 2f040681214af58a97e70d3a6e77a0fc2e02c624 assets/create/models/block/lime_nixie_tube.json 952d292d4dc2158e6106c5079cfa1ddb81c7777e assets/create/models/block/lime_postbox_closed.json 4357f5d9102d54c7fbe5325512a2cd42d94d6d42 assets/create/models/block/lime_postbox_open.json @@ -1280,6 +1277,9 @@ fb18280a2a708f60b00cc7c675804c219784871a assets/create/models/block/limestone_pi e4142a22c20d6e5b9a8b9f96c13d4e5f96adc59d assets/create/models/block/lime_table_cloth.json b92822a01e4fbed2463b1bdf7dcc736023988e20 assets/create/models/block/lime_toolbox.json 802b47f34b1053b7af980b08b6511f468e7dd7c1 assets/create/models/block/lime_valve_handle.json +8f53caad3899a30be5087a0ba155080834418cc0 assets/create/models/block/limestone.json +2b80f9421c2fe902d55d9bd95183ad4bae46c315 assets/create/models/block/limestone_pillar.json +fb18280a2a708f60b00cc7c675804c219784871a assets/create/models/block/limestone_pillar_horizontal.json 84b9ac6eafdbd037f3ff558c250a8b8952415af1 assets/create/models/block/linear_chassis.json 29ee936c09c1222c6a144e5bb39577b5a9cd28bf assets/create/models/block/linear_chassis_bottom.json a1a3804ddcb1db0a7b5c0693555f8eb326950dd0 assets/create/models/block/linear_chassis_top.json @@ -1325,18 +1325,18 @@ f9010894858512398bddd5d31b922e12594d2e3c assets/create/models/block/ornate_iron_ 92637fbd6bf54891411b32a494064b9a48e59411 assets/create/models/block/ornate_iron_window_pane_post.json 8416d497e7fc8ca4f9f4c608ccc0651036850256 assets/create/models/block/ornate_iron_window_pane_side.json 1cdaa9d4bd23f7b1eb14672dc9322d9dad966502 assets/create/models/block/ornate_iron_window_pane_side_alt.json -561beafce41b9e9c0b07bc6b7176dd4f6918c116 assets/create/models/block/oxidized_copper_shingles.json 7e0bab8109e322c6db5fe1d5999c06536c21c6eb assets/create/models/block/oxidized_copper_shingle_slab.json 42df32c4e2d1ffb2ee62748becfd1717118b440c assets/create/models/block/oxidized_copper_shingle_slab_top.json b55a733e3e68cfbd08d45bb9ac56deef9f728b60 assets/create/models/block/oxidized_copper_shingle_stairs.json 7b8745213af5aa7938fc04a295be6a087c72daa8 assets/create/models/block/oxidized_copper_shingle_stairs_inner.json d89419d48d6ee2f6747e7c93de8699db22ea3f59 assets/create/models/block/oxidized_copper_shingle_stairs_outer.json -5cf92b628ff1f832966138a58ed87d747681274c assets/create/models/block/oxidized_copper_tiles.json +561beafce41b9e9c0b07bc6b7176dd4f6918c116 assets/create/models/block/oxidized_copper_shingles.json ad6134598869711a12e2f95c9b5f25a0f7b8dd93 assets/create/models/block/oxidized_copper_tile_slab.json c17bac0fd6a20540813c6a1c000a553b7c5ac849 assets/create/models/block/oxidized_copper_tile_slab_top.json d5b30340364f5536e46bc67e777ef4fa20a36e04 assets/create/models/block/oxidized_copper_tile_stairs.json b40b315c23cbd3eb4658518bfac836f6091321a5 assets/create/models/block/oxidized_copper_tile_stairs_inner.json f4eaadab29b4f2e915237340e2d6f4aad4ba21d6 assets/create/models/block/oxidized_copper_tile_stairs_outer.json +5cf92b628ff1f832966138a58ed87d747681274c assets/create/models/block/oxidized_copper_tiles.json f8b51eec36c2eddc08a1b60894d863bb58f55625 assets/create/models/block/peculiar_bell_ceiling.json f70f83cfec770879c478eea3760ea187700f2878 assets/create/models/block/peculiar_bell_double_wall.json b9c9d00b844ca2f217ae21cc502cd4d082fed2d5 assets/create/models/block/peculiar_bell_floor.json @@ -1543,133 +1543,133 @@ ff52eb59dadfe675e416440f3115856a501428a6 assets/create/models/block/scoria.json 4d7d36f974d25a310db2f75800e8c7e0377881c6 assets/create/models/block/secondary_linear_chassis_top.json 5ecb821ac06873015d2d7ebcfb7e1f5fe85cf504 assets/create/models/block/secondary_linear_chassis_top_bottom.json e697898a0ec4c308314a4e0b7235fa0a9229da45 assets/create/models/block/shadow_steel_casing.json -73edb947b52c73e85a83422853d0b8a0fb34e82b assets/create/models/block/small_andesite_bricks.json -3bb5c8413b9e81a1adc339f873f37eb656904e06 assets/create/models/block/small_andesite_bricks_wall_post.json -0e70d94fc6ffdc0fd4a50a5910bc1455b401982f assets/create/models/block/small_andesite_bricks_wall_side.json -597fec784e40c1ff3b622824c32773d6d271f3b7 assets/create/models/block/small_andesite_bricks_wall_side_tall.json 593b962350c8de53156901b308617c6a246afa09 assets/create/models/block/small_andesite_brick_slab.json c83de8118653ccdce92a1b7f3501bf7359e0b310 assets/create/models/block/small_andesite_brick_slab_top.json f019380bcc81d52681e2beaf63e2b11836c45922 assets/create/models/block/small_andesite_brick_stairs.json 4fa72fe0115ad9ec83837852a2b2e2d22dde19ca assets/create/models/block/small_andesite_brick_stairs_inner.json f80f485f62dce86e98815b343c89e96b10623e53 assets/create/models/block/small_andesite_brick_stairs_outer.json -4750724972cbac6d7dac31e0689681eab6c37093 assets/create/models/block/small_asurine_bricks.json -407c7bea509bb0e9bf9f04e947ace584103d012d assets/create/models/block/small_asurine_bricks_wall_post.json -60491dfb4f2a6b78effdf18612b9a1cd7d930d8a assets/create/models/block/small_asurine_bricks_wall_side.json -e5d3172c08b65696a6d72220495463636d8b352c assets/create/models/block/small_asurine_bricks_wall_side_tall.json +73edb947b52c73e85a83422853d0b8a0fb34e82b assets/create/models/block/small_andesite_bricks.json +3bb5c8413b9e81a1adc339f873f37eb656904e06 assets/create/models/block/small_andesite_bricks_wall_post.json +0e70d94fc6ffdc0fd4a50a5910bc1455b401982f assets/create/models/block/small_andesite_bricks_wall_side.json +597fec784e40c1ff3b622824c32773d6d271f3b7 assets/create/models/block/small_andesite_bricks_wall_side_tall.json cdd354726eda82d83dc89871fa587b8c07b02a16 assets/create/models/block/small_asurine_brick_slab.json 7bdb6ed1e74437d083bca7d89c0d1b7c81e80b53 assets/create/models/block/small_asurine_brick_slab_top.json 086b9d4284d343967a582fd0a7d194bafd980e13 assets/create/models/block/small_asurine_brick_stairs.json db69f1580ca405b9a99f0e4ea8d9b9950ed6444e assets/create/models/block/small_asurine_brick_stairs_inner.json dd572cbff713b0f4830aef0bf3ba4adb80ee9908 assets/create/models/block/small_asurine_brick_stairs_outer.json -c2c72734ac526c319cb01e982824680bfb5f1186 assets/create/models/block/small_calcite_bricks.json -f17f2ecd5e5a32f92ec0ad0ba9e861a80432c0f2 assets/create/models/block/small_calcite_bricks_wall_post.json -1ad7654125aff67267567c0007cc03b8a15131b0 assets/create/models/block/small_calcite_bricks_wall_side.json -10c339f64c0e78f4fbb7a95c10bf7f9f399c0c6b assets/create/models/block/small_calcite_bricks_wall_side_tall.json +4750724972cbac6d7dac31e0689681eab6c37093 assets/create/models/block/small_asurine_bricks.json +407c7bea509bb0e9bf9f04e947ace584103d012d assets/create/models/block/small_asurine_bricks_wall_post.json +60491dfb4f2a6b78effdf18612b9a1cd7d930d8a assets/create/models/block/small_asurine_bricks_wall_side.json +e5d3172c08b65696a6d72220495463636d8b352c assets/create/models/block/small_asurine_bricks_wall_side_tall.json d07c57748981a54ffcdadc30ec21f728a3557bea assets/create/models/block/small_calcite_brick_slab.json 9a5e6a93328ad35b256b2512c28e683a74e807a9 assets/create/models/block/small_calcite_brick_slab_top.json c3d39e013dd0142f044f8f0a90de849a0d961e84 assets/create/models/block/small_calcite_brick_stairs.json 4e47a4708dafc0ea476e2d5b6567acfdc2c5c148 assets/create/models/block/small_calcite_brick_stairs_inner.json 6a41c44680a958299a787d8c8c8778d52167cd65 assets/create/models/block/small_calcite_brick_stairs_outer.json -485f6c0e37b24124ff23efa3f0caa2cfe85663dd assets/create/models/block/small_crimsite_bricks.json -57b050751e68c9a881d9598cfe8dfb45f19df08c assets/create/models/block/small_crimsite_bricks_wall_post.json -cb01f90c7ac1f56a6f79e1fecb126c349b6d53b0 assets/create/models/block/small_crimsite_bricks_wall_side.json -80932617b1d4b718071c1f8558398ba881743892 assets/create/models/block/small_crimsite_bricks_wall_side_tall.json +c2c72734ac526c319cb01e982824680bfb5f1186 assets/create/models/block/small_calcite_bricks.json +f17f2ecd5e5a32f92ec0ad0ba9e861a80432c0f2 assets/create/models/block/small_calcite_bricks_wall_post.json +1ad7654125aff67267567c0007cc03b8a15131b0 assets/create/models/block/small_calcite_bricks_wall_side.json +10c339f64c0e78f4fbb7a95c10bf7f9f399c0c6b assets/create/models/block/small_calcite_bricks_wall_side_tall.json 827867ddd9b5f6e2daa916c968531c7183ce7fa2 assets/create/models/block/small_crimsite_brick_slab.json dd19ebdbd1a2de827d467b0abd2d1d3ee5822305 assets/create/models/block/small_crimsite_brick_slab_top.json 58048cb41b740b008a98420ea93b567f38e2910f assets/create/models/block/small_crimsite_brick_stairs.json a943586885ea7d48fc27595d9741f97d852446e7 assets/create/models/block/small_crimsite_brick_stairs_inner.json 8dc173b8a9912341ccb9cd8c9a0d2d893571eb85 assets/create/models/block/small_crimsite_brick_stairs_outer.json -cd855b25c38be2c36dcbf6ab0d963a2c76043171 assets/create/models/block/small_deepslate_bricks.json -88a6c43f64c6d53b34719f41707622635108342b assets/create/models/block/small_deepslate_bricks_wall_post.json -dea1773ca9baf9e1a6a7a4288d348127b858c42d assets/create/models/block/small_deepslate_bricks_wall_side.json -673ab543b38a597fd74285cd25b8004c9e2bd706 assets/create/models/block/small_deepslate_bricks_wall_side_tall.json +485f6c0e37b24124ff23efa3f0caa2cfe85663dd assets/create/models/block/small_crimsite_bricks.json +57b050751e68c9a881d9598cfe8dfb45f19df08c assets/create/models/block/small_crimsite_bricks_wall_post.json +cb01f90c7ac1f56a6f79e1fecb126c349b6d53b0 assets/create/models/block/small_crimsite_bricks_wall_side.json +80932617b1d4b718071c1f8558398ba881743892 assets/create/models/block/small_crimsite_bricks_wall_side_tall.json 67c78a3e9250351d0ea18538640b596f05e957a4 assets/create/models/block/small_deepslate_brick_slab.json bc1af783fbcbe73df05e12c93625035db8089d16 assets/create/models/block/small_deepslate_brick_slab_top.json 91e00675337592d17a04032808ca64c4a159c814 assets/create/models/block/small_deepslate_brick_stairs.json 39e78262242637628628a07dc47908fb1593d3f2 assets/create/models/block/small_deepslate_brick_stairs_inner.json d7a61bc4c84070e0fd53e0957a5282078daff7f1 assets/create/models/block/small_deepslate_brick_stairs_outer.json -73e801fb607d76b42e1862323e9d149910a68298 assets/create/models/block/small_diorite_bricks.json -2bdb593d3ae4d856e96cc877f4927da25841af54 assets/create/models/block/small_diorite_bricks_wall_post.json -dd064be7962a2418784a513725fc7b5835e4ab40 assets/create/models/block/small_diorite_bricks_wall_side.json -3753c64785d74f1997b9f8f856fa873302621f39 assets/create/models/block/small_diorite_bricks_wall_side_tall.json +cd855b25c38be2c36dcbf6ab0d963a2c76043171 assets/create/models/block/small_deepslate_bricks.json +88a6c43f64c6d53b34719f41707622635108342b assets/create/models/block/small_deepslate_bricks_wall_post.json +dea1773ca9baf9e1a6a7a4288d348127b858c42d assets/create/models/block/small_deepslate_bricks_wall_side.json +673ab543b38a597fd74285cd25b8004c9e2bd706 assets/create/models/block/small_deepslate_bricks_wall_side_tall.json 59fc1d9dac0b6867779346413953174fc6b55d3c assets/create/models/block/small_diorite_brick_slab.json cbd6fe711e1203aa746d86d12bb85016b7142749 assets/create/models/block/small_diorite_brick_slab_top.json a6c823fa96ba8a06d101ca96a6898fe8a1faf83e assets/create/models/block/small_diorite_brick_stairs.json 7f128501d989122df9d2ab002a497356831caa1c assets/create/models/block/small_diorite_brick_stairs_inner.json 26222975b0efb2acea6473d0bcc99453aa9ed561 assets/create/models/block/small_diorite_brick_stairs_outer.json -7f55f9c8cae6a79a9ab22a4b593a2c5829390573 assets/create/models/block/small_dripstone_bricks.json -fd0880b2e55435c8dc6945fa71c67ba34d7b1e69 assets/create/models/block/small_dripstone_bricks_wall_post.json -c00e9c0bfb108b70975514694f38d3c4cd63e819 assets/create/models/block/small_dripstone_bricks_wall_side.json -26382c01766e04cfe7ea585cabc1baa1c409e0a0 assets/create/models/block/small_dripstone_bricks_wall_side_tall.json +73e801fb607d76b42e1862323e9d149910a68298 assets/create/models/block/small_diorite_bricks.json +2bdb593d3ae4d856e96cc877f4927da25841af54 assets/create/models/block/small_diorite_bricks_wall_post.json +dd064be7962a2418784a513725fc7b5835e4ab40 assets/create/models/block/small_diorite_bricks_wall_side.json +3753c64785d74f1997b9f8f856fa873302621f39 assets/create/models/block/small_diorite_bricks_wall_side_tall.json 7b18bb56d4509f490a73b2812a8e40333f400369 assets/create/models/block/small_dripstone_brick_slab.json 39b7aa7d1494e5328e8774acb8adec8a346e972f assets/create/models/block/small_dripstone_brick_slab_top.json 3d265aed7a723713d525d0fabf3a70600d9d60e4 assets/create/models/block/small_dripstone_brick_stairs.json 2be41e9c1367af7f0eb99856e35900df96974bd4 assets/create/models/block/small_dripstone_brick_stairs_inner.json 4026a9327d47d55218b00b0b4b92464b6448ad91 assets/create/models/block/small_dripstone_brick_stairs_outer.json -ad4cf29e0e67d0d202d5836486531551909c71bf assets/create/models/block/small_granite_bricks.json -d20963cbb5d2321a069bf42d203855a5584f8607 assets/create/models/block/small_granite_bricks_wall_post.json -b860879b66d2d23349fa95ff644d9eba21eb29bd assets/create/models/block/small_granite_bricks_wall_side.json -11593a2a0e307b3e1d847c84d8c61bc78fef2967 assets/create/models/block/small_granite_bricks_wall_side_tall.json +7f55f9c8cae6a79a9ab22a4b593a2c5829390573 assets/create/models/block/small_dripstone_bricks.json +fd0880b2e55435c8dc6945fa71c67ba34d7b1e69 assets/create/models/block/small_dripstone_bricks_wall_post.json +c00e9c0bfb108b70975514694f38d3c4cd63e819 assets/create/models/block/small_dripstone_bricks_wall_side.json +26382c01766e04cfe7ea585cabc1baa1c409e0a0 assets/create/models/block/small_dripstone_bricks_wall_side_tall.json cb0a72cedb6b2b043eaf8c8869648802d74a2eeb assets/create/models/block/small_granite_brick_slab.json d635840492541787d55cc005c7e207532edcdef3 assets/create/models/block/small_granite_brick_slab_top.json ba9bfedf5854fccaba8a5e60c26efb6e34ede3cd assets/create/models/block/small_granite_brick_stairs.json 9bebe59176e74926e28a139dc557c25283285e89 assets/create/models/block/small_granite_brick_stairs_inner.json 15d71900e76c131285447628e63bf1479ce7025a assets/create/models/block/small_granite_brick_stairs_outer.json -6224f2763224d3e746dafdaaf14fae68e2469b93 assets/create/models/block/small_limestone_bricks.json -ca038e240e4157897a6273692db2c952ab5b17d7 assets/create/models/block/small_limestone_bricks_wall_post.json -7920f8cfda77b22d4d29638faa6ae07d89e51ab3 assets/create/models/block/small_limestone_bricks_wall_side.json -6e1fa27744f4592111945e5cafee6d7d67b5299b assets/create/models/block/small_limestone_bricks_wall_side_tall.json +ad4cf29e0e67d0d202d5836486531551909c71bf assets/create/models/block/small_granite_bricks.json +d20963cbb5d2321a069bf42d203855a5584f8607 assets/create/models/block/small_granite_bricks_wall_post.json +b860879b66d2d23349fa95ff644d9eba21eb29bd assets/create/models/block/small_granite_bricks_wall_side.json +11593a2a0e307b3e1d847c84d8c61bc78fef2967 assets/create/models/block/small_granite_bricks_wall_side_tall.json 0e0f551bac87421e6b693aa9ca98fd5da2ee168b assets/create/models/block/small_limestone_brick_slab.json 6669c1e87ed79097f96e7e46eecf3ab6e7c9778c assets/create/models/block/small_limestone_brick_slab_top.json 5aff0145d2fc89549ac541db325dda25b8941583 assets/create/models/block/small_limestone_brick_stairs.json 250aa2c237a9532b19621fa604027433183961c3 assets/create/models/block/small_limestone_brick_stairs_inner.json 92da57d330e9905d017705dd931af1d1d6c1a00d assets/create/models/block/small_limestone_brick_stairs_outer.json -242e4f39f6df26917f21899f0c7d0415a166d4b9 assets/create/models/block/small_ochrum_bricks.json -06cb9faca0062947c08b2a7309a958aac5ab24ac assets/create/models/block/small_ochrum_bricks_wall_post.json -8d9d53206e222839333026c779b66b9fd8cf2cf9 assets/create/models/block/small_ochrum_bricks_wall_side.json -f412fbaa509f7b2d47a27d4bcb13590bfcae74ca assets/create/models/block/small_ochrum_bricks_wall_side_tall.json +6224f2763224d3e746dafdaaf14fae68e2469b93 assets/create/models/block/small_limestone_bricks.json +ca038e240e4157897a6273692db2c952ab5b17d7 assets/create/models/block/small_limestone_bricks_wall_post.json +7920f8cfda77b22d4d29638faa6ae07d89e51ab3 assets/create/models/block/small_limestone_bricks_wall_side.json +6e1fa27744f4592111945e5cafee6d7d67b5299b assets/create/models/block/small_limestone_bricks_wall_side_tall.json 517e3605a9e86a07c673e18d94c2c37109a2aef5 assets/create/models/block/small_ochrum_brick_slab.json 855ad9f6fe03ceb2cc33d9df3536cb4394acfa9b assets/create/models/block/small_ochrum_brick_slab_top.json c5fc35d6b0fe96c11537bc10d34a63ef80f3270c assets/create/models/block/small_ochrum_brick_stairs.json 9a2631d9f6821d2c01bc8b2588a69702d3b083cc assets/create/models/block/small_ochrum_brick_stairs_inner.json 1f0ccdef29dae18535ea304e954e06c91bb0620b assets/create/models/block/small_ochrum_brick_stairs_outer.json +242e4f39f6df26917f21899f0c7d0415a166d4b9 assets/create/models/block/small_ochrum_bricks.json +06cb9faca0062947c08b2a7309a958aac5ab24ac assets/create/models/block/small_ochrum_bricks_wall_post.json +8d9d53206e222839333026c779b66b9fd8cf2cf9 assets/create/models/block/small_ochrum_bricks_wall_side.json +f412fbaa509f7b2d47a27d4bcb13590bfcae74ca assets/create/models/block/small_ochrum_bricks_wall_side_tall.json be96f070be1f838c6fb442c164b5f9b4e5cfcee5 assets/create/models/block/small_rose_quartz_tiles.json -41e56d8e334b81a0d5270bdbe87617981e1f98b4 assets/create/models/block/small_scorchia_bricks.json -56aa81e05019533ce0e0f1ee3ef7bf20fcc400b4 assets/create/models/block/small_scorchia_bricks_wall_post.json -1e1fa90c8b144813770c4d53a3b734ae450895d6 assets/create/models/block/small_scorchia_bricks_wall_side.json -6a46cf73c03a2abea25a81dbb28f4150b355900c assets/create/models/block/small_scorchia_bricks_wall_side_tall.json 6aa3825ace2e73bec454aaa8597e3a892ee29eb7 assets/create/models/block/small_scorchia_brick_slab.json f0378625001171c449a403e372e59623f0fc6569 assets/create/models/block/small_scorchia_brick_slab_top.json 49fa4a3940f84902319df257d39812eb71c8a9e2 assets/create/models/block/small_scorchia_brick_stairs.json 4dee6e6dbe6a98a8eaa04f6812f322343f62fca1 assets/create/models/block/small_scorchia_brick_stairs_inner.json 8a19e7e5c03c155c9ef9332486ae0b069dea0502 assets/create/models/block/small_scorchia_brick_stairs_outer.json -6b435123d852579ba8467c4915cd5d0adaadeca0 assets/create/models/block/small_scoria_bricks.json -86b243074845ca66916ce96ef3774862cf9a39d4 assets/create/models/block/small_scoria_bricks_wall_post.json -57ccb3efbdc4a69cad60c8b90321338ba2e68321 assets/create/models/block/small_scoria_bricks_wall_side.json -d4c5398e10b25d2dc3cb3754a449fc2b60e4074f assets/create/models/block/small_scoria_bricks_wall_side_tall.json +41e56d8e334b81a0d5270bdbe87617981e1f98b4 assets/create/models/block/small_scorchia_bricks.json +56aa81e05019533ce0e0f1ee3ef7bf20fcc400b4 assets/create/models/block/small_scorchia_bricks_wall_post.json +1e1fa90c8b144813770c4d53a3b734ae450895d6 assets/create/models/block/small_scorchia_bricks_wall_side.json +6a46cf73c03a2abea25a81dbb28f4150b355900c assets/create/models/block/small_scorchia_bricks_wall_side_tall.json 918351c1270c26932c0c4783543779a25ca7e986 assets/create/models/block/small_scoria_brick_slab.json 4138e756b4b36f227e178acbcc233edb082ae603 assets/create/models/block/small_scoria_brick_slab_top.json b8e70cd7d9acdcf91be9783cd91d70275a006ea2 assets/create/models/block/small_scoria_brick_stairs.json 625bfbd58440ea4e270d57cc748f2b5f6cece63b assets/create/models/block/small_scoria_brick_stairs_inner.json 602a46fb2736acb8c50b0d04222e6c33e52dee87 assets/create/models/block/small_scoria_brick_stairs_outer.json -a8e8c633dfb6d9f14425b1fd28e88ecf08a88cc6 assets/create/models/block/small_tuff_bricks.json -1c3a22bed504cd7a7e507e83ee21399f8a3fb299 assets/create/models/block/small_tuff_bricks_wall_post.json -1aeb8cac7d0178a18ac1cf98c9a45ca8e67514b0 assets/create/models/block/small_tuff_bricks_wall_side.json -4c6b5c7c60ec4cad314064b171413a3e866e5f99 assets/create/models/block/small_tuff_bricks_wall_side_tall.json +6b435123d852579ba8467c4915cd5d0adaadeca0 assets/create/models/block/small_scoria_bricks.json +86b243074845ca66916ce96ef3774862cf9a39d4 assets/create/models/block/small_scoria_bricks_wall_post.json +57ccb3efbdc4a69cad60c8b90321338ba2e68321 assets/create/models/block/small_scoria_bricks_wall_side.json +d4c5398e10b25d2dc3cb3754a449fc2b60e4074f assets/create/models/block/small_scoria_bricks_wall_side_tall.json 6b2c4d8c8609de0d3d6ce1e30b1dd26ba59cb86d assets/create/models/block/small_tuff_brick_slab.json 1ba07367fcba6a3914f1703115304a7c19979542 assets/create/models/block/small_tuff_brick_slab_top.json 1a5ab239d0f2f041ee04005ceb60111e6848f5de assets/create/models/block/small_tuff_brick_stairs.json be3ee2c36f85a534a71d42a7d63a7816945b3c30 assets/create/models/block/small_tuff_brick_stairs_inner.json aa84e448041d5f74c75565f5e409b1e9b7e5155d assets/create/models/block/small_tuff_brick_stairs_outer.json -e9c75f1b4b663dce09b0a2f8282e574839c19d06 assets/create/models/block/small_veridium_bricks.json -725f6d3dbcfb469cede6fb27a98c1f398f3f3c8c assets/create/models/block/small_veridium_bricks_wall_post.json -b33ee496d43e315a5bed5eaabfd553e361fec1a9 assets/create/models/block/small_veridium_bricks_wall_side.json -80e950f93def51d82a63848b1fb6ac11600ab1bf assets/create/models/block/small_veridium_bricks_wall_side_tall.json +a8e8c633dfb6d9f14425b1fd28e88ecf08a88cc6 assets/create/models/block/small_tuff_bricks.json +1c3a22bed504cd7a7e507e83ee21399f8a3fb299 assets/create/models/block/small_tuff_bricks_wall_post.json +1aeb8cac7d0178a18ac1cf98c9a45ca8e67514b0 assets/create/models/block/small_tuff_bricks_wall_side.json +4c6b5c7c60ec4cad314064b171413a3e866e5f99 assets/create/models/block/small_tuff_bricks_wall_side_tall.json 30b150fe3cf9bdb6ee32cd6b0f51179b44be57d3 assets/create/models/block/small_veridium_brick_slab.json 2158dd9e71f6f60e5132105c68a41ad6e3927438 assets/create/models/block/small_veridium_brick_slab_top.json bbbfc8e3696945ed1f6c3afe73ae0745ff8deda1 assets/create/models/block/small_veridium_brick_stairs.json fc3a996b0ca01c2c09ad84b881c46e92918d084f assets/create/models/block/small_veridium_brick_stairs_inner.json e27a77984e8e28e6032f26bb010efcadfaeb5407 assets/create/models/block/small_veridium_brick_stairs_outer.json +e9c75f1b4b663dce09b0a2f8282e574839c19d06 assets/create/models/block/small_veridium_bricks.json +725f6d3dbcfb469cede6fb27a98c1f398f3f3c8c assets/create/models/block/small_veridium_bricks_wall_post.json +b33ee496d43e315a5bed5eaabfd553e361fec1a9 assets/create/models/block/small_veridium_bricks_wall_side.json +80e950f93def51d82a63848b1fb6ac11600ab1bf assets/create/models/block/small_veridium_bricks_wall_side_tall.json d7c1c2679c8ba543ae7be3b9cf3f4eea3c1a2f68 assets/create/models/block/spruce_window.json f4a4fbb9eea6fb1d0633e349eae6acdaf329e8d5 assets/create/models/block/spruce_window_pane_noside.json 02a25202a42debcd2b4aaa4113e3de4f8f6ee47c assets/create/models/block/spruce_window_pane_noside_alt.json @@ -1736,66 +1736,66 @@ e84875a4eb11e2161a93ec7569aa2ac1c2f60cef assets/create/models/block/warped_windo 378c865ff8213ff56f1f7a4b2d9cf26c71f036e8 assets/create/models/block/warped_window_pane_post.json f320de08cb113a9ad17acd2ebb8dfc57759e4f7d assets/create/models/block/warped_window_pane_side.json 2fc182d9697b5cddd93b01d1236931af27eee8fe assets/create/models/block/warped_window_pane_side_alt.json -32fdb85b5b62d5a0fb41732874c854788cdd2ba1 assets/create/models/block/waxed_copper_shingles.json fb7fb6deebd502946ab57f1b8a9f4a6b5dd48da3 assets/create/models/block/waxed_copper_shingle_slab.json 660f61112b8e46dec5050cb0ed4ee936965a7c58 assets/create/models/block/waxed_copper_shingle_slab_top.json 5d74be967bbe9feba4b630751f13af817a733d1d assets/create/models/block/waxed_copper_shingle_stairs.json 35cb89f29ce3f8d8af13602c08ecd7afbb7cf56a assets/create/models/block/waxed_copper_shingle_stairs_inner.json fcb9295f4f388e6d439ec9a3906ca326b6d69077 assets/create/models/block/waxed_copper_shingle_stairs_outer.json -32f06f39d0b34e4431795aa6e64f87e58dc1597b assets/create/models/block/waxed_copper_tiles.json +32fdb85b5b62d5a0fb41732874c854788cdd2ba1 assets/create/models/block/waxed_copper_shingles.json 298c6100de02ed9f813397d8ba38c46f35035c69 assets/create/models/block/waxed_copper_tile_slab.json d4422c2d96fb329087d1be70d8b983a8cf6c7f01 assets/create/models/block/waxed_copper_tile_slab_top.json fca72048f916d3a3e567b385c948cc1b59711ef4 assets/create/models/block/waxed_copper_tile_stairs.json 997479b62ed3d81ab633279ecc2fabd9588a3bf3 assets/create/models/block/waxed_copper_tile_stairs_inner.json d5c5bbfb9aaa282e11ad6e6309b1880b172ee653 assets/create/models/block/waxed_copper_tile_stairs_outer.json -19a773f91c58c49301f35965bac02d0c05fb2764 assets/create/models/block/waxed_exposed_copper_shingles.json +32f06f39d0b34e4431795aa6e64f87e58dc1597b assets/create/models/block/waxed_copper_tiles.json a3420b91fdebec40e508a5eebb145c0201bd80c8 assets/create/models/block/waxed_exposed_copper_shingle_slab.json 4178ea5e50ee17b3c15f4a59efd019c4a19bb892 assets/create/models/block/waxed_exposed_copper_shingle_slab_top.json dd2d747774abc86e428a883e299db66cded78e11 assets/create/models/block/waxed_exposed_copper_shingle_stairs.json b6845da62d96a33cee624bb70360e256b26eda83 assets/create/models/block/waxed_exposed_copper_shingle_stairs_inner.json 3d8b758e50e75c5adc26ab6f39f9d73f00866673 assets/create/models/block/waxed_exposed_copper_shingle_stairs_outer.json -9cb20c9d41629d8b9426cb65829365d10966338f assets/create/models/block/waxed_exposed_copper_tiles.json +19a773f91c58c49301f35965bac02d0c05fb2764 assets/create/models/block/waxed_exposed_copper_shingles.json cd21d9d2935b6d0103502e2731c11ea27ff64ecf assets/create/models/block/waxed_exposed_copper_tile_slab.json 0ec039ba59fb0028183433e52131ff355ace5bff assets/create/models/block/waxed_exposed_copper_tile_slab_top.json c51dbd34996ac4513234800e427ac308067d5e1d assets/create/models/block/waxed_exposed_copper_tile_stairs.json 68772d4352dc7ade995dfa57ba41a38ef819e855 assets/create/models/block/waxed_exposed_copper_tile_stairs_inner.json d932671822ba93b71a9c8b50e7207803a1c4dbab assets/create/models/block/waxed_exposed_copper_tile_stairs_outer.json -561beafce41b9e9c0b07bc6b7176dd4f6918c116 assets/create/models/block/waxed_oxidized_copper_shingles.json +9cb20c9d41629d8b9426cb65829365d10966338f assets/create/models/block/waxed_exposed_copper_tiles.json 7e0bab8109e322c6db5fe1d5999c06536c21c6eb assets/create/models/block/waxed_oxidized_copper_shingle_slab.json 42df32c4e2d1ffb2ee62748becfd1717118b440c assets/create/models/block/waxed_oxidized_copper_shingle_slab_top.json b55a733e3e68cfbd08d45bb9ac56deef9f728b60 assets/create/models/block/waxed_oxidized_copper_shingle_stairs.json 7b8745213af5aa7938fc04a295be6a087c72daa8 assets/create/models/block/waxed_oxidized_copper_shingle_stairs_inner.json d89419d48d6ee2f6747e7c93de8699db22ea3f59 assets/create/models/block/waxed_oxidized_copper_shingle_stairs_outer.json -5cf92b628ff1f832966138a58ed87d747681274c assets/create/models/block/waxed_oxidized_copper_tiles.json +561beafce41b9e9c0b07bc6b7176dd4f6918c116 assets/create/models/block/waxed_oxidized_copper_shingles.json ad6134598869711a12e2f95c9b5f25a0f7b8dd93 assets/create/models/block/waxed_oxidized_copper_tile_slab.json c17bac0fd6a20540813c6a1c000a553b7c5ac849 assets/create/models/block/waxed_oxidized_copper_tile_slab_top.json d5b30340364f5536e46bc67e777ef4fa20a36e04 assets/create/models/block/waxed_oxidized_copper_tile_stairs.json b40b315c23cbd3eb4658518bfac836f6091321a5 assets/create/models/block/waxed_oxidized_copper_tile_stairs_inner.json f4eaadab29b4f2e915237340e2d6f4aad4ba21d6 assets/create/models/block/waxed_oxidized_copper_tile_stairs_outer.json -9c73020e80c31cd710c218f9699ba9a795758ad0 assets/create/models/block/waxed_weathered_copper_shingles.json +5cf92b628ff1f832966138a58ed87d747681274c assets/create/models/block/waxed_oxidized_copper_tiles.json 897cfc177b073ca1bcb635c74108567f8748b5c4 assets/create/models/block/waxed_weathered_copper_shingle_slab.json efa57ba131c27e0064c0d958e69b10530a26ac41 assets/create/models/block/waxed_weathered_copper_shingle_slab_top.json 4ef11a7e3de630ad46b9179e8a9a34d55202f6c5 assets/create/models/block/waxed_weathered_copper_shingle_stairs.json f32a18c76cfaca2153f6321880a8da1347be37ce assets/create/models/block/waxed_weathered_copper_shingle_stairs_inner.json 9637f78e51ca7ed812e4c64c52e08f6fa0adbfc3 assets/create/models/block/waxed_weathered_copper_shingle_stairs_outer.json -9782a25341dd2ffb146430edbe6916932250c326 assets/create/models/block/waxed_weathered_copper_tiles.json +9c73020e80c31cd710c218f9699ba9a795758ad0 assets/create/models/block/waxed_weathered_copper_shingles.json 0c9669588972d4c2152bd2b043b8386b76a6e1c4 assets/create/models/block/waxed_weathered_copper_tile_slab.json 2d01a583cc948e9e0cb814cad968ed16a07dd46c assets/create/models/block/waxed_weathered_copper_tile_slab_top.json e26dd64495ff8801593e9c22203cbf364075badd assets/create/models/block/waxed_weathered_copper_tile_stairs.json b658c1022587bd670b5acee267607719c1544332 assets/create/models/block/waxed_weathered_copper_tile_stairs_inner.json e7ae89577be9d26a071bf96cbd7ed80293902b63 assets/create/models/block/waxed_weathered_copper_tile_stairs_outer.json -9c73020e80c31cd710c218f9699ba9a795758ad0 assets/create/models/block/weathered_copper_shingles.json +9782a25341dd2ffb146430edbe6916932250c326 assets/create/models/block/waxed_weathered_copper_tiles.json 897cfc177b073ca1bcb635c74108567f8748b5c4 assets/create/models/block/weathered_copper_shingle_slab.json efa57ba131c27e0064c0d958e69b10530a26ac41 assets/create/models/block/weathered_copper_shingle_slab_top.json 4ef11a7e3de630ad46b9179e8a9a34d55202f6c5 assets/create/models/block/weathered_copper_shingle_stairs.json f32a18c76cfaca2153f6321880a8da1347be37ce assets/create/models/block/weathered_copper_shingle_stairs_inner.json 9637f78e51ca7ed812e4c64c52e08f6fa0adbfc3 assets/create/models/block/weathered_copper_shingle_stairs_outer.json -9782a25341dd2ffb146430edbe6916932250c326 assets/create/models/block/weathered_copper_tiles.json +9c73020e80c31cd710c218f9699ba9a795758ad0 assets/create/models/block/weathered_copper_shingles.json 0c9669588972d4c2152bd2b043b8386b76a6e1c4 assets/create/models/block/weathered_copper_tile_slab.json 2d01a583cc948e9e0cb814cad968ed16a07dd46c assets/create/models/block/weathered_copper_tile_slab_top.json e26dd64495ff8801593e9c22203cbf364075badd assets/create/models/block/weathered_copper_tile_stairs.json b658c1022587bd670b5acee267607719c1544332 assets/create/models/block/weathered_copper_tile_stairs_inner.json e7ae89577be9d26a071bf96cbd7ed80293902b63 assets/create/models/block/weathered_copper_tile_stairs_outer.json +9782a25341dd2ffb146430edbe6916932250c326 assets/create/models/block/weathered_copper_tiles.json 045b812ddb1ca8dd6cd9b49852ddbd37f86cd2a6 assets/create/models/block/weathered_iron_block.json a569ddd725898a86f8745e46723edeff7fe7f2e9 assets/create/models/block/weathered_iron_window_1.json 133928d853037efb81022b69377669f0b16239bc assets/create/models/block/weathered_iron_window_2.json @@ -1971,13 +1971,13 @@ aaac7663d062731433c920d94a24b9b3a521dd8c assets/create/models/item/copper_bars.j ccdf08652511e5737a8489d86ea9422ade4f4ca5 assets/create/models/item/copper_nugget.json 86a770e9b2af1f19bf633f5cfeecd84848f73fbd assets/create/models/item/copper_scaffolding.json a4fd2f4f00e03b2ac5d863e93827d39a984cc2ff assets/create/models/item/copper_sheet.json -13b18ba2938e283d507fbca70518cf52198cdc71 assets/create/models/item/copper_shingles.json 79d9f8667965072f12e51e6601b5c36f8acc125f assets/create/models/item/copper_shingle_slab.json 9fe6f0bdea4595b403ed2d2cbc2023a9abeb79f0 assets/create/models/item/copper_shingle_stairs.json +13b18ba2938e283d507fbca70518cf52198cdc71 assets/create/models/item/copper_shingles.json 9a33eeb0f7c682ee2f8c0abbfa174f8828acc2b5 assets/create/models/item/copper_table_cloth.json -19642e4ea5deecaf57059827c4c13a19d2e73822 assets/create/models/item/copper_tiles.json a7147444fc28a4cce21b6cf38e9528537e27c352 assets/create/models/item/copper_tile_slab.json 7330324d6c64f0340d676ecef83a930515d9130e assets/create/models/item/copper_tile_stairs.json +19642e4ea5deecaf57059827c4c13a19d2e73822 assets/create/models/item/copper_tiles.json 08c35e85afe4eb2b106133c5d9c7d7c64ca9a915 assets/create/models/item/copper_valve_handle.json 5cec229a3117ea5987aa42288c070427ac48a5dc assets/create/models/item/copycat_panel.json 1b6707005830ca066a7e997c73391ca88c70bdb0 assets/create/models/item/copycat_step.json @@ -2007,114 +2007,114 @@ b6acd86be9e6cac8b9ed2bc6297d27941ca05f46 assets/create/models/item/crushed_raw_z b67e95801010eab58de02f2b0160bff3f008bd18 assets/create/models/item/crushing_wheel.json af189b0c04482064520d84546d81af8154824292 assets/create/models/item/cuckoo_clock.json 314fb287c7b16a6478fbefde0da80de8828b684e assets/create/models/item/cut_andesite.json -e2840073eac2e6419cd312b3d0177d4c64a5346c assets/create/models/item/cut_andesite_bricks.json 680fe77d50f7c3253ec4997f74761f962b784e15 assets/create/models/item/cut_andesite_brick_slab.json 3c1d56f9686bb2b97c168b0509ddfd06e80be9a0 assets/create/models/item/cut_andesite_brick_stairs.json 4222b965f8a18f78b92838e4642a28fa3e0ad648 assets/create/models/item/cut_andesite_brick_wall.json +e2840073eac2e6419cd312b3d0177d4c64a5346c assets/create/models/item/cut_andesite_bricks.json c100e02ef9b05f4f6df3ddbbfe91db1032d4854b assets/create/models/item/cut_andesite_slab.json f435a67b3d89d12b6e8cb5071a67e35f0918dc79 assets/create/models/item/cut_andesite_stairs.json df9084d532a085220280bc7bee579e1079fbf786 assets/create/models/item/cut_andesite_wall.json 025eedca45b222b91d93b9a3a89fac5ad328b152 assets/create/models/item/cut_asurine.json -1ceb483f428448f00a08541fbcf4f4787aef3f1e assets/create/models/item/cut_asurine_bricks.json 022c56e7aafa7ca4cdd1a88426eb43f9e02c3cc2 assets/create/models/item/cut_asurine_brick_slab.json 3131e09a221c2f0a17cfc7277603f2e3c8164bc7 assets/create/models/item/cut_asurine_brick_stairs.json dc1f5f03acc1165606c48df97953164f6bd7f092 assets/create/models/item/cut_asurine_brick_wall.json +1ceb483f428448f00a08541fbcf4f4787aef3f1e assets/create/models/item/cut_asurine_bricks.json e81d7df1f1b8281c38400713b09cbac59c4d53cc assets/create/models/item/cut_asurine_slab.json cf534603fe71423e0ab80d431ab12394d0a6bb21 assets/create/models/item/cut_asurine_stairs.json 7ca803f5a7798ea034db6385a5f36a48e235c247 assets/create/models/item/cut_asurine_wall.json 707fb799ca44280cad0b817f29a7c75dd0f0ce5e assets/create/models/item/cut_calcite.json -5678b9f76823efac2c6624acc7b2b911402112f4 assets/create/models/item/cut_calcite_bricks.json f794423b242228c43345dc1f40653133fb7f3db6 assets/create/models/item/cut_calcite_brick_slab.json 8e9b46e52758ec7f21c3b84c212e2f6565bf71d9 assets/create/models/item/cut_calcite_brick_stairs.json 1447d21b7fc331528bfd15e5b9d694eb1a31cfb3 assets/create/models/item/cut_calcite_brick_wall.json +5678b9f76823efac2c6624acc7b2b911402112f4 assets/create/models/item/cut_calcite_bricks.json c78c99c78a19097d890414b21270014b52bafd8d assets/create/models/item/cut_calcite_slab.json e6a9144a4bb9e5af3f57d0acdb26d66dc4547217 assets/create/models/item/cut_calcite_stairs.json daf2a2513f6636d140c23b90ba87aad35476c498 assets/create/models/item/cut_calcite_wall.json 29f2bc72aa50cdf34d1d5bfd01a4512d5974dc65 assets/create/models/item/cut_crimsite.json -20bc810ca5b2a35a423e57f287e2f42ad9940b89 assets/create/models/item/cut_crimsite_bricks.json 7c37d3de9674e70595498d1c46c5693d9f39a502 assets/create/models/item/cut_crimsite_brick_slab.json b974c0f2f0e5119d9bac6a36946d4dfdd65b4b5f assets/create/models/item/cut_crimsite_brick_stairs.json c1289ddff572149b2171859689228615802dc825 assets/create/models/item/cut_crimsite_brick_wall.json +20bc810ca5b2a35a423e57f287e2f42ad9940b89 assets/create/models/item/cut_crimsite_bricks.json 8855eb44a68277668c77858715652d6851fa507f assets/create/models/item/cut_crimsite_slab.json 57101d3c2d570bc2c389c1e05e1354d79de70a0a assets/create/models/item/cut_crimsite_stairs.json a10cd65d675a05b9dfbdac67a2d9ca3b4381396a assets/create/models/item/cut_crimsite_wall.json a4ad900cf65136835c259c1e349781538d537a9c assets/create/models/item/cut_deepslate.json -81b10b5d159db4000f4f6569b83fc7e8f702f015 assets/create/models/item/cut_deepslate_bricks.json a63bbe474ca7d8ceafb6bfcb21a88841980fe8e6 assets/create/models/item/cut_deepslate_brick_slab.json 7c1ad49844eafbd87f8c69a077a8c18ccdd4a919 assets/create/models/item/cut_deepslate_brick_stairs.json 6a4ee2e810731e0702c1493237343a567cc736d6 assets/create/models/item/cut_deepslate_brick_wall.json +81b10b5d159db4000f4f6569b83fc7e8f702f015 assets/create/models/item/cut_deepslate_bricks.json ff0d08d1b59de36b016f7952d2bd72d8e1eb1293 assets/create/models/item/cut_deepslate_slab.json 627c806a6eba8b730682821deb31627d75683e88 assets/create/models/item/cut_deepslate_stairs.json 9bdb85a688b09eb34eb8024a6808406118f78133 assets/create/models/item/cut_deepslate_wall.json c33c48d71d98f4b8a84c7f0a4ee88918fed3e798 assets/create/models/item/cut_diorite.json -e8a697df63b0b5fa74dbc70e76b55718a2cc388f assets/create/models/item/cut_diorite_bricks.json 63bc297b782c40c513873b7f8fd8284abce01753 assets/create/models/item/cut_diorite_brick_slab.json f604d088c8c7c6d847795459231d0df8c73d95fb assets/create/models/item/cut_diorite_brick_stairs.json b06be3da6017aa7fbc38b8aecda0d30dae313c13 assets/create/models/item/cut_diorite_brick_wall.json +e8a697df63b0b5fa74dbc70e76b55718a2cc388f assets/create/models/item/cut_diorite_bricks.json 4650f375365caeb237947f6e933d174ebbfbc1e2 assets/create/models/item/cut_diorite_slab.json 933d14f51272b39fc13e94d58f3100469d7cbe06 assets/create/models/item/cut_diorite_stairs.json 0cc44bb9ad0ed3ff11bc6113d0a9e31e99b169b8 assets/create/models/item/cut_diorite_wall.json e2123180fd5312d1e67b3a030fcbc4b6f11aa8bf assets/create/models/item/cut_dripstone.json -4b5d7bbee5741b112e2cb354c5fe49c088fc9b2f assets/create/models/item/cut_dripstone_bricks.json a815b2a927853d6d82d8b69f862be3091c5c8caa assets/create/models/item/cut_dripstone_brick_slab.json b8cb1b04eb869a06ded04c4c3acac6e5a315ee78 assets/create/models/item/cut_dripstone_brick_stairs.json 87fafd603eb4ba41981cd9c9371ac4618909f94d assets/create/models/item/cut_dripstone_brick_wall.json +4b5d7bbee5741b112e2cb354c5fe49c088fc9b2f assets/create/models/item/cut_dripstone_bricks.json 756c801f6bba006fbfd3486e95ba870909ab2902 assets/create/models/item/cut_dripstone_slab.json c59d314e1b5cce1c3745ce164c2a094e17f7a003 assets/create/models/item/cut_dripstone_stairs.json 125b24d28a9957740855467440ad8508d21c24d7 assets/create/models/item/cut_dripstone_wall.json 2fbce0b481f7cf2cf4f0fd03c86ef743b7c30879 assets/create/models/item/cut_granite.json -d8860602cc52fac5a09354c56e78fdfd7d9cb6a9 assets/create/models/item/cut_granite_bricks.json 3584117ed8a69c3842fde1d6accfaaa2c72e44f4 assets/create/models/item/cut_granite_brick_slab.json c68d1c09b9091bc501279115be16f83508b88fed assets/create/models/item/cut_granite_brick_stairs.json 5a37b24319a8708e444902eae3596b68daaffd15 assets/create/models/item/cut_granite_brick_wall.json +d8860602cc52fac5a09354c56e78fdfd7d9cb6a9 assets/create/models/item/cut_granite_bricks.json c2f6603e8cbfc0cdf5e5ef10c6a4baef9c917b6d assets/create/models/item/cut_granite_slab.json 66f8e6d556446441e157427437e9563075e2d6ce assets/create/models/item/cut_granite_stairs.json fe06c8aeab9e4c8a145375af46cbdaed701baad4 assets/create/models/item/cut_granite_wall.json b5c3df9c28a14683a363769cad5d154af56b8da4 assets/create/models/item/cut_limestone.json -7d026353711a464400e69c7e86c9b9c6aa70bf6d assets/create/models/item/cut_limestone_bricks.json 2822ebe1d4211f240e31866759e25add5f0fb56d assets/create/models/item/cut_limestone_brick_slab.json 694dfb73585167011d8123d64f5896697594f4ce assets/create/models/item/cut_limestone_brick_stairs.json db8851d6a1b7604ca1ba7615e1f162f6f5220801 assets/create/models/item/cut_limestone_brick_wall.json +7d026353711a464400e69c7e86c9b9c6aa70bf6d assets/create/models/item/cut_limestone_bricks.json 75584aa5e06168d8866b022fcd72377351b774d9 assets/create/models/item/cut_limestone_slab.json 1df9a186a146e597b48da4c4461f1a98ecf3646a assets/create/models/item/cut_limestone_stairs.json b70ac5462ef4d0363332656aa7cb82919f679893 assets/create/models/item/cut_limestone_wall.json 92bc693db4e0ba6164cd35d4f5fa0982f3b8f796 assets/create/models/item/cut_ochrum.json -3e8e00c602b1fbce888e6fe22d9525f1c025129d assets/create/models/item/cut_ochrum_bricks.json 1edc47c279fadde74322d3fa89ef776bdd6fb354 assets/create/models/item/cut_ochrum_brick_slab.json 4678e2a97c73139b458cea657a55f74659bc36d5 assets/create/models/item/cut_ochrum_brick_stairs.json 85044ec7033cd4c6aa913c4c4bb6c0e3a4386023 assets/create/models/item/cut_ochrum_brick_wall.json +3e8e00c602b1fbce888e6fe22d9525f1c025129d assets/create/models/item/cut_ochrum_bricks.json e0e494fb7fa1767241507347318560335339a2a8 assets/create/models/item/cut_ochrum_slab.json de7c5917bcb14f398d39e3932bfe5e1967ed7a24 assets/create/models/item/cut_ochrum_stairs.json 5a8f8c84e95ee0ab97106a801a456282f5ac207c assets/create/models/item/cut_ochrum_wall.json 1631a807135cf993d9a81068c65e78face2f24e0 assets/create/models/item/cut_scorchia.json -5ecb9692e478e29d64aeb5867e8677671560755d assets/create/models/item/cut_scorchia_bricks.json ac3a29573ce099ac57f59d0a2f1cdc0a453e0621 assets/create/models/item/cut_scorchia_brick_slab.json d3a8a8e0e85aaaadccb18cdce33da54ae0e8a8d7 assets/create/models/item/cut_scorchia_brick_stairs.json 83be13f6cbd9a58e10869e4152066cf3b265f347 assets/create/models/item/cut_scorchia_brick_wall.json +5ecb9692e478e29d64aeb5867e8677671560755d assets/create/models/item/cut_scorchia_bricks.json 0fee2e7f8e80bbd33e4d928c8374e6dae65f0b1f assets/create/models/item/cut_scorchia_slab.json 88a6b3709bab76390ace6f641eac18d43c9d099f assets/create/models/item/cut_scorchia_stairs.json d733d43252bf27b6fb1d7e016dc77556c3d1eb71 assets/create/models/item/cut_scorchia_wall.json ce75fb80c38c94bf6bf631eeb756909decaaaab0 assets/create/models/item/cut_scoria.json -81aa0bd4ec878754043a107466dcd87d49b3697c assets/create/models/item/cut_scoria_bricks.json d78a5126aefdd4cd182f9ec0ddda64df00d0f01c assets/create/models/item/cut_scoria_brick_slab.json 661d49b996f9c97a333e7e39dd13a0476db6b142 assets/create/models/item/cut_scoria_brick_stairs.json 3be69c075b479ac53c6201d7d7224d399f8009b6 assets/create/models/item/cut_scoria_brick_wall.json +81aa0bd4ec878754043a107466dcd87d49b3697c assets/create/models/item/cut_scoria_bricks.json 824bedfbeec53ec8f539fe73c0a3c3d927a21aa4 assets/create/models/item/cut_scoria_slab.json 15560f1251f18d53fe1b71adc6be5060c4d8fb94 assets/create/models/item/cut_scoria_stairs.json e35ebcc4f7f7b94623af85b181d916e48fbbb5ed assets/create/models/item/cut_scoria_wall.json 71284d3d6dba230dbecd01eb015e0e65877b820d assets/create/models/item/cut_tuff.json -4de100799e290db3fd46923781a83e6a12654266 assets/create/models/item/cut_tuff_bricks.json 4c7d5fadb0b0eaecf2055a0cd279f9ec130b93d0 assets/create/models/item/cut_tuff_brick_slab.json 6f32b83c9f82424c0e2a2e0a8813eb44c2ac4527 assets/create/models/item/cut_tuff_brick_stairs.json 9088296b7677bddf16d670858a619d846a134ef6 assets/create/models/item/cut_tuff_brick_wall.json +4de100799e290db3fd46923781a83e6a12654266 assets/create/models/item/cut_tuff_bricks.json e9134027cc917e2e878456edb49bcfee382e73b1 assets/create/models/item/cut_tuff_slab.json 8235a34249197c100645b55ded5ff619a055d8a6 assets/create/models/item/cut_tuff_stairs.json a1626993eafa8d85dc950e17cbf78378ed64c7d2 assets/create/models/item/cut_tuff_wall.json a343c74f1e55426330df18f522e6d2a81276c499 assets/create/models/item/cut_veridium.json -3c3fd197f8e299ff90850e24c6507ea12f373123 assets/create/models/item/cut_veridium_bricks.json c1c5561ce31e237b7ea8f1adfb6a79e661b7f940 assets/create/models/item/cut_veridium_brick_slab.json f633006045ccfcdf486d7a240217229d6eed717e assets/create/models/item/cut_veridium_brick_stairs.json 8182109a002317dd8d2767b3828f8c44166a053f assets/create/models/item/cut_veridium_brick_wall.json +3c3fd197f8e299ff90850e24c6507ea12f373123 assets/create/models/item/cut_veridium_bricks.json 410b949304faa5856028f7c42ab762b7498ffd95 assets/create/models/item/cut_veridium_slab.json 62697c0922b11537914d2f4f84faa0b909ee518d assets/create/models/item/cut_veridium_stairs.json 3921d61a26d48d999cbb2f6645611e53ea71978b assets/create/models/item/cut_veridium_wall.json @@ -2144,12 +2144,12 @@ badd4326fac0b0a1590a2e9bce7c2cdd4e4562f3 assets/create/models/item/empty_schemat 7ec3ed4aaab72d76f6414447bbb3ad7887adf61f assets/create/models/item/encased_fan.json 3e1fdcc80fd68199b1890bcc830f78c48e7c0e43 assets/create/models/item/experience_block.json 9775e83414c0febb5c5b832437b0580e91bcbff3 assets/create/models/item/experience_nugget.json -87add851ae3271d733c9e6888865c288b6716f3b assets/create/models/item/exposed_copper_shingles.json 721c8ac46bf23abec2bbf4cff6dbfdf96cc569a6 assets/create/models/item/exposed_copper_shingle_slab.json 6e1c7fcd8da84dc2d49adb9802ce4fb431eddae1 assets/create/models/item/exposed_copper_shingle_stairs.json -fa7ffb172a43774cc07a2bb201e7010a2549001d assets/create/models/item/exposed_copper_tiles.json +87add851ae3271d733c9e6888865c288b6716f3b assets/create/models/item/exposed_copper_shingles.json a443633d90ef9ac2a866b69b2ecdfad1841dc3e1 assets/create/models/item/exposed_copper_tile_slab.json 9bb425a14635fc8b36a9a95f3d0c54e0b129b7b4 assets/create/models/item/exposed_copper_tile_stairs.json +fa7ffb172a43774cc07a2bb201e7010a2549001d assets/create/models/item/exposed_copper_tiles.json 8b64a93d9b6e33e3caa66adb7a0cc8c5cd473023 assets/create/models/item/extendo_grip.json 9114fa2e92ea4b7bf949b2e5a26290b0bade1af3 assets/create/models/item/factory_gauge.json dad31483f65baaf187e6553e3cd301c5d69e9db4 assets/create/models/item/filter.json @@ -2179,11 +2179,11 @@ b8d6d2d163e2ab5f654bbc4eda9ad63f8064d27c assets/create/models/item/gray_seat.jso 334fd81d5e6574220ee5815f1452b4f4aa7ad223 assets/create/models/item/green_table_cloth.json 561e0579101bf602b252c0b9a5eec468c89d0e40 assets/create/models/item/green_toolbox.json 7d3ddad087b4d2c6a32f97092533cbfb5de0cb3b assets/create/models/item/green_valve_handle.json -9e352162c8135773a4eca41871beea8f3ca650ae assets/create/models/item/handheld_worldshaper.json dac0331061c464e6d3e2070b232781c632840191 assets/create/models/item/hand_crank.json +9e352162c8135773a4eca41871beea8f3ca650ae assets/create/models/item/handheld_worldshaper.json 7bb435c53cbf935d80a28746125aebbd6263e45c assets/create/models/item/haunted_bell.json -81d67fb0e59f25762a412990884813c72d399d55 assets/create/models/item/honeyed_apple.json 2e97629313eab1a4ac4b38785dbe7ed45346e625 assets/create/models/item/honey_bucket.json +81d67fb0e59f25762a412990884813c72d399d55 assets/create/models/item/honeyed_apple.json 70185e640169d6253f06fb98f31b240f4807a53e assets/create/models/item/horizontal_framed_glass.json d47884b13fadf545bd585cd9ae347368924b04b0 assets/create/models/item/horizontal_framed_glass_pane.json 58b6f4ec2af3a69ae7145fb25d73451b6e8a2834 assets/create/models/item/hose_pulley.json @@ -2224,13 +2224,13 @@ b56a28924b0b1b2530ebac7834e011700b09b966 assets/create/models/item/light_gray_po cc8834024208662cb100f7cd38a04637da3b6852 assets/create/models/item/light_gray_table_cloth.json c8513eb1c89652783e26d7dcfcf64afa97619bc8 assets/create/models/item/light_gray_toolbox.json 3774d23e76b5712e7004e333e0a770f2230c2998 assets/create/models/item/light_gray_valve_handle.json -8f53caad3899a30be5087a0ba155080834418cc0 assets/create/models/item/limestone.json -fba1e7d1cad39c89976b427db62544d80f47ad5d assets/create/models/item/limestone_pillar.json 26b8e1daf9cc4b206fb5f62904c7f1701ba93e67 assets/create/models/item/lime_postbox.json 32cd55a1c97a31a13ad106a457ec9925aa91f6d3 assets/create/models/item/lime_seat.json a0843c3731fa3c4d23bc2b91fd68410fcf1df149 assets/create/models/item/lime_table_cloth.json 931d187c11cb95a0eeae8f256187ef551b42007e assets/create/models/item/lime_toolbox.json d0f4148bdb0a905e68f54b5dfd829fd47e528fea assets/create/models/item/lime_valve_handle.json +8f53caad3899a30be5087a0ba155080834418cc0 assets/create/models/item/limestone.json +fba1e7d1cad39c89976b427db62544d80f47ad5d assets/create/models/item/limestone_pillar.json 1d30f9b525e8e9736b34a92f848e235c71fd6bd8 assets/create/models/item/linear_chassis.json 8f622f5f79446f6060d9e8815205fce919c8c829 assets/create/models/item/linked_controller.json 538e28af9013a43c258a659cbe67671991f3eee7 assets/create/models/item/magenta_postbox.json @@ -2275,15 +2275,15 @@ af50363d603d61340b336569d58c1febde253665 assets/create/models/item/ochrum.json 7e767ca9e0ddb769b38fabd9289648ac63f5413d assets/create/models/item/orange_valve_handle.json 82152bca4310111d91584a2a78f05e158bb4bd90 assets/create/models/item/ornate_iron_window.json ca749a88faeef441c55c0527d81257187938b6b0 assets/create/models/item/ornate_iron_window_pane.json -09b3cd8ff7b29a6dd59f739a95bb708646d23537 assets/create/models/item/oxidized_copper_shingles.json c9c7ccdb68de2e77cd9f7053fab19493dd30a985 assets/create/models/item/oxidized_copper_shingle_slab.json 89c5f7a0a28f238ebed2641e243a47e4be2ad5ab assets/create/models/item/oxidized_copper_shingle_stairs.json -1c3428e2aed32a013631db012642a34d4eaf0785 assets/create/models/item/oxidized_copper_tiles.json +09b3cd8ff7b29a6dd59f739a95bb708646d23537 assets/create/models/item/oxidized_copper_shingles.json f1af7c5f3840efc3ae07940ee6719eb3417a0e1a assets/create/models/item/oxidized_copper_tile_slab.json ef2fe68d407a03bf1ed8f2d2f3e7323777d061bb assets/create/models/item/oxidized_copper_tile_stairs.json -b21a1f3ee7de3e17f69d27fd13ae6b23b62aa22c assets/create/models/item/packager.json +1c3428e2aed32a013631db012642a34d4eaf0785 assets/create/models/item/oxidized_copper_tiles.json 5b974e55caffdbfc2156eb8b59dd99db12243bd3 assets/create/models/item/package_filter.json 7fd76e7d2e6c6d94352f1fa08d096b63616ad01e assets/create/models/item/package_frogport.json +b21a1f3ee7de3e17f69d27fd13ae6b23b62aa22c assets/create/models/item/packager.json 76aeceb41bb7df873dbafe1bd5e26deb24abf93f assets/create/models/item/peculiar_bell.json ab6c05a0468f3f4295a07adb362fa2d36cf6e3e8 assets/create/models/item/pink_postbox.json df13d4281dc45041ecd93504d45daef61d070581 assets/create/models/item/pink_seat.json @@ -2380,15 +2380,15 @@ d3274003067a943d749ba5d23b5abc0fee8727a2 assets/create/models/item/rare_thunder_ 48ceaaead35ae1422542a615c9db55bd88f464e6 assets/create/models/item/rare_vector_package.json 5f8e5283fbebb452f1a1141b33ee73f08879c75d assets/create/models/item/raw_zinc.json 4631d67976cef148c346a7016baaa6703e4f243e assets/create/models/item/raw_zinc_block.json -9dc6c52e258b00cac6ed23147983045c43218b5d assets/create/models/item/redstone_contact.json -f8f733364bdd32b2ad597e81103bc02344ce63bd assets/create/models/item/redstone_link.json -ae0ba4827a81bd51c5c01178c2ccdae3a722628a assets/create/models/item/redstone_requester.json 4b73ee9cc2651a3d1a97476d100f9c4d7e2b2efe assets/create/models/item/red_postbox.json 8d00eb1a10055a802556eab10e13f522d12acd1c assets/create/models/item/red_sand_paper.json b64a054c92cbd2e055502d470f3921d1077e63a1 assets/create/models/item/red_seat.json 359d9bdb2496140e297a1e5a98c9563bc09d56b9 assets/create/models/item/red_table_cloth.json ac4695cc465d094b4adba1a4e9efec42c916f37d assets/create/models/item/red_toolbox.json 02473f42ef4b53dc809c7c58ae657c014bfaf652 assets/create/models/item/red_valve_handle.json +9dc6c52e258b00cac6ed23147983045c43218b5d assets/create/models/item/redstone_contact.json +f8f733364bdd32b2ad597e81103bc02344ce63bd assets/create/models/item/redstone_link.json +ae0ba4827a81bd51c5c01178c2ccdae3a722628a assets/create/models/item/redstone_requester.json 9926bbe6dad7c4c1a146492116d232e941c80d2b assets/create/models/item/refined_radiance.json bf827486dc7a1b3aeae577844d2dab2a97051db9 assets/create/models/item/refined_radiance_casing.json a982c29763d90556cca03074c168462a52cb9526 assets/create/models/item/repackager.json @@ -2402,9 +2402,9 @@ d45005a89e2c0d29944e0112be274365e0e318a5 assets/create/models/item/rose_quartz_t 670e978a34faf6a3acd7880b2f94c2574178d586 assets/create/models/item/sand_paper.json 6854451e331242ec50c186a545538024b07ec123 assets/create/models/item/schedule.json 0effa517c214ba07dba2f4ed12dfcf4785e42dd8 assets/create/models/item/schematic.json -8b7727844d8c12c3c22828c7f65fc7ac2d273e36 assets/create/models/item/schematicannon.json 2a52f084fa8187dd8da28fe820dde50c47a93b57 assets/create/models/item/schematic_and_quill.json 4c8b34627001e35ee15412a0cd037d0f24ba914e assets/create/models/item/schematic_table.json +8b7727844d8c12c3c22828c7f65fc7ac2d273e36 assets/create/models/item/schematicannon.json 2955563914c2f84ed06474c135062e91189ddf3a assets/create/models/item/scorchia.json 669041e5ad29d2166cc8895f85aa262040671d3e assets/create/models/item/scorchia_pillar.json ff52eb59dadfe675e416440f3115856a501428a6 assets/create/models/item/scoria.json @@ -2415,63 +2415,63 @@ abaa6da82babc26717ffff44fc41327bd015c9a6 assets/create/models/item/shadow_steel. ffaec38d11b91add4e150e33d0e0e49394f5beca assets/create/models/item/shadow_steel_casing.json b6fcd9722e5a09a9207964cba68752512e3b945a assets/create/models/item/shaft.json 617c6e2f759b2a95da7ee7192a2661afc6f6e8f8 assets/create/models/item/shopping_list.json -58ca190177e77db90c8195347c29d52c2cd0c556 assets/create/models/item/small_andesite_bricks.json fa92996fada8545fc340fb401bd0568f56809bf0 assets/create/models/item/small_andesite_brick_slab.json 08474bf814a55795c1f94203ceb8a969be2a2132 assets/create/models/item/small_andesite_brick_stairs.json 0e00bc6aa5be242217ed6fe8cbe1ccdf180742fb assets/create/models/item/small_andesite_brick_wall.json -543055fabb706a93037c6a9e47c334508e41b06c assets/create/models/item/small_asurine_bricks.json +58ca190177e77db90c8195347c29d52c2cd0c556 assets/create/models/item/small_andesite_bricks.json b160c3277f00f19687cffb87f9cb3aa32d3633aa assets/create/models/item/small_asurine_brick_slab.json 183fa4919f06e8c3c10f1efeceefd55389a96102 assets/create/models/item/small_asurine_brick_stairs.json d6a5ffdb493fb2c8176a7e6b42e05c2d393a2782 assets/create/models/item/small_asurine_brick_wall.json -26d9361e33e362a772220146724c0927453831e0 assets/create/models/item/small_calcite_bricks.json +543055fabb706a93037c6a9e47c334508e41b06c assets/create/models/item/small_asurine_bricks.json 8c1b5d5d40393636c9ff10afc09038c89bc1b383 assets/create/models/item/small_calcite_brick_slab.json 481ce90fb6abb05c904f01df3fe635f702bbfac0 assets/create/models/item/small_calcite_brick_stairs.json 02adb90bdf06a7c4c57d09dfd3c77cceef9b7fbe assets/create/models/item/small_calcite_brick_wall.json -d5a033d3dedb799c4752b7e68b6881529f38f8e5 assets/create/models/item/small_crimsite_bricks.json +26d9361e33e362a772220146724c0927453831e0 assets/create/models/item/small_calcite_bricks.json 8f382537c99eac3335f72db8dba33ab71f99a919 assets/create/models/item/small_crimsite_brick_slab.json b5d012cf0c5c94b73e6825b6884ab1d3eee7d64e assets/create/models/item/small_crimsite_brick_stairs.json 236457bb16bc7e949c16f3f091ee74dc3f3e6973 assets/create/models/item/small_crimsite_brick_wall.json -6ce2cb7882f41fcbcd641a442c98767bda61f65f assets/create/models/item/small_deepslate_bricks.json +d5a033d3dedb799c4752b7e68b6881529f38f8e5 assets/create/models/item/small_crimsite_bricks.json ce79900b7aa1eff0d42cabcd0a7f80ef20824551 assets/create/models/item/small_deepslate_brick_slab.json a260711af72c749a6b72f72515bbecb2e01e3ed8 assets/create/models/item/small_deepslate_brick_stairs.json 4e474891c6a269166c2eb413fae78699e5657af4 assets/create/models/item/small_deepslate_brick_wall.json -e412eaa393965ef5426c3d8d95d5c9d69e37e054 assets/create/models/item/small_diorite_bricks.json +6ce2cb7882f41fcbcd641a442c98767bda61f65f assets/create/models/item/small_deepslate_bricks.json 55b82c2f30d52acee5c3807ab2ffaed1d773cfa8 assets/create/models/item/small_diorite_brick_slab.json 49a17610b5b05595894ca2683056cecd724c1111 assets/create/models/item/small_diorite_brick_stairs.json dd3630a9c5500e6cf09e95d09e7a3cc99db11899 assets/create/models/item/small_diorite_brick_wall.json -c29d35da520d0fe828bb364db403b8cdf55f0a2e assets/create/models/item/small_dripstone_bricks.json +e412eaa393965ef5426c3d8d95d5c9d69e37e054 assets/create/models/item/small_diorite_bricks.json 21e281ec7a82d48018366a0737c6867f625b4663 assets/create/models/item/small_dripstone_brick_slab.json 6862e72eedf80536f40b6ac42ff78f13f62d012f assets/create/models/item/small_dripstone_brick_stairs.json ca8613bb64ceb562c36dd1d6a3b76b5f15f35be9 assets/create/models/item/small_dripstone_brick_wall.json -81eae95d20a9e99a070dfb8f6e6c22ef29f628d3 assets/create/models/item/small_granite_bricks.json +c29d35da520d0fe828bb364db403b8cdf55f0a2e assets/create/models/item/small_dripstone_bricks.json a19aa13eb3c04a9e0931e22e4170eec80950efab assets/create/models/item/small_granite_brick_slab.json 51bc02587cad5dfcfaf9d040848faa5277a25a5f assets/create/models/item/small_granite_brick_stairs.json 147a6f42be8312fbf050ad53c1625a1458f73cc3 assets/create/models/item/small_granite_brick_wall.json -bfa76583bca68134bbe2793c263cc0b71e1406af assets/create/models/item/small_limestone_bricks.json +81eae95d20a9e99a070dfb8f6e6c22ef29f628d3 assets/create/models/item/small_granite_bricks.json a9599981e872e683dacd01b2f0af511f416dd526 assets/create/models/item/small_limestone_brick_slab.json d8f8eadea13fc90a1c8ee5aca4be71fb22a79fd0 assets/create/models/item/small_limestone_brick_stairs.json 67626afe8b0fc9135456a24ea49c602b83d6970d assets/create/models/item/small_limestone_brick_wall.json -2d4b22d4028c55cbabc7eb405c2c6d485390afab assets/create/models/item/small_ochrum_bricks.json +bfa76583bca68134bbe2793c263cc0b71e1406af assets/create/models/item/small_limestone_bricks.json f7547aacb8bdaf61424cd56565e40d3cd40a1cfa assets/create/models/item/small_ochrum_brick_slab.json 8a320ff9e75e16a182cb7d07784a595fe7876e04 assets/create/models/item/small_ochrum_brick_stairs.json 0eedd4fe5b0a82de16fed148836087ff4ae64a74 assets/create/models/item/small_ochrum_brick_wall.json +2d4b22d4028c55cbabc7eb405c2c6d485390afab assets/create/models/item/small_ochrum_bricks.json 97b8e3eaddac0b93d4b6bc140f573969fcba5823 assets/create/models/item/small_rose_quartz_tiles.json -ac1bf1d2344517c18b945afa198d5d05e2866f6b assets/create/models/item/small_scorchia_bricks.json 63ef9901ba1014027e8c873d8374d86abb73158e assets/create/models/item/small_scorchia_brick_slab.json f52601fe54695c225a595a65e9130665582db856 assets/create/models/item/small_scorchia_brick_stairs.json b4e0db087dc88e0a3a4a82197a0ce347d3c7a7aa assets/create/models/item/small_scorchia_brick_wall.json -25b6bb40701e782ed64414ec8391b304ad5e6b12 assets/create/models/item/small_scoria_bricks.json +ac1bf1d2344517c18b945afa198d5d05e2866f6b assets/create/models/item/small_scorchia_bricks.json a4bdeb066dcc44f8be058e6d9dfc0a3fd34819bf assets/create/models/item/small_scoria_brick_slab.json 5ffb0e7de917013cd82cece2506d72fce2cd5fc6 assets/create/models/item/small_scoria_brick_stairs.json 67dcbc7d52fbbe88f89b36e04f970b27024741e4 assets/create/models/item/small_scoria_brick_wall.json -90943707d8b232d816392bec8ae05e06b6eedd72 assets/create/models/item/small_tuff_bricks.json +25b6bb40701e782ed64414ec8391b304ad5e6b12 assets/create/models/item/small_scoria_bricks.json 91a144100eea8b4e67a0a4f31b35a714693fa001 assets/create/models/item/small_tuff_brick_slab.json b3f89c9f8e46fbdfc58171073d6ad91c588e5853 assets/create/models/item/small_tuff_brick_stairs.json 52c1d4cfb5f1726c9ccbb00db60bdd6f760bf40f assets/create/models/item/small_tuff_brick_wall.json -6935d6d9dbdb99fe7258d9347419d65571711263 assets/create/models/item/small_veridium_bricks.json +90943707d8b232d816392bec8ae05e06b6eedd72 assets/create/models/item/small_tuff_bricks.json 0bb60fc6ab570db83214fd10c83d931f6677e361 assets/create/models/item/small_veridium_brick_slab.json 89918d98b6830477b21ab7fb9e30807d3ca1d379 assets/create/models/item/small_veridium_brick_stairs.json ab4e7695e99548f83a89f3d5ad7690a576bafcc0 assets/create/models/item/small_veridium_brick_wall.json +6935d6d9dbdb99fe7258d9347419d65571711263 assets/create/models/item/small_veridium_bricks.json 6cf508dbd3d015ea730366db92bb17844dc2ca06 assets/create/models/item/smart_chute.json 9201f00edcf2ffa33cb079c28b5c33e39872c824 assets/create/models/item/smart_fluid_pipe.json 67804bdd890f167010f6101a700e85a3245f4cc3 assets/create/models/item/speedometer.json @@ -2482,9 +2482,9 @@ b82ab0c69df330f6f938ed1beee7b4add67d2e50 assets/create/models/item/steam_engine. 24acc593a5e910b6301afcb3f23cba526d23a0ab assets/create/models/item/steam_whistle.json 54f200be903e056e5cf9e2186f0a0a51f8f0f84e assets/create/models/item/sticker.json 0f88de164439640cc175ceef2017f7416b5a7018 assets/create/models/item/sticky_mechanical_piston.json -4b640b66765b206f8c2884b7c1a1ef860b81d841 assets/create/models/item/stockpile_switch.json 97222d9eb36944a89b8047423eafa6af3da82b0b assets/create/models/item/stock_link.json 67c98c6c7f2122850acfbee34688572934fdd226 assets/create/models/item/stock_ticker.json +4b640b66765b206f8c2884b7c1a1ef860b81d841 assets/create/models/item/stockpile_switch.json 6ee792277b9fd980c40e18e841afa63fc500ed0b assets/create/models/item/stressometer.json 8d4ce1ccf180016506292f63188c10d0dabe0ee3 assets/create/models/item/sturdy_sheet.json a10bb4d6d1a4483a806e3aaa086d48c0e20aaefe assets/create/models/item/super_glue.json @@ -2511,36 +2511,36 @@ b0f6d37aa695395e28a23d36775092f63ab3f5a5 assets/create/models/item/vertical_gear 9c5087114e35052c5e56bb752252de5d092408c5 assets/create/models/item/warped_window.json cdc1226f8a098adbc420fe50c98466507c3a3157 assets/create/models/item/warped_window_pane.json e5939b47bf7440dc101c667e68ef6bf750a3290f assets/create/models/item/water_wheel.json -be2f058a7ecb015599ee052ec27c4360d636999a assets/create/models/item/waxed_copper_shingles.json adc188e4e48bea80607c6e0c7076c9bdd7236cb0 assets/create/models/item/waxed_copper_shingle_slab.json 7e224aceaa94361256e95e4c44d8814aebaf297c assets/create/models/item/waxed_copper_shingle_stairs.json -eced19a2f721c54b968e5979cde2705f15faf3e1 assets/create/models/item/waxed_copper_tiles.json +be2f058a7ecb015599ee052ec27c4360d636999a assets/create/models/item/waxed_copper_shingles.json 68b3632c34adb9991aa993385f53624632c260f2 assets/create/models/item/waxed_copper_tile_slab.json a7fc0cc2d32dcd49c3274597ce7121f01fca03f8 assets/create/models/item/waxed_copper_tile_stairs.json -5336907eba067492f6d00b4b8514f9663830a1d5 assets/create/models/item/waxed_exposed_copper_shingles.json +eced19a2f721c54b968e5979cde2705f15faf3e1 assets/create/models/item/waxed_copper_tiles.json fd428034c46a240c4bb2a1aee625b8767f41c3ef assets/create/models/item/waxed_exposed_copper_shingle_slab.json 43d714187fe6c0cd1ed7abcddef1ebcd63979ff4 assets/create/models/item/waxed_exposed_copper_shingle_stairs.json -962b24b3611abefc21920d01452944710ab0da3f assets/create/models/item/waxed_exposed_copper_tiles.json +5336907eba067492f6d00b4b8514f9663830a1d5 assets/create/models/item/waxed_exposed_copper_shingles.json 25f5a10fe8e6acbdbf8457d56aeee065835a93ec assets/create/models/item/waxed_exposed_copper_tile_slab.json 22917505d328fb5b489b9f7f9068f1514b784abb assets/create/models/item/waxed_exposed_copper_tile_stairs.json -12c3dd893bddb66b9b387652c67c8f0e24b643ff assets/create/models/item/waxed_oxidized_copper_shingles.json +962b24b3611abefc21920d01452944710ab0da3f assets/create/models/item/waxed_exposed_copper_tiles.json 9b7c82376ea8c1c8ecbc7bbe15283f84b0d50d94 assets/create/models/item/waxed_oxidized_copper_shingle_slab.json fbb6043eb935aa0641a482ee7300c780be257440 assets/create/models/item/waxed_oxidized_copper_shingle_stairs.json -6b8f75d4818db903b22f4626d02671ab76a61023 assets/create/models/item/waxed_oxidized_copper_tiles.json +12c3dd893bddb66b9b387652c67c8f0e24b643ff assets/create/models/item/waxed_oxidized_copper_shingles.json 6e7bc8eb9a87d903dcc590e9918ce8d4411bf190 assets/create/models/item/waxed_oxidized_copper_tile_slab.json 10136759b31e4d957e8374948460d6c984711326 assets/create/models/item/waxed_oxidized_copper_tile_stairs.json -ce2dcfc01205da1dc70f34091a2c24f563e72466 assets/create/models/item/waxed_weathered_copper_shingles.json +6b8f75d4818db903b22f4626d02671ab76a61023 assets/create/models/item/waxed_oxidized_copper_tiles.json 2bf249c677d30a4febf950fa7c6caa87c348c54e assets/create/models/item/waxed_weathered_copper_shingle_slab.json 9fa84f2555d82b5a1550b748a332ceb443a04fae assets/create/models/item/waxed_weathered_copper_shingle_stairs.json -02d2ac048c9bea86d10673254dfc107f3c9c5bb5 assets/create/models/item/waxed_weathered_copper_tiles.json +ce2dcfc01205da1dc70f34091a2c24f563e72466 assets/create/models/item/waxed_weathered_copper_shingles.json ab40b1a5a03cd290d53ef2ea65f90dcfcd2673de assets/create/models/item/waxed_weathered_copper_tile_slab.json dadc7b65a4527e288c21a20df978796a8c444fd2 assets/create/models/item/waxed_weathered_copper_tile_stairs.json -86b8e71fa8b7aeb73eafda89d8d06d83da6a5d25 assets/create/models/item/weathered_copper_shingles.json +02d2ac048c9bea86d10673254dfc107f3c9c5bb5 assets/create/models/item/waxed_weathered_copper_tiles.json 94db30ad2381d2f2c37cdfd0d5ce5c45a2807640 assets/create/models/item/weathered_copper_shingle_slab.json 7262c01df4b5a8cd8c6a5545062f251d5ad9fd06 assets/create/models/item/weathered_copper_shingle_stairs.json -99f17b16b68201aefb78298b3e6c657e3c2235e0 assets/create/models/item/weathered_copper_tiles.json +86b8e71fa8b7aeb73eafda89d8d06d83da6a5d25 assets/create/models/item/weathered_copper_shingles.json 0b1b299d6dfab65b6060305a8b3e51f6e2df09f4 assets/create/models/item/weathered_copper_tile_slab.json 0c3989b44fde934ba8b88b071887e5ede522c417 assets/create/models/item/weathered_copper_tile_stairs.json +99f17b16b68201aefb78298b3e6c657e3c2235e0 assets/create/models/item/weathered_copper_tiles.json b5d591fbb40e062efe301b3b3b49580e5ad64566 assets/create/models/item/weathered_iron_block.json a569ddd725898a86f8745e46723edeff7fe7f2e9 assets/create/models/item/weathered_iron_window.json 68ca3316942b2df1623893cda722402238ab7724 assets/create/models/item/weathered_iron_window_pane.json @@ -2579,42 +2579,42 @@ b25b8c230fde8d6d77e8d516bed52236652b5ca6 data/create/advancements/recipes/buildi 537fe5dffa659e5838379587fbd84f2f641551ea data/create/advancements/recipes/building_blocks/calcite_pillar_from_stone_types_calcite_stonecutting.json 2636ac059b6412a46402cccbe5abe4fb49143662 data/create/advancements/recipes/building_blocks/cherry_window.json 3e08f575543f1e0abea979dbaee643572734788b data/create/advancements/recipes/building_blocks/cherry_window_pane.json -09f332cd34e6a92af9e8e4e757418c7ba8b536da data/create/advancements/recipes/building_blocks/copper_shingles_from_ingots_copper_stonecutting.json 55214a0fd27318b17163cace66c7525785127ef8 data/create/advancements/recipes/building_blocks/copper_shingle_slab.json fb4210dbbfb74459e10da94a540f3bfdf91c4a8d data/create/advancements/recipes/building_blocks/copper_shingle_slab_from_copper_shingles_stonecutting.json 31b04ac1b117fb65f5129c5bbb48e42c1c4c1003 data/create/advancements/recipes/building_blocks/copper_shingle_stairs.json bef4a9a4c2e722d4f086d6b4c9d6fa1d0836ec10 data/create/advancements/recipes/building_blocks/copper_shingle_stairs_from_copper_shingles_stonecutting.json -f66a48f01afb4fa1babee4a8c28b032280c3ac9e data/create/advancements/recipes/building_blocks/copper_tiles_from_ingots_copper_stonecutting.json +09f332cd34e6a92af9e8e4e757418c7ba8b536da data/create/advancements/recipes/building_blocks/copper_shingles_from_ingots_copper_stonecutting.json ef79744ebf31453d1c81789afed7b717837b3515 data/create/advancements/recipes/building_blocks/copper_tile_slab.json 8e9997c43b1c06521fe8d38b04ccb3f04c93d537 data/create/advancements/recipes/building_blocks/copper_tile_slab_from_copper_tiles_stonecutting.json a2609aa8b5453f2294f38c81d26e0b8dad71087d data/create/advancements/recipes/building_blocks/copper_tile_stairs.json d47e46c66bf69e8310e6687716858842e8aed7b5 data/create/advancements/recipes/building_blocks/copper_tile_stairs_from_copper_tiles_stonecutting.json +f66a48f01afb4fa1babee4a8c28b032280c3ac9e data/create/advancements/recipes/building_blocks/copper_tiles_from_ingots_copper_stonecutting.json cc14d10c75ab0fdd7c54db1922e5e56667739fef data/create/advancements/recipes/building_blocks/copycat_panel_from_ingots_zinc_stonecutting.json 55d2812be912c857ff666d581174378857d3bce2 data/create/advancements/recipes/building_blocks/copycat_step_from_ingots_zinc_stonecutting.json -8615fc107b1f4df86711081a9dccac8631b02e6b data/create/advancements/recipes/building_blocks/crafting/copper/waxed_copper_shingles_from_honeycomb.json 0e0eba8550768ef69087dff8112814f25233fab7 data/create/advancements/recipes/building_blocks/crafting/copper/waxed_copper_shingle_slab_from_honeycomb.json 2c960d55273df4c0c8c33b2c329175b35b18fc8c data/create/advancements/recipes/building_blocks/crafting/copper/waxed_copper_shingle_stairs_from_honeycomb.json -fa8f3ed9a4c6f0c3cd4c21b0ae4dc8ca4dba8678 data/create/advancements/recipes/building_blocks/crafting/copper/waxed_copper_tiles_from_honeycomb.json +8615fc107b1f4df86711081a9dccac8631b02e6b data/create/advancements/recipes/building_blocks/crafting/copper/waxed_copper_shingles_from_honeycomb.json d6f2aa7fd10c96f71c47bdabb3e53dc4c4e73706 data/create/advancements/recipes/building_blocks/crafting/copper/waxed_copper_tile_slab_from_honeycomb.json eca165eee20adba1557ccc74ef50ee90311b3019 data/create/advancements/recipes/building_blocks/crafting/copper/waxed_copper_tile_stairs_from_honeycomb.json -88a236933e8dfe0d809bda098d16782288c4800c data/create/advancements/recipes/building_blocks/crafting/copper/waxed_exposed_copper_shingles_from_honeycomb.json +fa8f3ed9a4c6f0c3cd4c21b0ae4dc8ca4dba8678 data/create/advancements/recipes/building_blocks/crafting/copper/waxed_copper_tiles_from_honeycomb.json 301149dabc4dce290b4884f4ed3cb2132123adf0 data/create/advancements/recipes/building_blocks/crafting/copper/waxed_exposed_copper_shingle_slab_from_honeycomb.json f360dce7bece72672f2624710c88edbe3e3f8885 data/create/advancements/recipes/building_blocks/crafting/copper/waxed_exposed_copper_shingle_stairs_from_honeycomb.json -bc27959288766492746f41c4810350dcef1b320d data/create/advancements/recipes/building_blocks/crafting/copper/waxed_exposed_copper_tiles_from_honeycomb.json +88a236933e8dfe0d809bda098d16782288c4800c data/create/advancements/recipes/building_blocks/crafting/copper/waxed_exposed_copper_shingles_from_honeycomb.json 7ceb4b74ff84ed404518b6cb5e1432dac5903b5f data/create/advancements/recipes/building_blocks/crafting/copper/waxed_exposed_copper_tile_slab_from_honeycomb.json ec1eec3bc25534484cb264134e62b578525422aa data/create/advancements/recipes/building_blocks/crafting/copper/waxed_exposed_copper_tile_stairs_from_honeycomb.json -2e8f1da032110e8c5ec375ffd425e5eed7f58cae data/create/advancements/recipes/building_blocks/crafting/copper/waxed_oxidized_copper_shingles_from_honeycomb.json +bc27959288766492746f41c4810350dcef1b320d data/create/advancements/recipes/building_blocks/crafting/copper/waxed_exposed_copper_tiles_from_honeycomb.json e34abb4d51c1d00419fc3d3799ca0d9fe7ea1027 data/create/advancements/recipes/building_blocks/crafting/copper/waxed_oxidized_copper_shingle_slab_from_honeycomb.json 9471e190beb603f022fb234f2cf35b5b4b93f0c0 data/create/advancements/recipes/building_blocks/crafting/copper/waxed_oxidized_copper_shingle_stairs_from_honeycomb.json -17fe14b753953a68887cd001fcaa264ef031463f data/create/advancements/recipes/building_blocks/crafting/copper/waxed_oxidized_copper_tiles_from_honeycomb.json +2e8f1da032110e8c5ec375ffd425e5eed7f58cae data/create/advancements/recipes/building_blocks/crafting/copper/waxed_oxidized_copper_shingles_from_honeycomb.json 2577754364f05264fac325f67597230d01fa0c1d data/create/advancements/recipes/building_blocks/crafting/copper/waxed_oxidized_copper_tile_slab_from_honeycomb.json 003e384d9594a4e6ef5678e74f04b56de047dbde data/create/advancements/recipes/building_blocks/crafting/copper/waxed_oxidized_copper_tile_stairs_from_honeycomb.json -5009a82a897a15407fec785005107b0d228fffe7 data/create/advancements/recipes/building_blocks/crafting/copper/waxed_weathered_copper_shingles_from_honeycomb.json +17fe14b753953a68887cd001fcaa264ef031463f data/create/advancements/recipes/building_blocks/crafting/copper/waxed_oxidized_copper_tiles_from_honeycomb.json 70ce32937dcf349dce77fef8022bc0c15863f6a6 data/create/advancements/recipes/building_blocks/crafting/copper/waxed_weathered_copper_shingle_slab_from_honeycomb.json 1fc498238dcc2705152573ba7f74bb50e7e66ca7 data/create/advancements/recipes/building_blocks/crafting/copper/waxed_weathered_copper_shingle_stairs_from_honeycomb.json -d12aa3dd5457327224fd007211878eec21043971 data/create/advancements/recipes/building_blocks/crafting/copper/waxed_weathered_copper_tiles_from_honeycomb.json +5009a82a897a15407fec785005107b0d228fffe7 data/create/advancements/recipes/building_blocks/crafting/copper/waxed_weathered_copper_shingles_from_honeycomb.json 6f461d7036de914c636b7916dc798775ccf25be1 data/create/advancements/recipes/building_blocks/crafting/copper/waxed_weathered_copper_tile_slab_from_honeycomb.json 3bc9efcddecd23fd06c6056a0ee7b937959cecc0 data/create/advancements/recipes/building_blocks/crafting/copper/waxed_weathered_copper_tile_stairs_from_honeycomb.json +d12aa3dd5457327224fd007211878eec21043971 data/create/advancements/recipes/building_blocks/crafting/copper/waxed_weathered_copper_tiles_from_honeycomb.json 3064c52dea808a00c211bfedb96106b563f480da data/create/advancements/recipes/building_blocks/crafting/kinetics/black_seat.json f07a0b21db200ab68a7df02db519869f68953286 data/create/advancements/recipes/building_blocks/crafting/kinetics/black_seat_from_other_seat.json 80ac4db5c53c7efc2666a7abb4e2e876c5f86588 data/create/advancements/recipes/building_blocks/crafting/kinetics/blue_seat.json @@ -2715,7 +2715,6 @@ f3188b24f8108be4219016689a4768f826b4fef3 data/create/advancements/recipes/buildi e88373b83226d860b0c2131213f5d3b09f31ab96 data/create/advancements/recipes/building_blocks/crimsite_pillar_from_stone_types_crimsite_stonecutting.json 09f7122cf360fd56bde2b1659bbed526f9a119c4 data/create/advancements/recipes/building_blocks/crimson_window.json b5234c6050bc0c6fe872a5ddc87d46ba39e07971 data/create/advancements/recipes/building_blocks/crimson_window_pane.json -b32f4345517c3c7299a06489325bd85f987145dc data/create/advancements/recipes/building_blocks/cut_andesite_bricks_from_stone_types_andesite_stonecutting.json 22fe2e61d7e9836d9f71c39bfbba50efc2fa184d data/create/advancements/recipes/building_blocks/cut_andesite_brick_slab.json 6d8d28364f1016dfd1d7cbe4a2637e2b6224e4d8 data/create/advancements/recipes/building_blocks/cut_andesite_brick_slab_from_stone_types_andesite_stonecutting.json 39e904f66d2194de5437b5da2f8db8b6f03d78f4 data/create/advancements/recipes/building_blocks/cut_andesite_brick_slab_recycling.json @@ -2723,6 +2722,7 @@ b32f4345517c3c7299a06489325bd85f987145dc data/create/advancements/recipes/buildi 480c696956b99c96cbaf46e7dad9711c40680ec8 data/create/advancements/recipes/building_blocks/cut_andesite_brick_stairs_from_stone_types_andesite_stonecutting.json 8d504cdb99f5dc59bef5ff35d0b443f2f4ba21d2 data/create/advancements/recipes/building_blocks/cut_andesite_brick_wall.json e1b8e5906d54368c98867b83143dc7acc7b0aa28 data/create/advancements/recipes/building_blocks/cut_andesite_brick_wall_from_stone_types_andesite_stonecutting.json +b32f4345517c3c7299a06489325bd85f987145dc data/create/advancements/recipes/building_blocks/cut_andesite_bricks_from_stone_types_andesite_stonecutting.json d5b44158f9a98d874d941fc4df99de7a2657af21 data/create/advancements/recipes/building_blocks/cut_andesite_from_stone_types_andesite_stonecutting.json c11998f554bbd42efdbdf58cf8efe5bcf69230de data/create/advancements/recipes/building_blocks/cut_andesite_slab.json 1f457c0e816e4dd70e1a960015d2004814d11926 data/create/advancements/recipes/building_blocks/cut_andesite_slab_from_stone_types_andesite_stonecutting.json @@ -2731,7 +2731,6 @@ a4d7adf49472a2069bad72defd39b111b83def3d data/create/advancements/recipes/buildi 6d38bb2b9812761c594ebdf717284ba8d32e88bc data/create/advancements/recipes/building_blocks/cut_andesite_stairs_from_stone_types_andesite_stonecutting.json 2f6b2296b11e0e743d68749e65af5ffa0f374998 data/create/advancements/recipes/building_blocks/cut_andesite_wall.json caf3b1c62d0f8df3ce126535f0566c899577bedb data/create/advancements/recipes/building_blocks/cut_andesite_wall_from_stone_types_andesite_stonecutting.json -54188623046e989d21e6e155933e4084fb2882c4 data/create/advancements/recipes/building_blocks/cut_asurine_bricks_from_stone_types_asurine_stonecutting.json 536a2bed2ed1e7e249886ef376c96a8d5a1facdc data/create/advancements/recipes/building_blocks/cut_asurine_brick_slab.json a4e833cadfbb82222a70d66524e804c83ea13f7b data/create/advancements/recipes/building_blocks/cut_asurine_brick_slab_from_stone_types_asurine_stonecutting.json 610163ac2f4b06121931a81ac4b3df39ece61998 data/create/advancements/recipes/building_blocks/cut_asurine_brick_slab_recycling.json @@ -2739,6 +2738,7 @@ a4e833cadfbb82222a70d66524e804c83ea13f7b data/create/advancements/recipes/buildi f92f31e80cc026160217afb6c757987f75ed0b33 data/create/advancements/recipes/building_blocks/cut_asurine_brick_stairs_from_stone_types_asurine_stonecutting.json fa6dc7eaa32652a00a7217ae25967de0791088b6 data/create/advancements/recipes/building_blocks/cut_asurine_brick_wall.json 33f361369bfd92f53b3e40c837b336edd04a26e9 data/create/advancements/recipes/building_blocks/cut_asurine_brick_wall_from_stone_types_asurine_stonecutting.json +54188623046e989d21e6e155933e4084fb2882c4 data/create/advancements/recipes/building_blocks/cut_asurine_bricks_from_stone_types_asurine_stonecutting.json a6b871faa10badaaaa1a0ebbba94c4f2f627c43f data/create/advancements/recipes/building_blocks/cut_asurine_from_stone_types_asurine_stonecutting.json 719e1d4fea3457f2990be6a5d6cd87915d546217 data/create/advancements/recipes/building_blocks/cut_asurine_slab.json 586918291dda711c79941cf484cb62dbb853a271 data/create/advancements/recipes/building_blocks/cut_asurine_slab_from_stone_types_asurine_stonecutting.json @@ -2747,7 +2747,6 @@ bd2a630d242ae9c89b071b0401285068071a346c data/create/advancements/recipes/buildi 03d7b1609d161043e28661d74f53b06d4408f561 data/create/advancements/recipes/building_blocks/cut_asurine_stairs_from_stone_types_asurine_stonecutting.json cba4a6feaf695e665204cac36f9109ba941b12a6 data/create/advancements/recipes/building_blocks/cut_asurine_wall.json 3327651dd3f2fd778abdcfe70d25137d916f3def data/create/advancements/recipes/building_blocks/cut_asurine_wall_from_stone_types_asurine_stonecutting.json -44873f9d05abde7d52a6eacdf3573d8b69c69452 data/create/advancements/recipes/building_blocks/cut_calcite_bricks_from_stone_types_calcite_stonecutting.json a070ffe63c182b33c4c6faedb391f51a209c0e27 data/create/advancements/recipes/building_blocks/cut_calcite_brick_slab.json 7ba1e7add81422599f798153e4fd069e9fbfdebf data/create/advancements/recipes/building_blocks/cut_calcite_brick_slab_from_stone_types_calcite_stonecutting.json f5e80ec393c306485d666d6f9f91c55d9f1ba592 data/create/advancements/recipes/building_blocks/cut_calcite_brick_slab_recycling.json @@ -2755,6 +2754,7 @@ f5e80ec393c306485d666d6f9f91c55d9f1ba592 data/create/advancements/recipes/buildi 627f85aa63133cf95dd828092e0232b9ec8acfd5 data/create/advancements/recipes/building_blocks/cut_calcite_brick_stairs_from_stone_types_calcite_stonecutting.json d8870e522a68274cc90eab07ea17b7b6cdc5a16c data/create/advancements/recipes/building_blocks/cut_calcite_brick_wall.json cdf5927f3c1b3ef8904f38f66317412799e189fb data/create/advancements/recipes/building_blocks/cut_calcite_brick_wall_from_stone_types_calcite_stonecutting.json +44873f9d05abde7d52a6eacdf3573d8b69c69452 data/create/advancements/recipes/building_blocks/cut_calcite_bricks_from_stone_types_calcite_stonecutting.json 9f8c31b0db2aab8f1c8f42bcef15a74bc36887d4 data/create/advancements/recipes/building_blocks/cut_calcite_from_stone_types_calcite_stonecutting.json 857666ad1c6a5cc886f6896a18f560098afaa67b data/create/advancements/recipes/building_blocks/cut_calcite_slab.json c55074cd091b0e078105abdc940c62afa8984265 data/create/advancements/recipes/building_blocks/cut_calcite_slab_from_stone_types_calcite_stonecutting.json @@ -2763,7 +2763,6 @@ c55074cd091b0e078105abdc940c62afa8984265 data/create/advancements/recipes/buildi ba3378e1d08de2af0b2a725727cf9f68bda60044 data/create/advancements/recipes/building_blocks/cut_calcite_stairs_from_stone_types_calcite_stonecutting.json db5f4e1eee91c2a65d36164c20aba0e9d3a502ae data/create/advancements/recipes/building_blocks/cut_calcite_wall.json 19de370083d2cf1234c9c4e6ff45d85ef34a1ac8 data/create/advancements/recipes/building_blocks/cut_calcite_wall_from_stone_types_calcite_stonecutting.json -b9a2edda241f6e0677a2003300f0be5d3ff8f4b0 data/create/advancements/recipes/building_blocks/cut_crimsite_bricks_from_stone_types_crimsite_stonecutting.json 9fda0e6edde197a9c28a854419a2a07e323b6b53 data/create/advancements/recipes/building_blocks/cut_crimsite_brick_slab.json 2da3f139759be7eea552885b2063a0e2dfc647b1 data/create/advancements/recipes/building_blocks/cut_crimsite_brick_slab_from_stone_types_crimsite_stonecutting.json 62d928c8ab2e09a3f87adacb5adb1a5ddc1d2a7b data/create/advancements/recipes/building_blocks/cut_crimsite_brick_slab_recycling.json @@ -2771,6 +2770,7 @@ b9a2edda241f6e0677a2003300f0be5d3ff8f4b0 data/create/advancements/recipes/buildi 89850244feb8a3293ba96702b7a56a4bea84e1f3 data/create/advancements/recipes/building_blocks/cut_crimsite_brick_stairs_from_stone_types_crimsite_stonecutting.json 267cab789c73d474299542fb0719967501fcf0c9 data/create/advancements/recipes/building_blocks/cut_crimsite_brick_wall.json 27007676b86eb8a3498982d8b5e68495b84d62d5 data/create/advancements/recipes/building_blocks/cut_crimsite_brick_wall_from_stone_types_crimsite_stonecutting.json +b9a2edda241f6e0677a2003300f0be5d3ff8f4b0 data/create/advancements/recipes/building_blocks/cut_crimsite_bricks_from_stone_types_crimsite_stonecutting.json a88d252d4e634ff194daa3ff98fd7e965e3ed09a data/create/advancements/recipes/building_blocks/cut_crimsite_from_stone_types_crimsite_stonecutting.json f703136e1783a42252bc1d89c31e5563cbdff583 data/create/advancements/recipes/building_blocks/cut_crimsite_slab.json 3330d332462da22de48d07b62277c1df8e646a3e data/create/advancements/recipes/building_blocks/cut_crimsite_slab_from_stone_types_crimsite_stonecutting.json @@ -2779,7 +2779,6 @@ c2707e5969f0c554537dda9d3e2a4c13e19863c3 data/create/advancements/recipes/buildi e9ba513178090b020525e72468a0450e225da779 data/create/advancements/recipes/building_blocks/cut_crimsite_stairs_from_stone_types_crimsite_stonecutting.json 7fb5ce65b7b5c2d76b4306d407aaa6eefe07b7e5 data/create/advancements/recipes/building_blocks/cut_crimsite_wall.json a83d5b669f92bd833af2768d2cf5d4797a86b63c data/create/advancements/recipes/building_blocks/cut_crimsite_wall_from_stone_types_crimsite_stonecutting.json -bc9eb21df37df4b69e5d202b3b770698a16f4413 data/create/advancements/recipes/building_blocks/cut_deepslate_bricks_from_stone_types_deepslate_stonecutting.json 2c380e8ddc83cef4213f136ff7a196d861728914 data/create/advancements/recipes/building_blocks/cut_deepslate_brick_slab.json 87b5dfc1e61fabe4e7661bea0d7a56cb75197a81 data/create/advancements/recipes/building_blocks/cut_deepslate_brick_slab_from_stone_types_deepslate_stonecutting.json 09cde6df1120cc5f5f129023885f323b4d1eeae9 data/create/advancements/recipes/building_blocks/cut_deepslate_brick_slab_recycling.json @@ -2787,6 +2786,7 @@ bc9eb21df37df4b69e5d202b3b770698a16f4413 data/create/advancements/recipes/buildi 28e15fe2c377540cb631f6648f49090f234e7704 data/create/advancements/recipes/building_blocks/cut_deepslate_brick_stairs_from_stone_types_deepslate_stonecutting.json d2b34f455ab0053f24a4f9dec7dcce45832ef25b data/create/advancements/recipes/building_blocks/cut_deepslate_brick_wall.json 7b174b65b813b4a9ca507e71fa142931e074f336 data/create/advancements/recipes/building_blocks/cut_deepslate_brick_wall_from_stone_types_deepslate_stonecutting.json +bc9eb21df37df4b69e5d202b3b770698a16f4413 data/create/advancements/recipes/building_blocks/cut_deepslate_bricks_from_stone_types_deepslate_stonecutting.json 83db3f5b46c996481b930974bddba75c82c115af data/create/advancements/recipes/building_blocks/cut_deepslate_from_stone_types_deepslate_stonecutting.json 8e8816aad8212c3557e77cc01df551fe1a0a306d data/create/advancements/recipes/building_blocks/cut_deepslate_slab.json 14ea447072200733dd9551a5ac6a9544593dd9f7 data/create/advancements/recipes/building_blocks/cut_deepslate_slab_from_stone_types_deepslate_stonecutting.json @@ -2795,7 +2795,6 @@ c7870abb459c8b174c380282ae211a87ab252521 data/create/advancements/recipes/buildi 4f157401a3019c96cc6ae5a0036f31351c651fbb data/create/advancements/recipes/building_blocks/cut_deepslate_stairs_from_stone_types_deepslate_stonecutting.json 9ae9635fa129aab54a7ec971b9cc61d300d3d53e data/create/advancements/recipes/building_blocks/cut_deepslate_wall.json 9b5df53000c79a7b20e3a1888e003b704809feda data/create/advancements/recipes/building_blocks/cut_deepslate_wall_from_stone_types_deepslate_stonecutting.json -fdef99789ca74623b00b05be2f975b63831645db data/create/advancements/recipes/building_blocks/cut_diorite_bricks_from_stone_types_diorite_stonecutting.json 30a00465dc9b19d8024146e2c2d6b9f41562da30 data/create/advancements/recipes/building_blocks/cut_diorite_brick_slab.json a55e7daf48a487d74b4a01e30b80968094154d2b data/create/advancements/recipes/building_blocks/cut_diorite_brick_slab_from_stone_types_diorite_stonecutting.json e445a3d8fd00f5e4f2ee56c797d8abf548598447 data/create/advancements/recipes/building_blocks/cut_diorite_brick_slab_recycling.json @@ -2803,6 +2802,7 @@ b421f24513612dd7a5d8977d7bff122fd5cf9522 data/create/advancements/recipes/buildi 3fe00adac35beeda79b7f9d930a1f13b033c0f12 data/create/advancements/recipes/building_blocks/cut_diorite_brick_stairs_from_stone_types_diorite_stonecutting.json 6d2235b8587863107a6d1a0818c81ee3dc217cdf data/create/advancements/recipes/building_blocks/cut_diorite_brick_wall.json 0ec4b69e98adf961f5d4d63700f11ad66a4116b5 data/create/advancements/recipes/building_blocks/cut_diorite_brick_wall_from_stone_types_diorite_stonecutting.json +fdef99789ca74623b00b05be2f975b63831645db data/create/advancements/recipes/building_blocks/cut_diorite_bricks_from_stone_types_diorite_stonecutting.json c9f52e0661fdc266f8429faf1570124fecfa2d6a data/create/advancements/recipes/building_blocks/cut_diorite_from_stone_types_diorite_stonecutting.json c7b73ddec6402e8b5ff5daedbbbc74f882338a8e data/create/advancements/recipes/building_blocks/cut_diorite_slab.json 46c841e5aae99106cbc28026dcfec946976127e5 data/create/advancements/recipes/building_blocks/cut_diorite_slab_from_stone_types_diorite_stonecutting.json @@ -2811,7 +2811,6 @@ ce67a5fae622955ad795e2b3d14c159a4c47b936 data/create/advancements/recipes/buildi 3b7ec28df80ea9cf87980b2c2184858ba6152a3f data/create/advancements/recipes/building_blocks/cut_diorite_stairs_from_stone_types_diorite_stonecutting.json c8fe9ab53eda2cdbff08678ebb577c169ea61a91 data/create/advancements/recipes/building_blocks/cut_diorite_wall.json 050f67b5a662bea3ef972521ef7f81c2ba99015c data/create/advancements/recipes/building_blocks/cut_diorite_wall_from_stone_types_diorite_stonecutting.json -b60683fdd629b201f40a6f9bb6594df7c5ac13f1 data/create/advancements/recipes/building_blocks/cut_dripstone_bricks_from_stone_types_dripstone_stonecutting.json 1e0d39ed56e2ab4eac084f26a1c6de905db29220 data/create/advancements/recipes/building_blocks/cut_dripstone_brick_slab.json 020cbc4c8063d186d3f5c9ece429e4cdff53cf63 data/create/advancements/recipes/building_blocks/cut_dripstone_brick_slab_from_stone_types_dripstone_stonecutting.json b44c9e7f9f62ffffb5566901e0a22010ba76641c data/create/advancements/recipes/building_blocks/cut_dripstone_brick_slab_recycling.json @@ -2819,6 +2818,7 @@ b44c9e7f9f62ffffb5566901e0a22010ba76641c data/create/advancements/recipes/buildi 466fbdf7de8dacd1032fb7af690862bb68707876 data/create/advancements/recipes/building_blocks/cut_dripstone_brick_stairs_from_stone_types_dripstone_stonecutting.json 253b54c191c933e88fa6a9b4e7c94340082c7d60 data/create/advancements/recipes/building_blocks/cut_dripstone_brick_wall.json e176568e3de8b8ca17a788f4cea89002b5ad2d1d data/create/advancements/recipes/building_blocks/cut_dripstone_brick_wall_from_stone_types_dripstone_stonecutting.json +b60683fdd629b201f40a6f9bb6594df7c5ac13f1 data/create/advancements/recipes/building_blocks/cut_dripstone_bricks_from_stone_types_dripstone_stonecutting.json ddc5a16cf0d2790d8133ab6801f4c55317d776e4 data/create/advancements/recipes/building_blocks/cut_dripstone_from_stone_types_dripstone_stonecutting.json 6e40c9af0747a8b3adb805ddd8fbb947aedb408c data/create/advancements/recipes/building_blocks/cut_dripstone_slab.json e7761f71f797d2e62dc0860cbd5153955b9be86c data/create/advancements/recipes/building_blocks/cut_dripstone_slab_from_stone_types_dripstone_stonecutting.json @@ -2827,7 +2827,6 @@ a199a9f78a44f4313a922b317893c68f743dc1a9 data/create/advancements/recipes/buildi b68a95a565ee9a3aec017431aa5b8cc6fffec3ef data/create/advancements/recipes/building_blocks/cut_dripstone_stairs_from_stone_types_dripstone_stonecutting.json a4287f34f95c008bdf7c0a886d05c3960665147b data/create/advancements/recipes/building_blocks/cut_dripstone_wall.json 76f5d4a6a9895064b15ae0c0f27a138bb3d57dbf data/create/advancements/recipes/building_blocks/cut_dripstone_wall_from_stone_types_dripstone_stonecutting.json -24cc01d592faf2bad57fc9b9a1de52c50d225446 data/create/advancements/recipes/building_blocks/cut_granite_bricks_from_stone_types_granite_stonecutting.json 83148f66dc7418740b6f9b6a660b0b9306d87f7c data/create/advancements/recipes/building_blocks/cut_granite_brick_slab.json d982802fc11848c87022f7bf05cecf090953002a data/create/advancements/recipes/building_blocks/cut_granite_brick_slab_from_stone_types_granite_stonecutting.json 6b8fa161725a4e2106226c3591a23def74398f48 data/create/advancements/recipes/building_blocks/cut_granite_brick_slab_recycling.json @@ -2835,6 +2834,7 @@ ce1c81b730b3acef9673f41769339f7d68385348 data/create/advancements/recipes/buildi e9732e3beaefbc6a457e0c4fd61f17f429f1cd8c data/create/advancements/recipes/building_blocks/cut_granite_brick_stairs_from_stone_types_granite_stonecutting.json 4f403aee2aae6aa0fc334b434cf5ade362153329 data/create/advancements/recipes/building_blocks/cut_granite_brick_wall.json 625c8849b5c07835b49dcb4322ec44586628a700 data/create/advancements/recipes/building_blocks/cut_granite_brick_wall_from_stone_types_granite_stonecutting.json +24cc01d592faf2bad57fc9b9a1de52c50d225446 data/create/advancements/recipes/building_blocks/cut_granite_bricks_from_stone_types_granite_stonecutting.json 07e6f3835c3683f007fd25140d671b668706484d data/create/advancements/recipes/building_blocks/cut_granite_from_stone_types_granite_stonecutting.json 2f33b7f82e977eb3fd0e0283313b1066eadadd18 data/create/advancements/recipes/building_blocks/cut_granite_slab.json a1b406ca98c2ba7d5225afea8463d586fc538428 data/create/advancements/recipes/building_blocks/cut_granite_slab_from_stone_types_granite_stonecutting.json @@ -2843,7 +2843,6 @@ af12a2d8f8bb2382f55135df8cfec00692a65fe3 data/create/advancements/recipes/buildi 284087e07acd28aa869d5433375e412f083108e9 data/create/advancements/recipes/building_blocks/cut_granite_stairs_from_stone_types_granite_stonecutting.json dbfb50c3d5048b1f5d8d74f39c389ecec81392d7 data/create/advancements/recipes/building_blocks/cut_granite_wall.json 6b287be7a900dbd715290b069a89ab226d6cec9c data/create/advancements/recipes/building_blocks/cut_granite_wall_from_stone_types_granite_stonecutting.json -4ef0a018dcf0b470061a4b1dbadc27684d8d467f data/create/advancements/recipes/building_blocks/cut_limestone_bricks_from_stone_types_limestone_stonecutting.json b0ade7dab7eb095f07882e4c19884162f18e704c data/create/advancements/recipes/building_blocks/cut_limestone_brick_slab.json 4fc2dc61d62a394cebc91e36745699eeaee650e7 data/create/advancements/recipes/building_blocks/cut_limestone_brick_slab_from_stone_types_limestone_stonecutting.json b8ec42f06ce9eb696643154d16150a223bd5ec65 data/create/advancements/recipes/building_blocks/cut_limestone_brick_slab_recycling.json @@ -2851,6 +2850,7 @@ d0b19c27309cd45d08a6a0cd779f1930bc2e7469 data/create/advancements/recipes/buildi 9f65617405592d587a940ff7513fcb34ca6ab423 data/create/advancements/recipes/building_blocks/cut_limestone_brick_stairs_from_stone_types_limestone_stonecutting.json 281e2ddcb58b603dea8f305ed6c8ddea98d0d030 data/create/advancements/recipes/building_blocks/cut_limestone_brick_wall.json 7b0ab5095a7d2b3e876a8c8b990161851c1c58c2 data/create/advancements/recipes/building_blocks/cut_limestone_brick_wall_from_stone_types_limestone_stonecutting.json +4ef0a018dcf0b470061a4b1dbadc27684d8d467f data/create/advancements/recipes/building_blocks/cut_limestone_bricks_from_stone_types_limestone_stonecutting.json f8663a45d71c52a3982c75bbfb61653c8d2fd668 data/create/advancements/recipes/building_blocks/cut_limestone_from_stone_types_limestone_stonecutting.json 9e22972cd4f2d673cfcf07a597f6a14402c91913 data/create/advancements/recipes/building_blocks/cut_limestone_slab.json 388a57bb88582eda9fef904a530f72b066d24e7d data/create/advancements/recipes/building_blocks/cut_limestone_slab_from_stone_types_limestone_stonecutting.json @@ -2859,7 +2859,6 @@ f8663a45d71c52a3982c75bbfb61653c8d2fd668 data/create/advancements/recipes/buildi b6dc46dca3fc039fd0fe53ab791731cb085c3b62 data/create/advancements/recipes/building_blocks/cut_limestone_stairs_from_stone_types_limestone_stonecutting.json a9382d5f876542bf4fa8aed605352daca4ad2f6f data/create/advancements/recipes/building_blocks/cut_limestone_wall.json 69d9116786c53cb3155bed4580d4b01bfe638243 data/create/advancements/recipes/building_blocks/cut_limestone_wall_from_stone_types_limestone_stonecutting.json -1f8ee1a91937295484d5c2fe0186a617589c1761 data/create/advancements/recipes/building_blocks/cut_ochrum_bricks_from_stone_types_ochrum_stonecutting.json a51d6ebed8e21e8808ccfbe9f9540291504da59a data/create/advancements/recipes/building_blocks/cut_ochrum_brick_slab.json eb08f00651259f83f6eced0f90dd8df0e9d0d508 data/create/advancements/recipes/building_blocks/cut_ochrum_brick_slab_from_stone_types_ochrum_stonecutting.json a189e0549723cefbd19a147274cd79909dca2b70 data/create/advancements/recipes/building_blocks/cut_ochrum_brick_slab_recycling.json @@ -2867,6 +2866,7 @@ a5dc9e74ad0d18d83bad3aab8c5e2768355a2370 data/create/advancements/recipes/buildi 27a5331727199b8b8f2dd6c581e25d17d12fc1ba data/create/advancements/recipes/building_blocks/cut_ochrum_brick_stairs_from_stone_types_ochrum_stonecutting.json 648e532441c664310047c5c9c78833d2eaea5920 data/create/advancements/recipes/building_blocks/cut_ochrum_brick_wall.json 053256b7b154ba5c10d2483d86658f132296e8f5 data/create/advancements/recipes/building_blocks/cut_ochrum_brick_wall_from_stone_types_ochrum_stonecutting.json +1f8ee1a91937295484d5c2fe0186a617589c1761 data/create/advancements/recipes/building_blocks/cut_ochrum_bricks_from_stone_types_ochrum_stonecutting.json 6abb6e36229685ca26ee31b5db3074a07453435e data/create/advancements/recipes/building_blocks/cut_ochrum_from_stone_types_ochrum_stonecutting.json 0c5e92fb20048fe5d9dcd42e10fd0f9b155c385a data/create/advancements/recipes/building_blocks/cut_ochrum_slab.json 941aba0ff7967d7ea56e1f811aa6bc34d4711796 data/create/advancements/recipes/building_blocks/cut_ochrum_slab_from_stone_types_ochrum_stonecutting.json @@ -2875,7 +2875,6 @@ fa14009e4de8cfdacdbb7679473ce359f2cb85be data/create/advancements/recipes/buildi d50accd7f37bfd9384790bdd727401757f6dc7e4 data/create/advancements/recipes/building_blocks/cut_ochrum_stairs_from_stone_types_ochrum_stonecutting.json ed0a72f6393c0d16240b89241f5bbac7dc003516 data/create/advancements/recipes/building_blocks/cut_ochrum_wall.json cda838f95015b0bf02fc5427e1a69ed6302b7e20 data/create/advancements/recipes/building_blocks/cut_ochrum_wall_from_stone_types_ochrum_stonecutting.json -a51cd5a82d9b30c8a68f7cdf8dd7a6b2f883c27c data/create/advancements/recipes/building_blocks/cut_scorchia_bricks_from_stone_types_scorchia_stonecutting.json ce33e5a98a83dae1f37ad4b3d4ea148de5bcacdf data/create/advancements/recipes/building_blocks/cut_scorchia_brick_slab.json 498825e9e5502a7ec8a1f23bfe998b960d7fc9eb data/create/advancements/recipes/building_blocks/cut_scorchia_brick_slab_from_stone_types_scorchia_stonecutting.json 8ffa08b1b4e4ab37dfbf09d2ec4a37f93c9503cb data/create/advancements/recipes/building_blocks/cut_scorchia_brick_slab_recycling.json @@ -2883,6 +2882,7 @@ ce33e5a98a83dae1f37ad4b3d4ea148de5bcacdf data/create/advancements/recipes/buildi 3c4b45560f446534821da63d4e713088928e5f4a data/create/advancements/recipes/building_blocks/cut_scorchia_brick_stairs_from_stone_types_scorchia_stonecutting.json 2aba76185175fff82898a7a905d3ec4ff448deaa data/create/advancements/recipes/building_blocks/cut_scorchia_brick_wall.json ca1f54af4425df994c6707f00e43b8db3ce66280 data/create/advancements/recipes/building_blocks/cut_scorchia_brick_wall_from_stone_types_scorchia_stonecutting.json +a51cd5a82d9b30c8a68f7cdf8dd7a6b2f883c27c data/create/advancements/recipes/building_blocks/cut_scorchia_bricks_from_stone_types_scorchia_stonecutting.json df847f312960866d3d53f48297ea3169c27314eb data/create/advancements/recipes/building_blocks/cut_scorchia_from_stone_types_scorchia_stonecutting.json 8095f7be8aac4f11d618549680d537bed8a921c5 data/create/advancements/recipes/building_blocks/cut_scorchia_slab.json a53831cf7f095fa4d0d92051bd0e21f912c2d9dd data/create/advancements/recipes/building_blocks/cut_scorchia_slab_from_stone_types_scorchia_stonecutting.json @@ -2891,7 +2891,6 @@ a53831cf7f095fa4d0d92051bd0e21f912c2d9dd data/create/advancements/recipes/buildi 30f1efaa46771dd22d7f3aa34f24c69bbdb59bd5 data/create/advancements/recipes/building_blocks/cut_scorchia_stairs_from_stone_types_scorchia_stonecutting.json e02d188d64b270682fa9d335a3423880d8358a0d data/create/advancements/recipes/building_blocks/cut_scorchia_wall.json 834c5a2a8d089822fa81a75b290818db276beab7 data/create/advancements/recipes/building_blocks/cut_scorchia_wall_from_stone_types_scorchia_stonecutting.json -2030ec21c96336bd4c4040857f40ec65d1a75075 data/create/advancements/recipes/building_blocks/cut_scoria_bricks_from_stone_types_scoria_stonecutting.json 705dfcd9f4b6b8a0c360436c097cb371c27cf60d data/create/advancements/recipes/building_blocks/cut_scoria_brick_slab.json 482cf1bbb65a4facc0ebf31ea91bab4d03580635 data/create/advancements/recipes/building_blocks/cut_scoria_brick_slab_from_stone_types_scoria_stonecutting.json 51d070acfc8ad4cd8ca4457ca346458c81eaade4 data/create/advancements/recipes/building_blocks/cut_scoria_brick_slab_recycling.json @@ -2899,6 +2898,7 @@ e02d188d64b270682fa9d335a3423880d8358a0d data/create/advancements/recipes/buildi 99ca117e6a4ad242d92566a2f398c28edb3b7061 data/create/advancements/recipes/building_blocks/cut_scoria_brick_stairs_from_stone_types_scoria_stonecutting.json 01e294976d8ce71b59fb14a47e2686bdce4fab21 data/create/advancements/recipes/building_blocks/cut_scoria_brick_wall.json 0c1d31d37a17d4bd752508022ddd9690bb92a521 data/create/advancements/recipes/building_blocks/cut_scoria_brick_wall_from_stone_types_scoria_stonecutting.json +2030ec21c96336bd4c4040857f40ec65d1a75075 data/create/advancements/recipes/building_blocks/cut_scoria_bricks_from_stone_types_scoria_stonecutting.json 41f420c88dbf61d3cb51966cca9b495d10c604d3 data/create/advancements/recipes/building_blocks/cut_scoria_from_stone_types_scoria_stonecutting.json 26c8447854e29243f0697236f59e258fa96ed369 data/create/advancements/recipes/building_blocks/cut_scoria_slab.json f3e2522664de4ff2ad92a89443e064ac857b7aef data/create/advancements/recipes/building_blocks/cut_scoria_slab_from_stone_types_scoria_stonecutting.json @@ -2907,7 +2907,6 @@ a0635452fd698415e8112e9e0f6d71571901ca34 data/create/advancements/recipes/buildi 1bb047298b71a57e8632607af7b17bab2690aecb data/create/advancements/recipes/building_blocks/cut_scoria_stairs_from_stone_types_scoria_stonecutting.json a33878fe778438a746a28c1fd03ca6d01092ebe4 data/create/advancements/recipes/building_blocks/cut_scoria_wall.json 74a637d0d0f360ad692661c0213c18a06a8ec500 data/create/advancements/recipes/building_blocks/cut_scoria_wall_from_stone_types_scoria_stonecutting.json -f0870d596d9ac9e5b5272fb4e3d2c90c29f3a63d data/create/advancements/recipes/building_blocks/cut_tuff_bricks_from_stone_types_tuff_stonecutting.json b75410afdb8775b2a834ded315913e0ae38e4df8 data/create/advancements/recipes/building_blocks/cut_tuff_brick_slab.json 34c2aead2f2355a8f0f9f9aa7dba58dd5187dbba data/create/advancements/recipes/building_blocks/cut_tuff_brick_slab_from_stone_types_tuff_stonecutting.json c071c43e93cc1735bebbbf320f1b8d2cba4be1e3 data/create/advancements/recipes/building_blocks/cut_tuff_brick_slab_recycling.json @@ -2915,6 +2914,7 @@ c89ec2300425688f9e72e45c64def0b09c0219b0 data/create/advancements/recipes/buildi c882f72f5a31bc92a8186834b105a2e07d864366 data/create/advancements/recipes/building_blocks/cut_tuff_brick_stairs_from_stone_types_tuff_stonecutting.json 70295775a6170a1332f5604aaf75a026630c9e93 data/create/advancements/recipes/building_blocks/cut_tuff_brick_wall.json 1b79d0e71dae77967c1554c203e68eeb51fe8054 data/create/advancements/recipes/building_blocks/cut_tuff_brick_wall_from_stone_types_tuff_stonecutting.json +f0870d596d9ac9e5b5272fb4e3d2c90c29f3a63d data/create/advancements/recipes/building_blocks/cut_tuff_bricks_from_stone_types_tuff_stonecutting.json 549d1f911c009a3cafff4edcb37116c92c2b8e21 data/create/advancements/recipes/building_blocks/cut_tuff_from_stone_types_tuff_stonecutting.json 5bc3e40a8e50a521ebd5fa58efa3ec21064163f7 data/create/advancements/recipes/building_blocks/cut_tuff_slab.json f1ab5be6cb7287517d87b173680ddf833a1dd534 data/create/advancements/recipes/building_blocks/cut_tuff_slab_from_stone_types_tuff_stonecutting.json @@ -2923,7 +2923,6 @@ b7d19085017530f0c2122511c35dbef6a50b337f data/create/advancements/recipes/buildi 3c9541b6e4eb8ff7f7b627a75e8c38ed9eeaf342 data/create/advancements/recipes/building_blocks/cut_tuff_stairs_from_stone_types_tuff_stonecutting.json 51ca798b8bd822ddbbfe8f07073eefb948b97b42 data/create/advancements/recipes/building_blocks/cut_tuff_wall.json 1aa1a0d00c19069f0c55e698b474115d7f437355 data/create/advancements/recipes/building_blocks/cut_tuff_wall_from_stone_types_tuff_stonecutting.json -6a80920618d8e9b7919c83c419e751971440d38a data/create/advancements/recipes/building_blocks/cut_veridium_bricks_from_stone_types_veridium_stonecutting.json e263f555c3a47c83187d29ae9b816edc0c1a763b data/create/advancements/recipes/building_blocks/cut_veridium_brick_slab.json f0e84bde804e52f504cd93bee5058a89f6939dc9 data/create/advancements/recipes/building_blocks/cut_veridium_brick_slab_from_stone_types_veridium_stonecutting.json 949fe819c76fd63edfd93bef5898119c8456fda3 data/create/advancements/recipes/building_blocks/cut_veridium_brick_slab_recycling.json @@ -2931,6 +2930,7 @@ fc87560dedbc951d10d9650a6f27192e7c3a1cc5 data/create/advancements/recipes/buildi 35b09d6300ff8e86f01bc0258fca5cfa80d55c61 data/create/advancements/recipes/building_blocks/cut_veridium_brick_stairs_from_stone_types_veridium_stonecutting.json 599d9ce510531c6006a4964bb4049a850a8457ee data/create/advancements/recipes/building_blocks/cut_veridium_brick_wall.json aaaad7a65a1c05071565ca91a181ff3c375e0141 data/create/advancements/recipes/building_blocks/cut_veridium_brick_wall_from_stone_types_veridium_stonecutting.json +6a80920618d8e9b7919c83c419e751971440d38a data/create/advancements/recipes/building_blocks/cut_veridium_bricks_from_stone_types_veridium_stonecutting.json c76ae7944646e8f13ea460ba6655b95b6c2798ea data/create/advancements/recipes/building_blocks/cut_veridium_from_stone_types_veridium_stonecutting.json 3bafa8873b62cb0333b44af77f2c6e824c5b3e95 data/create/advancements/recipes/building_blocks/cut_veridium_slab.json 143f64b0e5536693262f6a62c2a6fbf85bd4203e data/create/advancements/recipes/building_blocks/cut_veridium_slab_from_stone_types_veridium_stonecutting.json @@ -3116,7 +3116,6 @@ c4c087911453bd979e028d3b3558b273e3cb5926 data/create/advancements/recipes/buildi 780bb3d13fcd8abf6e166b04566b141e023ee11e data/create/advancements/recipes/building_blocks/scorchia_pillar_from_stone_types_scorchia_stonecutting.json 5c5c5080c1136c046caee2d14dd2c3c9f09abad3 data/create/advancements/recipes/building_blocks/scoria_from_stone_types_scoria_stonecutting.json 5a6b12869ffcbd1d9b4fbe1fee444fcde95d2953 data/create/advancements/recipes/building_blocks/scoria_pillar_from_stone_types_scoria_stonecutting.json -a51ca3151c517113338720edeac0e02a46ebb03a data/create/advancements/recipes/building_blocks/small_andesite_bricks_from_stone_types_andesite_stonecutting.json f72093994236a0580c6cafd08fb42f061733de01 data/create/advancements/recipes/building_blocks/small_andesite_brick_slab.json 05092201e6c514d3eae566fb1ce98ad415660112 data/create/advancements/recipes/building_blocks/small_andesite_brick_slab_from_stone_types_andesite_stonecutting.json 0e41d75b613a0ebd0c023669dcfd34f11b14fd0e data/create/advancements/recipes/building_blocks/small_andesite_brick_slab_recycling.json @@ -3124,7 +3123,7 @@ f72093994236a0580c6cafd08fb42f061733de01 data/create/advancements/recipes/buildi 8bbf898cbc47ac7a326c0d082a92a452b6915a7e data/create/advancements/recipes/building_blocks/small_andesite_brick_stairs_from_stone_types_andesite_stonecutting.json 9e0685dd668550c67812d1caccd8c8cae9f2041c data/create/advancements/recipes/building_blocks/small_andesite_brick_wall.json 7a1bfa848f950482f82d7fe7a9cf3cf916f91702 data/create/advancements/recipes/building_blocks/small_andesite_brick_wall_from_stone_types_andesite_stonecutting.json -0bfa788d0038077a88678ff16104a8b82038b3da data/create/advancements/recipes/building_blocks/small_asurine_bricks_from_stone_types_asurine_stonecutting.json +a51ca3151c517113338720edeac0e02a46ebb03a data/create/advancements/recipes/building_blocks/small_andesite_bricks_from_stone_types_andesite_stonecutting.json 3dccee988c08e1988886d9f09f2b5b42332ac083 data/create/advancements/recipes/building_blocks/small_asurine_brick_slab.json 438469fb06dff95a0ab9e0cb183795432d9b78dd data/create/advancements/recipes/building_blocks/small_asurine_brick_slab_from_stone_types_asurine_stonecutting.json 3eb65706d975e6f1e429f43d7384272a58872f10 data/create/advancements/recipes/building_blocks/small_asurine_brick_slab_recycling.json @@ -3132,7 +3131,7 @@ fb8cab1a3ecef97eaf7d744bb0d1d09d46859b60 data/create/advancements/recipes/buildi 525fff52f5dea3178356b7c5f7606d2a369b346e data/create/advancements/recipes/building_blocks/small_asurine_brick_stairs_from_stone_types_asurine_stonecutting.json 39df7ef2b88df45ba4a06bfa9cd7f863f813cb30 data/create/advancements/recipes/building_blocks/small_asurine_brick_wall.json 21aa9dc72b12eb0a33cdc9904ee595de802b55f4 data/create/advancements/recipes/building_blocks/small_asurine_brick_wall_from_stone_types_asurine_stonecutting.json -46666ef8d341971cdd989f14575973777a85cdc6 data/create/advancements/recipes/building_blocks/small_calcite_bricks_from_stone_types_calcite_stonecutting.json +0bfa788d0038077a88678ff16104a8b82038b3da data/create/advancements/recipes/building_blocks/small_asurine_bricks_from_stone_types_asurine_stonecutting.json d61fce64a295a2c3b9433bc27ac50f4f1f6a678d data/create/advancements/recipes/building_blocks/small_calcite_brick_slab.json 7f2e73d01b9bff473c4ecf76ab967b3aa934ff87 data/create/advancements/recipes/building_blocks/small_calcite_brick_slab_from_stone_types_calcite_stonecutting.json 1095487af055116acc2eba87d92dd0918385e9ac data/create/advancements/recipes/building_blocks/small_calcite_brick_slab_recycling.json @@ -3140,7 +3139,7 @@ d61fce64a295a2c3b9433bc27ac50f4f1f6a678d data/create/advancements/recipes/buildi e3bd0900dc92b26fe69c7f4e81db76678505222b data/create/advancements/recipes/building_blocks/small_calcite_brick_stairs_from_stone_types_calcite_stonecutting.json c88fb3af07c32aa127cbe0043075f50fed869839 data/create/advancements/recipes/building_blocks/small_calcite_brick_wall.json ea58b78e177134c73ed5bfb081761f90cc7caa3e data/create/advancements/recipes/building_blocks/small_calcite_brick_wall_from_stone_types_calcite_stonecutting.json -c48216f26cfe93ce99f7f2f0e9f68d1ee2a95e46 data/create/advancements/recipes/building_blocks/small_crimsite_bricks_from_stone_types_crimsite_stonecutting.json +46666ef8d341971cdd989f14575973777a85cdc6 data/create/advancements/recipes/building_blocks/small_calcite_bricks_from_stone_types_calcite_stonecutting.json ed4d6e7779749dd647f744f0486e78b93057aa33 data/create/advancements/recipes/building_blocks/small_crimsite_brick_slab.json 7f3ad6d79eb9d433d5a0e295eb2b099a5f815876 data/create/advancements/recipes/building_blocks/small_crimsite_brick_slab_from_stone_types_crimsite_stonecutting.json b980fcc4b29f9ff897dd867222fc4248d76e808a data/create/advancements/recipes/building_blocks/small_crimsite_brick_slab_recycling.json @@ -3148,7 +3147,7 @@ b980fcc4b29f9ff897dd867222fc4248d76e808a data/create/advancements/recipes/buildi c06600eda4e4bd7c46e4e315a0569fbdfa4bb087 data/create/advancements/recipes/building_blocks/small_crimsite_brick_stairs_from_stone_types_crimsite_stonecutting.json 4021a4a761b06def09f19d6a60bc0722e69ec08d data/create/advancements/recipes/building_blocks/small_crimsite_brick_wall.json 2d8eae517a914e93538307efe23d532582d487e2 data/create/advancements/recipes/building_blocks/small_crimsite_brick_wall_from_stone_types_crimsite_stonecutting.json -ed82f0fac452147faa997af1d45278f501ef165b data/create/advancements/recipes/building_blocks/small_deepslate_bricks_from_stone_types_deepslate_stonecutting.json +c48216f26cfe93ce99f7f2f0e9f68d1ee2a95e46 data/create/advancements/recipes/building_blocks/small_crimsite_bricks_from_stone_types_crimsite_stonecutting.json e4674821cc17adadecacc55d48c028847caf5fea data/create/advancements/recipes/building_blocks/small_deepslate_brick_slab.json 8c0c51d052b110fec3668618be2bdeaf8d0c7cc5 data/create/advancements/recipes/building_blocks/small_deepslate_brick_slab_from_stone_types_deepslate_stonecutting.json f8f7ace802b6c73fabfabbaae1c1383a3c0bcf6b data/create/advancements/recipes/building_blocks/small_deepslate_brick_slab_recycling.json @@ -3156,7 +3155,7 @@ e2e16c3c0e761ef44f9b21ae3bd95300a33459be data/create/advancements/recipes/buildi 37ef4192f1db7dd5c066a47480f86f60687c9894 data/create/advancements/recipes/building_blocks/small_deepslate_brick_stairs_from_stone_types_deepslate_stonecutting.json 6f4d365ce26fb4081a5af0f6e21631209b5b106d data/create/advancements/recipes/building_blocks/small_deepslate_brick_wall.json e0c7377c55dc94b8efd62cb6f57325c94206cbf4 data/create/advancements/recipes/building_blocks/small_deepslate_brick_wall_from_stone_types_deepslate_stonecutting.json -9bb23924495112ba177d12ba2a5adcb872a2b76f data/create/advancements/recipes/building_blocks/small_diorite_bricks_from_stone_types_diorite_stonecutting.json +ed82f0fac452147faa997af1d45278f501ef165b data/create/advancements/recipes/building_blocks/small_deepslate_bricks_from_stone_types_deepslate_stonecutting.json d4b96bcd8902e9bce19603abb99cb7edeb260189 data/create/advancements/recipes/building_blocks/small_diorite_brick_slab.json 2ed3800996491c9a1db23d9cbed04cc5ee963df6 data/create/advancements/recipes/building_blocks/small_diorite_brick_slab_from_stone_types_diorite_stonecutting.json 895d2158ba0783c5fd97b802ef5866d7532df6ba data/create/advancements/recipes/building_blocks/small_diorite_brick_slab_recycling.json @@ -3164,7 +3163,7 @@ d4b96bcd8902e9bce19603abb99cb7edeb260189 data/create/advancements/recipes/buildi 0f4b92965c05ddf71fa24b2b08a0cce358ac8dd1 data/create/advancements/recipes/building_blocks/small_diorite_brick_stairs_from_stone_types_diorite_stonecutting.json 633d921515fb4ad0e3177f3c8f151da80008053b data/create/advancements/recipes/building_blocks/small_diorite_brick_wall.json 3dea60492331bcd3253d90534559cc0bdb0822ae data/create/advancements/recipes/building_blocks/small_diorite_brick_wall_from_stone_types_diorite_stonecutting.json -632ced3760d55b56d1620e447b8b762e0e4a29f3 data/create/advancements/recipes/building_blocks/small_dripstone_bricks_from_stone_types_dripstone_stonecutting.json +9bb23924495112ba177d12ba2a5adcb872a2b76f data/create/advancements/recipes/building_blocks/small_diorite_bricks_from_stone_types_diorite_stonecutting.json 92bb21a400d9720a2f06882049d5b3863a93969d data/create/advancements/recipes/building_blocks/small_dripstone_brick_slab.json 02e2b98eeef9cdc20a8678beec4c7aa8a6cde948 data/create/advancements/recipes/building_blocks/small_dripstone_brick_slab_from_stone_types_dripstone_stonecutting.json 35830242bc48b1355830d6cb17dc4dc547d51bc0 data/create/advancements/recipes/building_blocks/small_dripstone_brick_slab_recycling.json @@ -3172,7 +3171,7 @@ d4b96bcd8902e9bce19603abb99cb7edeb260189 data/create/advancements/recipes/buildi 92523f3058a580743f95e9347fa97e0f5f6483f6 data/create/advancements/recipes/building_blocks/small_dripstone_brick_stairs_from_stone_types_dripstone_stonecutting.json 6e26ab4ad96225b7dd1a4aa06295b0d85e87400b data/create/advancements/recipes/building_blocks/small_dripstone_brick_wall.json e30a5f31d6478dfe7693077727b1abfc40b33f9b data/create/advancements/recipes/building_blocks/small_dripstone_brick_wall_from_stone_types_dripstone_stonecutting.json -1805b7f9db21b4530b173ab6945584e7d852b218 data/create/advancements/recipes/building_blocks/small_granite_bricks_from_stone_types_granite_stonecutting.json +632ced3760d55b56d1620e447b8b762e0e4a29f3 data/create/advancements/recipes/building_blocks/small_dripstone_bricks_from_stone_types_dripstone_stonecutting.json a2929bbd4c81b9601aeca74110936343102b7b5a data/create/advancements/recipes/building_blocks/small_granite_brick_slab.json 0fa83c337d5612e2b8368d5bff34117e0c1cf40a data/create/advancements/recipes/building_blocks/small_granite_brick_slab_from_stone_types_granite_stonecutting.json 0bc47cb22cc70a34879092a57c87551e6fa9f634 data/create/advancements/recipes/building_blocks/small_granite_brick_slab_recycling.json @@ -3180,7 +3179,7 @@ a2929bbd4c81b9601aeca74110936343102b7b5a data/create/advancements/recipes/buildi 44f3e71a4e8b78db74a21a42c3cebfbc15fe0180 data/create/advancements/recipes/building_blocks/small_granite_brick_stairs_from_stone_types_granite_stonecutting.json 3a6edafcb559e767caf421cf1bd6e064940f33e2 data/create/advancements/recipes/building_blocks/small_granite_brick_wall.json cac9914c729c0ecf5e9e1b4fe6498005e7c532f3 data/create/advancements/recipes/building_blocks/small_granite_brick_wall_from_stone_types_granite_stonecutting.json -1ca86b11356749caf7515fc61b8ac5de53d019f6 data/create/advancements/recipes/building_blocks/small_limestone_bricks_from_stone_types_limestone_stonecutting.json +1805b7f9db21b4530b173ab6945584e7d852b218 data/create/advancements/recipes/building_blocks/small_granite_bricks_from_stone_types_granite_stonecutting.json 4f3cc93f422ee9f05587b89d6729a6cc86f572c0 data/create/advancements/recipes/building_blocks/small_limestone_brick_slab.json 02d0c45cd014fd660a9d3eb1c1c6b40ba806b2fb data/create/advancements/recipes/building_blocks/small_limestone_brick_slab_from_stone_types_limestone_stonecutting.json 8fb46bce94f6cca943e4ae427c04d9617ada277d data/create/advancements/recipes/building_blocks/small_limestone_brick_slab_recycling.json @@ -3188,7 +3187,7 @@ cac9914c729c0ecf5e9e1b4fe6498005e7c532f3 data/create/advancements/recipes/buildi 00b61a4d23f8b16a7e4d9bf46fbe52c6b5dd561c data/create/advancements/recipes/building_blocks/small_limestone_brick_stairs_from_stone_types_limestone_stonecutting.json 7c6b80f174687efe10007c0235f2a68db7062b12 data/create/advancements/recipes/building_blocks/small_limestone_brick_wall.json 7f9ade635dcda8d5baae2bbdddc018bcc715f681 data/create/advancements/recipes/building_blocks/small_limestone_brick_wall_from_stone_types_limestone_stonecutting.json -bab018a0adcbc0582ba756158941a87923b20384 data/create/advancements/recipes/building_blocks/small_ochrum_bricks_from_stone_types_ochrum_stonecutting.json +1ca86b11356749caf7515fc61b8ac5de53d019f6 data/create/advancements/recipes/building_blocks/small_limestone_bricks_from_stone_types_limestone_stonecutting.json 9c98b7b56f92f6adc75473f5b0ae4dc69ac8aa9a data/create/advancements/recipes/building_blocks/small_ochrum_brick_slab.json 611fb57772f1446236256f1235751dec6f81cd0e data/create/advancements/recipes/building_blocks/small_ochrum_brick_slab_from_stone_types_ochrum_stonecutting.json 243821a2c3e465f5346ad58e0afda624c09ab946 data/create/advancements/recipes/building_blocks/small_ochrum_brick_slab_recycling.json @@ -3196,8 +3195,8 @@ b9a16792e6158a2923454c9a44d9c176c9607c24 data/create/advancements/recipes/buildi bb91a8ba1ef1c8cb725f18a4d577bb476b9ae68d data/create/advancements/recipes/building_blocks/small_ochrum_brick_stairs_from_stone_types_ochrum_stonecutting.json 5cf5574da0b29895960fa7f0fd63d3f81814f7b3 data/create/advancements/recipes/building_blocks/small_ochrum_brick_wall.json 1b5d14c921a85a3a5cdb9f845d4f0ddf98f87347 data/create/advancements/recipes/building_blocks/small_ochrum_brick_wall_from_stone_types_ochrum_stonecutting.json +bab018a0adcbc0582ba756158941a87923b20384 data/create/advancements/recipes/building_blocks/small_ochrum_bricks_from_stone_types_ochrum_stonecutting.json 8d6ccacf1af917094b1688ed70dc75bf54611e93 data/create/advancements/recipes/building_blocks/small_rose_quartz_tiles_from_polished_rose_quartz_stonecutting.json -7d679c66588f8a717619a7f89861d57ec04f04a1 data/create/advancements/recipes/building_blocks/small_scorchia_bricks_from_stone_types_scorchia_stonecutting.json 2003f1248faaeb4fe6761febda8e29d087f99dc7 data/create/advancements/recipes/building_blocks/small_scorchia_brick_slab.json ff5c50697aefe21c1570230a13255c912744b629 data/create/advancements/recipes/building_blocks/small_scorchia_brick_slab_from_stone_types_scorchia_stonecutting.json 8d1fd41b03940add231fa207d3ddaa1f78cf2b85 data/create/advancements/recipes/building_blocks/small_scorchia_brick_slab_recycling.json @@ -3205,7 +3204,7 @@ ff5c50697aefe21c1570230a13255c912744b629 data/create/advancements/recipes/buildi 8586f387cc9bb74250369373348005f6aa686af2 data/create/advancements/recipes/building_blocks/small_scorchia_brick_stairs_from_stone_types_scorchia_stonecutting.json 94552be031c17f5ef9d97cf5fe33beb15141291f data/create/advancements/recipes/building_blocks/small_scorchia_brick_wall.json 86e866f92095b03b5d77a91425e5e2ef307f4852 data/create/advancements/recipes/building_blocks/small_scorchia_brick_wall_from_stone_types_scorchia_stonecutting.json -e542cd94f84a90530332608b1040e2e6189a51fe data/create/advancements/recipes/building_blocks/small_scoria_bricks_from_stone_types_scoria_stonecutting.json +7d679c66588f8a717619a7f89861d57ec04f04a1 data/create/advancements/recipes/building_blocks/small_scorchia_bricks_from_stone_types_scorchia_stonecutting.json ad4c35afd6c3d55b356e38289c64e8cf6d194d10 data/create/advancements/recipes/building_blocks/small_scoria_brick_slab.json 2f1acca02bb5a40bf174ceeb5272ba1243b8635c data/create/advancements/recipes/building_blocks/small_scoria_brick_slab_from_stone_types_scoria_stonecutting.json dba264e073eab7b2fb1494cb117574b6a6b83919 data/create/advancements/recipes/building_blocks/small_scoria_brick_slab_recycling.json @@ -3213,7 +3212,7 @@ dba264e073eab7b2fb1494cb117574b6a6b83919 data/create/advancements/recipes/buildi 0e64e1dc80a0b84e05260191951ed930a8e578f6 data/create/advancements/recipes/building_blocks/small_scoria_brick_stairs_from_stone_types_scoria_stonecutting.json 95b866fac218affb9aac93272f5436e30dd4678c data/create/advancements/recipes/building_blocks/small_scoria_brick_wall.json 23493359766c969d2fa64575c5af047e6a924373 data/create/advancements/recipes/building_blocks/small_scoria_brick_wall_from_stone_types_scoria_stonecutting.json -b7fc4fbd0d6ce28946b5cbef40d86de3ca37f695 data/create/advancements/recipes/building_blocks/small_tuff_bricks_from_stone_types_tuff_stonecutting.json +e542cd94f84a90530332608b1040e2e6189a51fe data/create/advancements/recipes/building_blocks/small_scoria_bricks_from_stone_types_scoria_stonecutting.json 03acb1becaa3c7f6fc0ced99e6afcf4ac0ec4cb2 data/create/advancements/recipes/building_blocks/small_tuff_brick_slab.json 599693bc47bfd65cc9e3babc0a2f33c0d2bbfd31 data/create/advancements/recipes/building_blocks/small_tuff_brick_slab_from_stone_types_tuff_stonecutting.json aae2cb75ee4b9312e79dfea519c35f5e20ed4da6 data/create/advancements/recipes/building_blocks/small_tuff_brick_slab_recycling.json @@ -3221,7 +3220,7 @@ c72364e32b82f45f17491dd41967373c35d8dfb5 data/create/advancements/recipes/buildi 369763433d6af43d94392e870b3d861f739ba0f9 data/create/advancements/recipes/building_blocks/small_tuff_brick_stairs_from_stone_types_tuff_stonecutting.json 506bbae420bff66d492214c49dabf52e5cbcf6e4 data/create/advancements/recipes/building_blocks/small_tuff_brick_wall.json 6db7e4b981ec28c776988a531c03dbe28fb0a1c2 data/create/advancements/recipes/building_blocks/small_tuff_brick_wall_from_stone_types_tuff_stonecutting.json -9fd6e20a4555b591b17ef225316782de333780fa data/create/advancements/recipes/building_blocks/small_veridium_bricks_from_stone_types_veridium_stonecutting.json +b7fc4fbd0d6ce28946b5cbef40d86de3ca37f695 data/create/advancements/recipes/building_blocks/small_tuff_bricks_from_stone_types_tuff_stonecutting.json b61a773f683c415617a408fa0781e7e7d61cb1af data/create/advancements/recipes/building_blocks/small_veridium_brick_slab.json 526a5323263292bd091c03231a156e18460c34a1 data/create/advancements/recipes/building_blocks/small_veridium_brick_slab_from_stone_types_veridium_stonecutting.json ef040b7189b17cce9dd69c47af61c7abca6f43cd data/create/advancements/recipes/building_blocks/small_veridium_brick_slab_recycling.json @@ -3229,6 +3228,7 @@ ef040b7189b17cce9dd69c47af61c7abca6f43cd data/create/advancements/recipes/buildi 6a12b73815434a544881680cb071f273a75f62a5 data/create/advancements/recipes/building_blocks/small_veridium_brick_stairs_from_stone_types_veridium_stonecutting.json e6dfacd8f2f57d4df42927783750254f7163251a data/create/advancements/recipes/building_blocks/small_veridium_brick_wall.json ee4012cc014539be113ace8f80e51c85d2daead9 data/create/advancements/recipes/building_blocks/small_veridium_brick_wall_from_stone_types_veridium_stonecutting.json +9fd6e20a4555b591b17ef225316782de333780fa data/create/advancements/recipes/building_blocks/small_veridium_bricks_from_stone_types_veridium_stonecutting.json 03a87030672d40b0b2b6ad085103c9a5cef067ce data/create/advancements/recipes/building_blocks/spruce_window.json dfea65f25ebcbe0caf2694dec3d3ea616e2e9291 data/create/advancements/recipes/building_blocks/spruce_window_pane.json 763b3b49296a284f41cbccdc7f1ffb13c89d42db data/create/advancements/recipes/building_blocks/tiled_glass_from_glass_colorless_stonecutting.json @@ -3382,13 +3382,13 @@ fa0856e11351ad0882de2066569807e782071881 data/create/loot_tables/blocks/copper_b 0937b9f634b86dbe41e07eda52c69993fce60fb5 data/create/loot_tables/blocks/copper_door.json 8ed70d812f38adfa147db07a4f2bbe206a69ad20 data/create/loot_tables/blocks/copper_ladder.json ac621731ca23e6fbb1003be59edacdf837dbc37e data/create/loot_tables/blocks/copper_scaffolding.json -9be387731859ccc3aec7701c1804ddc3c5dde216 data/create/loot_tables/blocks/copper_shingles.json be31f0c68bfe80dff88959bd30ef9a9080dd3b3b data/create/loot_tables/blocks/copper_shingle_slab.json 83ae2652a2df217730d6fb34a65c3962e82a961d data/create/loot_tables/blocks/copper_shingle_stairs.json +9be387731859ccc3aec7701c1804ddc3c5dde216 data/create/loot_tables/blocks/copper_shingles.json f6a29868a011d9ad73bc29be94ec2a07a2626323 data/create/loot_tables/blocks/copper_table_cloth.json -9cb359c96543d7421250c4ef4e83a5e170974efb data/create/loot_tables/blocks/copper_tiles.json adbe83d6bf88dd7d2b0b8788bb619cedd37f59d9 data/create/loot_tables/blocks/copper_tile_slab.json 1e06f16b1fa8e78af5cbfc90ba8ff1136de83d2d data/create/loot_tables/blocks/copper_tile_stairs.json +9cb359c96543d7421250c4ef4e83a5e170974efb data/create/loot_tables/blocks/copper_tiles.json 4f75cad20e6b091d1f07cf3db98520d2dc3af5e7 data/create/loot_tables/blocks/copper_valve_handle.json 14a493a7bad6bd399b662da470b71810bd56e812 data/create/loot_tables/blocks/copycat_bars.json 3a2f3ab0834a0c5089ba0a11f5e9784ce59ef6d8 data/create/loot_tables/blocks/copycat_base.json @@ -3404,114 +3404,114 @@ d5d2f565bab2e2b81b0798fc7ce0e21acd362ce5 data/create/loot_tables/blocks/crimson_ b892718d33caf0c260b902c92f46f3bfd827af45 data/create/loot_tables/blocks/crushing_wheel.json ff7853a5d5c0f3bddbcfe07e47efd1ff04b14f0a data/create/loot_tables/blocks/cuckoo_clock.json 9083b026ee254645430434b67c2ba7a842f888bf data/create/loot_tables/blocks/cut_andesite.json -c1aa69f80ba11dd52fb3627fc32377599f5ff887 data/create/loot_tables/blocks/cut_andesite_bricks.json c74a4cac08ab1f66146466ff9fb40c8f210de63c data/create/loot_tables/blocks/cut_andesite_brick_slab.json df3f5dcbf676106800bc1113bb022658eb5e85d6 data/create/loot_tables/blocks/cut_andesite_brick_stairs.json 95c5a4a3327f522d986d7baaa747fce5ead8c032 data/create/loot_tables/blocks/cut_andesite_brick_wall.json +c1aa69f80ba11dd52fb3627fc32377599f5ff887 data/create/loot_tables/blocks/cut_andesite_bricks.json cb6cf8aefaac1e00596bd64a182a329dbba7e659 data/create/loot_tables/blocks/cut_andesite_slab.json 7106a637809dcbeb9d4a02a7ff9dc52f7fd9d7a2 data/create/loot_tables/blocks/cut_andesite_stairs.json e3cfa2ecb0b90ebe07cc98f8e47d22d2c0da67e5 data/create/loot_tables/blocks/cut_andesite_wall.json 75eacbc0656e7a83a20a054755ea7d7d78af983d data/create/loot_tables/blocks/cut_asurine.json -f780d37b956ed734cafcbe42b77f1a8ebfa33350 data/create/loot_tables/blocks/cut_asurine_bricks.json 43ad24bb9da878111f3606a17ef9b45bcc4964ae data/create/loot_tables/blocks/cut_asurine_brick_slab.json 8f4d0af32546b6cc77c68a08dc74494b8be1b7c3 data/create/loot_tables/blocks/cut_asurine_brick_stairs.json bb9ce58aa5b4e38c4d3b29aa8e0d905054023eae data/create/loot_tables/blocks/cut_asurine_brick_wall.json +f780d37b956ed734cafcbe42b77f1a8ebfa33350 data/create/loot_tables/blocks/cut_asurine_bricks.json 972ca04f91a1ce4d35995c14e1b17f773b15b61e data/create/loot_tables/blocks/cut_asurine_slab.json a55778dd8735286c3abc65046186b6b8dff0367e data/create/loot_tables/blocks/cut_asurine_stairs.json 70284c686f16d215ff1a8fb19bbe36fddbd31e18 data/create/loot_tables/blocks/cut_asurine_wall.json 0f450ecf60c5d201f332b2736c552d0b51b159b8 data/create/loot_tables/blocks/cut_calcite.json -aec526af372816f306826eefe4a6318db7964892 data/create/loot_tables/blocks/cut_calcite_bricks.json ec0d2854433ac4f58e53685c69dc19629fee16ca data/create/loot_tables/blocks/cut_calcite_brick_slab.json 584e39fa0b78ba8649f69b53f9f032dd1532d6ac data/create/loot_tables/blocks/cut_calcite_brick_stairs.json cc9cbdb7a50305e47181b2452bfce887f9879437 data/create/loot_tables/blocks/cut_calcite_brick_wall.json +aec526af372816f306826eefe4a6318db7964892 data/create/loot_tables/blocks/cut_calcite_bricks.json b4e5b6d5cb63b7b1a4fe639fd727a381bfd00588 data/create/loot_tables/blocks/cut_calcite_slab.json ca83b89401dba12341e6f26786103c10c90447ca data/create/loot_tables/blocks/cut_calcite_stairs.json 64df1c4a373c28bf9be3630935b01a43abd22e03 data/create/loot_tables/blocks/cut_calcite_wall.json 5df3a2229657d7b616790e922b1d1d558b4a5128 data/create/loot_tables/blocks/cut_crimsite.json -59cb609bc9671ac481832eeaf942533c6861fc0e data/create/loot_tables/blocks/cut_crimsite_bricks.json 6fee8d6425e1c832abed8fd9bccc8e6fae9441fc data/create/loot_tables/blocks/cut_crimsite_brick_slab.json 3123bc9e6123dfeda9bb3cece5c2220ac8485535 data/create/loot_tables/blocks/cut_crimsite_brick_stairs.json 56a8c7b1588f6fa9a1fb438e91b04673e02a0c86 data/create/loot_tables/blocks/cut_crimsite_brick_wall.json +59cb609bc9671ac481832eeaf942533c6861fc0e data/create/loot_tables/blocks/cut_crimsite_bricks.json 90ed82b09f2650ee913956d62803d15fc4c0bdbd data/create/loot_tables/blocks/cut_crimsite_slab.json 0e237e008523ed3e9934c598a708be533aaa0861 data/create/loot_tables/blocks/cut_crimsite_stairs.json 48e1edca75186f160a12fa26ac262c7f86d62c82 data/create/loot_tables/blocks/cut_crimsite_wall.json 7bfe4d183ed26de1d7b241c27880a70d28426502 data/create/loot_tables/blocks/cut_deepslate.json -6e375a42ddf38c99fee86531471573716e27fa44 data/create/loot_tables/blocks/cut_deepslate_bricks.json fa4b940ad8ee432ee0fabf496d2da3d5039c204a data/create/loot_tables/blocks/cut_deepslate_brick_slab.json 1063a94b3e90a52a7492d85b1c086514333f3421 data/create/loot_tables/blocks/cut_deepslate_brick_stairs.json 878d809a038c626e8054f9b71e27be08388d7615 data/create/loot_tables/blocks/cut_deepslate_brick_wall.json +6e375a42ddf38c99fee86531471573716e27fa44 data/create/loot_tables/blocks/cut_deepslate_bricks.json 7b5e46aaf34d71993f50b5b6fa1cd5d7ea64264c data/create/loot_tables/blocks/cut_deepslate_slab.json 7d45e8bb037a1e550132854200d57ce31e073993 data/create/loot_tables/blocks/cut_deepslate_stairs.json cd80fd4f573d59c22f0b9799f1ba7422215d4ff1 data/create/loot_tables/blocks/cut_deepslate_wall.json d79d52657307a30422d9ff2eb1caad78024c24f7 data/create/loot_tables/blocks/cut_diorite.json -9f627b6449ae27a1990b84a60349736129a11e39 data/create/loot_tables/blocks/cut_diorite_bricks.json 1809235166024fa74f65a96b622faa8eddf4ce14 data/create/loot_tables/blocks/cut_diorite_brick_slab.json a6bb9fb4eee3dab9a540b228801ce100c048c2a7 data/create/loot_tables/blocks/cut_diorite_brick_stairs.json 690a938a04543cb60f2952335be26b2df9c75715 data/create/loot_tables/blocks/cut_diorite_brick_wall.json +9f627b6449ae27a1990b84a60349736129a11e39 data/create/loot_tables/blocks/cut_diorite_bricks.json 208999222adb5b1cd4fa47b85000841dbae4ad21 data/create/loot_tables/blocks/cut_diorite_slab.json 12849a868e8dff48ebb688c84fc53d4cee2a4eaa data/create/loot_tables/blocks/cut_diorite_stairs.json 469fffcdd40aea22fedb81b7778cc3c61928f3fd data/create/loot_tables/blocks/cut_diorite_wall.json 302d0bb640f696109fe4edc0c1fa9db332231511 data/create/loot_tables/blocks/cut_dripstone.json -48707f37b94ff1a930ee45bb9e8b6b4b67226945 data/create/loot_tables/blocks/cut_dripstone_bricks.json eb31bc108180e2248d575d5d72325b5585254af0 data/create/loot_tables/blocks/cut_dripstone_brick_slab.json 9b624a456baf55960675d7857e159f69911a281a data/create/loot_tables/blocks/cut_dripstone_brick_stairs.json b4c754d4d5a6c28f537c2d73844e39059b2c1450 data/create/loot_tables/blocks/cut_dripstone_brick_wall.json +48707f37b94ff1a930ee45bb9e8b6b4b67226945 data/create/loot_tables/blocks/cut_dripstone_bricks.json eb9eca9a69f763cbe81dc79375ef76978594b51e data/create/loot_tables/blocks/cut_dripstone_slab.json 47fae3abc8bea3ee802d6759192e631f50329c5f data/create/loot_tables/blocks/cut_dripstone_stairs.json 70b71cc460cba2955694baf0550eadc2187e3a8a data/create/loot_tables/blocks/cut_dripstone_wall.json 26433a16a91414be15b20dc85b81b76d086be889 data/create/loot_tables/blocks/cut_granite.json -65c3936e78a90c53faa0b9f9b3034afc2728e7b9 data/create/loot_tables/blocks/cut_granite_bricks.json c6b8dfa87e9c33a0dd2b3398dcc524347e826d44 data/create/loot_tables/blocks/cut_granite_brick_slab.json 5e00417f06b4d357e7469f0efa6e319dfc587da3 data/create/loot_tables/blocks/cut_granite_brick_stairs.json 8d8779846af8121426f128cc7b5d501037bd1cd4 data/create/loot_tables/blocks/cut_granite_brick_wall.json +65c3936e78a90c53faa0b9f9b3034afc2728e7b9 data/create/loot_tables/blocks/cut_granite_bricks.json 6e7253b2801611b4698e786f495c2ade1088ee0b data/create/loot_tables/blocks/cut_granite_slab.json de8c10fb2c7409a3375f2db5cdce2027c3f419bd data/create/loot_tables/blocks/cut_granite_stairs.json cdf40bb46d9457a66129b300dc4d3f0160cc1de2 data/create/loot_tables/blocks/cut_granite_wall.json ac5f062c7fc270c63d67ccecf19499a9e91fa1c4 data/create/loot_tables/blocks/cut_limestone.json -b60fb652e1f83b1af12a15cb47450bd9a6087f6a data/create/loot_tables/blocks/cut_limestone_bricks.json 3b6d3a9b12cf1c2a20bf337cc0155bb66967f0ee data/create/loot_tables/blocks/cut_limestone_brick_slab.json 701249cc12b7aa6f5cc1691ac4dd17e665aa2180 data/create/loot_tables/blocks/cut_limestone_brick_stairs.json 3b8c5eef9b0e8c35e8573ce91f5fddbac7f76f24 data/create/loot_tables/blocks/cut_limestone_brick_wall.json +b60fb652e1f83b1af12a15cb47450bd9a6087f6a data/create/loot_tables/blocks/cut_limestone_bricks.json ba186786e8677f1c769e8f231fe872c48330e13a data/create/loot_tables/blocks/cut_limestone_slab.json d354966d57804afda39ff27336d8b0f38acf6ea3 data/create/loot_tables/blocks/cut_limestone_stairs.json 28b4eee2c6da259e50c58a51905fa2b79a9b89ef data/create/loot_tables/blocks/cut_limestone_wall.json b3d6d90dd0c3e9d4b47d1f87d5abc354dd8c1447 data/create/loot_tables/blocks/cut_ochrum.json -5856859aae0cc633cbd9d83ea7cf7910ce1a88de data/create/loot_tables/blocks/cut_ochrum_bricks.json 67cadc71d90fb2527b9b2b72a74463d71571e493 data/create/loot_tables/blocks/cut_ochrum_brick_slab.json 487b3e7dc1d9d07183b9b699e33f6371858435aa data/create/loot_tables/blocks/cut_ochrum_brick_stairs.json 289757860f07b63dcce531a74ce7e60b4669c51b data/create/loot_tables/blocks/cut_ochrum_brick_wall.json +5856859aae0cc633cbd9d83ea7cf7910ce1a88de data/create/loot_tables/blocks/cut_ochrum_bricks.json c9deec5e3c7343afa3d013704179e2147b2eb7ec data/create/loot_tables/blocks/cut_ochrum_slab.json e851d829db8ea4398bc1cbe6e743b4fba98d3413 data/create/loot_tables/blocks/cut_ochrum_stairs.json 5dce8524b70baeefaeba13422f5900b1a161a867 data/create/loot_tables/blocks/cut_ochrum_wall.json 293064edf2909db8c9edc26bedd1cc023c647664 data/create/loot_tables/blocks/cut_scorchia.json -767910313f0983ebfb49b80526747d762cbdf782 data/create/loot_tables/blocks/cut_scorchia_bricks.json 895c4b9cc71701a26ae0e765ee67f0c06cc70a9c data/create/loot_tables/blocks/cut_scorchia_brick_slab.json c53d72176cb5dd93977975dd84647391fa563e3a data/create/loot_tables/blocks/cut_scorchia_brick_stairs.json 460232ca38cba2f0adc5316d6db8db94db231953 data/create/loot_tables/blocks/cut_scorchia_brick_wall.json +767910313f0983ebfb49b80526747d762cbdf782 data/create/loot_tables/blocks/cut_scorchia_bricks.json c8201964d877a932fe9a9a2d0360004440f7c380 data/create/loot_tables/blocks/cut_scorchia_slab.json dfd09849dbf48a064269a5ea28d0422caa87e4d4 data/create/loot_tables/blocks/cut_scorchia_stairs.json bd5304e38bb92a445c159e9fe647b906e28b232e data/create/loot_tables/blocks/cut_scorchia_wall.json 6b87a22c39b545d5be92e476751b99ceb4bef740 data/create/loot_tables/blocks/cut_scoria.json -833252d2d63c7502f6f0d7981673a8081046c944 data/create/loot_tables/blocks/cut_scoria_bricks.json 659e86f89499539e435989c2eb29e88e9a0ff9f4 data/create/loot_tables/blocks/cut_scoria_brick_slab.json 8434d461090bc43328eec0b4249d27a9ba383707 data/create/loot_tables/blocks/cut_scoria_brick_stairs.json e3f853395b9b6fb7d5bb103c121a77e04526a9e8 data/create/loot_tables/blocks/cut_scoria_brick_wall.json +833252d2d63c7502f6f0d7981673a8081046c944 data/create/loot_tables/blocks/cut_scoria_bricks.json 8360d736887ae3dc22bcf522791ef981e380456c data/create/loot_tables/blocks/cut_scoria_slab.json c771f03308f45e1e87d92181f94cdfd4e61fa5d8 data/create/loot_tables/blocks/cut_scoria_stairs.json 6fecb7fa2774ea63ac0c66e9c3d0f41d6b8cdff7 data/create/loot_tables/blocks/cut_scoria_wall.json 396074ee7fd5a3ddbac9332c74b7bdc4164919e2 data/create/loot_tables/blocks/cut_tuff.json -81465ef7aa555d36adf249bbc9acfe80abbe308e data/create/loot_tables/blocks/cut_tuff_bricks.json 5148f230c773b83268d52650bdacc660025feb95 data/create/loot_tables/blocks/cut_tuff_brick_slab.json 19719a4a3f63d1ec46a9ca9736a825d2dcc880ff data/create/loot_tables/blocks/cut_tuff_brick_stairs.json e20991b67c07dca62c212b43da5b7e7e98146c0e data/create/loot_tables/blocks/cut_tuff_brick_wall.json +81465ef7aa555d36adf249bbc9acfe80abbe308e data/create/loot_tables/blocks/cut_tuff_bricks.json 6d16bd3860207ff6912afc2bf3f0454b572aabba data/create/loot_tables/blocks/cut_tuff_slab.json c14e52ac9901aa873c33d51988bd26465ce0e095 data/create/loot_tables/blocks/cut_tuff_stairs.json dd70800c79fa2ff56bd4ea032cf069bc27cc9076 data/create/loot_tables/blocks/cut_tuff_wall.json 1957b610d14460cc9ca797fe953bf9831509cdbf data/create/loot_tables/blocks/cut_veridium.json -673d1f0fefa7725ac5bfcabfcea577041adc4eeb data/create/loot_tables/blocks/cut_veridium_bricks.json c1515a908bde249c087be1e73aec37773bc3dc5c data/create/loot_tables/blocks/cut_veridium_brick_slab.json d9552e3e9f4de0e09df8ca9446066e94c6e2c681 data/create/loot_tables/blocks/cut_veridium_brick_stairs.json 584c4bd13d9870f9798155b47cc0d32e5751294d data/create/loot_tables/blocks/cut_veridium_brick_wall.json +673d1f0fefa7725ac5bfcabfcea577041adc4eeb data/create/loot_tables/blocks/cut_veridium_bricks.json 009186ed0efe29a229a28cfd913bc02ddad217d4 data/create/loot_tables/blocks/cut_veridium_slab.json 4845f7127921c7dd93a59118e63c37107d6c2061 data/create/loot_tables/blocks/cut_veridium_stairs.json b56caea031d637321eddfd5d122fc357d2c2e49c data/create/loot_tables/blocks/cut_veridium_wall.json @@ -3539,12 +3539,12 @@ dfe0af3ff61ed2b3082e49c745d8a3e0c5973f4b data/create/loot_tables/blocks/encased_ a2e9a8a10b7fc730c1d7c8db3b529e7a37b683f5 data/create/loot_tables/blocks/encased_fan.json 7ede9f64839f51e6a2eb05b08577d2873f281401 data/create/loot_tables/blocks/encased_fluid_pipe.json 4869211639326efaabd1aba1067bfbb3ab012884 data/create/loot_tables/blocks/experience_block.json -9fa4b0c8ee313b6c9a57d7d5b687cdd01c8259d3 data/create/loot_tables/blocks/exposed_copper_shingles.json 9dbd37ef5ff549f10475101205c1a9d4a44140bc data/create/loot_tables/blocks/exposed_copper_shingle_slab.json d2c9abd9260eb82ea1c2eeae5e2d6abd0b4d3ce8 data/create/loot_tables/blocks/exposed_copper_shingle_stairs.json -f0905ae4c9bdff8fe9e1ab4682a7b1efe2d27d9d data/create/loot_tables/blocks/exposed_copper_tiles.json +9fa4b0c8ee313b6c9a57d7d5b687cdd01c8259d3 data/create/loot_tables/blocks/exposed_copper_shingles.json 6841c02935838f00011d33fc392965326c4dbc5b data/create/loot_tables/blocks/exposed_copper_tile_slab.json 432a047156b93a09b7e027fc34f5680a8f68dc92 data/create/loot_tables/blocks/exposed_copper_tile_stairs.json +f0905ae4c9bdff8fe9e1ab4682a7b1efe2d27d9d data/create/loot_tables/blocks/exposed_copper_tiles.json 4dd285b35d9b94d48f7aa783e93bdd04d58c4a26 data/create/loot_tables/blocks/factory_gauge.json 3fae2a7a3f133a1d7c76ce91f6c48eab787d6ff6 data/create/loot_tables/blocks/fake_track.json 1d4734d6d9ba039c0dfa2271f08cdb55e35b721f data/create/loot_tables/blocks/fluid_pipe.json @@ -3620,8 +3620,6 @@ eb95d1e0abb93d5efecb0809e3901f37021c4dfc data/create/loot_tables/blocks/light_gr e61e9b3e116037c4ad44a7e222e5127e5767ddad data/create/loot_tables/blocks/light_gray_table_cloth.json e22dfadefcea50090efe87136a4b92e6ef20d379 data/create/loot_tables/blocks/light_gray_toolbox.json 3e586bc1281f15e25e75475dd726578ff032c6ae data/create/loot_tables/blocks/light_gray_valve_handle.json -c6bb0877c537dda15469934383dc45c608bfd1a4 data/create/loot_tables/blocks/limestone.json -49058a62e1abd34917f983b6bc13cc4353b613a2 data/create/loot_tables/blocks/limestone_pillar.json 582bb26f6df37d0c2dbe12983ad05fc74f5fb5c0 data/create/loot_tables/blocks/lime_nixie_tube.json ec9d973d218b26d51b82f265603feab31170c619 data/create/loot_tables/blocks/lime_postbox.json 623ac65211a9920325308b55285f78e3b7275751 data/create/loot_tables/blocks/lime_sail.json @@ -3629,6 +3627,8 @@ ec9d973d218b26d51b82f265603feab31170c619 data/create/loot_tables/blocks/lime_pos 10ecd65ecba6b66652dd04a385fc47a44c1f8110 data/create/loot_tables/blocks/lime_table_cloth.json 0f6a465501a445925e9aff7a4c84b3c8e2caa93e data/create/loot_tables/blocks/lime_toolbox.json 1a3ed7cd5660d7ea014956ea642e0b07d89bc297 data/create/loot_tables/blocks/lime_valve_handle.json +c6bb0877c537dda15469934383dc45c608bfd1a4 data/create/loot_tables/blocks/limestone.json +49058a62e1abd34917f983b6bc13cc4353b613a2 data/create/loot_tables/blocks/limestone_pillar.json baf70f9eb579f20b232a2af4e6b00a54f84844e6 data/create/loot_tables/blocks/linear_chassis.json e4c0f8ca822cf7555bd011825b430c3c735160d4 data/create/loot_tables/blocks/lit_blaze_burner.json 6bd8b044cc9c69a5268372e5436f556da2c1bf21 data/create/loot_tables/blocks/magenta_nixie_tube.json @@ -3674,14 +3674,14 @@ d6323d4b30faa87cd4b5b8b815cb16f78296f203 data/create/loot_tables/blocks/orange_s 30aef2df782b6b35cd16b4c205bb15de85bc0664 data/create/loot_tables/blocks/orange_valve_handle.json f4004c6d16754fc8867ed6618dace8e8f6dcc412 data/create/loot_tables/blocks/ornate_iron_window.json 6f14500e07c6d342804f9127e7b66047ffaeef1e data/create/loot_tables/blocks/ornate_iron_window_pane.json -3e54d3c4755a43d837a1d9b2005ea1dee4d02555 data/create/loot_tables/blocks/oxidized_copper_shingles.json 62c43a533e4ffeeec9f7657db5a796569087f806 data/create/loot_tables/blocks/oxidized_copper_shingle_slab.json f47a01824093455030fca66e7b8a39bcfc61d219 data/create/loot_tables/blocks/oxidized_copper_shingle_stairs.json -4d2a2863697664b3b71f02aa703c3504cd5cc826 data/create/loot_tables/blocks/oxidized_copper_tiles.json +3e54d3c4755a43d837a1d9b2005ea1dee4d02555 data/create/loot_tables/blocks/oxidized_copper_shingles.json 4d815b361af81bd0c0e14c853ca54ad3cde66a57 data/create/loot_tables/blocks/oxidized_copper_tile_slab.json d599ef03d1b69e4367ec0dea78f52c1964c99f9b data/create/loot_tables/blocks/oxidized_copper_tile_stairs.json -ab8cee7abd7dd92428bf7d8f0f5edd35082401a4 data/create/loot_tables/blocks/packager.json +4d2a2863697664b3b71f02aa703c3504cd5cc826 data/create/loot_tables/blocks/oxidized_copper_tiles.json 54aa9700df601640b705d912abe773d5b6ee2b1f data/create/loot_tables/blocks/package_frogport.json +ab8cee7abd7dd92428bf7d8f0f5edd35082401a4 data/create/loot_tables/blocks/packager.json 58bd9fe9d6706998bfbda3b077cfd0a740972091 data/create/loot_tables/blocks/peculiar_bell.json 4d7724df6fefee4512c4f7886d0e103d1dc39510 data/create/loot_tables/blocks/pink_nixie_tube.json df7b12349c64d035eb563535b03cb70d780c5a71 data/create/loot_tables/blocks/pink_postbox.json @@ -3767,9 +3767,6 @@ b4746e296f4bf63778e40a751b4c7fa8be45d21d data/create/loot_tables/blocks/purple_t 9e5e841d9f9a00d560ed17a7e197dc56bae334b7 data/create/loot_tables/blocks/radial_chassis.json 73a03fa31e299cec2c8a3dc0f31a8aa354b49bcd data/create/loot_tables/blocks/railway_casing.json f76e5a157d2aeab5708f464b1f3c8e47b3855f18 data/create/loot_tables/blocks/raw_zinc_block.json -bbc2d61eeea335f8f011d799ef6a5484ca027640 data/create/loot_tables/blocks/redstone_contact.json -4fa70deeac7e56121e42fb602dfa27ee1727f749 data/create/loot_tables/blocks/redstone_link.json -efc3a5595e4daf67fa43f84c9869dfc76fd6fca4 data/create/loot_tables/blocks/redstone_requester.json a50e1c28af16e9f1b4f48aa974461167139768a7 data/create/loot_tables/blocks/red_nixie_tube.json f36f1e69e4fb8723238f81aadbac892f54b5ac62 data/create/loot_tables/blocks/red_postbox.json 977d724cddf8eba053a3310ad0d30af15199bbed data/create/loot_tables/blocks/red_sail.json @@ -3777,6 +3774,9 @@ f36f1e69e4fb8723238f81aadbac892f54b5ac62 data/create/loot_tables/blocks/red_post 09796bc3be977e17927d0a9e32bff2982618e844 data/create/loot_tables/blocks/red_table_cloth.json 9713071cab536e8c1550a6309dc4563fecc2c4e0 data/create/loot_tables/blocks/red_toolbox.json 17d75711f4ef5d76aa931175364642732fb0c60d data/create/loot_tables/blocks/red_valve_handle.json +bbc2d61eeea335f8f011d799ef6a5484ca027640 data/create/loot_tables/blocks/redstone_contact.json +4fa70deeac7e56121e42fb602dfa27ee1727f749 data/create/loot_tables/blocks/redstone_link.json +efc3a5595e4daf67fa43f84c9869dfc76fd6fca4 data/create/loot_tables/blocks/redstone_requester.json 632067fe6309e31e78637eb0272209b630750242 data/create/loot_tables/blocks/refined_radiance_casing.json ee2c4d66d1264ec613e9e84fcac814d2f5806258 data/create/loot_tables/blocks/repackager.json 354a3b6c73379b7100b0dd12b3f3b008830c4d2d data/create/loot_tables/blocks/rope.json @@ -3786,8 +3786,8 @@ f74fdd78961619d712891c36e0a0778c25e145dc data/create/loot_tables/blocks/rope_pul a0575567d5679f2c54e5a25c6ec12338f8cdc939 data/create/loot_tables/blocks/rose_quartz_tiles.json de74765a3bbffafb87d632857dfcfa83f863f814 data/create/loot_tables/blocks/rotation_speed_controller.json 2af8df3e36ace336c43d68f4e53564640a89845f data/create/loot_tables/blocks/sail_frame.json -d499fd59d30da8b907b0f3a0f428700f066eddff data/create/loot_tables/blocks/schematicannon.json 5a54e930243919991d71a1c3296002ff86dd88e1 data/create/loot_tables/blocks/schematic_table.json +d499fd59d30da8b907b0f3a0f428700f066eddff data/create/loot_tables/blocks/schematicannon.json 1d9b0df1330f44681bbd56f8560a30ef9e2175ff data/create/loot_tables/blocks/scorchia.json e39f189bfaebd31aedceb11e25720f1e08eb238d data/create/loot_tables/blocks/scorchia_pillar.json 5e3a37dbb2fcc0d6be042bfd063fd8b1414d6169 data/create/loot_tables/blocks/scoria.json @@ -3796,64 +3796,64 @@ d39afcaedc84d582c0c1f21ec5945cd0a67d389d data/create/loot_tables/blocks/secondar e33a34b47e07cf3262c0dbdbc651b31b9492b18f data/create/loot_tables/blocks/sequenced_gearshift.json 7d61387106e5e7fcc4aa0b05b9560cd5f4ef7df8 data/create/loot_tables/blocks/shadow_steel_casing.json 7e67d04f861e0a680487e27f94022a7850652dfe data/create/loot_tables/blocks/shaft.json -e88ff4ab1341c2db8338de0708b0ca8f40f15a8b data/create/loot_tables/blocks/small_andesite_bricks.json 220febcbcc4a993d475b683ebef7468ebdb7bf26 data/create/loot_tables/blocks/small_andesite_brick_slab.json b4764c5bb538359bcc2a599ff3b7474ade2115ed data/create/loot_tables/blocks/small_andesite_brick_stairs.json a891496ffb91bef56c3b684cb55a57e27a72154a data/create/loot_tables/blocks/small_andesite_brick_wall.json -576d8f6beca755a4082f1c8941e2590c1d18107b data/create/loot_tables/blocks/small_asurine_bricks.json +e88ff4ab1341c2db8338de0708b0ca8f40f15a8b data/create/loot_tables/blocks/small_andesite_bricks.json 1a5d3543ebb7c0064ba8ff01160a22a0f5f29f36 data/create/loot_tables/blocks/small_asurine_brick_slab.json 64f4b44b786eda91d432f20c8b725b0415440b56 data/create/loot_tables/blocks/small_asurine_brick_stairs.json 60a1d505e955047cf933ae55efc2e7c10d0a5a79 data/create/loot_tables/blocks/small_asurine_brick_wall.json +576d8f6beca755a4082f1c8941e2590c1d18107b data/create/loot_tables/blocks/small_asurine_bricks.json 64bcfece2507b8510633ae20c00ab989232664ff data/create/loot_tables/blocks/small_bogey.json -c03bba06f66262c0ced5e85fa7dcbfbfc8c9db71 data/create/loot_tables/blocks/small_calcite_bricks.json b673542c79f4a82f2e80c0931354e994292811f6 data/create/loot_tables/blocks/small_calcite_brick_slab.json e10d286286bba8e172a56e0eeb9af18d06d1a76d data/create/loot_tables/blocks/small_calcite_brick_stairs.json d7214e942b203823fa2fece883e8406a7721369f data/create/loot_tables/blocks/small_calcite_brick_wall.json -f49d32973b0be51229f4e3fdc13958c9852c5c8a data/create/loot_tables/blocks/small_crimsite_bricks.json +c03bba06f66262c0ced5e85fa7dcbfbfc8c9db71 data/create/loot_tables/blocks/small_calcite_bricks.json ef8b0f604b627715542e8216ae5448e88995cc13 data/create/loot_tables/blocks/small_crimsite_brick_slab.json dbec9246ab957a3ed2dbd0707df12c1496258e05 data/create/loot_tables/blocks/small_crimsite_brick_stairs.json d4d5bd8b101655205c4f293f23e83f610e179e91 data/create/loot_tables/blocks/small_crimsite_brick_wall.json -8caba3e7001dd8df4d3e6365b97849570c74c840 data/create/loot_tables/blocks/small_deepslate_bricks.json +f49d32973b0be51229f4e3fdc13958c9852c5c8a data/create/loot_tables/blocks/small_crimsite_bricks.json 44567c10c28ddd221198824766d3fec289fb29d4 data/create/loot_tables/blocks/small_deepslate_brick_slab.json fc141f5cdb1001d344b5ef8fa3ad1fdfeb01d048 data/create/loot_tables/blocks/small_deepslate_brick_stairs.json 3cf68d27362e9bb5dc3255ccf810097fbee511ba data/create/loot_tables/blocks/small_deepslate_brick_wall.json -4f22a84f105c2fabfd08ff0782ec30bbdc59f940 data/create/loot_tables/blocks/small_diorite_bricks.json +8caba3e7001dd8df4d3e6365b97849570c74c840 data/create/loot_tables/blocks/small_deepslate_bricks.json f6565f4bd11b7e95008b0f8fc3f5f2c7af1b77f8 data/create/loot_tables/blocks/small_diorite_brick_slab.json e3cbe41b4b2c38d0d5e625e34b61fc79db16d3bd data/create/loot_tables/blocks/small_diorite_brick_stairs.json 787dfaa16dc30155c90cc360f6927fa067a30ed8 data/create/loot_tables/blocks/small_diorite_brick_wall.json -d9cc7f58c791e040df4abfce225524e01eb01d49 data/create/loot_tables/blocks/small_dripstone_bricks.json +4f22a84f105c2fabfd08ff0782ec30bbdc59f940 data/create/loot_tables/blocks/small_diorite_bricks.json f72338c9252528e41f60cb183cb4ee07cea47bf0 data/create/loot_tables/blocks/small_dripstone_brick_slab.json bedf0fba68e8a8ce4205a968429ebe9c3ddfb528 data/create/loot_tables/blocks/small_dripstone_brick_stairs.json c1168f58f342dfa332bfa7f53f5f03383c55ccf2 data/create/loot_tables/blocks/small_dripstone_brick_wall.json -8437e7e28e45c10562d182c4c07189bcc108cabb data/create/loot_tables/blocks/small_granite_bricks.json +d9cc7f58c791e040df4abfce225524e01eb01d49 data/create/loot_tables/blocks/small_dripstone_bricks.json 4d111f8580ac97cf1b49b667462f7141846f3d3a data/create/loot_tables/blocks/small_granite_brick_slab.json c16e015251126614960d3e6300cb04d3aeaf49b4 data/create/loot_tables/blocks/small_granite_brick_stairs.json e0ff780ddeb5d5c8d2b6cd7736ac05f4556de52c data/create/loot_tables/blocks/small_granite_brick_wall.json -c60def11fbac5010bf749960e084dd5cd0dc4b07 data/create/loot_tables/blocks/small_limestone_bricks.json +8437e7e28e45c10562d182c4c07189bcc108cabb data/create/loot_tables/blocks/small_granite_bricks.json 5222ac5255c9a9ada0ce1da0fd4f4acbeee8ddb7 data/create/loot_tables/blocks/small_limestone_brick_slab.json 97310b6b1cbea869ebaa52861542787c49cee017 data/create/loot_tables/blocks/small_limestone_brick_stairs.json 0855921034db43692baa9fd0bcb767154f96d591 data/create/loot_tables/blocks/small_limestone_brick_wall.json -eb6b2171a6c99a3a28089752f26ddc6ac1f941d1 data/create/loot_tables/blocks/small_ochrum_bricks.json +c60def11fbac5010bf749960e084dd5cd0dc4b07 data/create/loot_tables/blocks/small_limestone_bricks.json 8ced0c24db685dbf4382b7b71124005edde9e0b2 data/create/loot_tables/blocks/small_ochrum_brick_slab.json 090e7154fb2c3dfd20d37aa87f3df4572a27c615 data/create/loot_tables/blocks/small_ochrum_brick_stairs.json 60f2d9970ad8caf8ffe3aa8083dbba671b8d4b8b data/create/loot_tables/blocks/small_ochrum_brick_wall.json +eb6b2171a6c99a3a28089752f26ddc6ac1f941d1 data/create/loot_tables/blocks/small_ochrum_bricks.json a001d069c2b4d15c6dfd0312749765fc4e89571e data/create/loot_tables/blocks/small_rose_quartz_tiles.json -ce71e670948453691d4f09c8110b952afb41afa1 data/create/loot_tables/blocks/small_scorchia_bricks.json d521cf885c737da2e4717d43072840ffd3f4c5d9 data/create/loot_tables/blocks/small_scorchia_brick_slab.json de6b5d583e1adf4d49147e0719616dfd0165726d data/create/loot_tables/blocks/small_scorchia_brick_stairs.json 895603c6920338ffafd8d0d1310e47ac20bdbfda data/create/loot_tables/blocks/small_scorchia_brick_wall.json -8b7e61477c4fdc834d669bda9197b585d60f26a2 data/create/loot_tables/blocks/small_scoria_bricks.json +ce71e670948453691d4f09c8110b952afb41afa1 data/create/loot_tables/blocks/small_scorchia_bricks.json d1954c07a66f40123d8d78602795efad7c92070f data/create/loot_tables/blocks/small_scoria_brick_slab.json 291b5a560f09ed8f09ccc949a1a4da0006f139c7 data/create/loot_tables/blocks/small_scoria_brick_stairs.json ed572e947f78d637e6e1a4166c111121087c41c3 data/create/loot_tables/blocks/small_scoria_brick_wall.json -2c7097ee677f42452212b5dce8959065d2bb0e15 data/create/loot_tables/blocks/small_tuff_bricks.json +8b7e61477c4fdc834d669bda9197b585d60f26a2 data/create/loot_tables/blocks/small_scoria_bricks.json ad8a3571dc3ae0ee1ec7be7f35c9796e544f0682 data/create/loot_tables/blocks/small_tuff_brick_slab.json 17f4a98a81e5920b75c88133d15b63d431f3fb64 data/create/loot_tables/blocks/small_tuff_brick_stairs.json 7defad704f6278e329af634acfb9efd617b2003e data/create/loot_tables/blocks/small_tuff_brick_wall.json -e499c0a8a0f804003612f3a4c9286cb4b033fe4b data/create/loot_tables/blocks/small_veridium_bricks.json +2c7097ee677f42452212b5dce8959065d2bb0e15 data/create/loot_tables/blocks/small_tuff_bricks.json c7771827a715b9eaacd1a7b7e863e274b1dee11f data/create/loot_tables/blocks/small_veridium_brick_slab.json 818b65dd5d868527e7df7658a4f62a93f2795186 data/create/loot_tables/blocks/small_veridium_brick_stairs.json 7733e53a90f2ba9c17cdedaa8720e70df1a8d2de data/create/loot_tables/blocks/small_veridium_brick_wall.json +e499c0a8a0f804003612f3a4c9286cb4b033fe4b data/create/loot_tables/blocks/small_veridium_bricks.json a121d21b81e93c119b6ee32ca21d260d9c33cb2a data/create/loot_tables/blocks/smart_chute.json 4556eb2d607db3631d0a9524d22a50686ce4a5a8 data/create/loot_tables/blocks/smart_fluid_pipe.json 9601e8ba0eb098cc409557f17b01669d8b971461 data/create/loot_tables/blocks/speedometer.json @@ -3865,9 +3865,9 @@ bcd632c1180efbc990b077314cfce8514a25da7c data/create/loot_tables/blocks/spruce_w cae1bd9100b62841e260880faa80e2442f44a141 data/create/loot_tables/blocks/steam_whistle_extension.json 0bc3fdde351129e3a261a2420aff9d3f063c235e data/create/loot_tables/blocks/sticker.json 074f526902cb5fcff2129614428aba1ea05a6649 data/create/loot_tables/blocks/sticky_mechanical_piston.json -a7332324e63f7d28621ddfbd54eb3d091461d890 data/create/loot_tables/blocks/stockpile_switch.json af312881ec9bfb0902438f53c5cac020244bdba2 data/create/loot_tables/blocks/stock_link.json f4fa9bb255348dc79dcc0468b3beb9ad075eb036 data/create/loot_tables/blocks/stock_ticker.json +a7332324e63f7d28621ddfbd54eb3d091461d890 data/create/loot_tables/blocks/stockpile_switch.json b13496b1b4bc0be30605832e23894fb374dd796e data/create/loot_tables/blocks/stressometer.json 6a7df4d2730d57ae6e404b4bc8e01367e5ddbf07 data/create/loot_tables/blocks/tiled_glass.json 0ad584e41780dc0183af1fa1e49e126730dfdbab data/create/loot_tables/blocks/tiled_glass_pane.json @@ -3887,36 +3887,36 @@ cfc82d2aa8248caeaa17ff0a60db02607046550d data/create/loot_tables/blocks/warped_w 2eeddb89cfc597bc1ce0736b9f4a6f98e0dfa4d2 data/create/loot_tables/blocks/warped_window_pane.json ccab211722d7f06913a549851b0d6e8278edc845 data/create/loot_tables/blocks/water_wheel.json ea5dfcedc928e8dfa1c59cf3917d1577dff87494 data/create/loot_tables/blocks/water_wheel_structure.json -bbc6fc068adccea464909b87f1d1f426324d74cc data/create/loot_tables/blocks/waxed_copper_shingles.json cb31be1e75ca822454bd0a89954f74c4c8726b33 data/create/loot_tables/blocks/waxed_copper_shingle_slab.json c8e440e42141788d1988c57ab91cb1bfcd977407 data/create/loot_tables/blocks/waxed_copper_shingle_stairs.json -a3b8f12d983077477963fd3fc893c5acd36ad552 data/create/loot_tables/blocks/waxed_copper_tiles.json +bbc6fc068adccea464909b87f1d1f426324d74cc data/create/loot_tables/blocks/waxed_copper_shingles.json 807da1d66d6c7d07efc8973de43415fa4b5ddfdc data/create/loot_tables/blocks/waxed_copper_tile_slab.json 92759871a9c84815b98b6dcd22fcf0dd958bc8ab data/create/loot_tables/blocks/waxed_copper_tile_stairs.json -eb9781d081d52c34c041004c774b52169b4a9ca0 data/create/loot_tables/blocks/waxed_exposed_copper_shingles.json +a3b8f12d983077477963fd3fc893c5acd36ad552 data/create/loot_tables/blocks/waxed_copper_tiles.json be5aabc98f4d70028f2b49ae1eaf0bc68a693c53 data/create/loot_tables/blocks/waxed_exposed_copper_shingle_slab.json a99143d290addb98427be53d7fea1cbc702d630c data/create/loot_tables/blocks/waxed_exposed_copper_shingle_stairs.json -e79c0636852b37a463dc122d66cdec27d3aa10c4 data/create/loot_tables/blocks/waxed_exposed_copper_tiles.json +eb9781d081d52c34c041004c774b52169b4a9ca0 data/create/loot_tables/blocks/waxed_exposed_copper_shingles.json 234cbb59a0e00d82c5508c8e9a61e328c22c1c56 data/create/loot_tables/blocks/waxed_exposed_copper_tile_slab.json de628114eb25f393efc4c0934d79c5bdc4365f75 data/create/loot_tables/blocks/waxed_exposed_copper_tile_stairs.json -60fe0594baab9599956d990ba893f8915835db81 data/create/loot_tables/blocks/waxed_oxidized_copper_shingles.json +e79c0636852b37a463dc122d66cdec27d3aa10c4 data/create/loot_tables/blocks/waxed_exposed_copper_tiles.json c8935df7d4634dee2b01c8a0ac5de12397f4d9ed data/create/loot_tables/blocks/waxed_oxidized_copper_shingle_slab.json 2b9370b7fa362ea88f916dd53747da80e4ae3357 data/create/loot_tables/blocks/waxed_oxidized_copper_shingle_stairs.json -f0721c371b08214337f3f4fce3a3705840310bdb data/create/loot_tables/blocks/waxed_oxidized_copper_tiles.json +60fe0594baab9599956d990ba893f8915835db81 data/create/loot_tables/blocks/waxed_oxidized_copper_shingles.json de4d25cac546559173f740752625c82dfd6bae09 data/create/loot_tables/blocks/waxed_oxidized_copper_tile_slab.json 2ed72fc0ea28303f5c6d1039662f55c677cb7bcb data/create/loot_tables/blocks/waxed_oxidized_copper_tile_stairs.json -f309ffd94dfb3591efd2fab337a871a0ceff1084 data/create/loot_tables/blocks/waxed_weathered_copper_shingles.json +f0721c371b08214337f3f4fce3a3705840310bdb data/create/loot_tables/blocks/waxed_oxidized_copper_tiles.json 9a7b265a963e122d510de64012ed1d98ad9017f9 data/create/loot_tables/blocks/waxed_weathered_copper_shingle_slab.json 62f25a1bc013e9c3d487d9a53407e58d89907c5b data/create/loot_tables/blocks/waxed_weathered_copper_shingle_stairs.json -26e6a96f50e7f3384f896bf8a5c3d5ff2b422526 data/create/loot_tables/blocks/waxed_weathered_copper_tiles.json +f309ffd94dfb3591efd2fab337a871a0ceff1084 data/create/loot_tables/blocks/waxed_weathered_copper_shingles.json 3fa20e33ced4aee01775db57629b9580a6b8e200 data/create/loot_tables/blocks/waxed_weathered_copper_tile_slab.json 59b28bd57f461482a394dbce9ea10ee25fc7c294 data/create/loot_tables/blocks/waxed_weathered_copper_tile_stairs.json -3cd15ae684bc0e4e41f02b3ee79eafdbf052620c data/create/loot_tables/blocks/weathered_copper_shingles.json +26e6a96f50e7f3384f896bf8a5c3d5ff2b422526 data/create/loot_tables/blocks/waxed_weathered_copper_tiles.json 278a56aa433ba3647107b3bf0553da5a5f6d40dd data/create/loot_tables/blocks/weathered_copper_shingle_slab.json 198babfd55c3a30c6ac61e81d5e01b0cf8fca80a data/create/loot_tables/blocks/weathered_copper_shingle_stairs.json -771d98a6627d707228719e843bc80636b02dc985 data/create/loot_tables/blocks/weathered_copper_tiles.json +3cd15ae684bc0e4e41f02b3ee79eafdbf052620c data/create/loot_tables/blocks/weathered_copper_shingles.json d6862dc9f7d291df618fbce71eebf613711a5517 data/create/loot_tables/blocks/weathered_copper_tile_slab.json 57d5065d53016e4b1ef0fbad9b84605b1546bcc4 data/create/loot_tables/blocks/weathered_copper_tile_stairs.json +771d98a6627d707228719e843bc80636b02dc985 data/create/loot_tables/blocks/weathered_copper_tiles.json 013deea9b687ce96e5042de13ab0cba9dadce364 data/create/loot_tables/blocks/weathered_iron_block.json f0c51ad0a713aab00dff913361b8e5e8448b912a data/create/loot_tables/blocks/weathered_iron_window.json 1d3ea471ec3f2bbf10c7a11f040f8bbf0d1576a8 data/create/loot_tables/blocks/weathered_iron_window_pane.json @@ -3964,43 +3964,43 @@ da3692808565988e21ec5b1d5e976338ccc4a037 data/create/recipes/calcite_pillar_from 1157b2eab2ada187ea80feae298b77ed7ece4bfd data/create/recipes/copper_bars_from_ingots_copper_stonecutting.json b9d4f55128aa03ee6f6ab1831e709629a42c147e data/create/recipes/copper_ladder_from_ingots_copper_stonecutting.json 922c5ac48c8eb8b3a39f5626a381c2252fbac107 data/create/recipes/copper_scaffolding_from_ingots_copper_stonecutting.json -bab9fa969ba95850dc6e3bd0723387a61cbb05cd data/create/recipes/copper_shingles_from_ingots_copper_stonecutting.json bb083ae1d057dc0106946e4c68f9469b81724396 data/create/recipes/copper_shingle_slab.json 3689feaca2bd5355fa2d4226cd2cc519fa9b97c1 data/create/recipes/copper_shingle_slab_from_copper_shingles_stonecutting.json bd4cd7119f8371164b278afc679795a3c2a53406 data/create/recipes/copper_shingle_stairs.json 59f672e8e88d5f4655467e2696616b552debaf46 data/create/recipes/copper_shingle_stairs_from_copper_shingles_stonecutting.json +bab9fa969ba95850dc6e3bd0723387a61cbb05cd data/create/recipes/copper_shingles_from_ingots_copper_stonecutting.json 0225fc8d7b7a5027b8a61e6a043c3a8e505d876a data/create/recipes/copper_table_cloth_from_ingots_copper_stonecutting.json -d463aa891c7ae1b2eb1a758e4100c5a1c16cfffd data/create/recipes/copper_tiles_from_ingots_copper_stonecutting.json f64ba3f3c607b43ea77e5bccb7ec2048e5c6e424 data/create/recipes/copper_tile_slab.json 91b0390e0c772d43eb46b94a0113323f0f6a4387 data/create/recipes/copper_tile_slab_from_copper_tiles_stonecutting.json d31a41f6f7ef0bd20abab06cc31a9d2c56187117 data/create/recipes/copper_tile_stairs.json bf1b0a447169029161fb07feacd22d5aa806b2bf data/create/recipes/copper_tile_stairs_from_copper_tiles_stonecutting.json +d463aa891c7ae1b2eb1a758e4100c5a1c16cfffd data/create/recipes/copper_tiles_from_ingots_copper_stonecutting.json daa54c9ff3612521f06cc1979116beafcda852dd data/create/recipes/copycat_panel_from_ingots_zinc_stonecutting.json 745816d2c3fa29ede2510e39edc76f6fecee963f data/create/recipes/copycat_step_from_ingots_zinc_stonecutting.json -255c32272a704109fccdbb071d4dbf602cb8c1d8 data/create/recipes/crafting/copper/waxed_copper_shingles_from_honeycomb.json 57ae13042e0f96676fa322bf24db4976d75ca6bc data/create/recipes/crafting/copper/waxed_copper_shingle_slab_from_honeycomb.json 790565897535ea2e741d0a0ed7c0b561d594b69a data/create/recipes/crafting/copper/waxed_copper_shingle_stairs_from_honeycomb.json -0c6e14c5884257850c7360cba66bc8cca91c84e7 data/create/recipes/crafting/copper/waxed_copper_tiles_from_honeycomb.json +255c32272a704109fccdbb071d4dbf602cb8c1d8 data/create/recipes/crafting/copper/waxed_copper_shingles_from_honeycomb.json 4693ee65a4a5e1c93fc2acce7bfbc438e573ad9a data/create/recipes/crafting/copper/waxed_copper_tile_slab_from_honeycomb.json f8772b915663e3f70b3a2405a23c5ce87e8b8e49 data/create/recipes/crafting/copper/waxed_copper_tile_stairs_from_honeycomb.json -6d0dacc4db8966d38156fe17645732084379a887 data/create/recipes/crafting/copper/waxed_exposed_copper_shingles_from_honeycomb.json +0c6e14c5884257850c7360cba66bc8cca91c84e7 data/create/recipes/crafting/copper/waxed_copper_tiles_from_honeycomb.json 3bc0b81ea61229e24570e083caa4e5870d517e75 data/create/recipes/crafting/copper/waxed_exposed_copper_shingle_slab_from_honeycomb.json 191f34b27bc8966c2b6ba41403cc0933718748d3 data/create/recipes/crafting/copper/waxed_exposed_copper_shingle_stairs_from_honeycomb.json -cdd66bdfddbcdfacb27c030872d10b6e7f1356fd data/create/recipes/crafting/copper/waxed_exposed_copper_tiles_from_honeycomb.json +6d0dacc4db8966d38156fe17645732084379a887 data/create/recipes/crafting/copper/waxed_exposed_copper_shingles_from_honeycomb.json 2f6d2f8da4d4da2ed48e33d8f6e0b32d37a3ce6d data/create/recipes/crafting/copper/waxed_exposed_copper_tile_slab_from_honeycomb.json 4ed8482ed29fe7c3273db733fa141743c181d460 data/create/recipes/crafting/copper/waxed_exposed_copper_tile_stairs_from_honeycomb.json -0ca4e58d715d5ed4b051a94f2dff42d4d413ef07 data/create/recipes/crafting/copper/waxed_oxidized_copper_shingles_from_honeycomb.json +cdd66bdfddbcdfacb27c030872d10b6e7f1356fd data/create/recipes/crafting/copper/waxed_exposed_copper_tiles_from_honeycomb.json b421f16aea7c47fa8a62e69973f30e4e382f8a2c data/create/recipes/crafting/copper/waxed_oxidized_copper_shingle_slab_from_honeycomb.json 7ab7f673f57e219d3e486d0add1d7e2a8820cc6b data/create/recipes/crafting/copper/waxed_oxidized_copper_shingle_stairs_from_honeycomb.json -b7edffb9b1a936fd34fe23defefc8cb9ea4f6977 data/create/recipes/crafting/copper/waxed_oxidized_copper_tiles_from_honeycomb.json +0ca4e58d715d5ed4b051a94f2dff42d4d413ef07 data/create/recipes/crafting/copper/waxed_oxidized_copper_shingles_from_honeycomb.json 24582e83e8d36a6267df5c028addfb44c1a637e6 data/create/recipes/crafting/copper/waxed_oxidized_copper_tile_slab_from_honeycomb.json 9185ea241bcb5f2fe09d0d5c65832ef379e06c58 data/create/recipes/crafting/copper/waxed_oxidized_copper_tile_stairs_from_honeycomb.json -90bce9f262b87fb821210aceb88d09d815d15e5a data/create/recipes/crafting/copper/waxed_weathered_copper_shingles_from_honeycomb.json +b7edffb9b1a936fd34fe23defefc8cb9ea4f6977 data/create/recipes/crafting/copper/waxed_oxidized_copper_tiles_from_honeycomb.json a2cc99ad9b1234f5327971ee535af9bc25d0154c data/create/recipes/crafting/copper/waxed_weathered_copper_shingle_slab_from_honeycomb.json 0952753a079593d748b38ca84b666f2f886f5c1e data/create/recipes/crafting/copper/waxed_weathered_copper_shingle_stairs_from_honeycomb.json -724802d206db185ebf20bafbcfc35fe0f982f58a data/create/recipes/crafting/copper/waxed_weathered_copper_tiles_from_honeycomb.json +90bce9f262b87fb821210aceb88d09d815d15e5a data/create/recipes/crafting/copper/waxed_weathered_copper_shingles_from_honeycomb.json 98d0b72eb20e1d80cc590800ae2d642a47c3ae5f data/create/recipes/crafting/copper/waxed_weathered_copper_tile_slab_from_honeycomb.json 594b8fd5c30a84df97667b2c6dccc5dedd039d26 data/create/recipes/crafting/copper/waxed_weathered_copper_tile_stairs_from_honeycomb.json +724802d206db185ebf20bafbcfc35fe0f982f58a data/create/recipes/crafting/copper/waxed_weathered_copper_tiles_from_honeycomb.json 97c3e430ef2aecf61c457d0b8c4bbd23e1b01cc3 data/create/recipes/crafting/kinetics/black_seat.json 1129d02609125b48af2efa48f84dd3f90d51a341 data/create/recipes/crafting/kinetics/black_seat_from_other_seat.json 9e5a73e2343054d35e2fbfd20f0c49834d1a87a6 data/create/recipes/crafting/kinetics/black_valve_handle_from_other_valve_handle.json @@ -4136,7 +4136,6 @@ db333d47f9e1d6b02aa670ea0aa10dabbcb0e319 data/create/recipes/crafting/logistics/ c3f4fd2206f3885904913289761f2b8b758e4c95 data/create/recipes/crimsite_pillar_from_stone_types_crimsite_stonecutting.json e1815f97fbc2786d77f5378a2696e36050d8a1fd data/create/recipes/crimson_window.json 96009a12fe3f5ebf677ac069999e2ea2adbc9b7c data/create/recipes/crimson_window_pane.json -82cb9be82ce5109781169bdb47bbd49238b9824b data/create/recipes/cut_andesite_bricks_from_stone_types_andesite_stonecutting.json d6a41fc914a4a41478f115d9503658dba04a4d02 data/create/recipes/cut_andesite_brick_slab.json edf981198463ac58524606f86dc15d2265e8b993 data/create/recipes/cut_andesite_brick_slab_from_stone_types_andesite_stonecutting.json 72486864f3a0d31a92212552441eb659f2541b60 data/create/recipes/cut_andesite_brick_slab_recycling.json @@ -4144,6 +4143,7 @@ edf981198463ac58524606f86dc15d2265e8b993 data/create/recipes/cut_andesite_brick_ 22f463c679249738bf1a340a3b8ff14806303a70 data/create/recipes/cut_andesite_brick_stairs_from_stone_types_andesite_stonecutting.json 42b7105c1d776aed25c1c6bbd9254375079d7438 data/create/recipes/cut_andesite_brick_wall.json 7d25517650c9f66b65f0f8841cf9bcda7ea401ec data/create/recipes/cut_andesite_brick_wall_from_stone_types_andesite_stonecutting.json +82cb9be82ce5109781169bdb47bbd49238b9824b data/create/recipes/cut_andesite_bricks_from_stone_types_andesite_stonecutting.json c3ab483224c3adbd467a4ec0b26a1f6a53fe81c4 data/create/recipes/cut_andesite_from_stone_types_andesite_stonecutting.json 9f316131bb538da9f6b1bde9eaaa0a5bd5972a66 data/create/recipes/cut_andesite_slab.json 50dcff201da369bdc591fdc320aae3547f114284 data/create/recipes/cut_andesite_slab_from_stone_types_andesite_stonecutting.json @@ -4152,7 +4152,6 @@ c3ab483224c3adbd467a4ec0b26a1f6a53fe81c4 data/create/recipes/cut_andesite_from_s c284fc46aabae9c5ab79071eb63ec9b07a9d1002 data/create/recipes/cut_andesite_stairs_from_stone_types_andesite_stonecutting.json 3b6e66e92656ab5b0d1e15444db62ccb1cc01866 data/create/recipes/cut_andesite_wall.json 5df6e8d558f656533aff514aee8cdec7cf8d6fdf data/create/recipes/cut_andesite_wall_from_stone_types_andesite_stonecutting.json -e335b15907be053ab0f2649338b12a86371b78f7 data/create/recipes/cut_asurine_bricks_from_stone_types_asurine_stonecutting.json 41d085d3b8fce5b12d601d86fd0e88df9b482aec data/create/recipes/cut_asurine_brick_slab.json cf61e0806a3988a771675a261a540cbb62352d80 data/create/recipes/cut_asurine_brick_slab_from_stone_types_asurine_stonecutting.json 86606a0717bba33f457707d96461fec6a22d23de data/create/recipes/cut_asurine_brick_slab_recycling.json @@ -4160,6 +4159,7 @@ cf61e0806a3988a771675a261a540cbb62352d80 data/create/recipes/cut_asurine_brick_s 382a7faa460ac286631fe063280541f2f499d895 data/create/recipes/cut_asurine_brick_stairs_from_stone_types_asurine_stonecutting.json 09699c116bb201e742fef1fd3c987e9de4606e6a data/create/recipes/cut_asurine_brick_wall.json 8bb8a9f8e8dd0d6585311c326dcf3f40227149a9 data/create/recipes/cut_asurine_brick_wall_from_stone_types_asurine_stonecutting.json +e335b15907be053ab0f2649338b12a86371b78f7 data/create/recipes/cut_asurine_bricks_from_stone_types_asurine_stonecutting.json 0188d62fbeede94f8596dd5cc73d361a160e8c95 data/create/recipes/cut_asurine_from_stone_types_asurine_stonecutting.json 118e87a2a344238009b1bbbe70e6f314e27842d9 data/create/recipes/cut_asurine_slab.json 37c502094ee96da9e4983142dae5e023c6bcfe14 data/create/recipes/cut_asurine_slab_from_stone_types_asurine_stonecutting.json @@ -4168,7 +4168,6 @@ fe3dd5c7d5bdea71a75003cf3d50439d9d21458d data/create/recipes/cut_asurine_slab_re cade93c9328afcacf4507aa7699c4b09fb4592d4 data/create/recipes/cut_asurine_stairs_from_stone_types_asurine_stonecutting.json 80bec79b5daea4b2b72c0f5e9f189c1044583465 data/create/recipes/cut_asurine_wall.json 45a712e41a74982cfb94a39da199ec6c95eef798 data/create/recipes/cut_asurine_wall_from_stone_types_asurine_stonecutting.json -da11f21280ba1ed06ffe8afe77db3e9e1bbcb1a3 data/create/recipes/cut_calcite_bricks_from_stone_types_calcite_stonecutting.json 98e849c743ed1e4397bf6168215dfa7006a804c4 data/create/recipes/cut_calcite_brick_slab.json 1c21eb6c785729a8ea274513e1313aed952e105e data/create/recipes/cut_calcite_brick_slab_from_stone_types_calcite_stonecutting.json 2a3f078f7f40ba3bc5c17a037db1f8ee415e4e3f data/create/recipes/cut_calcite_brick_slab_recycling.json @@ -4176,6 +4175,7 @@ e4267c62bc6cfc8373df29ee2685f1e1b286b638 data/create/recipes/cut_calcite_brick_s 10fe509e01e3ed1b04bd2f384c0aa3db96b117f1 data/create/recipes/cut_calcite_brick_stairs_from_stone_types_calcite_stonecutting.json 9b55a6c9cf0ce697a242684953daf9aa94d024dc data/create/recipes/cut_calcite_brick_wall.json 1e67376e484923b84bd64b0b22b4e55b581ac419 data/create/recipes/cut_calcite_brick_wall_from_stone_types_calcite_stonecutting.json +da11f21280ba1ed06ffe8afe77db3e9e1bbcb1a3 data/create/recipes/cut_calcite_bricks_from_stone_types_calcite_stonecutting.json 98b014b64c97371f04aaacbdd23e13e274e36e3b data/create/recipes/cut_calcite_from_stone_types_calcite_stonecutting.json fcab91f11fe97a194b2c1b16115206166d3cd634 data/create/recipes/cut_calcite_slab.json 8426a494b776148056cb4525e62744d0be8b28cd data/create/recipes/cut_calcite_slab_from_stone_types_calcite_stonecutting.json @@ -4184,7 +4184,6 @@ fcab91f11fe97a194b2c1b16115206166d3cd634 data/create/recipes/cut_calcite_slab.js a7e7fb425d3c1f21f5ed53da79957363fed824df data/create/recipes/cut_calcite_stairs_from_stone_types_calcite_stonecutting.json 73eaf7bffa38bc874974871f3002cd3ee7f0c36e data/create/recipes/cut_calcite_wall.json 01b4c23362f15ee0e5c207c46383f96032c89d98 data/create/recipes/cut_calcite_wall_from_stone_types_calcite_stonecutting.json -07aff2bb6424de46463b2c965418ed52efd0a790 data/create/recipes/cut_crimsite_bricks_from_stone_types_crimsite_stonecutting.json 8ffb2c1c747f19ea37c0da3fe248b6c58981c9f6 data/create/recipes/cut_crimsite_brick_slab.json 86c3a5c64561052489b3ceb9e08be5a8729198a9 data/create/recipes/cut_crimsite_brick_slab_from_stone_types_crimsite_stonecutting.json e3215d4e651e70402b896ba50975cb2f23d16278 data/create/recipes/cut_crimsite_brick_slab_recycling.json @@ -4192,6 +4191,7 @@ e49f6e319fae9058cbece0e332a11e108234e608 data/create/recipes/cut_crimsite_brick_ c7186fb1a75f59aff929e843f50a162a090b7bb3 data/create/recipes/cut_crimsite_brick_stairs_from_stone_types_crimsite_stonecutting.json 272d8d01730a88eff4fc6923e93962650b992c46 data/create/recipes/cut_crimsite_brick_wall.json 13ac9464098e8c67e820dc898c025ab0382d852a data/create/recipes/cut_crimsite_brick_wall_from_stone_types_crimsite_stonecutting.json +07aff2bb6424de46463b2c965418ed52efd0a790 data/create/recipes/cut_crimsite_bricks_from_stone_types_crimsite_stonecutting.json 18ce9ff32eda2d869bd11f398a86e78b71f6d0fe data/create/recipes/cut_crimsite_from_stone_types_crimsite_stonecutting.json c39166aa6267ec5bc71893d5756955abfb644217 data/create/recipes/cut_crimsite_slab.json 6271d5bc0377814ba06061bfffcb812ca2ef8f03 data/create/recipes/cut_crimsite_slab_from_stone_types_crimsite_stonecutting.json @@ -4200,7 +4200,6 @@ acfe33dbb889c820c213bcbc8593766703bf3a25 data/create/recipes/cut_crimsite_slab_r 90b03cf1e72d3b803e33755832e0722ff264681b data/create/recipes/cut_crimsite_stairs_from_stone_types_crimsite_stonecutting.json 8dfe19522878af232deaa1fc13d83cf785684cba data/create/recipes/cut_crimsite_wall.json 18f9548175baab0173785d7ef308096067712dd2 data/create/recipes/cut_crimsite_wall_from_stone_types_crimsite_stonecutting.json -de1a11b7ed71f1f7aeea2791fe922feef689fd35 data/create/recipes/cut_deepslate_bricks_from_stone_types_deepslate_stonecutting.json 5e5c0e6b1b3e204de3c48fb6a4cd473a150979c2 data/create/recipes/cut_deepslate_brick_slab.json 2c0795b92759dab751f86f50aa80440df2245526 data/create/recipes/cut_deepslate_brick_slab_from_stone_types_deepslate_stonecutting.json dbcc41c48cf28b71dcd9f3b6ecae43c8de681532 data/create/recipes/cut_deepslate_brick_slab_recycling.json @@ -4208,6 +4207,7 @@ e21f8dc33e70ebd43ea79a4afaf3b4e8a449f4bd data/create/recipes/cut_deepslate_brick 7b3489e5b629a995691be117c5a378769c743449 data/create/recipes/cut_deepslate_brick_stairs_from_stone_types_deepslate_stonecutting.json 158bb41bffebb2543e4aa2d5f14cc8af1cdd8671 data/create/recipes/cut_deepslate_brick_wall.json 73a07a5fa665bb20d131f0a0e40806116316928a data/create/recipes/cut_deepslate_brick_wall_from_stone_types_deepslate_stonecutting.json +de1a11b7ed71f1f7aeea2791fe922feef689fd35 data/create/recipes/cut_deepslate_bricks_from_stone_types_deepslate_stonecutting.json 992fdc2eba2afe3ff8aad0ceee5424ecd3f3026d data/create/recipes/cut_deepslate_from_stone_types_deepslate_stonecutting.json 064e2f5edd9209af7742b0f0eb45204453bed46f data/create/recipes/cut_deepslate_slab.json f341d30b7fd427dea09a51d67e1e9532e5184be8 data/create/recipes/cut_deepslate_slab_from_stone_types_deepslate_stonecutting.json @@ -4216,7 +4216,6 @@ c08e12e44344efca550efa8ba14d0cb2f9f6c2c6 data/create/recipes/cut_deepslate_stair e6deec1352fb5c74c470dc488b71e5f8f55bdfbf data/create/recipes/cut_deepslate_stairs_from_stone_types_deepslate_stonecutting.json 2ad7fb3f3a143e58bea8eefe4cd9db3d1c37a3e6 data/create/recipes/cut_deepslate_wall.json e752527479f71f96bb34878008bf8cfb23fd3045 data/create/recipes/cut_deepslate_wall_from_stone_types_deepslate_stonecutting.json -2c23d13f48f3685bda6c564e080053fbfa71ab99 data/create/recipes/cut_diorite_bricks_from_stone_types_diorite_stonecutting.json 90b83c2a2026d70f49c91813305fdee721926db9 data/create/recipes/cut_diorite_brick_slab.json 9d51c690c77321437561a006dc2f9bba975875e6 data/create/recipes/cut_diorite_brick_slab_from_stone_types_diorite_stonecutting.json fa76e64ac9b569f5d5f2f1ecc54e51f9be15aacf data/create/recipes/cut_diorite_brick_slab_recycling.json @@ -4224,6 +4223,7 @@ aa6aea99e9ce2d5dc3d6555ab3d17928bca6195e data/create/recipes/cut_diorite_brick_s 9a26c4097519a9300e591b6578bbaf6c11f909e1 data/create/recipes/cut_diorite_brick_stairs_from_stone_types_diorite_stonecutting.json 78d37df17c7e2be73ce1d226ee552ff3f49b9e4f data/create/recipes/cut_diorite_brick_wall.json f668f2c78a779bc3d0546a82dea02b9f4688e05c data/create/recipes/cut_diorite_brick_wall_from_stone_types_diorite_stonecutting.json +2c23d13f48f3685bda6c564e080053fbfa71ab99 data/create/recipes/cut_diorite_bricks_from_stone_types_diorite_stonecutting.json 1918ecb2ab16ca7dbb30eee4852b67dd963d872e data/create/recipes/cut_diorite_from_stone_types_diorite_stonecutting.json 07fda5c89128648856f948a03ac56a2a2693cf1b data/create/recipes/cut_diorite_slab.json 28765ac7f8b62373b32f014d1dd7f4afb50e1906 data/create/recipes/cut_diorite_slab_from_stone_types_diorite_stonecutting.json @@ -4232,7 +4232,6 @@ dd5f3c59a5d292f7b5c046be35da7f67e8383aa1 data/create/recipes/cut_diorite_slab_re be2c6c01630b90895e7215edce3d02352793dbc4 data/create/recipes/cut_diorite_stairs_from_stone_types_diorite_stonecutting.json 8984b7b7dbc7e65ee04886516501a13278e889e9 data/create/recipes/cut_diorite_wall.json 8ff5d1ecff2202595f7cba5bd65c466c53ac2cc5 data/create/recipes/cut_diorite_wall_from_stone_types_diorite_stonecutting.json -10550b023989113c26d430136daf1dc49f10ce63 data/create/recipes/cut_dripstone_bricks_from_stone_types_dripstone_stonecutting.json 95717a80bb8ae296c2f77478a8f42b88cea88996 data/create/recipes/cut_dripstone_brick_slab.json f04bf1189b53e24974779d9e959e8973d9677162 data/create/recipes/cut_dripstone_brick_slab_from_stone_types_dripstone_stonecutting.json 332534fc2909ca83f5f7f4ab3adf92680bb17f79 data/create/recipes/cut_dripstone_brick_slab_recycling.json @@ -4240,6 +4239,7 @@ f04bf1189b53e24974779d9e959e8973d9677162 data/create/recipes/cut_dripstone_brick 17bf8160eaf16655d454ddfe22b82c9a86462146 data/create/recipes/cut_dripstone_brick_stairs_from_stone_types_dripstone_stonecutting.json 7d638d156326a2e542ed94837273d9cca5cf4fce data/create/recipes/cut_dripstone_brick_wall.json 154931db54115cf4a64147cdd6d1eb7efff48737 data/create/recipes/cut_dripstone_brick_wall_from_stone_types_dripstone_stonecutting.json +10550b023989113c26d430136daf1dc49f10ce63 data/create/recipes/cut_dripstone_bricks_from_stone_types_dripstone_stonecutting.json 7147f9199f174c9864109fe5723528921aaa0c46 data/create/recipes/cut_dripstone_from_stone_types_dripstone_stonecutting.json f2800b467eac75d0099f2f07e09b47115df4e09f data/create/recipes/cut_dripstone_slab.json a4f62a1a30592f82789988f93d8ae35d176eca59 data/create/recipes/cut_dripstone_slab_from_stone_types_dripstone_stonecutting.json @@ -4248,7 +4248,6 @@ a4f62a1a30592f82789988f93d8ae35d176eca59 data/create/recipes/cut_dripstone_slab_ f2df5efedb6fb25ecb877b888007990082d9aca4 data/create/recipes/cut_dripstone_stairs_from_stone_types_dripstone_stonecutting.json a177092d0270f9e07a4f9bef4d0c8fb2ed91d3bc data/create/recipes/cut_dripstone_wall.json a3731ef689d3ac790bc3e3fd507f1134c99a751a data/create/recipes/cut_dripstone_wall_from_stone_types_dripstone_stonecutting.json -9c4c64666b18d3adb11cd3d56667fabf6e88dfe2 data/create/recipes/cut_granite_bricks_from_stone_types_granite_stonecutting.json aa454bebffd7e77cfa5c1bd711bfbac27e3c5a14 data/create/recipes/cut_granite_brick_slab.json d073b9b0b8ca2fbdc5e1ed16f6f195a5f3af4588 data/create/recipes/cut_granite_brick_slab_from_stone_types_granite_stonecutting.json 1dfd539c17a3342a0cd194ce1465a808aacbeda3 data/create/recipes/cut_granite_brick_slab_recycling.json @@ -4256,6 +4255,7 @@ e069aa5c316feb2823ef98e8e6c89bb1bed23d2e data/create/recipes/cut_granite_brick_s f38fc7014aa83d4914d50d87ee3f8f762c078a78 data/create/recipes/cut_granite_brick_stairs_from_stone_types_granite_stonecutting.json 0fd9c3a778c7bdcd7aa06f892a9c260ad664d367 data/create/recipes/cut_granite_brick_wall.json b81db94b6228f512049324dd1436880f1e86e444 data/create/recipes/cut_granite_brick_wall_from_stone_types_granite_stonecutting.json +9c4c64666b18d3adb11cd3d56667fabf6e88dfe2 data/create/recipes/cut_granite_bricks_from_stone_types_granite_stonecutting.json 01970a95f17648a7ef1fb0337ee2e82eb2279e9e data/create/recipes/cut_granite_from_stone_types_granite_stonecutting.json 8fc1c51591e590c8718be0500a4dbcc2b47830ce data/create/recipes/cut_granite_slab.json d239323b7a3b65b2fd7005350a90d578671c2b81 data/create/recipes/cut_granite_slab_from_stone_types_granite_stonecutting.json @@ -4264,7 +4264,6 @@ d239323b7a3b65b2fd7005350a90d578671c2b81 data/create/recipes/cut_granite_slab_fr 3d85d483073d37fea7d9a95831b3b856c0725b98 data/create/recipes/cut_granite_stairs_from_stone_types_granite_stonecutting.json 3d4130fe5fe6e963fd5e10534e729e0448b9f05f data/create/recipes/cut_granite_wall.json d43a876bf89bf3536c80fd5e3ef0ee36c147cd06 data/create/recipes/cut_granite_wall_from_stone_types_granite_stonecutting.json -7cdd3cf302cfe4ef21c0a89dadef4f781e307bb0 data/create/recipes/cut_limestone_bricks_from_stone_types_limestone_stonecutting.json 0e3285206947bcfdf9606d3f8e61ea7d2899f7d2 data/create/recipes/cut_limestone_brick_slab.json c3d3ff37e29c435b2a13d30bd4ded0f6ca9fbfbc data/create/recipes/cut_limestone_brick_slab_from_stone_types_limestone_stonecutting.json 459babb2bd01e9e1ece4c8cd2865690997f01c66 data/create/recipes/cut_limestone_brick_slab_recycling.json @@ -4272,6 +4271,7 @@ d4f8dc640becf1c35416016500424ecd68d7ecee data/create/recipes/cut_limestone_brick 570983b2b27862dabe9f3d1bcd76d2909b8bdb3c data/create/recipes/cut_limestone_brick_stairs_from_stone_types_limestone_stonecutting.json aad4342a726fd65ca2b4c52a4e8857190e50b5be data/create/recipes/cut_limestone_brick_wall.json 5ac226aff9d854efc47ed71241e6c098b170b9b0 data/create/recipes/cut_limestone_brick_wall_from_stone_types_limestone_stonecutting.json +7cdd3cf302cfe4ef21c0a89dadef4f781e307bb0 data/create/recipes/cut_limestone_bricks_from_stone_types_limestone_stonecutting.json 329950373aaaf8e70c54cf5e2467c7a84f372078 data/create/recipes/cut_limestone_from_stone_types_limestone_stonecutting.json cbacfd31703ac908d28e42968bb571dccfa20612 data/create/recipes/cut_limestone_slab.json 628a0a64c2dcd63f17a3ec9ce55ac643b194eacc data/create/recipes/cut_limestone_slab_from_stone_types_limestone_stonecutting.json @@ -4280,7 +4280,6 @@ cbacfd31703ac908d28e42968bb571dccfa20612 data/create/recipes/cut_limestone_slab. ba301da212ee14ff42c38487d0906a2da203e3c3 data/create/recipes/cut_limestone_stairs_from_stone_types_limestone_stonecutting.json d2aac4ac16f9c842af1efd3896dd3250f6d8424e data/create/recipes/cut_limestone_wall.json b14e6972f8586e569a7ab4ecf6ed5d6db1a2bded data/create/recipes/cut_limestone_wall_from_stone_types_limestone_stonecutting.json -a1a2b95283d88e1d990e00da9a095fe928b2aa2f data/create/recipes/cut_ochrum_bricks_from_stone_types_ochrum_stonecutting.json d5a4fa7787d2e56e0b5c8d533567543b93cf694b data/create/recipes/cut_ochrum_brick_slab.json 58514a5f216706e9bb62b27ad03701fe02bac013 data/create/recipes/cut_ochrum_brick_slab_from_stone_types_ochrum_stonecutting.json 6cc3167ebf075d7b302a359d1afdddf5753d0e26 data/create/recipes/cut_ochrum_brick_slab_recycling.json @@ -4288,6 +4287,7 @@ d5a4fa7787d2e56e0b5c8d533567543b93cf694b data/create/recipes/cut_ochrum_brick_sl ec6339d6658b0d32e46c8a4a4e06d94a388a6332 data/create/recipes/cut_ochrum_brick_stairs_from_stone_types_ochrum_stonecutting.json c4139ae7a9742f7111d308fe66bf1d627533550b data/create/recipes/cut_ochrum_brick_wall.json 1b8a4c81680df542a5e6b9e665c96649cf3eb7fa data/create/recipes/cut_ochrum_brick_wall_from_stone_types_ochrum_stonecutting.json +a1a2b95283d88e1d990e00da9a095fe928b2aa2f data/create/recipes/cut_ochrum_bricks_from_stone_types_ochrum_stonecutting.json 2b967f3424196b5da9b396ea58fb969d406af789 data/create/recipes/cut_ochrum_from_stone_types_ochrum_stonecutting.json 5baa701f3cbe8d69e2e6a5554622dd78ef3ac451 data/create/recipes/cut_ochrum_slab.json 9a26cba276cf135a10c71d31f5b960b2ee6ac444 data/create/recipes/cut_ochrum_slab_from_stone_types_ochrum_stonecutting.json @@ -4296,7 +4296,6 @@ c4139ae7a9742f7111d308fe66bf1d627533550b data/create/recipes/cut_ochrum_brick_wa 75a232ccede0ffa7feb3e69da17c6a514a908907 data/create/recipes/cut_ochrum_stairs_from_stone_types_ochrum_stonecutting.json d9c05b7e4ce4ee86d0f6a9e1ee6c1b585ffee58b data/create/recipes/cut_ochrum_wall.json ee0dff8e1317aeffd061688879b97e81a00b7adb data/create/recipes/cut_ochrum_wall_from_stone_types_ochrum_stonecutting.json -087eefb8ffd61fd88f1db6ca25f9ac31e93f2fdf data/create/recipes/cut_scorchia_bricks_from_stone_types_scorchia_stonecutting.json 72ac9293e5791df07914e2d3ed00e5ff59d64b08 data/create/recipes/cut_scorchia_brick_slab.json 2f38c410d5eb93bdb8c8be0f68ac89726e3c765c data/create/recipes/cut_scorchia_brick_slab_from_stone_types_scorchia_stonecutting.json e296e6af6865bf6e4618dab8a96bb88f6999a9a5 data/create/recipes/cut_scorchia_brick_slab_recycling.json @@ -4304,6 +4303,7 @@ bd5984a6b96443319b7fad32db771d8ded0b0591 data/create/recipes/cut_scorchia_brick_ bd5c803c855222a29998dd784e6d12a18dd612d9 data/create/recipes/cut_scorchia_brick_stairs_from_stone_types_scorchia_stonecutting.json adfe0b08b5b72e579d47f36a4f835045e433e7f7 data/create/recipes/cut_scorchia_brick_wall.json 37fc5ae45d0260de9a5c45b0a1b208e4d146a562 data/create/recipes/cut_scorchia_brick_wall_from_stone_types_scorchia_stonecutting.json +087eefb8ffd61fd88f1db6ca25f9ac31e93f2fdf data/create/recipes/cut_scorchia_bricks_from_stone_types_scorchia_stonecutting.json f6dfd648418f24da093b80978c2f6e070f33ff6d data/create/recipes/cut_scorchia_from_stone_types_scorchia_stonecutting.json 7df99605c0c8761aeb9301d5391e1f16d41f89b3 data/create/recipes/cut_scorchia_slab.json fbd9a92d3c3d9e823cac51347320219f1734ec04 data/create/recipes/cut_scorchia_slab_from_stone_types_scorchia_stonecutting.json @@ -4312,7 +4312,6 @@ ad54182c3142ac9d9dd9bb4c5acc18f82e3fc5e5 data/create/recipes/cut_scorchia_stairs 1ddfefce136201ae78dbc53ba472080332fd6366 data/create/recipes/cut_scorchia_stairs_from_stone_types_scorchia_stonecutting.json 0a011b7cee33200fec5546168734c330952124da data/create/recipes/cut_scorchia_wall.json c594d886a303ad6e24d1283004442835ee861fbc data/create/recipes/cut_scorchia_wall_from_stone_types_scorchia_stonecutting.json -8650c0db70a3521b50404252106e0185b4f25a45 data/create/recipes/cut_scoria_bricks_from_stone_types_scoria_stonecutting.json 8baf09b5ff2004d71091b6f95307aa179a21f4df data/create/recipes/cut_scoria_brick_slab.json e7080ca9b6a507bec4a4a3dd52a28c1c33975628 data/create/recipes/cut_scoria_brick_slab_from_stone_types_scoria_stonecutting.json f5b56f6eb9c1ac0f8168b2b0f0b0ab00655ebfdb data/create/recipes/cut_scoria_brick_slab_recycling.json @@ -4320,6 +4319,7 @@ f5b56f6eb9c1ac0f8168b2b0f0b0ab00655ebfdb data/create/recipes/cut_scoria_brick_sl 3fd560355163f0afafefe886e75fd8b2c3cf2b6f data/create/recipes/cut_scoria_brick_stairs_from_stone_types_scoria_stonecutting.json ed803a4cdcf1dd01af03fff52e783f3539f78546 data/create/recipes/cut_scoria_brick_wall.json 553642a4e0dc5f934da8127a427ccdf53d3f51f9 data/create/recipes/cut_scoria_brick_wall_from_stone_types_scoria_stonecutting.json +8650c0db70a3521b50404252106e0185b4f25a45 data/create/recipes/cut_scoria_bricks_from_stone_types_scoria_stonecutting.json 5702063be3d38fa6b3ae5c998337676a0cf91149 data/create/recipes/cut_scoria_from_stone_types_scoria_stonecutting.json 295356022aee8a33272b430879615af638fc5a2c data/create/recipes/cut_scoria_slab.json 1656e822e823fcdf04120b55235aa477845a69a6 data/create/recipes/cut_scoria_slab_from_stone_types_scoria_stonecutting.json @@ -4328,7 +4328,6 @@ d0c88c037004911e377d88cf5a28ff85a413d07e data/create/recipes/cut_scoria_slab_rec 8748df6152c923930452397367562bb6007058cf data/create/recipes/cut_scoria_stairs_from_stone_types_scoria_stonecutting.json 7f9bd9de7bfba21eef449f8e11ffc8cf37de6b88 data/create/recipes/cut_scoria_wall.json 42235c6ded520ecda3321e8cd8910dcfa05cd61e data/create/recipes/cut_scoria_wall_from_stone_types_scoria_stonecutting.json -c02b4daf0050d705c145c0698aaa3094724ba2f1 data/create/recipes/cut_tuff_bricks_from_stone_types_tuff_stonecutting.json 214b6219b86d94ea5705e40f254a4d9a9ac894b7 data/create/recipes/cut_tuff_brick_slab.json 9e0182206fab754daa0596259be0b98a712ba859 data/create/recipes/cut_tuff_brick_slab_from_stone_types_tuff_stonecutting.json 86938ed4ef969e85163c25e2a60181433247b73b data/create/recipes/cut_tuff_brick_slab_recycling.json @@ -4336,6 +4335,7 @@ b4212528d6c8893c1d57c0a5ada60673105e399d data/create/recipes/cut_tuff_brick_stai 90f3241a3eb47d9b0902b639fadee76e41b92a72 data/create/recipes/cut_tuff_brick_stairs_from_stone_types_tuff_stonecutting.json b920d14ac41465f70b1fb8211c1c06d6c41ccadb data/create/recipes/cut_tuff_brick_wall.json aa41f89028dfa995dc11b881894e5a5993e4c4f9 data/create/recipes/cut_tuff_brick_wall_from_stone_types_tuff_stonecutting.json +c02b4daf0050d705c145c0698aaa3094724ba2f1 data/create/recipes/cut_tuff_bricks_from_stone_types_tuff_stonecutting.json 41dc800ae0a8918f4602d610ff0ba9714cdfe8dc data/create/recipes/cut_tuff_from_stone_types_tuff_stonecutting.json 573fff8b4fba92289dc6b113b58c8de25427f62d data/create/recipes/cut_tuff_slab.json 94667fb1e6203bd66bef10acfee7cd990009d26f data/create/recipes/cut_tuff_slab_from_stone_types_tuff_stonecutting.json @@ -4344,7 +4344,6 @@ aa41f89028dfa995dc11b881894e5a5993e4c4f9 data/create/recipes/cut_tuff_brick_wall 3b3ba319bd67a4e7f555cfcb54f9dc1fc22cf015 data/create/recipes/cut_tuff_stairs_from_stone_types_tuff_stonecutting.json 0c241d763e87b23b8799528e132e0d12b0e16141 data/create/recipes/cut_tuff_wall.json 5705b0312c5c70d48662c2ff375f0b2cfe3b4902 data/create/recipes/cut_tuff_wall_from_stone_types_tuff_stonecutting.json -8ab3c640b57421a8c0341ab4ec5bade31376d059 data/create/recipes/cut_veridium_bricks_from_stone_types_veridium_stonecutting.json 822f97726c72d31c4c614767c08140b3535e0640 data/create/recipes/cut_veridium_brick_slab.json 1705fd5fc9ecc9a650812c89f500b5ef9aec2626 data/create/recipes/cut_veridium_brick_slab_from_stone_types_veridium_stonecutting.json 238aeedf55624671809a37246581d28fe6b2c19e data/create/recipes/cut_veridium_brick_slab_recycling.json @@ -4352,6 +4351,7 @@ dfbef691643cead7111b3b1c51aabcda8419bc19 data/create/recipes/cut_veridium_brick_ db2ea87f3ec8924ba9e0b87cd6a6edeb93c0c2d8 data/create/recipes/cut_veridium_brick_stairs_from_stone_types_veridium_stonecutting.json 5e5c9fab7ba7143d206df7d8184742fb1a17c99c data/create/recipes/cut_veridium_brick_wall.json ed752a7f698e3ecbb5e4f848a78f8b3c7c6bf12e data/create/recipes/cut_veridium_brick_wall_from_stone_types_veridium_stonecutting.json +8ab3c640b57421a8c0341ab4ec5bade31376d059 data/create/recipes/cut_veridium_bricks_from_stone_types_veridium_stonecutting.json e0355543105e4ec9d672d2a050e70b5c198ea472 data/create/recipes/cut_veridium_from_stone_types_veridium_stonecutting.json fb3c671f64676538ea3aa96be483ac15b3cdeb3d data/create/recipes/cut_veridium_slab.json 7d7c80ac03ad8623f9a5d7f0ff0bb6f68985efa5 data/create/recipes/cut_veridium_slab_from_stone_types_veridium_stonecutting.json @@ -4537,7 +4537,6 @@ a157a43e7788d285b8d72eade5955369c9b9a1de data/create/recipes/rose_quartz_block_f 1268cc2bdd088d26b84fb4e481db27af61f94bd1 data/create/recipes/scorchia_pillar_from_stone_types_scorchia_stonecutting.json 2e8f4cdb3498547a5e6fe658bb33d4be5ce8f54b data/create/recipes/scoria_from_stone_types_scoria_stonecutting.json 770d3453c75f77b16db661f6e636892d3117690b data/create/recipes/scoria_pillar_from_stone_types_scoria_stonecutting.json -75dc56fcdcd6a10288f2d607bf6dcbbe10b35a64 data/create/recipes/small_andesite_bricks_from_stone_types_andesite_stonecutting.json 2e86fddc76285b4e380b845eb1150580b134d0ac data/create/recipes/small_andesite_brick_slab.json 311727e5c08ddbe0aa26275be74e9b83201ac8ab data/create/recipes/small_andesite_brick_slab_from_stone_types_andesite_stonecutting.json 2767e239c9d704b6bb5325b4f40e0aa0acdcdce1 data/create/recipes/small_andesite_brick_slab_recycling.json @@ -4545,7 +4544,7 @@ a157a43e7788d285b8d72eade5955369c9b9a1de data/create/recipes/rose_quartz_block_f 9e82896e00c1e14e514fac818e11e5b9ef5b10d7 data/create/recipes/small_andesite_brick_stairs_from_stone_types_andesite_stonecutting.json 5287d389b4954d954881d9f0293c52870bba88d0 data/create/recipes/small_andesite_brick_wall.json 1172ca76affd948c50b207124ee03c4f480f4ee8 data/create/recipes/small_andesite_brick_wall_from_stone_types_andesite_stonecutting.json -e3b69122b2cfe64b043384235eeb6d04f346e58b data/create/recipes/small_asurine_bricks_from_stone_types_asurine_stonecutting.json +75dc56fcdcd6a10288f2d607bf6dcbbe10b35a64 data/create/recipes/small_andesite_bricks_from_stone_types_andesite_stonecutting.json 9196a055491052afc14ed01667cccf2a0920e793 data/create/recipes/small_asurine_brick_slab.json f4cc3330837a647c098ccb24fbbbf583c3f960fc data/create/recipes/small_asurine_brick_slab_from_stone_types_asurine_stonecutting.json 063b2f0ad7e93698999922040132eb2b23661a38 data/create/recipes/small_asurine_brick_slab_recycling.json @@ -4553,7 +4552,7 @@ a85d2f957223f87ffa2c3f63cdf6f9f0f84bb921 data/create/recipes/small_asurine_brick c7cb218b0d8a1e358d593fc1fef82fc074289552 data/create/recipes/small_asurine_brick_stairs_from_stone_types_asurine_stonecutting.json 08d10ee57995e67ac1fb5feba04b03aee51dbe16 data/create/recipes/small_asurine_brick_wall.json 4c0aa6203295a36a6d7ffe9d7bf0973277162689 data/create/recipes/small_asurine_brick_wall_from_stone_types_asurine_stonecutting.json -07125218f9025833afa189fa0090f4d6b4660db0 data/create/recipes/small_calcite_bricks_from_stone_types_calcite_stonecutting.json +e3b69122b2cfe64b043384235eeb6d04f346e58b data/create/recipes/small_asurine_bricks_from_stone_types_asurine_stonecutting.json a72719de028ca9e07756dae6031af48525520fc2 data/create/recipes/small_calcite_brick_slab.json d8ebf6f1eb2e2372fb20def956398089adec5d13 data/create/recipes/small_calcite_brick_slab_from_stone_types_calcite_stonecutting.json ab4cfc2b34989d41a434781a3150ecd530c4f15b data/create/recipes/small_calcite_brick_slab_recycling.json @@ -4561,7 +4560,7 @@ c77a7700d978e23db14d947915591061dda8eab3 data/create/recipes/small_calcite_brick 4e066bfc60ea142d54ce939d025b6679ac9634ad data/create/recipes/small_calcite_brick_stairs_from_stone_types_calcite_stonecutting.json 64e53d8090fa26cc4cb62efea7c1615ff7f705c2 data/create/recipes/small_calcite_brick_wall.json 3ba736ae76249fa61692c13f7879af954f9bbd36 data/create/recipes/small_calcite_brick_wall_from_stone_types_calcite_stonecutting.json -a3309c81f84bf4fb78e9db2316fb758f9b2f8429 data/create/recipes/small_crimsite_bricks_from_stone_types_crimsite_stonecutting.json +07125218f9025833afa189fa0090f4d6b4660db0 data/create/recipes/small_calcite_bricks_from_stone_types_calcite_stonecutting.json 92cf7e99229c1e72405bb0875e6f939b3f5aea12 data/create/recipes/small_crimsite_brick_slab.json b993e081103c019b7b9b73b38ef8c408fb4500ac data/create/recipes/small_crimsite_brick_slab_from_stone_types_crimsite_stonecutting.json 7f6fa1fab65d910388f5f2ec4ee7d99cbda8df57 data/create/recipes/small_crimsite_brick_slab_recycling.json @@ -4569,7 +4568,7 @@ b993e081103c019b7b9b73b38ef8c408fb4500ac data/create/recipes/small_crimsite_bric 260da721849d1afd6f431d51538d1587ee3af8d5 data/create/recipes/small_crimsite_brick_stairs_from_stone_types_crimsite_stonecutting.json 093ac919f793111b442029198383a9de5b6df027 data/create/recipes/small_crimsite_brick_wall.json 8b8280a8282fa8718620ee3d69182e241a7852c0 data/create/recipes/small_crimsite_brick_wall_from_stone_types_crimsite_stonecutting.json -e7a3cb889ce6b530cd40f19e23bad943374e61b5 data/create/recipes/small_deepslate_bricks_from_stone_types_deepslate_stonecutting.json +a3309c81f84bf4fb78e9db2316fb758f9b2f8429 data/create/recipes/small_crimsite_bricks_from_stone_types_crimsite_stonecutting.json 022690548a46f5cc63adda3626824a81c6ebf490 data/create/recipes/small_deepslate_brick_slab.json 655be9ddf21dea2255fb2cb2628a5fee39eb10e2 data/create/recipes/small_deepslate_brick_slab_from_stone_types_deepslate_stonecutting.json d6d3db5604279cd402f64dbdeae7c3bee6d7ab78 data/create/recipes/small_deepslate_brick_slab_recycling.json @@ -4577,7 +4576,7 @@ d6d3db5604279cd402f64dbdeae7c3bee6d7ab78 data/create/recipes/small_deepslate_bri 0a458e8248fe395748bd6025d43c002db5a7d343 data/create/recipes/small_deepslate_brick_stairs_from_stone_types_deepslate_stonecutting.json 96e2c36ac2f2899c9681f12f43c8ae232ae09180 data/create/recipes/small_deepslate_brick_wall.json e5644f4227b9cc9b98158ce3ded98bff1ffb97f9 data/create/recipes/small_deepslate_brick_wall_from_stone_types_deepslate_stonecutting.json -38b80603a86df24f6be0df9fd5f7d9b7aa33d2f9 data/create/recipes/small_diorite_bricks_from_stone_types_diorite_stonecutting.json +e7a3cb889ce6b530cd40f19e23bad943374e61b5 data/create/recipes/small_deepslate_bricks_from_stone_types_deepslate_stonecutting.json 6c66b44941c8b97cfec5948b5d8b08355f8d8f67 data/create/recipes/small_diorite_brick_slab.json 801f6cc6e06db56344b37c9b76c69f921c6d9293 data/create/recipes/small_diorite_brick_slab_from_stone_types_diorite_stonecutting.json c1fe4bff306e2d2b5d5595e4b35dd85f7e6bf0ce data/create/recipes/small_diorite_brick_slab_recycling.json @@ -4585,7 +4584,7 @@ af6feedf00bdfa45c1b8f0dd46ddaa80da622fed data/create/recipes/small_diorite_brick 30a6f2bdfec2b3f578572c9f94112906411e7c54 data/create/recipes/small_diorite_brick_stairs_from_stone_types_diorite_stonecutting.json 8728b791808736de2ac31e8dc81aa43638ae0ac8 data/create/recipes/small_diorite_brick_wall.json 7a1fdcef7091d76230fbee410fa5241f584845c4 data/create/recipes/small_diorite_brick_wall_from_stone_types_diorite_stonecutting.json -8840d538648516dd02628fbe3ea4f032ceda78bb data/create/recipes/small_dripstone_bricks_from_stone_types_dripstone_stonecutting.json +38b80603a86df24f6be0df9fd5f7d9b7aa33d2f9 data/create/recipes/small_diorite_bricks_from_stone_types_diorite_stonecutting.json 39a545b60040bd2d922cd3bd5af5036b1b9b23ef data/create/recipes/small_dripstone_brick_slab.json c91e4dc211305456c38e5823def91811ad851202 data/create/recipes/small_dripstone_brick_slab_from_stone_types_dripstone_stonecutting.json 55bb37d07e841bb8eecf2013445c01c8e09ff824 data/create/recipes/small_dripstone_brick_slab_recycling.json @@ -4593,7 +4592,7 @@ c91e4dc211305456c38e5823def91811ad851202 data/create/recipes/small_dripstone_bri 1e23c8df90aef6cd3561369f72c6c3106da883f5 data/create/recipes/small_dripstone_brick_stairs_from_stone_types_dripstone_stonecutting.json fda46cc15c21e7843537df5b5331874fd7511e19 data/create/recipes/small_dripstone_brick_wall.json 336e47b35437ffea4bb86d34f94e6361b2bbcfb0 data/create/recipes/small_dripstone_brick_wall_from_stone_types_dripstone_stonecutting.json -42c74dec6c64d3675e15b2b73cb32fc9d24839e9 data/create/recipes/small_granite_bricks_from_stone_types_granite_stonecutting.json +8840d538648516dd02628fbe3ea4f032ceda78bb data/create/recipes/small_dripstone_bricks_from_stone_types_dripstone_stonecutting.json d1bb4e91d80ca8eb9c2f935cbb66ef08b9ca7059 data/create/recipes/small_granite_brick_slab.json ddb2f4652607b56332a927af939212a5789a34db data/create/recipes/small_granite_brick_slab_from_stone_types_granite_stonecutting.json f1388636bcf98d7d9103c23528053b28c6305b4e data/create/recipes/small_granite_brick_slab_recycling.json @@ -4601,7 +4600,7 @@ f1388636bcf98d7d9103c23528053b28c6305b4e data/create/recipes/small_granite_brick ba935a3d64eedbd9b7017d0abfab351f57589593 data/create/recipes/small_granite_brick_stairs_from_stone_types_granite_stonecutting.json dac22c54e8034587a3fcf3aa0ce19bb4b7607cd7 data/create/recipes/small_granite_brick_wall.json 7a8d9e2291675de9e72363d93410de9039216f32 data/create/recipes/small_granite_brick_wall_from_stone_types_granite_stonecutting.json -714f6a84a5b3d5d57c07364925555e6f545b0b3d data/create/recipes/small_limestone_bricks_from_stone_types_limestone_stonecutting.json +42c74dec6c64d3675e15b2b73cb32fc9d24839e9 data/create/recipes/small_granite_bricks_from_stone_types_granite_stonecutting.json b844632a588cb96397750f4387c7e6517f85092c data/create/recipes/small_limestone_brick_slab.json a1c0bc263cd4659a89213f4fcdd87eba7ae04427 data/create/recipes/small_limestone_brick_slab_from_stone_types_limestone_stonecutting.json ec9154a3791113f57dc1c16dfef4c837533b6fc6 data/create/recipes/small_limestone_brick_slab_recycling.json @@ -4609,7 +4608,7 @@ ec9154a3791113f57dc1c16dfef4c837533b6fc6 data/create/recipes/small_limestone_bri 6943fdc8162e4d53c459f425b2ff5b34e9caa477 data/create/recipes/small_limestone_brick_stairs_from_stone_types_limestone_stonecutting.json 27ff69345efea14b9688fe9b182809995ea8ad4a data/create/recipes/small_limestone_brick_wall.json 98a83f757f0ac9cc2a876ae407bb5765071e700d data/create/recipes/small_limestone_brick_wall_from_stone_types_limestone_stonecutting.json -22c69e391110280e13d50693b9c81355da57a315 data/create/recipes/small_ochrum_bricks_from_stone_types_ochrum_stonecutting.json +714f6a84a5b3d5d57c07364925555e6f545b0b3d data/create/recipes/small_limestone_bricks_from_stone_types_limestone_stonecutting.json abdd280694cb30ce0d2703aadeeb378af9a7f8b2 data/create/recipes/small_ochrum_brick_slab.json e37612fa2523fa3711242cac4ec5e596b3e55698 data/create/recipes/small_ochrum_brick_slab_from_stone_types_ochrum_stonecutting.json 8f3f47cb3e759104cf86a422339345f8795143d3 data/create/recipes/small_ochrum_brick_slab_recycling.json @@ -4617,8 +4616,8 @@ de8d7f8e57645c0b5a6e98eb0cc4e573c5cf96ac data/create/recipes/small_ochrum_brick_ 04ebbdd14f81f4b4dc7986cb5241caa9f48f4ff1 data/create/recipes/small_ochrum_brick_stairs_from_stone_types_ochrum_stonecutting.json 07876725f97ff611f8d1710462224f07cab3ebbd data/create/recipes/small_ochrum_brick_wall.json 2331801569ec95562afc802f7e2ff191d329a5c6 data/create/recipes/small_ochrum_brick_wall_from_stone_types_ochrum_stonecutting.json +22c69e391110280e13d50693b9c81355da57a315 data/create/recipes/small_ochrum_bricks_from_stone_types_ochrum_stonecutting.json 68a9f80b97d9322ed33067d7717180494b904bed data/create/recipes/small_rose_quartz_tiles_from_polished_rose_quartz_stonecutting.json -bf27af2e54ed1b09611d67ee7afa6c7f56d00d09 data/create/recipes/small_scorchia_bricks_from_stone_types_scorchia_stonecutting.json 133057778480e1d2e13fe7b2766ba0891feea3a5 data/create/recipes/small_scorchia_brick_slab.json dad342d215c98f3214752e0ebfaf3015943c5ac7 data/create/recipes/small_scorchia_brick_slab_from_stone_types_scorchia_stonecutting.json 0a57ad5fce22d69cdc1dd880403612ffb47af4ba data/create/recipes/small_scorchia_brick_slab_recycling.json @@ -4626,7 +4625,7 @@ dad342d215c98f3214752e0ebfaf3015943c5ac7 data/create/recipes/small_scorchia_bric 7f89c9c6dcea06a3022c72029a5e547aa1721773 data/create/recipes/small_scorchia_brick_stairs_from_stone_types_scorchia_stonecutting.json 43310b3fa43bd791ef0e2e30971a24e788c20139 data/create/recipes/small_scorchia_brick_wall.json de8edc4fa5eec031ad0a63c7f59141985ae9af9e data/create/recipes/small_scorchia_brick_wall_from_stone_types_scorchia_stonecutting.json -b1a67d052e26c2129c34ee0732cfe533beb3e571 data/create/recipes/small_scoria_bricks_from_stone_types_scoria_stonecutting.json +bf27af2e54ed1b09611d67ee7afa6c7f56d00d09 data/create/recipes/small_scorchia_bricks_from_stone_types_scorchia_stonecutting.json d8a41adcc6ae9b0eb71a83b2dd89ff92a10e0057 data/create/recipes/small_scoria_brick_slab.json 34f4dd094f2949e3fd21f95ac890ae803b81fbea data/create/recipes/small_scoria_brick_slab_from_stone_types_scoria_stonecutting.json f15ad1cb05f5b02b630b982d23bd951178a3650c data/create/recipes/small_scoria_brick_slab_recycling.json @@ -4634,7 +4633,7 @@ df5a1437fb112519d904cc9f1cd28d5d891fb04d data/create/recipes/small_scoria_brick_ d36428daf8bf4e560f649e5eb40a8cd7a27e7a0e data/create/recipes/small_scoria_brick_stairs_from_stone_types_scoria_stonecutting.json cad432398d8886d60b94e96b2c2096ae27fffb50 data/create/recipes/small_scoria_brick_wall.json 9cff8370aaa81ece466fe15642c00a9992bd416c data/create/recipes/small_scoria_brick_wall_from_stone_types_scoria_stonecutting.json -e51ced16059f7c37fe3652a1cf4d938f91e956fc data/create/recipes/small_tuff_bricks_from_stone_types_tuff_stonecutting.json +b1a67d052e26c2129c34ee0732cfe533beb3e571 data/create/recipes/small_scoria_bricks_from_stone_types_scoria_stonecutting.json dd83af4a10a9b0ba6a4efb272d8b6b1611524a39 data/create/recipes/small_tuff_brick_slab.json e3a12b87830e47387e9ac118bb3d12b73558d757 data/create/recipes/small_tuff_brick_slab_from_stone_types_tuff_stonecutting.json 85dff00dc49eaf65f1f149a7f21a9f307b1b9710 data/create/recipes/small_tuff_brick_slab_recycling.json @@ -4642,7 +4641,7 @@ e03a8270b01b9a5cad238db4ce2b8f66ea78e8bf data/create/recipes/small_tuff_brick_st cd50bb5842c90038f6ac74e45971ab2e914d1463 data/create/recipes/small_tuff_brick_stairs_from_stone_types_tuff_stonecutting.json e795fbe5062ec47cc660ee26c8398477509c5f18 data/create/recipes/small_tuff_brick_wall.json 34471a7ebb431b6d1e3be5fa480b800b96556fee data/create/recipes/small_tuff_brick_wall_from_stone_types_tuff_stonecutting.json -82f17edc61a319c74dbdfa730584305899bd7572 data/create/recipes/small_veridium_bricks_from_stone_types_veridium_stonecutting.json +e51ced16059f7c37fe3652a1cf4d938f91e956fc data/create/recipes/small_tuff_bricks_from_stone_types_tuff_stonecutting.json f9a2f4ca078364e05b3446fe890ea207e5a56e87 data/create/recipes/small_veridium_brick_slab.json 234c3baee4c9428caab3e344f396ec87064103e3 data/create/recipes/small_veridium_brick_slab_from_stone_types_veridium_stonecutting.json b0db8335e3c7fd88f074c3895bea952efc0e8df8 data/create/recipes/small_veridium_brick_slab_recycling.json @@ -4650,6 +4649,7 @@ a1e214c230574526ca0a2fec059b4157ddec557d data/create/recipes/small_veridium_bric f63031587a64ed88ddba1df07767dd8d8caa1d2e data/create/recipes/small_veridium_brick_stairs_from_stone_types_veridium_stonecutting.json 9b003fbf2bcd975501ba307ea68c6c4bab397683 data/create/recipes/small_veridium_brick_wall.json 1ba48c5cae05b6f4b1ad223ce80925f1eaaf5dfd data/create/recipes/small_veridium_brick_wall_from_stone_types_veridium_stonecutting.json +82f17edc61a319c74dbdfa730584305899bd7572 data/create/recipes/small_veridium_bricks_from_stone_types_veridium_stonecutting.json 47973044b19b35ce169e7d46abc9d11a2f67a487 data/create/recipes/spruce_window.json 810544f79bf4b002981e614eaa8e49b48a7b5397 data/create/recipes/spruce_window_pane.json e343a80c92dab60f99c9b441d00189aceee477a0 data/create/recipes/tiled_glass_from_glass_colorless_stonecutting.json @@ -4675,10 +4675,11 @@ a57dfe9974b8b6d338b9ab4ae124297fda7780b9 data/create/recipes/weathered_iron_wind 11034a79e8f167249b78e6e3863e01991ac9d778 data/create/recipes/weathered_iron_window_pane.json f365be4eda73234b73aa49c97b065f1a8baafbf6 data/create/tags/blocks/brittle.json 8b6c0b444b15f7fb2d55b9cbcb68537c1269f877 data/create/tags/blocks/casing.json -35133e95f1c8fdd7a1c21afcc231fc0bffefb9a8 data/create/tags/blocks/contraption_inventory_deny.json +c603fae95069714ac3d256dfa31f8d2639efafa7 data/create/tags/blocks/chest_mounted_storage.json c7ec0dbc18e9c1b58e568ed925287b89df11a136 data/create/tags/blocks/copycat_allow.json 876eb9210f4a14898a2fe6d225699c66b5bdfeef data/create/tags/blocks/copycat_deny.json 7296238b4c6b81251870addce1de8ecda63381dc data/create/tags/blocks/corals.json +35133e95f1c8fdd7a1c21afcc231fc0bffefb9a8 data/create/tags/blocks/fallback_mounted_storage_blacklist.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 @@ -4693,6 +4694,7 @@ f400870b8dbcd14238be3ec99c419093073ba3a6 data/create/tags/blocks/postboxes.json 9bc8c13fd80bdbe7f767b91ee1a1042e9aff02b0 data/create/tags/blocks/roots.json 55dccb895bbdacfbd6ee9005486cd3fe9df01249 data/create/tags/blocks/safe_nbt.json 79418bd729cef417b322cef9b491e7ae83317d61 data/create/tags/blocks/seats.json +7d783d948cc49503fb645045fe9ef48906b74341 data/create/tags/blocks/simple_mounted_storage.json 8a6ad3c63fb0c436ec8109f39358213930effd5a data/create/tags/blocks/table_cloths.json 5def5088f7fd31b80e6f28c1c4ea146aa9d7d15b data/create/tags/blocks/toolboxes.json 2589b135c0e96ad29076569e144528fe32ea5b39 data/create/tags/blocks/tracks.json diff --git a/src/generated/resources/data/create/tags/blocks/chest_mounted_storage.json b/src/generated/resources/data/create/tags/blocks/chest_mounted_storage.json new file mode 100644 index 0000000000..86533f935b --- /dev/null +++ b/src/generated/resources/data/create/tags/blocks/chest_mounted_storage.json @@ -0,0 +1,6 @@ +{ + "values": [ + "minecraft:chest", + "minecraft:trapped_chest" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/blocks/contraption_inventory_deny.json b/src/generated/resources/data/create/tags/blocks/fallback_mounted_storage_blacklist.json similarity index 100% rename from src/generated/resources/data/create/tags/blocks/contraption_inventory_deny.json rename to src/generated/resources/data/create/tags/blocks/fallback_mounted_storage_blacklist.json diff --git a/src/generated/resources/data/create/tags/blocks/simple_mounted_storage.json b/src/generated/resources/data/create/tags/blocks/simple_mounted_storage.json new file mode 100644 index 0000000000..93f3ee349c --- /dev/null +++ b/src/generated/resources/data/create/tags/blocks/simple_mounted_storage.json @@ -0,0 +1,22 @@ +{ + "values": [ + "minecraft:barrel", + "minecraft:shulker_box", + "minecraft:white_shulker_box", + "minecraft:orange_shulker_box", + "minecraft:magenta_shulker_box", + "minecraft:light_blue_shulker_box", + "minecraft:yellow_shulker_box", + "minecraft:lime_shulker_box", + "minecraft:pink_shulker_box", + "minecraft:gray_shulker_box", + "minecraft:light_gray_shulker_box", + "minecraft:cyan_shulker_box", + "minecraft:purple_shulker_box", + "minecraft:blue_shulker_box", + "minecraft:brown_shulker_box", + "minecraft:green_shulker_box", + "minecraft:red_shulker_box", + "minecraft:black_shulker_box" + ] +} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/AllBlocks.java b/src/main/java/com/simibubi/create/AllBlocks.java index 514c7a4fc5..28786c917a 100644 --- a/src/main/java/com/simibubi/create/AllBlocks.java +++ b/src/main/java/com/simibubi/create/AllBlocks.java @@ -3,6 +3,8 @@ package com.simibubi.create; import static com.simibubi.create.AllInteractionBehaviours.interactionBehaviour; import static com.simibubi.create.AllMovementBehaviours.movementBehaviour; import static com.simibubi.create.Create.REGISTRATE; +import static com.simibubi.create.api.contraption.storage.MountedStorageTypeRegistry.mountedFluidStorage; +import static com.simibubi.create.api.contraption.storage.MountedStorageTypeRegistry.mountedItemStorage; import static com.simibubi.create.content.redstone.displayLink.AllDisplayBehaviours.assignDataBehaviour; import static com.simibubi.create.foundation.data.BlockStateGen.axisBlock; import static com.simibubi.create.foundation.data.BlockStateGen.simpleCubeAll; @@ -105,6 +107,7 @@ import com.simibubi.create.content.fluids.tank.FluidTankBlock; import com.simibubi.create.content.fluids.tank.FluidTankGenerator; import com.simibubi.create.content.fluids.tank.FluidTankItem; import com.simibubi.create.content.fluids.tank.FluidTankModel; +import com.simibubi.create.content.fluids.tank.FluidTankMovementBehavior; import com.simibubi.create.content.kinetics.BlockStressDefaults; import com.simibubi.create.content.kinetics.belt.BeltBlock; import com.simibubi.create.content.kinetics.belt.BeltGenerator; @@ -329,6 +332,7 @@ import net.minecraft.world.level.storage.loot.predicates.ExplosionCondition; import net.minecraft.world.level.storage.loot.predicates.LootItemCondition; import net.minecraft.world.level.storage.loot.providers.nbt.ContextNbtProvider; import net.minecraft.world.level.storage.loot.providers.number.ConstantValue; + import net.minecraftforge.client.model.generators.ConfiguredModel; import net.minecraftforge.client.model.generators.ModelFile; import net.minecraftforge.common.Tags; @@ -796,6 +800,7 @@ public class AllBlocks { .blockstate((c, p) -> p.simpleBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p))) .onRegister(assignDataBehaviour(new ItemNameDisplaySource(), "combine_item_names")) .onRegister(interactionBehaviour(new MountedDepotInteractionBehaviour())) + .transform(mountedItemStorage(AllMountedStorageTypes.DEPOT)) .item() .transform(customItemModel("_", "block")) .register(); @@ -994,6 +999,8 @@ public class AllBlocks { .blockstate(new FluidTankGenerator()::generate) .onRegister(CreateRegistrate.blockModel(() -> FluidTankModel::standard)) .onRegister(assignDataBehaviour(new BoilerDisplaySource(), "boiler_status")) + .transform(mountedFluidStorage(AllMountedStorageTypes.FLUID_TANK)) + .onRegister(movementBehaviour(new FluidTankMovementBehavior())) .addLayer(() -> RenderType::cutoutMipped) .item(FluidTankItem::new) .model(AssetLookup.customBlockItemModel("_", "block_single_window")) @@ -1009,6 +1016,7 @@ public class AllBlocks { .tag(AllBlockTags.SAFE_NBT.tag) .blockstate(new FluidTankGenerator("creative_")::generate) .onRegister(CreateRegistrate.blockModel(() -> FluidTankModel::creative)) + .transform(mountedFluidStorage(AllMountedStorageTypes.CREATIVE_FLUID_TANK)) .addLayer(() -> RenderType::cutoutMipped) .item(FluidTankItem::new) .properties(p -> p.rarity(Rarity.EPIC)) @@ -1822,6 +1830,7 @@ public class AllBlocks { REGISTRATE.block("creative_crate", CreativeCrateBlock::new) .transform(BuilderTransformers.crate("creative")) .properties(p -> p.mapColor(MapColor.COLOR_PURPLE)) + .transform(mountedItemStorage(AllMountedStorageTypes.CREATIVE_CRATE)) .register(); public static final BlockEntry ITEM_VAULT = REGISTRATE.block("item_vault", ItemVaultBlock::new) @@ -1836,6 +1845,7 @@ public class AllBlocks { .rotationY(s.getValue(ItemVaultBlock.HORIZONTAL_AXIS) == Axis.X ? 90 : 0) .build())) .onRegister(connectedTextures(ItemVaultCTBehaviour::new)) + .transform(mountedItemStorage(AllMountedStorageTypes.VAULT)) .item(ItemVaultItem::new) .build() .register(); @@ -2242,6 +2252,7 @@ public class AllBlocks { .texture("0", p.modLoc("block/toolbox/" + colourName))); }) .onRegisterAfter(Registries.ITEM, v -> ItemDescription.useKey(v, "block.create.toolbox")) + .transform(mountedItemStorage(AllMountedStorageTypes.TOOLBOX)) .tag(AllBlockTags.TOOLBOXES.tag) .item(UncontainableBlockItem::new) .model((c, p) -> p.withExistingParent(colourName + "_toolbox", p.modLoc("block/toolbox/item")) diff --git a/src/main/java/com/simibubi/create/AllMountedStorageTypes.java b/src/main/java/com/simibubi/create/AllMountedStorageTypes.java new file mode 100644 index 0000000000..aba02b31c9 --- /dev/null +++ b/src/main/java/com/simibubi/create/AllMountedStorageTypes.java @@ -0,0 +1,57 @@ +package com.simibubi.create; + +import static com.simibubi.create.Create.REGISTRATE; + +import java.util.function.Supplier; + +import com.simibubi.create.api.contraption.storage.fluid.MountedFluidStorageType; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; +import com.simibubi.create.api.contraption.storage.item.chest.ChestMountedStorageType; +import com.simibubi.create.api.contraption.storage.item.simple.SimpleMountedStorageType; +import com.simibubi.create.content.contraptions.behaviour.dispenser.storage.DispenserMountedStorageType; +import com.simibubi.create.content.equipment.toolbox.ToolboxMountedStorageType; +import com.simibubi.create.content.fluids.tank.storage.FluidTankMountedStorageType; +import com.simibubi.create.content.fluids.tank.storage.creative.CreativeFluidTankMountedStorageType; +import com.simibubi.create.content.logistics.crate.CreativeCrateMountedStorageType; +import com.simibubi.create.content.logistics.depot.storage.DepotMountedStorageType; +import com.simibubi.create.content.logistics.vault.ItemVaultMountedStorageType; +import com.simibubi.create.impl.contraption.storage.FallbackMountedStorageType; +import com.tterrag.registrate.util.entry.RegistryEntry; + +import net.minecraft.world.level.block.Blocks; + +public class AllMountedStorageTypes { + // fallback is special, provider is registered on lookup creation so it's always last + public static final RegistryEntry FALLBACK = simpleItem("fallback", FallbackMountedStorageType::new); + + // registrations for these are handled by the blocks, not the types + public static final RegistryEntry CREATIVE_CRATE = simpleItem("creative_crate", CreativeCrateMountedStorageType::new); + public static final RegistryEntry VAULT = simpleItem("vault", ItemVaultMountedStorageType::new); + public static final RegistryEntry TOOLBOX = simpleItem("toolbox", ToolboxMountedStorageType::new); + public static final RegistryEntry DEPOT = simpleItem("depot", DepotMountedStorageType::new); + public static final RegistryEntry FLUID_TANK = simpleFluid("fluid_tank", FluidTankMountedStorageType::new); + public static final RegistryEntry CREATIVE_FLUID_TANK = simpleFluid("creative_fluid_tank", CreativeFluidTankMountedStorageType::new); + + // these are for external blocks, register associations here + public static final RegistryEntry SIMPLE = REGISTRATE.mountedItemStorage("simple", SimpleMountedStorageType.Impl::new) + .registerTo(AllTags.AllBlockTags.SIMPLE_MOUNTED_STORAGE.tag) + .register(); + public static final RegistryEntry CHEST = REGISTRATE.mountedItemStorage("chest", ChestMountedStorageType::new) + .registerTo(AllTags.AllBlockTags.CHEST_MOUNTED_STORAGE.tag) + .register(); + public static final RegistryEntry DISPENSER = REGISTRATE.mountedItemStorage("dispenser", DispenserMountedStorageType::new) + .registerTo(Blocks.DISPENSER) + .registerTo(Blocks.DROPPER) + .register(); + + private static > RegistryEntry simpleItem(String name, Supplier supplier) { + return REGISTRATE.mountedItemStorage(name, supplier).register(); + } + + private static > RegistryEntry simpleFluid(String name, Supplier supplier) { + return REGISTRATE.mountedFluidStorage(name, supplier).register(); + } + + public static void register() { + } +} diff --git a/src/main/java/com/simibubi/create/AllPackets.java b/src/main/java/com/simibubi/create/AllPackets.java index cf771352b4..04a05d3100 100644 --- a/src/main/java/com/simibubi/create/AllPackets.java +++ b/src/main/java/com/simibubi/create/AllPackets.java @@ -16,6 +16,7 @@ import com.simibubi.create.content.contraptions.ContraptionColliderLockPacket.Co import com.simibubi.create.content.contraptions.ContraptionDisassemblyPacket; import com.simibubi.create.content.contraptions.ContraptionRelocationPacket; import com.simibubi.create.content.contraptions.ContraptionStallPacket; +import com.simibubi.create.content.contraptions.MountedStorageSyncPacket; import com.simibubi.create.content.contraptions.TrainCollisionPacket; import com.simibubi.create.content.contraptions.actors.contraptionControls.ContraptionDisableActorPacket; import com.simibubi.create.content.contraptions.actors.trainControls.ControlsInputPacket; @@ -30,9 +31,7 @@ import com.simibubi.create.content.contraptions.glue.SuperGlueSelectionPacket; import com.simibubi.create.content.contraptions.minecart.CouplingCreationPacket; import com.simibubi.create.content.contraptions.minecart.capability.MinecartControllerUpdatePacket; import com.simibubi.create.content.contraptions.sync.ClientMotionPacket; -import com.simibubi.create.content.contraptions.sync.ContraptionFluidPacket; import com.simibubi.create.content.contraptions.sync.ContraptionInteractionPacket; -import com.simibubi.create.content.contraptions.sync.ContraptionItemPacket; import com.simibubi.create.content.contraptions.sync.ContraptionSeatMappingPacket; import com.simibubi.create.content.contraptions.sync.LimbSwingUpdatePacket; import com.simibubi.create.content.contraptions.wrench.RadialWrenchMenuSubmitPacket; @@ -123,6 +122,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; + import net.minecraftforge.network.NetworkDirection; import net.minecraftforge.network.NetworkEvent.Context; import net.minecraftforge.network.NetworkRegistry; @@ -218,8 +218,7 @@ public enum AllPackets { LIMBSWING_UPDATE(LimbSwingUpdatePacket.class, LimbSwingUpdatePacket::new, PLAY_TO_CLIENT), MINECART_CONTROLLER(MinecartControllerUpdatePacket.class, MinecartControllerUpdatePacket::new, PLAY_TO_CLIENT), FLUID_SPLASH(FluidSplashPacket.class, FluidSplashPacket::new, PLAY_TO_CLIENT), - CONTRAPTION_FLUID(ContraptionFluidPacket.class, ContraptionFluidPacket::new, PLAY_TO_CLIENT), - CONTRAPTION_ITEM(ContraptionItemPacket.class, ContraptionItemPacket::new, PLAY_TO_CLIENT), + MOUNTED_STORAGE_SYNC(MountedStorageSyncPacket.class, MountedStorageSyncPacket::new, PLAY_TO_CLIENT), GANTRY_UPDATE(GantryContraptionUpdatePacket.class, GantryContraptionUpdatePacket::new, PLAY_TO_CLIENT), BLOCK_HIGHLIGHT(HighlightPacket.class, HighlightPacket::new, PLAY_TO_CLIENT), TUNNEL_FLAP(TunnelFlapPacket.class, TunnelFlapPacket::new, PLAY_TO_CLIENT), diff --git a/src/main/java/com/simibubi/create/AllTags.java b/src/main/java/com/simibubi/create/AllTags.java index c8e51aa3de..7ee0ea6710 100644 --- a/src/main/java/com/simibubi/create/AllTags.java +++ b/src/main/java/com/simibubi/create/AllTags.java @@ -82,7 +82,6 @@ public class AllTags { BRITTLE, CASING, - CONTRAPTION_INVENTORY_DENY, COPYCAT_ALLOW, COPYCAT_DENY, FAN_PROCESSING_CATALYSTS_BLASTING(MOD, "fan_processing_catalysts/blasting"), @@ -105,6 +104,9 @@ public class AllTags { VALVE_HANDLES, WINDMILL_SAILS, WRENCH_PICKUP, + CHEST_MOUNTED_STORAGE, + SIMPLE_MOUNTED_STORAGE, + FALLBACK_MOUNTED_STORAGE_BLACKLIST, ROOTS, CORALS, diff --git a/src/main/java/com/simibubi/create/Create.java b/src/main/java/com/simibubi/create/Create.java index c9d1b3aeb0..41540fc060 100644 --- a/src/main/java/com/simibubi/create/Create.java +++ b/src/main/java/com/simibubi/create/Create.java @@ -128,6 +128,7 @@ public class Create { AllPackets.registerPackets(); AllFeatures.register(modEventBus); AllPlacementModifiers.register(modEventBus); + AllMountedStorageTypes.register(); AllConfigs.register(modLoadingContext); diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/MountedStorageTypeRegistry.java b/src/main/java/com/simibubi/create/api/contraption/storage/MountedStorageTypeRegistry.java new file mode 100644 index 0000000000..845637970c --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/storage/MountedStorageTypeRegistry.java @@ -0,0 +1,65 @@ +package com.simibubi.create.api.contraption.storage; + +import com.simibubi.create.Create; +import com.simibubi.create.api.contraption.storage.fluid.MountedFluidStorageType; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; +import com.simibubi.create.api.lookup.BlockLookup; +import com.simibubi.create.impl.contraption.storage.MountedStorageTypeRegistryImpl; +import com.tterrag.registrate.builders.BlockBuilder; +import com.tterrag.registrate.util.entry.RegistryEntry; +import com.tterrag.registrate.util.nullness.NonNullUnaryOperator; + +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.level.block.Block; +import net.minecraftforge.registries.IForgeRegistry; + +public class MountedStorageTypeRegistry { + public static final ResourceKey>> ITEMS = ResourceKey.createRegistryKey( + Create.asResource("mounted_item_storage_type") + ); + public static final ResourceKey>> FLUIDS = ResourceKey.createRegistryKey( + Create.asResource("mounted_fluid_storage_type") + ); + + /** + * Lookup used for finding the item storage type associated with a block. + * @see BlockLookup + */ + public static final BlockLookup> ITEM_LOOKUP = MountedStorageTypeRegistryImpl.ITEM_LOOKUP; + /** + * Lookup used for finding the fluid storage type associated with a block. + * @see BlockLookup + */ + public static final BlockLookup> FLUID_LOOKUP = MountedStorageTypeRegistryImpl.FLUID_LOOKUP; + + /** + * @throws NullPointerException if called before registry registration + */ + public static IForgeRegistry> getItemsRegistry() { + return MountedStorageTypeRegistryImpl.getItemsRegistry(); + } + + /** + * @throws NullPointerException if called before registry registration + */ + public static IForgeRegistry> getFluidsRegistry() { + return MountedStorageTypeRegistryImpl.getFluidsRegistry(); + } + + /** + * Utility for use with Registrate builders. Creates a builder transformer + * that will register the given MountedItemStorageType to a block when ready. + */ + public static NonNullUnaryOperator> mountedItemStorage(RegistryEntry> type) { + return builder -> builder.onRegisterAfter(ITEMS, block -> ITEM_LOOKUP.register(block, type.get())); + } + + /** + * Utility for use with Registrate builders. Creates a builder transformer + * that will register the given MountedFluidStorageType to a block when ready. + */ + public static NonNullUnaryOperator> mountedFluidStorage(RegistryEntry> type) { + return builder -> builder.onRegisterAfter(ITEMS, block -> FLUID_LOOKUP.register(block, type.get())); + } +} diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/SyncedMountedStorage.java b/src/main/java/com/simibubi/create/api/contraption/storage/SyncedMountedStorage.java new file mode 100644 index 0000000000..035ed5d94f --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/storage/SyncedMountedStorage.java @@ -0,0 +1,25 @@ +package com.simibubi.create.api.contraption.storage; + +import com.simibubi.create.content.contraptions.Contraption; + +import net.minecraft.core.BlockPos; + +/** + * Optional interface for mounted storage that is synced with the client. + */ +public interface SyncedMountedStorage { + /** + * @return true if this storage needs to be synced. + */ + boolean isDirty(); + + /** + * Called after this storage has been synced. + */ + void markClean(); + + /** + * Called on the client side after this storage has been synced from the server. + */ + void afterSync(Contraption contraption, BlockPos localPos); +} diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/fluid/MountedFluidStorage.java b/src/main/java/com/simibubi/create/api/contraption/storage/fluid/MountedFluidStorage.java new file mode 100644 index 0000000000..449f207afe --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/storage/fluid/MountedFluidStorage.java @@ -0,0 +1,31 @@ +package com.simibubi.create.api.contraption.storage.fluid; + +import java.util.Objects; + +import org.jetbrains.annotations.Nullable; + +import com.mojang.serialization.Codec; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.fluids.capability.IFluidHandler; + +public abstract class MountedFluidStorage implements IFluidHandler { + public static final Codec CODEC = MountedFluidStorageType.CODEC.dispatch( + storage -> storage.type, type -> type.codec + ); + + public final MountedFluidStorageType type; + + protected MountedFluidStorage(MountedFluidStorageType type) { + this.type = Objects.requireNonNull(type); + } + + /** + * Un-mount this storage back into the world. The expected storage type of the target + * block has already been checked to make sure it matches this storage's type. + */ + public abstract void unmount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be); +} diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/fluid/MountedFluidStorageType.java b/src/main/java/com/simibubi/create/api/contraption/storage/fluid/MountedFluidStorageType.java new file mode 100644 index 0000000000..75dc708195 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/storage/fluid/MountedFluidStorageType.java @@ -0,0 +1,27 @@ +package com.simibubi.create.api.contraption.storage.fluid; + +import org.jetbrains.annotations.Nullable; + +import com.mojang.serialization.Codec; +import com.simibubi.create.api.contraption.storage.MountedStorageTypeRegistry; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.ExtraCodecs; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; + +public abstract class MountedFluidStorageType { + public static final Codec> CODEC = ExtraCodecs.lazyInitializedCodec( + () -> MountedStorageTypeRegistry.getFluidsRegistry().getCodec() + ); + + public final Codec codec; + + protected MountedFluidStorageType(Codec codec) { + this.codec = codec; + } + + @Nullable + public abstract T mount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be); +} diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/fluid/MountedFluidStorageWrapper.java b/src/main/java/com/simibubi/create/api/contraption/storage/fluid/MountedFluidStorageWrapper.java new file mode 100644 index 0000000000..9d983e5395 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/storage/fluid/MountedFluidStorageWrapper.java @@ -0,0 +1,20 @@ +package com.simibubi.create.api.contraption.storage.fluid; + +import com.google.common.collect.ImmutableMap; +import com.simibubi.create.foundation.fluid.CombinedTankWrapper; + +import net.minecraft.core.BlockPos; +import net.minecraftforge.fluids.capability.IFluidHandler; + +/** + * Wrapper around many MountedFluidStorages, providing access to all of them as one storage. + * They can still be accessed individually through the map. + */ +public class MountedFluidStorageWrapper extends CombinedTankWrapper { + public final ImmutableMap storages; + + public MountedFluidStorageWrapper(ImmutableMap storages) { + super(storages.values().toArray(IFluidHandler[]::new)); + this.storages = storages; + } +} diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/fluid/WrapperMountedFluidStorage.java b/src/main/java/com/simibubi/create/api/contraption/storage/fluid/WrapperMountedFluidStorage.java new file mode 100644 index 0000000000..63d445f8f6 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/storage/fluid/WrapperMountedFluidStorage.java @@ -0,0 +1,56 @@ +package com.simibubi.create.api.contraption.storage.fluid; + +import org.jetbrains.annotations.NotNull; + +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.IFluidHandler; + +/** + * Partial implementation of a MountedFluidStorage that wraps a fluid handler. + */ +public abstract class WrapperMountedFluidStorage extends MountedFluidStorage { + protected final T wrapped; + + protected WrapperMountedFluidStorage(MountedFluidStorageType type, T wrapped) { + super(type); + this.wrapped = wrapped; + } + + @Override + public int getTanks() { + return this.wrapped.getTanks(); + } + + @Override + @NotNull + public FluidStack getFluidInTank(int tank) { + return this.wrapped.getFluidInTank(tank); + } + + @Override + public int getTankCapacity(int tank) { + return this.wrapped.getTankCapacity(tank); + } + + @Override + public boolean isFluidValid(int tank, @NotNull FluidStack stack) { + return this.wrapped.isFluidValid(tank, stack); + } + + @Override + public int fill(FluidStack resource, FluidAction action) { + return this.wrapped.fill(resource, action); + } + + @Override + @NotNull + public FluidStack drain(FluidStack resource, FluidAction action) { + return this.wrapped.drain(resource, action); + } + + @Override + @NotNull + public FluidStack drain(int maxDrain, FluidAction action) { + return this.wrapped.drain(maxDrain, action); + } +} diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/fluid/registrate/MountedFluidStorageTypeBuilder.java b/src/main/java/com/simibubi/create/api/contraption/storage/fluid/registrate/MountedFluidStorageTypeBuilder.java new file mode 100644 index 0000000000..cf1ae43e8b --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/storage/fluid/registrate/MountedFluidStorageTypeBuilder.java @@ -0,0 +1,36 @@ +package com.simibubi.create.api.contraption.storage.fluid.registrate; + +import com.simibubi.create.api.contraption.storage.MountedStorageTypeRegistry; +import com.simibubi.create.api.contraption.storage.fluid.MountedFluidStorageType; +import com.tterrag.registrate.AbstractRegistrate; +import com.tterrag.registrate.builders.AbstractBuilder; +import com.tterrag.registrate.builders.BuilderCallback; +import com.tterrag.registrate.util.nullness.NonnullType; + +import net.minecraft.tags.TagKey; +import net.minecraft.world.level.block.Block; + +public class MountedFluidStorageTypeBuilder, P> extends AbstractBuilder, T, P, MountedFluidStorageTypeBuilder> { + private final T type; + + public MountedFluidStorageTypeBuilder(AbstractRegistrate owner, P parent, String name, BuilderCallback callback, T type) { + super(owner, parent, name, callback, MountedStorageTypeRegistry.FLUIDS); + this.type = type; + } + + public MountedFluidStorageTypeBuilder registerTo(Block block) { + MountedStorageTypeRegistry.FLUID_LOOKUP.register(block, this.type); + return this; + } + + public MountedFluidStorageTypeBuilder registerTo(TagKey tag) { + MountedStorageTypeRegistry.FLUID_LOOKUP.registerTag(tag, this.type); + return this; + } + + @Override + @NonnullType + protected T createEntry() { + return this.type; + } +} diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/item/MountedItemStorage.java b/src/main/java/com/simibubi/create/api/contraption/storage/item/MountedItemStorage.java new file mode 100644 index 0000000000..f4a562991d --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/storage/item/MountedItemStorage.java @@ -0,0 +1,152 @@ +package com.simibubi.create.api.contraption.storage.item; + +import java.util.Objects; +import java.util.OptionalInt; +import java.util.function.Consumer; +import java.util.function.Predicate; + +import org.jetbrains.annotations.Nullable; + +import com.mojang.serialization.Codec; +import com.simibubi.create.api.contraption.storage.item.menu.MountedStorageMenus; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.contraptions.MountedStorageManager; +import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; +import com.simibubi.create.foundation.utility.CreateLang; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.MenuProvider; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.items.IItemHandlerModifiable; + +public abstract class MountedItemStorage implements IItemHandlerModifiable { + public static final Codec CODEC = MountedItemStorageType.CODEC.dispatch( + storage -> storage.type, type -> type.codec + ); + + public final MountedItemStorageType type; + + protected MountedItemStorage(MountedItemStorageType type) { + this.type = Objects.requireNonNull(type); + } + + /** + * Un-mount this storage back into the world. The expected storage type of the target + * block has already been checked to make sure it matches this storage's type. + */ + public abstract void unmount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be); + + /** + * Internal mounted storages are not exposed to the larger contraption inventory. + * They are only for internal use, such as access from a {@link MovementBehaviour}. + * Internal storages are still accessible through {@link MovementContext#getItemStorage()} + * as well as {@link MountedStorageManager#getAllItemStorages()}. + * A storage being internal implies that it does not provide fuel either. + * This is only called once on assembly. + */ + public boolean isInternal() { + return false; + } + + /** + * Contraptions may search storage for fuel, such as for powering furnace minecarts + * and trains. Return false if this storage should + */ + public boolean providesFuel() { + return true; + } + + /** + * Handle a player clicking on this mounted storage. This is always called on the server. + * The default implementation will try to open a generic GUI for standard inventories. + * For this to work, this storage must have 1-6 complete rows of 9 slots. + * @return true if the interaction was successful + */ + public boolean handleInteraction(ServerPlayer player, Contraption contraption, StructureBlockInfo info) { + ServerLevel level = player.serverLevel(); + BlockPos localPos = info.pos(); + Vec3 localPosVec = Vec3.atCenterOf(localPos); + Predicate stillValid = p -> { + Vec3 currentPos = contraption.entity.toGlobalVector(localPosVec, 0); + return this.isMenuValid(player, contraption, currentPos); + }; + Component menuName = this.getMenuName(info, contraption); + IItemHandlerModifiable handler = this.getHandlerForMenu(info, contraption); + Consumer onClose = p -> { + Vec3 newPos = contraption.entity.toGlobalVector(localPosVec, 0); + this.playClosingSound(level, newPos); + }; + + OptionalInt id = player.openMenu(this.createMenuProvider(menuName, handler, stillValid, onClose)); + if (id.isPresent()) { + Vec3 globalPos = contraption.entity.toGlobalVector(localPosVec, 0); + this.playOpeningSound(level, globalPos); + return true; + } else { + return false; + } + } + + /** + * Get the item handler that will be used by this storage's menu. This is useful for + * handling multi-blocks, such as double chests. + */ + protected IItemHandlerModifiable getHandlerForMenu(StructureBlockInfo info, Contraption contraption) { + return this; + } + + /** + * @param player the player who opened the menu + * @param pos the center of this storage in-world + * @return true if a GUI opened for this storage is still valid + */ + protected boolean isMenuValid(ServerPlayer player, Contraption contraption, Vec3 pos) { + return contraption.entity.isAlive() && player.distanceToSqr(pos) < (8 * 8); + } + + /** + * @return the title to be shown in the GUI when this storage is opened + */ + protected Component getMenuName(StructureBlockInfo info, Contraption contraption) { + MutableComponent blockName = info.state().getBlock().getName(); + return CreateLang.translateDirect("contraptions.moving_container", blockName); + } + + /** + * @return a MenuProvider that provides the menu players will see when opening this storage + */ + @Nullable + protected MenuProvider createMenuProvider(Component name, IItemHandlerModifiable handler, + Predicate stillValid, Consumer onClose) { + return MountedStorageMenus.createGeneric(name, handler, stillValid, onClose); + } + + /** + * Play the sound made by opening this storage's GUI. + */ + protected void playOpeningSound(ServerLevel level, Vec3 pos) { + level.playSound( + null, BlockPos.containing(pos), + SoundEvents.BARREL_OPEN, SoundSource.BLOCKS, + 0.75f, 1f + ); + } + + /** + * Play the sound made by closing this storage's GUI. + */ + protected void playClosingSound(ServerLevel level, Vec3 pos) { + } +} diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/item/MountedItemStorageType.java b/src/main/java/com/simibubi/create/api/contraption/storage/item/MountedItemStorageType.java new file mode 100644 index 0000000000..0376f0d776 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/storage/item/MountedItemStorageType.java @@ -0,0 +1,27 @@ +package com.simibubi.create.api.contraption.storage.item; + +import org.jetbrains.annotations.Nullable; + +import com.mojang.serialization.Codec; +import com.simibubi.create.api.contraption.storage.MountedStorageTypeRegistry; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.ExtraCodecs; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; + +public abstract class MountedItemStorageType { + public static final Codec> CODEC = ExtraCodecs.lazyInitializedCodec( + () -> MountedStorageTypeRegistry.getItemsRegistry().getCodec() + ); + + public final Codec codec; + + protected MountedItemStorageType(Codec codec) { + this.codec = codec; + } + + @Nullable + public abstract T mount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be); +} diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/item/MountedItemStorageWrapper.java b/src/main/java/com/simibubi/create/api/contraption/storage/item/MountedItemStorageWrapper.java new file mode 100644 index 0000000000..641d3ea21e --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/storage/item/MountedItemStorageWrapper.java @@ -0,0 +1,20 @@ +package com.simibubi.create.api.contraption.storage.item; + +import com.google.common.collect.ImmutableMap; + +import net.minecraft.core.BlockPos; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.wrapper.CombinedInvWrapper; + +/** + * Wrapper around many MountedItemStorages, providing access to all of them as one storage. + * They can still be accessed individually through the map. + */ +public class MountedItemStorageWrapper extends CombinedInvWrapper { + public final ImmutableMap storages; + + public MountedItemStorageWrapper(ImmutableMap storages) { + super(storages.values().toArray(IItemHandlerModifiable[]::new)); + this.storages = storages; + } +} diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/item/WrapperMountedItemStorage.java b/src/main/java/com/simibubi/create/api/contraption/storage/item/WrapperMountedItemStorage.java new file mode 100644 index 0000000000..5fb1c1ac51 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/storage/item/WrapperMountedItemStorage.java @@ -0,0 +1,66 @@ +package com.simibubi.create.api.contraption.storage.item; + +import org.jetbrains.annotations.NotNull; + +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.ItemStackHandler; + +/** + * Partial implementation of a MountedItemStorage that wraps an item handler. + */ +public abstract class WrapperMountedItemStorage extends MountedItemStorage { + protected final T wrapped; + + protected WrapperMountedItemStorage(MountedItemStorageType type, T wrapped) { + super(type); + this.wrapped = wrapped; + } + + @Override + public void setStackInSlot(int slot, @NotNull ItemStack stack) { + this.wrapped.setStackInSlot(slot, stack); + } + + @Override + public int getSlots() { + return this.wrapped.getSlots(); + } + + @Override + @NotNull + public ItemStack getStackInSlot(int slot) { + return this.wrapped.getStackInSlot(slot); + } + + @Override + @NotNull + public ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate) { + return this.wrapped.insertItem(slot, stack, simulate); + } + + @Override + @NotNull + public ItemStack extractItem(int slot, int amount, boolean simulate) { + return this.wrapped.extractItem(slot, amount, simulate); + } + + @Override + public int getSlotLimit(int slot) { + return this.wrapped.getSlotLimit(slot); + } + + @Override + public boolean isItemValid(int slot, @NotNull ItemStack stack) { + return this.wrapped.isItemValid(slot, stack); + } + + public static ItemStackHandler copyToItemStackHandler(IItemHandler handler) { + ItemStackHandler copy = new ItemStackHandler(handler.getSlots()); + for (int i = 0; i < handler.getSlots(); i++) { + copy.setStackInSlot(i, handler.getStackInSlot(i).copy()); + } + return copy; + } +} diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/item/chest/ChestMountedStorage.java b/src/main/java/com/simibubi/create/api/contraption/storage/item/chest/ChestMountedStorage.java new file mode 100644 index 0000000000..31e1f7249c --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/storage/item/chest/ChestMountedStorage.java @@ -0,0 +1,111 @@ +package com.simibubi.create.api.contraption.storage.item.chest; + +import org.jetbrains.annotations.Nullable; + +import com.mojang.serialization.Codec; +import com.simibubi.create.AllMountedStorageTypes; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorage; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; +import com.simibubi.create.api.contraption.storage.item.simple.SimpleMountedStorage; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.foundation.item.ItemHelper; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.Container; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.ChestBlock; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.ChestType; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.wrapper.CombinedInvWrapper; +import net.minecraftforge.items.wrapper.InvWrapper; + +/** + * Mounted storage that handles opening a combined GUI for double chests. + */ +public class ChestMountedStorage extends SimpleMountedStorage { + public static final Codec CODEC = SimpleMountedStorage.codec(ChestMountedStorage::new); + + protected ChestMountedStorage(MountedItemStorageType type, IItemHandler handler) { + super(type, handler); + } + + public ChestMountedStorage(IItemHandler handler) { + this(AllMountedStorageTypes.CHEST.get(), handler); + } + + @Override + public void unmount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be) { + // the capability will include both sides of chests, but mounted storage is 1:1 + if (be instanceof Container container && this.getSlots() == container.getContainerSize()) { + ItemHelper.copyContents(this, new InvWrapper(container)); + } + } + + @Override + protected IItemHandlerModifiable getHandlerForMenu(StructureBlockInfo info, Contraption contraption) { + BlockState state = info.state(); + ChestType type = state.getValue(ChestBlock.TYPE); + if (type == ChestType.SINGLE) + return this; + + Direction facing = state.getValue(ChestBlock.FACING); + Direction connectedDirection = ChestBlock.getConnectedDirection(state); + BlockPos otherHalfPos = info.pos().relative(connectedDirection); + + MountedItemStorage otherHalf = this.getOtherHalf(contraption, otherHalfPos, state.getBlock(), facing, type); + if (otherHalf == null) + return this; + + if (type == ChestType.RIGHT) { + return new CombinedInvWrapper(this, otherHalf); + } else { + return new CombinedInvWrapper(otherHalf, this); + } + } + + @Nullable + protected MountedItemStorage getOtherHalf(Contraption contraption, BlockPos localPos, Block block, + Direction thisFacing, ChestType thisType) { + StructureBlockInfo info = contraption.getBlocks().get(localPos); + if (info == null) + return null; + BlockState state = info.state(); + if (!state.is(block)) + return null; + + Direction facing = state.getValue(ChestBlock.FACING); + ChestType type = state.getValue(ChestBlock.TYPE); + + return facing == thisFacing && type == thisType.getOpposite() + ? contraption.getStorage().getMountedItems().storages.get(localPos) + : null; + } + + @Override + protected void playOpeningSound(ServerLevel level, Vec3 pos) { + level.playSound( + null, BlockPos.containing(pos), + SoundEvents.CHEST_OPEN, SoundSource.BLOCKS, + 0.75f, 1f + ); + } + + @Override + protected void playClosingSound(ServerLevel level, Vec3 pos) { + level.playSound( + null, BlockPos.containing(pos), + SoundEvents.CHEST_CLOSE, SoundSource.BLOCKS, + 0.75f, 1f + ); + } +} diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/item/chest/ChestMountedStorageType.java b/src/main/java/com/simibubi/create/api/contraption/storage/item/chest/ChestMountedStorageType.java new file mode 100644 index 0000000000..e6a6054312 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/storage/item/chest/ChestMountedStorageType.java @@ -0,0 +1,25 @@ +package com.simibubi.create.api.contraption.storage.item.chest; + +import com.simibubi.create.api.contraption.storage.item.simple.SimpleMountedStorage; +import com.simibubi.create.api.contraption.storage.item.simple.SimpleMountedStorageType; + +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.wrapper.InvWrapper; +import net.minecraft.world.Container; +import net.minecraft.world.level.block.entity.BlockEntity; + +public class ChestMountedStorageType extends SimpleMountedStorageType { + public ChestMountedStorageType() { + super(ChestMountedStorage.CODEC); + } + + @Override + protected IItemHandler getHandler(BlockEntity be) { + return be instanceof Container container ? new InvWrapper(container) : null; + } + + @Override + protected SimpleMountedStorage createStorage(IItemHandler handler) { + return new ChestMountedStorage(handler); + } +} diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/item/menu/MountedStorageMenus.java b/src/main/java/com/simibubi/create/api/contraption/storage/item/menu/MountedStorageMenus.java new file mode 100644 index 0000000000..a939c8eee7 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/storage/item/menu/MountedStorageMenus.java @@ -0,0 +1,52 @@ +package com.simibubi.create.api.contraption.storage.item.menu; + +import java.util.List; +import java.util.function.Consumer; +import java.util.function.Predicate; + +import net.minecraft.network.chat.Component; +import net.minecraft.world.Container; +import net.minecraft.world.MenuProvider; +import net.minecraft.world.SimpleMenuProvider; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.ChestMenu; +import net.minecraft.world.inventory.DispenserMenu; +import net.minecraft.world.inventory.MenuConstructor; +import net.minecraft.world.inventory.MenuType; +import net.minecraftforge.items.IItemHandlerModifiable; + +import org.jetbrains.annotations.Nullable; + +/** + * Methods for creating generic menus usable by mounted storages. + */ +public class MountedStorageMenus { + public static final List> GENERIC_CHEST_MENUS = List.of( + MenuType.GENERIC_9x1, MenuType.GENERIC_9x2, MenuType.GENERIC_9x3, + MenuType.GENERIC_9x4, MenuType.GENERIC_9x5, MenuType.GENERIC_9x6 + ); + + @Nullable + public static MenuProvider createGeneric(Component menuName, IItemHandlerModifiable handler, + Predicate stillValid, Consumer onClose) { + int rows = handler.getSlots() / 9; + if (rows < 1 || rows > 6) + return null; + + MenuType type = GENERIC_CHEST_MENUS.get(rows - 1); + Container wrapper = new StorageInteractionWrapper(handler, stillValid, onClose); + MenuConstructor constructor = (id, inv, player) -> new ChestMenu(type, id, inv, wrapper, rows); + return new SimpleMenuProvider(constructor, menuName); + } + + @Nullable + public static MenuProvider createGeneric9x9(Component name, IItemHandlerModifiable handler, + Predicate stillValid, Consumer onClose) { + if (handler.getSlots() != 9) + return null; + + Container wrapper = new StorageInteractionWrapper(handler, stillValid, onClose); + MenuConstructor constructor = (id, inv, player) -> new DispenserMenu(id, inv, wrapper); + return new SimpleMenuProvider(constructor, name); + } +} diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/item/menu/StorageInteractionWrapper.java b/src/main/java/com/simibubi/create/api/contraption/storage/item/menu/StorageInteractionWrapper.java new file mode 100644 index 0000000000..d509f81c3c --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/storage/item/menu/StorageInteractionWrapper.java @@ -0,0 +1,35 @@ +package com.simibubi.create.api.contraption.storage.item.menu; + +import java.util.function.Consumer; +import java.util.function.Predicate; + +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.wrapper.RecipeWrapper; + +import net.minecraft.world.entity.player.Player; + +public class StorageInteractionWrapper extends RecipeWrapper { + private final Predicate stillValid; + private final Consumer onClose; + + public StorageInteractionWrapper(IItemHandlerModifiable inv, Predicate stillValid, Consumer onClose) { + super(inv); + this.stillValid = stillValid; + this.onClose = onClose; + } + + @Override + public boolean stillValid(Player player) { + return this.stillValid.test(player); + } + + @Override + public int getMaxStackSize() { + return 64; + } + + @Override + public void stopOpen(Player player) { + this.onClose.accept(player); + } +} diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/item/registrate/MountedItemStorageTypeBuilder.java b/src/main/java/com/simibubi/create/api/contraption/storage/item/registrate/MountedItemStorageTypeBuilder.java new file mode 100644 index 0000000000..0739a772c0 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/storage/item/registrate/MountedItemStorageTypeBuilder.java @@ -0,0 +1,36 @@ +package com.simibubi.create.api.contraption.storage.item.registrate; + +import com.simibubi.create.api.contraption.storage.MountedStorageTypeRegistry; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; +import com.tterrag.registrate.AbstractRegistrate; +import com.tterrag.registrate.builders.AbstractBuilder; +import com.tterrag.registrate.builders.BuilderCallback; +import com.tterrag.registrate.util.nullness.NonnullType; + +import net.minecraft.tags.TagKey; +import net.minecraft.world.level.block.Block; + +public class MountedItemStorageTypeBuilder, P> extends AbstractBuilder, T, P, MountedItemStorageTypeBuilder> { + private final T type; + + public MountedItemStorageTypeBuilder(AbstractRegistrate owner, P parent, String name, BuilderCallback callback, T type) { + super(owner, parent, name, callback, MountedStorageTypeRegistry.ITEMS); + this.type = type; + } + + public MountedItemStorageTypeBuilder registerTo(Block block) { + MountedStorageTypeRegistry.ITEM_LOOKUP.register(block, this.type); + return this; + } + + public MountedItemStorageTypeBuilder registerTo(TagKey tag) { + MountedStorageTypeRegistry.ITEM_LOOKUP.registerTag(tag, this.type); + return this; + } + + @Override + @NonnullType + protected T createEntry() { + return this.type; + } +} diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/item/simple/SimpleMountedStorage.java b/src/main/java/com/simibubi/create/api/contraption/storage/item/simple/SimpleMountedStorage.java new file mode 100644 index 0000000000..fce14d1cdd --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/storage/item/simple/SimpleMountedStorage.java @@ -0,0 +1,76 @@ +package com.simibubi.create.api.contraption.storage.item.simple; + +import java.util.Optional; +import java.util.function.Function; + +import com.mojang.serialization.Codec; +import com.simibubi.create.AllMountedStorageTypes; + +import com.simibubi.create.AllTags; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; +import com.simibubi.create.api.contraption.storage.item.WrapperMountedItemStorage; + +import com.simibubi.create.foundation.utility.CreateCodecs; + +import net.minecraftforge.common.capabilities.ForgeCapabilities; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.ItemStackHandler; + +import org.jetbrains.annotations.Nullable; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; + +/** + * Widely-applicable mounted storage implementation. + * Gets an item handler from the mounted block, copies it to an ItemStackHandler, + * and then copies the inventory back to the target when unmounting. + * All blocks for which this mounted storage is registered must provide an + * {@link IItemHandlerModifiable} to {@link ForgeCapabilities#ITEM_HANDLER}. + *
+ * To use this implementation, either register {@link AllMountedStorageTypes#SIMPLE} to your block + * manually, or add your block to the {@link AllTags.AllBlockTags#SIMPLE_MOUNTED_STORAGE} tag. + * It is also possible to extend this class to create your own implementation. + */ +public class SimpleMountedStorage extends WrapperMountedItemStorage { + public static final Codec CODEC = codec(SimpleMountedStorage::new); + + public SimpleMountedStorage(MountedItemStorageType type, IItemHandler handler) { + super(type, copyToItemStackHandler(handler)); + } + + public SimpleMountedStorage(IItemHandler handler) { + this(AllMountedStorageTypes.SIMPLE.get(), handler); + } + + @Override + public void unmount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be) { + if (be == null) + return; + + be.getCapability(ForgeCapabilities.ITEM_HANDLER).resolve().flatMap(this::validate).ifPresent(handler -> { + for (int i = 0; i < handler.getSlots(); i++) { + handler.setStackInSlot(i, this.getStackInSlot(i)); + } + }); + } + + /** + * Make sure the targeted handler is valid for copying items back into. + * It is highly recommended to call super in overrides. + */ + protected Optional validate(IItemHandler handler) { + if (handler.getSlots() == this.getSlots() && handler instanceof IItemHandlerModifiable modifiable) { + return Optional.of(modifiable); + } else { + return Optional.empty(); + } + } + + public static Codec codec(Function factory) { + return CreateCodecs.ITEM_STACK_HANDLER.xmap(factory, storage -> storage.wrapped); + } +} diff --git a/src/main/java/com/simibubi/create/api/contraption/storage/item/simple/SimpleMountedStorageType.java b/src/main/java/com/simibubi/create/api/contraption/storage/item/simple/SimpleMountedStorageType.java new file mode 100644 index 0000000000..61748939cf --- /dev/null +++ b/src/main/java/com/simibubi/create/api/contraption/storage/item/simple/SimpleMountedStorageType.java @@ -0,0 +1,49 @@ +package com.simibubi.create.api.contraption.storage.item.simple; + +import java.util.Optional; + +import com.mojang.serialization.Codec; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; + +import net.minecraftforge.common.capabilities.ForgeCapabilities; + +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.IItemHandlerModifiable; + +import org.jetbrains.annotations.Nullable; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; + +public abstract class SimpleMountedStorageType extends MountedItemStorageType { + protected SimpleMountedStorageType(Codec codec) { + super(codec); + } + + @Override + @Nullable + public SimpleMountedStorage mount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be) { + return Optional.ofNullable(be) + .map(this::getHandler) + .map(this::createStorage) + .orElse(null); + } + + protected IItemHandler getHandler(BlockEntity be) { + IItemHandler handler = be.getCapability(ForgeCapabilities.ITEM_HANDLER).orElse(null); + // make sure the handler is modifiable so new contents can be moved over on disassembly + return handler instanceof IItemHandlerModifiable modifiable ? modifiable : null; + } + + protected SimpleMountedStorage createStorage(IItemHandler handler) { + return new SimpleMountedStorage(this, handler); + } + + public static final class Impl extends SimpleMountedStorageType { + public Impl() { + super(SimpleMountedStorage.CODEC); + } + } +} diff --git a/src/main/java/com/simibubi/create/api/lookup/BlockLookup.java b/src/main/java/com/simibubi/create/api/lookup/BlockLookup.java new file mode 100644 index 0000000000..ce0936b0e6 --- /dev/null +++ b/src/main/java/com/simibubi/create/api/lookup/BlockLookup.java @@ -0,0 +1,66 @@ +package com.simibubi.create.api.lookup; + +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.impl.lookup.BlockLookupImpl; + +import net.minecraft.tags.TagKey; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; + +/** + * Lookup for objects provided by blocks. Values can either be registered directly + * or found lazily through providers. Providers are only queried once per block. + * If they return a value, that value is cached. If they don't, that block is recorded + * as not having a corresponding value. + *

+ * Provided values are reset on resource reloads and will be re-queried and re-cached the + * next time a block is queried. + *

+ * All providers are expected to be registered synchronously during game init. + * Adding new ones late is not supported. + */ +@ApiStatus.NonExtendable +public interface BlockLookup { + @Nullable + T find(Block block); + + /** + * Shortcut to avoid calling getBlock() on a BlockState. + */ + @Nullable + T find(BlockState state); + + /** + * Register a value to one block. + */ + void register(Block block, T value); + + /** + * Register a value to all entries of a tag. + */ + void registerTag(TagKey tag, T value); + + /** + * Register a new provider that will be queried. + * Providers are queried in reverse-registration order. + */ + void registerProvider(Provider provider); + + static BlockLookup create() { + return new BlockLookupImpl<>(); + } + + static BlockLookup create(Provider initialProvider) { + BlockLookup lookup = new BlockLookupImpl<>(); + lookup.registerProvider(initialProvider); + return lookup; + } + + @FunctionalInterface + interface Provider { + @Nullable + T get(Block block); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/Contraption.java b/src/main/java/com/simibubi/create/content/contraptions/Contraption.java index 502acc26f2..26b025425d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/Contraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/Contraption.java @@ -124,10 +124,6 @@ import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraftforge.client.model.data.ModelData; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.capability.IFluidHandler; -import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.wrapper.CombinedInvWrapper; import net.minecraftforge.registries.GameData; public abstract class Contraption { @@ -267,7 +263,7 @@ public abstract class Contraption { stabilizedSubContraptions.put(movedContraption.getUUID(), new BlockFace(toLocalPos(pos), face)); } - storage.createHandlers(); + storage.initialize(); gatherBBsOffThread(); } @@ -427,7 +423,7 @@ public abstract class Contraption { frontier.add(offsetPos); } - addBlock(pos, capture(world, pos)); + addBlock(world, pos, capture(world, pos)); if (blocks.size() <= AllConfigs.server().kinetics.maxBlocksMoved.get()) return true; else @@ -566,7 +562,7 @@ public abstract class Contraption { frontier.add(ropePos); break; } - addBlock(ropePos, capture(world, ropePos)); + addBlock(world, ropePos, capture(world, ropePos)); } } @@ -638,24 +634,25 @@ public abstract class Contraption { return Pair.of(new StructureBlockInfo(pos, blockstate, compoundnbt), blockEntity); } - protected void addBlock(BlockPos pos, Pair pair) { + protected void addBlock(Level level, BlockPos pos, Pair pair) { StructureBlockInfo captured = pair.getKey(); BlockPos localPos = pos.subtract(anchor); - StructureBlockInfo structureBlockInfo = new StructureBlockInfo(localPos, captured.state(), captured.nbt()); + BlockState state = captured.state(); + StructureBlockInfo structureBlockInfo = new StructureBlockInfo(localPos, state, captured.nbt()); if (blocks.put(localPos, structureBlockInfo) != null) return; bounds = bounds.minmax(new AABB(localPos)); BlockEntity be = pair.getValue(); - storage.addBlock(localPos, be); + storage.addBlock(level, state, pos, localPos, be); captureMultiblock(localPos, structureBlockInfo, be); - if (AllMovementBehaviours.getBehaviour(captured.state()) != null) + if (AllMovementBehaviours.getBehaviour(state) != null) actors.add(MutablePair.of(structureBlockInfo, null)); - MovingInteractionBehaviour interactionBehaviour = AllInteractionBehaviours.getBehaviour(captured.state()); + MovingInteractionBehaviour interactionBehaviour = AllInteractionBehaviours.getBehaviour(state); if (interactionBehaviour != null) interactors.put(localPos, interactionBehaviour); @@ -735,6 +732,8 @@ public abstract class Contraption { }); }); + storage.read(nbt, spawnData, this); + actors.clear(); nbt.getList("Actors", Tag.TAG_COMPOUND) .forEach(c -> { @@ -776,8 +775,6 @@ public abstract class Contraption { interactors.put(pos, behaviour); }); - storage.read(nbt, presentBlockEntities, spawnData); - if (nbt.contains("BoundsFront")) bounds = NBTHelper.readAABB(nbt.getList("BoundsFront", Tag.TAG_FLOAT)); @@ -827,8 +824,8 @@ public abstract class Contraption { superglueNBT.add(c); } } - - (spawnPacket ? getStorageForSpawnPacket() : storage).write(nbt, spawnPacket); + + writeStorage(nbt, spawnPacket); ListTag interactorNBT = new ListTag(); for (BlockPos pos : interactors.keySet()) { @@ -870,9 +867,9 @@ public abstract class Contraption { return nbt; } - - protected MountedStorageManager getStorageForSpawnPacket() { - return storage; + + public void writeStorage(CompoundTag nbt, boolean spawnPacket) { + storage.write(nbt, spawnPacket); } private CompoundTag writeBlocksCompound() { @@ -974,8 +971,6 @@ public abstract class Contraption { } public void removeBlocksFromWorld(Level world, BlockPos offset) { - storage.removeStorageFromWorld(); - glueToRemove.forEach(glue -> { superglue.add(glue.getBoundingBox() .move(Vec3.atLowerCornerOf(offset.offset(anchor)) @@ -1157,9 +1152,10 @@ public abstract class Contraption { } blockEntity.load(tag); - storage.addStorageToWorld(block, blockEntity); } + storage.unmount(world, block, targetPos, blockEntity); + if (blockEntity != null) { transform.apply(blockEntity); } @@ -1180,8 +1176,6 @@ public abstract class Contraption { if (!world.isClientSide) world.addFreshEntity(new SuperGlueEntity(world, box)); } - - storage.clear(); } protected void translateMultiblockControllers(StructureTransform transform) { @@ -1449,20 +1443,8 @@ public abstract class Contraption { return maxDistSq; } - public IItemHandlerModifiable getSharedInventory() { - return storage.getItems(); - } - - public IItemHandlerModifiable getSharedFuelInventory() { - return storage.getFuelItems(); - } - - public IFluidHandler getSharedFluidTanks() { - return storage.getFluids(); - } - - public MountedStorageManager getStorageManager() { - return storage; + public MountedStorageManager getStorage() { + return this.storage; } public RenderedBlocks getRenderedBlocks() { @@ -1487,36 +1469,8 @@ public abstract class Contraption { return simplifiedEntityColliders; } - public void handleContraptionFluidPacket(BlockPos localPos, FluidStack containedFluid) { - storage.updateContainedFluid(localPos, containedFluid); - } - - public void handleContraptionItemPacket(BlockPos localPos, List containedItems) { - storage.updateContainedItem(localPos, containedItems); - } - - public static class ContraptionInvWrapper extends CombinedInvWrapper { - protected final boolean isExternal; - - public ContraptionInvWrapper(boolean isExternal, IItemHandlerModifiable... itemHandler) { - super(itemHandler); - this.isExternal = isExternal; - } - - public ContraptionInvWrapper(IItemHandlerModifiable... itemHandler) { - this(false, itemHandler); - } - - public boolean isSlotExternal(int slot) { - if (isExternal) - return true; - IItemHandlerModifiable handler = getHandlerFromIndex(getIndexForSlot(slot)); - return handler instanceof ContraptionInvWrapper && ((ContraptionInvWrapper) handler).isSlotExternal(slot); - } - } - public void tickStorage(AbstractContraptionEntity entity) { - storage.entityTick(entity); + getStorage().tick(entity); } public boolean containsBlockBreakers() { diff --git a/src/main/java/com/simibubi/create/content/contraptions/MountedFluidStorage.java b/src/main/java/com/simibubi/create/content/contraptions/MountedFluidStorage.java deleted file mode 100644 index f0024dce60..0000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/MountedFluidStorage.java +++ /dev/null @@ -1,174 +0,0 @@ -package com.simibubi.create.content.contraptions; - -import com.simibubi.create.AllPackets; -import com.simibubi.create.content.contraptions.sync.ContraptionFluidPacket; -import com.simibubi.create.content.fluids.tank.CreativeFluidTankBlockEntity; -import com.simibubi.create.content.fluids.tank.CreativeFluidTankBlockEntity.CreativeSmartFluidTank; -import com.simibubi.create.content.fluids.tank.FluidTankBlockEntity; -import com.simibubi.create.foundation.fluid.SmartFluidTank; - -import net.createmod.catnip.animation.LerpedFloat; -import net.createmod.catnip.animation.LerpedFloat.Chaser; -import net.createmod.catnip.nbt.NBTHelper; -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.block.entity.BlockEntity; - -import net.minecraftforge.common.capabilities.ForgeCapabilities; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.IFluidTank; -import net.minecraftforge.fluids.capability.IFluidHandler; -import net.minecraftforge.network.PacketDistributor; - -public class MountedFluidStorage { - - SmartFluidTank tank; - private boolean valid; - private BlockEntity blockEntity; - - private int packetCooldown = 0; - private boolean sendPacket = false; - - public static boolean canUseAsStorage(BlockEntity be) { - if (be instanceof FluidTankBlockEntity) - return ((FluidTankBlockEntity) be).isController(); - return false; - } - - public MountedFluidStorage(BlockEntity be) { - assignBlockEntity(be); - } - - public void assignBlockEntity(BlockEntity be) { - this.blockEntity = be; - tank = createMountedTank(be); - } - - private SmartFluidTank createMountedTank(BlockEntity be) { - if (be instanceof CreativeFluidTankBlockEntity) - return new CreativeSmartFluidTank( - ((FluidTankBlockEntity) be).getTotalTankSize() * FluidTankBlockEntity.getCapacityMultiplier(), $ -> { - }); - if (be instanceof FluidTankBlockEntity) - return new SmartFluidTank( - ((FluidTankBlockEntity) be).getTotalTankSize() * FluidTankBlockEntity.getCapacityMultiplier(), - this::onFluidStackChanged); - return null; - } - - public void tick(Entity entity, BlockPos pos, boolean isRemote) { - if (!isRemote) { - if (packetCooldown > 0) - packetCooldown--; - else if (sendPacket) { - sendPacket = false; - AllPackets.getChannel().send(PacketDistributor.TRACKING_ENTITY.with(() -> entity), - new ContraptionFluidPacket(entity.getId(), pos, tank.getFluid())); - packetCooldown = 8; - } - return; - } - - if (!(blockEntity instanceof FluidTankBlockEntity)) - return; - FluidTankBlockEntity tank = (FluidTankBlockEntity) blockEntity; - tank.getFluidLevel() - .tickChaser(); - } - - public void updateFluid(FluidStack fluid) { - tank.setFluid(fluid); - if (!(blockEntity instanceof FluidTankBlockEntity)) - return; - float fillState = tank.getFluidAmount() / (float) tank.getCapacity(); - FluidTankBlockEntity tank = (FluidTankBlockEntity) blockEntity; - if (tank.getFluidLevel() == null) - tank.setFluidLevel(LerpedFloat.linear() - .startWithValue(fillState)); - tank.getFluidLevel() - .chase(fillState, 0.5, Chaser.EXP); - IFluidTank tankInventory = tank.getTankInventory(); - if (tankInventory instanceof SmartFluidTank) - ((SmartFluidTank) tankInventory).setFluid(fluid); - } - - public void removeStorageFromWorld() { - valid = false; - if (blockEntity == null) - return; - - IFluidHandler teHandler = blockEntity.getCapability(ForgeCapabilities.FLUID_HANDLER) - .orElse(null); - if (!(teHandler instanceof SmartFluidTank)) - return; - SmartFluidTank smartTank = (SmartFluidTank) teHandler; - tank.setFluid(smartTank.getFluid()); - sendPacket = false; - valid = true; - } - - private void onFluidStackChanged(FluidStack fs) { - sendPacket = true; - } - - public void addStorageToWorld(BlockEntity be) { - if (tank instanceof CreativeSmartFluidTank) - return; - - LazyOptional capability = be.getCapability(ForgeCapabilities.FLUID_HANDLER); - IFluidHandler teHandler = capability.orElse(null); - if (!(teHandler instanceof SmartFluidTank)) - return; - - SmartFluidTank inv = (SmartFluidTank) teHandler; - inv.setFluid(tank.getFluid() - .copy()); - } - - public IFluidHandler getFluidHandler() { - return tank; - } - - public CompoundTag serialize() { - if (!valid) - return null; - CompoundTag tag = tank.writeToNBT(new CompoundTag()); - tag.putInt("Capacity", tank.getCapacity()); - - if (tank instanceof CreativeSmartFluidTank) { - NBTHelper.putMarker(tag, "Bottomless"); - tag.put("ProvidedStack", tank.getFluid() - .writeToNBT(new CompoundTag())); - } - return tag; - } - - public static MountedFluidStorage deserialize(CompoundTag nbt) { - MountedFluidStorage storage = new MountedFluidStorage(null); - if (nbt == null) - return storage; - - int capacity = nbt.getInt("Capacity"); - storage.tank = new SmartFluidTank(capacity, storage::onFluidStackChanged); - storage.valid = true; - - if (nbt.contains("Bottomless")) { - FluidStack providedStack = FluidStack.loadFluidStackFromNBT(nbt.getCompound("ProvidedStack")); - CreativeSmartFluidTank creativeSmartFluidTank = new CreativeSmartFluidTank(capacity, $ -> { - }); - creativeSmartFluidTank.setContainedFluid(providedStack); - storage.tank = creativeSmartFluidTank; - return storage; - } - - storage.tank.readFromNBT(nbt); - return storage; - } - - public boolean isValid() { - return valid; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/MountedStorage.java b/src/main/java/com/simibubi/create/content/contraptions/MountedStorage.java deleted file mode 100644 index faa6be9e7e..0000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/MountedStorage.java +++ /dev/null @@ -1,297 +0,0 @@ -package com.simibubi.create.content.contraptions; - -import java.util.List; - -import com.simibubi.create.AllBlockEntityTypes; -import com.simibubi.create.AllPackets; -import com.simibubi.create.AllTags.AllBlockTags; -import com.simibubi.create.content.contraptions.sync.ContraptionItemPacket; -import com.simibubi.create.content.equipment.toolbox.ToolboxInventory; -import com.simibubi.create.content.kinetics.belt.transport.TransportedItemStack; -import com.simibubi.create.content.kinetics.crafter.MechanicalCrafterBlockEntity; -import com.simibubi.create.content.logistics.crate.BottomlessItemHandler; -import com.simibubi.create.content.logistics.depot.DepotBehaviour; -import com.simibubi.create.content.logistics.depot.DepotBlockEntity; -import com.simibubi.create.content.logistics.vault.ItemVaultBlockEntity; -import com.simibubi.create.content.processing.recipe.ProcessingInventory; - -import net.createmod.catnip.nbt.NBTHelper; -import net.minecraft.core.BlockPos; -import net.minecraft.core.NonNullList; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.ContainerHelper; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.entity.BarrelBlockEntity; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.ChestBlockEntity; -import net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity; -import net.minecraft.world.level.block.state.BlockState; - -import net.minecraftforge.common.capabilities.ForgeCapabilities; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.ItemStackHandler; -import net.minecraftforge.network.PacketDistributor; -import net.minecraftforge.registries.ForgeRegistries; - -public class MountedStorage { - - private static final ItemStackHandler dummyHandler = new ItemStackHandler(); - - ItemStackHandler handler; - boolean noFuel; - boolean valid; - - private int packetCooldown = 0; - private boolean sendPacket = false; - - BlockEntity blockEntity; - - public static boolean canUseAsStorage(BlockEntity be) { - if (be == null) - return false; - if (be instanceof MechanicalCrafterBlockEntity) - return false; - if (AllBlockEntityTypes.CREATIVE_CRATE.is(be)) - return true; - if (be instanceof ShulkerBoxBlockEntity) - return true; - if (be instanceof ChestBlockEntity) - return true; - if (be instanceof BarrelBlockEntity) - return true; - if (be instanceof ItemVaultBlockEntity) - return true; - if (be instanceof DepotBlockEntity) - return true; - - try { - LazyOptional capability = be.getCapability(ForgeCapabilities.ITEM_HANDLER); - IItemHandler handler = capability.orElse(null); - if (handler instanceof ItemStackHandler) - return !(handler instanceof ProcessingInventory); - return canUseModdedInventory(be, handler); - - } catch (Exception e) { - return false; - } - } - - public static boolean canUseModdedInventory(BlockEntity be, IItemHandler handler) { - if (!(handler instanceof IItemHandlerModifiable validItemHandler)) - return false; - BlockState blockState = be.getBlockState(); - if (AllBlockTags.CONTRAPTION_INVENTORY_DENY.matches(blockState)) - return false; - - // There doesn't appear to be much of a standard for tagging chests/barrels - String blockId = ForgeRegistries.BLOCKS.getKey(blockState.getBlock()) - .getPath(); - if (blockId.contains("ender")) - return false; - return blockId.endsWith("_chest") || blockId.endsWith("_barrel"); - } - - public MountedStorage(BlockEntity be) { - this.blockEntity = be; - handler = dummyHandler; - noFuel = be instanceof ItemVaultBlockEntity; - } - - public void removeStorageFromWorld() { - valid = false; - sendPacket = false; - if (blockEntity == null) - return; - - if (blockEntity instanceof DepotBlockEntity depot) { - handler = new SyncedMountedItemStackHandler(1); - handler.setStackInSlot(0, depot.getHeldItem()); - valid = true; - return; - } - - if (blockEntity instanceof ChestBlockEntity) { - CompoundTag tag = blockEntity.saveWithFullMetadata(); - if (tag.contains("LootTable", 8)) - return; - - handler = new ItemStackHandler(((ChestBlockEntity) blockEntity).getContainerSize()); - NonNullList items = NonNullList.withSize(handler.getSlots(), ItemStack.EMPTY); - ContainerHelper.loadAllItems(tag, items); - for (int i = 0; i < items.size(); i++) - handler.setStackInSlot(i, items.get(i)); - valid = true; - return; - } - - IItemHandler beHandler = blockEntity.getCapability(ForgeCapabilities.ITEM_HANDLER) - .orElse(dummyHandler); - if (beHandler == dummyHandler) - return; - - // multiblock vaults need to provide individual invs - if (blockEntity instanceof ItemVaultBlockEntity) { - handler = ((ItemVaultBlockEntity) blockEntity).getInventoryOfBlock(); - valid = true; - return; - } - - // be uses ItemStackHandler - if (beHandler instanceof ItemStackHandler) { - handler = (ItemStackHandler) beHandler; - valid = true; - return; - } - - // serialization not accessible -> fill into a serializable handler - if (beHandler instanceof IItemHandlerModifiable) { - IItemHandlerModifiable inv = (IItemHandlerModifiable) beHandler; - handler = new ItemStackHandler(beHandler.getSlots()); - for (int slot = 0; slot < handler.getSlots(); slot++) { - handler.setStackInSlot(slot, inv.getStackInSlot(slot)); - inv.setStackInSlot(slot, ItemStack.EMPTY); - } - valid = true; - return; - } - - } - - public void addStorageToWorld(BlockEntity be) { - // FIXME: More dynamic mounted storage in .4 - if (handler instanceof BottomlessItemHandler) - return; - - if (be instanceof DepotBlockEntity depot) { - if (handler.getSlots() > 0) - depot.getBehaviour(DepotBehaviour.TYPE) - .setCenteredHeldItem(new TransportedItemStack(handler.getStackInSlot(0))); - return; - } - - if (be instanceof ChestBlockEntity) { - CompoundTag tag = be.saveWithFullMetadata(); - tag.remove("Items"); - NonNullList items = NonNullList.withSize(handler.getSlots(), ItemStack.EMPTY); - for (int i = 0; i < items.size(); i++) - items.set(i, handler.getStackInSlot(i)); - ContainerHelper.saveAllItems(tag, items); - be.load(tag); - return; - } - - if (be instanceof ItemVaultBlockEntity) { - ((ItemVaultBlockEntity) be).applyInventoryToBlock(handler); - return; - } - - LazyOptional capability = be.getCapability(ForgeCapabilities.ITEM_HANDLER); - IItemHandler teHandler = capability.orElse(null); - if (!(teHandler instanceof IItemHandlerModifiable)) - return; - - IItemHandlerModifiable inv = (IItemHandlerModifiable) teHandler; - for (int slot = 0; slot < Math.min(inv.getSlots(), handler.getSlots()); slot++) - inv.setStackInSlot(slot, handler.getStackInSlot(slot)); - } - - public void tick(Entity entity, BlockPos pos, boolean isRemote) { - if (isRemote) - return; - if (packetCooldown > 0) { - packetCooldown--; - return; - } - if (sendPacket) { - sendPacket = false; - AllPackets.getChannel() - .send(PacketDistributor.TRACKING_ENTITY.with(() -> entity), - new ContraptionItemPacket(entity.getId(), pos, handler)); - packetCooldown = 8; - } - } - - public void updateItems(List containedItems) { - for (int i = 0; i < Math.min(containedItems.size(), handler.getSlots()); i++) - handler.setStackInSlot(i, containedItems.get(i)); - if (blockEntity instanceof DepotBlockEntity depot) - depot.setHeldItem(handler.getStackInSlot(0)); - } - - public IItemHandlerModifiable getItemHandler() { - return handler; - } - - public CompoundTag serialize() { - if (!valid) - return null; - - CompoundTag tag = handler.serializeNBT(); - if (noFuel) - NBTHelper.putMarker(tag, "NoFuel"); - if (handler instanceof ToolboxInventory) - NBTHelper.putMarker(tag, "Toolbox"); - if (needsSync()) - NBTHelper.putMarker(tag, "Synced"); - - if (!(handler instanceof BottomlessItemHandler)) - return tag; - - NBTHelper.putMarker(tag, "Bottomless"); - tag.put("ProvidedStack", handler.getStackInSlot(0) - .serializeNBT()); - return tag; - } - - public static MountedStorage deserialize(CompoundTag nbt) { - MountedStorage storage = new MountedStorage(null); - storage.handler = new ItemStackHandler(); - if (nbt == null) - return storage; - if (nbt.contains("Toolbox")) - storage.handler = new ToolboxInventory(null); - if (nbt.contains("Synced")) - storage.handler = storage.new SyncedMountedItemStackHandler(1); - - storage.valid = true; - storage.noFuel = nbt.contains("NoFuel"); - - if (nbt.contains("Bottomless")) { - ItemStack providedStack = ItemStack.of(nbt.getCompound("ProvidedStack")); - storage.handler = new BottomlessItemHandler(() -> providedStack); - return storage; - } - - storage.handler.deserializeNBT(nbt); - return storage; - } - - public boolean isValid() { - return valid; - } - - public boolean canUseForFuel() { - return !noFuel; - } - - public boolean needsSync() { - return handler instanceof SyncedMountedItemStackHandler; - } - - public class SyncedMountedItemStackHandler extends ItemStackHandler { - - public SyncedMountedItemStackHandler(int i) { - super(i); - } - - @Override - protected void onContentsChanged(int slot) { - sendPacket = true; - } - - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/MountedStorageInteraction.java b/src/main/java/com/simibubi/create/content/contraptions/MountedStorageInteraction.java deleted file mode 100644 index db1c057984..0000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/MountedStorageInteraction.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.simibubi.create.content.contraptions; - -import java.util.List; -import java.util.function.Supplier; - -import com.google.common.collect.ImmutableList; -import com.simibubi.create.foundation.utility.CreateLang; - -import net.minecraft.network.chat.Component; -import net.minecraft.util.Mth; -import net.minecraft.world.MenuProvider; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.inventory.ChestMenu; -import net.minecraft.world.inventory.MenuType; -import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.wrapper.RecipeWrapper; - -public class MountedStorageInteraction { - - public static final List> menus = ImmutableList.of(MenuType.GENERIC_9x1, MenuType.GENERIC_9x2, - MenuType.GENERIC_9x3, MenuType.GENERIC_9x4, MenuType.GENERIC_9x5, MenuType.GENERIC_9x6); - - public static MenuProvider createMenuProvider(Component displayName, IItemHandlerModifiable handler, - int slotCount, Supplier stillValid) { - int rows = Mth.clamp(slotCount / 9, 1, 6); - MenuType menuType = menus.get(rows - 1); - Component menuName = CreateLang.translateDirect("contraptions.moving_container", displayName); - - return new MenuProvider() { - - @Override - public AbstractContainerMenu createMenu(int pContainerId, Inventory pPlayerInventory, Player pPlayer) { - return new ChestMenu(menuType, pContainerId, pPlayerInventory, new StorageInteractionContainer(handler, stillValid), - rows); - } - - @Override - public Component getDisplayName() { - return menuName; - } - - }; - } - - public static class StorageInteractionContainer extends RecipeWrapper { - - private Supplier stillValid; - - public StorageInteractionContainer(IItemHandlerModifiable inv, Supplier stillValid) { - super(inv); - this.stillValid = stillValid; - } - - @Override - public boolean stillValid(Player player) { - return stillValid.get(); - } - - @Override - public int getMaxStackSize() { - return 64; - } - - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/MountedStorageManager.java b/src/main/java/com/simibubi/create/content/contraptions/MountedStorageManager.java index b62f34270e..a22470baca 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/MountedStorageManager.java +++ b/src/main/java/com/simibubi/create/content/contraptions/MountedStorageManager.java @@ -1,289 +1,474 @@ package com.simibubi.create.content.contraptions; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.IdentityHashMap; import java.util.List; import java.util.Map; -import java.util.Map.Entry; -import java.util.TreeMap; -import java.util.function.Supplier; -import java.util.stream.Collectors; +import java.util.Set; +import java.util.function.Predicate; -import com.simibubi.create.content.contraptions.Contraption.ContraptionInvWrapper; -import com.simibubi.create.content.fluids.tank.FluidTankBlockEntity; -import com.simibubi.create.content.logistics.depot.DepotBlockEntity; -import com.simibubi.create.foundation.fluid.CombinedTankWrapper; +import org.jetbrains.annotations.Nullable; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Sets; +import com.google.common.collect.Sets.SetView; +import com.mojang.datafixers.util.Pair; +import com.simibubi.create.AllPackets; +import com.simibubi.create.Create; +import com.simibubi.create.api.contraption.storage.MountedStorageTypeRegistry; +import com.simibubi.create.api.contraption.storage.SyncedMountedStorage; +import com.simibubi.create.api.contraption.storage.fluid.MountedFluidStorage; +import com.simibubi.create.api.contraption.storage.fluid.MountedFluidStorageType; +import com.simibubi.create.api.contraption.storage.fluid.MountedFluidStorageWrapper; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorage; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageWrapper; +import com.simibubi.create.content.equipment.toolbox.ToolboxMountedStorage; +import com.simibubi.create.content.fluids.tank.storage.FluidTankMountedStorage; +import com.simibubi.create.content.fluids.tank.storage.creative.CreativeFluidTankMountedStorage; +import com.simibubi.create.content.logistics.crate.CreativeCrateMountedStorage; +import com.simibubi.create.content.logistics.depot.storage.DepotMountedStorage; +import com.simibubi.create.content.logistics.vault.ItemVaultMountedStorage; +import com.simibubi.create.impl.contraption.storage.FallbackMountedStorage; -import net.createmod.catnip.lang.Components; import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.NbtOps; import net.minecraft.nbt.NbtUtils; import net.minecraft.nbt.Tag; -import net.minecraft.network.chat.Component; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.ChestBlock; +import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.properties.ChestType; +import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.IFluidTank; -import net.minecraftforge.fluids.capability.IFluidHandler; -import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction; -import net.minecraftforge.fluids.capability.templates.FluidTank; import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.ItemStackHandler; import net.minecraftforge.items.wrapper.CombinedInvWrapper; +import net.minecraftforge.network.PacketDistributor; public class MountedStorageManager { + // builders used during assembly, null afterward + // ImmutableMap.Builder is not used because it will throw with duplicate keys, not override them + private Map itemsBuilder; + private Map fluidsBuilder; + private Map syncedItemsBuilder; + private Map syncedFluidsBuilder; - protected ContraptionInvWrapper inventory; - protected ContraptionInvWrapper fuelInventory; - protected CombinedTankWrapper fluidInventory; - protected Map storage; - protected Map fluidStorage; + // built data structures after assembly, null before + private ImmutableMap allItemStorages; + // different from allItemStorages, does not contain internal ones + protected MountedItemStorageWrapper items; + @Nullable + protected MountedItemStorageWrapper fuelItems; + protected MountedFluidStorageWrapper fluids; + + private ImmutableMap syncedItems; + private ImmutableMap syncedFluids; + + private List externalHandlers; + private CombinedInvWrapper allItems; + + // ticks until storage can sync again + private int syncCooldown; + + // client-side: not all storages are synced, this determines which interactions are valid + private Set interactablePositions; public MountedStorageManager() { - storage = new TreeMap<>(); - fluidStorage = new TreeMap<>(); + this.reset(); } - public void entityTick(AbstractContraptionEntity entity) { - boolean isClientSide = entity.level().isClientSide; - storage.forEach((pos, mfs) -> mfs.tick(entity, pos, isClientSide)); - fluidStorage.forEach((pos, mfs) -> mfs.tick(entity, pos, isClientSide)); - } - - public void createHandlers() { - Collection itemHandlers = storage.values(); - - inventory = wrapItems(itemHandlers.stream() - .map(MountedStorage::getItemHandler) - .toList(), false); - - fuelInventory = wrapItems(itemHandlers.stream() - .filter(MountedStorage::canUseForFuel) - .map(MountedStorage::getItemHandler) - .toList(), true); - - fluidInventory = wrapFluids(fluidStorage.values() - .stream() - .map(MountedFluidStorage::getFluidHandler) - .collect(Collectors.toList())); - } - - protected ContraptionInvWrapper wrapItems(Collection list, boolean fuel) { - return new ContraptionInvWrapper(Arrays.copyOf(list.toArray(), list.size(), IItemHandlerModifiable[].class)); - } - - protected CombinedTankWrapper wrapFluids(Collection list) { - return new CombinedTankWrapper(Arrays.copyOf(list.toArray(), list.size(), IFluidHandler[].class)); - } - - public void addBlock(BlockPos localPos, BlockEntity be) { - if (be != null && MountedStorage.canUseAsStorage(be)) - storage.put(localPos, new MountedStorage(be)); - if (be != null && MountedFluidStorage.canUseAsStorage(be)) - fluidStorage.put(localPos, new MountedFluidStorage(be)); - } - - public void read(CompoundTag nbt, Map presentBlockEntities, boolean clientPacket) { - storage.clear(); - NBTHelper.iterateCompoundList(nbt.getList("Storage", Tag.TAG_COMPOUND), c -> storage - .put(NbtUtils.readBlockPos(c.getCompound("Pos")), MountedStorage.deserialize(c.getCompound("Data")))); - - fluidStorage.clear(); - NBTHelper.iterateCompoundList(nbt.getList("FluidStorage", Tag.TAG_COMPOUND), c -> fluidStorage - .put(NbtUtils.readBlockPos(c.getCompound("Pos")), MountedFluidStorage.deserialize(c.getCompound("Data")))); - - if (clientPacket && presentBlockEntities != null) - bindTanksAndDepots(presentBlockEntities); - - List handlers = new ArrayList<>(); - List fuelHandlers = new ArrayList<>(); - for (MountedStorage mountedStorage : storage.values()) { - IItemHandlerModifiable itemHandler = mountedStorage.getItemHandler(); - handlers.add(itemHandler); - if (mountedStorage.canUseForFuel()) - fuelHandlers.add(itemHandler); + public void initialize() { + if (this.isInitialized()) { + throw new IllegalStateException("Mounted storage has already been initialized"); } - inventory = wrapItems(handlers, false); - fuelInventory = wrapItems(fuelHandlers, true); - fluidInventory = wrapFluids(fluidStorage.values() - .stream() - .map(MountedFluidStorage::getFluidHandler) - .toList()); + this.allItemStorages = ImmutableMap.copyOf(this.itemsBuilder); + + this.items = new MountedItemStorageWrapper(subMap( + this.allItemStorages, storage -> !storage.isInternal() + )); + + this.allItems = this.items; + this.itemsBuilder = null; + + ImmutableMap fuelMap = subMap( + this.allItemStorages, storage -> !storage.isInternal() && storage.providesFuel() + ); + this.fuelItems = fuelMap.isEmpty() ? null : new MountedItemStorageWrapper(fuelMap); + + ImmutableMap fluids = ImmutableMap.copyOf(this.fluidsBuilder); + this.fluids = new MountedFluidStorageWrapper(fluids); + this.fluidsBuilder = null; + + this.syncedItems = ImmutableMap.copyOf(this.syncedItemsBuilder); + this.syncedItemsBuilder = null; + this.syncedFluids = ImmutableMap.copyOf(this.syncedFluidsBuilder); + this.syncedFluidsBuilder = null; } - public void bindTanksAndDepots(Map presentBlockEntities) { - for (Entry entry : storage.entrySet()) { - BlockEntity blockEntity = presentBlockEntities.get(entry.getKey()); - if (!(blockEntity instanceof DepotBlockEntity depot)) - return; - depot.setHeldItem(entry.getValue().handler.getStackInSlot(0)); - entry.getValue().blockEntity = depot; - } - for (Entry entry : fluidStorage.entrySet()) { - BlockEntity blockEntity = presentBlockEntities.get(entry.getKey()); - if (!(blockEntity instanceof FluidTankBlockEntity tank)) - return; - IFluidTank tankInventory = tank.getTankInventory(); - MountedFluidStorage mfs = entry.getValue(); - if (tankInventory instanceof FluidTank) - ((FluidTank) tankInventory).setFluid(mfs.tank.getFluid()); - tank.getFluidLevel() - .startWithValue(tank.getFillState()); - mfs.assignBlockEntity(tank); + private boolean isInitialized() { + return this.itemsBuilder == null; + } + + private void assertInitialized() { + if (!this.isInitialized()) { + throw new IllegalStateException("MountedStorageManager is uninitialized"); } } - public void write(CompoundTag nbt, boolean clientPacket) { - ListTag storageNBT = new ListTag(); - for (BlockPos pos : storage.keySet()) { - CompoundTag c = new CompoundTag(); - MountedStorage mountedStorage = storage.get(pos); - if (!mountedStorage.isValid()) - continue; - if (clientPacket && !mountedStorage.needsSync()) - continue; - c.put("Pos", NbtUtils.writeBlockPos(pos)); - c.put("Data", mountedStorage.serialize()); - storageNBT.add(c); - } - - ListTag fluidStorageNBT = new ListTag(); - for (BlockPos pos : fluidStorage.keySet()) { - CompoundTag c = new CompoundTag(); - MountedFluidStorage mountedStorage = fluidStorage.get(pos); - if (!mountedStorage.isValid()) - continue; - c.put("Pos", NbtUtils.writeBlockPos(pos)); - c.put("Data", mountedStorage.serialize()); - fluidStorageNBT.add(c); - } - - nbt.put("Storage", storageNBT); - nbt.put("FluidStorage", fluidStorageNBT); + protected void reset() { + this.allItemStorages = null; + this.items = null; + this.fuelItems = null; + this.fluids = null; + this.externalHandlers = new ArrayList<>(); + this.allItems = null; + this.itemsBuilder = new HashMap<>(); + this.fluidsBuilder = new HashMap<>(); + this.syncedItemsBuilder = new HashMap<>(); + this.syncedFluidsBuilder = new HashMap<>(); + // interactablePositions intentionally not reset } - public void removeStorageFromWorld() { - storage.values() - .forEach(MountedStorage::removeStorageFromWorld); - fluidStorage.values() - .forEach(MountedFluidStorage::removeStorageFromWorld); - } - - public void addStorageToWorld(StructureBlockInfo block, BlockEntity blockEntity) { - if (storage.containsKey(block.pos())) { - MountedStorage mountedStorage = storage.get(block.pos()); - if (mountedStorage.isValid()) - mountedStorage.addStorageToWorld(blockEntity); - } - - if (fluidStorage.containsKey(block.pos())) { - MountedFluidStorage mountedStorage = fluidStorage.get(block.pos()); - if (mountedStorage.isValid()) - mountedStorage.addStorageToWorld(blockEntity); - } - } - - public void clear() { - for (int i = 0; i < inventory.getSlots(); i++) - if (!inventory.isSlotExternal(i)) - inventory.setStackInSlot(i, ItemStack.EMPTY); - for (int i = 0; i < fluidInventory.getTanks(); i++) - fluidInventory.drain(fluidInventory.getFluidInTank(i), FluidAction.EXECUTE); - } - - public void updateContainedFluid(BlockPos localPos, FluidStack containedFluid) { - MountedFluidStorage mountedFluidStorage = fluidStorage.get(localPos); - if (mountedFluidStorage != null) - mountedFluidStorage.updateFluid(containedFluid); - } - - public void updateContainedItem(BlockPos localPos, List containedItems) { - MountedStorage mountedStorage = storage.get(localPos); - if (mountedStorage != null) - mountedStorage.updateItems(containedItems); - } - - public void attachExternal(IItemHandlerModifiable externalStorage) { - inventory = new ContraptionInvWrapper(externalStorage, inventory); - fuelInventory = new ContraptionInvWrapper(externalStorage, fuelInventory); - } - - public IItemHandlerModifiable getItems() { - return inventory; - } - - public IItemHandlerModifiable getFuelItems() { - return fuelInventory; - } - - public IFluidHandler getFluids() { - return fluidInventory; - } - - public Map getMountedItemStorage() { - return storage; - } - - public Map getMountedFluidStorage() { - return fluidStorage; - } - - public boolean handlePlayerStorageInteraction(Contraption contraption, Player player, BlockPos localPos) { - if (player.level().isClientSide()) { - BlockEntity localBE = contraption.presentBlockEntities.get(localPos); - return MountedStorage.canUseAsStorage(localBE); - } - - MountedStorageManager storageManager = contraption.getStorageForSpawnPacket(); - MountedStorage storage = storageManager.storage.get(localPos); - if (storage == null || storage.getItemHandler() == null) - return false; - IItemHandlerModifiable handler = storage.getItemHandler(); - - StructureBlockInfo info = contraption.getBlocks() - .get(localPos); - if (info != null && info.state().hasProperty(ChestBlock.TYPE)) { - ChestType chestType = info.state().getValue(ChestBlock.TYPE); - Direction facing = info.state().getOptionalValue(ChestBlock.FACING) - .orElse(Direction.SOUTH); - Direction connectedDirection = - chestType == ChestType.LEFT ? facing.getClockWise() : facing.getCounterClockWise(); - - if (chestType != ChestType.SINGLE) { - MountedStorage storage2 = storageManager.storage.get(localPos.relative(connectedDirection)); - if (storage2 != null && storage2.getItemHandler() != null) - handler = chestType == ChestType.RIGHT ? new CombinedInvWrapper(handler, storage2.getItemHandler()) - : new CombinedInvWrapper(storage2.getItemHandler(), handler); + public void addBlock(Level level, BlockState state, BlockPos globalPos, BlockPos localPos, @Nullable BlockEntity be) { + MountedItemStorageType itemType = MountedStorageTypeRegistry.ITEM_LOOKUP.find(state); + if (itemType != null) { + MountedItemStorage storage = itemType.mount(level, state, globalPos, be); + if (storage != null) { + this.addStorage(storage, localPos); } } - int slotCount = handler.getSlots(); - if (slotCount == 0) - return false; - if (slotCount % 9 != 0) - return false; - - Supplier stillValid = () -> contraption.entity.isAlive() - && player.distanceToSqr(contraption.entity.toGlobalVector(Vec3.atCenterOf(localPos), 0)) < 64; - Component name = info != null ? info.state().getBlock() - .getName() : Components.literal("Container"); - player.openMenu(MountedStorageInteraction.createMenuProvider(name, handler, slotCount, stillValid)); - - Vec3 soundPos = contraption.entity.toGlobalVector(Vec3.atCenterOf(localPos), 0); - player.level().playSound(null, BlockPos.containing(soundPos), SoundEvents.BARREL_OPEN, SoundSource.BLOCKS, 0.75f, 1f); - return true; + MountedFluidStorageType fluidType = MountedStorageTypeRegistry.FLUID_LOOKUP.find(state); + if (fluidType != null) { + MountedFluidStorage storage = fluidType.mount(level, state, globalPos, be); + if (storage != null) { + this.addStorage(storage, localPos); + } + } } + public void unmount(Level level, StructureBlockInfo info, BlockPos globalPos, @Nullable BlockEntity be) { + BlockPos localPos = info.pos(); + BlockState state = info.state(); + + MountedItemStorage itemStorage = this.getAllItemStorages().get(localPos); + if (itemStorage != null) { + MountedItemStorageType expectedType = MountedStorageTypeRegistry.ITEM_LOOKUP.find(state); + if (itemStorage.type == expectedType) { + itemStorage.unmount(level, state, globalPos, be); + } + } + + MountedFluidStorage fluidStorage = this.getFluids().storages.get(localPos); + if (fluidStorage != null) { + MountedFluidStorageType expectedType = MountedStorageTypeRegistry.FLUID_LOOKUP.find(state); + if (fluidStorage.type == expectedType) { + fluidStorage.unmount(level, state, globalPos, be); + } + } + } + + public void tick(AbstractContraptionEntity entity) { + if (this.syncCooldown > 0) { + this.syncCooldown--; + return; + } + + Map items = new HashMap<>(); + Map fluids = new HashMap<>(); + this.syncedItems.forEach((pos, storage) -> { + if (storage.isDirty()) { + items.put(pos, (MountedItemStorage) storage); + storage.markClean(); + } + }); + this.syncedFluids.forEach((pos, storage) -> { + if (storage.isDirty()) { + fluids.put(pos, (MountedFluidStorage) storage); + storage.markClean(); + } + }); + + if (!items.isEmpty() || !fluids.isEmpty()) { + MountedStorageSyncPacket packet = new MountedStorageSyncPacket(entity.getId(), items, fluids); + AllPackets.getChannel().send(PacketDistributor.TRACKING_ENTITY.with(() -> entity), packet); + this.syncCooldown = 8; + } + } + + public void handleSync(MountedStorageSyncPacket packet, AbstractContraptionEntity entity) { + // packet only contains changed storages, grab existing ones before resetting + ImmutableMap items = this.getAllItemStorages(); + MountedFluidStorageWrapper fluids = this.getFluids(); + this.reset(); + + // track freshly synced storages + Map syncedStorages = new IdentityHashMap<>(); + + try { + // re-add existing ones + this.itemsBuilder.putAll(items); + this.fluidsBuilder.putAll(fluids.storages); + // add newly synced ones, overriding existing ones if present + packet.items.forEach((pos, storage) -> { + this.itemsBuilder.put(pos, storage); + syncedStorages.put((SyncedMountedStorage) storage, pos); + }); + packet.fluids.forEach((pos, storage) -> { + this.fluidsBuilder.put(pos, storage); + syncedStorages.put((SyncedMountedStorage) storage, pos); + }); + } catch (Throwable t) { + // an exception will leave the manager in an invalid state + Create.LOGGER.error("An error occurred while syncing a MountedStorageManager", t); + } + + this.initialize(); + + // call all afterSync methods + Contraption contraption = entity.getContraption(); + syncedStorages.forEach((storage, pos) -> storage.afterSync(contraption, pos)); + } + + // contraption is provided on the client for initial afterSync storage callbacks + public void read(CompoundTag nbt, boolean clientPacket, @Nullable Contraption contraption) { + this.reset(); + + try { + NBTHelper.iterateCompoundList(nbt.getList("items", Tag.TAG_COMPOUND), tag -> { + BlockPos pos = NbtUtils.readBlockPos(tag.getCompound("pos")); + CompoundTag data = tag.getCompound("storage"); + MountedItemStorage.CODEC.decode(NbtOps.INSTANCE, data) + .result() + .map(Pair::getFirst) + .ifPresent(storage -> this.addStorage(storage, pos)); + }); + + NBTHelper.iterateCompoundList(nbt.getList("fluids", Tag.TAG_COMPOUND), tag -> { + BlockPos pos = NbtUtils.readBlockPos(tag.getCompound("pos")); + CompoundTag data = tag.getCompound("storage"); + MountedFluidStorage.CODEC.decode(NbtOps.INSTANCE, data) + .result() + .map(Pair::getFirst) + .ifPresent(storage -> this.addStorage(storage, pos)); + }); + + this.readLegacy(nbt); + + if (nbt.contains("interactable_positions")) { + this.interactablePositions = new HashSet<>(); + NBTHelper.iterateCompoundList(nbt.getList("interactable_positions", Tag.TAG_COMPOUND), tag -> { + BlockPos pos = NbtUtils.readBlockPos(tag); + this.interactablePositions.add(pos); + }); + } + } catch (Throwable t) { + Create.LOGGER.error("Error deserializing mounted storage", t); + // an exception will leave the manager in an invalid state, initialize must be called + } + + this.initialize(); + + // for client sync, run initial afterSync callbacks + if (!clientPacket || contraption == null) + return; + + this.getAllItemStorages().forEach((pos, storage) -> { + if (storage instanceof SyncedMountedStorage synced) { + synced.afterSync(contraption, pos); + } + }); + this.getFluids().storages.forEach((pos, storage) -> { + if (storage instanceof SyncedMountedStorage synced) { + synced.afterSync(contraption, pos); + } + }); + } + + public void write(CompoundTag nbt, boolean clientPacket) { + ListTag items = new ListTag(); + this.getAllItemStorages().forEach((pos, storage) -> { + if (!clientPacket || storage instanceof SyncedMountedStorage) { + MountedItemStorage.CODEC.encodeStart(NbtOps.INSTANCE, storage).result().ifPresent(encoded -> { + CompoundTag tag = new CompoundTag(); + tag.put("pos", NbtUtils.writeBlockPos(pos)); + tag.put("storage", encoded); + items.add(tag); + }); + } + } + ); + if (!items.isEmpty()) { + nbt.put("items", items); + } + + ListTag fluids = new ListTag(); + this.getFluids().storages.forEach((pos, storage) -> { + if (!clientPacket || storage instanceof SyncedMountedStorage) { + MountedFluidStorage.CODEC.encodeStart(NbtOps.INSTANCE, storage).result().ifPresent(encoded -> { + CompoundTag tag = new CompoundTag(); + tag.put("pos", NbtUtils.writeBlockPos(pos)); + tag.put("storage", encoded); + fluids.add(tag); + }); + } + } + ); + if (!fluids.isEmpty()) { + nbt.put("fluids", fluids); + } + + if (clientPacket) { + // let the client know of all non-synced ones too + SetView positions = Sets.union(this.getAllItemStorages().keySet(), this.getFluids().storages.keySet()); + ListTag list = new ListTag(); + for (BlockPos pos : positions) { + list.add(NbtUtils.writeBlockPos(pos)); + } + nbt.put("interactable_positions", list); + } + } + + public void attachExternal(IItemHandlerModifiable externalStorage) { + this.externalHandlers.add(externalStorage); + IItemHandlerModifiable[] all = new IItemHandlerModifiable[this.externalHandlers.size() + 1]; + all[0] = this.items; + for (int i = 0; i < this.externalHandlers.size(); i++) { + all[i + 1] = this.externalHandlers.get(i); + } + + this.allItems = new CombinedInvWrapper(all); + } + + /** + * The primary way to access a contraption's inventory. Includes all + * non-internal mounted storages as well as all external storage. + */ + public CombinedInvWrapper getAllItems() { + this.assertInitialized(); + return this.allItems; + } + + /** + * Gets a map of all MountedItemStorages in the contraption, irrelevant of them + * being internal or providing fuel. + * @see MountedItemStorage#isInternal() + * @see MountedItemStorage#providesFuel() + */ + public ImmutableMap getAllItemStorages() { + this.assertInitialized(); + return this.allItemStorages; + } + + /** + * Gets an item handler wrapping all non-internal mounted storages. This is not + * the whole contraption inventory as it does not include external storages. + * Most often, you want {@link #getAllItems()}, which does. + */ + public MountedItemStorageWrapper getMountedItems() { + this.assertInitialized(); + return this.items; + } + + /** + * Gets an item handler wrapping all non-internal mounted storages that provide fuel. + * May be null if none are present. + */ + @Nullable + public MountedItemStorageWrapper getFuelItems() { + this.assertInitialized(); + return this.fuelItems; + } + + /** + * Gets a fluid handler wrapping all mounted fluid storages. + */ + public MountedFluidStorageWrapper getFluids() { + this.assertInitialized(); + return this.fluids; + } + + public boolean handlePlayerStorageInteraction(Contraption contraption, Player player, BlockPos localPos) { + if (!(player instanceof ServerPlayer serverPlayer)) { + return this.interactablePositions != null && this.interactablePositions.contains(localPos); + } + + StructureBlockInfo info = contraption.getBlocks().get(localPos); + if (info == null) + return false; + + MountedStorageManager storageManager = contraption.getStorage(); + MountedItemStorage storage = storageManager.getAllItemStorages().get(localPos); + + if (storage != null) { + return storage.handleInteraction(serverPlayer, contraption, info); + } else { + return false; + } + } + + private void readLegacy(CompoundTag nbt) { + NBTHelper.iterateCompoundList(nbt.getList("Storage", Tag.TAG_COMPOUND), tag -> { + BlockPos pos = NbtUtils.readBlockPos(tag.getCompound("Pos")); + CompoundTag data = tag.getCompound("Data"); + + if (data.contains("Toolbox")) { + this.addStorage(ToolboxMountedStorage.fromLegacy(data), pos); + } else if (data.contains("NoFuel")) { + this.addStorage(ItemVaultMountedStorage.fromLegacy(data), pos); + } else if (data.contains("Bottomless")) { + ItemStack supplied = ItemStack.of(data.getCompound("ProvidedStack")); + this.addStorage(new CreativeCrateMountedStorage(supplied), pos); + } else if (data.contains("Synced")) { + this.addStorage(DepotMountedStorage.fromLegacy(data), pos); + } else { + // we can create a fallback storage safely, it will be validated before unmounting + ItemStackHandler handler = new ItemStackHandler(); + handler.deserializeNBT(data); + this.addStorage(new FallbackMountedStorage(handler), pos); + } + }); + + NBTHelper.iterateCompoundList(nbt.getList("FluidStorage", Tag.TAG_COMPOUND), tag -> { + BlockPos pos = NbtUtils.readBlockPos(tag.getCompound("Pos")); + CompoundTag data = tag.getCompound("Data"); + + if (data.contains("Bottomless")) { + this.addStorage(CreativeFluidTankMountedStorage.fromLegacy(data), pos); + } else { + this.addStorage(FluidTankMountedStorage.fromLegacy(data), pos); + } + }); + } + + private void addStorage(MountedItemStorage storage, BlockPos pos) { + this.itemsBuilder.put(pos, storage); + if (storage instanceof SyncedMountedStorage synced) + this.syncedItemsBuilder.put(pos, synced); + } + + private void addStorage(MountedFluidStorage storage, BlockPos pos) { + this.fluidsBuilder.put(pos, storage); + if (storage instanceof SyncedMountedStorage synced) + this.syncedFluidsBuilder.put(pos, synced); + } + + private static ImmutableMap subMap(Map map, Predicate predicate) { + ImmutableMap.Builder builder = ImmutableMap.builder(); + map.forEach((key, value) -> { + if (predicate.test(value)) { + builder.put(key, value); + } + }); + return builder.build(); + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/MountedStorageSyncPacket.java b/src/main/java/com/simibubi/create/content/contraptions/MountedStorageSyncPacket.java new file mode 100644 index 0000000000..751990c21a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/MountedStorageSyncPacket.java @@ -0,0 +1,63 @@ +package com.simibubi.create.content.contraptions; + +import java.util.Map; + +import com.mojang.serialization.Codec; +import com.simibubi.create.api.contraption.storage.fluid.MountedFluidStorage; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorage; +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.NbtOps; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.entity.Entity; + +import net.minecraftforge.network.NetworkEvent.Context; + +public class MountedStorageSyncPacket extends SimplePacketBase { + public final int contraptionId; + public final Map items; + public final Map fluids; + + public MountedStorageSyncPacket(int contraptionId, Map items, Map fluids) { + this.contraptionId = contraptionId; + this.items = items; + this.fluids = fluids; + } + + public MountedStorageSyncPacket(FriendlyByteBuf buf) { + this.contraptionId = buf.readVarInt(); + this.items = read(buf, MountedItemStorage.CODEC); + this.fluids = read(buf, MountedFluidStorage.CODEC); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeVarInt(this.contraptionId); + write(buffer, this.items, MountedItemStorage.CODEC); + write(buffer, this.fluids, MountedFluidStorage.CODEC); + } + + @SuppressWarnings("deprecation") + private static void write(FriendlyByteBuf buf, Map map, Codec codec) { + buf.writeMap(map, FriendlyByteBuf::writeBlockPos, (b, t) -> b.writeWithCodec(NbtOps.INSTANCE, codec, t)); + } + + @SuppressWarnings("deprecation") + private static Map read(FriendlyByteBuf buf, Codec codec) { + return buf.readMap(FriendlyByteBuf::readBlockPos, (b) -> b.readWithCodec(NbtOps.INSTANCE, codec)); + } + + @Override + public boolean handle(Context context) { + context.enqueueWork(() -> { + Entity entity = Minecraft.getInstance().level.getEntity(this.contraptionId); + if (!(entity instanceof AbstractContraptionEntity contraption)) + return; + + contraption.getContraption().getStorage().handleSync(this, contraption); + }); + return true; + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/OrientedContraptionEntity.java b/src/main/java/com/simibubi/create/content/contraptions/OrientedContraptionEntity.java index eb7c1db7a4..d94ded193d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/OrientedContraptionEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/OrientedContraptionEntity.java @@ -9,6 +9,7 @@ import javax.annotation.Nullable; import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.AllEntityTypes; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageWrapper; import com.simibubi.create.content.contraptions.bearing.StabilizedContraption; import com.simibubi.create.content.contraptions.minecart.MinecartSim2020; import com.simibubi.create.content.contraptions.minecart.capability.CapabilityMinecartController; @@ -435,9 +436,12 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity { .normalize() .scale(1)); if (fuel < 5 && contraption != null) { - ItemStack coal = ItemHelper.extract(contraption.getSharedInventory(), FUEL_ITEMS, 1, false); - if (!coal.isEmpty()) - fuel += 3600; + MountedItemStorageWrapper fuelItems = contraption.getStorage().getFuelItems(); + if (fuelItems != null) { + ItemStack coal = ItemHelper.extract(fuelItems, FUEL_ITEMS, 1, false); + if (!coal.isEmpty()) + fuel += 3600; + } } if (fuel != fuelBefore || pushX != 0 || pushZ != 0) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableFluidInterfaceBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableFluidInterfaceBlockEntity.java index 99b3106343..04feb48608 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableFluidInterfaceBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableFluidInterfaceBlockEntity.java @@ -24,7 +24,7 @@ public class PortableFluidInterfaceBlockEntity extends PortableStorageInterfaceB @Override public void startTransferringTo(Contraption contraption, float distance) { LazyOptional oldcap = capability; - capability = LazyOptional.of(() -> new InterfaceFluidHandler(contraption.getSharedFluidTanks())); + capability = LazyOptional.of(() -> new InterfaceFluidHandler(contraption.getStorage().getFluids())); oldcap.invalidate(); super.startTransferringTo(contraption, distance); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableItemInterfaceBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableItemInterfaceBlockEntity.java index fd72d56279..df3e2439ce 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableItemInterfaceBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/psi/PortableItemInterfaceBlockEntity.java @@ -25,7 +25,7 @@ public class PortableItemInterfaceBlockEntity extends PortableStorageInterfaceBl @Override public void startTransferringTo(Contraption contraption, float distance) { LazyOptional oldCap = capability; - capability = LazyOptional.of(() -> new InterfaceItemHandler(contraption.getSharedInventory())); + capability = LazyOptional.of(() -> new InterfaceItemHandler(contraption.getStorage().getAllItems())); oldCap.invalidate(); super.startTransferringTo(contraption, distance); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerMovementBehaviour.java index 768dba4317..fe17bfd1aa 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/actors/roller/RollerMovementBehaviour.java @@ -197,7 +197,7 @@ public class RollerMovementBehaviour extends BlockBreakingMovementBehaviour { if (!getStateToPaveWith(context).isAir()) { FilterItemStack filter = context.getFilterFromBE(); if (!ItemHelper - .extract(context.contraption.getSharedInventory(), + .extract(context.contraption.getStorage().getAllItems(), stack -> filter.test(context.world, stack), 1, true) .isEmpty()) startingY = 0; @@ -476,7 +476,7 @@ public class RollerMovementBehaviour extends BlockBreakingMovementBehaviour { return PaveResult.FAIL; FilterItemStack filter = context.getFilterFromBE(); - ItemStack held = ItemHelper.extract(context.contraption.getSharedInventory(), + ItemStack held = ItemHelper.extract(context.contraption.getStorage().getAllItems(), stack -> filter.test(context.world, stack), 1, false); if (held.isEmpty()) return PaveResult.FAIL; diff --git a/src/main/java/com/simibubi/create/content/contraptions/bearing/BearingContraption.java b/src/main/java/com/simibubi/create/content/contraptions/bearing/BearingContraption.java index ce4f40be7b..665122f97b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/bearing/BearingContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/bearing/BearingContraption.java @@ -57,11 +57,11 @@ public class BearingContraption extends Contraption { } @Override - public void addBlock(BlockPos pos, Pair capture) { + public void addBlock(Level level, BlockPos pos, Pair capture) { BlockPos localPos = pos.subtract(anchor); if (!getBlocks().containsKey(localPos) && AllBlockTags.WINDMILL_SAILS.matches(getSailBlock(capture))) sailBlocks++; - super.addBlock(pos, capture); + super.addBlock(level, pos, capture); } private BlockState getSailBlock(Pair capture) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/behaviour/MovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/MovementBehaviour.java index 02f502258f..f13673b304 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/behaviour/MovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/MovementBehaviour.java @@ -53,7 +53,7 @@ public interface MovementBehaviour { default void dropItem(MovementContext context, ItemStack stack) { ItemStack remainder; if (AllConfigs.server().kinetics.moveItemsToStorage.get()) - remainder = ItemHandlerHelper.insertItem(context.contraption.getSharedInventory(), stack, false); + remainder = ItemHandlerHelper.insertItem(context.contraption.getStorage().getAllItems(), stack, false); else remainder = stack; if (remainder.isEmpty()) diff --git a/src/main/java/com/simibubi/create/content/contraptions/behaviour/MovementContext.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/MovementContext.java index e742457371..d25d20103a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/behaviour/MovementContext.java +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/MovementContext.java @@ -1,7 +1,13 @@ package com.simibubi.create.content.contraptions.behaviour; +import java.util.function.Supplier; import java.util.function.UnaryOperator; +import org.jetbrains.annotations.Nullable; + +import com.google.common.base.Suppliers; +import com.simibubi.create.api.contraption.storage.fluid.MountedFluidStorage; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorage; import com.simibubi.create.content.contraptions.Contraption; import com.simibubi.create.content.logistics.filter.FilterItemStack; @@ -35,6 +41,9 @@ public class MovementContext { private FilterItemStack filter; + private final Supplier itemStorage; + private final Supplier fluidStorage; + public MovementContext(Level world, StructureBlockInfo info, Contraption contraption) { this.world = world; this.state = info.state(); @@ -51,6 +60,8 @@ public class MovementContext { data = new CompoundTag(); stall = false; filter = null; + this.itemStorage = Suppliers.memoize(() -> contraption.getStorage().getAllItemStorages().get(this.localPos)); + this.fluidStorage = Suppliers.memoize(() -> contraption.getStorage().getFluids().storages.get(this.localPos)); } public float getAnimationSpeed() { @@ -94,4 +105,13 @@ public class MovementContext { return filter = FilterItemStack.of(blockEntityData.getCompound("Filter")); } + @Nullable + public MountedItemStorage getItemStorage() { + return this.itemStorage.get(); + } + + @Nullable + public MountedFluidStorage getFluidStorage() { + return this.fluidStorage.get(); + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DispenserMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DispenserMovementBehaviour.java index 1018e98875..b82fd1057e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DispenserMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DispenserMovementBehaviour.java @@ -1,11 +1,18 @@ package com.simibubi.create.content.contraptions.behaviour.dispenser; import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; import com.simibubi.create.content.contraptions.behaviour.MovementContext; import com.simibubi.create.foundation.mixin.accessor.DispenserBlockAccessor; +import org.jetbrains.annotations.Nullable; + import net.minecraft.core.BlockPos; +import net.minecraft.core.BlockSource; import net.minecraft.core.Direction; import net.minecraft.core.dispenser.AbstractProjectileDispenseBehavior; import net.minecraft.core.dispenser.DefaultDispenseItemBehavior; @@ -14,11 +21,13 @@ import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.DispenserBlock; +import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; public class DispenserMovementBehaviour extends DropperMovementBehaviour { - private static final HashMap MOVED_DISPENSE_ITEM_BEHAVIOURS = new HashMap<>(); - private static final HashMap MOVED_PROJECTILE_DISPENSE_BEHAVIOURS = new HashMap<>(); + private static final Map movedDispenseItemBehaviors = new HashMap<>(); + private static final Set blacklist = new HashSet<>(); + private static boolean spawnEggsRegistered = false; public static void gatherMovedDispenseItemBehaviours() { @@ -27,7 +36,7 @@ public class DispenserMovementBehaviour extends DropperMovementBehaviour { public static void registerMovedDispenseItemBehaviour(Item item, IMovedDispenseItemBehaviour movedDispenseItemBehaviour) { - MOVED_DISPENSE_ITEM_BEHAVIOURS.put(item, movedDispenseItemBehaviour); + movedDispenseItemBehaviors.put(item, movedDispenseItemBehaviour); } public static DispenseItemBehavior getDispenseMethod(ItemStack itemstack) { @@ -35,55 +44,64 @@ public class DispenserMovementBehaviour extends DropperMovementBehaviour { } @Override - protected void activate(MovementContext context, BlockPos pos) { + protected IMovedDispenseItemBehaviour getDispenseBehavior(MovementContext context, BlockPos pos, ItemStack stack) { if (!spawnEggsRegistered) { spawnEggsRegistered = true; IMovedDispenseItemBehaviour.initSpawnEggs(); } - DispenseItemLocation location = getDispenseLocation(context); - if (location.isEmpty()) { - context.world.levelEvent(1001, pos, 0); - } else { - ItemStack itemStack = getItemStackAt(location, context); - // Special dispense item behaviour for moving contraptions - if (MOVED_DISPENSE_ITEM_BEHAVIOURS.containsKey(itemStack.getItem())) { - setItemStackAt(location, MOVED_DISPENSE_ITEM_BEHAVIOURS.get(itemStack.getItem()).dispense(itemStack, context, pos), context); - return; - } - - ItemStack backup = itemStack.copy(); - // If none is there, try vanilla registry - try { - if (MOVED_PROJECTILE_DISPENSE_BEHAVIOURS.containsKey(itemStack.getItem())) { - setItemStackAt(location, MOVED_PROJECTILE_DISPENSE_BEHAVIOURS.get(itemStack.getItem()).dispense(itemStack, context, pos), context); - return; - } - - DispenseItemBehavior behavior = getDispenseMethod(itemStack); - if (behavior instanceof AbstractProjectileDispenseBehavior) { // Projectile behaviours can be converted most of the time - IMovedDispenseItemBehaviour movedBehaviour = MovedProjectileDispenserBehaviour.of((AbstractProjectileDispenseBehavior) behavior); - setItemStackAt(location, movedBehaviour.dispense(itemStack, context, pos), context); - MOVED_PROJECTILE_DISPENSE_BEHAVIOURS.put(itemStack.getItem(), movedBehaviour); // buffer conversion if successful - return; - } - - Vec3 facingVec = Vec3.atLowerCornerOf(context.state.getValue(DispenserBlock.FACING).getNormal()); - facingVec = context.rotation.apply(facingVec); - facingVec.normalize(); - Direction clostestFacing = Direction.getNearest(facingVec.x, facingVec.y, facingVec.z); - ContraptionBlockSource blockSource = new ContraptionBlockSource(context, pos, clostestFacing); - - if (behavior.getClass() != DefaultDispenseItemBehavior.class) { // There is a dispense item behaviour registered for the vanilla dispenser - setItemStackAt(location, behavior.dispense(blockSource, itemStack), context); - return; - } - } catch (NullPointerException ignored) { - itemStack = backup; // Something went wrong with the BE being null in ContraptionBlockSource, reset the stack - } - - setItemStackAt(location, DEFAULT_BEHAVIOUR.dispense(itemStack, context, pos), context); // the default: launch the item + Item item = stack.getItem(); + // return registered/cached behavior if present + if (movedDispenseItemBehaviors.containsKey(item)) { + return movedDispenseItemBehaviors.get(item); } + + // if there isn't one, try to create one from a vanilla behavior + if (blacklist.contains(item)) { + // unless it's been blacklisted, which means a behavior was created already and errored + return MovedDefaultDispenseItemBehaviour.INSTANCE; + } + + DispenseItemBehavior behavior = getDispenseMethod(stack); + // no behavior or default, use the moved default + if (behavior == null || behavior.getClass() == DefaultDispenseItemBehavior.class) + return MovedDefaultDispenseItemBehaviour.INSTANCE; + + // projectile-specific behaviors are pretty straightforward to convert + if (behavior instanceof AbstractProjectileDispenseBehavior projectile) { + IMovedDispenseItemBehaviour movedBehaviour = MovedProjectileDispenserBehaviour.of(projectile); + // cache it for later + registerMovedDispenseItemBehaviour(item, movedBehaviour); + return movedBehaviour; + } + + // other behaviors are more convoluted due to BlockSource providing a BlockEntity. + Vec3 normal = getRotatedFacingNormal(context); + Direction nearestFacing = Direction.getNearest(normal.x, normal.y, normal.z); + ContraptionBlockSource source = new ContraptionBlockSource(context, pos, nearestFacing); + IMovedDispenseItemBehaviour movedBehavior = new FallbackMovedDispenseBehavior(item, behavior, source); + registerMovedDispenseItemBehaviour(item, movedBehavior); + return movedBehavior; } + private static Vec3 getRotatedFacingNormal(MovementContext ctx) { + Direction facing = ctx.state.getValue(DispenserBlock.FACING); + Vec3 normal = Vec3.atLowerCornerOf(facing.getNormal()); + return ctx.rotation.apply(normal); + } + + private record FallbackMovedDispenseBehavior(Item item, DispenseItemBehavior wrapped, BlockSource source) implements IMovedDispenseItemBehaviour { + @Override + public ItemStack dispense(ItemStack stack, MovementContext context, BlockPos pos) { + ItemStack backup = stack.copy(); + try { + return this.wrapped.dispense(this.source, stack); + } catch (NullPointerException ignored) { + // error due to lack of a BlockEntity. Un-register self to avoid continuing to fail + movedDispenseItemBehaviors.remove(this.item); + blacklist.add(this.item); + return backup; + } + } + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DropperMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DropperMovementBehaviour.java index 65f73bbe26..c164440c13 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DropperMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/DropperMovementBehaviour.java @@ -1,132 +1,88 @@ package com.simibubi.create.content.contraptions.behaviour.dispenser; -import java.util.ArrayList; -import java.util.List; -import java.util.Random; +import java.util.function.Predicate; +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.api.contraption.storage.item.MountedItemStorage; import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; import com.simibubi.create.content.contraptions.behaviour.MovementContext; import com.simibubi.create.foundation.item.ItemHelper; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntList; +import net.minecraft.Util; import net.minecraft.core.BlockPos; -import net.minecraft.core.NonNullList; -import net.minecraft.world.ContainerHelper; +import net.minecraft.util.RandomSource; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; +import net.minecraft.world.level.block.LevelEvent; +import net.minecraftforge.items.IItemHandler; public class DropperMovementBehaviour implements MovementBehaviour { - protected static final MovedDefaultDispenseItemBehaviour DEFAULT_BEHAVIOUR = - new MovedDefaultDispenseItemBehaviour(); - private static final Random RNG = new Random(); - - protected void activate(MovementContext context, BlockPos pos) { - DispenseItemLocation location = getDispenseLocation(context); - if (location.isEmpty()) { - context.world.levelEvent(1001, pos, 0); - } else { - setItemStackAt(location, DEFAULT_BEHAVIOUR.dispense(getItemStackAt(location, context), context, pos), - context); - } - } - @Override public void visitNewPosition(MovementContext context, BlockPos pos) { if (context.world.isClientSide) return; - collectItems(context); - activate(context, pos); - } - private void collectItems(MovementContext context) { - getStacks(context).stream() - .filter(itemStack -> !itemStack.isEmpty() && itemStack.getItem() != Items.AIR - && itemStack.getMaxStackSize() > itemStack.getCount()) - .forEach(itemStack -> itemStack.grow(ItemHelper - .extract(context.contraption.getSharedInventory(), (otherItemStack) -> ItemStack.isSameItemSameTags(itemStack, otherItemStack), - ItemHelper.ExtractionCountMode.UPTO, itemStack.getMaxStackSize() - itemStack.getCount(), false) - .getCount())); - } - - private void updateTemporaryData(MovementContext context) { - if (!(context.temporaryData instanceof NonNullList) && context.world != null) { - NonNullList stacks = NonNullList.withSize(getInvSize(), ItemStack.EMPTY); - ContainerHelper.loadAllItems(context.blockEntityData, stacks); - context.temporaryData = stacks; - } - } - - @SuppressWarnings("unchecked") - private NonNullList getStacks(MovementContext context) { - updateTemporaryData(context); - return (NonNullList) context.temporaryData; - } - - private ArrayList getUseableLocations(MovementContext context) { - ArrayList useable = new ArrayList<>(); - for (int slot = 0; slot < getInvSize(); slot++) { - DispenseItemLocation location = new DispenseItemLocation(true, slot); - ItemStack testStack = getItemStackAt(location, context); - if (testStack == null || testStack.isEmpty()) - continue; - if (testStack.getMaxStackSize() == 1) { - location = new DispenseItemLocation(false, ItemHelper.findFirstMatchingSlotIndex( - context.contraption.getSharedInventory(), ItemHelper.sameItemPredicate(testStack))); - if (!getItemStackAt(location, context).isEmpty()) - useable.add(location); - } else if (testStack.getCount() >= 2) - useable.add(location); - } - return useable; - } - - @Override - public void writeExtraData(MovementContext context) { - NonNullList stacks = getStacks(context); - if (stacks == null) + MountedItemStorage storage = context.getItemStorage(); + if (storage == null) return; - ContainerHelper.saveAllItems(context.blockEntityData, stacks); + + int slot = getSlot(storage, context.world.random, context.contraption.getStorage().getAllItems()); + if (slot == -1) { + // all slots empty + failDispense(context, pos); + return; + } + + // copy because dispense behaviors will modify it directly + ItemStack stack = storage.getStackInSlot(slot).copy(); + IMovedDispenseItemBehaviour behavior = getDispenseBehavior(context, pos, stack); + ItemStack remainder = behavior.dispense(stack, context, pos); + storage.setStackInSlot(slot, remainder); } - @Override - public void stopMoving(MovementContext context) { - MovementBehaviour.super.stopMoving(context); - writeExtraData(context); + protected IMovedDispenseItemBehaviour getDispenseBehavior(MovementContext context, BlockPos pos, ItemStack stack) { + return MovedDefaultDispenseItemBehaviour.INSTANCE; } - protected DispenseItemLocation getDispenseLocation(MovementContext context) { - int i = -1; - int j = 1; - List useableLocations = getUseableLocations(context); - for (int k = 0; k < useableLocations.size(); ++k) { - if (RNG.nextInt(j++) == 0) { - i = k; + /** + * Finds a dispensable slot. Empty slots are skipped and nearly-empty slots are topped off. + */ + private static int getSlot(MountedItemStorage storage, RandomSource random, IItemHandler contraptionInventory) { + IntList filledSlots = new IntArrayList(); + for (int i = 0; i < storage.getSlots(); i++) { + ItemStack stack = storage.getStackInSlot(i); + if (stack.isEmpty()) + continue; + + if (stack.getCount() == 1 && stack.getMaxStackSize() != 1) { + stack = tryTopOff(stack, contraptionInventory); + if (stack == null) { + continue; + } } + + filledSlots.add(i); } - if (i < 0) - return DispenseItemLocation.NONE; - else - return useableLocations.get(i); + + return switch (filledSlots.size()) { + case 0 -> -1; + case 1 -> filledSlots.getInt(0); + default -> Util.getRandom(filledSlots, random); + }; } - protected ItemStack getItemStackAt(DispenseItemLocation location, MovementContext context) { - if (location.isInternal()) { - return getStacks(context).get(location.getSlot()); - } else { - return context.contraption.getSharedInventory() - .getStackInSlot(location.getSlot()); - } + @Nullable + private static ItemStack tryTopOff(ItemStack stack, IItemHandler from) { + Predicate test = otherStack -> ItemStack.isSameItemSameTags(stack, otherStack); + int needed = stack.getMaxStackSize() - stack.getCount(); + + ItemStack extracted = ItemHelper.extract(from, test, ItemHelper.ExtractionCountMode.UPTO, needed, false); + return extracted.isEmpty() ? null : stack.copyWithCount(stack.getCount() + extracted.getCount()); } - protected void setItemStackAt(DispenseItemLocation location, ItemStack stack, MovementContext context) { - if (location.isInternal()) { - getStacks(context).set(location.getSlot(), stack); - } else { - context.contraption.getSharedInventory() - .setStackInSlot(location.getSlot(), stack); - } - } - - private static int getInvSize() { - return 9; + private static void failDispense(MovementContext ctx, BlockPos pos) { + ctx.world.levelEvent(LevelEvent.SOUND_DISPENSER_FAIL, pos, 0); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/MovedDefaultDispenseItemBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/MovedDefaultDispenseItemBehaviour.java index 1ad03f1bcf..641b4556cd 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/MovedDefaultDispenseItemBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/MovedDefaultDispenseItemBehaviour.java @@ -13,9 +13,10 @@ import net.minecraft.world.level.block.DispenserBlock; import net.minecraft.world.level.block.entity.HopperBlockEntity; import net.minecraft.world.phys.Vec3; import net.minecraftforge.items.ItemHandlerHelper; +import net.minecraftforge.items.wrapper.CombinedInvWrapper; public class MovedDefaultDispenseItemBehaviour implements IMovedDispenseItemBehaviour { - private static final MovedDefaultDispenseItemBehaviour DEFAULT_INSTANCE = new MovedDefaultDispenseItemBehaviour(); + public static final MovedDefaultDispenseItemBehaviour INSTANCE = new MovedDefaultDispenseItemBehaviour(); public static void doDispense(Level p_82486_0_, ItemStack p_82486_1_, int p_82486_2_, Vec3 facing, BlockPos p_82486_4_, MovementContext context) { @@ -98,10 +99,21 @@ public class MovedDefaultDispenseItemBehaviour implements IMovedDispenseItemBeha protected ItemStack placeItemInInventory(ItemStack consumedFrom, ItemStack output, MovementContext context, BlockPos pos, Vec3 facing) { consumedFrom.shrink(1); - ItemStack remainder = - ItemHandlerHelper.insertItem(context.contraption.getSharedInventory(), output.copy(), false); - if (!remainder.isEmpty()) - DEFAULT_INSTANCE.dispenseStack(output, context, pos, facing); + + ItemStack toInsert = output.copy(); + // try inserting into own inventory first + ItemStack remainder = ItemHandlerHelper.insertItem(context.getItemStorage(), toInsert, false); + if (!remainder.isEmpty()) { + // next, try the whole contraption inventory + // note that this contains the dispenser inventory. That's fine. + CombinedInvWrapper contraption = context.contraption.getStorage().getAllItems(); + ItemStack newRemainder = ItemHandlerHelper.insertItem(contraption, remainder, false); + if (!newRemainder.isEmpty()) { + // if there's *still* something left, dispense into world + INSTANCE.dispenseStack(remainder, context, pos, facing); + } + } + return consumedFrom; } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/storage/DispenserMountedStorage.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/storage/DispenserMountedStorage.java new file mode 100644 index 0000000000..b20c5cd906 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/storage/DispenserMountedStorage.java @@ -0,0 +1,49 @@ +package com.simibubi.create.content.contraptions.behaviour.dispenser.storage; + +import java.util.function.Consumer; +import java.util.function.Predicate; + +import org.jetbrains.annotations.Nullable; + +import com.mojang.serialization.Codec; +import com.simibubi.create.AllMountedStorageTypes; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; +import com.simibubi.create.api.contraption.storage.item.menu.MountedStorageMenus; +import com.simibubi.create.api.contraption.storage.item.simple.SimpleMountedStorage; + +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.MenuProvider; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.IItemHandlerModifiable; + +public class DispenserMountedStorage extends SimpleMountedStorage { + public static final Codec CODEC = SimpleMountedStorage.codec(DispenserMountedStorage::new); + + protected DispenserMountedStorage(MountedItemStorageType type, IItemHandler handler) { + super(type, handler); + } + + public DispenserMountedStorage(IItemHandler handler) { + this(AllMountedStorageTypes.DISPENSER.get(), handler); + } + + @Override + public boolean isInternal() { + return true; + } + + @Override + @Nullable + protected MenuProvider createMenuProvider(Component name, IItemHandlerModifiable handler, + Predicate stillValid, Consumer onClose) { + return MountedStorageMenus.createGeneric9x9(name, handler, stillValid, onClose); + } + + @Override + protected void playOpeningSound(ServerLevel level, Vec3 pos) { + // dispensers are silent + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/storage/DispenserMountedStorageType.java b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/storage/DispenserMountedStorageType.java new file mode 100644 index 0000000000..a5ff233a7a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/behaviour/dispenser/storage/DispenserMountedStorageType.java @@ -0,0 +1,17 @@ +package com.simibubi.create.content.contraptions.behaviour.dispenser.storage; + +import com.simibubi.create.api.contraption.storage.item.simple.SimpleMountedStorage; +import com.simibubi.create.api.contraption.storage.item.simple.SimpleMountedStorageType; + +import net.minecraftforge.items.IItemHandler; + +public class DispenserMountedStorageType extends SimpleMountedStorageType { + public DispenserMountedStorageType() { + super(DispenserMountedStorage.CODEC); + } + + @Override + protected SimpleMountedStorage createStorage(IItemHandler handler) { + return new DispenserMountedStorage(handler); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/minecart/TrainCargoManager.java b/src/main/java/com/simibubi/create/content/contraptions/minecart/TrainCargoManager.java index 6b045b69a4..33a9fadce8 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/minecart/TrainCargoManager.java +++ b/src/main/java/com/simibubi/create/content/contraptions/minecart/TrainCargoManager.java @@ -1,21 +1,18 @@ package com.simibubi.create.content.contraptions.minecart; -import java.util.Arrays; -import java.util.Collection; -import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; -import com.simibubi.create.content.contraptions.Contraption.ContraptionInvWrapper; -import com.simibubi.create.content.contraptions.MountedStorageManager; -import com.simibubi.create.foundation.fluid.CombinedTankWrapper; +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.api.contraption.storage.fluid.MountedFluidStorageWrapper; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageWrapper; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.contraptions.MountedStorageManager; -import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.capability.IFluidHandler; -import net.minecraftforge.items.IItemHandlerModifiable; public class TrainCargoManager extends MountedStorageManager { @@ -28,20 +25,13 @@ public class TrainCargoManager extends MountedStorageManager { } @Override - public void createHandlers() { - super.createHandlers(); - } - - @Override - protected ContraptionInvWrapper wrapItems(Collection list, boolean fuel) { - if (fuel) - return super.wrapItems(list, fuel); - return new CargoInvWrapper(Arrays.copyOf(list.toArray(), list.size(), IItemHandlerModifiable[].class)); - } - - @Override - protected CombinedTankWrapper wrapFluids(Collection list) { - return new CargoTankWrapper(Arrays.copyOf(list.toArray(), list.size(), IFluidHandler[].class)); + public void initialize() { + super.initialize(); + this.items = new CargoInvWrapper(this.items); + if (this.fuelItems != null) { + this.fuelItems = new CargoInvWrapper(this.fuelItems); + } + this.fluids = new CargoTankWrapper(this.fluids); } @Override @@ -51,36 +41,35 @@ public class TrainCargoManager extends MountedStorageManager { } @Override - public void read(CompoundTag nbt, Map presentBlockEntities, boolean clientPacket) { - super.read(nbt, presentBlockEntities, clientPacket); + public void read(CompoundTag nbt, boolean clientPacket, @Nullable Contraption contraption) { + super.read(nbt, clientPacket, contraption); ticksSinceLastExchange = nbt.getInt("TicksSinceLastExchange"); } public void resetIdleCargoTracker() { ticksSinceLastExchange = 0; } - + public void tickIdleCargoTracker() { ticksSinceLastExchange++; } - + public int getTicksSinceLastExchange() { return ticksSinceLastExchange; } - + public int getVersion() { return version.get(); } - + void changeDetected() { version.incrementAndGet(); resetIdleCargoTracker(); } - class CargoInvWrapper extends ContraptionInvWrapper { - - public CargoInvWrapper(IItemHandlerModifiable... itemHandler) { - super(false, itemHandler); + class CargoInvWrapper extends MountedItemStorageWrapper { + CargoInvWrapper(MountedItemStorageWrapper wrapped) { + super(wrapped.storages); } @Override @@ -108,10 +97,9 @@ public class TrainCargoManager extends MountedStorageManager { } - class CargoTankWrapper extends CombinedTankWrapper { - - public CargoTankWrapper(IFluidHandler... fluidHandler) { - super(fluidHandler); + class CargoTankWrapper extends MountedFluidStorageWrapper { + CargoTankWrapper(MountedFluidStorageWrapper wrapped) { + super(wrapped.storages); } @Override @@ -137,7 +125,7 @@ public class TrainCargoManager extends MountedStorageManager { changeDetected(); return drained; } - + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/mounted/MountedContraption.java b/src/main/java/com/simibubi/create/content/contraptions/mounted/MountedContraption.java index c358b89e2a..d9afae3424 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/mounted/MountedContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/mounted/MountedContraption.java @@ -60,7 +60,7 @@ public class MountedContraption extends Contraption { return false; Axis axis = state.getValue(RAIL_SHAPE) == RailShape.EAST_WEST ? Axis.X : Axis.Z; - addBlock(pos, Pair.of(new StructureBlockInfo(pos, AllBlocks.MINECART_ANCHOR.getDefaultState() + addBlock(world, pos, Pair.of(new StructureBlockInfo(pos, AllBlocks.MINECART_ANCHOR.getDefaultState() .setValue(BlockStateProperties.HORIZONTAL_AXIS, axis), null), null)); if (blocks.size() == 1) @@ -154,7 +154,7 @@ public class MountedContraption extends Contraption { public void addExtraInventories(Entity cart) { if (cart instanceof Container container) - storage.attachExternal(new ContraptionInvWrapper(true, new InvWrapper(container))); + storage.attachExternal(new InvWrapper(container)); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/piston/PistonContraption.java b/src/main/java/com/simibubi/create/content/contraptions/piston/PistonContraption.java index 05edb3a379..a0fc4237ee 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/piston/PistonContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/piston/PistonContraption.java @@ -187,8 +187,8 @@ public class PistonContraption extends TranslatingContraption { } @Override - public void addBlock(BlockPos pos, Pair capture) { - super.addBlock(pos.relative(orientation, -initialExtensionProgress), capture); + public void addBlock(Level level, BlockPos pos, Pair capture) { + super.addBlock(level, pos.relative(orientation, -initialExtensionProgress), capture); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/sync/ContraptionFluidPacket.java b/src/main/java/com/simibubi/create/content/contraptions/sync/ContraptionFluidPacket.java deleted file mode 100644 index 2c94225b87..0000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/sync/ContraptionFluidPacket.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.simibubi.create.content.contraptions.sync; - -import com.simibubi.create.content.contraptions.AbstractContraptionEntity; -import com.simibubi.create.foundation.networking.SimplePacketBase; - -import net.minecraft.client.Minecraft; -import net.minecraft.core.BlockPos; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.entity.Entity; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.network.NetworkEvent.Context; - -public class ContraptionFluidPacket extends SimplePacketBase { - - private int entityId; - private BlockPos localPos; - private FluidStack containedFluid; - - public ContraptionFluidPacket(int entityId, BlockPos localPos, FluidStack containedFluid) { - this.entityId = entityId; - this.localPos = localPos; - this.containedFluid = containedFluid; - } - - public ContraptionFluidPacket(FriendlyByteBuf buffer) { - entityId = buffer.readInt(); - localPos = buffer.readBlockPos(); - containedFluid = FluidStack.readFromPacket(buffer); - } - - @Override - public void write(FriendlyByteBuf buffer) { - buffer.writeInt(entityId); - buffer.writeBlockPos(localPos); - containedFluid.writeToPacket(buffer); - } - - @Override - public boolean handle(Context context) { - context.enqueueWork(() -> { - Entity entityByID = Minecraft.getInstance().level.getEntity(entityId); - if (!(entityByID instanceof AbstractContraptionEntity)) - return; - AbstractContraptionEntity contraptionEntity = (AbstractContraptionEntity) entityByID; - contraptionEntity.getContraption().handleContraptionFluidPacket(localPos, containedFluid); - }); - return true; - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/sync/ContraptionItemPacket.java b/src/main/java/com/simibubi/create/content/contraptions/sync/ContraptionItemPacket.java deleted file mode 100644 index 6f18fc1e58..0000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/sync/ContraptionItemPacket.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.simibubi.create.content.contraptions.sync; - -import java.util.ArrayList; -import java.util.List; - -import com.simibubi.create.content.contraptions.AbstractContraptionEntity; -import com.simibubi.create.foundation.networking.SimplePacketBase; - -import net.minecraft.client.Minecraft; -import net.minecraft.core.BlockPos; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.items.ItemStackHandler; -import net.minecraftforge.network.NetworkEvent.Context; - -public class ContraptionItemPacket extends SimplePacketBase { - - private int entityId; - private BlockPos localPos; - private List containedItems; - - public ContraptionItemPacket(int entityId, BlockPos localPos, ItemStackHandler handler) { - this.entityId = entityId; - this.localPos = localPos; - this.containedItems = new ArrayList<>(handler.getSlots()); - for (int i = 0; i < handler.getSlots(); i++) - containedItems.add(handler.getStackInSlot(i)); - } - - public ContraptionItemPacket(FriendlyByteBuf buffer) { - entityId = buffer.readInt(); - localPos = buffer.readBlockPos(); - int count = buffer.readVarInt(); - containedItems = new ArrayList<>(); - for (int i = 0; i < count; i++) - containedItems.add(buffer.readItem()); - } - - @Override - public void write(FriendlyByteBuf buffer) { - buffer.writeInt(entityId); - buffer.writeBlockPos(localPos); - buffer.writeVarInt(containedItems.size()); - for (ItemStack stack : containedItems) - buffer.writeItem(stack); - } - - @Override - public boolean handle(Context context) { - context.enqueueWork(() -> { - Entity entityByID = Minecraft.getInstance().level.getEntity(entityId); - if (!(entityByID instanceof AbstractContraptionEntity)) - return; - AbstractContraptionEntity contraptionEntity = (AbstractContraptionEntity) entityByID; - contraptionEntity.getContraption().handleContraptionItemPacket(localPos, containedItems); - }); - return true; - } -} diff --git a/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxInventory.java b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxInventory.java index f42768c367..0c042c0c8c 100644 --- a/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxInventory.java +++ b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxInventory.java @@ -6,7 +6,10 @@ import java.util.function.Consumer; import javax.annotation.Nonnull; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; import com.simibubi.create.AllItems; +import com.simibubi.create.foundation.item.ItemSlots; import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.nbt.CompoundTag; @@ -16,6 +19,10 @@ import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.items.ItemStackHandler; public class ToolboxInventory extends ItemStackHandler { + public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( + ItemSlots.maxSizeCodec(8).fieldOf("items").forGetter(ItemSlots::fromHandler), + ItemStack.CODEC.listOf().fieldOf("filters").forGetter(toolbox -> toolbox.filters) + ).apply(instance, ToolboxInventory::deserialize)); public static final int STACKS_PER_COMPARTMENT = 4; List filters; @@ -212,4 +219,11 @@ public class ToolboxInventory extends ItemStackHandler { blockEntity.notifyUpdate(); } + private static ToolboxInventory deserialize(ItemSlots slots, List filters) { + ToolboxInventory inventory = new ToolboxInventory(null); + slots.forEach(inventory::setStackInSlot); + inventory.filters = filters; + return inventory; + } + } diff --git a/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxMountedStorage.java b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxMountedStorage.java new file mode 100644 index 0000000000..b984915c0f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxMountedStorage.java @@ -0,0 +1,60 @@ +package com.simibubi.create.content.equipment.toolbox; + +import org.jetbrains.annotations.Nullable; + +import com.mojang.serialization.Codec; +import com.simibubi.create.AllMountedStorageTypes; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; +import com.simibubi.create.api.contraption.storage.item.WrapperMountedItemStorage; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.foundation.item.ItemHelper; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; + +public class ToolboxMountedStorage extends WrapperMountedItemStorage { + public static final Codec CODEC = ToolboxInventory.CODEC.xmap( + ToolboxMountedStorage::new, storage -> storage.wrapped + ); + + protected ToolboxMountedStorage(MountedItemStorageType type, ToolboxInventory wrapped) { + super(type, wrapped); + } + + protected ToolboxMountedStorage(ToolboxInventory wrapped) { + this(AllMountedStorageTypes.TOOLBOX.get(), wrapped); + } + + @Override + public void unmount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be) { + if (be instanceof ToolboxBlockEntity toolbox) { + ItemHelper.copyContents(this, toolbox.inventory); + } + } + + @Override + public boolean handleInteraction(ServerPlayer player, Contraption contraption, StructureBlockInfo info) { + // The default impl will fail anyway, might as well cancel trying + return false; + } + + public static ToolboxMountedStorage fromToolbox(ToolboxBlockEntity toolbox) { + // the inventory will send updates to the block entity, make an isolated copy to avoid that + ToolboxInventory copy = new ToolboxInventory(null); + ItemHelper.copyContents(toolbox.inventory, copy); + copy.filters = toolbox.inventory.filters.stream().map(ItemStack::copy).toList(); + return new ToolboxMountedStorage(copy); + } + + public static ToolboxMountedStorage fromLegacy(CompoundTag nbt) { + ToolboxInventory inv = new ToolboxInventory(null); + inv.deserializeNBT(nbt); + return new ToolboxMountedStorage(inv); + } +} diff --git a/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxMountedStorageType.java b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxMountedStorageType.java new file mode 100644 index 0000000000..7ff776e95a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/equipment/toolbox/ToolboxMountedStorageType.java @@ -0,0 +1,22 @@ +package com.simibubi.create.content.equipment.toolbox; + +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; + +import org.jetbrains.annotations.Nullable; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; + +public class ToolboxMountedStorageType extends MountedItemStorageType { + public ToolboxMountedStorageType() { + super(ToolboxMountedStorage.CODEC); + } + + @Override + @Nullable + public ToolboxMountedStorage mount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be) { + return be instanceof ToolboxBlockEntity toolbox ? ToolboxMountedStorage.fromToolbox(toolbox) : null; + } +} diff --git a/src/main/java/com/simibubi/create/content/fluids/tank/CreativeFluidTankBlockEntity.java b/src/main/java/com/simibubi/create/content/fluids/tank/CreativeFluidTankBlockEntity.java index e0c5a55dc4..3371ba1da2 100644 --- a/src/main/java/com/simibubi/create/content/fluids/tank/CreativeFluidTankBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/fluids/tank/CreativeFluidTankBlockEntity.java @@ -3,13 +3,17 @@ package com.simibubi.create.content.fluids.tank; import java.util.List; import java.util.function.Consumer; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; import com.simibubi.create.foundation.fluid.SmartFluidTank; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; +import net.minecraft.util.ExtraCodecs; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.templates.FluidTank; public class CreativeFluidTankBlockEntity extends FluidTankBlockEntity { @@ -21,26 +25,34 @@ public class CreativeFluidTankBlockEntity extends FluidTankBlockEntity { protected SmartFluidTank createInventory() { return new CreativeSmartFluidTank(getCapacityMultiplier(), this::onFluidStackChanged); } - + @Override public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { return false; } public static class CreativeSmartFluidTank extends SmartFluidTank { + public static final Codec CODEC = RecordCodecBuilder.create(i -> i.group( + FluidStack.CODEC.fieldOf("fluid").forGetter(FluidTank::getFluid), + ExtraCodecs.NON_NEGATIVE_INT.fieldOf("capacity").forGetter(FluidTank::getCapacity) + ).apply(i, (fluid, capacity) -> { + CreativeSmartFluidTank tank = new CreativeSmartFluidTank(capacity, $ -> {}); + tank.setFluid(fluid); + return tank; + })); public CreativeSmartFluidTank(int capacity, Consumer updateCallback) { super(capacity, updateCallback); } - + @Override public int getFluidAmount() { return getFluid().isEmpty() ? 0 : getTankCapacity(0); } - + public void setContainedFluid(FluidStack fluidStack) { fluid = fluidStack.copy(); - if (!fluidStack.isEmpty()) + if (!fluidStack.isEmpty()) fluid.setAmount(getTankCapacity(0)); onContentsChanged(); } diff --git a/src/main/java/com/simibubi/create/content/fluids/tank/FluidTankBlockEntity.java b/src/main/java/com/simibubi/create/content/fluids/tank/FluidTankBlockEntity.java index 7b3ca45908..1a60714e93 100644 --- a/src/main/java/com/simibubi/create/content/fluids/tank/FluidTankBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/fluids/tank/FluidTankBlockEntity.java @@ -509,7 +509,7 @@ public class FluidTankBlockEntity extends SmartBlockEntity implements IHaveGoggl registerAwardables(behaviours, AllAdvancements.STEAM_ENGINE_MAXED, AllAdvancements.PIPE_ORGAN); } - public IFluidTank getTankInventory() { + public FluidTank getTankInventory() { return tankInventory; } diff --git a/src/main/java/com/simibubi/create/content/fluids/tank/FluidTankMovementBehavior.java b/src/main/java/com/simibubi/create/content/fluids/tank/FluidTankMovementBehavior.java new file mode 100644 index 0000000000..9f57a9deb5 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/fluids/tank/FluidTankMovementBehavior.java @@ -0,0 +1,24 @@ +package com.simibubi.create.content.fluids.tank; + +import com.simibubi.create.content.contraptions.behaviour.MovementBehaviour; +import com.simibubi.create.content.contraptions.behaviour.MovementContext; + +import net.minecraft.world.level.block.entity.BlockEntity; + +// The fluid level needs to be ticked to animate smoothly +public class FluidTankMovementBehavior implements MovementBehaviour { + @Override + public boolean mustTickWhileDisabled() { + return true; + } + + @Override + public void tick(MovementContext context) { + if (context.world.isClientSide) { + BlockEntity be = context.contraption.presentBlockEntities.get(context.localPos); + if (be instanceof FluidTankBlockEntity tank) { + tank.getFluidLevel().tickChaser(); + } + } + } +} diff --git a/src/main/java/com/simibubi/create/content/fluids/tank/storage/FluidTankMountedStorage.java b/src/main/java/com/simibubi/create/content/fluids/tank/storage/FluidTankMountedStorage.java new file mode 100644 index 0000000000..a686bfb59d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/fluids/tank/storage/FluidTankMountedStorage.java @@ -0,0 +1,110 @@ +package com.simibubi.create.content.fluids.tank.storage; + +import org.jetbrains.annotations.Nullable; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import com.simibubi.create.AllMountedStorageTypes; +import com.simibubi.create.api.contraption.storage.SyncedMountedStorage; +import com.simibubi.create.api.contraption.storage.fluid.MountedFluidStorageType; +import com.simibubi.create.api.contraption.storage.fluid.WrapperMountedFluidStorage; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.fluids.tank.FluidTankBlockEntity; +import com.simibubi.create.content.fluids.tank.storage.FluidTankMountedStorage.Handler; + +import net.createmod.catnip.animation.LerpedFloat; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.ExtraCodecs; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; + +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.templates.FluidTank; + +public class FluidTankMountedStorage extends WrapperMountedFluidStorage implements SyncedMountedStorage { + public static final Codec CODEC = RecordCodecBuilder.create(i -> i.group( + ExtraCodecs.NON_NEGATIVE_INT.fieldOf("capacity").forGetter(FluidTankMountedStorage::getCapacity), + FluidStack.CODEC.fieldOf("fluid").forGetter(FluidTankMountedStorage::getFluid) + ).apply(i, FluidTankMountedStorage::new)); + + private boolean dirty; + + protected FluidTankMountedStorage(MountedFluidStorageType type, int capacity, FluidStack stack) { + super(type, new Handler(capacity, stack)); + this.wrapped.onChange = () -> this.dirty = true; + } + + protected FluidTankMountedStorage(int capacity, FluidStack stack) { + this(AllMountedStorageTypes.FLUID_TANK.get(), capacity, stack); + } + + @Override + public void unmount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be) { + if (be instanceof FluidTankBlockEntity tank && tank.isController()) { + FluidTank inventory = tank.getTankInventory(); + // capacity shouldn't change, leave it + inventory.setFluid(this.wrapped.getFluid()); + } + } + + public FluidStack getFluid() { + return this.wrapped.getFluid(); + } + + public int getCapacity() { + return this.wrapped.getCapacity(); + } + + @Override + public boolean isDirty() { + return this.dirty; + } + + @Override + public void markClean() { + this.dirty = false; + } + + @Override + public void afterSync(Contraption contraption, BlockPos localPos) { + BlockEntity be = contraption.presentBlockEntities.get(localPos); + if (!(be instanceof FluidTankBlockEntity tank)) + return; + + FluidTank inv = tank.getTankInventory(); + inv.setFluid(this.getFluid()); + float fillLevel = inv.getFluidAmount() / (float) inv.getCapacity(); + if (tank.getFluidLevel() == null) { + tank.setFluidLevel(LerpedFloat.linear().startWithValue(fillLevel)); + } + tank.getFluidLevel().chase(fillLevel, 0.5, LerpedFloat.Chaser.EXP); + } + + public static FluidTankMountedStorage fromTank(FluidTankBlockEntity tank) { + // tank has update callbacks, make an isolated copy + FluidTank inventory = tank.getTankInventory(); + return new FluidTankMountedStorage(inventory.getCapacity(), inventory.getFluid().copy()); + } + + public static FluidTankMountedStorage fromLegacy(CompoundTag nbt) { + int capacity = nbt.getInt("Capacity"); + FluidStack fluid = FluidStack.loadFluidStackFromNBT(nbt); + return new FluidTankMountedStorage(capacity, fluid); + } + + public static final class Handler extends FluidTank { + private Runnable onChange = () -> {}; + + public Handler(int capacity, FluidStack stack) { + super(capacity); + this.setFluid(stack); + } + + @Override + protected void onContentsChanged() { + this.onChange.run(); + } + } +} diff --git a/src/main/java/com/simibubi/create/content/fluids/tank/storage/FluidTankMountedStorageType.java b/src/main/java/com/simibubi/create/content/fluids/tank/storage/FluidTankMountedStorageType.java new file mode 100644 index 0000000000..3ed06d3400 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/fluids/tank/storage/FluidTankMountedStorageType.java @@ -0,0 +1,27 @@ +package com.simibubi.create.content.fluids.tank.storage; + +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.api.contraption.storage.fluid.MountedFluidStorageType; +import com.simibubi.create.content.fluids.tank.FluidTankBlockEntity; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; + +public class FluidTankMountedStorageType extends MountedFluidStorageType { + public FluidTankMountedStorageType() { + super(FluidTankMountedStorage.CODEC); + } + + @Override + @Nullable + public FluidTankMountedStorage mount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be) { + if (be instanceof FluidTankBlockEntity tank && tank.isController()) { + return FluidTankMountedStorage.fromTank(tank); + } + + return null; + } +} diff --git a/src/main/java/com/simibubi/create/content/fluids/tank/storage/creative/CreativeFluidTankMountedStorage.java b/src/main/java/com/simibubi/create/content/fluids/tank/storage/creative/CreativeFluidTankMountedStorage.java new file mode 100644 index 0000000000..0d8f1cbc32 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/fluids/tank/storage/creative/CreativeFluidTankMountedStorage.java @@ -0,0 +1,53 @@ +package com.simibubi.create.content.fluids.tank.storage.creative; + +import org.jetbrains.annotations.Nullable; + +import com.mojang.serialization.Codec; +import com.simibubi.create.AllMountedStorageTypes; +import com.simibubi.create.api.contraption.storage.fluid.MountedFluidStorageType; +import com.simibubi.create.api.contraption.storage.fluid.WrapperMountedFluidStorage; +import com.simibubi.create.content.fluids.tank.CreativeFluidTankBlockEntity; +import com.simibubi.create.content.fluids.tank.CreativeFluidTankBlockEntity.CreativeSmartFluidTank; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.templates.FluidTank; + +public class CreativeFluidTankMountedStorage extends WrapperMountedFluidStorage { + public static final Codec CODEC = CreativeSmartFluidTank.CODEC.xmap( + CreativeFluidTankMountedStorage::new, storage -> storage.wrapped + ); + + protected CreativeFluidTankMountedStorage(MountedFluidStorageType type, CreativeSmartFluidTank tank) { + super(type, tank); + } + + protected CreativeFluidTankMountedStorage(CreativeSmartFluidTank tank) { + this(AllMountedStorageTypes.CREATIVE_FLUID_TANK.get(), tank); + } + + @Override + public void unmount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be) { + // no need to do anything, supplied stack can't change while mounted + } + + public static CreativeFluidTankMountedStorage fromTank(CreativeFluidTankBlockEntity tank) { + // make an isolated copy + FluidTank inv = tank.getTankInventory(); + CreativeSmartFluidTank copy = new CreativeSmartFluidTank(inv.getCapacity(), $ -> {}); + copy.setContainedFluid(inv.getFluid()); + return new CreativeFluidTankMountedStorage(copy); + } + + public static CreativeFluidTankMountedStorage fromLegacy(CompoundTag nbt) { + int capacity = nbt.getInt("Capacity"); + FluidStack fluid = FluidStack.loadFluidStackFromNBT(nbt.getCompound("ProvidedStack")); + CreativeSmartFluidTank tank = new CreativeSmartFluidTank(capacity, $ -> {}); + tank.setContainedFluid(fluid); + return new CreativeFluidTankMountedStorage(tank); + } +} diff --git a/src/main/java/com/simibubi/create/content/fluids/tank/storage/creative/CreativeFluidTankMountedStorageType.java b/src/main/java/com/simibubi/create/content/fluids/tank/storage/creative/CreativeFluidTankMountedStorageType.java new file mode 100644 index 0000000000..0dfe49612a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/fluids/tank/storage/creative/CreativeFluidTankMountedStorageType.java @@ -0,0 +1,27 @@ +package com.simibubi.create.content.fluids.tank.storage.creative; + +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.api.contraption.storage.fluid.MountedFluidStorageType; +import com.simibubi.create.content.fluids.tank.CreativeFluidTankBlockEntity; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; + +public class CreativeFluidTankMountedStorageType extends MountedFluidStorageType { + public CreativeFluidTankMountedStorageType() { + super(CreativeFluidTankMountedStorage.CODEC); + } + + @Override + @Nullable + public CreativeFluidTankMountedStorage mount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be) { + if (be instanceof CreativeFluidTankBlockEntity tank) { + return CreativeFluidTankMountedStorage.fromTank(tank); + } + + return null; + } +} diff --git a/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerMovementBehaviour.java b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerMovementBehaviour.java index fb0ba1c50e..850e6d97aa 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/kinetics/deployer/DeployerMovementBehaviour.java @@ -144,7 +144,7 @@ public class DeployerMovementBehaviour implements MovementBehaviour { ItemStack contextStack = requiredItems.isEmpty() ? ItemStack.EMPTY : requiredItems.get(0).stack; if (!context.contraption.hasUniversalCreativeCrate) { - IItemHandler itemHandler = context.contraption.getSharedInventory(); + IItemHandler itemHandler = context.contraption.getStorage().getAllItems(); for (ItemRequirement.StackRequirement required : requiredItems) { ItemStack stack = ItemHelper .extract(itemHandler, required::matches, ExtractionCountMode.EXACTLY, @@ -233,7 +233,7 @@ public class DeployerMovementBehaviour implements MovementBehaviour { FilterItemStack filter = context.getFilterFromBE(); if (AllItems.SCHEMATIC.isIn(filter.item())) return; - ItemStack held = ItemHelper.extract(context.contraption.getSharedInventory(), + ItemStack held = ItemHelper.extract(context.contraption.getStorage().getAllItems(), stack -> filter.test(context.world, stack), 1, false); player.setItemInHand(InteractionHand.MAIN_HAND, held); } diff --git a/src/main/java/com/simibubi/create/content/kinetics/saw/SawMovementBehaviour.java b/src/main/java/com/simibubi/create/content/kinetics/saw/SawMovementBehaviour.java index ee6c7029b8..aa2a0731e0 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/saw/SawMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/kinetics/saw/SawMovementBehaviour.java @@ -82,7 +82,7 @@ public class SawMovementBehaviour extends BlockBreakingMovementBehaviour { } public void dropItemFromCutTree(MovementContext context, BlockPos pos, ItemStack stack) { - ItemStack remainder = ItemHandlerHelper.insertItem(context.contraption.getSharedInventory(), stack, false); + ItemStack remainder = ItemHandlerHelper.insertItem(context.contraption.getStorage().getAllItems(), stack, false); if (remainder.isEmpty()) return; diff --git a/src/main/java/com/simibubi/create/content/logistics/crate/CreativeCrateMountedStorage.java b/src/main/java/com/simibubi/create/content/logistics/crate/CreativeCrateMountedStorage.java new file mode 100644 index 0000000000..785928cb0c --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/crate/CreativeCrateMountedStorage.java @@ -0,0 +1,82 @@ +package com.simibubi.create.content.logistics.crate; + +import com.mojang.serialization.Codec; +import com.simibubi.create.AllMountedStorageTypes; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorage; + +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; + +public class CreativeCrateMountedStorage extends MountedItemStorage { + public static final Codec CODEC = ItemStack.CODEC.xmap( + CreativeCrateMountedStorage::new, storage -> storage.suppliedStack + ); + + private final ItemStack suppliedStack; + private final ItemStack cachedStackInSlot; + + protected CreativeCrateMountedStorage(MountedItemStorageType type, ItemStack suppliedStack) { + super(type); + this.suppliedStack = suppliedStack; + this.cachedStackInSlot = suppliedStack.copyWithCount(suppliedStack.getMaxStackSize()); + } + + public CreativeCrateMountedStorage(ItemStack suppliedStack) { + this(AllMountedStorageTypes.CREATIVE_CRATE.get(), suppliedStack); + } + + @Override + public void unmount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be) { + // no need to do anything here, the supplied item can't change while mounted + } + + @Override + public int getSlots() { + return 2; // 0 holds the supplied stack endlessly, 1 is always empty to accept + } + + @Override + @NotNull + public ItemStack getStackInSlot(int slot) { + return slot == 0 ? this.cachedStackInSlot : ItemStack.EMPTY; + } + + @Override + public void setStackInSlot(int slot, @NotNull ItemStack stack) { + } + + @Override + @NotNull + public ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate) { + return ItemStack.EMPTY; // no remainder, accept any input + } + + @Override + @NotNull + public ItemStack extractItem(int slot, int amount, boolean simulate) { + if (slot == 0 && !this.suppliedStack.isEmpty()) { + int count = Math.min(amount, this.suppliedStack.getMaxStackSize()); + return this.suppliedStack.copyWithCount(count); + } + + return ItemStack.EMPTY; + } + + @Override + public int getSlotLimit(int slot) { + return 64; + } + + @Override + public boolean isItemValid(int slot, @NotNull ItemStack stack) { + return true; + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/crate/CreativeCrateMountedStorageType.java b/src/main/java/com/simibubi/create/content/logistics/crate/CreativeCrateMountedStorageType.java new file mode 100644 index 0000000000..86b261e1c9 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/crate/CreativeCrateMountedStorageType.java @@ -0,0 +1,28 @@ +package com.simibubi.create.content.logistics.crate; + +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; + +import org.jetbrains.annotations.Nullable; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; + +public class CreativeCrateMountedStorageType extends MountedItemStorageType { + public CreativeCrateMountedStorageType() { + super(CreativeCrateMountedStorage.CODEC); + } + + @Override + @Nullable + public CreativeCrateMountedStorage mount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be) { + if (be instanceof CreativeCrateBlockEntity crate) { + ItemStack supplied = crate.filtering.getFilter(); + return new CreativeCrateMountedStorage(supplied); + } + + return null; + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/depot/MountedDepotInteractionBehaviour.java b/src/main/java/com/simibubi/create/content/logistics/depot/MountedDepotInteractionBehaviour.java index e4ebc9ad01..06cd5d2615 100644 --- a/src/main/java/com/simibubi/create/content/logistics/depot/MountedDepotInteractionBehaviour.java +++ b/src/main/java/com/simibubi/create/content/logistics/depot/MountedDepotInteractionBehaviour.java @@ -1,17 +1,17 @@ package com.simibubi.create.content.logistics.depot; import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorage; import com.simibubi.create.content.contraptions.AbstractContraptionEntity; -import com.simibubi.create.content.contraptions.MountedStorage; import com.simibubi.create.content.contraptions.MountedStorageManager; import com.simibubi.create.content.contraptions.behaviour.MovingInteractionBehaviour; +import com.simibubi.create.content.logistics.depot.storage.DepotMountedStorage; import net.minecraft.core.BlockPos; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.phys.Vec3; -import net.minecraftforge.items.IItemHandlerModifiable; public class MountedDepotInteractionBehaviour extends MovingInteractionBehaviour { @@ -24,23 +24,17 @@ public class MountedDepotInteractionBehaviour extends MovingInteractionBehaviour if (player.level().isClientSide) return true; - MountedStorageManager storageManager = contraptionEntity.getContraption() - .getStorageManager(); - if (storageManager == null) + MountedStorageManager manager = contraptionEntity.getContraption().getStorage(); + + MountedItemStorage storage = manager.getAllItemStorages().get(localPos); + if (!(storage instanceof DepotMountedStorage depot)) return false; - MountedStorage mountedStorage = storageManager.getMountedItemStorage() - .get(localPos); - if (mountedStorage == null) - return false; - - IItemHandlerModifiable itemHandler = mountedStorage.getItemHandler(); - ItemStack itemOnDepot = itemHandler.getStackInSlot(0); - + ItemStack itemOnDepot = depot.getItem(); if (itemOnDepot.isEmpty() && itemInHand.isEmpty()) return true; - itemHandler.setStackInSlot(0, itemInHand.copy()); + depot.setItem(itemInHand.copy()); player.setItemInHand(activeHand, itemOnDepot.copy()); AllSoundEvents.DEPOT_PLOP.playOnServer(player.level(), BlockPos.containing(contraptionEntity.toGlobalVector(Vec3.atCenterOf(localPos), 0))); diff --git a/src/main/java/com/simibubi/create/content/logistics/depot/storage/DepotMountedStorage.java b/src/main/java/com/simibubi/create/content/logistics/depot/storage/DepotMountedStorage.java new file mode 100644 index 0000000000..d96eda7471 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/depot/storage/DepotMountedStorage.java @@ -0,0 +1,109 @@ +package com.simibubi.create.content.logistics.depot.storage; + +import org.jetbrains.annotations.Nullable; + +import com.mojang.serialization.Codec; +import com.simibubi.create.AllMountedStorageTypes; +import com.simibubi.create.api.contraption.storage.SyncedMountedStorage; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; +import com.simibubi.create.api.contraption.storage.item.WrapperMountedItemStorage; +import com.simibubi.create.content.contraptions.Contraption; +import com.simibubi.create.content.logistics.depot.DepotBlockEntity; +import com.simibubi.create.content.logistics.depot.storage.DepotMountedStorage.Handler; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; + +import net.minecraftforge.items.ItemStackHandler; + +public class DepotMountedStorage extends WrapperMountedItemStorage implements SyncedMountedStorage { + public static final Codec CODEC = ItemStack.CODEC.xmap( + DepotMountedStorage::new, DepotMountedStorage::getItem + ); + + private boolean dirty; + + protected DepotMountedStorage(ItemStack stack) { + this(AllMountedStorageTypes.DEPOT.get(), stack); + } + + protected DepotMountedStorage(MountedItemStorageType type, ItemStack stack) { + super(type, new Handler(stack)); + this.wrapped.onChange = () -> this.dirty = true; + } + + @Override + public void unmount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be) { + if (be instanceof DepotBlockEntity depot) { + depot.setHeldItem(this.getStackInSlot(0)); + } + } + + @Override + public boolean handleInteraction(ServerPlayer player, Contraption contraption, StructureBlockInfo info) { + // interaction is handled in the Interaction Behavior, swaps items with the player + return false; + } + + @Override + public boolean isDirty() { + return this.dirty; + } + + @Override + public void markClean() { + this.dirty = false; + } + + @Override + public void afterSync(Contraption contraption, BlockPos localPos) { + BlockEntity be = contraption.presentBlockEntities.get(localPos); + if (be instanceof DepotBlockEntity depot) { + depot.setHeldItem(this.getItem()); + } + } + + public void setItem(ItemStack stack) { + this.setStackInSlot(0, stack); + } + + public ItemStack getItem() { + return this.getStackInSlot(0); + } + + public static DepotMountedStorage fromDepot(DepotBlockEntity depot) { + ItemStack held = depot.getHeldItem(); + return new DepotMountedStorage(held.copy()); + } + + public static DepotMountedStorage fromLegacy(CompoundTag nbt) { + ItemStackHandler handler = new ItemStackHandler(); + handler.deserializeNBT(nbt); + if (handler.getSlots() == 1) { + ItemStack stack = handler.getStackInSlot(0); + return new DepotMountedStorage(stack); + } else { + return new DepotMountedStorage(ItemStack.EMPTY); + } + } + + public static final class Handler extends ItemStackHandler { + private Runnable onChange = () -> {}; + + private Handler(ItemStack stack) { + super(1); + this.setStackInSlot(0, stack); + } + + @Override + protected void onContentsChanged(int slot) { + this.onChange.run(); + } + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/depot/storage/DepotMountedStorageType.java b/src/main/java/com/simibubi/create/content/logistics/depot/storage/DepotMountedStorageType.java new file mode 100644 index 0000000000..6b47a17487 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/depot/storage/DepotMountedStorageType.java @@ -0,0 +1,27 @@ +package com.simibubi.create.content.logistics.depot.storage; + +import org.jetbrains.annotations.Nullable; + +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; +import com.simibubi.create.content.logistics.depot.DepotBlockEntity; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; + +public class DepotMountedStorageType extends MountedItemStorageType { + public DepotMountedStorageType() { + super(DepotMountedStorage.CODEC); + } + + @Override + @Nullable + public DepotMountedStorage mount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be) { + if (be instanceof DepotBlockEntity depot) { + return DepotMountedStorage.fromDepot(depot); + } + + return null; + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelMovementBehaviour.java b/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelMovementBehaviour.java index 6f34f46b29..b5f96ac912 100644 --- a/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/logistics/funnel/FunnelMovementBehaviour.java @@ -76,7 +76,7 @@ public class FunnelMovementBehaviour implements MovementBehaviour { boolean upTo = context.blockEntityData.getBoolean("UpTo"); filterAmount = hasFilter ? filterAmount : 1; - ItemStack extract = ItemHelper.extract(context.contraption.getSharedInventory(), + ItemStack extract = ItemHelper.extract(context.contraption.getStorage().getAllItems(), s -> filter.test(world, s), upTo ? ItemHelper.ExtractionCountMode.UPTO : ItemHelper.ExtractionCountMode.EXACTLY, filterAmount, false); @@ -105,7 +105,7 @@ public class FunnelMovementBehaviour implements MovementBehaviour { if (!filter.test(context.world, toInsert)) continue; ItemStack remainder = - ItemHandlerHelper.insertItemStacked(context.contraption.getSharedInventory(), toInsert, false); + ItemHandlerHelper.insertItemStacked(context.contraption.getStorage().getAllItems(), toInsert, false); if (remainder.getCount() == toInsert.getCount()) continue; if (remainder.isEmpty()) { diff --git a/src/main/java/com/simibubi/create/content/logistics/vault/ItemVaultMountedStorage.java b/src/main/java/com/simibubi/create/content/logistics/vault/ItemVaultMountedStorage.java new file mode 100644 index 0000000000..41044545a4 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/vault/ItemVaultMountedStorage.java @@ -0,0 +1,53 @@ +package com.simibubi.create.content.logistics.vault; + +import org.jetbrains.annotations.Nullable; + +import com.mojang.serialization.Codec; +import com.simibubi.create.AllMountedStorageTypes; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; +import com.simibubi.create.api.contraption.storage.item.WrapperMountedItemStorage; +import com.simibubi.create.foundation.utility.CreateCodecs; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.items.ItemStackHandler; + +public class ItemVaultMountedStorage extends WrapperMountedItemStorage { + public static final Codec CODEC = CreateCodecs.ITEM_STACK_HANDLER.xmap( + ItemVaultMountedStorage::new, storage -> storage.wrapped + ); + + protected ItemVaultMountedStorage(MountedItemStorageType type, ItemStackHandler handler) { + super(type, handler); + } + + protected ItemVaultMountedStorage(ItemStackHandler handler) { + this(AllMountedStorageTypes.VAULT.get(), handler); + } + + @Override + public void unmount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be) { + if (be instanceof ItemVaultBlockEntity vault) { + vault.applyInventoryToBlock(this.wrapped); + } + } + + @Override + public boolean providesFuel() { + return false; + } + + public static ItemVaultMountedStorage fromVault(ItemVaultBlockEntity vault) { + // Vault inventories have a world-affecting onContentsChanged, copy to a safe one + return new ItemVaultMountedStorage(copyToItemStackHandler(vault.getInventoryOfBlock())); + } + + public static ItemVaultMountedStorage fromLegacy(CompoundTag nbt) { + ItemStackHandler handler = new ItemStackHandler(); + handler.deserializeNBT(nbt); + return new ItemVaultMountedStorage(handler); + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/vault/ItemVaultMountedStorageType.java b/src/main/java/com/simibubi/create/content/logistics/vault/ItemVaultMountedStorageType.java new file mode 100644 index 0000000000..51b065850e --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/vault/ItemVaultMountedStorageType.java @@ -0,0 +1,22 @@ +package com.simibubi.create.content.logistics.vault; + +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; + +import org.jetbrains.annotations.Nullable; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; + +public class ItemVaultMountedStorageType extends MountedItemStorageType { + public ItemVaultMountedStorageType() { + super(ItemVaultMountedStorage.CODEC); + } + + @Override + @Nullable + public ItemVaultMountedStorage mount(Level level, BlockState state, BlockPos pos, @Nullable BlockEntity be) { + return be instanceof ItemVaultBlockEntity vault ? ItemVaultMountedStorage.fromVault(vault) : null; + } +} diff --git a/src/main/java/com/simibubi/create/content/trains/entity/Carriage.java b/src/main/java/com/simibubi/create/content/trains/entity/Carriage.java index 2b49322ca7..3f0c36b22e 100644 --- a/src/main/java/com/simibubi/create/content/trains/entity/Carriage.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/Carriage.java @@ -30,9 +30,9 @@ import com.simibubi.create.foundation.advancement.AllAdvancements; import net.createmod.catnip.data.Couple; import net.createmod.catnip.data.Iterate; -import net.createmod.catnip.nbt.NBTHelper; import net.createmod.catnip.data.Pair; import net.createmod.catnip.math.VecHelper; +import net.createmod.catnip.nbt.NBTHelper; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; @@ -46,6 +46,7 @@ import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.fml.DistExecutor; @@ -647,7 +648,7 @@ public class Carriage { public void read(CompoundTag tag) { cutoff = tag.getFloat("Cutoff"); discardTicks = tag.getInt("DiscardTicks"); - storage.read(tag, null, false); + storage.read(tag, false, null); if (tag.contains("Pivot")) pivot = TrackNodeLocation.read(tag.getCompound("Pivot"), null); if (positionAnchor != null) diff --git a/src/main/java/com/simibubi/create/content/trains/entity/CarriageContraption.java b/src/main/java/com/simibubi/create/content/trains/entity/CarriageContraption.java index 59e733d154..ed64cbf0ef 100644 --- a/src/main/java/com/simibubi/create/content/trains/entity/CarriageContraption.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/CarriageContraption.java @@ -10,7 +10,6 @@ import java.util.Optional; import org.apache.commons.lang3.tuple.Pair; import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.AssemblyException; import com.simibubi.create.content.contraptions.Contraption; import com.simibubi.create.content.contraptions.ContraptionType; @@ -39,11 +38,6 @@ import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo; import net.minecraft.world.phys.AABB; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.capability.IFluidHandler; -import net.minecraftforge.fluids.capability.templates.FluidTank; -import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.ItemStackHandler; public class CarriageContraption extends Contraption { @@ -67,8 +61,12 @@ public class CarriageContraption extends Contraption { public int portalCutoffMin; public int portalCutoffMax; - static final IItemHandlerModifiable fallbackItems = new ItemStackHandler(); - static final IFluidHandler fallbackFluids = new FluidTank(0); + static final MountedStorageManager fallbackStorage; + + static { + fallbackStorage = new MountedStorageManager(); + fallbackStorage.initialize(); + } public CarriageContraption() { conductorSeats = new HashMap<>(); @@ -123,7 +121,8 @@ public class CarriageContraption extends Contraption { StructureBlockInfo info = blocks.get(controlsPos); if (!AllBlocks.TRAIN_CONTROLS.has(info.state())) return false; - return info.state().getValue(ControlsBlock.FACING) == direction.getOpposite(); + return info.state() + .getValue(ControlsBlock.FACING) == direction.getOpposite(); } public void swapStorageAfterAssembly(CarriageContraptionEntity cce) { @@ -228,17 +227,12 @@ public class CarriageContraption extends Contraption { return false; } - @Override - protected MountedStorageManager getStorageForSpawnPacket() { - return storageProxy; - } - @Override public ContraptionType getType() { return ContraptionType.CARRIAGE; } - public Direction getAssemblyDirection() { + public Direction getAssemblyDirection() { return assemblyDirection; } @@ -321,30 +315,16 @@ public class CarriageContraption extends Contraption { } @Override - public IItemHandlerModifiable getSharedInventory() { - return storageProxy == null ? fallbackItems : storageProxy.getItems(); + public MountedStorageManager getStorage() { + return storageProxy == null ? fallbackStorage : storageProxy; } @Override - public IFluidHandler getSharedFluidTanks() { - return storageProxy == null ? fallbackFluids : storageProxy.getFluids(); - } - - public void handleContraptionFluidPacket(BlockPos localPos, FluidStack containedFluid) { - storage.updateContainedFluid(localPos, containedFluid); - } - - @Override - public MountedStorageManager getStorageManager() { - return storageProxy; - } - - @Override - public void tickStorage(AbstractContraptionEntity entity) { - if (entity.level().isClientSide) - storage.entityTick(entity); - else if (storageProxy != null) - storageProxy.entityTick(entity); + public void writeStorage(CompoundTag nbt, boolean spawnPacket) { + if (!spawnPacket) + return; + if (storageProxy != null) + storageProxy.write(nbt, spawnPacket); } } diff --git a/src/main/java/com/simibubi/create/content/trains/entity/Train.java b/src/main/java/com/simibubi/create/content/trains/entity/Train.java index 11a150f316..0f2e8488fa 100644 --- a/src/main/java/com/simibubi/create/content/trains/entity/Train.java +++ b/src/main/java/com/simibubi/create/content/trains/entity/Train.java @@ -218,7 +218,7 @@ public class Train { if (shouldActivate) break; - IItemHandlerModifiable inv = carriage.storage.getItems(); + IItemHandlerModifiable inv = carriage.storage.getAllItems(); if (inv != null) { for (int slot = 0; slot < inv.getSlots(); slot++) { if (shouldActivate) diff --git a/src/main/java/com/simibubi/create/content/trains/schedule/condition/ItemThresholdCondition.java b/src/main/java/com/simibubi/create/content/trains/schedule/condition/ItemThresholdCondition.java index 31a6132f4a..4927f4e18f 100644 --- a/src/main/java/com/simibubi/create/content/trains/schedule/condition/ItemThresholdCondition.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/condition/ItemThresholdCondition.java @@ -45,7 +45,7 @@ public class ItemThresholdCondition extends CargoThresholdCondition { int foundItems = 0; for (Carriage carriage : train.carriages) { - IItemHandlerModifiable items = carriage.storage.getItems(); + IItemHandlerModifiable items = carriage.storage.getAllItems(); for (int i = 0; i < items.getSlots(); i++) { ItemStack stackInSlot = items.getStackInSlot(i); if (!stack.test(level, stackInSlot)) diff --git a/src/main/java/com/simibubi/create/content/trains/schedule/destination/DeliverPackagesInstruction.java b/src/main/java/com/simibubi/create/content/trains/schedule/destination/DeliverPackagesInstruction.java index f9bafe17f1..b577f4dd17 100644 --- a/src/main/java/com/simibubi/create/content/trains/schedule/destination/DeliverPackagesInstruction.java +++ b/src/main/java/com/simibubi/create/content/trains/schedule/destination/DeliverPackagesInstruction.java @@ -27,6 +27,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.ItemStack; + import net.minecraftforge.items.IItemHandlerModifiable; public class DeliverPackagesInstruction extends ScheduleInstruction { @@ -78,7 +79,7 @@ public class DeliverPackagesInstruction extends ScheduleInstruction { } for (Carriage carriage : train.carriages) { - IItemHandlerModifiable carriageInventory = carriage.storage.getItems(); + IItemHandlerModifiable carriageInventory = carriage.storage.getAllItems(); if (carriageInventory == null) continue; diff --git a/src/main/java/com/simibubi/create/content/trains/station/GlobalStation.java b/src/main/java/com/simibubi/create/content/trains/station/GlobalStation.java index a8c58fdae4..bcf7fe995f 100644 --- a/src/main/java/com/simibubi/create/content/trains/station/GlobalStation.java +++ b/src/main/java/com/simibubi/create/content/trains/station/GlobalStation.java @@ -182,7 +182,7 @@ public class GlobalStation extends SingleBlockEntityEdgePoint { .getLevel(getBlockEntityDimension()); } - IItemHandlerModifiable carriageInventory = carriage.storage.getItems(); + IItemHandlerModifiable carriageInventory = carriage.storage.getAllItems(); if (carriageInventory == null) continue; diff --git a/src/main/java/com/simibubi/create/foundation/data/BuilderTransformers.java b/src/main/java/com/simibubi/create/foundation/data/BuilderTransformers.java index a9035726d1..3bca53fa4f 100644 --- a/src/main/java/com/simibubi/create/foundation/data/BuilderTransformers.java +++ b/src/main/java/com/simibubi/create/foundation/data/BuilderTransformers.java @@ -549,5 +549,4 @@ public class BuilderTransformers { c::get, 2)) .simpleItem(); } - } diff --git a/src/main/java/com/simibubi/create/foundation/data/CreateRegistrate.java b/src/main/java/com/simibubi/create/foundation/data/CreateRegistrate.java index bc0228f4d4..01528a1673 100644 --- a/src/main/java/com/simibubi/create/foundation/data/CreateRegistrate.java +++ b/src/main/java/com/simibubi/create/foundation/data/CreateRegistrate.java @@ -13,6 +13,10 @@ import java.util.function.Supplier; import org.jetbrains.annotations.Nullable; import com.simibubi.create.CreateClient; +import com.simibubi.create.api.contraption.storage.fluid.MountedFluidStorageType; +import com.simibubi.create.api.contraption.storage.fluid.registrate.MountedFluidStorageTypeBuilder; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; +import com.simibubi.create.api.contraption.storage.item.registrate.MountedItemStorageTypeBuilder; import com.simibubi.create.content.decoration.encasing.CasingConnectivity; import com.simibubi.create.content.fluids.VirtualFluid; import com.simibubi.create.foundation.block.connected.CTModel; @@ -140,6 +144,14 @@ public class CreateRegistrate extends AbstractRegistrate { }); } + public > MountedItemStorageTypeBuilder mountedItemStorage(String name, Supplier supplier) { + return this.entry(name, callback -> new MountedItemStorageTypeBuilder<>(this, this, name, callback, supplier.get())); + } + + public > MountedFluidStorageTypeBuilder mountedFluidStorage(String name, Supplier supplier) { + return this.entry(name, callback -> new MountedFluidStorageTypeBuilder<>(this, this, name, callback, supplier.get())); + } + /* Palettes */ public BlockBuilder paletteStoneBlock(String name, diff --git a/src/main/java/com/simibubi/create/foundation/item/ItemHelper.java b/src/main/java/com/simibubi/create/foundation/item/ItemHelper.java index 15da360793..17be640d22 100644 --- a/src/main/java/com/simibubi/create/foundation/item/ItemHelper.java +++ b/src/main/java/com/simibubi/create/foundation/item/ItemHelper.java @@ -7,6 +7,8 @@ import java.util.function.Predicate; import javax.annotation.Nullable; +import net.minecraftforge.items.IItemHandlerModifiable; + import org.apache.commons.lang3.mutable.MutableInt; import com.simibubi.create.content.logistics.box.PackageEntity; @@ -309,4 +311,13 @@ public class ItemHelper { return remainder; } + public static void copyContents(IItemHandler from, IItemHandlerModifiable to) { + if (from.getSlots() != to.getSlots()) { + throw new IllegalArgumentException("Slot count mismatch"); + } + + for (int i = 0; i < from.getSlots(); i++) { + to.setStackInSlot(i, from.getStackInSlot(i).copy()); + } + } } diff --git a/src/main/java/com/simibubi/create/foundation/item/ItemSlots.java b/src/main/java/com/simibubi/create/foundation/item/ItemSlots.java new file mode 100644 index 0000000000..d9f3c96c55 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/item/ItemSlots.java @@ -0,0 +1,115 @@ +package com.simibubi.create.foundation.item; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.IntFunction; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import com.simibubi.create.foundation.utility.CreateCodecs; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import net.minecraft.util.ExtraCodecs; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.IItemHandlerModifiable; + +/** + * Utility class representing non-empty slots in an item inventory. + */ +public class ItemSlots { + public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( + Codec.unboundedMap(CreateCodecs.boundedIntStr(0), ItemStack.CODEC).fieldOf("items").forGetter(ItemSlots::toBoxedMap), + ExtraCodecs.NON_NEGATIVE_INT.fieldOf("size").forGetter(ItemSlots::getSize) + ).apply(instance, ItemSlots::deserialize)); + + private final Int2ObjectMap map; + private int size; + + public ItemSlots() { + this.map = new Int2ObjectOpenHashMap<>(); + this.size = 0; + } + + public void set(int slot, ItemStack stack) { + if (slot < 0) { + throw new IllegalArgumentException("Slot must be positive"); + } else if (!stack.isEmpty()) { + this.map.put(slot, stack); + this.size = Math.max(this.size, slot + 1); + } + } + + public int getSize() { + return this.size; + } + + public void setSize(int size) { + if (size <= this.getHighestSlot()) { + throw new IllegalStateException("cannot set size to below the highest slot"); + } + this.size = size; + } + + public void forEach(SlotConsumer consumer) { + for (Int2ObjectMap.Entry entry : this.map.int2ObjectEntrySet()) { + consumer.accept(entry.getIntKey(), entry.getValue()); + } + } + + private int getHighestSlot() { + return this.map.keySet().intStream().max().orElse(-1); + } + + public T toHandler(IntFunction factory) { + T handler = factory.apply(this.size); + this.forEach(handler::setStackInSlot); + return handler; + } + + public static ItemSlots fromHandler(IItemHandler handler) { + ItemSlots slots = new ItemSlots(); + slots.setSize(handler.getSlots()); + for (int i = 0; i < handler.getSlots(); i++) { + ItemStack stack = handler.getStackInSlot(i); + if (!stack.isEmpty()) { + slots.set(i, stack.copy()); + } + } + return slots; + } + + public Map toBoxedMap() { + Map map = new HashMap<>(); + this.forEach(map::put); + return map; + } + + public static ItemSlots fromBoxedMap(Map map) { + ItemSlots slots = new ItemSlots(); + map.forEach(slots::set); + return slots; + } + + public static Codec maxSizeCodec(int maxSize) { + return ExtraCodecs.validate( + CODEC, + slots -> slots.size <= maxSize + ? DataResult.success(slots) + : DataResult.error(() -> "Slots above maximum of " + maxSize) + ); + } + + private static ItemSlots deserialize(Map map, int size) { + ItemSlots slots = fromBoxedMap(map); + slots.setSize(size); + return slots; + } + + @FunctionalInterface + public interface SlotConsumer { + void accept(int slot, ItemStack stack); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/utility/CreateCodecs.java b/src/main/java/com/simibubi/create/foundation/utility/CreateCodecs.java new file mode 100644 index 0000000000..c912a8858e --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/utility/CreateCodecs.java @@ -0,0 +1,33 @@ +package com.simibubi.create.foundation.utility; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; +import com.simibubi.create.foundation.item.ItemSlots; + +import net.minecraft.util.ExtraCodecs; + +import net.minecraftforge.items.ItemStackHandler; + +public class CreateCodecs { + public static final Codec INT_STR = Codec.STRING.comapFlatMap( + string -> { + try { + return DataResult.success(Integer.parseInt(string)); + } catch (NumberFormatException ignored) { + return DataResult.error(() -> "Not an integer: " + string); + } + }, + String::valueOf + ); + + public static final Codec ITEM_STACK_HANDLER = ItemSlots.CODEC.xmap( + slots -> slots.toHandler(ItemStackHandler::new), ItemSlots::fromHandler + ); + + public static Codec boundedIntStr(int min) { + return ExtraCodecs.validate( + INT_STR, + i -> i >= min ? DataResult.success(i) : DataResult.error(() -> "Value under minimum of " + min) + ); + } +} diff --git a/src/main/java/com/simibubi/create/impl/contraption/storage/FallbackMountedStorage.java b/src/main/java/com/simibubi/create/impl/contraption/storage/FallbackMountedStorage.java new file mode 100644 index 0000000000..2201036c96 --- /dev/null +++ b/src/main/java/com/simibubi/create/impl/contraption/storage/FallbackMountedStorage.java @@ -0,0 +1,33 @@ +package com.simibubi.create.impl.contraption.storage; + +import java.util.Optional; + +import com.mojang.serialization.Codec; +import com.simibubi.create.AllMountedStorageTypes; +import com.simibubi.create.api.contraption.storage.item.simple.SimpleMountedStorage; + +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.ItemStackHandler; + +/** + * A fallback mounted storage impl that will try to be used when no type is + * registered for a block. This requires that the mounted block provide an item handler + * whose class is exactly {@link ItemStackHandler}. + */ +public class FallbackMountedStorage extends SimpleMountedStorage { + public static final Codec CODEC = SimpleMountedStorage.codec(FallbackMountedStorage::new); + + public FallbackMountedStorage(IItemHandler handler) { + super(AllMountedStorageTypes.FALLBACK.get(), handler); + } + + @Override + protected Optional validate(IItemHandler handler) { + return super.validate(handler).filter(FallbackMountedStorage::isValid); + } + + public static boolean isValid(IItemHandler handler) { + return handler.getClass() == ItemStackHandler.class; + } +} diff --git a/src/main/java/com/simibubi/create/impl/contraption/storage/FallbackMountedStorageType.java b/src/main/java/com/simibubi/create/impl/contraption/storage/FallbackMountedStorageType.java new file mode 100644 index 0000000000..d2b2c7c3f4 --- /dev/null +++ b/src/main/java/com/simibubi/create/impl/contraption/storage/FallbackMountedStorageType.java @@ -0,0 +1,21 @@ +package com.simibubi.create.impl.contraption.storage; + +import com.simibubi.create.api.contraption.storage.item.simple.SimpleMountedStorageType; + +import net.minecraftforge.items.IItemHandler; +import net.minecraft.world.level.block.entity.BlockEntity; + +import org.jetbrains.annotations.ApiStatus; + +@ApiStatus.Internal +public class FallbackMountedStorageType extends SimpleMountedStorageType { + public FallbackMountedStorageType() { + super(FallbackMountedStorage.CODEC); + } + + @Override + protected IItemHandler getHandler(BlockEntity be) { + IItemHandler handler = super.getHandler(be); + return handler != null && FallbackMountedStorage.isValid(handler) ? handler : null; + } +} diff --git a/src/main/java/com/simibubi/create/impl/contraption/storage/MountedStorageTypeRegistryImpl.java b/src/main/java/com/simibubi/create/impl/contraption/storage/MountedStorageTypeRegistryImpl.java new file mode 100644 index 0000000000..66fa681d46 --- /dev/null +++ b/src/main/java/com/simibubi/create/impl/contraption/storage/MountedStorageTypeRegistryImpl.java @@ -0,0 +1,57 @@ +package com.simibubi.create.impl.contraption.storage; + +import java.util.Objects; + +import org.jetbrains.annotations.ApiStatus; + +import com.simibubi.create.AllMountedStorageTypes; +import com.simibubi.create.AllTags; +import com.simibubi.create.api.contraption.storage.MountedStorageTypeRegistry; +import com.simibubi.create.api.contraption.storage.fluid.MountedFluidStorageType; +import com.simibubi.create.api.contraption.storage.item.MountedItemStorageType; +import com.simibubi.create.api.lookup.BlockLookup; + +import net.minecraft.world.level.block.Block; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.registries.IForgeRegistry; +import net.minecraftforge.registries.NewRegistryEvent; +import net.minecraftforge.registries.RegistryBuilder; + +@ApiStatus.Internal +@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD) +public class MountedStorageTypeRegistryImpl { + public static final BlockLookup> ITEM_LOOKUP = BlockLookup.create(MountedStorageTypeRegistryImpl::itemFallback); + public static final BlockLookup> FLUID_LOOKUP = BlockLookup.create(); + + private static IForgeRegistry> itemsRegistry; + private static IForgeRegistry> fluidsRegistry; + + public static IForgeRegistry> getItemsRegistry() { + return Objects.requireNonNull(itemsRegistry, "Registry accessed too early"); + } + + public static IForgeRegistry> getFluidsRegistry() { + return Objects.requireNonNull(fluidsRegistry, "Registry accessed too early"); + } + + @SubscribeEvent + public static void registerRegistries(NewRegistryEvent event) { + event.create( + new RegistryBuilder>() + .setName(MountedStorageTypeRegistry.ITEMS.location()), + registry -> itemsRegistry = registry + ); + event.create( + new RegistryBuilder>() + .setName(MountedStorageTypeRegistry.FLUIDS.location()), + registry -> fluidsRegistry = registry + ); + } + + private static MountedItemStorageType itemFallback(Block block) { + return AllTags.AllBlockTags.FALLBACK_MOUNTED_STORAGE_BLACKLIST.matches(block) + ? null + : AllMountedStorageTypes.FALLBACK.get(); + } +} diff --git a/src/main/java/com/simibubi/create/impl/lookup/BlockLookupImpl.java b/src/main/java/com/simibubi/create/impl/lookup/BlockLookupImpl.java new file mode 100644 index 0000000000..a5406d9a9a --- /dev/null +++ b/src/main/java/com/simibubi/create/impl/lookup/BlockLookupImpl.java @@ -0,0 +1,103 @@ +package com.simibubi.create.impl.lookup; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import com.simibubi.create.api.lookup.BlockLookup; + +import net.minecraftforge.event.TagsUpdatedEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; + +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; + +import net.minecraft.tags.TagKey; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; + +@ApiStatus.Internal +@Mod.EventBusSubscriber +public class BlockLookupImpl implements BlockLookup { + private static final List> allLookups = new ArrayList<>(); + + private final Map map; + private final Map providedValues; + private final Set providedNull; + private final List> providers; + + public BlockLookupImpl() { + this.map = new IdentityHashMap<>(); + this.providedValues = new IdentityHashMap<>(); + this.providedNull = new HashSet<>(); + this.providers = new ArrayList<>(); + allLookups.add(this); + } + + @Nullable + @Override + public T find(BlockState state) { + return this.find(state.getBlock()); + } + + @Nullable + @Override + public T find(Block block) { + T registered = this.map.get(block); + if (registered != null) + return registered; + + if (this.providedNull.contains(block)) + return null; + + return this.providedValues.computeIfAbsent(block, $ -> { + for (Provider provider : this.providers) { + T value = provider.get(block); + if (value != null) { + return value; + } + } + + this.providedNull.add(block); + return null; + }); + } + + @Override + public void register(Block block, T value) { + this.map.put(block, value); + } + + @Override + public void registerTag(TagKey tag, T value) { + this.registerProvider(new TagProvider<>(tag, value)); + } + + @Override + public void registerProvider(Provider provider) { + this.providers.add(0, provider); + } + + @SubscribeEvent + public static void onTagsReloaded(TagsUpdatedEvent event) { + if (event.getUpdateCause() == TagsUpdatedEvent.UpdateCause.SERVER_DATA_LOAD) { + for (BlockLookupImpl lookup : allLookups) { + lookup.providedValues.clear(); + lookup.providedNull.clear(); + } + } + } + + private record TagProvider(TagKey tag, T value) implements Provider { + @Override + @Nullable + @SuppressWarnings("deprecation") + public T get(Block block) { + return block.builtInRegistryHolder().is(this.tag) ? this.value : null; + } + } +} diff --git a/src/main/java/com/simibubi/create/infrastructure/data/CreateRegistrateTags.java b/src/main/java/com/simibubi/create/infrastructure/data/CreateRegistrateTags.java index 34e68c9598..2818cad421 100644 --- a/src/main/java/com/simibubi/create/infrastructure/data/CreateRegistrateTags.java +++ b/src/main/java/com/simibubi/create/infrastructure/data/CreateRegistrateTags.java @@ -109,6 +109,18 @@ public class CreateRegistrateTags { .addTag(BlockTags.PRESSURE_PLATES) .addTag(BlockTags.RAILS); + // tags aren't used here because the implementations of modded entries are unknown + prov.tag(AllBlockTags.CHEST_MOUNTED_STORAGE.tag).add( + Blocks.CHEST, Blocks.TRAPPED_CHEST + ); + prov.tag(AllBlockTags.SIMPLE_MOUNTED_STORAGE.tag).add( + Blocks.BARREL, Blocks.SHULKER_BOX, + Blocks.WHITE_SHULKER_BOX, Blocks.ORANGE_SHULKER_BOX, Blocks.MAGENTA_SHULKER_BOX, Blocks.LIGHT_BLUE_SHULKER_BOX, + Blocks.YELLOW_SHULKER_BOX, Blocks.LIME_SHULKER_BOX, Blocks.PINK_SHULKER_BOX, Blocks.GRAY_SHULKER_BOX, + Blocks.LIGHT_GRAY_SHULKER_BOX, Blocks.CYAN_SHULKER_BOX, Blocks.PURPLE_SHULKER_BOX, Blocks.BLUE_SHULKER_BOX, + Blocks.BROWN_SHULKER_BOX, Blocks.GREEN_SHULKER_BOX, Blocks.RED_SHULKER_BOX, Blocks.BLACK_SHULKER_BOX + ); + prov.tag(AllBlockTags.ROOTS.tag) .add(Blocks.MANGROVE_ROOTS);